mirror of
https://github.com/chylex/Hardcore-Ender-Expansion-2.git
synced 2025-09-15 14:32:09 +02:00
Compare commits
4 Commits
components
...
master
Author | SHA1 | Date | |
---|---|---|---|
2cb463f0aa
|
|||
2b343108bc
|
|||
65d8d709ab
|
|||
f73bcc6635
|
11
build.gradle
11
build.gradle
@@ -16,7 +16,7 @@ buildscript {
|
||||
ext {
|
||||
forge_gradle_version = "4.1.+"
|
||||
mixin_gradle_version = "0.7-SNAPSHOT"
|
||||
kotlin_version = "1.5.20"
|
||||
kotlin_version = "1.7.0"
|
||||
}
|
||||
|
||||
repositories {
|
||||
@@ -83,16 +83,13 @@ allprojects {
|
||||
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) {
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
apiVersion = "1.5"
|
||||
languageVersion = "1.5"
|
||||
useIR = true
|
||||
apiVersion = "1.7"
|
||||
languageVersion = "1.7"
|
||||
freeCompilerArgs = [
|
||||
"-Xno-call-assertions",
|
||||
"-Xno-param-assertions",
|
||||
"-Xno-receiver-assertions",
|
||||
"-Xjvm-default=all",
|
||||
"-Xuse-experimental=kotlin.contracts.ExperimentalContracts",
|
||||
"-XXLanguage:+InlineClasses"
|
||||
"-XXLanguage:+InlineClasses",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@@ -580,8 +580,6 @@ e66091a13a6e7593eb5bd971978d24a5a0e375b3 data/hee/loot_tables/blocks/whitebark.j
|
||||
9bd3a9e24162d2c81047b834f8f79d6cabec86be data/hee/loot_tables/blocks/whitebark_planks.json
|
||||
7d84dc443a052e349593b71d2c0a523e75396cdf data/hee/loot_tables/blocks/whitebark_slab.json
|
||||
83e0b81adb3f9dd488397e8459b95f7b0ce19927 data/hee/loot_tables/blocks/whitebark_stairs.json
|
||||
37f3c55266db3db8dc6d22fdbaf3d53243016b77 data/hee/tags/blocks/gloomrock_particles.json
|
||||
1a70c674d979a59cea18d92f2227ab8a5ed2ccc7 data/hee/tags/blocks/void_portal_frame_crafted.json
|
||||
f5996244831ab38fe1fae2f304bbd7825d6ad98b data/minecraft/tags/blocks/bamboo_plantable_on.json
|
||||
479189f9b35a3c8f795539daf6a1809130242c5b data/minecraft/tags/blocks/flower_pots.json
|
||||
424e2e03cf62f23f4496468a97b9f0df060df9fe data/minecraft/tags/blocks/impermeable.json
|
||||
|
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
"hee:gloomrock",
|
||||
"hee:gloomrock_bricks",
|
||||
"hee:gloomrock_smooth",
|
||||
"hee:gloomrock_smooth_red",
|
||||
"hee:gloomrock_smooth_orange",
|
||||
"hee:gloomrock_smooth_yellow",
|
||||
"hee:gloomrock_smooth_green",
|
||||
"hee:gloomrock_smooth_cyan",
|
||||
"hee:gloomrock_smooth_blue",
|
||||
"hee:gloomrock_smooth_purple",
|
||||
"hee:gloomrock_smooth_magenta",
|
||||
"hee:gloomrock_smooth_white"
|
||||
]
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
"hee:void_portal_frame_crafted",
|
||||
"hee:void_portal_storage_crafted"
|
||||
]
|
||||
}
|
@@ -37,7 +37,7 @@ import net.minecraftforge.common.data.ExistingFileHelper
|
||||
class BlockModels(generator: DataGenerator, modid: String, existingFileHelper: ExistingFileHelper) : BlockModelProvider(generator, modid, existingFileHelper) {
|
||||
override fun registerModels() {
|
||||
for (block in ModBlocks.ALL) {
|
||||
(block as? IHeeBlock)?.let { registerModel(block, it.model.generate(block).blockModel) { builder -> builder } }
|
||||
(block as? IHeeBlock)?.model?.let { registerModel(block, it.blockModel) { builder -> builder } }
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -32,7 +32,7 @@ import net.minecraftforge.common.data.ExistingFileHelper
|
||||
class BlockStates(generator: DataGenerator, modid: String, existingFileHelper: ExistingFileHelper) : BlockStateProvider(generator, modid, existingFileHelper) {
|
||||
override fun registerStatesAndModels() {
|
||||
for (block in ModBlocks.ALL) {
|
||||
(block as? IHeeBlock)?.let { registerState(block, it.model.generate(block).blockState) }
|
||||
(block as? IHeeBlock)?.model?.let { registerState(block, it.blockState) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -39,13 +39,15 @@ import net.minecraftforge.common.data.ExistingFileHelper
|
||||
class ItemModels(generator: DataGenerator, modid: String, existingFileHelper: ExistingFileHelper) : ItemModelProvider(generator, modid, existingFileHelper) {
|
||||
override fun registerModels() {
|
||||
for (item in ModItems.ALL) {
|
||||
(item as? IHeeItem)?.let { registerModel(item, it.model) }
|
||||
(item as? IHeeItem)?.model?.let {
|
||||
registerModel(item, it)
|
||||
}
|
||||
}
|
||||
|
||||
for (block in ModBlocks.ALL) {
|
||||
(block as? IHeeBlock)
|
||||
?.let { it.model.generate(block).itemModel }
|
||||
?.let { registerModel(if (it.asItem) block.asItem() else block, it.model) }
|
||||
(block as? IHeeBlock)?.model?.itemModel?.let {
|
||||
registerModel(if (it.asItem) block.asItem() else block, it.model)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -6,6 +6,8 @@ import chylex.hee.client.DebugMenu
|
||||
import chylex.hee.client.GameModeToggle
|
||||
import chylex.hee.client.TerritoryVoidDebug
|
||||
import chylex.hee.game.block.BlockScaffoldingDebug
|
||||
import chylex.hee.game.block.HeeBlock
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.command.client.CommandClientDebugToggles
|
||||
import chylex.hee.game.command.client.CommandClientScaffolding
|
||||
import chylex.hee.game.command.server.CommandServerInstability
|
||||
@@ -43,8 +45,9 @@ internal object Debug : IDebugModule {
|
||||
CommandServerTestWorld
|
||||
)
|
||||
|
||||
override val scaffoldingBlockBehavior
|
||||
get() = BlockScaffoldingDebug
|
||||
override fun createScaffoldingBlock(builder: BlockBuilder): HeeBlock {
|
||||
return BlockScaffoldingDebug(builder)
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun onClientSetup(@Suppress("UNUSED_PARAMETER") e: FMLClientSetupEvent) {
|
||||
|
@@ -2,7 +2,7 @@ package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.debug.PowerShell
|
||||
import chylex.hee.game.Environment
|
||||
import chylex.hee.game.block.components.IPlayerUseBlockComponent
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.command.client.CommandClientScaffolding
|
||||
import chylex.hee.game.world.generation.structure.file.StructureFile
|
||||
import chylex.hee.game.world.generation.util.WorldToStructureWorldAdapter
|
||||
@@ -27,13 +27,14 @@ import net.minecraft.util.Direction.WEST
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.Util
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.BlockRayTraceResult
|
||||
import net.minecraft.util.text.StringTextComponent
|
||||
import net.minecraft.util.text.TextFormatting
|
||||
import net.minecraft.world.World
|
||||
import java.nio.file.Files
|
||||
|
||||
object BlockScaffoldingDebug : IPlayerUseBlockComponent {
|
||||
override fun use(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand): ActionResultType {
|
||||
class BlockScaffoldingDebug(builder: BlockBuilder) : BlockScaffolding(builder) {
|
||||
override fun onBlockActivated(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hit: BlockRayTraceResult): ActionResultType {
|
||||
if (world.isRemote && player.isSneaking && !player.abilities.isFlying) {
|
||||
val palette = CommandClientScaffolding.currentPalette
|
||||
|
||||
@@ -53,7 +54,7 @@ object BlockScaffoldingDebug : IPlayerUseBlockComponent {
|
||||
val box = BoundingBox(minPos, maxPos)
|
||||
val serverWorld = Environment.getDimension(world.dimensionKey)
|
||||
|
||||
val (structureTag, missingMappings) = StructureFile.save(WorldToStructureWorldAdapter(serverWorld, serverWorld.rand, box.min), box.size, palette, state.block)
|
||||
val (structureTag, missingMappings) = StructureFile.save(WorldToStructureWorldAdapter(serverWorld, serverWorld.rand, box.min), box.size, palette, this)
|
||||
val structureFile = Files.createTempDirectory("HardcoreEnderExpansion_Structure_").resolve(CommandClientScaffolding.currentFile).toFile()
|
||||
|
||||
CompressedStreamTools.write(structureTag, structureFile)
|
||||
|
@@ -5,7 +5,7 @@ import chylex.hee.game.block.properties.BlockDrop
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.loot.LootTables
|
||||
|
||||
open class HeeBlock(builder: BlockBuilder) : Block(builder.p), IHeeBlock { // TODO abstract
|
||||
open class HeeBlock(builder: BlockBuilder) : Block(builder.p), IHeeBlock {
|
||||
override val drop
|
||||
get() = if (lootTable == LootTables.EMPTY) BlockDrop.Nothing else BlockDrop.Self
|
||||
}
|
||||
|
@@ -1,5 +0,0 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import net.minecraft.block.Block
|
||||
|
||||
abstract class HeeBlock2(properties: Properties) : Block(properties), IHeeBlock
|
@@ -1,229 +0,0 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.game.block.builder.HeeBlockComponents
|
||||
import chylex.hee.game.world.util.getBlock
|
||||
import chylex.hee.util.forge.Side
|
||||
import chylex.hee.util.forge.Sided
|
||||
import chylex.hee.util.forge.asBool
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockRenderType
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.client.util.ITooltipFlag
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.EntitySpawnPlacementRegistry.PlacementType
|
||||
import net.minecraft.entity.EntityType
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.item.BlockItemUseContext
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.loot.LootContext
|
||||
import net.minecraft.state.StateContainer.Builder
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.util.ActionResultType
|
||||
import net.minecraft.util.Direction
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.Mirror
|
||||
import net.minecraft.util.Rotation
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.BlockRayTraceResult
|
||||
import net.minecraft.util.math.RayTraceResult
|
||||
import net.minecraft.util.math.shapes.ISelectionContext
|
||||
import net.minecraft.util.math.shapes.VoxelShape
|
||||
import net.minecraft.util.text.ITextComponent
|
||||
import net.minecraft.world.Explosion
|
||||
import net.minecraft.world.IBlockReader
|
||||
import net.minecraft.world.IWorld
|
||||
import net.minecraft.world.IWorldReader
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.world.server.ServerWorld
|
||||
import java.util.Random
|
||||
|
||||
abstract class HeeBlockWithComponents(properties: Properties, components: HeeBlockComponents) : HeeBlock2(properties) {
|
||||
private companion object {
|
||||
private val RAND = Random()
|
||||
}
|
||||
|
||||
private val states = components.states.build()
|
||||
|
||||
private val name = components.name
|
||||
private val tooltip = components.tooltip
|
||||
|
||||
private val shape = components.shape
|
||||
private val renderType = components.renderType
|
||||
private val ambientOcclusionValue = components.ambientOcclusionValue
|
||||
private val clientEffects = components.clientEffects
|
||||
|
||||
private val drops = components.drops
|
||||
private val harvestability = components.harvestability
|
||||
private val experience = components.experience
|
||||
private val flammability = components.flammability
|
||||
|
||||
private val entity = components.entity
|
||||
private val placement = components.placement
|
||||
private val onAdded = components.onAdded
|
||||
private val onNeighborChanged = components.onNeighborChanged
|
||||
private val setStateFromNeighbor = components.setStateFromNeighbor
|
||||
|
||||
private val scheduledTick = components.scheduledTick
|
||||
private val randomTick = components.randomTick
|
||||
|
||||
private val playerUse = components.playerUse
|
||||
private val onExploded = components.onExploded
|
||||
private val onCreatureSpawning = components.onCreatureSpawning
|
||||
private val collideWithEntity = components.collideWithEntity
|
||||
|
||||
private var isAir = components.isAir
|
||||
|
||||
init {
|
||||
defaultState = states.applyDefaults(stateContainer.baseState)
|
||||
}
|
||||
|
||||
abstract override fun fillStateContainer(builder: Builder<Block, BlockState>)
|
||||
|
||||
override fun rotate(state: BlockState, rotation: Rotation): BlockState {
|
||||
return states.getRotatedState(state, rotation)
|
||||
}
|
||||
|
||||
override fun mirror(state: BlockState, mirror: Mirror): BlockState {
|
||||
return states.getMirroredState(state, mirror)
|
||||
}
|
||||
|
||||
override fun getTranslationKey(): String {
|
||||
return name?.translationKey ?: super.getTranslationKey()
|
||||
}
|
||||
|
||||
@Sided(Side.CLIENT)
|
||||
override fun addInformation(stack: ItemStack, world: IBlockReader?, lines: MutableList<ITextComponent>, flags: ITooltipFlag) {
|
||||
tooltip?.add(lines, stack, flags.isAdvanced, world)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun getShape(state: BlockState, worldIn: IBlockReader, pos: BlockPos, context: ISelectionContext): VoxelShape {
|
||||
return shape?.getShape(state) ?: super.getShape(state, worldIn, pos, context)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun getCollisionShape(state: BlockState, worldIn: IBlockReader, pos: BlockPos, context: ISelectionContext): VoxelShape {
|
||||
return shape?.getCollisionShape(state) ?: super.getCollisionShape(state, worldIn, pos, context)
|
||||
}
|
||||
|
||||
override fun getRaytraceShape(state: BlockState, worldIn: IBlockReader, pos: BlockPos): VoxelShape {
|
||||
return super.getRaytraceShape(state, worldIn, pos)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun getRenderType(state: BlockState): BlockRenderType {
|
||||
return renderType ?: super.getRenderType(state)
|
||||
}
|
||||
|
||||
@Sided(Side.CLIENT)
|
||||
@Suppress("DEPRECATION")
|
||||
override fun getAmbientOcclusionLightValue(state: BlockState, worldIn: IBlockReader, pos: BlockPos): Float {
|
||||
return ambientOcclusionValue ?: super.getAmbientOcclusionLightValue(state, worldIn, pos)
|
||||
}
|
||||
|
||||
@Sided(Side.CLIENT)
|
||||
override fun animateTick(state: BlockState, world: World, pos: BlockPos, rand: Random) {
|
||||
clientEffects?.randomTick(state, world, pos, rand)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun getDrops(state: BlockState, context: LootContext.Builder): MutableList<ItemStack> {
|
||||
return drops?.getDrops(state, context) ?: super.getDrops(state, context)
|
||||
}
|
||||
|
||||
override fun getPickBlock(state: BlockState, target: RayTraceResult, world: IBlockReader, pos: BlockPos, player: PlayerEntity): ItemStack {
|
||||
return drops?.getPickBlock(state, world, pos) ?: super.getPickBlock(state, target, world, pos, player)
|
||||
}
|
||||
|
||||
override fun canHarvestBlock(state: BlockState, world: IBlockReader, pos: BlockPos, player: PlayerEntity): Boolean {
|
||||
return harvestability?.canHarvest(player)?.asBool ?: super.canHarvestBlock(state, world, pos, player)
|
||||
}
|
||||
|
||||
override fun getExpDrop(state: BlockState, world: IWorldReader, pos: BlockPos, fortune: Int, silktouch: Int): Int {
|
||||
return experience?.getExperience((world as? World)?.rand ?: RAND) ?: 0
|
||||
}
|
||||
|
||||
override fun getFlammability(state: BlockState, world: IBlockReader, pos: BlockPos, face: Direction): Int {
|
||||
return flammability?.takeIfFlammable(state)?.flammability ?: 0
|
||||
}
|
||||
|
||||
override fun getFireSpreadSpeed(state: BlockState, world: IBlockReader, pos: BlockPos, face: Direction): Int {
|
||||
return flammability?.takeIfFlammable(state)?.fireSpread ?: 0
|
||||
}
|
||||
|
||||
override fun hasTileEntity(state: BlockState): Boolean {
|
||||
return entity != null
|
||||
}
|
||||
|
||||
override fun createTileEntity(state: BlockState, world: IBlockReader): TileEntity? {
|
||||
return entity?.create()
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun isValidPosition(state: BlockState, world: IWorldReader, pos: BlockPos): Boolean {
|
||||
return placement?.isPositionValid(state, world, pos) ?: super.isValidPosition(state, world, pos)
|
||||
}
|
||||
|
||||
override fun getStateForPlacement(context: BlockItemUseContext): BlockState? {
|
||||
return placement?.getPlacedState(defaultState, context.world, context.pos, context) ?: super.getStateForPlacement(context)
|
||||
}
|
||||
|
||||
override fun onBlockPlacedBy(world: World, pos: BlockPos, state: BlockState, placer: LivingEntity?, stack: ItemStack) {
|
||||
placement?.onPlacedBy(state, world, pos, placer, stack)
|
||||
}
|
||||
|
||||
override fun onBlockAdded(state: BlockState, world: World, pos: BlockPos, oldState: BlockState, isMoving: Boolean) {
|
||||
onAdded?.onAdded(state, world, pos)
|
||||
scheduledTick?.onAdded(state, world, pos, world.rand)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun neighborChanged(state: BlockState, world: World, pos: BlockPos, neighborBlock: Block, neighborPos: BlockPos, isMoving: Boolean) {
|
||||
super.neighborChanged(state, world, pos, neighborBlock, neighborPos, isMoving)
|
||||
onNeighborChanged?.onNeighborChanged(state, world, pos, neighborBlock, neighborPos.getBlock(world), neighborPos)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun updatePostPlacement(state: BlockState, neighborFacing: Direction, neighborState: BlockState, world: IWorld, currentPos: BlockPos, neighborPos: BlockPos): BlockState {
|
||||
return setStateFromNeighbor?.getNewState(state, world, currentPos, neighborFacing, neighborPos) ?: super.updatePostPlacement(state, neighborFacing, neighborState, world, currentPos, neighborPos)
|
||||
}
|
||||
|
||||
override fun tick(state: BlockState, world: ServerWorld, pos: BlockPos, rand: Random) {
|
||||
scheduledTick?.onTick(state, world, pos, rand)
|
||||
}
|
||||
|
||||
override fun randomTick(state: BlockState, world: ServerWorld, pos: BlockPos, rand: Random) {
|
||||
randomTick?.onTick(state, world, pos, rand)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
override fun onBlockActivated(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hit: BlockRayTraceResult): ActionResultType {
|
||||
return playerUse?.use(state, world, pos, player, hand) ?: super.onBlockActivated(state, world, pos, player, hand, hit)
|
||||
}
|
||||
|
||||
override fun canDropFromExplosion(state: BlockState, world: IBlockReader, pos: BlockPos, explosion: Explosion): Boolean {
|
||||
return onExploded?.canDrop(explosion) ?: super.canDropFromExplosion(state, world, pos, explosion)
|
||||
}
|
||||
|
||||
override fun onBlockExploded(state: BlockState, world: World, pos: BlockPos, explosion: Explosion) {
|
||||
onExploded?.onExploded(state, world, pos, explosion)
|
||||
super.onBlockExploded(state, world, pos, explosion)
|
||||
}
|
||||
|
||||
override fun canCreatureSpawn(state: BlockState, world: IBlockReader, pos: BlockPos, type: PlacementType?, entityType: EntityType<*>?): Boolean {
|
||||
return onCreatureSpawning?.canSpawn(world, pos, type, entityType)?.asBool ?: super.canCreatureSpawn(state, world, pos, type, entityType)
|
||||
}
|
||||
|
||||
override fun onEntityCollision(state: BlockState, world: World, pos: BlockPos, entity: Entity) {
|
||||
collideWithEntity?.collide(state, world, pos, entity)
|
||||
}
|
||||
|
||||
override fun isAir(state: BlockState, world: IBlockReader, pos: BlockPos): Boolean {
|
||||
return isAir ?: super.isAir(state, world, pos)
|
||||
}
|
||||
|
||||
override fun propagatesSkylightDown(state: BlockState, world: IBlockReader, pos: BlockPos): Boolean {
|
||||
return isAir == true || super.propagatesSkylightDown(state, world, pos)
|
||||
}
|
||||
}
|
@@ -1,13 +1,12 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.client.text.LocalizationStrategy
|
||||
import chylex.hee.game.block.builder.AbstractHeeBlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockDrop
|
||||
import chylex.hee.game.block.properties.BlockModel
|
||||
import chylex.hee.game.block.properties.BlockRenderLayer
|
||||
import chylex.hee.game.block.properties.BlockRenderLayer.SOLID
|
||||
import chylex.hee.game.block.properties.BlockTint
|
||||
import chylex.hee.game.block.properties.IBlockStateModelSupplier
|
||||
import chylex.hee.game.block.properties.IBlockStateModel
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.tags.ITag.INamedTag
|
||||
|
||||
@@ -18,7 +17,7 @@ interface IHeeBlock {
|
||||
val localizationExtra: Map<String, String>
|
||||
get() = emptyMap()
|
||||
|
||||
val model: IBlockStateModelSupplier
|
||||
val model: IBlockStateModel
|
||||
get() = BlockModel.Cube
|
||||
|
||||
val renderLayer: BlockRenderLayer
|
||||
@@ -32,14 +31,4 @@ interface IHeeBlock {
|
||||
|
||||
val tags: List<INamedTag<Block>>
|
||||
get() = emptyList()
|
||||
|
||||
class FromBuilder(builder: AbstractHeeBlockBuilder<*>) : IHeeBlock {
|
||||
override val localization = builder.localization ?: super.localization
|
||||
override val localizationExtra = builder.localizationExtra.toMap()
|
||||
override val model = builder.model ?: super.model
|
||||
override val renderLayer = builder.renderLayer ?: super.renderLayer
|
||||
override val tint = builder.tint
|
||||
override val drop = builder.drop ?: super.drop
|
||||
override val tags = builder.tags.toList()
|
||||
}
|
||||
}
|
||||
|
@@ -1,149 +0,0 @@
|
||||
package chylex.hee.game.block.builder
|
||||
|
||||
import chylex.hee.client.text.LocalizationStrategy
|
||||
import chylex.hee.game.block.IHeeBlock
|
||||
import chylex.hee.game.block.properties.BlockDrop
|
||||
import chylex.hee.game.block.properties.BlockHardness
|
||||
import chylex.hee.game.block.properties.BlockHarvestTool
|
||||
import chylex.hee.game.block.properties.BlockRenderLayer
|
||||
import chylex.hee.game.block.properties.BlockTint
|
||||
import chylex.hee.game.block.properties.IBlockStateModelSupplier
|
||||
import net.minecraft.block.AbstractBlock.IPositionPredicate
|
||||
import net.minecraft.block.AbstractBlock.Properties
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.SoundType
|
||||
import net.minecraft.block.material.Material
|
||||
import net.minecraft.block.material.MaterialColor
|
||||
import net.minecraft.tags.ITag.INamedTag
|
||||
|
||||
abstract class AbstractHeeBlockBuilder<T : Block> {
|
||||
private companion object {
|
||||
private val DEFAULT_MATERIAL = Material.Builder(MaterialColor.AIR).build()
|
||||
|
||||
private fun always(value: Boolean): IPositionPredicate {
|
||||
return IPositionPredicate { _, _, _ -> value }
|
||||
}
|
||||
}
|
||||
|
||||
var localization: LocalizationStrategy? = null
|
||||
val localizationExtra = mutableMapOf<String, String>()
|
||||
|
||||
var model: IBlockStateModelSupplier? = null
|
||||
var renderLayer: BlockRenderLayer? = null
|
||||
|
||||
var material: Material? = null
|
||||
var color: MaterialColor? = null
|
||||
var sound: SoundType? = null
|
||||
var tint: BlockTint? = null
|
||||
var light: Int? = null
|
||||
|
||||
var isSolid: Boolean? = null
|
||||
var isOpaque: Boolean? = null
|
||||
var suffocates: Boolean? = null
|
||||
var blocksVision: Boolean? = null
|
||||
|
||||
var drop: BlockDrop? = null
|
||||
var tool: BlockHarvestTool? = null
|
||||
var hardness: BlockHardness? = null
|
||||
|
||||
private val lazyComponents = lazy(::HeeBlockComponents)
|
||||
val components
|
||||
get() = lazyComponents.value
|
||||
|
||||
val tags = mutableListOf<INamedTag<Block>>()
|
||||
val interfaces = HeeBlockInterfaces()
|
||||
|
||||
fun includeFrom(source: AbstractHeeBlockBuilder<*>) {
|
||||
source.localization?.let { this.localization = it }
|
||||
this.localizationExtra.putAll(source.localizationExtra)
|
||||
|
||||
source.model?.let { this.model = it }
|
||||
source.renderLayer?.let { this.renderLayer = it }
|
||||
|
||||
source.material?.let { this.material = it }
|
||||
source.color?.let { this.color = it }
|
||||
source.sound?.let { this.sound = it }
|
||||
source.tint?.let { this.tint = it }
|
||||
source.light?.let { this.light = it }
|
||||
|
||||
source.isSolid?.let { this.isSolid = it }
|
||||
source.isOpaque?.let { this.isOpaque = it }
|
||||
source.suffocates?.let { this.suffocates = it }
|
||||
source.blocksVision?.let { this.blocksVision = it }
|
||||
|
||||
source.drop?.let { this.drop = it }
|
||||
source.tool?.let { this.tool = it }
|
||||
source.hardness?.let { this.hardness = it }
|
||||
|
||||
if (source.lazyComponents.isInitialized()) {
|
||||
this.components.includeFrom(source.components)
|
||||
}
|
||||
|
||||
this.tags.addAll(source.tags)
|
||||
this.interfaces.includeFrom(source.interfaces)
|
||||
}
|
||||
|
||||
protected val heeDelegate
|
||||
get() = object : IHeeBlock {
|
||||
override val localization = this@AbstractHeeBlockBuilder.localization ?: super.localization
|
||||
override val localizationExtra = this@AbstractHeeBlockBuilder.localizationExtra.toMap()
|
||||
override val model = this@AbstractHeeBlockBuilder.model ?: super.model
|
||||
override val renderLayer = this@AbstractHeeBlockBuilder.renderLayer ?: super.renderLayer
|
||||
override val tint = this@AbstractHeeBlockBuilder.tint
|
||||
override val drop = this@AbstractHeeBlockBuilder.drop ?: super.drop
|
||||
override val tags = this@AbstractHeeBlockBuilder.tags.toList()
|
||||
}
|
||||
|
||||
private fun buildProperties(setup: ((Properties) -> Properties)?): Properties {
|
||||
val material = material ?: DEFAULT_MATERIAL
|
||||
val color = color ?: material.color
|
||||
val tool = tool ?: BlockHarvestTool.NONE
|
||||
|
||||
var properties = Properties.create(material, color)
|
||||
|
||||
if (setup != null) {
|
||||
properties = setup(properties)
|
||||
}
|
||||
|
||||
properties = tool.applyTo(properties)
|
||||
properties = properties.apply(sound, Properties::sound)
|
||||
properties = properties.apply(light) { level -> setLightLevel { level } }
|
||||
properties = properties.apply(isOpaque) { setOpaque(always(it)) }
|
||||
properties = properties.apply(suffocates) { setSuffocates(always(it)) }
|
||||
properties = properties.apply(blocksVision) { setBlocksVision(always(it)) }
|
||||
properties = properties.apply(hardness) { it.applyTo(this) }
|
||||
|
||||
if (isSolid == false) {
|
||||
properties = properties.notSolid()
|
||||
}
|
||||
|
||||
if (!material.blocksMovement()) {
|
||||
if (isSolid == true) {
|
||||
throw UnsupportedOperationException("[AbstractHeeBlockBuilder] cannot create a block that does not block movement and is solid at the same time")
|
||||
}
|
||||
|
||||
properties = properties.doesNotBlockMovement()
|
||||
}
|
||||
|
||||
if (drop === BlockDrop.Nothing) {
|
||||
properties = properties.noDrops()
|
||||
}
|
||||
|
||||
if (lazyComponents.isInitialized() && components.randomTick != null) {
|
||||
properties = properties.tickRandomly()
|
||||
}
|
||||
|
||||
return properties
|
||||
}
|
||||
|
||||
private inline fun <T> Properties.apply(value: T?, function: Properties.(T) -> Properties): Properties {
|
||||
return if (value == null) this else function(value)
|
||||
}
|
||||
|
||||
fun build(propertiesSetup: (Properties.() -> Properties)? = null): T {
|
||||
val components = if (lazyComponents.isInitialized()) components else null
|
||||
return buildBlock(buildProperties(propertiesSetup), components)
|
||||
}
|
||||
|
||||
internal abstract fun buildBlock(properties: Properties, components: HeeBlockComponents?): T
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
package chylex.hee.game.block.builder
|
||||
|
||||
import chylex.hee.game.block.HeeBlock2
|
||||
import chylex.hee.game.block.HeeBlockWithComponents
|
||||
import chylex.hee.game.block.IHeeBlock
|
||||
import chylex.hee.game.block.interfaces.IBlockWithInterfaces
|
||||
import net.minecraft.block.AbstractBlock.Properties
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.state.StateContainer.Builder
|
||||
|
||||
open class HeeBlockBuilder : AbstractHeeBlockBuilder<HeeBlock2>() {
|
||||
override fun buildBlock(properties: Properties, components: HeeBlockComponents?): HeeBlock2 {
|
||||
if (components != null) {
|
||||
return object : HeeBlockWithComponents(properties, components), IHeeBlock by IHeeBlock.FromBuilder(this@HeeBlockBuilder), IBlockWithInterfaces by interfaces.delegate {
|
||||
override fun fillStateContainer(builder: Builder<Block, BlockState>) {
|
||||
components.states.fillContainer(builder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return object : HeeBlock2(properties), IHeeBlock by IHeeBlock.FromBuilder(this), IBlockWithInterfaces by interfaces.delegate {}
|
||||
}
|
||||
}
|
||||
|
||||
inline fun HeeBlockBuilder(setup: HeeBlockBuilder.() -> Unit) = HeeBlockBuilder().apply(setup)
|
@@ -1,86 +0,0 @@
|
||||
package chylex.hee.game.block.builder
|
||||
|
||||
import chylex.hee.game.block.components.IBlockAddedComponent
|
||||
import chylex.hee.game.block.components.IBlockClientEffectsComponent
|
||||
import chylex.hee.game.block.components.IBlockCollideWithEntityComponent
|
||||
import chylex.hee.game.block.components.IBlockDropsComponent
|
||||
import chylex.hee.game.block.components.IBlockEntityComponent
|
||||
import chylex.hee.game.block.components.IBlockExperienceComponent
|
||||
import chylex.hee.game.block.components.IBlockExplodedComponent
|
||||
import chylex.hee.game.block.components.IBlockHarvestabilityComponent
|
||||
import chylex.hee.game.block.components.IBlockNameComponent
|
||||
import chylex.hee.game.block.components.IBlockNeighborChanged
|
||||
import chylex.hee.game.block.components.IBlockPlacementComponent
|
||||
import chylex.hee.game.block.components.IBlockRandomTickComponent
|
||||
import chylex.hee.game.block.components.IBlockScheduledTickComponent
|
||||
import chylex.hee.game.block.components.IBlockShapeComponent
|
||||
import chylex.hee.game.block.components.ICreatureSpawningOnBlockComponent
|
||||
import chylex.hee.game.block.components.IFlammableBlockComponent
|
||||
import chylex.hee.game.block.components.IPlayerUseBlockComponent
|
||||
import chylex.hee.game.block.components.ISetBlockStateFromNeighbor
|
||||
import chylex.hee.game.item.components.ITooltipComponent
|
||||
import net.minecraft.block.BlockRenderType
|
||||
|
||||
class HeeBlockComponents {
|
||||
val states = HeeBlockStates.Builder()
|
||||
|
||||
var name: IBlockNameComponent? = null
|
||||
var tooltip: ITooltipComponent? = null
|
||||
|
||||
var shape: IBlockShapeComponent? = null
|
||||
var renderType: BlockRenderType? = null
|
||||
var ambientOcclusionValue: Float? = null
|
||||
var clientEffects: IBlockClientEffectsComponent? = null
|
||||
|
||||
var drops: IBlockDropsComponent? = null
|
||||
var harvestability: IBlockHarvestabilityComponent? = null
|
||||
var experience: IBlockExperienceComponent? = null
|
||||
var flammability: IFlammableBlockComponent? = null
|
||||
|
||||
var entity: IBlockEntityComponent? = null
|
||||
var placement: IBlockPlacementComponent? = null
|
||||
var onAdded: IBlockAddedComponent? = null
|
||||
var onNeighborChanged: IBlockNeighborChanged? = null
|
||||
var setStateFromNeighbor: ISetBlockStateFromNeighbor? = null
|
||||
|
||||
var scheduledTick: IBlockScheduledTickComponent? = null
|
||||
var randomTick: IBlockRandomTickComponent? = null
|
||||
|
||||
var playerUse: IPlayerUseBlockComponent? = null
|
||||
var onExploded: IBlockExplodedComponent? = null
|
||||
var onCreatureSpawning: ICreatureSpawningOnBlockComponent? = null
|
||||
var collideWithEntity: IBlockCollideWithEntityComponent? = null
|
||||
|
||||
var isAir: Boolean? = null
|
||||
|
||||
fun includeFrom(source: HeeBlockComponents) {
|
||||
source.name?.let { this.name = it }
|
||||
source.tooltip?.let { this.tooltip = it }
|
||||
|
||||
source.shape?.let { this.shape = it }
|
||||
source.renderType?.let { this.renderType = it }
|
||||
source.ambientOcclusionValue?.let { this.ambientOcclusionValue = it }
|
||||
source.clientEffects?.let { this.clientEffects = it }
|
||||
|
||||
source.drops?.let { this.drops = it }
|
||||
source.harvestability?.let { this.harvestability = it }
|
||||
source.experience?.let { this.experience = it }
|
||||
source.flammability?.let { this.flammability = it }
|
||||
|
||||
source.entity?.let { this.entity = it }
|
||||
source.placement?.let { this.placement = it }
|
||||
source.onAdded?.let { this.onAdded = it }
|
||||
source.onNeighborChanged?.let { this.onNeighborChanged = it }
|
||||
source.setStateFromNeighbor?.let { this.setStateFromNeighbor = it }
|
||||
|
||||
source.scheduledTick?.let { this.scheduledTick = it }
|
||||
source.randomTick?.let { this.randomTick = it }
|
||||
|
||||
source.playerUse?.let { this.playerUse = it }
|
||||
source.onExploded?.let { this.onExploded = it }
|
||||
source.onCreatureSpawning?.let { this.onCreatureSpawning = it }
|
||||
source.collideWithEntity?.let { this.collideWithEntity = it }
|
||||
|
||||
source.isAir?.let { this.isAir = it }
|
||||
}
|
||||
}
|
@@ -1,23 +0,0 @@
|
||||
package chylex.hee.game.block.builder
|
||||
|
||||
import chylex.hee.game.block.interfaces.BlockInterfaceContainer
|
||||
import chylex.hee.game.block.interfaces.IBlockInterface
|
||||
import chylex.hee.game.block.interfaces.NoBlockInterfaces
|
||||
|
||||
class HeeBlockInterfaces {
|
||||
private val interfaces = mutableMapOf<Class<out IBlockInterface>, Any>()
|
||||
|
||||
internal val delegate
|
||||
get() = if (interfaces.isEmpty())
|
||||
NoBlockInterfaces
|
||||
else
|
||||
BlockInterfaceContainer(interfaces)
|
||||
|
||||
operator fun <T : IBlockInterface> set(type: Class<T>, impl: T) {
|
||||
interfaces[type] = impl
|
||||
}
|
||||
|
||||
fun includeFrom(source: HeeBlockInterfaces) {
|
||||
this.interfaces.putAll(source.interfaces)
|
||||
}
|
||||
}
|
@@ -1,50 +0,0 @@
|
||||
package chylex.hee.game.block.builder
|
||||
|
||||
import chylex.hee.game.block.util.BlockStateGenerics
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.state.Property
|
||||
import net.minecraft.state.StateContainer
|
||||
import net.minecraft.util.Direction
|
||||
import net.minecraft.util.Mirror
|
||||
import net.minecraft.util.Rotation
|
||||
|
||||
class HeeBlockStates private constructor(private val statesWithDefaults: Map<Property<*>, Comparable<*>>, private val facingProperty: Property<Direction>?) {
|
||||
fun applyDefaults(state: BlockState): BlockState {
|
||||
if (statesWithDefaults.isEmpty()) {
|
||||
return state
|
||||
}
|
||||
|
||||
return statesWithDefaults.entries.fold(state) { acc, entry ->
|
||||
BlockStateGenerics.withProperty(acc, entry.key, entry.value)
|
||||
}
|
||||
}
|
||||
|
||||
fun getRotatedState(state: BlockState, rotation: Rotation): BlockState {
|
||||
return facingProperty?.let { state.with(it, rotation.rotate(state[it])) } ?: state
|
||||
}
|
||||
|
||||
fun getMirroredState(state: BlockState, mirror: Mirror): BlockState {
|
||||
return facingProperty?.let { state.with(it, mirror.mirror(state[it])) } ?: state
|
||||
}
|
||||
|
||||
class Builder {
|
||||
private val statesWithDefaults = mutableMapOf<Property<*>, Comparable<*>>()
|
||||
|
||||
var facingProperty: Property<Direction>? = null
|
||||
|
||||
fun <T : Comparable<T>> set(state: Property<T>, default: T) {
|
||||
statesWithDefaults[state] = default
|
||||
}
|
||||
|
||||
fun fillContainer(builder: StateContainer.Builder<Block, BlockState>) {
|
||||
for (property in statesWithDefaults.keys) {
|
||||
builder.add(property)
|
||||
}
|
||||
}
|
||||
|
||||
fun build(): HeeBlockStates {
|
||||
return HeeBlockStates(statesWithDefaults.toMap(), facingProperty)
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
package chylex.hee.game.block.components
|
||||
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.World
|
||||
|
||||
fun interface IBlockAddedComponent {
|
||||
fun onAdded(state: BlockState, world: World, pos: BlockPos)
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
package chylex.hee.game.block.components
|
||||
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.World
|
||||
import java.util.Random
|
||||
|
||||
interface IBlockClientEffectsComponent {
|
||||
fun randomTick(state: BlockState, world: World, pos: BlockPos, rand: Random) {}
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
package chylex.hee.game.block.components
|
||||
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.World
|
||||
|
||||
fun interface IBlockCollideWithEntityComponent {
|
||||
fun collide(state: BlockState, world: World, pos: BlockPos, entity: Entity)
|
||||
}
|
@@ -1,15 +0,0 @@
|
||||
package chylex.hee.game.block.components
|
||||
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.loot.LootContext
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.IBlockReader
|
||||
|
||||
interface IBlockDropsComponent {
|
||||
fun getDrops(state: BlockState, context: LootContext.Builder): MutableList<ItemStack>
|
||||
|
||||
fun getPickBlock(state: BlockState, world: IBlockReader, pos: BlockPos): ItemStack? {
|
||||
return null
|
||||
}
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
package chylex.hee.game.block.components
|
||||
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
|
||||
fun interface IBlockEntityComponent {
|
||||
fun create(): TileEntity
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
package chylex.hee.game.block.components
|
||||
|
||||
import java.util.Random
|
||||
|
||||
fun interface IBlockExperienceComponent {
|
||||
fun getExperience(rand: Random): Int
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
package chylex.hee.game.block.components
|
||||
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.Explosion
|
||||
import net.minecraft.world.World
|
||||
|
||||
interface IBlockExplodedComponent {
|
||||
fun canDrop(explosion: Explosion): Boolean
|
||||
fun onExploded(state: BlockState, world: World, pos: BlockPos, explosion: Explosion)
|
||||
}
|
@@ -1,8 +0,0 @@
|
||||
package chylex.hee.game.block.components
|
||||
|
||||
import chylex.hee.util.forge.EventResult
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
|
||||
fun interface IBlockHarvestabilityComponent {
|
||||
fun canHarvest(player: PlayerEntity): EventResult
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
package chylex.hee.game.block.components
|
||||
|
||||
import net.minecraft.block.Block
|
||||
|
||||
interface IBlockNameComponent {
|
||||
val translationKey: String
|
||||
|
||||
companion object {
|
||||
fun of(translationKey: String) = object : IBlockNameComponent {
|
||||
override val translationKey
|
||||
get() = translationKey
|
||||
}
|
||||
|
||||
fun of(block: Block) = object : IBlockNameComponent {
|
||||
override val translationKey
|
||||
get() = block.translationKey
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
package chylex.hee.game.block.components
|
||||
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.World
|
||||
|
||||
fun interface IBlockNeighborChanged {
|
||||
fun onNeighborChanged(state: BlockState, world: World, pos: BlockPos, oldNeighborBlock: Block, newNeighborBlock: Block, neighborPos: BlockPos)
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
package chylex.hee.game.block.components
|
||||
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.item.BlockItemUseContext
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.IWorldReader
|
||||
import net.minecraft.world.World
|
||||
|
||||
interface IBlockPlacementComponent {
|
||||
fun isPositionValid(state: BlockState, world: IWorldReader, pos: BlockPos): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
fun getPlacedState(defaultState: BlockState, world: World, pos: BlockPos, context: BlockItemUseContext): BlockState {
|
||||
return defaultState
|
||||
}
|
||||
|
||||
fun onPlacedBy(state: BlockState, world: World, pos: BlockPos, placer: LivingEntity?, stack: ItemStack) {}
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
package chylex.hee.game.block.components
|
||||
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.World
|
||||
import java.util.Random
|
||||
|
||||
fun interface IBlockRandomTickComponent {
|
||||
fun onTick(state: BlockState, world: World, pos: BlockPos, rand: Random)
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
package chylex.hee.game.block.components
|
||||
|
||||
import chylex.hee.game.block.properties.TickSchedule
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.World
|
||||
import java.util.Random
|
||||
|
||||
interface IBlockScheduledTickComponent {
|
||||
/**
|
||||
* Return the amount of ticks before the first [onTick] call after the block is added to the world.
|
||||
*/
|
||||
fun onAdded(state: BlockState, world: World, pos: BlockPos, rand: Random): TickSchedule
|
||||
|
||||
/**
|
||||
* Return the amount of ticks before the next [onTick] call.
|
||||
*/
|
||||
fun onTick(state: BlockState, world: World, pos: BlockPos, rand: Random): TickSchedule
|
||||
}
|
@@ -1,30 +0,0 @@
|
||||
package chylex.hee.game.block.components
|
||||
|
||||
import chylex.hee.game.block.util.asVoxelShape
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.util.math.AxisAlignedBB
|
||||
import net.minecraft.util.math.shapes.VoxelShape
|
||||
|
||||
interface IBlockShapeComponent {
|
||||
fun getShape(state: BlockState): VoxelShape
|
||||
|
||||
fun getCollisionShape(state: BlockState): VoxelShape? {
|
||||
return null
|
||||
}
|
||||
|
||||
fun getRaytraceShape(state: BlockState): VoxelShape? {
|
||||
return null
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun of(shape: VoxelShape) = object : IBlockShapeComponent {
|
||||
override fun getShape(state: BlockState): VoxelShape {
|
||||
return shape
|
||||
}
|
||||
}
|
||||
|
||||
fun of(aabb: AxisAlignedBB): IBlockShapeComponent {
|
||||
return of(aabb.asVoxelShape)
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
package chylex.hee.game.block.components
|
||||
|
||||
import chylex.hee.util.forge.EventResult
|
||||
import net.minecraft.entity.EntitySpawnPlacementRegistry.PlacementType
|
||||
import net.minecraft.entity.EntityType
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.IBlockReader
|
||||
|
||||
fun interface ICreatureSpawningOnBlockComponent {
|
||||
fun canSpawn(world: IBlockReader, pos: BlockPos, placementType: PlacementType?, entityType: EntityType<*>?): EventResult
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
package chylex.hee.game.block.components
|
||||
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.state.properties.BlockStateProperties
|
||||
|
||||
interface IFlammableBlockComponent {
|
||||
val flammability: Int
|
||||
val fireSpread: Int
|
||||
|
||||
fun takeIfFlammable(state: BlockState): IFlammableBlockComponent? {
|
||||
return this.takeUnless { state.hasProperty(BlockStateProperties.WATERLOGGED) && state[BlockStateProperties.WATERLOGGED] }
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun of(flammability: Int, fireSpread: Int) = object : IFlammableBlockComponent {
|
||||
override val flammability = flammability
|
||||
override val fireSpread = fireSpread
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,12 +0,0 @@
|
||||
package chylex.hee.game.block.components
|
||||
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.util.ActionResultType
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.World
|
||||
|
||||
fun interface IPlayerUseBlockComponent {
|
||||
fun use(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand): ActionResultType
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
package chylex.hee.game.block.components
|
||||
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.util.Direction
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.IWorld
|
||||
|
||||
fun interface ISetBlockStateFromNeighbor {
|
||||
fun getNewState(state: BlockState, world: IWorld, pos: BlockPos, neighborFacing: Direction, neighborPos: BlockPos): BlockState
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
package chylex.hee.game.block.interfaces
|
||||
|
||||
internal class BlockInterfaceContainer(interfaces: Map<Class<out IBlockInterface>, Any>) : IBlockWithInterfaces {
|
||||
private val interfaces = interfaces.toMap()
|
||||
|
||||
override fun getInterface(type: Class<out IBlockInterface>): Any? {
|
||||
return interfaces[type]
|
||||
}
|
||||
}
|
@@ -1,6 +0,0 @@
|
||||
package chylex.hee.game.block.interfaces
|
||||
|
||||
/**
|
||||
* Marks interfaces that can be attached to blocks.
|
||||
*/
|
||||
interface IBlockInterface
|
@@ -1,15 +0,0 @@
|
||||
package chylex.hee.game.block.interfaces
|
||||
|
||||
import net.minecraft.block.Block
|
||||
|
||||
interface IBlockWithInterfaces {
|
||||
fun getInterface(type: Class<out IBlockInterface>): Any?
|
||||
}
|
||||
|
||||
inline fun <reified T : IBlockInterface> IBlockWithInterfaces.getHeeInterface(): T? {
|
||||
return this.getInterface(T::class.java) as? T
|
||||
}
|
||||
|
||||
inline fun <reified T : IBlockInterface> Block.getHeeInterface(): T? {
|
||||
return (this as? IBlockWithInterfaces)?.getHeeInterface()
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
package chylex.hee.game.block.interfaces
|
||||
|
||||
internal object NoBlockInterfaces : IBlockWithInterfaces {
|
||||
override fun getInterface(type: Class<out IBlockInterface>): Any? {
|
||||
return null
|
||||
}
|
||||
}
|
@@ -1,10 +1,9 @@
|
||||
package chylex.hee.game.block.logic
|
||||
|
||||
import chylex.hee.game.block.interfaces.IBlockInterface
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.IBlockReader
|
||||
|
||||
interface IBlockDynamicHardness : IBlockInterface {
|
||||
interface IBlockDynamicHardness {
|
||||
fun getBlockHardness(world: IBlockReader, pos: BlockPos, state: BlockState, originalHardness: Float): Float
|
||||
}
|
||||
|
@@ -1,11 +0,0 @@
|
||||
package chylex.hee.game.block.properties
|
||||
|
||||
import net.minecraft.block.AbstractBlock.Properties
|
||||
|
||||
data class BlockHardness(val hardness: Float, val resistance: Float) {
|
||||
constructor(hardnessAndResistance: Float) : this(hardnessAndResistance, hardnessAndResistance)
|
||||
|
||||
fun applyTo(properties: Properties): Properties {
|
||||
return properties.hardnessAndResistance(hardness, resistance)
|
||||
}
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
package chylex.hee.game.block.properties
|
||||
|
||||
import net.minecraft.block.AbstractBlock.Properties
|
||||
import net.minecraftforge.common.ToolType
|
||||
|
||||
@Suppress("DataClassPrivateConstructor")
|
||||
data class BlockHarvestTool private constructor(val tier: Int, val toolType: ToolType?, val requiresTool: Boolean) {
|
||||
fun applyTo(properties: Properties): Properties {
|
||||
return properties
|
||||
.harvestLevel(tier)
|
||||
.let { if (toolType != null) it.harvestTool(toolType) else it }
|
||||
.let { if (requiresTool) it.setRequiresTool() else it }
|
||||
}
|
||||
|
||||
companion object {
|
||||
val NONE = BlockHarvestTool(-1, null, requiresTool = false)
|
||||
|
||||
fun required(tier: Int, toolType: ToolType) = BlockHarvestTool(tier, toolType, requiresTool = true)
|
||||
fun optional(tier: Int, toolType: ToolType) = BlockHarvestTool(tier, toolType, requiresTool = false)
|
||||
}
|
||||
}
|
@@ -1,13 +1,7 @@
|
||||
package chylex.hee.game.block.properties
|
||||
|
||||
import net.minecraft.block.Block
|
||||
|
||||
interface IBlockStateModel : IBlockStateModelSupplier {
|
||||
interface IBlockStateModel {
|
||||
val blockState: BlockStatePreset
|
||||
val blockModel: BlockModel
|
||||
val itemModel: BlockItemModel?
|
||||
|
||||
override fun generate(block: Block): IBlockStateModel {
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +0,0 @@
|
||||
package chylex.hee.game.block.properties
|
||||
|
||||
import net.minecraft.block.Block
|
||||
|
||||
fun interface IBlockStateModelSupplier {
|
||||
fun generate(block: Block): IBlockStateModel
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
package chylex.hee.game.block.properties
|
||||
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.World
|
||||
|
||||
sealed class TickSchedule {
|
||||
abstract fun schedule(world: World, pos: BlockPos, block: Block)
|
||||
|
||||
object Never : TickSchedule() {
|
||||
override fun schedule(world: World, pos: BlockPos, block: Block) {}
|
||||
}
|
||||
|
||||
class InTicks(private val ticks: Int) : TickSchedule() {
|
||||
override fun schedule(world: World, pos: BlockPos, block: Block) {
|
||||
world.pendingBlockTicks.scheduleTick(pos, block, ticks)
|
||||
}
|
||||
}
|
||||
}
|
@@ -2,8 +2,8 @@ package chylex.hee.game.item.components
|
||||
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.util.text.ITextComponent
|
||||
import net.minecraft.world.IBlockReader
|
||||
import net.minecraft.world.World
|
||||
|
||||
fun interface ITooltipComponent {
|
||||
fun add(lines: MutableList<ITextComponent>, stack: ItemStack, advanced: Boolean, world: IBlockReader?)
|
||||
fun add(lines: MutableList<ITextComponent>, stack: ItemStack, advanced: Boolean, world: World?)
|
||||
}
|
||||
|
@@ -2,10 +2,10 @@ package chylex.hee.game.item.components
|
||||
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.util.text.ITextComponent
|
||||
import net.minecraft.world.IBlockReader
|
||||
import net.minecraft.world.World
|
||||
|
||||
class StaticTooltipComponent(private vararg val lines: ITextComponent) : ITooltipComponent {
|
||||
override fun add(lines: MutableList<ITextComponent>, stack: ItemStack, advanced: Boolean, world: IBlockReader?) {
|
||||
override fun add(lines: MutableList<ITextComponent>, stack: ItemStack, advanced: Boolean, world: World?) {
|
||||
lines.addAll(this.lines)
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,6 @@
|
||||
package chylex.hee.game.world.generation.noise
|
||||
|
||||
import chylex.hee.util.math.FloatRange
|
||||
import chylex.hee.util.math.range
|
||||
import chylex.hee.util.math.remapRange
|
||||
import chylex.hee.util.math.remap
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.roundToInt
|
||||
@@ -28,12 +26,12 @@ class NoiseValue(var value: Double) {
|
||||
it.coerceIn(minimum, maximum)
|
||||
}
|
||||
|
||||
fun remap(oldRange: FloatRange, newRange: FloatRange) = then {
|
||||
remapRange(it, oldRange, newRange)
|
||||
fun remap(fromMin: Double, fromMax: Double, toMin: Double, toMax: Double) = then {
|
||||
it.remap(fromMin, fromMax, toMin, toMax)
|
||||
}
|
||||
|
||||
fun remap(newRange: FloatRange) = then {
|
||||
remapRange(it, range(0F, 1F), newRange)
|
||||
fun remap(toMin: Double, toMax: Double) = then {
|
||||
it.remap(fromMin = 0.0, fromMax = 1.0, toMin, toMax)
|
||||
}
|
||||
|
||||
inline fun ifNonZero(block: NoiseValue.() -> Unit) {
|
||||
|
@@ -1,11 +1,13 @@
|
||||
package chylex.hee.system
|
||||
|
||||
import chylex.hee.game.block.components.IPlayerUseBlockComponent
|
||||
import chylex.hee.game.block.HeeBlock
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.command.IClientCommand
|
||||
import chylex.hee.game.command.ICommand
|
||||
|
||||
interface IDebugModule {
|
||||
val clientCommands: List<IClientCommand>
|
||||
val serverCommands: List<ICommand>
|
||||
val scaffoldingBlockBehavior: IPlayerUseBlockComponent?
|
||||
|
||||
fun createScaffoldingBlock(builder: BlockBuilder): HeeBlock
|
||||
}
|
||||
|
@@ -18,54 +18,65 @@ import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.vector.Vector3d
|
||||
import org.apache.logging.log4j.Logger
|
||||
|
||||
inline fun <T : PacketBuffer> T.use(block: T.() -> Unit) {
|
||||
block()
|
||||
}
|
||||
|
||||
// BlockPos
|
||||
|
||||
inline fun PacketBuffer.writePos(pos: BlockPos) {
|
||||
inline fun ByteBuf.writePos(pos: BlockPos) {
|
||||
this.writeLong(pos.toLong())
|
||||
}
|
||||
|
||||
inline fun PacketBuffer.readPos(): BlockPos {
|
||||
inline fun ByteBuf.readPos(): BlockPos {
|
||||
return Pos(this.readLong())
|
||||
}
|
||||
|
||||
// Vec3d (Full)
|
||||
|
||||
fun PacketBuffer.writeVec(vec: Vector3d) {
|
||||
fun ByteBuf.writeVec(vec: Vector3d) {
|
||||
this.writeDouble(vec.x)
|
||||
this.writeDouble(vec.y)
|
||||
this.writeDouble(vec.z)
|
||||
}
|
||||
|
||||
fun PacketBuffer.readVec(): Vector3d {
|
||||
return Vec(readDouble(), readDouble(), readDouble())
|
||||
fun ByteBuf.readVec(): Vector3d {
|
||||
return Vec(this.readDouble(), this.readDouble(), this.readDouble())
|
||||
}
|
||||
|
||||
// Vec3d (Float)
|
||||
|
||||
fun PacketBuffer.writeFloatVec(vec: Vector3d) {
|
||||
fun ByteBuf.writeFloatVec(vec: Vector3d) {
|
||||
this.writeFloat(vec.x.toFloat())
|
||||
this.writeFloat(vec.y.toFloat())
|
||||
this.writeFloat(vec.z.toFloat())
|
||||
}
|
||||
|
||||
fun PacketBuffer.readFloatVec(): Vector3d {
|
||||
return Vec(readFloat().toDouble(), readFloat().toDouble(), readFloat().toDouble())
|
||||
fun ByteBuf.readFloatVec(): Vector3d {
|
||||
return Vec(this.readFloat().toDouble(), this.readFloat().toDouble(), this.readFloat().toDouble())
|
||||
}
|
||||
|
||||
// Vec3d (Compact)
|
||||
|
||||
fun PacketBuffer.writeCompactVec(vec: Vector3d) {
|
||||
fun ByteBuf.writeCompactVec(vec: Vector3d) {
|
||||
this.writeInt((vec.x * 8.0).floorToInt())
|
||||
this.writeInt((vec.y * 8.0).floorToInt())
|
||||
this.writeInt((vec.z * 8.0).floorToInt())
|
||||
}
|
||||
|
||||
fun PacketBuffer.readCompactVec(): Vector3d {
|
||||
return Vec(readInt() * 0.125, readInt() * 0.125, readInt() * 0.125)
|
||||
fun ByteBuf.readCompactVec(): Vector3d {
|
||||
return Vec(this.readInt() * 0.125, this.readInt() * 0.125, this.readInt() * 0.125)
|
||||
}
|
||||
|
||||
// Enum
|
||||
|
||||
fun <T : Enum<T>> PacketBuffer.writeEnum(value: T?) {
|
||||
this.writeVarInt(value?.ordinal ?: -1)
|
||||
}
|
||||
|
||||
inline fun <reified T : Enum<T>> PacketBuffer.readEnum(): T? {
|
||||
val ordinal = this.readVarInt()
|
||||
|
||||
return if (ordinal >= 0)
|
||||
T::class.java.enumConstants.getOrNull(ordinal)
|
||||
else
|
||||
null
|
||||
}
|
||||
|
||||
// NBT
|
||||
|
@@ -1,16 +0,0 @@
|
||||
package chylex.hee.util.forge
|
||||
|
||||
import net.minecraftforge.eventbus.api.Event.Result.ALLOW
|
||||
import net.minecraftforge.eventbus.api.Event.Result.DEFAULT
|
||||
import net.minecraftforge.eventbus.api.Event.Result.DENY
|
||||
|
||||
val EventResult.asBool: Boolean?
|
||||
get() = when (this) {
|
||||
ALLOW -> true
|
||||
DENY -> false
|
||||
DEFAULT -> null
|
||||
}
|
||||
|
||||
fun EventResult(allow: Boolean): EventResult {
|
||||
return if (allow) ALLOW else DENY
|
||||
}
|
@@ -46,17 +46,17 @@ fun lerp(from: Double, to: Double, progress: Double): Double {
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a range of values in [from] range to values in [to] range using linear interpolation.
|
||||
* Remaps a value from the range [[fromMin], [fromMax]] to a value in the range [[toMin], [toMax]] using linear interpolation.
|
||||
*/
|
||||
fun remapRange(value: Float, from: FloatRange, to: FloatRange): Float {
|
||||
val remappedBetween0And1 = (value - from.start) / (from.end - from.start)
|
||||
return to.start + remappedBetween0And1 * (to.end - to.start)
|
||||
fun Float.remap(fromMin: Float, fromMax: Float, toMin: Float, toMax: Float): Float {
|
||||
val remappedBetween0And1 = (this - fromMin) / (fromMax - fromMin)
|
||||
return toMin + remappedBetween0And1 * (toMax - toMin)
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a range of values in [from] range to values in [to] range using linear interpolation.
|
||||
* Remaps a value from the range [[fromMin], [fromMax]] to a value in the range [[toMin], [toMax]] using linear interpolation.
|
||||
*/
|
||||
fun remapRange(value: Double, from: FloatRange, to: FloatRange): Double {
|
||||
val remappedBetween0And1 = (value - from.start) / (from.end - from.start)
|
||||
return to.start + remappedBetween0And1 * (to.end - to.start)
|
||||
fun Double.remap(fromMin: Double, fromMax: Double, toMin: Double, toMax: Double): Double {
|
||||
val remappedBetween0And1 = (this - fromMin) / (fromMax - fromMin)
|
||||
return toMin + remappedBetween0And1 * (toMax - toMin)
|
||||
}
|
||||
|
@@ -1,14 +0,0 @@
|
||||
package chylex.hee.util.math
|
||||
|
||||
@JvmInline
|
||||
value class FloatRange(private val combined: Long) {
|
||||
constructor(start: Float, end: Float) : this((start.toRawBits() shlong 32) or (end.toRawBits().toLong() and 0xFFFF_FFFFL))
|
||||
|
||||
val start
|
||||
get() = Float.fromBits((combined ushr 32).toInt())
|
||||
|
||||
val end
|
||||
get() = Float.fromBits((combined and 0xFFFF_FFFFL).toInt())
|
||||
}
|
||||
|
||||
fun range(start: Float, end: Float) = FloatRange(start, end)
|
@@ -15,6 +15,7 @@ import net.minecraftforge.common.util.Constants.NBT
|
||||
import org.apache.logging.log4j.Logger
|
||||
import java.util.Locale
|
||||
import java.util.UUID
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
|
||||
typealias NBTBase = net.minecraft.nbt.INBT
|
||||
@@ -54,12 +55,14 @@ inline fun TagCompound.hasKey(key: String, type: Int): Boolean {
|
||||
return this.contains(key, type)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
@JvmName("isNotNullAndHasKey")
|
||||
inline fun TagCompound?.hasKey(key: String): Boolean {
|
||||
contract { returns(true) implies (this@hasKey != null) }
|
||||
return this != null && this.hasKey(key)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
@JvmName("isNotNullAndHasKey")
|
||||
inline fun TagCompound?.hasKey(key: String, type: Int): Boolean {
|
||||
contract { returns(true) implies (this@hasKey != null) }
|
||||
|
@@ -1,7 +1,6 @@
|
||||
package chylex.hee.util.random
|
||||
|
||||
import chylex.hee.util.math.range
|
||||
import chylex.hee.util.math.remapRange
|
||||
import chylex.hee.util.math.remap
|
||||
import java.util.Random
|
||||
import kotlin.math.pow
|
||||
|
||||
@@ -30,7 +29,7 @@ abstract class RandomDouble private constructor(val min: Double, val max: Double
|
||||
|
||||
fun Exp(min: Double, max: Double, exp: Double) = object : RandomDouble(min, max) {
|
||||
override fun invoke(rand: Random): Double {
|
||||
return remapRange(rand.nextDouble().pow(exp), range(0F, 1F), range(min.toFloat(), max.toFloat()))
|
||||
return rand.nextDouble().pow(exp).remap(fromMin = 0.0, fromMax = 1.0, toMin = min, toMax = max)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,3 +1,5 @@
|
||||
rootProject.name = "HEE"
|
||||
|
||||
include ":util"
|
||||
include ":system"
|
||||
include ":debug"
|
||||
|
@@ -10,7 +10,6 @@ import chylex.hee.client.util.MC
|
||||
import chylex.hee.game.Resource
|
||||
import chylex.hee.game.block.BlockAbstractPortal
|
||||
import chylex.hee.game.block.entity.TileEntityEnergyCluster
|
||||
import chylex.hee.game.block.interfaces.getHeeInterface
|
||||
import chylex.hee.game.block.properties.Materials
|
||||
import chylex.hee.game.mechanics.energy.IClusterOracleItem
|
||||
import chylex.hee.game.mechanics.energy.IEnergyQuantity
|
||||
@@ -36,7 +35,7 @@ import net.minecraftforge.client.event.RenderGameOverlayEvent
|
||||
import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType.HELMET
|
||||
|
||||
@SubscribeAllEvents(Side.CLIENT, modid = HEE.ID)
|
||||
object OverlayRenderer { // TODO move to appropriate block builders
|
||||
object OverlayRenderer {
|
||||
private const val BORDER_SIZE = 4
|
||||
private const val LINE_SPACING = 7
|
||||
|
||||
@@ -148,7 +147,7 @@ object OverlayRenderer { // TODO move to appropriate block builders
|
||||
clusterLookedAt = pos.getTile(world)
|
||||
e.isCanceled = true
|
||||
}
|
||||
else if (block.getHeeInterface<BlockAbstractPortal.IInnerPortalBlock>() != null) {
|
||||
else if (block is BlockAbstractPortal) {
|
||||
e.isCanceled = true
|
||||
}
|
||||
}
|
||||
|
@@ -25,8 +25,7 @@ import chylex.hee.util.forge.SubscribeAllEvents
|
||||
import chylex.hee.util.forge.SubscribeEvent
|
||||
import chylex.hee.util.math.LerpedFloat
|
||||
import chylex.hee.util.math.floorToInt
|
||||
import chylex.hee.util.math.range
|
||||
import chylex.hee.util.math.remapRange
|
||||
import chylex.hee.util.math.remap
|
||||
import chylex.hee.util.math.scale
|
||||
import com.mojang.blaze3d.matrix.MatrixStack
|
||||
import com.mojang.blaze3d.platform.GlStateManager.FogMode.EXP2
|
||||
@@ -118,7 +117,7 @@ object TerritoryRenderer {
|
||||
// Fog rendering
|
||||
|
||||
private val currentFogDensityMp
|
||||
get() = 1F + (9F * remapRange(currentVoidFactor, range(-0.5F, 1F), range(0F, 1F)).coerceIn(0F, 1F).pow(1.5F))
|
||||
get() = 1F + (9F * currentVoidFactor.remap(fromMin = -0.5F, fromMax = 1F, toMin = 0F, toMax = 1F).coerceIn(0F, 1F).pow(1.5F))
|
||||
|
||||
private val currentRenderDistanceMp
|
||||
get() = MC.settings.renderDistanceChunks.let { if (it > 12) 0F else (1F - (it / 16.5F)).pow((it - 1) * 0.25F) }
|
||||
@@ -148,7 +147,7 @@ object TerritoryRenderer {
|
||||
get() = Void.voidFactor.get(MC.partialTicks)
|
||||
|
||||
val currentSkyAlpha
|
||||
get() = remapRange(currentVoidFactor, range(-1F, 0.5F), range(1F, 0F)).coerceIn(0F, 1F)
|
||||
get() = currentVoidFactor.remap(fromMin = -1F, fromMax = 0.5F, toMin = 1F, toMax = 0F).coerceIn(0F, 1F)
|
||||
|
||||
private object Void {
|
||||
private val VOID_PARTICLE = ParticleSpawnerCustom(
|
||||
|
@@ -1,9 +1,9 @@
|
||||
package chylex.hee.client.render.block
|
||||
|
||||
import chylex.hee.game.block.BlockAbstractPortal
|
||||
import chylex.hee.game.block.BlockVoidPortalInner.Companion.TYPE
|
||||
import chylex.hee.game.block.BlockVoidPortalInner.ITerritoryInstanceFactory
|
||||
import chylex.hee.game.block.BlockVoidPortalInner.IVoidPortalController
|
||||
import chylex.hee.game.block.BlockVoidPortalInner.TYPE
|
||||
import chylex.hee.game.block.BlockVoidPortalInner.Type.HUB
|
||||
import chylex.hee.game.block.BlockVoidPortalInner.Type.RETURN_ACTIVE
|
||||
import chylex.hee.game.block.entity.TileEntityPortalInner
|
||||
|
@@ -49,13 +49,13 @@ class RenderEntityTokenHolder(manager: EntityRendererManager) : EntityRenderer<E
|
||||
matrix.rotateX(55F)
|
||||
matrix.rotateZ(55F)
|
||||
|
||||
ModelEntityTokenHolder.render(matrix, buffer.getBuffer(RenderType.getEntityTranslucent(getEntityTexture(entity) ?: textures.getValue(NORMAL))), combinedLight, OverlayTexture.NO_OVERLAY, 1F, 1F, 1F, alpha)
|
||||
ModelEntityTokenHolder.render(matrix, buffer.getBuffer(RenderType.getEntityTranslucent(getEntityTexture(entity))), combinedLight, OverlayTexture.NO_OVERLAY, 1F, 1F, 1F, alpha)
|
||||
|
||||
matrix.pop()
|
||||
matrix.pop()
|
||||
}
|
||||
|
||||
override fun getEntityTexture(entity: EntityTokenHolder): ResourceLocation? {
|
||||
return textures[entity.tokenType]
|
||||
override fun getEntityTexture(entity: EntityTokenHolder): ResourceLocation {
|
||||
return textures.getValue(entity.tokenType)
|
||||
}
|
||||
}
|
||||
|
@@ -1,51 +0,0 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.components.IBlockShapeComponent
|
||||
import chylex.hee.game.block.properties.BlockDrop
|
||||
import chylex.hee.game.block.properties.BlockHardness
|
||||
import chylex.hee.game.block.properties.BlockHarvestTool
|
||||
import chylex.hee.game.block.properties.BlockModel
|
||||
import chylex.hee.game.block.properties.IBlockStateModelSupplier
|
||||
import chylex.hee.game.block.properties.Materials
|
||||
import net.minecraft.block.SoundType
|
||||
import net.minecraft.block.material.MaterialColor
|
||||
import net.minecraft.util.math.AxisAlignedBB
|
||||
import net.minecraftforge.common.Tags
|
||||
|
||||
val BlockIndestructible
|
||||
get() = HeeBlockBuilder {
|
||||
drop = BlockDrop.Nothing
|
||||
tool = BlockHarvestTool.NONE
|
||||
hardness = BlockHardness(hardness = -1F, resistance = 3600000F)
|
||||
}
|
||||
|
||||
val BlockEndStoneBase
|
||||
get() = HeeBlockBuilder {
|
||||
material = Materials.SOLID
|
||||
color = MaterialColor.SAND
|
||||
sound = SoundType.STONE
|
||||
}
|
||||
|
||||
val BlockEndOre
|
||||
get() = HeeBlockBuilder {
|
||||
includeFrom(BlockEndStoneBase)
|
||||
tags.add(Tags.Blocks.ORES)
|
||||
}
|
||||
|
||||
val BlockPortalFrameBase
|
||||
get() = HeeBlockBuilder {
|
||||
model = IBlockStateModelSupplier { BlockModel.PortalFrame(it, "plain") }
|
||||
|
||||
material = Materials.SOLID
|
||||
color = MaterialColor.SAND
|
||||
sound = SoundType.STONE
|
||||
|
||||
components.shape = IBlockShapeComponent.of(AxisAlignedBB(0.0, 0.0, 0.0, 1.0, 0.8125, 1.0))
|
||||
}
|
||||
|
||||
val BlockPortalFrameIndestructible
|
||||
get() = HeeBlockBuilder {
|
||||
includeFrom(BlockPortalFrameBase)
|
||||
includeFrom(BlockIndestructible)
|
||||
}
|
@@ -1,15 +1,11 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.client.text.LocalizationStrategy
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.components.IBlockCollideWithEntityComponent
|
||||
import chylex.hee.game.block.components.IBlockEntityComponent
|
||||
import chylex.hee.game.block.components.IBlockShapeComponent
|
||||
import chylex.hee.game.block.interfaces.IBlockInterface
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockModel
|
||||
import chylex.hee.game.block.properties.BlockStateModel
|
||||
import chylex.hee.game.block.properties.BlockStatePreset
|
||||
import chylex.hee.game.entity.util.EntityPortalContact
|
||||
import chylex.hee.game.block.util.asVoxelShape
|
||||
import chylex.hee.game.world.util.Facing4
|
||||
import chylex.hee.game.world.util.allInBox
|
||||
import chylex.hee.game.world.util.allInBoxMutable
|
||||
@@ -28,27 +24,25 @@ import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockRenderType.INVISIBLE
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.block.SoundType
|
||||
import net.minecraft.block.material.Material
|
||||
import net.minecraft.block.material.MaterialColor
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.tags.BlockTags
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.util.math.AxisAlignedBB
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.shapes.ISelectionContext
|
||||
import net.minecraft.util.math.shapes.VoxelShape
|
||||
import net.minecraft.util.math.shapes.VoxelShapes
|
||||
import net.minecraft.world.IBlockReader
|
||||
import net.minecraft.world.World
|
||||
|
||||
class BlockAbstractPortal(impl: IInnerPortalBlock) : HeeBlockBuilder() {
|
||||
abstract class BlockAbstractPortal(builder: BlockBuilder) : BlockSimpleShaped(builder, AxisAlignedBB(0.0, 0.0, 0.0, 1.0, 0.75, 1.0)) {
|
||||
companion object {
|
||||
const val MAX_DISTANCE_FROM_FRAME = 6.0
|
||||
const val MAX_SIZE = 5
|
||||
|
||||
private const val TRANSLATION_SPEED_LONG = 600000L
|
||||
const val TRANSLATION_SPEED_LONG = 600000L
|
||||
const val TRANSLATION_SPEED_INV = 1.0 / TRANSLATION_SPEED_LONG
|
||||
|
||||
private val SHAPE = VoxelShapes.create(0.0, 0.0, 0.0, 1.0, 0.75, 1.0)
|
||||
private val COLLISION_SHAPE = VoxelShapes.create(0.0, 0.0, 0.0, 1.0, 0.025, 1.0)
|
||||
private val COLLISION_AABB = AxisAlignedBB(0.0, 0.0, 0.0, 1.0, 0.025, 1.0).asVoxelShape
|
||||
|
||||
fun findInnerArea(world: World, controllerPos: BlockPos, frameBlock: Block): Pair<BlockPos, BlockPos>? {
|
||||
val mirrorRange = 1..(MAX_SIZE + 1)
|
||||
@@ -100,52 +94,36 @@ class BlockAbstractPortal(impl: IInnerPortalBlock) : HeeBlockBuilder() {
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
includeFrom(BlockIndestructible)
|
||||
|
||||
localization = LocalizationStrategy.DeleteWords("Inner")
|
||||
|
||||
model = BlockStateModel(BlockStatePreset.SimpleFrom(Blocks.END_PORTAL), BlockModel.Manual)
|
||||
|
||||
material = Material.PORTAL
|
||||
color = MaterialColor.BLACK
|
||||
sound = SoundType.STONE
|
||||
light = 15
|
||||
|
||||
isSolid = false
|
||||
|
||||
tags.add(BlockTags.PORTALS)
|
||||
|
||||
components.shape = object : IBlockShapeComponent {
|
||||
override fun getShape(state: BlockState): VoxelShape {
|
||||
return SHAPE
|
||||
}
|
||||
|
||||
override fun getCollisionShape(state: BlockState): VoxelShape? {
|
||||
return COLLISION_SHAPE
|
||||
}
|
||||
}
|
||||
|
||||
components.renderType = INVISIBLE
|
||||
|
||||
components.entity = IBlockEntityComponent(impl::createTileEntity)
|
||||
|
||||
components.collideWithEntity = IBlockCollideWithEntityComponent { _, world, pos, entity ->
|
||||
if (!world.isRemote && !entity.isPassenger && !entity.isBeingRidden && entity.canChangeDimension() && entity.posY <= pos.y + 0.05 && EntityPortalContact.shouldTeleport(entity)) {
|
||||
impl.teleportEntity(world, pos, entity)
|
||||
}
|
||||
}
|
||||
|
||||
interfaces[IInnerPortalBlock::class.java] = impl
|
||||
}
|
||||
|
||||
interface IInnerPortalBlock : IBlockInterface {
|
||||
fun createTileEntity(): TileEntity
|
||||
fun teleportEntity(world: World, pos: BlockPos, entity: Entity)
|
||||
}
|
||||
|
||||
interface IPortalController {
|
||||
val clientAnimationProgress: LerpedFloat
|
||||
val clientPortalOffset: LerpedFloat
|
||||
}
|
||||
|
||||
final override val localization
|
||||
get() = LocalizationStrategy.DeleteWords("Inner")
|
||||
|
||||
final override val model
|
||||
get() = BlockStateModel(BlockStatePreset.SimpleFrom(Blocks.END_PORTAL), BlockModel.Manual)
|
||||
|
||||
final override val tags
|
||||
get() = listOf(BlockTags.PORTALS)
|
||||
|
||||
override fun hasTileEntity(state: BlockState): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
abstract override fun createTileEntity(state: BlockState, world: IBlockReader): TileEntity
|
||||
protected abstract fun onEntityInside(world: World, pos: BlockPos, entity: Entity)
|
||||
|
||||
final override fun onEntityCollision(state: BlockState, world: World, pos: BlockPos, entity: Entity) {
|
||||
if (!world.isRemote && !entity.isPassenger && !entity.isBeingRidden && entity.canChangeDimension() && entity.posY <= pos.y + 0.05) {
|
||||
onEntityInside(world, pos, entity)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getCollisionShape(state: BlockState, world: IBlockReader, pos: BlockPos, context: ISelectionContext): VoxelShape {
|
||||
return COLLISION_AABB
|
||||
}
|
||||
|
||||
final override fun getRenderType(state: BlockState) = INVISIBLE
|
||||
}
|
||||
|
@@ -5,18 +5,11 @@ import chylex.hee.game.Resource.location
|
||||
import chylex.hee.game.block.BlockCorruptedEnergy.SpawnResult.FAIL
|
||||
import chylex.hee.game.block.BlockCorruptedEnergy.SpawnResult.PASSTHROUGH
|
||||
import chylex.hee.game.block.BlockCorruptedEnergy.SpawnResult.SUCCESS
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.components.IBlockClientEffectsComponent
|
||||
import chylex.hee.game.block.components.IBlockCollideWithEntityComponent
|
||||
import chylex.hee.game.block.components.IBlockRandomTickComponent
|
||||
import chylex.hee.game.block.components.IBlockScheduledTickComponent
|
||||
import chylex.hee.game.block.entity.TileEntityEnergyCluster
|
||||
import chylex.hee.game.block.properties.BlockDrop
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockModel
|
||||
import chylex.hee.game.block.properties.BlockStateModel
|
||||
import chylex.hee.game.block.properties.BlockStatePreset
|
||||
import chylex.hee.game.block.properties.Materials
|
||||
import chylex.hee.game.block.properties.TickSchedule
|
||||
import chylex.hee.game.block.util.Property
|
||||
import chylex.hee.game.block.util.with
|
||||
import chylex.hee.game.entity.CustomCreatureType
|
||||
@@ -42,19 +35,25 @@ import chylex.hee.game.world.util.getTile
|
||||
import chylex.hee.game.world.util.removeBlock
|
||||
import chylex.hee.game.world.util.setState
|
||||
import chylex.hee.init.ModBlocks
|
||||
import chylex.hee.util.forge.Side
|
||||
import chylex.hee.util.forge.Sided
|
||||
import chylex.hee.util.random.nextInt
|
||||
import chylex.hee.util.random.removeItem
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockRenderType.INVISIBLE
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.block.SoundType
|
||||
import net.minecraft.block.material.MaterialColor
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.state.StateContainer.Builder
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.IBlockReader
|
||||
import net.minecraft.world.World
|
||||
import net.minecraft.world.server.ServerWorld
|
||||
import java.util.Random
|
||||
|
||||
object BlockCorruptedEnergy : HeeBlockBuilder() {
|
||||
class BlockCorruptedEnergy(builder: BlockBuilder) : HeeBlock(builder) {
|
||||
companion object {
|
||||
private const val MIN_LEVEL = 0
|
||||
private const val MAX_LEVEL = 20
|
||||
|
||||
@@ -73,93 +72,24 @@ object BlockCorruptedEnergy : HeeBlockBuilder() {
|
||||
hideOnMinimalSetting = false
|
||||
)
|
||||
|
||||
init {
|
||||
localization = LocalizationStrategy.None
|
||||
model = BlockStateModel(BlockStatePreset.Simple, BlockModel.NoAmbientOcclusion(BlockModel.Cross(Blocks.BARRIER.asItem().location)))
|
||||
// renderLayer = CUTOUT // Debugging
|
||||
|
||||
material = Materials.CORRUPTED_ENERGY
|
||||
color = MaterialColor.PURPLE
|
||||
sound = SoundType.SAND
|
||||
|
||||
isSolid = false
|
||||
|
||||
drop = BlockDrop.Nothing
|
||||
|
||||
components.states.set(LEVEL, MIN_LEVEL)
|
||||
|
||||
components.renderType = INVISIBLE
|
||||
components.ambientOcclusionValue = 1F
|
||||
|
||||
components.clientEffects = object : IBlockClientEffectsComponent {
|
||||
override fun randomTick(state: BlockState, world: World, pos: BlockPos, rand: Random) {
|
||||
val amount = rand.nextInt(0, 2)
|
||||
if (amount > 0) {
|
||||
PARTICLE_CORRUPTION.spawn(Point(pos, amount), rand) // POLISH figure out how to show particles outside animateTick range
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
components.scheduledTick = object : IBlockScheduledTickComponent {
|
||||
override fun onAdded(state: BlockState, world: World, pos: BlockPos, rand: Random): TickSchedule {
|
||||
return tickScheduleForLevel(state[LEVEL])
|
||||
}
|
||||
|
||||
override fun onTick(state: BlockState, world: World, pos: BlockPos, rand: Random): TickSchedule {
|
||||
val level = state[LEVEL]
|
||||
val remainingFacings = Facing6.toMutableList()
|
||||
|
||||
repeat(rand.nextInt(3, 5).coerceAtMost(level)) {
|
||||
val facing = rand.removeItem(remainingFacings)
|
||||
val adjacentPos = pos.offset(facing)
|
||||
|
||||
val spreadDecrease = if (rand.nextInt(3) == 0) 0 else 1
|
||||
|
||||
if (spawn(world, adjacentPos, level - spreadDecrease) == PASSTHROUGH) {
|
||||
spawn(world, adjacentPos.offset(facing), level - spreadDecrease - 1)
|
||||
}
|
||||
}
|
||||
|
||||
if (rand.nextInt(4) != 0) {
|
||||
val decreaseToLevel = level - rand.nextInt(1, 2)
|
||||
|
||||
if (decreaseToLevel < MIN_LEVEL) {
|
||||
pos.removeBlock(world)
|
||||
return TickSchedule.Never
|
||||
}
|
||||
|
||||
pos.setState(world, state.with(LEVEL, decreaseToLevel), FLAG_NONE) // does not call onBlockAdded for the same Block instance
|
||||
}
|
||||
|
||||
return tickScheduleForLevel(level)
|
||||
}
|
||||
|
||||
private fun tickScheduleForLevel(level: Int): TickSchedule {
|
||||
return TickSchedule.InTicks((MAX_TICK_RATE - (level / 2)).coerceAtLeast(MIN_TICK_RATE))
|
||||
}
|
||||
}
|
||||
|
||||
components.randomTick = IBlockRandomTickComponent { state, world, pos, _ ->
|
||||
if (!world.pendingBlockTicks.isTickScheduled(pos, state.block)) {
|
||||
pos.removeBlock(world)
|
||||
}
|
||||
}
|
||||
|
||||
components.collideWithEntity = IBlockCollideWithEntityComponent { state, world, pos, entity ->
|
||||
if (!world.isRemote && entity is LivingEntity && !isEntityTolerant(entity)) {
|
||||
CombinedDamage(
|
||||
DAMAGE_PART_NORMAL to 0.75F,
|
||||
DAMAGE_PART_MAGIC to (0.75F + state[LEVEL] / 10F)
|
||||
).dealTo(entity, TITLE_MAGIC)
|
||||
}
|
||||
}
|
||||
|
||||
components.isAir = true
|
||||
private fun tickRateForLevel(level: Int): Int {
|
||||
return (MAX_TICK_RATE - (level / 2)).coerceAtLeast(MIN_TICK_RATE)
|
||||
}
|
||||
|
||||
private fun isEntityTolerant(entity: LivingEntity): Boolean {
|
||||
return CustomCreatureType.isDemon(entity) || CustomCreatureType.isShadow(entity) || entity is IImmuneToCorruptedEnergy
|
||||
}
|
||||
}
|
||||
|
||||
override val localization
|
||||
get() = LocalizationStrategy.None
|
||||
|
||||
override val model
|
||||
get() = BlockStateModel(BlockStatePreset.Simple, BlockModel.NoAmbientOcclusion(BlockModel.Cross(Blocks.BARRIER.asItem().location)))
|
||||
|
||||
override fun fillStateContainer(container: Builder<Block, BlockState>) {
|
||||
container.add(LEVEL)
|
||||
}
|
||||
|
||||
// Utility methods
|
||||
|
||||
@@ -167,19 +97,19 @@ object BlockCorruptedEnergy : HeeBlockBuilder() {
|
||||
SUCCESS, PASSTHROUGH, FAIL
|
||||
}
|
||||
|
||||
fun spawn(world: World, pos: BlockPos, level: Int): SpawnResult {
|
||||
fun spawnCorruptedEnergy(world: World, pos: BlockPos, level: Int): SpawnResult {
|
||||
if (level < MIN_LEVEL) {
|
||||
return FAIL
|
||||
}
|
||||
else if (level > MAX_LEVEL) {
|
||||
return spawn(world, pos, MAX_LEVEL)
|
||||
return spawnCorruptedEnergy(world, pos, MAX_LEVEL)
|
||||
}
|
||||
|
||||
val currentState = pos.getState(world)
|
||||
val currentBlock = currentState.block
|
||||
var updateFlags = FLAG_SYNC_CLIENT
|
||||
|
||||
if (currentBlock === ModBlocks.CORRUPTED_ENERGY) {
|
||||
if (currentBlock === this) {
|
||||
if (level - currentState[LEVEL] < 3 || world.rand.nextBoolean()) {
|
||||
return FAIL
|
||||
}
|
||||
@@ -200,7 +130,88 @@ object BlockCorruptedEnergy : HeeBlockBuilder() {
|
||||
PASSTHROUGH
|
||||
}
|
||||
|
||||
pos.setState(world, ModBlocks.CORRUPTED_ENERGY.with(LEVEL, level), updateFlags)
|
||||
pos.setState(world, this.with(LEVEL, level), updateFlags)
|
||||
return SUCCESS
|
||||
}
|
||||
|
||||
// Tick handling
|
||||
|
||||
override fun onBlockAdded(state: BlockState, world: World, pos: BlockPos, oldState: BlockState, isMoving: Boolean) {
|
||||
world.pendingBlockTicks.scheduleTick(pos, this, tickRateForLevel(state[LEVEL]))
|
||||
}
|
||||
|
||||
override fun randomTick(state: BlockState, world: ServerWorld, pos: BlockPos, rand: Random) {
|
||||
if (!world.pendingBlockTicks.isTickScheduled(pos, this)) {
|
||||
pos.removeBlock(world)
|
||||
}
|
||||
}
|
||||
|
||||
override fun tick(state: BlockState, world: ServerWorld, pos: BlockPos, rand: Random) {
|
||||
val level = state[LEVEL]
|
||||
val remainingFacings = Facing6.toMutableList()
|
||||
|
||||
repeat(rand.nextInt(3, 5).coerceAtMost(level)) {
|
||||
val facing = rand.removeItem(remainingFacings)
|
||||
val adjacentPos = pos.offset(facing)
|
||||
|
||||
val spreadDecrease = if (rand.nextInt(3) == 0) 0 else 1
|
||||
|
||||
if (spawnCorruptedEnergy(world, adjacentPos, level - spreadDecrease) == PASSTHROUGH) {
|
||||
spawnCorruptedEnergy(world, adjacentPos.offset(facing), level - spreadDecrease - 1)
|
||||
}
|
||||
}
|
||||
|
||||
if (rand.nextInt(4) != 0) {
|
||||
val decreaseToLevel = level - rand.nextInt(1, 2)
|
||||
|
||||
if (decreaseToLevel < MIN_LEVEL) {
|
||||
pos.removeBlock(world)
|
||||
return
|
||||
}
|
||||
|
||||
pos.setState(world, state.with(LEVEL, decreaseToLevel), FLAG_NONE) // does not call onBlockAdded for the same Block instance
|
||||
}
|
||||
|
||||
world.pendingBlockTicks.scheduleTick(pos, this, tickRateForLevel(level))
|
||||
}
|
||||
|
||||
// Interactions
|
||||
|
||||
override fun isAir(state: BlockState, world: IBlockReader, pos: BlockPos): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun propagatesSkylightDown(state: BlockState, world: IBlockReader, pos: BlockPos): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onEntityCollision(state: BlockState, world: World, pos: BlockPos, entity: Entity) {
|
||||
if (!world.isRemote && entity is LivingEntity && !isEntityTolerant(entity)) {
|
||||
CombinedDamage(
|
||||
DAMAGE_PART_NORMAL to 0.75F,
|
||||
DAMAGE_PART_MAGIC to (0.75F + state[LEVEL] / 10F)
|
||||
).dealTo(entity, TITLE_MAGIC)
|
||||
}
|
||||
}
|
||||
|
||||
// Client side
|
||||
|
||||
@Sided(Side.CLIENT)
|
||||
override fun animateTick(state: BlockState, world: World, pos: BlockPos, rand: Random) {
|
||||
val amount = rand.nextInt(0, 2)
|
||||
|
||||
if (amount > 0) {
|
||||
PARTICLE_CORRUPTION.spawn(Point(pos, amount), rand) // POLISH figure out how to show particles outside animateTick range
|
||||
}
|
||||
}
|
||||
|
||||
@Sided(Side.CLIENT)
|
||||
override fun getAmbientOcclusionLightValue(state: BlockState, world: IBlockReader, pos: BlockPos): Float {
|
||||
return 1F
|
||||
}
|
||||
|
||||
override fun getRenderType(state: BlockState) = INVISIBLE
|
||||
|
||||
// Debugging
|
||||
// override fun getRenderLayer() = CUTOUT
|
||||
}
|
||||
|
@@ -1,46 +1,42 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.components.IBlockAddedComponent
|
||||
import chylex.hee.game.block.components.IBlockEntityComponent
|
||||
import chylex.hee.game.block.components.IPlayerUseBlockComponent
|
||||
import chylex.hee.game.block.components.ISetBlockStateFromNeighbor
|
||||
import chylex.hee.game.block.entity.TileEntityEndPortalAcceptor
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockModel
|
||||
import chylex.hee.game.world.util.getTile
|
||||
import chylex.hee.init.ModBlocks
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.util.ActionResultType
|
||||
import net.minecraft.util.ActionResultType.PASS
|
||||
import net.minecraft.util.ActionResultType.SUCCESS
|
||||
import net.minecraft.util.Direction
|
||||
import net.minecraft.util.Direction.UP
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.BlockRayTraceResult
|
||||
import net.minecraft.world.IBlockReader
|
||||
import net.minecraft.world.IWorld
|
||||
import net.minecraft.world.World
|
||||
|
||||
object BlockEndPortalAcceptor : HeeBlockBuilder() {
|
||||
init {
|
||||
includeFrom(BlockPortalFrameIndestructible)
|
||||
class BlockEndPortalAcceptor(builder: BlockBuilder) : BlockPortalFrame(builder) {
|
||||
override val model
|
||||
get() = BlockModel.PortalFrame(ModBlocks.END_PORTAL_FRAME, "acceptor")
|
||||
|
||||
model = BlockModel.PortalFrame(ModBlocks.END_PORTAL_FRAME, "acceptor")
|
||||
override fun hasTileEntity(state: BlockState): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
components.entity = IBlockEntityComponent(::TileEntityEndPortalAcceptor)
|
||||
override fun createTileEntity(state: BlockState, world: IBlockReader): TileEntity {
|
||||
return TileEntityEndPortalAcceptor()
|
||||
}
|
||||
|
||||
components.onAdded = IBlockAddedComponent { _, world, pos ->
|
||||
override fun onBlockAdded(state: BlockState, world: World, pos: BlockPos, oldState: BlockState, isMoving: Boolean) {
|
||||
BlockAbstractPortal.spawnInnerBlocks(world, pos, ModBlocks.END_PORTAL_FRAME, ModBlocks.END_PORTAL_INNER, minSize = 1)
|
||||
}
|
||||
|
||||
components.setStateFromNeighbor = ISetBlockStateFromNeighbor { state, world, pos, neighborFacing, _ ->
|
||||
if (!world.isRemote && neighborFacing == UP) {
|
||||
pos.getTile<TileEntityEndPortalAcceptor>(world)?.refreshClusterState()
|
||||
} // TODO neighbor changed?
|
||||
|
||||
state
|
||||
}
|
||||
|
||||
components.playerUse = object : IPlayerUseBlockComponent {
|
||||
override fun use(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand): ActionResultType {
|
||||
override fun onBlockActivated(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hit: BlockRayTraceResult): ActionResultType {
|
||||
if (player.isCreative && player.isSneaking) {
|
||||
pos.getTile<TileEntityEndPortalAcceptor>(world)?.toggleChargeFromCreativeMode()
|
||||
return SUCCESS
|
||||
@@ -48,6 +44,13 @@ object BlockEndPortalAcceptor : HeeBlockBuilder() {
|
||||
|
||||
return PASS
|
||||
}
|
||||
}
|
||||
|
||||
override fun updatePostPlacement(state: BlockState, facing: Direction, neighborState: BlockState, world: IWorld, pos: BlockPos, neighborPos: BlockPos): BlockState {
|
||||
if (!world.isRemote && facing == UP) {
|
||||
pos.getTile<TileEntityEndPortalAcceptor>(world)?.refreshClusterState()
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
return super.updatePostPlacement(state, facing, neighborState, world, pos, neighborPos)
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,10 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.HEE
|
||||
import chylex.hee.game.block.BlockAbstractPortal.IInnerPortalBlock
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.entity.TileEntityEndPortalAcceptor
|
||||
import chylex.hee.game.block.entity.TileEntityPortalInner
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.entity.util.EntityPortalContact
|
||||
import chylex.hee.game.mechanics.causatum.CausatumStage
|
||||
import chylex.hee.game.mechanics.causatum.EnderCausatum
|
||||
import chylex.hee.game.world.isEndDimension
|
||||
@@ -12,28 +12,32 @@ import chylex.hee.game.world.server.DimensionTeleporter
|
||||
import chylex.hee.game.world.util.closestTickingTile
|
||||
import chylex.hee.init.ModBlocks
|
||||
import chylex.hee.util.math.Pos
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.IBlockReader
|
||||
import net.minecraft.world.World
|
||||
|
||||
object BlockEndPortalInner : HeeBlockBuilder() {
|
||||
init {
|
||||
includeFrom(BlockAbstractPortal(object : IInnerPortalBlock {
|
||||
override fun createTileEntity(): TileEntity {
|
||||
class BlockEndPortalInner(builder: BlockBuilder) : BlockAbstractPortal(builder) {
|
||||
override fun createTileEntity(state: BlockState, world: IBlockReader): TileEntity {
|
||||
return TileEntityPortalInner.End()
|
||||
}
|
||||
|
||||
override fun teleportEntity(world: World, pos: BlockPos, entity: Entity) {
|
||||
override fun onEntityInside(world: World, pos: BlockPos, entity: Entity) {
|
||||
if (!EntityPortalContact.shouldTeleport(entity)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (world.isEndDimension) {
|
||||
DimensionTeleporter.changeDimension(entity, World.OVERWORLD, DimensionTeleporter.LastEndPortal)
|
||||
}
|
||||
else {
|
||||
val acceptor = pos.closestTickingTile<TileEntityEndPortalAcceptor>(world, BlockAbstractPortal.MAX_DISTANCE_FROM_FRAME)
|
||||
val acceptor = pos.closestTickingTile<TileEntityEndPortalAcceptor>(world, MAX_DISTANCE_FROM_FRAME)
|
||||
|
||||
if (acceptor != null && acceptor.isCharged) {
|
||||
BlockAbstractPortal.findInnerArea(world, acceptor.pos, ModBlocks.END_PORTAL_FRAME)?.let { (min, max) ->
|
||||
findInnerArea(world, acceptor.pos, ModBlocks.END_PORTAL_FRAME)?.let { (min, max) ->
|
||||
DimensionTeleporter.LastEndPortal.updateForEntity(entity, Pos((min.x + max.x) / 2, pos.y, (min.z + max.z) / 2))
|
||||
}
|
||||
|
||||
@@ -45,6 +49,4 @@ object BlockEndPortalInner : HeeBlockBuilder() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
@@ -1,23 +1,22 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.components.IBlockExperienceComponent
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockDrop
|
||||
import chylex.hee.game.block.properties.BlockHardness
|
||||
import chylex.hee.game.block.properties.BlockHarvestTool
|
||||
import chylex.hee.game.item.util.Tool.Level.STONE
|
||||
import chylex.hee.util.random.nextInt
|
||||
import net.minecraftforge.common.ToolType.PICKAXE
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.IWorldReader
|
||||
import net.minecraft.world.World
|
||||
import net.minecraftforge.common.Tags
|
||||
|
||||
object BlockEndPowderOre : HeeBlockBuilder() {
|
||||
init {
|
||||
includeFrom(BlockEndOre)
|
||||
class BlockEndPowderOre(builder: BlockBuilder) : HeeBlock(builder) {
|
||||
override val drop
|
||||
get() = BlockDrop.Manual
|
||||
|
||||
drop = BlockDrop.Manual
|
||||
override val tags
|
||||
get() = listOf(Tags.Blocks.ORES)
|
||||
|
||||
tool = BlockHarvestTool.required(STONE, PICKAXE)
|
||||
hardness = BlockHardness(hardness = 2F, resistance = 5.4F)
|
||||
|
||||
components.experience = IBlockExperienceComponent { rand -> rand.nextInt(1, 2) }
|
||||
override fun getExpDrop(state: BlockState, world: IWorldReader, pos: BlockPos, fortune: Int, silktouch: Int): Int {
|
||||
return ((world as? World)?.rand ?: RANDOM).nextInt(1, 2)
|
||||
}
|
||||
}
|
||||
|
@@ -2,48 +2,22 @@ package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.client.text.LocalizationStrategy
|
||||
import chylex.hee.game.Resource.location
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockHardness
|
||||
import chylex.hee.game.block.properties.BlockHarvestTool
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockModel
|
||||
import chylex.hee.game.block.properties.IBlockStateModelSupplier
|
||||
import chylex.hee.game.item.util.Tool.Level.WOOD
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.block.material.MaterialColor
|
||||
import net.minecraftforge.common.Tags
|
||||
import net.minecraftforge.common.ToolType.PICKAXE
|
||||
|
||||
object BlockEndStoneCustom : HeeBlockBuilder() {
|
||||
init {
|
||||
includeFrom(BlockEndStoneBase)
|
||||
class BlockEndStoneCustom(builder: BlockBuilder, mapColor: MaterialColor) : HeeBlock(builder.clone { color = mapColor }) {
|
||||
override val localization
|
||||
get() = LocalizationStrategy.MoveToBeginning(wordCount = 1)
|
||||
|
||||
localization = LocalizationStrategy.MoveToBeginning(wordCount = 1)
|
||||
|
||||
model = IBlockStateModelSupplier {
|
||||
BlockModel.WithTextures(
|
||||
override val model
|
||||
get() = BlockModel.WithTextures(
|
||||
BlockModel.CubeBottomTop(bottom = Blocks.END_STONE.location),
|
||||
mapOf("particle" to it.location("_top"))
|
||||
mapOf("particle" to this.location("_top"))
|
||||
)
|
||||
}
|
||||
|
||||
tags.add(Tags.Blocks.END_STONES)
|
||||
|
||||
tool = BlockHarvestTool.required(WOOD, PICKAXE)
|
||||
hardness = BlockHardness(hardness = 3F, resistance = 9F)
|
||||
}
|
||||
|
||||
val INFESTED = HeeBlockBuilder {
|
||||
includeFrom(BlockEndStoneCustom)
|
||||
color = MaterialColor.RED
|
||||
}
|
||||
|
||||
val BURNED = HeeBlockBuilder {
|
||||
includeFrom(BlockEndStoneCustom)
|
||||
color = MaterialColor.ADOBE // RENAME ORANGE
|
||||
}
|
||||
|
||||
val ENCHANTED = HeeBlockBuilder {
|
||||
includeFrom(BlockEndStoneCustom)
|
||||
color = MaterialColor.PURPLE
|
||||
}
|
||||
override val tags
|
||||
get() = listOf(Tags.Blocks.END_STONES)
|
||||
}
|
||||
|
@@ -1,48 +1,26 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.components.IBlockHarvestabilityComponent
|
||||
import chylex.hee.game.block.properties.BlockHardness
|
||||
import chylex.hee.game.block.properties.BlockHarvestTool
|
||||
import chylex.hee.game.block.properties.Materials
|
||||
import chylex.hee.game.item.util.Tool.Level.IRON
|
||||
import chylex.hee.util.forge.EventResult
|
||||
import net.minecraft.block.SoundType
|
||||
import net.minecraft.block.material.MaterialColor
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.item.Items
|
||||
import net.minecraft.util.Hand.MAIN_HAND
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.IBlockReader
|
||||
import net.minecraftforge.common.Tags
|
||||
import net.minecraftforge.common.ToolType.PICKAXE
|
||||
|
||||
abstract class BlockEndium : HeeBlockBuilder() {
|
||||
init {
|
||||
material = Materials.SOLID
|
||||
tool = BlockHarvestTool.required(IRON, PICKAXE)
|
||||
|
||||
components.harvestability = IBlockHarvestabilityComponent {
|
||||
if (it.getHeldItem(MAIN_HAND).item === Items.GOLDEN_PICKAXE)
|
||||
EventResult.ALLOW
|
||||
else
|
||||
EventResult.DEFAULT
|
||||
}
|
||||
sealed class BlockEndium(builder: BlockBuilder) : HeeBlock(builder) {
|
||||
override fun canHarvestBlock(state: BlockState, world: IBlockReader, pos: BlockPos, player: PlayerEntity): Boolean {
|
||||
return super.canHarvestBlock(state, world, pos, player) || player.getHeldItem(MAIN_HAND).item === Items.GOLDEN_PICKAXE
|
||||
}
|
||||
|
||||
object Ore : BlockEndium() {
|
||||
init {
|
||||
includeFrom(BlockEndOre)
|
||||
|
||||
hardness = BlockHardness(hardness = 5F, resistance = 9.9F)
|
||||
}
|
||||
class Ore(builder: BlockBuilder) : BlockEndium(builder) {
|
||||
override val tags
|
||||
get() = listOf(Tags.Blocks.ORES)
|
||||
}
|
||||
|
||||
object Block : BlockEndium() {
|
||||
init {
|
||||
color = MaterialColor.LAPIS
|
||||
sound = SoundType.METAL
|
||||
|
||||
tags.add(Tags.Blocks.STORAGE_BLOCKS)
|
||||
|
||||
hardness = BlockHardness(hardness = 6.2F, resistance = 12F)
|
||||
}
|
||||
class Block(builder: BlockBuilder) : BlockEndium(builder) {
|
||||
override val tags
|
||||
get() = listOf(Tags.Blocks.STORAGE_BLOCKS)
|
||||
}
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@ import chylex.hee.game.mechanics.instability.Instability
|
||||
import chylex.hee.game.world.util.allInCenteredSphereMutable
|
||||
import chylex.hee.game.world.util.getTile
|
||||
import chylex.hee.game.world.util.removeBlock
|
||||
import chylex.hee.init.ModBlocks
|
||||
import chylex.hee.init.ModItems
|
||||
import chylex.hee.util.forge.Side
|
||||
import chylex.hee.util.forge.Sided
|
||||
@@ -42,7 +43,7 @@ class BlockEnergyCluster(builder: BlockBuilder) : BlockSimpleShaped(builder, Axi
|
||||
val units = amount.units.value.toFloat()
|
||||
val corruptedEnergyLevel = (2F + (units.pow(0.74F) / 9F)).ceilToInt()
|
||||
|
||||
BlockCorruptedEnergy.spawn(world, pos, corruptedEnergyLevel)
|
||||
ModBlocks.CORRUPTED_ENERGY.spawnCorruptedEnergy(world, pos, corruptedEnergyLevel)
|
||||
|
||||
if (causeInstability) {
|
||||
Instability.get(world).triggerAction((10 + 2 * corruptedEnergyLevel).toUShort(), pos)
|
||||
@@ -56,7 +57,7 @@ class BlockEnergyCluster(builder: BlockBuilder) : BlockSimpleShaped(builder, Axi
|
||||
val corruptedEnergyLevel = (2F + (units.pow(0.74F) / 9F)).ceilToInt()
|
||||
|
||||
for (testPos in pos.allInCenteredSphereMutable(corruptedEnergyRadius)) {
|
||||
BlockCorruptedEnergy.spawn(world, testPos, corruptedEnergyLevel)
|
||||
ModBlocks.CORRUPTED_ENERGY.spawnCorruptedEnergy(world, testPos, corruptedEnergyLevel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,46 +1,25 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.HEE
|
||||
import chylex.hee.client.text.LocalizationStrategy
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.components.ICreatureSpawningOnBlockComponent
|
||||
import chylex.hee.game.block.properties.BlockHardness
|
||||
import chylex.hee.game.block.properties.BlockHarvestTool
|
||||
import chylex.hee.game.block.properties.Materials
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.entity.technical.EntityTechnicalTrigger
|
||||
import chylex.hee.game.entity.technical.EntityTechnicalTrigger.Types.ENERGY_SHRINE_GLOBAL
|
||||
import chylex.hee.game.entity.util.posVec
|
||||
import chylex.hee.game.entity.util.selectEntities
|
||||
import chylex.hee.game.item.util.Tool.Level.WOOD
|
||||
import chylex.hee.game.item.util.Tool.Type.PICKAXE
|
||||
import chylex.hee.game.world.generation.feature.energyshrine.EnergyShrinePieces
|
||||
import chylex.hee.init.ModTags
|
||||
import chylex.hee.util.forge.EventResult
|
||||
import chylex.hee.util.math.center
|
||||
import net.minecraft.block.SoundType
|
||||
import net.minecraft.block.material.MaterialColor
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.entity.EntitySpawnPlacementRegistry.PlacementType
|
||||
import net.minecraft.entity.EntityType
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.IBlockReader
|
||||
import net.minecraft.world.IEntityReader
|
||||
|
||||
object BlockGloomrock : HeeBlockBuilder() {
|
||||
init {
|
||||
material = Materials.SOLID
|
||||
color = MaterialColor.BLACK
|
||||
sound = SoundType.STONE
|
||||
|
||||
tool = BlockHarvestTool.required(WOOD, PICKAXE)
|
||||
hardness = BlockHardness(hardness = 1.6F, resistance = 4.2F)
|
||||
|
||||
tags.add(ModTags.GLOOMROCK_PARTICLES)
|
||||
|
||||
components.onCreatureSpawning = object : ICreatureSpawningOnBlockComponent {
|
||||
override fun canSpawn(world: IBlockReader, pos: BlockPos, placementType: PlacementType?, entityType: EntityType<*>?): EventResult {
|
||||
open class BlockGloomrock(builder: BlockBuilder) : HeeBlock(builder) {
|
||||
override fun canCreatureSpawn(state: BlockState, world: IBlockReader, pos: BlockPos, type: PlacementType?, entityType: EntityType<*>?): Boolean {
|
||||
if (world !is IEntityReader) {
|
||||
HEE.log.warn("[BlockGloomrock] attempted to check spawn on a world != IEntityReader (${world.javaClass})")
|
||||
return EventResult.DENY
|
||||
return false
|
||||
}
|
||||
|
||||
val center = pos.center
|
||||
@@ -51,24 +30,6 @@ object BlockGloomrock : HeeBlockBuilder() {
|
||||
.inBox<EntityTechnicalTrigger>(size.toCenteredBoundingBox(center))
|
||||
.find { it.triggerType == ENERGY_SHRINE_GLOBAL }
|
||||
|
||||
return EventResult(trigger == null || !size.toCenteredBoundingBox(trigger.posVec).contains(center))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val BRICKS = HeeBlockBuilder {
|
||||
includeFrom(BlockGloomrock)
|
||||
hardness = BlockHardness(hardness = 2.8F, resistance = 6F)
|
||||
}
|
||||
|
||||
val SMOOTH = HeeBlockBuilder {
|
||||
includeFrom(BlockGloomrock)
|
||||
localization = LocalizationStrategy.MoveToBeginning(wordCount = 1)
|
||||
hardness = BlockHardness(hardness = 2F, resistance = 4.8F)
|
||||
}
|
||||
|
||||
val SMOOTH_COLORED = HeeBlockBuilder {
|
||||
includeFrom(SMOOTH)
|
||||
localization = LocalizationStrategy.MoveToBeginning(LocalizationStrategy.DeleteWords("Smooth"), wordCount = 1)
|
||||
return trigger == null || !size.toCenteredBoundingBox(trigger.posVec).contains(center)
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,9 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.client.text.LocalizationStrategy
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
|
||||
class BlockGloomrockSmooth(builder: BlockBuilder) : BlockGloomrock(builder) {
|
||||
override val localization
|
||||
get() = LocalizationStrategy.MoveToBeginning(wordCount = 1)
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.client.text.LocalizationStrategy
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
|
||||
class BlockGloomrockSmoothColored(builder: BlockBuilder) : BlockGloomrock(builder) {
|
||||
override val localization
|
||||
get() = LocalizationStrategy.MoveToBeginning(LocalizationStrategy.DeleteWords("Smooth"), wordCount = 1)
|
||||
}
|
@@ -1,37 +1,31 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.game.Resource.location
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.components.IBlockAddedComponent
|
||||
import chylex.hee.game.block.components.IBlockEntityComponent
|
||||
import chylex.hee.game.block.components.IBlockPlacementComponent
|
||||
import chylex.hee.game.block.components.IBlockShapeComponent
|
||||
import chylex.hee.game.block.components.IPlayerUseBlockComponent
|
||||
import chylex.hee.game.block.components.ISetBlockStateFromNeighbor
|
||||
import chylex.hee.game.block.entity.TileEntityIgneousPlate
|
||||
import chylex.hee.game.block.logic.IBlockDynamicHardness
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockModel
|
||||
import chylex.hee.game.block.properties.BlockStateModel
|
||||
import chylex.hee.game.block.properties.BlockStatePreset
|
||||
import chylex.hee.game.block.properties.IBlockStateModelSupplier
|
||||
import chylex.hee.game.block.properties.Materials
|
||||
import chylex.hee.game.block.util.FURNACE_FACING
|
||||
import chylex.hee.game.block.util.Property
|
||||
import chylex.hee.game.block.util.asVoxelShape
|
||||
import chylex.hee.game.entity.technical.EntityTechnicalIgneousPlateLogic
|
||||
import chylex.hee.game.item.properties.ItemModel
|
||||
import chylex.hee.game.world.util.Facing6
|
||||
import chylex.hee.game.world.util.getState
|
||||
import chylex.hee.game.world.util.getTile
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockRenderType.ENTITYBLOCK_ANIMATED
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.block.SoundType
|
||||
import net.minecraft.block.material.MaterialColor
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.item.BlockItemUseContext
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.item.Items
|
||||
import net.minecraft.state.StateContainer.Builder
|
||||
import net.minecraft.tileentity.FurnaceTileEntity
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.util.ActionResultType
|
||||
import net.minecraft.util.ActionResultType.PASS
|
||||
import net.minecraft.util.ActionResultType.SUCCESS
|
||||
@@ -43,14 +37,20 @@ import net.minecraft.util.Direction.SOUTH
|
||||
import net.minecraft.util.Direction.UP
|
||||
import net.minecraft.util.Direction.WEST
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.Mirror
|
||||
import net.minecraft.util.Rotation
|
||||
import net.minecraft.util.math.AxisAlignedBB
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.BlockRayTraceResult
|
||||
import net.minecraft.util.math.shapes.ISelectionContext
|
||||
import net.minecraft.util.math.shapes.VoxelShape
|
||||
import net.minecraft.util.math.shapes.VoxelShapes
|
||||
import net.minecraft.world.IBlockReader
|
||||
import net.minecraft.world.IWorld
|
||||
import net.minecraft.world.IWorldReader
|
||||
import net.minecraft.world.World
|
||||
|
||||
object BlockIgneousPlate : HeeBlockBuilder() {
|
||||
class BlockIgneousPlate(builder: BlockBuilder) : HeeBlock(builder), IBlockDynamicHardness {
|
||||
companion object {
|
||||
val FACING_NOT_DOWN = Property.facing("facing", Facing6.minusElement(DOWN))
|
||||
|
||||
private const val BB_SIDE_MIN = 0.125
|
||||
@@ -58,91 +58,13 @@ object BlockIgneousPlate : HeeBlockBuilder() {
|
||||
private const val BB_TOP = 0.125
|
||||
|
||||
private val BOUNDING_BOX = mapOf(
|
||||
UP to VoxelShapes.create(BB_SIDE_MIN, 0.0, BB_SIDE_MIN, BB_SIDE_MAX, BB_TOP, BB_SIDE_MAX),
|
||||
NORTH to VoxelShapes.create(BB_SIDE_MIN, BB_SIDE_MIN, 1.0 - BB_TOP, BB_SIDE_MAX, BB_SIDE_MAX, 1.0),
|
||||
SOUTH to VoxelShapes.create(BB_SIDE_MIN, BB_SIDE_MIN, 0.0, BB_SIDE_MAX, BB_SIDE_MAX, BB_TOP),
|
||||
EAST to VoxelShapes.create(0.0, BB_SIDE_MIN, BB_SIDE_MIN, BB_TOP, BB_SIDE_MAX, BB_SIDE_MAX),
|
||||
WEST to VoxelShapes.create(1.0 - BB_TOP, BB_SIDE_MIN, BB_SIDE_MIN, 1.0, BB_SIDE_MAX, BB_SIDE_MAX)
|
||||
UP to AxisAlignedBB(BB_SIDE_MIN, 0.0, BB_SIDE_MIN, BB_SIDE_MAX, BB_TOP, BB_SIDE_MAX).asVoxelShape,
|
||||
NORTH to AxisAlignedBB(BB_SIDE_MIN, BB_SIDE_MIN, 1.0 - BB_TOP, BB_SIDE_MAX, BB_SIDE_MAX, 1.0).asVoxelShape,
|
||||
SOUTH to AxisAlignedBB(BB_SIDE_MIN, BB_SIDE_MIN, 0.0, BB_SIDE_MAX, BB_SIDE_MAX, BB_TOP).asVoxelShape,
|
||||
EAST to AxisAlignedBB(0.0, BB_SIDE_MIN, BB_SIDE_MIN, BB_TOP, BB_SIDE_MAX, BB_SIDE_MAX).asVoxelShape,
|
||||
WEST to AxisAlignedBB(1.0 - BB_TOP, BB_SIDE_MIN, BB_SIDE_MIN, 1.0, BB_SIDE_MAX, BB_SIDE_MAX).asVoxelShape
|
||||
)
|
||||
|
||||
init {
|
||||
model = IBlockStateModelSupplier {
|
||||
BlockStateModel(BlockStatePreset.Simple, BlockModel.ParticleOnly(it.location), ItemModel.Simple)
|
||||
}
|
||||
|
||||
material = Materials.IGNEOUS_ROCK_PLATE
|
||||
color = MaterialColor.AIR
|
||||
sound = SoundType.STONE
|
||||
|
||||
components.states.set(FACING_NOT_DOWN, default = UP)
|
||||
components.states.facingProperty = FACING_NOT_DOWN
|
||||
|
||||
components.shape = object : IBlockShapeComponent {
|
||||
override fun getShape(state: BlockState): VoxelShape {
|
||||
return BOUNDING_BOX[state[FACING_NOT_DOWN]] ?: BOUNDING_BOX.getValue(UP)
|
||||
}
|
||||
}
|
||||
|
||||
components.renderType = ENTITYBLOCK_ANIMATED
|
||||
|
||||
components.entity = IBlockEntityComponent(::TileEntityIgneousPlate)
|
||||
|
||||
components.placement = object : IBlockPlacementComponent {
|
||||
override fun isPositionValid(state: BlockState, world: IWorldReader, pos: BlockPos): Boolean {
|
||||
return FACING_NOT_DOWN.allowedValues.any { canPlacePlateAt(world, pos, it) }
|
||||
}
|
||||
|
||||
override fun getPlacedState(defaultState: BlockState, world: World, pos: BlockPos, context: BlockItemUseContext): BlockState {
|
||||
return if (canPlacePlateAt(world, pos, context.face))
|
||||
defaultState.with(FACING_NOT_DOWN, context.face)
|
||||
else
|
||||
FACING_NOT_DOWN.allowedValues.firstOrNull { canPlacePlateAt(world, pos, it) }?.let { defaultState.with(FACING_NOT_DOWN, it) } ?: defaultState
|
||||
}
|
||||
}
|
||||
|
||||
components.onAdded = IBlockAddedComponent { state, world, pos ->
|
||||
pos.offset(state[FACING_NOT_DOWN].opposite).getTile<FurnaceTileEntity>(world)?.let(EntityTechnicalIgneousPlateLogic.Companion::createForFurnace)
|
||||
}
|
||||
|
||||
components.setStateFromNeighbor = ISetBlockStateFromNeighbor { state, world, pos, _, _ ->
|
||||
if (!canPlacePlateAt(world, pos, state[FACING_NOT_DOWN]))
|
||||
Blocks.AIR.defaultState
|
||||
else
|
||||
state
|
||||
}
|
||||
|
||||
components.playerUse = object : IPlayerUseBlockComponent {
|
||||
override fun use(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand): ActionResultType {
|
||||
val heldItem = player.getHeldItem(hand)
|
||||
if (heldItem.item !== Items.WATER_BUCKET) {
|
||||
return PASS
|
||||
}
|
||||
|
||||
if (!world.isRemote && tryCoolPlate(world, pos, state) && !player.abilities.isCreativeMode) {
|
||||
player.setHeldItem(hand, ItemStack(Items.BUCKET))
|
||||
}
|
||||
|
||||
return SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
interfaces[IBlockDynamicHardness::class.java] = object : IBlockDynamicHardness {
|
||||
override fun getBlockHardness(world: IBlockReader, pos: BlockPos, state: BlockState, originalHardness: Float): Float {
|
||||
val tile = pos.getTile<TileEntityIgneousPlate>(world) ?: return 0F
|
||||
|
||||
return when {
|
||||
tile.isOverheating -> 10F
|
||||
tile.isWorking -> 4F
|
||||
else -> 0F
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun tryCoolPlate(world: World, pos: BlockPos, state: BlockState): Boolean {
|
||||
return pos.offset(state[FACING_NOT_DOWN].opposite).getTile<FurnaceTileEntity>(world)?.let(EntityTechnicalIgneousPlateLogic.Companion::triggerCooling) == true
|
||||
}
|
||||
|
||||
private fun canPlacePlateAt(world: IWorldReader, pos: BlockPos, facing: Direction): Boolean {
|
||||
val furnacePos = pos.offset(facing.opposite)
|
||||
val state = furnacePos.getState(world)
|
||||
@@ -154,3 +76,100 @@ object BlockIgneousPlate : HeeBlockBuilder() {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override val model
|
||||
get() = BlockStateModel(BlockStatePreset.Simple, BlockModel.ParticleOnly(this.location), ItemModel.Simple)
|
||||
|
||||
init {
|
||||
defaultState = stateContainer.baseState.with(FACING_NOT_DOWN, UP)
|
||||
}
|
||||
|
||||
override fun fillStateContainer(container: Builder<Block, BlockState>) {
|
||||
container.add(FACING_NOT_DOWN)
|
||||
}
|
||||
|
||||
override fun hasTileEntity(state: BlockState): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun createTileEntity(state: BlockState, world: IBlockReader): TileEntity {
|
||||
return TileEntityIgneousPlate()
|
||||
}
|
||||
|
||||
// Placement rules
|
||||
|
||||
override fun isValidPosition(state: BlockState, world: IWorldReader, pos: BlockPos): Boolean {
|
||||
return FACING_NOT_DOWN.allowedValues.any { canPlacePlateAt(world, pos, it) }
|
||||
}
|
||||
|
||||
override fun getStateForPlacement(context: BlockItemUseContext): BlockState {
|
||||
val world = context.world
|
||||
val pos = context.pos
|
||||
val facing = context.face
|
||||
|
||||
return if (canPlacePlateAt(world, pos, facing))
|
||||
defaultState.with(FACING_NOT_DOWN, facing)
|
||||
else
|
||||
FACING_NOT_DOWN.allowedValues.firstOrNull { canPlacePlateAt(world, pos, it) }?.let { defaultState.with(FACING_NOT_DOWN, it) } ?: defaultState
|
||||
}
|
||||
|
||||
override fun onBlockAdded(state: BlockState, world: World, pos: BlockPos, oldState: BlockState, isMoving: Boolean) {
|
||||
pos.offset(state[FACING_NOT_DOWN].opposite).getTile<FurnaceTileEntity>(world)?.let(EntityTechnicalIgneousPlateLogic.Companion::createForFurnace)
|
||||
}
|
||||
|
||||
override fun updatePostPlacement(state: BlockState, facing: Direction, neighborState: BlockState, world: IWorld, pos: BlockPos, neighborPos: BlockPos): BlockState {
|
||||
@Suppress("DEPRECATION")
|
||||
return if (!canPlacePlateAt(world, pos, state[FACING_NOT_DOWN]))
|
||||
Blocks.AIR.defaultState
|
||||
else
|
||||
super.updatePostPlacement(state, facing, neighborState, world, pos, neighborPos)
|
||||
}
|
||||
|
||||
// Interactions
|
||||
|
||||
override fun getBlockHardness(world: IBlockReader, pos: BlockPos, state: BlockState, originalHardness: Float): Float {
|
||||
val tile = pos.getTile<TileEntityIgneousPlate>(world) ?: return 0F
|
||||
|
||||
return when {
|
||||
tile.isOverheating -> 10F
|
||||
tile.isWorking -> 4F
|
||||
else -> 0F
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBlockActivated(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hit: BlockRayTraceResult): ActionResultType {
|
||||
val heldItem = player.getHeldItem(hand)
|
||||
|
||||
if (heldItem.item === Items.WATER_BUCKET) {
|
||||
if (!world.isRemote && tryCoolPlate(world, pos, state) && !player.abilities.isCreativeMode) {
|
||||
player.setHeldItem(hand, ItemStack(Items.BUCKET))
|
||||
}
|
||||
|
||||
return SUCCESS
|
||||
}
|
||||
|
||||
return PASS
|
||||
}
|
||||
|
||||
fun tryCoolPlate(world: World, pos: BlockPos, state: BlockState): Boolean {
|
||||
return pos.offset(state[FACING_NOT_DOWN].opposite).getTile<FurnaceTileEntity>(world)?.let(EntityTechnicalIgneousPlateLogic.Companion::triggerCooling) == true
|
||||
}
|
||||
|
||||
// State handling
|
||||
|
||||
override fun rotate(state: BlockState, rot: Rotation): BlockState {
|
||||
return state.with(FACING_NOT_DOWN, rot.rotate(state[FACING_NOT_DOWN]))
|
||||
}
|
||||
|
||||
override fun mirror(state: BlockState, mirror: Mirror): BlockState {
|
||||
return state.with(FACING_NOT_DOWN, mirror.mirror(state[FACING_NOT_DOWN]))
|
||||
}
|
||||
|
||||
// Rendering
|
||||
|
||||
override fun getShape(state: BlockState, world: IBlockReader, pos: BlockPos, context: ISelectionContext): VoxelShape {
|
||||
return BOUNDING_BOX[state[FACING_NOT_DOWN]] ?: BOUNDING_BOX.getValue(UP)
|
||||
}
|
||||
|
||||
override fun getRenderType(state: BlockState) = ENTITYBLOCK_ANIMATED
|
||||
}
|
||||
|
@@ -1,24 +1,14 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.client.text.LocalizationStrategy
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.components.IBlockDropsComponent
|
||||
import chylex.hee.game.block.components.IBlockEntityComponent
|
||||
import chylex.hee.game.block.components.IBlockExplodedComponent
|
||||
import chylex.hee.game.block.components.IBlockPlacementComponent
|
||||
import chylex.hee.game.block.components.IBlockShapeComponent
|
||||
import chylex.hee.game.block.components.IPlayerUseBlockComponent
|
||||
import chylex.hee.game.block.components.ISetBlockStateFromNeighbor
|
||||
import chylex.hee.game.block.entity.TileEntityJarODust
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockDrop
|
||||
import chylex.hee.game.block.properties.BlockHardness
|
||||
import chylex.hee.game.block.properties.BlockModel
|
||||
import chylex.hee.game.block.properties.BlockRenderLayer.TRANSLUCENT
|
||||
import chylex.hee.game.block.properties.BlockStateModel
|
||||
import chylex.hee.game.block.properties.BlockStatePreset
|
||||
import chylex.hee.game.block.properties.Materials
|
||||
import chylex.hee.game.fx.util.playServer
|
||||
import chylex.hee.game.item.components.ITooltipComponent
|
||||
import chylex.hee.game.item.util.size
|
||||
import chylex.hee.game.mechanics.dust.DustLayers
|
||||
import chylex.hee.game.mechanics.dust.DustLayers.Side.BOTTOM
|
||||
@@ -26,107 +16,147 @@ import chylex.hee.game.mechanics.dust.DustLayers.Side.TOP
|
||||
import chylex.hee.game.mechanics.dust.DustType
|
||||
import chylex.hee.game.world.util.getTile
|
||||
import chylex.hee.game.world.util.isTopSolid
|
||||
import chylex.hee.init.ModBlocks
|
||||
import chylex.hee.init.ModSounds
|
||||
import chylex.hee.system.heeTag
|
||||
import chylex.hee.system.heeTagOrNull
|
||||
import chylex.hee.util.forge.Side
|
||||
import chylex.hee.util.forge.Sided
|
||||
import chylex.hee.util.math.center
|
||||
import chylex.hee.util.nbt.getListOfCompounds
|
||||
import chylex.hee.util.nbt.putList
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.block.SoundType
|
||||
import net.minecraft.block.material.MaterialColor
|
||||
import net.minecraft.client.util.ITooltipFlag
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.loot.LootContext.Builder
|
||||
import net.minecraft.loot.LootContext
|
||||
import net.minecraft.loot.LootParameters
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.util.ActionResultType
|
||||
import net.minecraft.util.ActionResultType.PASS
|
||||
import net.minecraft.util.ActionResultType.SUCCESS
|
||||
import net.minecraft.util.Direction
|
||||
import net.minecraft.util.Direction.DOWN
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.SoundCategory
|
||||
import net.minecraft.util.math.AxisAlignedBB
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.shapes.VoxelShapes
|
||||
import net.minecraft.util.math.BlockRayTraceResult
|
||||
import net.minecraft.util.math.RayTraceResult
|
||||
import net.minecraft.util.text.ITextComponent
|
||||
import net.minecraft.util.text.TranslationTextComponent
|
||||
import net.minecraft.world.Explosion
|
||||
import net.minecraft.world.IBlockReader
|
||||
import net.minecraft.world.IWorld
|
||||
import net.minecraft.world.IWorldReader
|
||||
import net.minecraft.world.World
|
||||
|
||||
object BlockJarODust : HeeBlockBuilder() {
|
||||
init {
|
||||
localization = LocalizationStrategy.ReplaceWords("O", "o'")
|
||||
localizationExtra["block.hee.jar_o_dust.tooltip.entry"] = "§7%sx %s"
|
||||
|
||||
model = BlockStateModel(BlockStatePreset.Simple, BlockModel.Manual)
|
||||
renderLayer = TRANSLUCENT
|
||||
|
||||
material = Materials.JAR_O_DUST
|
||||
color = MaterialColor.ORANGE_TERRACOTTA
|
||||
sound = SoundType.METAL
|
||||
|
||||
drop = BlockDrop.Manual
|
||||
hardness = BlockHardness(hardness = 0.4F, resistance = 0F)
|
||||
|
||||
components.tooltip = object : ITooltipComponent {
|
||||
override fun add(lines: MutableList<ITextComponent>, stack: ItemStack, advanced: Boolean, world: IBlockReader?) {
|
||||
val contents = getLayersFromStack(stack)?.contents ?: return
|
||||
val entries = contents
|
||||
.groupingBy { it.first }
|
||||
.fold(0) { acc, entry -> acc + entry.second }
|
||||
.entries
|
||||
.sortedWith(compareBy({ -it.value }, { it.key.key }))
|
||||
|
||||
for ((dustType, dustAmount) in entries) {
|
||||
lines.add(TranslationTextComponent("block.hee.jar_o_dust.tooltip.entry", dustAmount, TranslationTextComponent(dustType.item.translationKey)))
|
||||
}
|
||||
}
|
||||
class BlockJarODust(builder: BlockBuilder) : BlockSimpleShaped(builder, AABB) {
|
||||
companion object {
|
||||
val AABB = AxisAlignedBB(0.1875, 0.0, 0.1875, 0.8125, 0.84375, 0.8125)
|
||||
}
|
||||
|
||||
components.shape = IBlockShapeComponent.of(VoxelShapes.create(0.1875, 0.0, 0.1875, 0.8125, 0.84375, 0.8125))
|
||||
override val localization
|
||||
get() = LocalizationStrategy.ReplaceWords("O", "o'")
|
||||
|
||||
components.drops = object : IBlockDropsComponent {
|
||||
override fun getDrops(state: BlockState, context: Builder): MutableList<ItemStack> {
|
||||
val drop = (context.get(LootParameters.BLOCK_ENTITY) as? TileEntityJarODust)?.let(::getDrop)
|
||||
override val localizationExtra
|
||||
get() = mapOf("block.hee.jar_o_dust.tooltip.entry" to "§7%sx %s")
|
||||
|
||||
return if (drop == null)
|
||||
mutableListOf()
|
||||
override val model
|
||||
get() = BlockStateModel(BlockStatePreset.Simple, BlockModel.Manual)
|
||||
|
||||
override val renderLayer
|
||||
get() = TRANSLUCENT
|
||||
|
||||
override val drop
|
||||
get() = BlockDrop.Manual
|
||||
|
||||
override fun hasTileEntity(state: BlockState): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun createTileEntity(state: BlockState, world: IBlockReader): TileEntity {
|
||||
return TileEntityJarODust()
|
||||
}
|
||||
|
||||
// ItemStack serialization
|
||||
|
||||
fun getLayersFromStack(stack: ItemStack): DustLayers? {
|
||||
return if (stack.item === this.asItem())
|
||||
stack.heeTagOrNull?.getListOfCompounds(TileEntityJarODust.LAYERS_TAG)?.let { list -> DustLayers(TileEntityJarODust.DUST_CAPACITY).apply { deserializeNBT(list) } }
|
||||
else
|
||||
mutableListOf(drop)
|
||||
null
|
||||
}
|
||||
|
||||
override fun getPickBlock(state: BlockState, world: IBlockReader, pos: BlockPos): ItemStack? {
|
||||
return pos.getTile<TileEntityJarODust>(world)?.let(::getDrop)
|
||||
fun setLayersInStack(stack: ItemStack, layers: DustLayers) {
|
||||
if (stack.item === this.asItem()) {
|
||||
stack.heeTag.putList(TileEntityJarODust.LAYERS_TAG, layers.serializeNBT())
|
||||
}
|
||||
}
|
||||
|
||||
components.entity = IBlockEntityComponent(::TileEntityJarODust)
|
||||
// Placement
|
||||
|
||||
components.placement = object : IBlockPlacementComponent {
|
||||
override fun isPositionValid(state: BlockState, world: IWorldReader, pos: BlockPos): Boolean {
|
||||
return pos.down().isTopSolid(world)
|
||||
override fun isValidPosition(state: BlockState, world: IWorldReader, pos: BlockPos): Boolean {
|
||||
@Suppress("DEPRECATION")
|
||||
return super.isValidPosition(state, world, pos) && pos.down().isTopSolid(world)
|
||||
}
|
||||
|
||||
override fun onPlacedBy(state: BlockState, world: World, pos: BlockPos, placer: LivingEntity?, stack: ItemStack) {
|
||||
override fun updatePostPlacement(state: BlockState, facing: Direction, neighborState: BlockState, world: IWorld, pos: BlockPos, neighborPos: BlockPos): BlockState {
|
||||
@Suppress("DEPRECATION")
|
||||
return if (facing == DOWN && !isValidPosition(state, world, pos))
|
||||
Blocks.AIR.defaultState
|
||||
else
|
||||
super.updatePostPlacement(state, facing, neighborState, world, pos, neighborPos)
|
||||
}
|
||||
|
||||
override fun onBlockPlacedBy(world: World, pos: BlockPos, state: BlockState, placer: LivingEntity?, stack: ItemStack) {
|
||||
val list = stack.heeTagOrNull?.getListOfCompounds(TileEntityJarODust.LAYERS_TAG)
|
||||
|
||||
if (list != null) {
|
||||
pos.getTile<TileEntityJarODust>(world)?.layers?.deserializeNBT(list)
|
||||
}
|
||||
}
|
||||
|
||||
// Drops
|
||||
|
||||
private fun getDrop(tile: TileEntityJarODust): ItemStack {
|
||||
return ItemStack(this).also { setLayersInStack(it, tile.layers) }
|
||||
}
|
||||
|
||||
components.setStateFromNeighbor = ISetBlockStateFromNeighbor { state, world, pos, neighborFacing, _ ->
|
||||
if (neighborFacing == DOWN && !state.isValidPosition(world, pos))
|
||||
Blocks.AIR.defaultState
|
||||
override fun getDrops(state: BlockState, context: LootContext.Builder): MutableList<ItemStack> {
|
||||
val drop = (context.get(LootParameters.BLOCK_ENTITY) as? TileEntityJarODust)?.let(::getDrop)
|
||||
|
||||
return if (drop != null)
|
||||
mutableListOf(drop)
|
||||
else
|
||||
state
|
||||
mutableListOf()
|
||||
}
|
||||
|
||||
components.playerUse = IPlayerUseBlockComponent { _, world, pos, player, hand ->
|
||||
override fun getPickBlock(state: BlockState, target: RayTraceResult, world: IBlockReader, pos: BlockPos, player: PlayerEntity): ItemStack {
|
||||
return pos.getTile<TileEntityJarODust>(world)?.let(::getDrop) ?: ItemStack(this)
|
||||
}
|
||||
|
||||
override fun canDropFromExplosion(explosion: Explosion): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onBlockExploded(state: BlockState, world: World, pos: BlockPos, explosion: Explosion) {
|
||||
pos.getTile<TileEntityJarODust>(world)?.let {
|
||||
val layers = it.layers
|
||||
|
||||
repeat(layers.contents.size) {
|
||||
spawnAsEntity(world, pos, layers.removeDust(BOTTOM))
|
||||
}
|
||||
}
|
||||
|
||||
ModSounds.BLOCK_JAR_O_DUST_SHATTER.playServer(world, pos.center, SoundCategory.BLOCKS)
|
||||
super.onBlockExploded(state, world, pos, explosion)
|
||||
}
|
||||
|
||||
// Interaction
|
||||
|
||||
override fun onBlockActivated(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hit: BlockRayTraceResult): ActionResultType {
|
||||
val heldItem = player.getHeldItem(hand)
|
||||
|
||||
val result = if (heldItem.isEmpty)
|
||||
@@ -134,57 +164,16 @@ object BlockJarODust : HeeBlockBuilder() {
|
||||
else
|
||||
tryInsertDust(world, pos, player, heldItem)
|
||||
|
||||
if (result) SUCCESS else PASS
|
||||
return if (result) SUCCESS else PASS
|
||||
}
|
||||
|
||||
components.onExploded = object : IBlockExplodedComponent {
|
||||
override fun canDrop(explosion: Explosion): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onExploded(state: BlockState, world: World, pos: BlockPos, explosion: Explosion) {
|
||||
pos.getTile<TileEntityJarODust>(world)?.let {
|
||||
val layers = it.layers
|
||||
|
||||
repeat(layers.contents.size) {
|
||||
Block.spawnAsEntity(world, pos, layers.removeDust(BOTTOM))
|
||||
}
|
||||
}
|
||||
|
||||
ModSounds.BLOCK_JAR_O_DUST_SHATTER.playServer(world, pos.center, SoundCategory.BLOCKS)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ItemStack
|
||||
|
||||
fun getLayersFromStack(stack: ItemStack): DustLayers? {
|
||||
return if (stack.item === ModBlocks.JAR_O_DUST.asItem())
|
||||
stack.heeTagOrNull?.getListOfCompounds(TileEntityJarODust.LAYERS_TAG)?.let { list -> DustLayers(TileEntityJarODust.DUST_CAPACITY).apply { deserializeNBT(list) } }
|
||||
else
|
||||
null
|
||||
}
|
||||
|
||||
fun setLayersInStack(stack: ItemStack, layers: DustLayers) {
|
||||
if (stack.item === ModBlocks.JAR_O_DUST.asItem()) {
|
||||
stack.heeTag.putList(TileEntityJarODust.LAYERS_TAG, layers.serializeNBT())
|
||||
}
|
||||
}
|
||||
|
||||
// Drops
|
||||
|
||||
private fun getDrop(tile: TileEntityJarODust): ItemStack {
|
||||
return ItemStack(ModBlocks.JAR_O_DUST).also { setLayersInStack(it, tile.layers) }
|
||||
}
|
||||
|
||||
// Interaction
|
||||
|
||||
private fun tryExtractDust(world: World, pos: BlockPos, player: PlayerEntity, hand: Hand): Boolean {
|
||||
if (world.isRemote) {
|
||||
return true
|
||||
}
|
||||
|
||||
val removed = pos.getTile<TileEntityJarODust>(world)?.layers?.removeDust(if (player.isSneaking) BOTTOM else TOP)
|
||||
|
||||
if (removed != null) {
|
||||
player.setHeldItem(hand, removed)
|
||||
}
|
||||
@@ -208,4 +197,23 @@ object BlockJarODust : HeeBlockBuilder() {
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Client side
|
||||
|
||||
@Sided(Side.CLIENT)
|
||||
override fun addInformation(stack: ItemStack, world: IBlockReader?, lines: MutableList<ITextComponent>, flags: ITooltipFlag) {
|
||||
val contents = getLayersFromStack(stack)?.contents
|
||||
|
||||
if (contents != null) {
|
||||
val entries = contents
|
||||
.groupingBy { it.first }
|
||||
.fold(0) { acc, entry -> acc + entry.second }
|
||||
.entries
|
||||
.sortedWith(compareBy({ -it.value }, { it.key.key }))
|
||||
|
||||
for ((dustType, dustAmount) in entries) {
|
||||
lines.add(TranslationTextComponent("block.hee.jar_o_dust.tooltip.entry", dustAmount, TranslationTextComponent(dustType.item.translationKey)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,18 +1,26 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.client.text.LocalizationStrategy
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.components.IBlockEntityComponent
|
||||
import chylex.hee.game.block.entity.TileEntityMinersBurialAltar
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockModel
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.util.math.AxisAlignedBB
|
||||
import net.minecraft.world.IBlockReader
|
||||
|
||||
object BlockMinersBurialAltar : HeeBlockBuilder() {
|
||||
init {
|
||||
includeFrom(BlockMinersBurialCube.INDESCRUCTIBLE)
|
||||
class BlockMinersBurialAltar(builder: BlockBuilder) : BlockSimpleShaped(builder, AxisAlignedBB(0.0, 0.0, 0.0, 1.0, 0.75, 1.0)) {
|
||||
override val localization
|
||||
get() = LocalizationStrategy.ReplaceWords("Miners", "Miner's")
|
||||
|
||||
localization = LocalizationStrategy.ReplaceWords("Miners", "Miner's")
|
||||
model = BlockModel.Manual
|
||||
override val model
|
||||
get() = BlockModel.Manual
|
||||
|
||||
components.entity = IBlockEntityComponent(::TileEntityMinersBurialAltar)
|
||||
override fun hasTileEntity(state: BlockState): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun createTileEntity(state: BlockState, world: IBlockReader): TileEntity {
|
||||
return TileEntityMinersBurialAltar()
|
||||
}
|
||||
}
|
||||
|
@@ -1,29 +1,9 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.client.text.LocalizationStrategy
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockHardness
|
||||
import chylex.hee.game.block.properties.BlockHarvestTool
|
||||
import chylex.hee.game.block.properties.Materials
|
||||
import chylex.hee.game.item.util.Tool.Level
|
||||
import net.minecraft.block.SoundType
|
||||
import net.minecraft.block.material.MaterialColor
|
||||
import net.minecraftforge.common.ToolType
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
|
||||
object BlockMinersBurialCube : HeeBlockBuilder() {
|
||||
init {
|
||||
localization = LocalizationStrategy.Parenthesized(LocalizationStrategy.DeleteWords(LocalizationStrategy.ReplaceWords("Miners", "Miner's"), "Plain"), wordCount = 1, wordOffset = 3, fromStart = true)
|
||||
|
||||
material = Materials.SOLID
|
||||
color = MaterialColor.RED
|
||||
sound = SoundType.STONE
|
||||
|
||||
tool = BlockHarvestTool.required(Level.WOOD, ToolType.PICKAXE)
|
||||
hardness = BlockHardness(hardness = 0.6F, resistance = 120F)
|
||||
}
|
||||
|
||||
val INDESCRUCTIBLE = HeeBlockBuilder {
|
||||
includeFrom(BlockIndestructible)
|
||||
includeFrom(BlockMinersBurialCube)
|
||||
}
|
||||
class BlockMinersBurialCube(builder: BlockBuilder) : HeeBlock(builder) {
|
||||
override val localization
|
||||
get() = LocalizationStrategy.Parenthesized(LocalizationStrategy.DeleteWords(LocalizationStrategy.ReplaceWords("Miners", "Miner's"), "Plain"), wordCount = 1, wordOffset = 3, fromStart = true)
|
||||
}
|
||||
|
@@ -1,50 +1,28 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.client.text.LocalizationStrategy
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockHardness
|
||||
import chylex.hee.game.block.properties.BlockHarvestTool
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockStateModels
|
||||
import chylex.hee.game.block.properties.Materials
|
||||
import chylex.hee.game.item.util.Tool.Level.DIAMOND
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.SoundType
|
||||
import net.minecraft.block.material.MaterialColor
|
||||
import net.minecraftforge.common.Tags
|
||||
import net.minecraftforge.common.ToolType.PICKAXE
|
||||
|
||||
object BlockObsidianCube : HeeBlockBuilder() {
|
||||
private val DEFAULT_LOCALIZATION = LocalizationStrategy.MoveToBeginning(wordCount = 1, wordOffset = 1, fromStart = true)
|
||||
open class BlockObsidianCube(builder: BlockBuilder) : HeeBlock(builder) {
|
||||
override val localization: LocalizationStrategy
|
||||
get() = LocalizationStrategy.MoveToBeginning(wordCount = 1, wordOffset = 1, fromStart = true)
|
||||
|
||||
init {
|
||||
localization = DEFAULT_LOCALIZATION
|
||||
final override val tags
|
||||
get() = listOf(Tags.Blocks.OBSIDIAN)
|
||||
|
||||
tags.add(Tags.Blocks.OBSIDIAN)
|
||||
open class Lit(builder: BlockBuilder, private val modelBlock: Block) : BlockObsidianCube(builder) {
|
||||
override val localization: LocalizationStrategy
|
||||
get() = LocalizationStrategy.Parenthesized(super.localization, wordCount = 1, fromStart = false)
|
||||
|
||||
material = Materials.SOLID
|
||||
color = MaterialColor.BLACK
|
||||
sound = SoundType.STONE
|
||||
tool = BlockHarvestTool.required(DIAMOND, PICKAXE)
|
||||
hardness = BlockHardness(hardness = 20F, resistance = 300F)
|
||||
override val model
|
||||
get() = BlockStateModels.Cube(modelBlock)
|
||||
}
|
||||
|
||||
class Lit(modelBlock: Block) : HeeBlockBuilder() {
|
||||
init {
|
||||
includeFrom(BlockObsidianCube)
|
||||
|
||||
localization = LocalizationStrategy.Parenthesized(DEFAULT_LOCALIZATION, wordCount = 1, fromStart = false)
|
||||
model = BlockStateModels.Cube(modelBlock)
|
||||
|
||||
light = 15
|
||||
}
|
||||
}
|
||||
|
||||
class TowerTop(modelBlock: Block) : HeeBlockBuilder() {
|
||||
init {
|
||||
includeFrom(BlockIndestructible)
|
||||
includeFrom(Lit(modelBlock))
|
||||
|
||||
localization = LocalizationStrategy.Default
|
||||
}
|
||||
class TowerTop(builder: BlockBuilder, modelBlock: Block) : Lit(builder, modelBlock) {
|
||||
override val localization
|
||||
get() = LocalizationStrategy.Default
|
||||
}
|
||||
}
|
||||
|
10
src/main/java/chylex/hee/game/block/BlockPortalFrame.kt
Normal file
10
src/main/java/chylex/hee/game/block/BlockPortalFrame.kt
Normal file
@@ -0,0 +1,10 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockModel
|
||||
import net.minecraft.util.math.AxisAlignedBB
|
||||
|
||||
open class BlockPortalFrame(builder: BlockBuilder) : BlockSimpleShaped(builder, AxisAlignedBB(0.0, 0.0, 0.0, 1.0, 0.8125, 1.0)) {
|
||||
override val model
|
||||
get() = BlockModel.PortalFrame(this, "plain")
|
||||
}
|
@@ -3,20 +3,16 @@ package chylex.hee.game.block
|
||||
import chylex.hee.client.text.LocalizationStrategy
|
||||
import chylex.hee.client.util.MC
|
||||
import chylex.hee.game.Resource
|
||||
import chylex.hee.game.block.BlockPuzzleLogic.IPuzzleLogic
|
||||
import chylex.hee.game.block.BlockPuzzleLogic.State.ACTIVE
|
||||
import chylex.hee.game.block.BlockPuzzleLogic.State.DISABLED
|
||||
import chylex.hee.game.block.BlockPuzzleLogic.State.INACTIVE
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.components.IBlockPlacementComponent
|
||||
import chylex.hee.game.block.interfaces.IBlockInterface
|
||||
import chylex.hee.game.block.interfaces.getHeeInterface
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockModel
|
||||
import chylex.hee.game.block.properties.BlockRenderLayer.CUTOUT
|
||||
import chylex.hee.game.block.properties.BlockStateModel
|
||||
import chylex.hee.game.block.properties.BlockStatePreset
|
||||
import chylex.hee.game.block.properties.BlockTint
|
||||
import chylex.hee.game.block.properties.Materials
|
||||
import chylex.hee.game.block.properties.IBlockStateModel
|
||||
import chylex.hee.game.block.util.Property
|
||||
import chylex.hee.game.block.util.withFacing
|
||||
import chylex.hee.game.entity.util.posVec
|
||||
@@ -50,10 +46,9 @@ import chylex.hee.util.random.nextFloat
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.HorizontalBlock.HORIZONTAL_FACING
|
||||
import net.minecraft.block.SoundType
|
||||
import net.minecraft.block.material.MaterialColor
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.item.BlockItemUseContext
|
||||
import net.minecraft.state.StateContainer.Builder
|
||||
import net.minecraft.util.Direction
|
||||
import net.minecraft.util.Direction.NORTH
|
||||
import net.minecraft.util.Direction.SOUTH
|
||||
@@ -65,7 +60,7 @@ import net.minecraft.world.IBlockDisplayReader
|
||||
import net.minecraft.world.World
|
||||
import java.util.Random
|
||||
|
||||
class BlockPuzzleLogic(impl: IPuzzleLogic) : HeeBlockBuilder() {
|
||||
sealed class BlockPuzzleLogic(builder: BlockBuilder) : HeeBlock(builder) {
|
||||
companion object {
|
||||
val STATE = Property.enum<State>("state")
|
||||
|
||||
@@ -106,7 +101,7 @@ class BlockPuzzleLogic(impl: IPuzzleLogic) : HeeBlockBuilder() {
|
||||
var closest = pos
|
||||
var closestDistSq = pos.distanceSqTo(player)
|
||||
|
||||
for (testPos in pos.floodFill(Facing4) { isPuzzleBlock(it.getBlock(world)) }) {
|
||||
for (testPos in pos.floodFill(Facing4) { it.getBlock(world) is BlockPuzzleLogic }) {
|
||||
PARTICLE_TOGGLE.spawn(Point(testPos, 3), rand)
|
||||
|
||||
val distSq = testPos.distanceSqTo(player)
|
||||
@@ -128,12 +123,8 @@ class BlockPuzzleLogic(impl: IPuzzleLogic) : HeeBlockBuilder() {
|
||||
}
|
||||
}
|
||||
|
||||
fun isPuzzleBlock(block: Block): Boolean {
|
||||
return block.getHeeInterface<IPuzzleLogic>() != null
|
||||
}
|
||||
|
||||
fun isPuzzleBlockEnabled(state: BlockState): Boolean {
|
||||
return isPuzzleBlock(state.block) && state[STATE] != DISABLED
|
||||
private fun isPuzzleBlockEnabled(state: BlockState): Boolean {
|
||||
return state.block is BlockPuzzleLogic && state[STATE] != DISABLED
|
||||
}
|
||||
|
||||
fun findAllBlocks(world: World, pos: BlockPos): List<BlockPos> {
|
||||
@@ -213,66 +204,6 @@ class BlockPuzzleLogic(impl: IPuzzleLogic) : HeeBlockBuilder() {
|
||||
mapOf("top" to Resource.Custom("block/puzzle_overlay_$itemSuffix"))
|
||||
)
|
||||
)
|
||||
|
||||
fun onToggled(world: World, pos: BlockPos, facing: Direction): List<Pair<BlockPos, Direction>> {
|
||||
val state = pos.getState(world)
|
||||
val logic = state.block.getHeeInterface<IPuzzleLogic>()
|
||||
|
||||
return if (logic != null && toggleState(world, pos, state))
|
||||
logic.getNextChains(world, pos, facing)
|
||||
else
|
||||
emptyList()
|
||||
}
|
||||
|
||||
private fun toggleState(world: World, pos: BlockPos, state: BlockState): Boolean {
|
||||
val type = state[STATE]
|
||||
|
||||
if (type == DISABLED) {
|
||||
return false
|
||||
}
|
||||
|
||||
pos.setState(world, state.with(STATE, type.toggled))
|
||||
PacketClientFX(FX_TOGGLE, FxBlockData(pos)).sendToAllAround(world, pos, 24.0)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
includeFrom(BlockIndestructible)
|
||||
|
||||
renderLayer = CUTOUT
|
||||
|
||||
material = Materials.SOLID
|
||||
color = MaterialColor.ADOBE /* RENAME ORANGE */
|
||||
sound = SoundType.STONE
|
||||
|
||||
tint = object : BlockTint() {
|
||||
@Sided(Side.CLIENT)
|
||||
override fun tint(state: BlockState, world: IBlockDisplayReader?, pos: BlockPos?, tintIndex: Int): Int {
|
||||
if (tintIndex != 1) {
|
||||
return NO_TINT
|
||||
}
|
||||
|
||||
if (world == null && pos == null) {
|
||||
return RGB(104, 58, 16).i // make the color slightly more visible in inventory
|
||||
}
|
||||
|
||||
return when (state[STATE]) {
|
||||
ACTIVE -> RGB(117, 66, 19).i
|
||||
INACTIVE -> RGB(212, 157, 102).i
|
||||
DISABLED -> RGB( 58, 40, 23).i
|
||||
else -> NO_TINT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
components.states.set(STATE, ACTIVE)
|
||||
|
||||
interfaces[IPuzzleLogic::class.java] = impl
|
||||
}
|
||||
|
||||
fun interface IPuzzleLogic : IBlockInterface {
|
||||
fun getNextChains(world: World, pos: BlockPos, facing: Direction): List<Pair<BlockPos, Direction>>
|
||||
}
|
||||
|
||||
enum class State(private val serializableName: String) : IStringSerializable {
|
||||
@@ -292,101 +223,159 @@ class BlockPuzzleLogic(impl: IPuzzleLogic) : HeeBlockBuilder() {
|
||||
}
|
||||
}
|
||||
|
||||
object Plain : HeeBlockBuilder() {
|
||||
internal val LOGIC = IPuzzleLogic { _, pos, facing -> listOf(makePair(pos, facing)) }
|
||||
abstract override val model: IBlockStateModel
|
||||
|
||||
final override val renderLayer
|
||||
get() = CUTOUT
|
||||
|
||||
init {
|
||||
includeFrom(BlockPuzzleLogic(LOGIC))
|
||||
defaultState = stateContainer.baseState.with(STATE, ACTIVE)
|
||||
}
|
||||
|
||||
localization = LocalizationStrategy.Parenthesized(wordCount = 1, fromStart = false)
|
||||
model = createPlainModel()
|
||||
override fun fillStateContainer(container: Builder<Block, BlockState>) {
|
||||
container.add(STATE)
|
||||
}
|
||||
|
||||
// Logic
|
||||
|
||||
fun onToggled(world: World, pos: BlockPos, facing: Direction): List<Pair<BlockPos, Direction>> {
|
||||
val state = pos.getState(world)
|
||||
|
||||
return if (toggleState(world, pos, state))
|
||||
getNextChains(world, pos, facing)
|
||||
else
|
||||
emptyList()
|
||||
}
|
||||
|
||||
protected fun toggleState(world: World, pos: BlockPos, state: BlockState): Boolean {
|
||||
val type = state[STATE]
|
||||
|
||||
if (type == DISABLED) {
|
||||
return false
|
||||
}
|
||||
|
||||
pos.setState(world, state.with(STATE, type.toggled))
|
||||
PacketClientFX(FX_TOGGLE, FxBlockData(pos)).sendToAllAround(world, pos, 24.0)
|
||||
return true
|
||||
}
|
||||
|
||||
protected abstract fun getNextChains(world: World, pos: BlockPos, facing: Direction): List<Pair<BlockPos, Direction>>
|
||||
|
||||
// Variations
|
||||
|
||||
class Plain(builder: BlockBuilder) : BlockPuzzleLogic(builder) {
|
||||
override val localization
|
||||
get() = LocalizationStrategy.Parenthesized(wordCount = 1, fromStart = false)
|
||||
|
||||
override val model
|
||||
get() = createPlainModel()
|
||||
|
||||
override fun getNextChains(world: World, pos: BlockPos, facing: Direction): List<Pair<BlockPos, Direction>> {
|
||||
return listOf(makePair(pos, facing))
|
||||
}
|
||||
}
|
||||
|
||||
class Burst(radius: Int) : HeeBlockBuilder() {
|
||||
private val logic = IPuzzleLogic { world, pos, facing ->
|
||||
pos.allInCenteredBox(radius, 0, radius).toList().flatMap { toggleAndChain(world, it, facing) }.distinct()
|
||||
}
|
||||
class Burst(builder: BlockBuilder, private val radius: Int) : BlockPuzzleLogic(builder) {
|
||||
override val localization
|
||||
get() = LocalizationStrategy.Parenthesized(LocalizationStrategy.ReplaceWords("$diameter", "${diameter}x${diameter}"), wordCount = 2, fromStart = false)
|
||||
|
||||
init {
|
||||
includeFrom(BlockPuzzleLogic(logic))
|
||||
override val model
|
||||
get() = createOverlayModel("burst_$diameter")
|
||||
|
||||
val diameter = 1 + (radius * 2)
|
||||
localization = LocalizationStrategy.Parenthesized(LocalizationStrategy.ReplaceWords("$diameter", "${diameter}x${diameter}"), wordCount = 2, fromStart = false)
|
||||
model = createOverlayModel("burst_$diameter")
|
||||
}
|
||||
private val diameter
|
||||
get() = 1 + (radius * 2)
|
||||
|
||||
private fun toggleAndChain(world: World, pos: BlockPos, facing: Direction): List<Pair<BlockPos, Direction>> {
|
||||
val state = pos.getState(world)
|
||||
val logic = state.block.getHeeInterface<IPuzzleLogic>()
|
||||
val block = state.block
|
||||
|
||||
return if (logic == null || !toggleState(world, pos, state) || logic === Plain.LOGIC || logic === this.logic)
|
||||
return if (block !is BlockPuzzleLogic || !toggleState(world, pos, state) || block is Plain || block is Burst)
|
||||
emptyList()
|
||||
else
|
||||
logic.getNextChains(world, pos, facing)
|
||||
block.getNextChains(world, pos, facing)
|
||||
}
|
||||
|
||||
override fun getNextChains(world: World, pos: BlockPos, facing: Direction): List<Pair<BlockPos, Direction>> {
|
||||
return pos.allInCenteredBox(radius, 0, radius).toList().flatMap { toggleAndChain(world, it, facing) }.distinct()
|
||||
}
|
||||
}
|
||||
|
||||
private class RedirectSome(blockDirections: Array<String>, itemDirection: String, directions: Array<Direction>) : HeeBlockBuilder() {
|
||||
private val logic = BlockPuzzleLogic { world, pos, facing ->
|
||||
sealed class RedirectSome private constructor(builder: BlockBuilder, private val blockDirections: Array<String>, private val itemDirection: String, private val directions: Array<Direction>) : BlockPuzzleLogic(builder) {
|
||||
class R1(builder: BlockBuilder) : RedirectSome(builder, arrayOf("n", "s", "e", "w"), "n", arrayOf(NORTH))
|
||||
class R2(builder: BlockBuilder) : RedirectSome(builder, arrayOf("ns", "ew"), "ns", arrayOf(NORTH, SOUTH))
|
||||
|
||||
override val localization
|
||||
get() = LocalizationStrategy.Parenthesized(wordCount = 2, fromStart = false)
|
||||
|
||||
override val model
|
||||
get() = createOverlayModel("redirect_" + directions.size + itemDirection, blockDirections.map { "redirect_" + directions.size + it })
|
||||
|
||||
init {
|
||||
defaultState = stateContainer.baseState.with(STATE, ACTIVE).withFacing(NORTH)
|
||||
}
|
||||
|
||||
override fun fillStateContainer(container: Builder<Block, BlockState>) {
|
||||
container.add(STATE, HORIZONTAL_FACING)
|
||||
}
|
||||
|
||||
override fun getStateForPlacement(context: BlockItemUseContext): BlockState {
|
||||
return this.withFacing(context.placementHorizontalFacing)
|
||||
}
|
||||
|
||||
override fun getNextChains(world: World, pos: BlockPos, facing: Direction): List<Pair<BlockPos, Direction>> {
|
||||
val rotation = pos.getState(world)[HORIZONTAL_FACING].horizontalIndex + NORTH.horizontalIndex
|
||||
val exclude = facing.opposite
|
||||
|
||||
directions.map { Direction.byHorizontalIndex(it.horizontalIndex + rotation) }.filter { it != exclude }.map { makePair(pos, it) }
|
||||
}
|
||||
|
||||
init {
|
||||
includeFrom(logic)
|
||||
|
||||
localization = LocalizationStrategy.Parenthesized(wordCount = 2, fromStart = false)
|
||||
model = createOverlayModel("redirect_" + directions.size + itemDirection, blockDirections.map { "redirect_" + directions.size + it })
|
||||
|
||||
components.states.set(HORIZONTAL_FACING, NORTH)
|
||||
components.states.facingProperty = HORIZONTAL_FACING
|
||||
|
||||
components.placement = object : IBlockPlacementComponent {
|
||||
override fun getPlacedState(defaultState: BlockState, world: World, pos: BlockPos, context: BlockItemUseContext): BlockState {
|
||||
return defaultState.withFacing(context.placementHorizontalFacing)
|
||||
}
|
||||
}
|
||||
return directions.map { Direction.byHorizontalIndex(it.horizontalIndex + rotation) }.filter { it != exclude }.map { makePair(pos, it) }
|
||||
}
|
||||
}
|
||||
|
||||
object RedirectOne : HeeBlockBuilder() {
|
||||
init {
|
||||
includeFrom(RedirectSome(arrayOf("n", "s", "e", "w"), "n", arrayOf(NORTH)))
|
||||
}
|
||||
}
|
||||
class RedirectAll(builder: BlockBuilder) : BlockPuzzleLogic(builder) {
|
||||
override val localization
|
||||
get() = LocalizationStrategy.Parenthesized(wordCount = 2, fromStart = false)
|
||||
|
||||
object RedirectTwo : HeeBlockBuilder() {
|
||||
init {
|
||||
includeFrom(RedirectSome(arrayOf("ns", "ew"), "ns", arrayOf(NORTH, SOUTH)))
|
||||
}
|
||||
}
|
||||
override val model
|
||||
get() = createOverlayModel("redirect_4")
|
||||
|
||||
object RedirectAll : HeeBlockBuilder() {
|
||||
init {
|
||||
includeFrom(BlockPuzzleLogic { _, pos, facing ->
|
||||
Facing4.filter { it != facing.opposite }.map { makePair(pos, it) }
|
||||
})
|
||||
|
||||
localization = LocalizationStrategy.Parenthesized(wordCount = 2, fromStart = false)
|
||||
model = createOverlayModel("redirect_4")
|
||||
}
|
||||
}
|
||||
|
||||
object Teleport : HeeBlockBuilder() {
|
||||
private val logic = object : IPuzzleLogic {
|
||||
override fun getNextChains(world: World, pos: BlockPos, facing: Direction): List<Pair<BlockPos, Direction>> {
|
||||
return findAllBlocks(world, pos).filter { it != pos && it.getBlock(world).getHeeInterface<IPuzzleLogic>() === this }.map { makePair(it, facing) }
|
||||
return Facing4.filter { it != facing.opposite }.map { makePair(pos, it) }
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
includeFrom(BlockPuzzleLogic(logic))
|
||||
class Teleport(builder: BlockBuilder) : BlockPuzzleLogic(builder) {
|
||||
override val localization
|
||||
get() = LocalizationStrategy.Parenthesized(wordCount = 1, fromStart = false)
|
||||
|
||||
localization = LocalizationStrategy.Parenthesized(wordCount = 1, fromStart = false)
|
||||
model = createOverlayModel("teleport")
|
||||
override val model
|
||||
get() = createOverlayModel("teleport")
|
||||
|
||||
override fun getNextChains(world: World, pos: BlockPos, facing: Direction): List<Pair<BlockPos, Direction>> {
|
||||
return findAllBlocks(world, pos).filter { it != pos && it.getBlock(world) is Teleport }.map { makePair(it, facing) }
|
||||
}
|
||||
}
|
||||
|
||||
// Client side
|
||||
|
||||
override val tint: BlockTint
|
||||
get() = Tint
|
||||
|
||||
private object Tint : BlockTint() {
|
||||
@Sided(Side.CLIENT)
|
||||
override fun tint(state: BlockState, world: IBlockDisplayReader?, pos: BlockPos?, tintIndex: Int): Int {
|
||||
if (tintIndex != 1) {
|
||||
return NO_TINT
|
||||
}
|
||||
|
||||
if (world == null && pos == null) {
|
||||
return RGB(104, 58, 16).i // make the color slightly more visible in inventory
|
||||
}
|
||||
|
||||
return when (state[STATE]) {
|
||||
ACTIVE -> RGB(117, 66, 19).i
|
||||
INACTIVE -> RGB(212, 157, 102).i
|
||||
DISABLED -> RGB( 58, 40, 23).i
|
||||
else -> NO_TINT
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,20 +1,9 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.client.text.LocalizationStrategy
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.properties.Materials
|
||||
import net.minecraft.block.SoundType
|
||||
import net.minecraft.block.material.MaterialColor
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
|
||||
object BlockPuzzleWall : HeeBlockBuilder() {
|
||||
init {
|
||||
includeFrom(BlockIndestructible)
|
||||
|
||||
localization = LocalizationStrategy.Parenthesized(wordCount = 1, fromStart = false)
|
||||
|
||||
material = Materials.SOLID
|
||||
color = MaterialColor.ADOBE // RENAME ORANGE
|
||||
sound = SoundType.STONE
|
||||
light = 14
|
||||
}
|
||||
class BlockPuzzleWall(builder: BlockBuilder) : HeeBlock(builder) {
|
||||
override val localization
|
||||
get() = LocalizationStrategy.Parenthesized(wordCount = 1, fromStart = false)
|
||||
}
|
||||
|
@@ -2,55 +2,62 @@ package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.HEE
|
||||
import chylex.hee.game.Environment
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.components.IBlockShapeComponent
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockModel
|
||||
import chylex.hee.game.block.properties.BlockRenderLayer.CUTOUT
|
||||
import chylex.hee.game.block.properties.Materials
|
||||
import chylex.hee.util.forge.Side
|
||||
import chylex.hee.util.forge.Sided
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.SoundType
|
||||
import net.minecraft.block.material.MaterialColor
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.shapes.ISelectionContext
|
||||
import net.minecraft.util.math.shapes.VoxelShape
|
||||
import net.minecraft.util.math.shapes.VoxelShapes
|
||||
import net.minecraft.world.IBlockReader
|
||||
|
||||
object BlockScaffolding : HeeBlockBuilder() {
|
||||
open class BlockScaffolding protected constructor(builder: BlockBuilder) : HeeBlock(builder) {
|
||||
companion object {
|
||||
var enableShape = true
|
||||
|
||||
init {
|
||||
includeFrom(BlockIndestructible)
|
||||
|
||||
model = BlockModel.Manual
|
||||
renderLayer = CUTOUT
|
||||
|
||||
material = Materials.SCAFFOLDING
|
||||
color = MaterialColor.AIR
|
||||
sound = SoundType.STONE
|
||||
|
||||
isSolid = false
|
||||
isOpaque = false
|
||||
suffocates = false
|
||||
blocksVision = false
|
||||
|
||||
components.shape = object : IBlockShapeComponent {
|
||||
override fun getShape(state: BlockState): VoxelShape {
|
||||
return fullCubeIf(enableShape)
|
||||
}
|
||||
|
||||
override fun getCollisionShape(state: BlockState): VoxelShape {
|
||||
return fullCubeIf(enableShape && Environment.getClientSidePlayer().let { it == null || !it.abilities.isFlying })
|
||||
}
|
||||
|
||||
override fun getRaytraceShape(state: BlockState): VoxelShape {
|
||||
return fullCubeIf(enableShape && Environment.getClientSidePlayer().let { it == null || it.isSneaking || it.abilities.isFlying })
|
||||
}
|
||||
|
||||
private fun fullCubeIf(condition: Boolean): VoxelShape {
|
||||
return if (condition) VoxelShapes.fullCube() else VoxelShapes.empty()
|
||||
fun create(builder: BlockBuilder): HeeBlock {
|
||||
return HEE.debugModule?.createScaffoldingBlock(builder) ?: BlockScaffolding(builder)
|
||||
}
|
||||
}
|
||||
|
||||
components.ambientOcclusionValue = 1F
|
||||
override val model
|
||||
get() = BlockModel.Manual
|
||||
|
||||
components.playerUse = HEE.debugModule?.scaffoldingBlockBehavior
|
||||
override val renderLayer
|
||||
get() = CUTOUT
|
||||
|
||||
// Visuals and physics
|
||||
|
||||
override fun getShape(state: BlockState, world: IBlockReader, pos: BlockPos, context: ISelectionContext): VoxelShape {
|
||||
return if (enableShape)
|
||||
VoxelShapes.fullCube()
|
||||
else
|
||||
VoxelShapes.empty()
|
||||
}
|
||||
|
||||
override fun getCollisionShape(state: BlockState, world: IBlockReader, pos: BlockPos, context: ISelectionContext): VoxelShape {
|
||||
val player = Environment.getClientSidePlayer()
|
||||
|
||||
return if ((player == null || !player.abilities.isFlying) && enableShape)
|
||||
VoxelShapes.fullCube()
|
||||
else
|
||||
VoxelShapes.empty()
|
||||
}
|
||||
|
||||
override fun getRaytraceShape(state: BlockState, world: IBlockReader, pos: BlockPos): VoxelShape {
|
||||
val player = Environment.getClientSidePlayer()
|
||||
|
||||
return if ((player == null || player.isSneaking || player.abilities.isFlying) && enableShape)
|
||||
VoxelShapes.fullCube()
|
||||
else
|
||||
VoxelShapes.empty()
|
||||
}
|
||||
|
||||
@Sided(Side.CLIENT)
|
||||
override fun getAmbientOcclusionLightValue(state: BlockState, world: IBlockReader, pos: BlockPos): Float {
|
||||
return 1F
|
||||
}
|
||||
}
|
||||
|
@@ -2,43 +2,42 @@ package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.game.Resource
|
||||
import chylex.hee.game.Resource.location
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.components.IBlockExperienceComponent
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockDrop
|
||||
import chylex.hee.game.block.properties.BlockHardness
|
||||
import chylex.hee.game.block.properties.BlockHarvestTool
|
||||
import chylex.hee.game.block.properties.BlockModel
|
||||
import chylex.hee.game.block.properties.BlockRenderLayer.CUTOUT
|
||||
import chylex.hee.game.block.properties.BlockStateModel
|
||||
import chylex.hee.game.block.properties.BlockStatePreset
|
||||
import chylex.hee.game.block.properties.IBlockStateModelSupplier
|
||||
import chylex.hee.game.item.util.Tool.Level.STONE
|
||||
import chylex.hee.game.item.util.Tool.Type.PICKAXE
|
||||
import chylex.hee.init.ModBlocks
|
||||
import chylex.hee.util.math.ceilToInt
|
||||
import chylex.hee.util.random.nextBiasedFloat
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.IWorldReader
|
||||
import net.minecraft.world.World
|
||||
import net.minecraftforge.common.Tags
|
||||
|
||||
object BlockStardustOre : HeeBlockBuilder() {
|
||||
init {
|
||||
includeFrom(BlockEndOre)
|
||||
|
||||
model = IBlockStateModelSupplier {
|
||||
BlockStateModel(
|
||||
class BlockStardustOre(builder: BlockBuilder) : HeeBlock(builder) {
|
||||
override val model
|
||||
get() = BlockStateModel(
|
||||
BlockStatePreset.None,
|
||||
BlockModel.WithTextures(BlockModel.FromParent(Resource.Custom("block/cube_overlay")), mapOf(
|
||||
"particle" to it.location("_particle"),
|
||||
"particle" to ModBlocks.STARDUST_ORE.location("_particle"),
|
||||
"base" to Blocks.END_STONE.location,
|
||||
))
|
||||
)
|
||||
}
|
||||
|
||||
renderLayer = CUTOUT
|
||||
override val renderLayer
|
||||
get() = CUTOUT
|
||||
|
||||
drop = BlockDrop.Manual
|
||||
override val drop
|
||||
get() = BlockDrop.Manual
|
||||
|
||||
tool = BlockHarvestTool.required(STONE, PICKAXE)
|
||||
hardness = BlockHardness(hardness = 2.8F, resistance = 8.4F)
|
||||
override val tags
|
||||
get() = listOf(Tags.Blocks.ORES)
|
||||
|
||||
components.experience = IBlockExperienceComponent { rand -> (rand.nextBiasedFloat(4F) * 6F).ceilToInt() }
|
||||
override fun getExpDrop(state: BlockState, world: IWorldReader, pos: BlockPos, fortune: Int, silktouch: Int): Int {
|
||||
return (((world as? World)?.rand ?: RANDOM).nextBiasedFloat(4F) * 6F).ceilToInt()
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,26 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.game.block.logic.IBlockDynamicHardness
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.world.util.Facing4
|
||||
import chylex.hee.game.world.util.getBlock
|
||||
import chylex.hee.init.ModBlocks
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.IBlockReader
|
||||
|
||||
open class BlockVoidPortalCrafted(builder: BlockBuilder) : BlockPortalFrame(builder), IBlockDynamicHardness {
|
||||
override val model
|
||||
get() = ModBlocks.VOID_PORTAL_FRAME.model
|
||||
|
||||
override fun getBlockHardness(world: IBlockReader, pos: BlockPos, state: BlockState, originalHardness: Float): Float {
|
||||
return if (Facing4.any { pos.offset(it).getBlock(world) === ModBlocks.VOID_PORTAL_INNER })
|
||||
originalHardness * 20F
|
||||
else
|
||||
originalHardness
|
||||
}
|
||||
|
||||
override fun getTranslationKey(): String {
|
||||
return ModBlocks.VOID_PORTAL_FRAME.translationKey
|
||||
}
|
||||
}
|
@@ -1,48 +0,0 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.components.IBlockNameComponent
|
||||
import chylex.hee.game.block.logic.IBlockDynamicHardness
|
||||
import chylex.hee.game.block.properties.BlockHardness
|
||||
import chylex.hee.game.block.properties.BlockHarvestTool
|
||||
import chylex.hee.game.item.util.Tool.Level.DIAMOND
|
||||
import chylex.hee.game.world.util.Facing4
|
||||
import chylex.hee.game.world.util.getBlock
|
||||
import chylex.hee.init.ModBlocks
|
||||
import chylex.hee.init.ModTags
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.IBlockReader
|
||||
import net.minecraftforge.common.ToolType.PICKAXE
|
||||
|
||||
object BlockVoidPortalFrame {
|
||||
object Indestructible : HeeBlockBuilder() {
|
||||
init {
|
||||
includeFrom(BlockPortalFrameIndestructible)
|
||||
}
|
||||
}
|
||||
|
||||
object Crafted : HeeBlockBuilder() {
|
||||
init {
|
||||
includeFrom(BlockPortalFrameBase)
|
||||
|
||||
model = ModBlocks.VOID_PORTAL_FRAME.model.generate(ModBlocks.VOID_PORTAL_FRAME)
|
||||
|
||||
tags.add(ModTags.VOID_PORTAL_FRAME_CRAFTED)
|
||||
|
||||
tool = BlockHarvestTool.required(DIAMOND, PICKAXE)
|
||||
hardness = BlockHardness(hardnessAndResistance = 1.7F)
|
||||
|
||||
components.name = IBlockNameComponent.of(ModBlocks.VOID_PORTAL_FRAME)
|
||||
|
||||
interfaces[IBlockDynamicHardness::class.java] = object : IBlockDynamicHardness {
|
||||
override fun getBlockHardness(world: IBlockReader, pos: BlockPos, state: BlockState, originalHardness: Float): Float {
|
||||
return if (Facing4.any { pos.offset(it).getBlock(world) === ModBlocks.VOID_PORTAL_INNER })
|
||||
originalHardness * 20F
|
||||
else
|
||||
originalHardness
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,16 +1,14 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.game.block.BlockAbstractPortal.IInnerPortalBlock
|
||||
import chylex.hee.game.block.BlockAbstractPortal.IPortalController
|
||||
import chylex.hee.game.block.BlockVoidPortalInner.Type.HUB
|
||||
import chylex.hee.game.block.BlockVoidPortalInner.Type.RETURN_ACTIVE
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.components.IBlockNeighborChanged
|
||||
import chylex.hee.game.block.entity.TileEntityPortalInner
|
||||
import chylex.hee.game.block.entity.TileEntityVoidPortalStorage
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.block.util.Property
|
||||
import chylex.hee.game.entity.Teleporter
|
||||
import chylex.hee.game.entity.Teleporter.FxRange.Silent
|
||||
import chylex.hee.game.entity.util.EntityPortalContact
|
||||
import chylex.hee.game.mechanics.causatum.EnderCausatum
|
||||
import chylex.hee.game.territory.TerritoryType
|
||||
import chylex.hee.game.territory.system.TerritoryInstance
|
||||
@@ -26,34 +24,125 @@ import chylex.hee.game.world.util.max
|
||||
import chylex.hee.game.world.util.min
|
||||
import chylex.hee.game.world.util.offsetUntil
|
||||
import chylex.hee.game.world.util.setAir
|
||||
import chylex.hee.init.ModTags
|
||||
import chylex.hee.util.math.Pos
|
||||
import chylex.hee.util.math.Vec3
|
||||
import chylex.hee.util.math.center
|
||||
import chylex.hee.util.math.subtractY
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.LivingEntity
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.state.StateContainer.Builder
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.util.IStringSerializable
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.IBlockReader
|
||||
import net.minecraft.world.World
|
||||
|
||||
object BlockVoidPortalInner : HeeBlockBuilder() {
|
||||
class BlockVoidPortalInner(builder: BlockBuilder) : BlockAbstractPortal(builder) {
|
||||
companion object {
|
||||
val TYPE = Property.enum<Type>("type")
|
||||
|
||||
private val TELEPORTER = Teleporter(postEvent = false, effectRange = Silent)
|
||||
|
||||
fun teleportEntity(entity: Entity, info: SpawnInfo) {
|
||||
val targetVec = info.pos.center.subtractY(0.45)
|
||||
|
||||
if (entity is LivingEntity) {
|
||||
if (entity is PlayerEntity) {
|
||||
TerritoryType.fromPos(info.pos)?.let { EnderCausatum.triggerStage(entity, it.stage) }
|
||||
}
|
||||
|
||||
info.yaw?.let { entity.rotationYaw = it }
|
||||
entity.rotationPitch = 0F
|
||||
|
||||
TELEPORTER.toLocation(entity, targetVec)
|
||||
}
|
||||
else {
|
||||
entity.setPositionAndUpdate(targetVec.x, targetVec.y, targetVec.z)
|
||||
entity.motion = Vec3.ZERO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class Type(private val serializableName: String) : IStringSerializable {
|
||||
HUB("hub"),
|
||||
RETURN_ACTIVE("return_active"),
|
||||
RETURN_INACTIVE("return_inactive");
|
||||
|
||||
override fun getString(): String {
|
||||
return serializableName
|
||||
}
|
||||
}
|
||||
|
||||
interface IVoidPortalController : IPortalController {
|
||||
val currentInstanceFactory: ITerritoryInstanceFactory?
|
||||
}
|
||||
|
||||
interface ITerritoryInstanceFactory {
|
||||
val territory: TerritoryType
|
||||
fun create(entity: Entity): TerritoryInstance?
|
||||
}
|
||||
|
||||
// Instance
|
||||
|
||||
init {
|
||||
includeFrom(BlockAbstractPortal(object : IInnerPortalBlock {
|
||||
override fun createTileEntity(): TileEntity {
|
||||
defaultState = stateContainer.baseState.with(TYPE, HUB)
|
||||
}
|
||||
|
||||
override fun fillStateContainer(container: Builder<Block, BlockState>) {
|
||||
container.add(TYPE)
|
||||
}
|
||||
|
||||
override fun createTileEntity(state: BlockState, world: IBlockReader): TileEntity {
|
||||
return TileEntityPortalInner.Void()
|
||||
}
|
||||
|
||||
override fun teleportEntity(world: World, pos: BlockPos, entity: Entity) {
|
||||
// Breaking
|
||||
|
||||
override fun neighborChanged(state: BlockState, world: World, pos: BlockPos, neighborBlock: Block, neighborPos: BlockPos, isMoving: Boolean) {
|
||||
if (neighborBlock is BlockVoidPortalCrafted && neighborPos.getBlock(world) !is BlockVoidPortalCrafted) {
|
||||
for (portalPos in pos.floodFill(Facing4) { it.getBlock(world) === this }) {
|
||||
portalPos.setAir(world)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
super.neighborChanged(state, world, pos, neighborBlock, neighborPos, isMoving)
|
||||
}
|
||||
|
||||
// Interaction
|
||||
|
||||
private fun findSpawnPortalCenter(entity: Entity, pos: BlockPos): BlockPos? {
|
||||
val world = entity.world
|
||||
val offsets = Facing4.map { facing -> pos.offsetUntil(facing, 1..MAX_SIZE) { it.getBlock(world) !== this } ?: return null }
|
||||
|
||||
val minPos = offsets.reduce(BlockPos::min)
|
||||
val maxPos = offsets.reduce(BlockPos::max)
|
||||
|
||||
return Pos((minPos.x + maxPos.x) / 2, pos.y, (minPos.z + maxPos.z) / 2)
|
||||
}
|
||||
|
||||
private fun updateSpawnPortal(entity: Entity, pos: BlockPos) {
|
||||
if (entity !is PlayerEntity) {
|
||||
return
|
||||
}
|
||||
|
||||
val centerPos = findSpawnPortalCenter(entity, pos) ?: return
|
||||
val instance = TerritoryInstance.fromPos(entity) ?: return
|
||||
|
||||
instance.updateSpawnPoint(entity, centerPos)
|
||||
}
|
||||
|
||||
override fun onEntityInside(world: World, pos: BlockPos, entity: Entity) {
|
||||
if (!EntityPortalContact.shouldTeleport(entity)) {
|
||||
return
|
||||
}
|
||||
|
||||
when(pos.getState(world)[TYPE]) {
|
||||
HUB -> {
|
||||
val info = pos.closestTickingTile<TileEntityVoidPortalStorage>(world, BlockAbstractPortal.MAX_DISTANCE_FROM_FRAME)?.prepareSpawnPoint(entity)
|
||||
val info = pos.closestTickingTile<TileEntityVoidPortalStorage>(world, MAX_DISTANCE_FROM_FRAME)?.prepareSpawnPoint(entity)
|
||||
|
||||
if (info != null) {
|
||||
if (entity.isInEndDimension) {
|
||||
@@ -78,76 +167,4 @@ object BlockVoidPortalInner : HeeBlockBuilder() {
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
components.states.set(TYPE, HUB)
|
||||
|
||||
components.onNeighborChanged = IBlockNeighborChanged { state, world, pos, oldNeighborBlock, newNeighborBlock, _ ->
|
||||
if (ModTags.VOID_PORTAL_FRAME_CRAFTED.contains(oldNeighborBlock) && !ModTags.VOID_PORTAL_FRAME_CRAFTED.contains(newNeighborBlock)) {
|
||||
for (portalPos in pos.floodFill(Facing4) { it.getBlock(world) === state.block }) {
|
||||
portalPos.setAir(world)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class Type(private val serializableName: String) : IStringSerializable {
|
||||
HUB("hub"),
|
||||
RETURN_ACTIVE("return_active"),
|
||||
RETURN_INACTIVE("return_inactive");
|
||||
|
||||
override fun getString(): String {
|
||||
return serializableName
|
||||
}
|
||||
}
|
||||
|
||||
interface IVoidPortalController : IPortalController {
|
||||
val currentInstanceFactory: ITerritoryInstanceFactory?
|
||||
}
|
||||
|
||||
interface ITerritoryInstanceFactory {
|
||||
val territory: TerritoryType
|
||||
fun create(entity: Entity): TerritoryInstance?
|
||||
}
|
||||
|
||||
fun teleportEntity(entity: Entity, info: SpawnInfo) {
|
||||
val targetVec = info.pos.center.subtractY(0.45)
|
||||
|
||||
if (entity is LivingEntity) {
|
||||
if (entity is PlayerEntity) {
|
||||
TerritoryType.fromPos(info.pos)?.let { EnderCausatum.triggerStage(entity, it.stage) }
|
||||
}
|
||||
|
||||
info.yaw?.let { entity.rotationYaw = it }
|
||||
entity.rotationPitch = 0F
|
||||
|
||||
TELEPORTER.toLocation(entity, targetVec)
|
||||
}
|
||||
else {
|
||||
entity.setPositionAndUpdate(targetVec.x, targetVec.y, targetVec.z)
|
||||
entity.motion = Vec3.ZERO
|
||||
}
|
||||
}
|
||||
|
||||
private fun findSpawnPortalCenter(entity: Entity, pos: BlockPos): BlockPos? {
|
||||
val world = entity.world
|
||||
val block = pos.getBlock(world)
|
||||
val offsets = Facing4.map { facing -> pos.offsetUntil(facing, 1..BlockAbstractPortal.MAX_SIZE) { it.getBlock(world) !== block } ?: return null }
|
||||
|
||||
val minPos = offsets.reduce(BlockPos::min)
|
||||
val maxPos = offsets.reduce(BlockPos::max)
|
||||
|
||||
return Pos((minPos.x + maxPos.x) / 2, pos.y, (minPos.z + maxPos.z) / 2)
|
||||
}
|
||||
|
||||
private fun updateSpawnPortal(entity: Entity, pos: BlockPos) {
|
||||
if (entity !is PlayerEntity) {
|
||||
return
|
||||
}
|
||||
|
||||
val centerPos = findSpawnPortalCenter(entity, pos) ?: return
|
||||
val instance = TerritoryInstance.fromPos(entity) ?: return
|
||||
|
||||
instance.updateSpawnPoint(entity, centerPos)
|
||||
}
|
||||
}
|
||||
|
@@ -1,40 +1,47 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.components.IBlockAddedComponent
|
||||
import chylex.hee.game.block.components.IBlockEntityComponent
|
||||
import chylex.hee.game.block.components.IBlockNameComponent
|
||||
import chylex.hee.game.block.components.IPlayerUseBlockComponent
|
||||
import chylex.hee.game.block.entity.TileEntityVoidPortalStorage
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockModel
|
||||
import chylex.hee.game.world.util.getTile
|
||||
import chylex.hee.init.ModBlocks
|
||||
import chylex.hee.init.ModContainers
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.util.ActionResultType
|
||||
import net.minecraft.util.ActionResultType.SUCCESS
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.BlockRayTraceResult
|
||||
import net.minecraft.world.IBlockReader
|
||||
import net.minecraft.world.World
|
||||
|
||||
abstract class BlockVoidPortalStorage(base: HeeBlockBuilder, minPortalSize: Int) : HeeBlockBuilder() {
|
||||
init {
|
||||
includeFrom(base)
|
||||
class BlockVoidPortalStorage(builder: BlockBuilder) : BlockPortalFrame(builder) {
|
||||
override val model
|
||||
get() = BlockModel.PortalFrame(ModBlocks.VOID_PORTAL_FRAME, "storage")
|
||||
|
||||
model = BlockModel.PortalFrame(ModBlocks.VOID_PORTAL_FRAME, "storage")
|
||||
|
||||
components.entity = IBlockEntityComponent(::TileEntityVoidPortalStorage)
|
||||
|
||||
components.onAdded = IBlockAddedComponent { _, world, pos ->
|
||||
BlockAbstractPortal.spawnInnerBlocks(world, pos, ModBlocks.VOID_PORTAL_FRAME, ModBlocks.VOID_PORTAL_INNER, minSize = minPortalSize)
|
||||
override fun hasTileEntity(state: BlockState): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
components.playerUse = IPlayerUseBlockComponent { _, world, pos, player, _ ->
|
||||
pos.getTile<TileEntityVoidPortalStorage>(world)?.let { ModContainers.open(player, it, pos) }
|
||||
SUCCESS
|
||||
}
|
||||
override fun createTileEntity(state: BlockState, world: IBlockReader): TileEntity {
|
||||
return TileEntityVoidPortalStorage()
|
||||
}
|
||||
|
||||
object Indestructible : BlockVoidPortalStorage(BlockVoidPortalFrame.Indestructible, minPortalSize = 1)
|
||||
override fun onBlockAdded(state: BlockState, world: World, pos: BlockPos, oldState: BlockState, isMoving: Boolean) {
|
||||
BlockAbstractPortal.spawnInnerBlocks(world, pos, ModBlocks.VOID_PORTAL_FRAME, ModBlocks.VOID_PORTAL_INNER, minSize = 1)
|
||||
}
|
||||
|
||||
object Crafted : BlockVoidPortalStorage(BlockVoidPortalFrame.Crafted, minPortalSize = 3) {
|
||||
init {
|
||||
components.name = IBlockNameComponent.of(ModBlocks.VOID_PORTAL_STORAGE)
|
||||
}
|
||||
override fun onBlockActivated(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hit: BlockRayTraceResult): ActionResultType {
|
||||
if (world.isRemote) {
|
||||
return SUCCESS
|
||||
}
|
||||
|
||||
pos.getTile<TileEntityVoidPortalStorage>(world)?.let {
|
||||
ModContainers.open(player, it, pos)
|
||||
}
|
||||
|
||||
return SUCCESS
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,39 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.init.ModBlocks
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.util.ActionResultType
|
||||
import net.minecraft.util.Hand
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.BlockRayTraceResult
|
||||
import net.minecraft.world.IBlockReader
|
||||
import net.minecraft.world.World
|
||||
|
||||
class BlockVoidPortalStorageCrafted(builder: BlockBuilder) : BlockVoidPortalCrafted(builder) {
|
||||
override val model
|
||||
get() = ModBlocks.VOID_PORTAL_STORAGE.model
|
||||
|
||||
override fun hasTileEntity(state: BlockState): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun createTileEntity(state: BlockState, world: IBlockReader): TileEntity {
|
||||
return ModBlocks.VOID_PORTAL_STORAGE.createTileEntity(state, world)
|
||||
}
|
||||
|
||||
override fun onBlockAdded(state: BlockState, world: World, pos: BlockPos, oldState: BlockState, isMoving: Boolean) {
|
||||
BlockAbstractPortal.spawnInnerBlocks(world, pos, ModBlocks.VOID_PORTAL_FRAME_CRAFTED, ModBlocks.VOID_PORTAL_INNER, minSize = 3)
|
||||
}
|
||||
|
||||
override fun onBlockActivated(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hit: BlockRayTraceResult): ActionResultType {
|
||||
@Suppress("DEPRECATION")
|
||||
return ModBlocks.VOID_PORTAL_STORAGE.onBlockActivated(state, world, pos, player, hand, hit)
|
||||
}
|
||||
|
||||
override fun getTranslationKey(): String {
|
||||
return ModBlocks.VOID_PORTAL_STORAGE.translationKey
|
||||
}
|
||||
}
|
@@ -1,47 +1,27 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.game.Resource.location
|
||||
import chylex.hee.game.block.builder.HeeBlockBuilder
|
||||
import chylex.hee.game.block.components.IFlammableBlockComponent
|
||||
import chylex.hee.game.block.properties.BlockHardness
|
||||
import chylex.hee.game.block.properties.BlockHarvestTool
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockModel
|
||||
import chylex.hee.game.item.util.Tool.Level.WOOD
|
||||
import chylex.hee.init.ModBlocks
|
||||
import net.minecraft.block.SoundType
|
||||
import net.minecraft.block.material.Material
|
||||
import net.minecraft.block.material.MaterialColor
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.tags.BlockTags
|
||||
import net.minecraftforge.common.ToolType.AXE
|
||||
import net.minecraft.util.Direction
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.IBlockReader
|
||||
|
||||
object BlockWhitebark : HeeBlockBuilder() {
|
||||
init {
|
||||
material = Material.WOOD
|
||||
color = MaterialColor.SNOW
|
||||
sound = SoundType.WOOD
|
||||
tool = BlockHarvestTool.optional(WOOD, AXE)
|
||||
class BlockWhitebark(builder: BlockBuilder) : HeeBlock(builder) {
|
||||
override val model
|
||||
get() = BlockModel.Cube(ModBlocks.WHITEBARK_LOG.location)
|
||||
|
||||
override val tags
|
||||
get() = listOf(BlockTags.LOGS, BlockTags.LOGS_THAT_BURN)
|
||||
|
||||
override fun getFlammability(state: BlockState, world: IBlockReader, pos: BlockPos, face: Direction): Int {
|
||||
return 5
|
||||
}
|
||||
|
||||
val BARK = HeeBlockBuilder {
|
||||
includeFrom(BlockWhitebark)
|
||||
|
||||
model = BlockModel.Cube(ModBlocks.WHITEBARK_LOG.location)
|
||||
|
||||
tags.add(BlockTags.LOGS)
|
||||
tags.add(BlockTags.LOGS_THAT_BURN)
|
||||
|
||||
hardness = BlockHardness(hardnessAndResistance = 2F)
|
||||
|
||||
components.flammability = IFlammableBlockComponent.of(flammability = 5, fireSpread = 5)
|
||||
}
|
||||
|
||||
val PLANKS = HeeBlockBuilder {
|
||||
includeFrom(BlockWhitebark)
|
||||
|
||||
tags.add(BlockTags.PLANKS)
|
||||
|
||||
hardness = BlockHardness(hardness = 2F, resistance = 3F)
|
||||
|
||||
components.flammability = IFlammableBlockComponent.of(flammability = 20, fireSpread = 5)
|
||||
override fun getFireSpreadSpeed(state: BlockState, world: IBlockReader, pos: BlockPos, face: Direction): Int {
|
||||
return 5
|
||||
}
|
||||
}
|
||||
|
21
src/main/java/chylex/hee/game/block/BlockWhitebarkPlanks.kt
Normal file
21
src/main/java/chylex/hee/game/block/BlockWhitebarkPlanks.kt
Normal file
@@ -0,0 +1,21 @@
|
||||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.tags.BlockTags
|
||||
import net.minecraft.util.Direction
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.world.IBlockReader
|
||||
|
||||
class BlockWhitebarkPlanks(builder: BlockBuilder) : HeeBlock(builder) {
|
||||
override val tags
|
||||
get() = listOf(BlockTags.PLANKS)
|
||||
|
||||
override fun getFlammability(state: BlockState, world: IBlockReader, pos: BlockPos, face: Direction): Int {
|
||||
return 20
|
||||
}
|
||||
|
||||
override fun getFireSpreadSpeed(state: BlockState, world: IBlockReader, pos: BlockPos, face: Direction): Int {
|
||||
return 5
|
||||
}
|
||||
}
|
@@ -32,7 +32,6 @@ import chylex.hee.game.world.util.setState
|
||||
import chylex.hee.init.ModSounds
|
||||
import chylex.hee.network.client.PacketClientFX
|
||||
import chylex.hee.util.buffer.readPos
|
||||
import chylex.hee.util.buffer.use
|
||||
import chylex.hee.util.buffer.writePos
|
||||
import chylex.hee.util.math.center
|
||||
import chylex.hee.util.nbt.TagCompound
|
||||
@@ -174,9 +173,9 @@ interface IBlockDeathFlowerDecaying {
|
||||
private val PARTICLE_MOT = Gaussian(0.02F)
|
||||
|
||||
class FxHealData(private val pos: BlockPos, private val newLevel: Int) : IFxData {
|
||||
override fun write(buffer: PacketBuffer) = buffer.use {
|
||||
writePos(pos)
|
||||
writeByte(newLevel)
|
||||
override fun write(buffer: PacketBuffer) {
|
||||
buffer.writePos(pos)
|
||||
buffer.writeByte(newLevel)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,5 @@
|
||||
package chylex.hee.game.block.dispenser
|
||||
|
||||
import chylex.hee.game.block.BlockIgneousPlate
|
||||
import chylex.hee.game.block.util.DISPENSER_FACING
|
||||
import chylex.hee.game.world.util.getState
|
||||
import chylex.hee.init.ModBlocks
|
||||
@@ -17,7 +16,7 @@ class DispenseWaterExtinguishIgneousPlate(private val originalBehavior: IDispens
|
||||
val facingState = facingPos.getState(world)
|
||||
|
||||
if (facingState.block === ModBlocks.IGNEOUS_PLATE) {
|
||||
return if (BlockIgneousPlate.tryCoolPlate(world, facingPos, facingState))
|
||||
return if (ModBlocks.IGNEOUS_PLATE.tryCoolPlate(world, facingPos, facingState))
|
||||
ItemStack(Items.BUCKET)
|
||||
else
|
||||
stack
|
||||
|
@@ -27,7 +27,6 @@ import chylex.hee.init.ModSounds
|
||||
import chylex.hee.init.ModTileEntities
|
||||
import chylex.hee.network.client.PacketClientFX
|
||||
import chylex.hee.util.buffer.readCompactVec
|
||||
import chylex.hee.util.buffer.use
|
||||
import chylex.hee.util.buffer.writeCompactVec
|
||||
import chylex.hee.util.collection.mutableWeightedListOf
|
||||
import chylex.hee.util.collection.weightedListOf
|
||||
@@ -119,17 +118,17 @@ class TileEntityMinersBurialAltar(type: TileEntityType<TileEntityMinersBurialAlt
|
||||
)
|
||||
|
||||
class FxSpawnData(private val pos: Vector3d, private val type: Byte) : IFxData {
|
||||
override fun write(buffer: PacketBuffer) = buffer.use {
|
||||
writeCompactVec(pos)
|
||||
writeByte(type.toInt())
|
||||
override fun write(buffer: PacketBuffer) {
|
||||
buffer.writeCompactVec(pos)
|
||||
buffer.writeByte(type.toInt())
|
||||
}
|
||||
}
|
||||
|
||||
val FX_SPAWN = object : IFxHandler<FxSpawnData> {
|
||||
override fun handle(buffer: PacketBuffer, world: World, rand: Random) = buffer.use {
|
||||
val pos = readCompactVec()
|
||||
override fun handle(buffer: PacketBuffer, world: World, rand: Random) {
|
||||
val pos = buffer.readCompactVec()
|
||||
|
||||
when (readByte()) {
|
||||
when (buffer.readByte()) {
|
||||
REDEEM_TYPE_TOKEN -> {
|
||||
PARTICLE_SPAWN.spawn(Point(pos, 9), rand)
|
||||
}
|
||||
|
@@ -36,6 +36,7 @@ abstract class TileEntityBasePortalController(type: TileEntityType<out TileEntit
|
||||
when (clientRenderState) {
|
||||
Invisible -> clientAnimationProgress.update(max(0F, clientAnimationProgress - clientAnimationFadeOutSpeed))
|
||||
is Animating -> clientAnimationProgress.update(min(1F, clientAnimationProgress + clientAnimationFadeInSpeed))
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -46,6 +46,13 @@ object BlockBuilders {
|
||||
explosionResistance = 0.6F
|
||||
}
|
||||
|
||||
val buildEndiumBlock = BlockBuilder(Materials.SOLID, MaterialColor.LAPIS, SoundType.METAL).apply {
|
||||
requiresTool = true
|
||||
harvestTool = Pair(IRON, PICKAXE)
|
||||
harvestHardness = 6.2F
|
||||
explosionResistance = 12.0F
|
||||
}
|
||||
|
||||
val buildEnderSol = BlockBuilder(Materials.SOLID, MaterialColor.WOOD, SoundType.GROUND.clone(pitch = 0.85F)).apply {
|
||||
requiresTool = true
|
||||
harvestTool = Pair(WOOD, SHOVEL)
|
||||
@@ -69,6 +76,16 @@ object BlockBuilders {
|
||||
explosionResistance = 4.2F
|
||||
}
|
||||
|
||||
val buildGloomrockBricks = buildGloomrock.clone {
|
||||
harvestHardness = 2.8F
|
||||
explosionResistance = 6.0F
|
||||
}
|
||||
|
||||
val buildGloomrockSmooth = buildGloomrock.clone {
|
||||
harvestHardness = 2.0F
|
||||
explosionResistance = 4.8F
|
||||
}
|
||||
|
||||
val buildGloomtorch = BlockBuilder(Materials.SOLID, MaterialColor.BLACK, SoundType.STONE).apply {
|
||||
explosionResistance = 0.3F
|
||||
lightLevel = 13
|
||||
@@ -116,6 +133,19 @@ object BlockBuilders {
|
||||
lightLevel = 15
|
||||
}
|
||||
|
||||
val buildObsidianTowerTop = buildObsidianVariationLit.clone {
|
||||
makeIndestructible()
|
||||
}
|
||||
|
||||
// Building (End Stone)
|
||||
|
||||
val buildEndStone = BlockBuilder(Materials.SOLID, MaterialColor.SAND, SoundType.STONE).apply {
|
||||
requiresTool = true
|
||||
harvestTool = Pair(WOOD, PICKAXE)
|
||||
harvestHardness = 3.0F
|
||||
explosionResistance = 9.0F
|
||||
}
|
||||
|
||||
// Building (Dark Loam)
|
||||
|
||||
val buildDarkLoam = BlockBuilder(Materials.SOLID, MaterialColor.BLACK, SoundType.GROUND).apply {
|
||||
@@ -132,6 +162,10 @@ object BlockBuilders {
|
||||
explosionResistance = 2.0F
|
||||
}
|
||||
|
||||
val buildWhitebarkPlanks = buildWhitebark.clone {
|
||||
explosionResistance = 3.0F
|
||||
}
|
||||
|
||||
// Building (Miner's Burial)
|
||||
|
||||
val buildMinersBurial = BlockBuilder(Materials.SOLID, MaterialColor.RED, SoundType.STONE).apply {
|
||||
@@ -141,6 +175,10 @@ object BlockBuilders {
|
||||
explosionResistance = 120F
|
||||
}
|
||||
|
||||
val buildMinersBurialIndestructible = buildMinersBurial.clone {
|
||||
makeIndestructible()
|
||||
}
|
||||
|
||||
// Fluids
|
||||
|
||||
val buildCauldron = BlockBuilder(Material.IRON, MaterialColor.STONE, SoundType.STONE).apply {
|
||||
@@ -150,11 +188,26 @@ object BlockBuilders {
|
||||
|
||||
// Interactive (Storage)
|
||||
|
||||
val buildJarODust = BlockBuilder(Materials.JAR_O_DUST, MaterialColor.ORANGE_TERRACOTTA, SoundType.METAL).apply {
|
||||
harvestHardness = 0.4F
|
||||
explosionResistance = 0F
|
||||
}
|
||||
|
||||
val buildLootChest = BlockBuilder(Materials.SOLID, MaterialColor.BLACK, SoundType.METAL).apply {
|
||||
makeIndestructible()
|
||||
lightLevel = 13
|
||||
}
|
||||
|
||||
// Interactive (Puzzle)
|
||||
|
||||
val buildPuzzleLogic = BlockBuilder(Materials.SOLID, MaterialColor.ADOBE /* RENAME ORANGE */, SoundType.STONE).apply {
|
||||
makeIndestructible()
|
||||
}
|
||||
|
||||
val buildPuzzleWall = buildPuzzleLogic.clone {
|
||||
lightLevel = 14
|
||||
}
|
||||
|
||||
// Interactive (Gates)
|
||||
|
||||
val buildExperienceGate = BlockBuilder(Materials.SOLID, MaterialColor.GREEN, SoundType.METAL).apply {
|
||||
@@ -164,6 +217,8 @@ object BlockBuilders {
|
||||
|
||||
// Interactive (Uncategorized)
|
||||
|
||||
val buildIgneousPlate = BlockBuilder(Materials.IGNEOUS_ROCK_PLATE, MaterialColor.AIR, SoundType.STONE)
|
||||
|
||||
val buildBrewingStand = BlockBuilder(Material.IRON, MaterialColor.YELLOW, SoundType.STONE).apply {
|
||||
isSolid = false
|
||||
harvestHardness = 0.5F
|
||||
@@ -177,6 +232,24 @@ object BlockBuilders {
|
||||
requiresTool = true
|
||||
}
|
||||
|
||||
val buildEndPowderOre = buildEndOre.clone {
|
||||
harvestTool = Pair(STONE, PICKAXE)
|
||||
harvestHardness = 2.0F
|
||||
explosionResistance = 5.4F
|
||||
}
|
||||
|
||||
val buildEndiumOre = buildEndOre.clone {
|
||||
harvestTool = Pair(IRON, PICKAXE)
|
||||
harvestHardness = 5.0F
|
||||
explosionResistance = 9.9F
|
||||
}
|
||||
|
||||
val buildStardustOre = buildEndOre.clone {
|
||||
harvestTool = Pair(STONE, PICKAXE)
|
||||
harvestHardness = 2.8F
|
||||
explosionResistance = 8.4F
|
||||
}
|
||||
|
||||
val buildIgneousRockOre = buildEndOre.clone {
|
||||
harvestTool = Pair(DIAMOND, PICKAXE)
|
||||
harvestHardness = 1.6F
|
||||
@@ -242,6 +315,25 @@ object BlockBuilders {
|
||||
noDrops = true
|
||||
}
|
||||
|
||||
// Portals
|
||||
|
||||
val buildPortalInner = BlockBuilder(Material.PORTAL, MaterialColor.BLACK, SoundType.STONE).apply {
|
||||
makeIndestructible()
|
||||
isSolid = false
|
||||
lightLevel = 15
|
||||
}
|
||||
|
||||
val buildPortalFrame = BlockBuilder(Materials.SOLID, MaterialColor.SAND, SoundType.STONE).apply {
|
||||
makeIndestructible()
|
||||
}
|
||||
|
||||
val buildPortalFrameCrafted = BlockBuilder(Materials.SOLID, MaterialColor.SAND, SoundType.STONE).apply {
|
||||
requiresTool = true
|
||||
harvestTool = Pair(DIAMOND, PICKAXE)
|
||||
harvestHardness = 1.7F
|
||||
explosionResistance = 1.7F
|
||||
}
|
||||
|
||||
// Energy
|
||||
|
||||
val buildEnergyCluster = BlockBuilder(Materials.ENERGY_CLUSTER, MaterialColor.SNOW, SoundType.GLASS.clone(volume = 1.25F, pitch = 1.35F)).apply {
|
||||
@@ -250,6 +342,12 @@ object BlockBuilders {
|
||||
noDrops = true
|
||||
}
|
||||
|
||||
val buildCorruptedEnergy = BlockBuilder(Materials.CORRUPTED_ENERGY, MaterialColor.PURPLE, SoundType.SAND).apply {
|
||||
isSolid = false
|
||||
randomTicks = true // just to be safe
|
||||
noDrops = true
|
||||
}
|
||||
|
||||
// Tables
|
||||
|
||||
val buildTablePedestal = buildGloomrock.clone {
|
||||
@@ -274,6 +372,14 @@ object BlockBuilders {
|
||||
lightLevel = 15
|
||||
}
|
||||
|
||||
val buildScaffolding = BlockBuilder(Materials.SCAFFOLDING, MaterialColor.AIR, SoundType.STONE).apply {
|
||||
makeIndestructible()
|
||||
isSolid = false
|
||||
isOpaque = false
|
||||
suffocates = false
|
||||
blocksVision = false
|
||||
}
|
||||
|
||||
// Overrides
|
||||
|
||||
val buildEndPortalOverride = BlockBuilder(Material.PORTAL, MaterialColor.BLACK, SoundType.STONE).apply {
|
||||
|
@@ -23,8 +23,9 @@ import chylex.hee.network.client.PacketClientMoveYourAss
|
||||
import chylex.hee.network.client.PacketClientRotateInstantly
|
||||
import chylex.hee.network.client.PacketClientTeleportInstantly
|
||||
import chylex.hee.util.buffer.readCompactVec
|
||||
import chylex.hee.util.buffer.use
|
||||
import chylex.hee.util.buffer.readEnum
|
||||
import chylex.hee.util.buffer.writeCompactVec
|
||||
import chylex.hee.util.buffer.writeEnum
|
||||
import chylex.hee.util.math.Pos
|
||||
import chylex.hee.util.math.Vec
|
||||
import chylex.hee.util.math.addY
|
||||
@@ -78,16 +79,16 @@ class Teleporter(
|
||||
private val soundVolume: Float,
|
||||
private val extraRange: Float = 0F,
|
||||
) : IFxData {
|
||||
override fun write(buffer: PacketBuffer) = buffer.use {
|
||||
writeCompactVec(startPoint)
|
||||
writeCompactVec(endPoint)
|
||||
writeByte((width * 10F).floorToInt().coerceIn(0, 100))
|
||||
writeByte((height * 10F).floorToInt().coerceIn(0, 100))
|
||||
override fun write(buffer: PacketBuffer) {
|
||||
buffer.writeCompactVec(startPoint)
|
||||
buffer.writeCompactVec(endPoint)
|
||||
buffer.writeByte((width * 10F).floorToInt().coerceIn(0, 100))
|
||||
buffer.writeByte((height * 10F).floorToInt().coerceIn(0, 100))
|
||||
|
||||
writeRegistryId(soundEvent)
|
||||
writeEnumValue(soundCategory)
|
||||
writeByte((soundVolume * 10F).floorToInt().coerceIn(0, 250))
|
||||
writeByte(extraRange.floorToInt().coerceIn(0, 255))
|
||||
buffer.writeRegistryId(soundEvent)
|
||||
buffer.writeEnum(soundCategory)
|
||||
buffer.writeByte((soundVolume * 10F).floorToInt().coerceIn(0, 250))
|
||||
buffer.writeByte(extraRange.floorToInt().coerceIn(0, 255))
|
||||
}
|
||||
|
||||
fun send(world: World) {
|
||||
@@ -99,20 +100,20 @@ class Teleporter(
|
||||
}
|
||||
|
||||
val FX_TELEPORT = object : IFxHandler<FxTeleportData> {
|
||||
override fun handle(buffer: PacketBuffer, world: World, rand: Random) = buffer.use {
|
||||
override fun handle(buffer: PacketBuffer, world: World, rand: Random) {
|
||||
val player = MC.player ?: return
|
||||
val playerPos = player.posVec
|
||||
|
||||
val startPoint = readCompactVec()
|
||||
val endPoint = readCompactVec()
|
||||
val startPoint = buffer.readCompactVec()
|
||||
val endPoint = buffer.readCompactVec()
|
||||
|
||||
val halfWidth = (readByte() / 10F) * 0.5F
|
||||
val halfHeight = (readByte() / 10F) * 0.5F
|
||||
val halfWidth = (buffer.readByte() / 10F) * 0.5F
|
||||
val halfHeight = (buffer.readByte() / 10F) * 0.5F
|
||||
|
||||
val soundEvent = readRegistryIdSafe(SoundEvent::class.java)
|
||||
val soundCategory = readEnumValue(SoundCategory::class.java)
|
||||
val soundVolume = readByte() / 10F
|
||||
val soundRange = 16F + readByte()
|
||||
val soundEvent = buffer.readRegistryIdSafe(SoundEvent::class.java)
|
||||
val soundCategory = buffer.readEnum() ?: SoundCategory.NEUTRAL
|
||||
val soundVolume = buffer.readByte() / 10F
|
||||
val soundRange = 16F + buffer.readByte()
|
||||
|
||||
val soundPosition = if (playerPos.squareDistanceTo(startPoint) < playerPos.squareDistanceTo(endPoint))
|
||||
startPoint
|
||||
|
@@ -16,7 +16,6 @@ import chylex.hee.game.world.util.getTile
|
||||
import chylex.hee.game.world.util.removeBlock
|
||||
import chylex.hee.game.world.util.setState
|
||||
import chylex.hee.init.ModEntities
|
||||
import chylex.hee.util.buffer.use
|
||||
import chylex.hee.util.math.Pos
|
||||
import chylex.hee.util.math.Vec3
|
||||
import chylex.hee.util.math.subtractY
|
||||
@@ -86,12 +85,12 @@ open class EntityFallingBlockHeavy(type: EntityType<out EntityFallingBlockHeavy>
|
||||
return NetworkHooks.getEntitySpawningPacket(this)
|
||||
}
|
||||
|
||||
override fun writeSpawnData(buffer: PacketBuffer) = buffer.use {
|
||||
writeInt(fallTile?.let(Block::getStateId) ?: 0)
|
||||
override fun writeSpawnData(buffer: PacketBuffer) {
|
||||
buffer.writeInt(fallTile?.let(Block::getStateId) ?: 0)
|
||||
}
|
||||
|
||||
override fun readSpawnData(buffer: PacketBuffer) = buffer.use {
|
||||
fallTile = Block.getStateById(readInt())
|
||||
override fun readSpawnData(buffer: PacketBuffer) {
|
||||
fallTile = Block.getStateById(buffer.readInt())
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
|
@@ -18,7 +18,6 @@ import chylex.hee.init.ModEntities
|
||||
import chylex.hee.init.ModSounds
|
||||
import chylex.hee.network.client.PacketClientFX
|
||||
import chylex.hee.util.buffer.readPos
|
||||
import chylex.hee.util.buffer.use
|
||||
import chylex.hee.util.buffer.writePos
|
||||
import chylex.hee.util.math.Pos
|
||||
import chylex.hee.util.random.nextFloat
|
||||
@@ -45,16 +44,16 @@ class EntityFallingObsidian : EntityFallingBlockHeavy {
|
||||
private val DAMAGE = Damage(PEACEFUL_EXCLUSION, ARMOR_PROTECTION(false), ENCHANTMENT_PROTECTION)
|
||||
|
||||
class FxFallData(private val pos: BlockPos, private val volume: Float) : IFxData {
|
||||
override fun write(buffer: PacketBuffer) = buffer.use {
|
||||
writePos(pos)
|
||||
writeFloat(volume)
|
||||
override fun write(buffer: PacketBuffer) {
|
||||
buffer.writePos(pos)
|
||||
buffer.writeFloat(volume)
|
||||
}
|
||||
}
|
||||
|
||||
val FX_FALL = object : IFxHandler<FxFallData> {
|
||||
override fun handle(buffer: PacketBuffer, world: World, rand: Random) = buffer.use {
|
||||
val pos = readPos()
|
||||
val volume = readFloat()
|
||||
override fun handle(buffer: PacketBuffer, world: World, rand: Random) {
|
||||
val pos = buffer.readPos()
|
||||
val volume = buffer.readFloat()
|
||||
|
||||
repeat(2) {
|
||||
ModSounds.BLOCK_OBSIDIAN_LAND.playClient(pos, SoundCategory.BLOCKS, volume = volume, pitch = rand.nextFloat(0.8F, 1.2F))
|
||||
|
@@ -24,8 +24,7 @@ import chylex.hee.init.ModEntities
|
||||
import chylex.hee.system.heeTag
|
||||
import chylex.hee.util.math.Vec
|
||||
import chylex.hee.util.math.center
|
||||
import chylex.hee.util.math.range
|
||||
import chylex.hee.util.math.remapRange
|
||||
import chylex.hee.util.math.remap
|
||||
import chylex.hee.util.nbt.TagCompound
|
||||
import chylex.hee.util.nbt.use
|
||||
import chylex.hee.util.random.nextFloat
|
||||
@@ -269,9 +268,9 @@ class EntityInfusedTNT : TNTEntity {
|
||||
val waterRatio = foundWaterBlocks.size.toFloat() / totalCountedBlocks
|
||||
|
||||
val dropAmount = when {
|
||||
waterRatio < 0.1 -> remapRange(waterRatio, range(0.0F, 0.1F), range(1.0F, 1.6F))
|
||||
waterRatio < 0.4 -> remapRange(waterRatio, range(0.1F, 0.4F), range(1.6F, 4.0F))
|
||||
else -> remapRange(waterRatio, range(0.4F, 1.0F), range(4.0F, 5.8F))
|
||||
waterRatio < 0.1 -> waterRatio.remap(fromMin = 0.0F, fromMax = 0.1F, toMin = 1.0F, toMax = 1.6F)
|
||||
waterRatio < 0.4 -> waterRatio.remap(fromMin = 0.1F, fromMax = 0.4F, toMin = 1.6F, toMax = 4.0F)
|
||||
else -> waterRatio.remap(fromMin = 0.4F, fromMax = 1.0F, toMin = 4.0F, toMax = 5.8F)
|
||||
}
|
||||
|
||||
val lootTable = Environment.getLootTable(LootTables.GAMEPLAY_FISHING)
|
||||
|
@@ -5,7 +5,6 @@ import chylex.hee.game.particle.spawner.properties.IOffset.Constant
|
||||
import chylex.hee.game.particle.spawner.properties.IOffset.InBox
|
||||
import chylex.hee.game.particle.spawner.properties.IShape.Point
|
||||
import chylex.hee.init.ModEntities
|
||||
import chylex.hee.util.buffer.use
|
||||
import chylex.hee.util.math.square
|
||||
import net.minecraft.entity.EntityType
|
||||
import net.minecraft.item.ItemStack
|
||||
@@ -33,12 +32,12 @@ class EntityItemFreshlyCooked : EntityItemBase, IEntityAdditionalSpawnData {
|
||||
)
|
||||
}
|
||||
|
||||
override fun writeSpawnData(buffer: PacketBuffer) = buffer.use {
|
||||
writeShort(age)
|
||||
override fun writeSpawnData(buffer: PacketBuffer) {
|
||||
buffer.writeShort(age)
|
||||
}
|
||||
|
||||
override fun readSpawnData(buffer: PacketBuffer) = buffer.use {
|
||||
age = readShort().toInt()
|
||||
override fun readSpawnData(buffer: PacketBuffer) {
|
||||
age = buffer.readShort().toInt()
|
||||
}
|
||||
|
||||
override fun tick() {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user