1
0
mirror of https://github.com/chylex/Hardcore-Ender-Expansion-2.git synced 2025-09-16 08:24:48 +02:00

2 Commits

Author SHA1 Message Date
1135c192bb TODOs 2022-06-20 18:33:28 +02:00
8933d8d8cc WIP 2022-06-20 18:28:11 +02:00
94 changed files with 2218 additions and 1272 deletions

View File

@@ -580,6 +580,8 @@ e66091a13a6e7593eb5bd971978d24a5a0e375b3 data/hee/loot_tables/blocks/whitebark.j
9bd3a9e24162d2c81047b834f8f79d6cabec86be data/hee/loot_tables/blocks/whitebark_planks.json 9bd3a9e24162d2c81047b834f8f79d6cabec86be data/hee/loot_tables/blocks/whitebark_planks.json
7d84dc443a052e349593b71d2c0a523e75396cdf data/hee/loot_tables/blocks/whitebark_slab.json 7d84dc443a052e349593b71d2c0a523e75396cdf data/hee/loot_tables/blocks/whitebark_slab.json
83e0b81adb3f9dd488397e8459b95f7b0ce19927 data/hee/loot_tables/blocks/whitebark_stairs.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 f5996244831ab38fe1fae2f304bbd7825d6ad98b data/minecraft/tags/blocks/bamboo_plantable_on.json
479189f9b35a3c8f795539daf6a1809130242c5b data/minecraft/tags/blocks/flower_pots.json 479189f9b35a3c8f795539daf6a1809130242c5b data/minecraft/tags/blocks/flower_pots.json
424e2e03cf62f23f4496468a97b9f0df060df9fe data/minecraft/tags/blocks/impermeable.json 424e2e03cf62f23f4496468a97b9f0df060df9fe data/minecraft/tags/blocks/impermeable.json

View File

@@ -0,0 +1,17 @@
{
"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"
]
}

View File

@@ -0,0 +1,7 @@
{
"replace": false,
"values": [
"hee:void_portal_frame_crafted",
"hee:void_portal_storage_crafted"
]
}

View File

@@ -37,7 +37,7 @@ import net.minecraftforge.common.data.ExistingFileHelper
class BlockModels(generator: DataGenerator, modid: String, existingFileHelper: ExistingFileHelper) : BlockModelProvider(generator, modid, existingFileHelper) { class BlockModels(generator: DataGenerator, modid: String, existingFileHelper: ExistingFileHelper) : BlockModelProvider(generator, modid, existingFileHelper) {
override fun registerModels() { override fun registerModels() {
for (block in ModBlocks.ALL) { for (block in ModBlocks.ALL) {
(block as? IHeeBlock)?.model?.let { registerModel(block, it.blockModel) { builder -> builder } } (block as? IHeeBlock)?.let { registerModel(block, it.model.generate(block).blockModel) { builder -> builder } }
} }
} }

View File

@@ -32,7 +32,7 @@ import net.minecraftforge.common.data.ExistingFileHelper
class BlockStates(generator: DataGenerator, modid: String, existingFileHelper: ExistingFileHelper) : BlockStateProvider(generator, modid, existingFileHelper) { class BlockStates(generator: DataGenerator, modid: String, existingFileHelper: ExistingFileHelper) : BlockStateProvider(generator, modid, existingFileHelper) {
override fun registerStatesAndModels() { override fun registerStatesAndModels() {
for (block in ModBlocks.ALL) { for (block in ModBlocks.ALL) {
(block as? IHeeBlock)?.model?.let { registerState(block, it.blockState) } (block as? IHeeBlock)?.let { registerState(block, it.model.generate(block).blockState) }
} }
} }

View File

@@ -39,15 +39,13 @@ import net.minecraftforge.common.data.ExistingFileHelper
class ItemModels(generator: DataGenerator, modid: String, existingFileHelper: ExistingFileHelper) : ItemModelProvider(generator, modid, existingFileHelper) { class ItemModels(generator: DataGenerator, modid: String, existingFileHelper: ExistingFileHelper) : ItemModelProvider(generator, modid, existingFileHelper) {
override fun registerModels() { override fun registerModels() {
for (item in ModItems.ALL) { for (item in ModItems.ALL) {
(item as? IHeeItem)?.model?.let { (item as? IHeeItem)?.let { registerModel(item, it.model) }
registerModel(item, it)
}
} }
for (block in ModBlocks.ALL) { for (block in ModBlocks.ALL) {
(block as? IHeeBlock)?.model?.itemModel?.let { (block as? IHeeBlock)
registerModel(if (it.asItem) block.asItem() else block, it.model) ?.let { it.model.generate(block).itemModel }
} ?.let { registerModel(if (it.asItem) block.asItem() else block, it.model) }
} }
} }

View File

@@ -6,8 +6,6 @@ import chylex.hee.client.DebugMenu
import chylex.hee.client.GameModeToggle import chylex.hee.client.GameModeToggle
import chylex.hee.client.TerritoryVoidDebug import chylex.hee.client.TerritoryVoidDebug
import chylex.hee.game.block.BlockScaffoldingDebug 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.CommandClientDebugToggles
import chylex.hee.game.command.client.CommandClientScaffolding import chylex.hee.game.command.client.CommandClientScaffolding
import chylex.hee.game.command.server.CommandServerInstability import chylex.hee.game.command.server.CommandServerInstability
@@ -45,9 +43,8 @@ internal object Debug : IDebugModule {
CommandServerTestWorld CommandServerTestWorld
) )
override fun createScaffoldingBlock(builder: BlockBuilder): HeeBlock { override val scaffoldingBlockBehavior
return BlockScaffoldingDebug(builder) get() = BlockScaffoldingDebug
}
@SubscribeEvent @SubscribeEvent
fun onClientSetup(@Suppress("UNUSED_PARAMETER") e: FMLClientSetupEvent) { fun onClientSetup(@Suppress("UNUSED_PARAMETER") e: FMLClientSetupEvent) {

View File

@@ -2,7 +2,7 @@ package chylex.hee.game.block
import chylex.hee.debug.PowerShell import chylex.hee.debug.PowerShell
import chylex.hee.game.Environment import chylex.hee.game.Environment
import chylex.hee.game.block.properties.BlockBuilder import chylex.hee.game.block.components.IPlayerUseBlockComponent
import chylex.hee.game.command.client.CommandClientScaffolding import chylex.hee.game.command.client.CommandClientScaffolding
import chylex.hee.game.world.generation.structure.file.StructureFile import chylex.hee.game.world.generation.structure.file.StructureFile
import chylex.hee.game.world.generation.util.WorldToStructureWorldAdapter import chylex.hee.game.world.generation.util.WorldToStructureWorldAdapter
@@ -27,14 +27,13 @@ import net.minecraft.util.Direction.WEST
import net.minecraft.util.Hand import net.minecraft.util.Hand
import net.minecraft.util.Util import net.minecraft.util.Util
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.BlockRayTraceResult
import net.minecraft.util.text.StringTextComponent import net.minecraft.util.text.StringTextComponent
import net.minecraft.util.text.TextFormatting import net.minecraft.util.text.TextFormatting
import net.minecraft.world.World import net.minecraft.world.World
import java.nio.file.Files import java.nio.file.Files
class BlockScaffoldingDebug(builder: BlockBuilder) : BlockScaffolding(builder) { object BlockScaffoldingDebug : IPlayerUseBlockComponent {
override fun onBlockActivated(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hit: BlockRayTraceResult): ActionResultType { override fun use(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand): ActionResultType {
if (world.isRemote && player.isSneaking && !player.abilities.isFlying) { if (world.isRemote && player.isSneaking && !player.abilities.isFlying) {
val palette = CommandClientScaffolding.currentPalette val palette = CommandClientScaffolding.currentPalette
@@ -54,7 +53,7 @@ class BlockScaffoldingDebug(builder: BlockBuilder) : BlockScaffolding(builder) {
val box = BoundingBox(minPos, maxPos) val box = BoundingBox(minPos, maxPos)
val serverWorld = Environment.getDimension(world.dimensionKey) val serverWorld = Environment.getDimension(world.dimensionKey)
val (structureTag, missingMappings) = StructureFile.save(WorldToStructureWorldAdapter(serverWorld, serverWorld.rand, box.min), box.size, palette, this) val (structureTag, missingMappings) = StructureFile.save(WorldToStructureWorldAdapter(serverWorld, serverWorld.rand, box.min), box.size, palette, state.block)
val structureFile = Files.createTempDirectory("HardcoreEnderExpansion_Structure_").resolve(CommandClientScaffolding.currentFile).toFile() val structureFile = Files.createTempDirectory("HardcoreEnderExpansion_Structure_").resolve(CommandClientScaffolding.currentFile).toFile()
CompressedStreamTools.write(structureTag, structureFile) CompressedStreamTools.write(structureTag, structureFile)

View File

@@ -5,7 +5,7 @@ import chylex.hee.game.block.properties.BlockDrop
import net.minecraft.block.Block import net.minecraft.block.Block
import net.minecraft.loot.LootTables import net.minecraft.loot.LootTables
open class HeeBlock(builder: BlockBuilder) : Block(builder.p), IHeeBlock { open class HeeBlock(builder: BlockBuilder) : Block(builder.p), IHeeBlock { // TODO abstract
override val drop override val drop
get() = if (lootTable == LootTables.EMPTY) BlockDrop.Nothing else BlockDrop.Self get() = if (lootTable == LootTables.EMPTY) BlockDrop.Nothing else BlockDrop.Self
} }

View File

@@ -0,0 +1,5 @@
package chylex.hee.game.block
import net.minecraft.block.Block
abstract class HeeBlock2(properties: Properties) : Block(properties), IHeeBlock

View File

@@ -0,0 +1,229 @@
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)
}
}

View File

@@ -1,12 +1,13 @@
package chylex.hee.game.block package chylex.hee.game.block
import chylex.hee.client.text.LocalizationStrategy 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.BlockDrop
import chylex.hee.game.block.properties.BlockModel import chylex.hee.game.block.properties.BlockModel
import chylex.hee.game.block.properties.BlockRenderLayer import chylex.hee.game.block.properties.BlockRenderLayer
import chylex.hee.game.block.properties.BlockRenderLayer.SOLID import chylex.hee.game.block.properties.BlockRenderLayer.SOLID
import chylex.hee.game.block.properties.BlockTint import chylex.hee.game.block.properties.BlockTint
import chylex.hee.game.block.properties.IBlockStateModel import chylex.hee.game.block.properties.IBlockStateModelSupplier
import net.minecraft.block.Block import net.minecraft.block.Block
import net.minecraft.tags.ITag.INamedTag import net.minecraft.tags.ITag.INamedTag
@@ -17,7 +18,7 @@ interface IHeeBlock {
val localizationExtra: Map<String, String> val localizationExtra: Map<String, String>
get() = emptyMap() get() = emptyMap()
val model: IBlockStateModel val model: IBlockStateModelSupplier
get() = BlockModel.Cube get() = BlockModel.Cube
val renderLayer: BlockRenderLayer val renderLayer: BlockRenderLayer
@@ -31,4 +32,14 @@ interface IHeeBlock {
val tags: List<INamedTag<Block>> val tags: List<INamedTag<Block>>
get() = emptyList() 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()
}
} }

View File

@@ -0,0 +1,149 @@
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
}

View File

@@ -0,0 +1,26 @@
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)

View File

@@ -0,0 +1,86 @@
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 }
}
}

View File

@@ -0,0 +1,23 @@
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)
}
}

View File

@@ -0,0 +1,50 @@
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)
}
}
}

View File

@@ -0,0 +1,9 @@
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)
}

View File

@@ -0,0 +1,10 @@
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) {}
}

View File

@@ -0,0 +1,10 @@
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)
}

View File

@@ -0,0 +1,15 @@
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
}
}

View File

@@ -0,0 +1,7 @@
package chylex.hee.game.block.components
import net.minecraft.tileentity.TileEntity
fun interface IBlockEntityComponent {
fun create(): TileEntity
}

View File

@@ -0,0 +1,7 @@
package chylex.hee.game.block.components
import java.util.Random
fun interface IBlockExperienceComponent {
fun getExperience(rand: Random): Int
}

View File

@@ -0,0 +1,11 @@
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)
}

View File

@@ -0,0 +1,8 @@
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
}

View File

@@ -0,0 +1,19 @@
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
}
}
}

View File

@@ -0,0 +1,10 @@
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)
}

View File

@@ -0,0 +1,21 @@
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) {}
}

View File

@@ -0,0 +1,10 @@
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)
}

View File

@@ -0,0 +1,19 @@
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
}

View File

@@ -0,0 +1,30 @@
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)
}
}
}

View File

@@ -0,0 +1,11 @@
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
}

View File

@@ -0,0 +1,20 @@
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
}
}
}

View File

@@ -0,0 +1,12 @@
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
}

View File

@@ -0,0 +1,10 @@
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
}

View File

@@ -0,0 +1,9 @@
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]
}
}

View File

@@ -0,0 +1,6 @@
package chylex.hee.game.block.interfaces
/**
* Marks interfaces that can be attached to blocks.
*/
interface IBlockInterface

View File

@@ -0,0 +1,15 @@
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()
}

View File

@@ -0,0 +1,7 @@
package chylex.hee.game.block.interfaces
internal object NoBlockInterfaces : IBlockWithInterfaces {
override fun getInterface(type: Class<out IBlockInterface>): Any? {
return null
}
}

View File

@@ -1,9 +1,10 @@
package chylex.hee.game.block.logic package chylex.hee.game.block.logic
import chylex.hee.game.block.interfaces.IBlockInterface
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.world.IBlockReader import net.minecraft.world.IBlockReader
interface IBlockDynamicHardness { interface IBlockDynamicHardness : IBlockInterface {
fun getBlockHardness(world: IBlockReader, pos: BlockPos, state: BlockState, originalHardness: Float): Float fun getBlockHardness(world: IBlockReader, pos: BlockPos, state: BlockState, originalHardness: Float): Float
} }

View File

@@ -0,0 +1,11 @@
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)
}
}

View File

@@ -0,0 +1,21 @@
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)
}
}

View File

@@ -1,7 +1,13 @@
package chylex.hee.game.block.properties package chylex.hee.game.block.properties
interface IBlockStateModel { import net.minecraft.block.Block
interface IBlockStateModel : IBlockStateModelSupplier {
val blockState: BlockStatePreset val blockState: BlockStatePreset
val blockModel: BlockModel val blockModel: BlockModel
val itemModel: BlockItemModel? val itemModel: BlockItemModel?
override fun generate(block: Block): IBlockStateModel {
return this
}
} }

View File

@@ -0,0 +1,7 @@
package chylex.hee.game.block.properties
import net.minecraft.block.Block
fun interface IBlockStateModelSupplier {
fun generate(block: Block): IBlockStateModel
}

View File

@@ -0,0 +1,19 @@
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)
}
}
}

View File

@@ -2,8 +2,8 @@ package chylex.hee.game.item.components
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.util.text.ITextComponent import net.minecraft.util.text.ITextComponent
import net.minecraft.world.World import net.minecraft.world.IBlockReader
fun interface ITooltipComponent { fun interface ITooltipComponent {
fun add(lines: MutableList<ITextComponent>, stack: ItemStack, advanced: Boolean, world: World?) fun add(lines: MutableList<ITextComponent>, stack: ItemStack, advanced: Boolean, world: IBlockReader?)
} }

View File

@@ -2,10 +2,10 @@ package chylex.hee.game.item.components
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.util.text.ITextComponent import net.minecraft.util.text.ITextComponent
import net.minecraft.world.World import net.minecraft.world.IBlockReader
class StaticTooltipComponent(private vararg val lines: ITextComponent) : ITooltipComponent { class StaticTooltipComponent(private vararg val lines: ITextComponent) : ITooltipComponent {
override fun add(lines: MutableList<ITextComponent>, stack: ItemStack, advanced: Boolean, world: World?) { override fun add(lines: MutableList<ITextComponent>, stack: ItemStack, advanced: Boolean, world: IBlockReader?) {
lines.addAll(this.lines) lines.addAll(this.lines)
} }
} }

View File

@@ -1,13 +1,11 @@
package chylex.hee.system package chylex.hee.system
import chylex.hee.game.block.HeeBlock import chylex.hee.game.block.components.IPlayerUseBlockComponent
import chylex.hee.game.block.properties.BlockBuilder
import chylex.hee.game.command.IClientCommand import chylex.hee.game.command.IClientCommand
import chylex.hee.game.command.ICommand import chylex.hee.game.command.ICommand
interface IDebugModule { interface IDebugModule {
val clientCommands: List<IClientCommand> val clientCommands: List<IClientCommand>
val serverCommands: List<ICommand> val serverCommands: List<ICommand>
val scaffoldingBlockBehavior: IPlayerUseBlockComponent?
fun createScaffoldingBlock(builder: BlockBuilder): HeeBlock
} }

View File

@@ -0,0 +1,16 @@
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
}

View File

@@ -10,6 +10,7 @@ import chylex.hee.client.util.MC
import chylex.hee.game.Resource import chylex.hee.game.Resource
import chylex.hee.game.block.BlockAbstractPortal import chylex.hee.game.block.BlockAbstractPortal
import chylex.hee.game.block.entity.TileEntityEnergyCluster 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.block.properties.Materials
import chylex.hee.game.mechanics.energy.IClusterOracleItem import chylex.hee.game.mechanics.energy.IClusterOracleItem
import chylex.hee.game.mechanics.energy.IEnergyQuantity import chylex.hee.game.mechanics.energy.IEnergyQuantity
@@ -35,7 +36,7 @@ import net.minecraftforge.client.event.RenderGameOverlayEvent
import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType.HELMET import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType.HELMET
@SubscribeAllEvents(Side.CLIENT, modid = HEE.ID) @SubscribeAllEvents(Side.CLIENT, modid = HEE.ID)
object OverlayRenderer { object OverlayRenderer { // TODO move to appropriate block builders
private const val BORDER_SIZE = 4 private const val BORDER_SIZE = 4
private const val LINE_SPACING = 7 private const val LINE_SPACING = 7
@@ -147,7 +148,7 @@ object OverlayRenderer {
clusterLookedAt = pos.getTile(world) clusterLookedAt = pos.getTile(world)
e.isCanceled = true e.isCanceled = true
} }
else if (block is BlockAbstractPortal) { else if (block.getHeeInterface<BlockAbstractPortal.IInnerPortalBlock>() != null) {
e.isCanceled = true e.isCanceled = true
} }
} }

View File

@@ -1,9 +1,9 @@
package chylex.hee.client.render.block package chylex.hee.client.render.block
import chylex.hee.game.block.BlockAbstractPortal 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.ITerritoryInstanceFactory
import chylex.hee.game.block.BlockVoidPortalInner.IVoidPortalController 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.HUB
import chylex.hee.game.block.BlockVoidPortalInner.Type.RETURN_ACTIVE import chylex.hee.game.block.BlockVoidPortalInner.Type.RETURN_ACTIVE
import chylex.hee.game.block.entity.TileEntityPortalInner import chylex.hee.game.block.entity.TileEntityPortalInner

View File

@@ -0,0 +1,51 @@
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)
}

View File

@@ -1,11 +1,15 @@
package chylex.hee.game.block package chylex.hee.game.block
import chylex.hee.client.text.LocalizationStrategy import chylex.hee.client.text.LocalizationStrategy
import chylex.hee.game.block.properties.BlockBuilder 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.BlockModel import chylex.hee.game.block.properties.BlockModel
import chylex.hee.game.block.properties.BlockStateModel import chylex.hee.game.block.properties.BlockStateModel
import chylex.hee.game.block.properties.BlockStatePreset import chylex.hee.game.block.properties.BlockStatePreset
import chylex.hee.game.block.util.asVoxelShape import chylex.hee.game.entity.util.EntityPortalContact
import chylex.hee.game.world.util.Facing4 import chylex.hee.game.world.util.Facing4
import chylex.hee.game.world.util.allInBox import chylex.hee.game.world.util.allInBox
import chylex.hee.game.world.util.allInBoxMutable import chylex.hee.game.world.util.allInBoxMutable
@@ -24,25 +28,27 @@ import net.minecraft.block.Block
import net.minecraft.block.BlockRenderType.INVISIBLE import net.minecraft.block.BlockRenderType.INVISIBLE
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.block.Blocks 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.entity.Entity
import net.minecraft.tags.BlockTags import net.minecraft.tags.BlockTags
import net.minecraft.tileentity.TileEntity import net.minecraft.tileentity.TileEntity
import net.minecraft.util.math.AxisAlignedBB
import net.minecraft.util.math.BlockPos 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.VoxelShape
import net.minecraft.world.IBlockReader import net.minecraft.util.math.shapes.VoxelShapes
import net.minecraft.world.World import net.minecraft.world.World
abstract class BlockAbstractPortal(builder: BlockBuilder) : BlockSimpleShaped(builder, AxisAlignedBB(0.0, 0.0, 0.0, 1.0, 0.75, 1.0)) { class BlockAbstractPortal(impl: IInnerPortalBlock) : HeeBlockBuilder() {
companion object { companion object {
const val MAX_DISTANCE_FROM_FRAME = 6.0 const val MAX_DISTANCE_FROM_FRAME = 6.0
const val MAX_SIZE = 5 const val MAX_SIZE = 5
const val TRANSLATION_SPEED_LONG = 600000L private const val TRANSLATION_SPEED_LONG = 600000L
const val TRANSLATION_SPEED_INV = 1.0 / TRANSLATION_SPEED_LONG const val TRANSLATION_SPEED_INV = 1.0 / TRANSLATION_SPEED_LONG
private val COLLISION_AABB = AxisAlignedBB(0.0, 0.0, 0.0, 1.0, 0.025, 1.0).asVoxelShape 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)
fun findInnerArea(world: World, controllerPos: BlockPos, frameBlock: Block): Pair<BlockPos, BlockPos>? { fun findInnerArea(world: World, controllerPos: BlockPos, frameBlock: Block): Pair<BlockPos, BlockPos>? {
val mirrorRange = 1..(MAX_SIZE + 1) val mirrorRange = 1..(MAX_SIZE + 1)
@@ -94,36 +100,52 @@ abstract class BlockAbstractPortal(builder: BlockBuilder) : BlockSimpleShaped(bu
} }
} }
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 { interface IPortalController {
val clientAnimationProgress: LerpedFloat val clientAnimationProgress: LerpedFloat
val clientPortalOffset: 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
} }

View File

@@ -5,11 +5,18 @@ import chylex.hee.game.Resource.location
import chylex.hee.game.block.BlockCorruptedEnergy.SpawnResult.FAIL import chylex.hee.game.block.BlockCorruptedEnergy.SpawnResult.FAIL
import chylex.hee.game.block.BlockCorruptedEnergy.SpawnResult.PASSTHROUGH import chylex.hee.game.block.BlockCorruptedEnergy.SpawnResult.PASSTHROUGH
import chylex.hee.game.block.BlockCorruptedEnergy.SpawnResult.SUCCESS 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.entity.TileEntityEnergyCluster
import chylex.hee.game.block.properties.BlockBuilder import chylex.hee.game.block.properties.BlockDrop
import chylex.hee.game.block.properties.BlockModel import chylex.hee.game.block.properties.BlockModel
import chylex.hee.game.block.properties.BlockStateModel import chylex.hee.game.block.properties.BlockStateModel
import chylex.hee.game.block.properties.BlockStatePreset 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.Property
import chylex.hee.game.block.util.with import chylex.hee.game.block.util.with
import chylex.hee.game.entity.CustomCreatureType import chylex.hee.game.entity.CustomCreatureType
@@ -35,60 +42,123 @@ import chylex.hee.game.world.util.getTile
import chylex.hee.game.world.util.removeBlock import chylex.hee.game.world.util.removeBlock
import chylex.hee.game.world.util.setState import chylex.hee.game.world.util.setState
import chylex.hee.init.ModBlocks 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.nextInt
import chylex.hee.util.random.removeItem import chylex.hee.util.random.removeItem
import net.minecraft.block.Block
import net.minecraft.block.BlockRenderType.INVISIBLE import net.minecraft.block.BlockRenderType.INVISIBLE
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.block.Blocks import net.minecraft.block.Blocks
import net.minecraft.entity.Entity import net.minecraft.block.SoundType
import net.minecraft.block.material.MaterialColor
import net.minecraft.entity.LivingEntity import net.minecraft.entity.LivingEntity
import net.minecraft.state.StateContainer.Builder
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.world.IBlockReader
import net.minecraft.world.World import net.minecraft.world.World
import net.minecraft.world.server.ServerWorld
import java.util.Random import java.util.Random
class BlockCorruptedEnergy(builder: BlockBuilder) : HeeBlock(builder) { object BlockCorruptedEnergy : HeeBlockBuilder() {
companion object { private const val MIN_LEVEL = 0
private const val MIN_LEVEL = 0 private const val MAX_LEVEL = 20
private const val MAX_LEVEL = 20
private const val MAX_TICK_RATE = 5 private const val MAX_TICK_RATE = 5
private const val MIN_TICK_RATE = 1 private const val MIN_TICK_RATE = 1
val LEVEL = Property.int("level", MIN_LEVEL..MAX_LEVEL) val LEVEL = Property.int("level", MIN_LEVEL..MAX_LEVEL)
private val DAMAGE_PART_NORMAL = Damage(DIFFICULTY_SCALING, ARMOR_PROTECTION(false), ENCHANTMENT_PROTECTION) private val DAMAGE_PART_NORMAL = Damage(DIFFICULTY_SCALING, ARMOR_PROTECTION(false), ENCHANTMENT_PROTECTION)
private val DAMAGE_PART_MAGIC = Damage(MAGIC_TYPE, NUDITY_DANGER, RAPID_DAMAGE(2)) private val DAMAGE_PART_MAGIC = Damage(MAGIC_TYPE, NUDITY_DANGER, RAPID_DAMAGE(2))
private val PARTICLE_CORRUPTION = ParticleSpawnerCustom( private val PARTICLE_CORRUPTION = ParticleSpawnerCustom(
type = ParticleCorruptedEnergy, type = ParticleCorruptedEnergy,
pos = InBox(0.75F), pos = InBox(0.75F),
mot = InBox(0.05F), mot = InBox(0.05F),
hideOnMinimalSetting = false hideOnMinimalSetting = false
) )
private fun tickRateForLevel(level: Int): Int { init {
return (MAX_TICK_RATE - (level / 2)).coerceAtLeast(MIN_TICK_RATE) 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
}
}
} }
private fun isEntityTolerant(entity: LivingEntity): Boolean { components.scheduledTick = object : IBlockScheduledTickComponent {
return CustomCreatureType.isDemon(entity) || CustomCreatureType.isShadow(entity) || entity is IImmuneToCorruptedEnergy 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
} }
override val localization private fun isEntityTolerant(entity: LivingEntity): Boolean {
get() = LocalizationStrategy.None return CustomCreatureType.isDemon(entity) || CustomCreatureType.isShadow(entity) || entity is IImmuneToCorruptedEnergy
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 // Utility methods
@@ -97,19 +167,19 @@ class BlockCorruptedEnergy(builder: BlockBuilder) : HeeBlock(builder) {
SUCCESS, PASSTHROUGH, FAIL SUCCESS, PASSTHROUGH, FAIL
} }
fun spawnCorruptedEnergy(world: World, pos: BlockPos, level: Int): SpawnResult { fun spawn(world: World, pos: BlockPos, level: Int): SpawnResult {
if (level < MIN_LEVEL) { if (level < MIN_LEVEL) {
return FAIL return FAIL
} }
else if (level > MAX_LEVEL) { else if (level > MAX_LEVEL) {
return spawnCorruptedEnergy(world, pos, MAX_LEVEL) return spawn(world, pos, MAX_LEVEL)
} }
val currentState = pos.getState(world) val currentState = pos.getState(world)
val currentBlock = currentState.block val currentBlock = currentState.block
var updateFlags = FLAG_SYNC_CLIENT var updateFlags = FLAG_SYNC_CLIENT
if (currentBlock === this) { if (currentBlock === ModBlocks.CORRUPTED_ENERGY) {
if (level - currentState[LEVEL] < 3 || world.rand.nextBoolean()) { if (level - currentState[LEVEL] < 3 || world.rand.nextBoolean()) {
return FAIL return FAIL
} }
@@ -130,88 +200,7 @@ class BlockCorruptedEnergy(builder: BlockBuilder) : HeeBlock(builder) {
PASSTHROUGH PASSTHROUGH
} }
pos.setState(world, this.with(LEVEL, level), updateFlags) pos.setState(world, ModBlocks.CORRUPTED_ENERGY.with(LEVEL, level), updateFlags)
return SUCCESS 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
} }

View File

@@ -1,56 +1,53 @@
package chylex.hee.game.block 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.entity.TileEntityEndPortalAcceptor
import chylex.hee.game.block.properties.BlockBuilder
import chylex.hee.game.block.properties.BlockModel import chylex.hee.game.block.properties.BlockModel
import chylex.hee.game.world.util.getTile import chylex.hee.game.world.util.getTile
import chylex.hee.init.ModBlocks import chylex.hee.init.ModBlocks
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.entity.player.PlayerEntity import net.minecraft.entity.player.PlayerEntity
import net.minecraft.tileentity.TileEntity
import net.minecraft.util.ActionResultType import net.minecraft.util.ActionResultType
import net.minecraft.util.ActionResultType.PASS import net.minecraft.util.ActionResultType.PASS
import net.minecraft.util.ActionResultType.SUCCESS import net.minecraft.util.ActionResultType.SUCCESS
import net.minecraft.util.Direction
import net.minecraft.util.Direction.UP import net.minecraft.util.Direction.UP
import net.minecraft.util.Hand import net.minecraft.util.Hand
import net.minecraft.util.math.BlockPos 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 import net.minecraft.world.World
class BlockEndPortalAcceptor(builder: BlockBuilder) : BlockPortalFrame(builder) { object BlockEndPortalAcceptor : HeeBlockBuilder() {
override val model init {
get() = BlockModel.PortalFrame(ModBlocks.END_PORTAL_FRAME, "acceptor") includeFrom(BlockPortalFrameIndestructible)
override fun hasTileEntity(state: BlockState): Boolean { model = BlockModel.PortalFrame(ModBlocks.END_PORTAL_FRAME, "acceptor")
return true
}
override fun createTileEntity(state: BlockState, world: IBlockReader): TileEntity { components.entity = IBlockEntityComponent(::TileEntityEndPortalAcceptor)
return TileEntityEndPortalAcceptor()
}
override fun onBlockAdded(state: BlockState, world: World, pos: BlockPos, oldState: BlockState, isMoving: Boolean) { components.onAdded = IBlockAddedComponent { _, world, pos ->
BlockAbstractPortal.spawnInnerBlocks(world, pos, ModBlocks.END_PORTAL_FRAME, ModBlocks.END_PORTAL_INNER, minSize = 1) BlockAbstractPortal.spawnInnerBlocks(world, pos, ModBlocks.END_PORTAL_FRAME, ModBlocks.END_PORTAL_INNER, minSize = 1)
}
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
} }
return PASS components.setStateFromNeighbor = ISetBlockStateFromNeighbor { state, world, pos, neighborFacing, _ ->
} if (!world.isRemote && neighborFacing == UP) {
pos.getTile<TileEntityEndPortalAcceptor>(world)?.refreshClusterState()
} // TODO neighbor changed?
override fun updatePostPlacement(state: BlockState, facing: Direction, neighborState: BlockState, world: IWorld, pos: BlockPos, neighborPos: BlockPos): BlockState { state
if (!world.isRemote && facing == UP) {
pos.getTile<TileEntityEndPortalAcceptor>(world)?.refreshClusterState()
} }
@Suppress("DEPRECATION") components.playerUse = object : IPlayerUseBlockComponent {
return super.updatePostPlacement(state, facing, neighborState, world, pos, neighborPos) override fun use(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand): ActionResultType {
if (player.isCreative && player.isSneaking) {
pos.getTile<TileEntityEndPortalAcceptor>(world)?.toggleChargeFromCreativeMode()
return SUCCESS
}
return PASS
}
}
} }
} }

View File

@@ -1,10 +1,10 @@
package chylex.hee.game.block package chylex.hee.game.block
import chylex.hee.HEE 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.TileEntityEndPortalAcceptor
import chylex.hee.game.block.entity.TileEntityPortalInner 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.CausatumStage
import chylex.hee.game.mechanics.causatum.EnderCausatum import chylex.hee.game.mechanics.causatum.EnderCausatum
import chylex.hee.game.world.isEndDimension import chylex.hee.game.world.isEndDimension
@@ -12,41 +12,39 @@ import chylex.hee.game.world.server.DimensionTeleporter
import chylex.hee.game.world.util.closestTickingTile import chylex.hee.game.world.util.closestTickingTile
import chylex.hee.init.ModBlocks import chylex.hee.init.ModBlocks
import chylex.hee.util.math.Pos import chylex.hee.util.math.Pos
import net.minecraft.block.BlockState
import net.minecraft.entity.Entity import net.minecraft.entity.Entity
import net.minecraft.entity.player.PlayerEntity import net.minecraft.entity.player.PlayerEntity
import net.minecraft.tileentity.TileEntity import net.minecraft.tileentity.TileEntity
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.world.IBlockReader
import net.minecraft.world.World import net.minecraft.world.World
class BlockEndPortalInner(builder: BlockBuilder) : BlockAbstractPortal(builder) { object BlockEndPortalInner : HeeBlockBuilder() {
override fun createTileEntity(state: BlockState, world: IBlockReader): TileEntity { init {
return TileEntityPortalInner.End() includeFrom(BlockAbstractPortal(object : IInnerPortalBlock {
} override fun createTileEntity(): TileEntity {
return TileEntityPortalInner.End()
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, MAX_DISTANCE_FROM_FRAME)
if (acceptor != null && acceptor.isCharged) {
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))
}
if (entity is PlayerEntity) {
EnderCausatum.triggerStage(entity, CausatumStage.S2_ENTERED_END)
}
DimensionTeleporter.changeDimension(entity, HEE.dim, DimensionTeleporter.EndSpawnPortal)
} }
}
override fun teleportEntity(world: World, pos: BlockPos, entity: Entity) {
if (world.isEndDimension) {
DimensionTeleporter.changeDimension(entity, World.OVERWORLD, DimensionTeleporter.LastEndPortal)
}
else {
val acceptor = pos.closestTickingTile<TileEntityEndPortalAcceptor>(world, BlockAbstractPortal.MAX_DISTANCE_FROM_FRAME)
if (acceptor != null && acceptor.isCharged) {
BlockAbstractPortal.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))
}
if (entity is PlayerEntity) {
EnderCausatum.triggerStage(entity, CausatumStage.S2_ENTERED_END)
}
DimensionTeleporter.changeDimension(entity, HEE.dim, DimensionTeleporter.EndSpawnPortal)
}
}
}
}))
} }
} }

View File

@@ -1,22 +1,23 @@
package chylex.hee.game.block package chylex.hee.game.block
import chylex.hee.game.block.properties.BlockBuilder import chylex.hee.game.block.builder.HeeBlockBuilder
import chylex.hee.game.block.components.IBlockExperienceComponent
import chylex.hee.game.block.properties.BlockDrop 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 chylex.hee.util.random.nextInt
import net.minecraft.block.BlockState import net.minecraftforge.common.ToolType.PICKAXE
import net.minecraft.util.math.BlockPos
import net.minecraft.world.IWorldReader
import net.minecraft.world.World
import net.minecraftforge.common.Tags
class BlockEndPowderOre(builder: BlockBuilder) : HeeBlock(builder) { object BlockEndPowderOre : HeeBlockBuilder() {
override val drop init {
get() = BlockDrop.Manual includeFrom(BlockEndOre)
override val tags drop = BlockDrop.Manual
get() = listOf(Tags.Blocks.ORES)
override fun getExpDrop(state: BlockState, world: IWorldReader, pos: BlockPos, fortune: Int, silktouch: Int): Int { tool = BlockHarvestTool.required(STONE, PICKAXE)
return ((world as? World)?.rand ?: RANDOM).nextInt(1, 2) hardness = BlockHardness(hardness = 2F, resistance = 5.4F)
components.experience = IBlockExperienceComponent { rand -> rand.nextInt(1, 2) }
} }
} }

View File

@@ -2,22 +2,48 @@ package chylex.hee.game.block
import chylex.hee.client.text.LocalizationStrategy import chylex.hee.client.text.LocalizationStrategy
import chylex.hee.game.Resource.location import chylex.hee.game.Resource.location
import chylex.hee.game.block.properties.BlockBuilder 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.BlockModel 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.Blocks
import net.minecraft.block.material.MaterialColor import net.minecraft.block.material.MaterialColor
import net.minecraftforge.common.Tags import net.minecraftforge.common.Tags
import net.minecraftforge.common.ToolType.PICKAXE
class BlockEndStoneCustom(builder: BlockBuilder, mapColor: MaterialColor) : HeeBlock(builder.clone { color = mapColor }) { object BlockEndStoneCustom : HeeBlockBuilder() {
override val localization init {
get() = LocalizationStrategy.MoveToBeginning(wordCount = 1) includeFrom(BlockEndStoneBase)
override val model localization = LocalizationStrategy.MoveToBeginning(wordCount = 1)
get() = BlockModel.WithTextures(
BlockModel.CubeBottomTop(bottom = Blocks.END_STONE.location),
mapOf("particle" to this.location("_top"))
)
override val tags model = IBlockStateModelSupplier {
get() = listOf(Tags.Blocks.END_STONES) BlockModel.WithTextures(
BlockModel.CubeBottomTop(bottom = Blocks.END_STONE.location),
mapOf("particle" to it.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
}
} }

View File

@@ -1,26 +1,48 @@
package chylex.hee.game.block package chylex.hee.game.block
import chylex.hee.game.block.properties.BlockBuilder import chylex.hee.game.block.builder.HeeBlockBuilder
import net.minecraft.block.BlockState import chylex.hee.game.block.components.IBlockHarvestabilityComponent
import net.minecraft.entity.player.PlayerEntity 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 net.minecraft.item.Items import net.minecraft.item.Items
import net.minecraft.util.Hand.MAIN_HAND 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.Tags
import net.minecraftforge.common.ToolType.PICKAXE
sealed class BlockEndium(builder: BlockBuilder) : HeeBlock(builder) { abstract class BlockEndium : HeeBlockBuilder() {
override fun canHarvestBlock(state: BlockState, world: IBlockReader, pos: BlockPos, player: PlayerEntity): Boolean { init {
return super.canHarvestBlock(state, world, pos, player) || player.getHeldItem(MAIN_HAND).item === Items.GOLDEN_PICKAXE 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
}
} }
class Ore(builder: BlockBuilder) : BlockEndium(builder) { object Ore : BlockEndium() {
override val tags init {
get() = listOf(Tags.Blocks.ORES) includeFrom(BlockEndOre)
hardness = BlockHardness(hardness = 5F, resistance = 9.9F)
}
} }
class Block(builder: BlockBuilder) : BlockEndium(builder) { object Block : BlockEndium() {
override val tags init {
get() = listOf(Tags.Blocks.STORAGE_BLOCKS) color = MaterialColor.LAPIS
sound = SoundType.METAL
tags.add(Tags.Blocks.STORAGE_BLOCKS)
hardness = BlockHardness(hardness = 6.2F, resistance = 12F)
}
} }
} }

View File

@@ -9,7 +9,6 @@ import chylex.hee.game.mechanics.instability.Instability
import chylex.hee.game.world.util.allInCenteredSphereMutable import chylex.hee.game.world.util.allInCenteredSphereMutable
import chylex.hee.game.world.util.getTile import chylex.hee.game.world.util.getTile
import chylex.hee.game.world.util.removeBlock import chylex.hee.game.world.util.removeBlock
import chylex.hee.init.ModBlocks
import chylex.hee.init.ModItems import chylex.hee.init.ModItems
import chylex.hee.util.forge.Side import chylex.hee.util.forge.Side
import chylex.hee.util.forge.Sided import chylex.hee.util.forge.Sided
@@ -43,7 +42,7 @@ class BlockEnergyCluster(builder: BlockBuilder) : BlockSimpleShaped(builder, Axi
val units = amount.units.value.toFloat() val units = amount.units.value.toFloat()
val corruptedEnergyLevel = (2F + (units.pow(0.74F) / 9F)).ceilToInt() val corruptedEnergyLevel = (2F + (units.pow(0.74F) / 9F)).ceilToInt()
ModBlocks.CORRUPTED_ENERGY.spawnCorruptedEnergy(world, pos, corruptedEnergyLevel) BlockCorruptedEnergy.spawn(world, pos, corruptedEnergyLevel)
if (causeInstability) { if (causeInstability) {
Instability.get(world).triggerAction((10 + 2 * corruptedEnergyLevel).toUShort(), pos) Instability.get(world).triggerAction((10 + 2 * corruptedEnergyLevel).toUShort(), pos)
@@ -57,7 +56,7 @@ class BlockEnergyCluster(builder: BlockBuilder) : BlockSimpleShaped(builder, Axi
val corruptedEnergyLevel = (2F + (units.pow(0.74F) / 9F)).ceilToInt() val corruptedEnergyLevel = (2F + (units.pow(0.74F) / 9F)).ceilToInt()
for (testPos in pos.allInCenteredSphereMutable(corruptedEnergyRadius)) { for (testPos in pos.allInCenteredSphereMutable(corruptedEnergyRadius)) {
ModBlocks.CORRUPTED_ENERGY.spawnCorruptedEnergy(world, testPos, corruptedEnergyLevel) BlockCorruptedEnergy.spawn(world, testPos, corruptedEnergyLevel)
} }
} }
} }

View File

@@ -1,35 +1,74 @@
package chylex.hee.game.block package chylex.hee.game.block
import chylex.hee.HEE import chylex.hee.HEE
import chylex.hee.game.block.properties.BlockBuilder 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.entity.technical.EntityTechnicalTrigger import chylex.hee.game.entity.technical.EntityTechnicalTrigger
import chylex.hee.game.entity.technical.EntityTechnicalTrigger.Types.ENERGY_SHRINE_GLOBAL import chylex.hee.game.entity.technical.EntityTechnicalTrigger.Types.ENERGY_SHRINE_GLOBAL
import chylex.hee.game.entity.util.posVec import chylex.hee.game.entity.util.posVec
import chylex.hee.game.entity.util.selectEntities 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.game.world.generation.feature.energyshrine.EnergyShrinePieces
import chylex.hee.init.ModTags
import chylex.hee.util.forge.EventResult
import chylex.hee.util.math.center import chylex.hee.util.math.center
import net.minecraft.block.BlockState import net.minecraft.block.SoundType
import net.minecraft.block.material.MaterialColor
import net.minecraft.entity.EntitySpawnPlacementRegistry.PlacementType import net.minecraft.entity.EntitySpawnPlacementRegistry.PlacementType
import net.minecraft.entity.EntityType import net.minecraft.entity.EntityType
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.world.IBlockReader import net.minecraft.world.IBlockReader
import net.minecraft.world.IEntityReader import net.minecraft.world.IEntityReader
open class BlockGloomrock(builder: BlockBuilder) : HeeBlock(builder) { object BlockGloomrock : HeeBlockBuilder() {
override fun canCreatureSpawn(state: BlockState, world: IBlockReader, pos: BlockPos, type: PlacementType?, entityType: EntityType<*>?): Boolean { init {
if (world !is IEntityReader) { material = Materials.SOLID
HEE.log.warn("[BlockGloomrock] attempted to check spawn on a world != IEntityReader (${world.javaClass})") color = MaterialColor.BLACK
return false 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 {
if (world !is IEntityReader) {
HEE.log.warn("[BlockGloomrock] attempted to check spawn on a world != IEntityReader (${world.javaClass})")
return EventResult.DENY
}
val center = pos.center
val size = EnergyShrinePieces.STRUCTURE_SIZE
val trigger = world
.selectEntities
.inBox<EntityTechnicalTrigger>(size.toCenteredBoundingBox(center))
.find { it.triggerType == ENERGY_SHRINE_GLOBAL }
return EventResult(trigger == null || !size.toCenteredBoundingBox(trigger.posVec).contains(center))
}
} }
}
val center = pos.center val BRICKS = HeeBlockBuilder {
val size = EnergyShrinePieces.STRUCTURE_SIZE includeFrom(BlockGloomrock)
hardness = BlockHardness(hardness = 2.8F, resistance = 6F)
}
val trigger = world val SMOOTH = HeeBlockBuilder {
.selectEntities includeFrom(BlockGloomrock)
.inBox<EntityTechnicalTrigger>(size.toCenteredBoundingBox(center)) localization = LocalizationStrategy.MoveToBeginning(wordCount = 1)
.find { it.triggerType == ENERGY_SHRINE_GLOBAL } hardness = BlockHardness(hardness = 2F, resistance = 4.8F)
}
return trigger == null || !size.toCenteredBoundingBox(trigger.posVec).contains(center) val SMOOTH_COLORED = HeeBlockBuilder {
includeFrom(SMOOTH)
localization = LocalizationStrategy.MoveToBeginning(LocalizationStrategy.DeleteWords("Smooth"), wordCount = 1)
} }
} }

View File

@@ -1,9 +0,0 @@
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)
}

View File

@@ -1,9 +0,0 @@
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)
}

View File

@@ -1,31 +1,37 @@
package chylex.hee.game.block package chylex.hee.game.block
import chylex.hee.game.Resource.location 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.entity.TileEntityIgneousPlate
import chylex.hee.game.block.logic.IBlockDynamicHardness 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.BlockModel
import chylex.hee.game.block.properties.BlockStateModel import chylex.hee.game.block.properties.BlockStateModel
import chylex.hee.game.block.properties.BlockStatePreset 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.FURNACE_FACING
import chylex.hee.game.block.util.Property 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.entity.technical.EntityTechnicalIgneousPlateLogic
import chylex.hee.game.item.properties.ItemModel import chylex.hee.game.item.properties.ItemModel
import chylex.hee.game.world.util.Facing6 import chylex.hee.game.world.util.Facing6
import chylex.hee.game.world.util.getState import chylex.hee.game.world.util.getState
import chylex.hee.game.world.util.getTile import chylex.hee.game.world.util.getTile
import net.minecraft.block.Block
import net.minecraft.block.BlockRenderType.ENTITYBLOCK_ANIMATED import net.minecraft.block.BlockRenderType.ENTITYBLOCK_ANIMATED
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.block.Blocks 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.entity.player.PlayerEntity
import net.minecraft.item.BlockItemUseContext import net.minecraft.item.BlockItemUseContext
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.item.Items import net.minecraft.item.Items
import net.minecraft.state.StateContainer.Builder
import net.minecraft.tileentity.FurnaceTileEntity import net.minecraft.tileentity.FurnaceTileEntity
import net.minecraft.tileentity.TileEntity
import net.minecraft.util.ActionResultType import net.minecraft.util.ActionResultType
import net.minecraft.util.ActionResultType.PASS import net.minecraft.util.ActionResultType.PASS
import net.minecraft.util.ActionResultType.SUCCESS import net.minecraft.util.ActionResultType.SUCCESS
@@ -37,139 +43,114 @@ import net.minecraft.util.Direction.SOUTH
import net.minecraft.util.Direction.UP import net.minecraft.util.Direction.UP
import net.minecraft.util.Direction.WEST import net.minecraft.util.Direction.WEST
import net.minecraft.util.Hand 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.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.VoxelShape
import net.minecraft.util.math.shapes.VoxelShapes
import net.minecraft.world.IBlockReader import net.minecraft.world.IBlockReader
import net.minecraft.world.IWorld
import net.minecraft.world.IWorldReader import net.minecraft.world.IWorldReader
import net.minecraft.world.World import net.minecraft.world.World
class BlockIgneousPlate(builder: BlockBuilder) : HeeBlock(builder), IBlockDynamicHardness { object BlockIgneousPlate : HeeBlockBuilder() {
companion object { val FACING_NOT_DOWN = Property.facing("facing", Facing6.minusElement(DOWN))
val FACING_NOT_DOWN = Property.facing("facing", Facing6.minusElement(DOWN))
private const val BB_SIDE_MIN = 0.125 private const val BB_SIDE_MIN = 0.125
private const val BB_SIDE_MAX = 0.875 private const val BB_SIDE_MAX = 0.875
private const val BB_TOP = 0.125 private const val BB_TOP = 0.125
private val BOUNDING_BOX = mapOf( private val BOUNDING_BOX = mapOf(
UP to AxisAlignedBB(BB_SIDE_MIN, 0.0, BB_SIDE_MIN, BB_SIDE_MAX, BB_TOP, BB_SIDE_MAX).asVoxelShape, UP to VoxelShapes.create(BB_SIDE_MIN, 0.0, BB_SIDE_MIN, BB_SIDE_MAX, BB_TOP, BB_SIDE_MAX),
NORTH to AxisAlignedBB(BB_SIDE_MIN, BB_SIDE_MIN, 1.0 - BB_TOP, BB_SIDE_MAX, BB_SIDE_MAX, 1.0).asVoxelShape, NORTH to VoxelShapes.create(BB_SIDE_MIN, BB_SIDE_MIN, 1.0 - BB_TOP, BB_SIDE_MAX, BB_SIDE_MAX, 1.0),
SOUTH to AxisAlignedBB(BB_SIDE_MIN, BB_SIDE_MIN, 0.0, BB_SIDE_MAX, BB_SIDE_MAX, BB_TOP).asVoxelShape, SOUTH to VoxelShapes.create(BB_SIDE_MIN, BB_SIDE_MIN, 0.0, BB_SIDE_MAX, BB_SIDE_MAX, BB_TOP),
EAST to AxisAlignedBB(0.0, BB_SIDE_MIN, BB_SIDE_MIN, BB_TOP, BB_SIDE_MAX, BB_SIDE_MAX).asVoxelShape, EAST to VoxelShapes.create(0.0, BB_SIDE_MIN, BB_SIDE_MIN, BB_TOP, BB_SIDE_MAX, BB_SIDE_MAX),
WEST to AxisAlignedBB(1.0 - BB_TOP, BB_SIDE_MIN, BB_SIDE_MIN, 1.0, BB_SIDE_MAX, BB_SIDE_MAX).asVoxelShape WEST to VoxelShapes.create(1.0 - BB_TOP, BB_SIDE_MIN, BB_SIDE_MIN, 1.0, BB_SIDE_MAX, BB_SIDE_MAX)
) )
private fun canPlacePlateAt(world: IWorldReader, pos: BlockPos, facing: Direction): Boolean {
val furnacePos = pos.offset(facing.opposite)
val state = furnacePos.getState(world)
return (
state.properties.contains(FURNACE_FACING) &&
state[FURNACE_FACING] != facing &&
furnacePos.getTile<FurnaceTileEntity>(world) != null
)
}
}
override val model
get() = BlockStateModel(BlockStatePreset.Simple, BlockModel.ParticleOnly(this.location), ItemModel.Simple)
init { init {
defaultState = stateContainer.baseState.with(FACING_NOT_DOWN, UP) model = IBlockStateModelSupplier {
} BlockStateModel(BlockStatePreset.Simple, BlockModel.ParticleOnly(it.location), ItemModel.Simple)
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 { material = Materials.IGNEOUS_ROCK_PLATE
val heldItem = player.getHeldItem(hand) color = MaterialColor.AIR
sound = SoundType.STONE
if (heldItem.item === Items.WATER_BUCKET) { components.states.set(FACING_NOT_DOWN, default = UP)
if (!world.isRemote && tryCoolPlate(world, pos, state) && !player.abilities.isCreativeMode) { components.states.facingProperty = FACING_NOT_DOWN
player.setHeldItem(hand, ItemStack(Items.BUCKET))
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) }
} }
return SUCCESS 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
}
} }
return PASS 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 { 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 return pos.offset(state[FACING_NOT_DOWN].opposite).getTile<FurnaceTileEntity>(world)?.let(EntityTechnicalIgneousPlateLogic.Companion::triggerCooling) == true
} }
// State handling private fun canPlacePlateAt(world: IWorldReader, pos: BlockPos, facing: Direction): Boolean {
val furnacePos = pos.offset(facing.opposite)
val state = furnacePos.getState(world)
override fun rotate(state: BlockState, rot: Rotation): BlockState { return (
return state.with(FACING_NOT_DOWN, rot.rotate(state[FACING_NOT_DOWN])) state.properties.contains(FURNACE_FACING) &&
state[FURNACE_FACING] != facing &&
furnacePos.getTile<FurnaceTileEntity>(world) != null
)
} }
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
} }

View File

@@ -1,14 +1,24 @@
package chylex.hee.game.block package chylex.hee.game.block
import chylex.hee.client.text.LocalizationStrategy 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.entity.TileEntityJarODust
import chylex.hee.game.block.properties.BlockBuilder
import chylex.hee.game.block.properties.BlockDrop 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.BlockModel
import chylex.hee.game.block.properties.BlockRenderLayer.TRANSLUCENT import chylex.hee.game.block.properties.BlockRenderLayer.TRANSLUCENT
import chylex.hee.game.block.properties.BlockStateModel import chylex.hee.game.block.properties.BlockStateModel
import chylex.hee.game.block.properties.BlockStatePreset 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.fx.util.playServer
import chylex.hee.game.item.components.ITooltipComponent
import chylex.hee.game.item.util.size import chylex.hee.game.item.util.size
import chylex.hee.game.mechanics.dust.DustLayers import chylex.hee.game.mechanics.dust.DustLayers
import chylex.hee.game.mechanics.dust.DustLayers.Side.BOTTOM import chylex.hee.game.mechanics.dust.DustLayers.Side.BOTTOM
@@ -16,164 +26,165 @@ import chylex.hee.game.mechanics.dust.DustLayers.Side.TOP
import chylex.hee.game.mechanics.dust.DustType import chylex.hee.game.mechanics.dust.DustType
import chylex.hee.game.world.util.getTile import chylex.hee.game.world.util.getTile
import chylex.hee.game.world.util.isTopSolid import chylex.hee.game.world.util.isTopSolid
import chylex.hee.init.ModBlocks
import chylex.hee.init.ModSounds import chylex.hee.init.ModSounds
import chylex.hee.system.heeTag import chylex.hee.system.heeTag
import chylex.hee.system.heeTagOrNull 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.math.center
import chylex.hee.util.nbt.getListOfCompounds import chylex.hee.util.nbt.getListOfCompounds
import chylex.hee.util.nbt.putList import chylex.hee.util.nbt.putList
import net.minecraft.block.Block
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.block.Blocks import net.minecraft.block.Blocks
import net.minecraft.client.util.ITooltipFlag import net.minecraft.block.SoundType
import net.minecraft.block.material.MaterialColor
import net.minecraft.entity.LivingEntity import net.minecraft.entity.LivingEntity
import net.minecraft.entity.player.PlayerEntity import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.loot.LootContext import net.minecraft.loot.LootContext.Builder
import net.minecraft.loot.LootParameters 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.PASS
import net.minecraft.util.ActionResultType.SUCCESS import net.minecraft.util.ActionResultType.SUCCESS
import net.minecraft.util.Direction
import net.minecraft.util.Direction.DOWN import net.minecraft.util.Direction.DOWN
import net.minecraft.util.Hand import net.minecraft.util.Hand
import net.minecraft.util.SoundCategory import net.minecraft.util.SoundCategory
import net.minecraft.util.math.AxisAlignedBB
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.BlockRayTraceResult import net.minecraft.util.math.shapes.VoxelShapes
import net.minecraft.util.math.RayTraceResult
import net.minecraft.util.text.ITextComponent import net.minecraft.util.text.ITextComponent
import net.minecraft.util.text.TranslationTextComponent import net.minecraft.util.text.TranslationTextComponent
import net.minecraft.world.Explosion import net.minecraft.world.Explosion
import net.minecraft.world.IBlockReader import net.minecraft.world.IBlockReader
import net.minecraft.world.IWorld
import net.minecraft.world.IWorldReader import net.minecraft.world.IWorldReader
import net.minecraft.world.World import net.minecraft.world.World
class BlockJarODust(builder: BlockBuilder) : BlockSimpleShaped(builder, AABB) { object BlockJarODust : HeeBlockBuilder() {
companion object { init {
val AABB = AxisAlignedBB(0.1875, 0.0, 0.1875, 0.8125, 0.84375, 0.8125) 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)))
}
}
}
components.shape = IBlockShapeComponent.of(VoxelShapes.create(0.1875, 0.0, 0.1875, 0.8125, 0.84375, 0.8125))
components.drops = object : IBlockDropsComponent {
override fun getDrops(state: BlockState, context: Builder): MutableList<ItemStack> {
val drop = (context.get(LootParameters.BLOCK_ENTITY) as? TileEntityJarODust)?.let(::getDrop)
return if (drop == null)
mutableListOf()
else
mutableListOf(drop)
}
override fun getPickBlock(state: BlockState, world: IBlockReader, pos: BlockPos): ItemStack? {
return pos.getTile<TileEntityJarODust>(world)?.let(::getDrop)
}
}
components.entity = IBlockEntityComponent(::TileEntityJarODust)
components.placement = object : IBlockPlacementComponent {
override fun isPositionValid(state: BlockState, world: IWorldReader, pos: BlockPos): Boolean {
return pos.down().isTopSolid(world)
}
override fun onPlacedBy(state: BlockState, world: World, pos: BlockPos, placer: LivingEntity?, stack: ItemStack) {
val list = stack.heeTagOrNull?.getListOfCompounds(TileEntityJarODust.LAYERS_TAG)
if (list != null) {
pos.getTile<TileEntityJarODust>(world)?.layers?.deserializeNBT(list)
}
}
}
components.setStateFromNeighbor = ISetBlockStateFromNeighbor { state, world, pos, neighborFacing, _ ->
if (neighborFacing == DOWN && !state.isValidPosition(world, pos))
Blocks.AIR.defaultState
else
state
}
components.playerUse = IPlayerUseBlockComponent { _, world, pos, player, hand ->
val heldItem = player.getHeldItem(hand)
val result = if (heldItem.isEmpty)
tryExtractDust(world, pos, player, hand)
else
tryInsertDust(world, pos, player, heldItem)
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)
}
}
} }
override val localization // ItemStack
get() = LocalizationStrategy.ReplaceWords("O", "o'")
override val localizationExtra
get() = mapOf("block.hee.jar_o_dust.tooltip.entry" to "§7%sx %s")
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? { fun getLayersFromStack(stack: ItemStack): DustLayers? {
return if (stack.item === this.asItem()) return if (stack.item === ModBlocks.JAR_O_DUST.asItem())
stack.heeTagOrNull?.getListOfCompounds(TileEntityJarODust.LAYERS_TAG)?.let { list -> DustLayers(TileEntityJarODust.DUST_CAPACITY).apply { deserializeNBT(list) } } stack.heeTagOrNull?.getListOfCompounds(TileEntityJarODust.LAYERS_TAG)?.let { list -> DustLayers(TileEntityJarODust.DUST_CAPACITY).apply { deserializeNBT(list) } }
else else
null null
} }
fun setLayersInStack(stack: ItemStack, layers: DustLayers) { fun setLayersInStack(stack: ItemStack, layers: DustLayers) {
if (stack.item === this.asItem()) { if (stack.item === ModBlocks.JAR_O_DUST.asItem()) {
stack.heeTag.putList(TileEntityJarODust.LAYERS_TAG, layers.serializeNBT()) stack.heeTag.putList(TileEntityJarODust.LAYERS_TAG, layers.serializeNBT())
} }
} }
// Placement
override fun isValidPosition(state: BlockState, world: IWorldReader, pos: BlockPos): Boolean {
@Suppress("DEPRECATION")
return super.isValidPosition(state, world, pos) && pos.down().isTopSolid(world)
}
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 // Drops
private fun getDrop(tile: TileEntityJarODust): ItemStack { private fun getDrop(tile: TileEntityJarODust): ItemStack {
return ItemStack(this).also { setLayersInStack(it, tile.layers) } return ItemStack(ModBlocks.JAR_O_DUST).also { setLayersInStack(it, tile.layers) }
}
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
mutableListOf()
}
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 // 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)
tryExtractDust(world, pos, player, hand)
else
tryInsertDust(world, pos, player, heldItem)
return if (result) SUCCESS else PASS
}
private fun tryExtractDust(world: World, pos: BlockPos, player: PlayerEntity, hand: Hand): Boolean { private fun tryExtractDust(world: World, pos: BlockPos, player: PlayerEntity, hand: Hand): Boolean {
if (world.isRemote) { if (world.isRemote) {
return true return true
} }
val removed = pos.getTile<TileEntityJarODust>(world)?.layers?.removeDust(if (player.isSneaking) BOTTOM else TOP) val removed = pos.getTile<TileEntityJarODust>(world)?.layers?.removeDust(if (player.isSneaking) BOTTOM else TOP)
if (removed != null) { if (removed != null) {
player.setHeldItem(hand, removed) player.setHeldItem(hand, removed)
} }
@@ -197,23 +208,4 @@ class BlockJarODust(builder: BlockBuilder) : BlockSimpleShaped(builder, AABB) {
return true 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)))
}
}
}
} }

View File

@@ -1,26 +1,18 @@
package chylex.hee.game.block package chylex.hee.game.block
import chylex.hee.client.text.LocalizationStrategy 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.entity.TileEntityMinersBurialAltar
import chylex.hee.game.block.properties.BlockBuilder
import chylex.hee.game.block.properties.BlockModel 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
class BlockMinersBurialAltar(builder: BlockBuilder) : BlockSimpleShaped(builder, AxisAlignedBB(0.0, 0.0, 0.0, 1.0, 0.75, 1.0)) { object BlockMinersBurialAltar : HeeBlockBuilder() {
override val localization init {
get() = LocalizationStrategy.ReplaceWords("Miners", "Miner's") includeFrom(BlockMinersBurialCube.INDESCRUCTIBLE)
override val model localization = LocalizationStrategy.ReplaceWords("Miners", "Miner's")
get() = BlockModel.Manual model = BlockModel.Manual
override fun hasTileEntity(state: BlockState): Boolean { components.entity = IBlockEntityComponent(::TileEntityMinersBurialAltar)
return true
}
override fun createTileEntity(state: BlockState, world: IBlockReader): TileEntity {
return TileEntityMinersBurialAltar()
} }
} }

View File

@@ -1,9 +1,29 @@
package chylex.hee.game.block package chylex.hee.game.block
import chylex.hee.client.text.LocalizationStrategy import chylex.hee.client.text.LocalizationStrategy
import chylex.hee.game.block.properties.BlockBuilder 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
class BlockMinersBurialCube(builder: BlockBuilder) : HeeBlock(builder) { object BlockMinersBurialCube : HeeBlockBuilder() {
override val localization init {
get() = LocalizationStrategy.Parenthesized(LocalizationStrategy.DeleteWords(LocalizationStrategy.ReplaceWords("Miners", "Miner's"), "Plain"), wordCount = 1, wordOffset = 3, fromStart = true) 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)
}
} }

View File

@@ -1,28 +1,50 @@
package chylex.hee.game.block package chylex.hee.game.block
import chylex.hee.client.text.LocalizationStrategy import chylex.hee.client.text.LocalizationStrategy
import chylex.hee.game.block.properties.BlockBuilder 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.BlockStateModels 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.Block
import net.minecraft.block.SoundType
import net.minecraft.block.material.MaterialColor
import net.minecraftforge.common.Tags import net.minecraftforge.common.Tags
import net.minecraftforge.common.ToolType.PICKAXE
open class BlockObsidianCube(builder: BlockBuilder) : HeeBlock(builder) { object BlockObsidianCube : HeeBlockBuilder() {
override val localization: LocalizationStrategy private val DEFAULT_LOCALIZATION = LocalizationStrategy.MoveToBeginning(wordCount = 1, wordOffset = 1, fromStart = true)
get() = LocalizationStrategy.MoveToBeginning(wordCount = 1, wordOffset = 1, fromStart = true)
final override val tags init {
get() = listOf(Tags.Blocks.OBSIDIAN) localization = DEFAULT_LOCALIZATION
open class Lit(builder: BlockBuilder, private val modelBlock: Block) : BlockObsidianCube(builder) { tags.add(Tags.Blocks.OBSIDIAN)
override val localization: LocalizationStrategy
get() = LocalizationStrategy.Parenthesized(super.localization, wordCount = 1, fromStart = false)
override val model material = Materials.SOLID
get() = BlockStateModels.Cube(modelBlock) color = MaterialColor.BLACK
sound = SoundType.STONE
tool = BlockHarvestTool.required(DIAMOND, PICKAXE)
hardness = BlockHardness(hardness = 20F, resistance = 300F)
} }
class TowerTop(builder: BlockBuilder, modelBlock: Block) : Lit(builder, modelBlock) { class Lit(modelBlock: Block) : HeeBlockBuilder() {
override val localization init {
get() = LocalizationStrategy.Default 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
}
} }
} }

View File

@@ -1,10 +0,0 @@
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")
}

View File

@@ -3,16 +3,20 @@ package chylex.hee.game.block
import chylex.hee.client.text.LocalizationStrategy import chylex.hee.client.text.LocalizationStrategy
import chylex.hee.client.util.MC import chylex.hee.client.util.MC
import chylex.hee.game.Resource 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.ACTIVE
import chylex.hee.game.block.BlockPuzzleLogic.State.DISABLED import chylex.hee.game.block.BlockPuzzleLogic.State.DISABLED
import chylex.hee.game.block.BlockPuzzleLogic.State.INACTIVE import chylex.hee.game.block.BlockPuzzleLogic.State.INACTIVE
import chylex.hee.game.block.properties.BlockBuilder 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.BlockModel import chylex.hee.game.block.properties.BlockModel
import chylex.hee.game.block.properties.BlockRenderLayer.CUTOUT import chylex.hee.game.block.properties.BlockRenderLayer.CUTOUT
import chylex.hee.game.block.properties.BlockStateModel import chylex.hee.game.block.properties.BlockStateModel
import chylex.hee.game.block.properties.BlockStatePreset import chylex.hee.game.block.properties.BlockStatePreset
import chylex.hee.game.block.properties.BlockTint import chylex.hee.game.block.properties.BlockTint
import chylex.hee.game.block.properties.IBlockStateModel import chylex.hee.game.block.properties.Materials
import chylex.hee.game.block.util.Property import chylex.hee.game.block.util.Property
import chylex.hee.game.block.util.withFacing import chylex.hee.game.block.util.withFacing
import chylex.hee.game.entity.util.posVec import chylex.hee.game.entity.util.posVec
@@ -46,9 +50,10 @@ import chylex.hee.util.random.nextFloat
import net.minecraft.block.Block import net.minecraft.block.Block
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.block.HorizontalBlock.HORIZONTAL_FACING 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.entity.Entity
import net.minecraft.item.BlockItemUseContext import net.minecraft.item.BlockItemUseContext
import net.minecraft.state.StateContainer.Builder
import net.minecraft.util.Direction import net.minecraft.util.Direction
import net.minecraft.util.Direction.NORTH import net.minecraft.util.Direction.NORTH
import net.minecraft.util.Direction.SOUTH import net.minecraft.util.Direction.SOUTH
@@ -60,7 +65,7 @@ import net.minecraft.world.IBlockDisplayReader
import net.minecraft.world.World import net.minecraft.world.World
import java.util.Random import java.util.Random
sealed class BlockPuzzleLogic(builder: BlockBuilder) : HeeBlock(builder) { class BlockPuzzleLogic(impl: IPuzzleLogic) : HeeBlockBuilder() {
companion object { companion object {
val STATE = Property.enum<State>("state") val STATE = Property.enum<State>("state")
@@ -101,7 +106,7 @@ sealed class BlockPuzzleLogic(builder: BlockBuilder) : HeeBlock(builder) {
var closest = pos var closest = pos
var closestDistSq = pos.distanceSqTo(player) var closestDistSq = pos.distanceSqTo(player)
for (testPos in pos.floodFill(Facing4) { it.getBlock(world) is BlockPuzzleLogic }) { for (testPos in pos.floodFill(Facing4) { isPuzzleBlock(it.getBlock(world)) }) {
PARTICLE_TOGGLE.spawn(Point(testPos, 3), rand) PARTICLE_TOGGLE.spawn(Point(testPos, 3), rand)
val distSq = testPos.distanceSqTo(player) val distSq = testPos.distanceSqTo(player)
@@ -123,8 +128,12 @@ sealed class BlockPuzzleLogic(builder: BlockBuilder) : HeeBlock(builder) {
} }
} }
private fun isPuzzleBlockEnabled(state: BlockState): Boolean { fun isPuzzleBlock(block: Block): Boolean {
return state.block is BlockPuzzleLogic && state[STATE] != DISABLED return block.getHeeInterface<IPuzzleLogic>() != null
}
fun isPuzzleBlockEnabled(state: BlockState): Boolean {
return isPuzzleBlock(state.block) && state[STATE] != DISABLED
} }
fun findAllBlocks(world: World, pos: BlockPos): List<BlockPos> { fun findAllBlocks(world: World, pos: BlockPos): List<BlockPos> {
@@ -204,6 +213,66 @@ sealed class BlockPuzzleLogic(builder: BlockBuilder) : HeeBlock(builder) {
mapOf("top" to Resource.Custom("block/puzzle_overlay_$itemSuffix")) 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 { enum class State(private val serializableName: String) : IStringSerializable {
@@ -223,159 +292,101 @@ sealed class BlockPuzzleLogic(builder: BlockBuilder) : HeeBlock(builder) {
} }
} }
abstract override val model: IBlockStateModel object Plain : HeeBlockBuilder() {
internal val LOGIC = IPuzzleLogic { _, pos, facing -> listOf(makePair(pos, facing)) }
final override val renderLayer init {
get() = CUTOUT includeFrom(BlockPuzzleLogic(LOGIC))
init { localization = LocalizationStrategy.Parenthesized(wordCount = 1, fromStart = false)
defaultState = stateContainer.baseState.with(STATE, ACTIVE) 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(builder: BlockBuilder, private val radius: Int) : BlockPuzzleLogic(builder) { class Burst(radius: Int) : HeeBlockBuilder() {
override val localization private val logic = IPuzzleLogic { world, pos, facing ->
get() = LocalizationStrategy.Parenthesized(LocalizationStrategy.ReplaceWords("$diameter", "${diameter}x${diameter}"), wordCount = 2, fromStart = false) pos.allInCenteredBox(radius, 0, radius).toList().flatMap { toggleAndChain(world, it, facing) }.distinct()
}
override val model init {
get() = createOverlayModel("burst_$diameter") includeFrom(BlockPuzzleLogic(logic))
private val diameter val diameter = 1 + (radius * 2)
get() = 1 + (radius * 2) localization = LocalizationStrategy.Parenthesized(LocalizationStrategy.ReplaceWords("$diameter", "${diameter}x${diameter}"), wordCount = 2, fromStart = false)
model = createOverlayModel("burst_$diameter")
}
private fun toggleAndChain(world: World, pos: BlockPos, facing: Direction): List<Pair<BlockPos, Direction>> { private fun toggleAndChain(world: World, pos: BlockPos, facing: Direction): List<Pair<BlockPos, Direction>> {
val state = pos.getState(world) val state = pos.getState(world)
val block = state.block val logic = state.block.getHeeInterface<IPuzzleLogic>()
return if (block !is BlockPuzzleLogic || !toggleState(world, pos, state) || block is Plain || block is Burst) return if (logic == null || !toggleState(world, pos, state) || logic === Plain.LOGIC || logic === this.logic)
emptyList() emptyList()
else else
block.getNextChains(world, pos, facing) logic.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()
} }
} }
sealed class RedirectSome private constructor(builder: BlockBuilder, private val blockDirections: Array<String>, private val itemDirection: String, private val directions: Array<Direction>) : BlockPuzzleLogic(builder) { private class RedirectSome(blockDirections: Array<String>, itemDirection: String, directions: Array<Direction>) : HeeBlockBuilder() {
class R1(builder: BlockBuilder) : RedirectSome(builder, arrayOf("n", "s", "e", "w"), "n", arrayOf(NORTH)) private val logic = BlockPuzzleLogic { world, pos, facing ->
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 rotation = pos.getState(world)[HORIZONTAL_FACING].horizontalIndex + NORTH.horizontalIndex
val exclude = facing.opposite val exclude = facing.opposite
return directions.map { Direction.byHorizontalIndex(it.horizontalIndex + rotation) }.filter { it != exclude }.map { makePair(pos, it) } 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)
}
}
} }
} }
class RedirectAll(builder: BlockBuilder) : BlockPuzzleLogic(builder) { object RedirectOne : HeeBlockBuilder() {
override val localization init {
get() = LocalizationStrategy.Parenthesized(wordCount = 2, fromStart = false) includeFrom(RedirectSome(arrayOf("n", "s", "e", "w"), "n", arrayOf(NORTH)))
override val model
get() = createOverlayModel("redirect_4")
override fun getNextChains(world: World, pos: BlockPos, facing: Direction): List<Pair<BlockPos, Direction>> {
return Facing4.filter { it != facing.opposite }.map { makePair(pos, it) }
} }
} }
class Teleport(builder: BlockBuilder) : BlockPuzzleLogic(builder) { object RedirectTwo : HeeBlockBuilder() {
override val localization init {
get() = LocalizationStrategy.Parenthesized(wordCount = 1, fromStart = false) includeFrom(RedirectSome(arrayOf("ns", "ew"), "ns", arrayOf(NORTH, SOUTH)))
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 object RedirectAll : HeeBlockBuilder() {
init {
includeFrom(BlockPuzzleLogic { _, pos, facing ->
Facing4.filter { it != facing.opposite }.map { makePair(pos, it) }
})
override val tint: BlockTint localization = LocalizationStrategy.Parenthesized(wordCount = 2, fromStart = false)
get() = Tint model = createOverlayModel("redirect_4")
}
}
private object Tint : BlockTint() { object Teleport : HeeBlockBuilder() {
@Sided(Side.CLIENT) private val logic = object : IPuzzleLogic {
override fun tint(state: BlockState, world: IBlockDisplayReader?, pos: BlockPos?, tintIndex: Int): Int { override fun getNextChains(world: World, pos: BlockPos, facing: Direction): List<Pair<BlockPos, Direction>> {
if (tintIndex != 1) { return findAllBlocks(world, pos).filter { it != pos && it.getBlock(world).getHeeInterface<IPuzzleLogic>() === this }.map { makePair(it, facing) }
return NO_TINT
} }
}
if (world == null && pos == null) { init {
return RGB(104, 58, 16).i // make the color slightly more visible in inventory includeFrom(BlockPuzzleLogic(logic))
}
return when (state[STATE]) { localization = LocalizationStrategy.Parenthesized(wordCount = 1, fromStart = false)
ACTIVE -> RGB(117, 66, 19).i model = createOverlayModel("teleport")
INACTIVE -> RGB(212, 157, 102).i
DISABLED -> RGB( 58, 40, 23).i
else -> NO_TINT
}
} }
} }
} }

View File

@@ -1,9 +1,20 @@
package chylex.hee.game.block package chylex.hee.game.block
import chylex.hee.client.text.LocalizationStrategy import chylex.hee.client.text.LocalizationStrategy
import chylex.hee.game.block.properties.BlockBuilder 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
class BlockPuzzleWall(builder: BlockBuilder) : HeeBlock(builder) { object BlockPuzzleWall : HeeBlockBuilder() {
override val localization init {
get() = LocalizationStrategy.Parenthesized(wordCount = 1, fromStart = false) includeFrom(BlockIndestructible)
localization = LocalizationStrategy.Parenthesized(wordCount = 1, fromStart = false)
material = Materials.SOLID
color = MaterialColor.ADOBE // RENAME ORANGE
sound = SoundType.STONE
light = 14
}
} }

View File

@@ -2,62 +2,55 @@ package chylex.hee.game.block
import chylex.hee.HEE import chylex.hee.HEE
import chylex.hee.game.Environment import chylex.hee.game.Environment
import chylex.hee.game.block.properties.BlockBuilder import chylex.hee.game.block.builder.HeeBlockBuilder
import chylex.hee.game.block.components.IBlockShapeComponent
import chylex.hee.game.block.properties.BlockModel import chylex.hee.game.block.properties.BlockModel
import chylex.hee.game.block.properties.BlockRenderLayer.CUTOUT import chylex.hee.game.block.properties.BlockRenderLayer.CUTOUT
import chylex.hee.util.forge.Side import chylex.hee.game.block.properties.Materials
import chylex.hee.util.forge.Sided
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.util.math.BlockPos import net.minecraft.block.SoundType
import net.minecraft.util.math.shapes.ISelectionContext import net.minecraft.block.material.MaterialColor
import net.minecraft.util.math.shapes.VoxelShape import net.minecraft.util.math.shapes.VoxelShape
import net.minecraft.util.math.shapes.VoxelShapes import net.minecraft.util.math.shapes.VoxelShapes
import net.minecraft.world.IBlockReader
open class BlockScaffolding protected constructor(builder: BlockBuilder) : HeeBlock(builder) { object BlockScaffolding : HeeBlockBuilder() {
companion object { var enableShape = true
var enableShape = true
fun create(builder: BlockBuilder): HeeBlock { init {
return HEE.debugModule?.createScaffoldingBlock(builder) ?: BlockScaffolding(builder) 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()
}
} }
}
override val model components.ambientOcclusionValue = 1F
get() = BlockModel.Manual
override val renderLayer components.playerUse = HEE.debugModule?.scaffoldingBlockBehavior
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
} }
} }

View File

@@ -2,42 +2,43 @@ package chylex.hee.game.block
import chylex.hee.game.Resource import chylex.hee.game.Resource
import chylex.hee.game.Resource.location import chylex.hee.game.Resource.location
import chylex.hee.game.block.properties.BlockBuilder import chylex.hee.game.block.builder.HeeBlockBuilder
import chylex.hee.game.block.components.IBlockExperienceComponent
import chylex.hee.game.block.properties.BlockDrop 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.BlockModel
import chylex.hee.game.block.properties.BlockRenderLayer.CUTOUT import chylex.hee.game.block.properties.BlockRenderLayer.CUTOUT
import chylex.hee.game.block.properties.BlockStateModel import chylex.hee.game.block.properties.BlockStateModel
import chylex.hee.game.block.properties.BlockStatePreset import chylex.hee.game.block.properties.BlockStatePreset
import chylex.hee.init.ModBlocks 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.util.math.ceilToInt import chylex.hee.util.math.ceilToInt
import chylex.hee.util.random.nextBiasedFloat import chylex.hee.util.random.nextBiasedFloat
import net.minecraft.block.BlockState
import net.minecraft.block.Blocks 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
class BlockStardustOre(builder: BlockBuilder) : HeeBlock(builder) { object BlockStardustOre : HeeBlockBuilder() {
override val model init {
get() = BlockStateModel( includeFrom(BlockEndOre)
BlockStatePreset.None,
BlockModel.WithTextures(BlockModel.FromParent(Resource.Custom("block/cube_overlay")), mapOf(
"particle" to ModBlocks.STARDUST_ORE.location("_particle"),
"base" to Blocks.END_STONE.location,
))
)
override val renderLayer model = IBlockStateModelSupplier {
get() = CUTOUT BlockStateModel(
BlockStatePreset.None,
BlockModel.WithTextures(BlockModel.FromParent(Resource.Custom("block/cube_overlay")), mapOf(
"particle" to it.location("_particle"),
"base" to Blocks.END_STONE.location,
))
)
}
override val drop renderLayer = CUTOUT
get() = BlockDrop.Manual
override val tags drop = BlockDrop.Manual
get() = listOf(Tags.Blocks.ORES)
override fun getExpDrop(state: BlockState, world: IWorldReader, pos: BlockPos, fortune: Int, silktouch: Int): Int { tool = BlockHarvestTool.required(STONE, PICKAXE)
return (((world as? World)?.rand ?: RANDOM).nextBiasedFloat(4F) * 6F).ceilToInt() hardness = BlockHardness(hardness = 2.8F, resistance = 8.4F)
components.experience = IBlockExperienceComponent { rand -> (rand.nextBiasedFloat(4F) * 6F).ceilToInt() }
} }
} }

View File

@@ -1,26 +0,0 @@
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
}
}

View File

@@ -0,0 +1,48 @@
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
}
}
}
}
}

View File

@@ -1,14 +1,16 @@
package chylex.hee.game.block 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.HUB
import chylex.hee.game.block.BlockVoidPortalInner.Type.RETURN_ACTIVE 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.TileEntityPortalInner
import chylex.hee.game.block.entity.TileEntityVoidPortalStorage 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.block.util.Property
import chylex.hee.game.entity.Teleporter import chylex.hee.game.entity.Teleporter
import chylex.hee.game.entity.Teleporter.FxRange.Silent 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.mechanics.causatum.EnderCausatum
import chylex.hee.game.territory.TerritoryType import chylex.hee.game.territory.TerritoryType
import chylex.hee.game.territory.system.TerritoryInstance import chylex.hee.game.territory.system.TerritoryInstance
@@ -24,44 +26,67 @@ import chylex.hee.game.world.util.max
import chylex.hee.game.world.util.min import chylex.hee.game.world.util.min
import chylex.hee.game.world.util.offsetUntil import chylex.hee.game.world.util.offsetUntil
import chylex.hee.game.world.util.setAir import chylex.hee.game.world.util.setAir
import chylex.hee.init.ModTags
import chylex.hee.util.math.Pos import chylex.hee.util.math.Pos
import chylex.hee.util.math.Vec3 import chylex.hee.util.math.Vec3
import chylex.hee.util.math.center import chylex.hee.util.math.center
import chylex.hee.util.math.subtractY 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.Entity
import net.minecraft.entity.LivingEntity import net.minecraft.entity.LivingEntity
import net.minecraft.entity.player.PlayerEntity import net.minecraft.entity.player.PlayerEntity
import net.minecraft.state.StateContainer.Builder
import net.minecraft.tileentity.TileEntity import net.minecraft.tileentity.TileEntity
import net.minecraft.util.IStringSerializable import net.minecraft.util.IStringSerializable
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.world.IBlockReader
import net.minecraft.world.World import net.minecraft.world.World
class BlockVoidPortalInner(builder: BlockBuilder) : BlockAbstractPortal(builder) { object BlockVoidPortalInner : HeeBlockBuilder() {
companion object { val TYPE = Property.enum<Type>("type")
val TYPE = Property.enum<Type>("type")
private val TELEPORTER = Teleporter(postEvent = false, effectRange = Silent) private val TELEPORTER = Teleporter(postEvent = false, effectRange = Silent)
fun teleportEntity(entity: Entity, info: SpawnInfo) { init {
val targetVec = info.pos.center.subtractY(0.45) includeFrom(BlockAbstractPortal(object : IInnerPortalBlock {
override fun createTileEntity(): TileEntity {
if (entity is LivingEntity) { return TileEntityPortalInner.Void()
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) override fun teleportEntity(world: World, pos: BlockPos, entity: Entity) {
entity.motion = Vec3.ZERO when (pos.getState(world)[TYPE]) {
HUB -> {
val info = pos.closestTickingTile<TileEntityVoidPortalStorage>(world, BlockAbstractPortal.MAX_DISTANCE_FROM_FRAME)?.prepareSpawnPoint(entity)
if (info != null) {
if (entity.isInEndDimension) {
DimensionTeleporter.LastHubPortal.updateForEntity(entity, null)
updateSpawnPortal(entity, pos)
teleportEntity(entity, info)
}
else {
DimensionTeleporter.LastHubPortal.updateForEntity(entity, pos)
DimensionTeleporter.changeDimension(entity, World.THE_END, DimensionTeleporter.EndTerritoryPortal(info))
}
}
}
RETURN_ACTIVE -> {
if (!DimensionTeleporter.LastHubPortal.tryOverrideTeleport(entity)) {
updateSpawnPortal(entity, pos)
teleportEntity(entity, TerritoryInstance.THE_HUB_INSTANCE.prepareSpawnPoint(entity as? PlayerEntity, clearanceRadius = 2))
}
}
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)
}
} }
} }
} }
@@ -85,38 +110,29 @@ class BlockVoidPortalInner(builder: BlockBuilder) : BlockAbstractPortal(builder)
fun create(entity: Entity): TerritoryInstance? fun create(entity: Entity): TerritoryInstance?
} }
// Instance fun teleportEntity(entity: Entity, info: SpawnInfo) {
val targetVec = info.pos.center.subtractY(0.45)
init { if (entity is LivingEntity) {
defaultState = stateContainer.baseState.with(TYPE, HUB) if (entity is PlayerEntity) {
} TerritoryType.fromPos(info.pos)?.let { EnderCausatum.triggerStage(entity, it.stage) }
override fun fillStateContainer(container: Builder<Block, BlockState>) {
container.add(TYPE)
}
override fun createTileEntity(state: BlockState, world: IBlockReader): TileEntity {
return TileEntityPortalInner.Void()
}
// 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)
} }
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
} }
@Suppress("DEPRECATION")
super.neighborChanged(state, world, pos, neighborBlock, neighborPos, isMoving)
} }
// Interaction
private fun findSpawnPortalCenter(entity: Entity, pos: BlockPos): BlockPos? { private fun findSpawnPortalCenter(entity: Entity, pos: BlockPos): BlockPos? {
val world = entity.world val world = entity.world
val offsets = Facing4.map { facing -> pos.offsetUntil(facing, 1..MAX_SIZE) { it.getBlock(world) !== this } ?: return null } 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 minPos = offsets.reduce(BlockPos::min)
val maxPos = offsets.reduce(BlockPos::max) val maxPos = offsets.reduce(BlockPos::max)
@@ -134,37 +150,4 @@ class BlockVoidPortalInner(builder: BlockBuilder) : BlockAbstractPortal(builder)
instance.updateSpawnPoint(entity, centerPos) 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, MAX_DISTANCE_FROM_FRAME)?.prepareSpawnPoint(entity)
if (info != null) {
if (entity.isInEndDimension) {
DimensionTeleporter.LastHubPortal.updateForEntity(entity, null)
updateSpawnPortal(entity, pos)
teleportEntity(entity, info)
}
else {
DimensionTeleporter.LastHubPortal.updateForEntity(entity, pos)
DimensionTeleporter.changeDimension(entity, World.THE_END, DimensionTeleporter.EndTerritoryPortal(info))
}
}
}
RETURN_ACTIVE -> {
if (!DimensionTeleporter.LastHubPortal.tryOverrideTeleport(entity)) {
updateSpawnPortal(entity, pos)
teleportEntity(entity, TerritoryInstance.THE_HUB_INSTANCE.prepareSpawnPoint(entity as? PlayerEntity, clearanceRadius = 2))
}
}
else -> {}
}
}
} }

View File

@@ -1,47 +1,40 @@
package chylex.hee.game.block 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.entity.TileEntityVoidPortalStorage
import chylex.hee.game.block.properties.BlockBuilder
import chylex.hee.game.block.properties.BlockModel import chylex.hee.game.block.properties.BlockModel
import chylex.hee.game.world.util.getTile import chylex.hee.game.world.util.getTile
import chylex.hee.init.ModBlocks import chylex.hee.init.ModBlocks
import chylex.hee.init.ModContainers 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.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
class BlockVoidPortalStorage(builder: BlockBuilder) : BlockPortalFrame(builder) { abstract class BlockVoidPortalStorage(base: HeeBlockBuilder, minPortalSize: Int) : HeeBlockBuilder() {
override val model init {
get() = BlockModel.PortalFrame(ModBlocks.VOID_PORTAL_FRAME, "storage") includeFrom(base)
override fun hasTileEntity(state: BlockState): Boolean { model = BlockModel.PortalFrame(ModBlocks.VOID_PORTAL_FRAME, "storage")
return true
}
override fun createTileEntity(state: BlockState, world: IBlockReader): TileEntity { components.entity = IBlockEntityComponent(::TileEntityVoidPortalStorage)
return TileEntityVoidPortalStorage()
}
override fun onBlockAdded(state: BlockState, world: World, pos: BlockPos, oldState: BlockState, isMoving: Boolean) { components.onAdded = IBlockAddedComponent { _, world, pos ->
BlockAbstractPortal.spawnInnerBlocks(world, pos, ModBlocks.VOID_PORTAL_FRAME, ModBlocks.VOID_PORTAL_INNER, minSize = 1) BlockAbstractPortal.spawnInnerBlocks(world, pos, ModBlocks.VOID_PORTAL_FRAME, ModBlocks.VOID_PORTAL_INNER, minSize = minPortalSize)
}
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 { components.playerUse = IPlayerUseBlockComponent { _, world, pos, player, _ ->
ModContainers.open(player, it, pos) pos.getTile<TileEntityVoidPortalStorage>(world)?.let { ModContainers.open(player, it, pos) }
SUCCESS
} }
}
return SUCCESS object Indestructible : BlockVoidPortalStorage(BlockVoidPortalFrame.Indestructible, minPortalSize = 1)
object Crafted : BlockVoidPortalStorage(BlockVoidPortalFrame.Crafted, minPortalSize = 3) {
init {
components.name = IBlockNameComponent.of(ModBlocks.VOID_PORTAL_STORAGE)
}
} }
} }

View File

@@ -1,39 +0,0 @@
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
}
}

View File

@@ -1,27 +1,47 @@
package chylex.hee.game.block package chylex.hee.game.block
import chylex.hee.game.Resource.location import chylex.hee.game.Resource.location
import chylex.hee.game.block.properties.BlockBuilder 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.BlockModel import chylex.hee.game.block.properties.BlockModel
import chylex.hee.game.item.util.Tool.Level.WOOD
import chylex.hee.init.ModBlocks import chylex.hee.init.ModBlocks
import net.minecraft.block.BlockState import net.minecraft.block.SoundType
import net.minecraft.block.material.Material
import net.minecraft.block.material.MaterialColor
import net.minecraft.tags.BlockTags import net.minecraft.tags.BlockTags
import net.minecraft.util.Direction import net.minecraftforge.common.ToolType.AXE
import net.minecraft.util.math.BlockPos
import net.minecraft.world.IBlockReader
class BlockWhitebark(builder: BlockBuilder) : HeeBlock(builder) { object BlockWhitebark : HeeBlockBuilder() {
override val model init {
get() = BlockModel.Cube(ModBlocks.WHITEBARK_LOG.location) material = Material.WOOD
color = MaterialColor.SNOW
override val tags sound = SoundType.WOOD
get() = listOf(BlockTags.LOGS, BlockTags.LOGS_THAT_BURN) tool = BlockHarvestTool.optional(WOOD, AXE)
override fun getFlammability(state: BlockState, world: IBlockReader, pos: BlockPos, face: Direction): Int {
return 5
} }
override fun getFireSpreadSpeed(state: BlockState, world: IBlockReader, pos: BlockPos, face: Direction): Int { val BARK = HeeBlockBuilder {
return 5 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)
} }
} }

View File

@@ -1,21 +0,0 @@
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
}
}

View File

@@ -1,5 +1,6 @@
package chylex.hee.game.block.dispenser package chylex.hee.game.block.dispenser
import chylex.hee.game.block.BlockIgneousPlate
import chylex.hee.game.block.util.DISPENSER_FACING import chylex.hee.game.block.util.DISPENSER_FACING
import chylex.hee.game.world.util.getState import chylex.hee.game.world.util.getState
import chylex.hee.init.ModBlocks import chylex.hee.init.ModBlocks
@@ -16,7 +17,7 @@ class DispenseWaterExtinguishIgneousPlate(private val originalBehavior: IDispens
val facingState = facingPos.getState(world) val facingState = facingPos.getState(world)
if (facingState.block === ModBlocks.IGNEOUS_PLATE) { if (facingState.block === ModBlocks.IGNEOUS_PLATE) {
return if (ModBlocks.IGNEOUS_PLATE.tryCoolPlate(world, facingPos, facingState)) return if (BlockIgneousPlate.tryCoolPlate(world, facingPos, facingState))
ItemStack(Items.BUCKET) ItemStack(Items.BUCKET)
else else
stack stack

View File

@@ -46,13 +46,6 @@ object BlockBuilders {
explosionResistance = 0.6F 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 { val buildEnderSol = BlockBuilder(Materials.SOLID, MaterialColor.WOOD, SoundType.GROUND.clone(pitch = 0.85F)).apply {
requiresTool = true requiresTool = true
harvestTool = Pair(WOOD, SHOVEL) harvestTool = Pair(WOOD, SHOVEL)
@@ -76,16 +69,6 @@ object BlockBuilders {
explosionResistance = 4.2F 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 { val buildGloomtorch = BlockBuilder(Materials.SOLID, MaterialColor.BLACK, SoundType.STONE).apply {
explosionResistance = 0.3F explosionResistance = 0.3F
lightLevel = 13 lightLevel = 13
@@ -133,19 +116,6 @@ object BlockBuilders {
lightLevel = 15 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) // Building (Dark Loam)
val buildDarkLoam = BlockBuilder(Materials.SOLID, MaterialColor.BLACK, SoundType.GROUND).apply { val buildDarkLoam = BlockBuilder(Materials.SOLID, MaterialColor.BLACK, SoundType.GROUND).apply {
@@ -162,10 +132,6 @@ object BlockBuilders {
explosionResistance = 2.0F explosionResistance = 2.0F
} }
val buildWhitebarkPlanks = buildWhitebark.clone {
explosionResistance = 3.0F
}
// Building (Miner's Burial) // Building (Miner's Burial)
val buildMinersBurial = BlockBuilder(Materials.SOLID, MaterialColor.RED, SoundType.STONE).apply { val buildMinersBurial = BlockBuilder(Materials.SOLID, MaterialColor.RED, SoundType.STONE).apply {
@@ -175,10 +141,6 @@ object BlockBuilders {
explosionResistance = 120F explosionResistance = 120F
} }
val buildMinersBurialIndestructible = buildMinersBurial.clone {
makeIndestructible()
}
// Fluids // Fluids
val buildCauldron = BlockBuilder(Material.IRON, MaterialColor.STONE, SoundType.STONE).apply { val buildCauldron = BlockBuilder(Material.IRON, MaterialColor.STONE, SoundType.STONE).apply {
@@ -188,26 +150,11 @@ object BlockBuilders {
// Interactive (Storage) // 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 { val buildLootChest = BlockBuilder(Materials.SOLID, MaterialColor.BLACK, SoundType.METAL).apply {
makeIndestructible() makeIndestructible()
lightLevel = 13 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) // Interactive (Gates)
val buildExperienceGate = BlockBuilder(Materials.SOLID, MaterialColor.GREEN, SoundType.METAL).apply { val buildExperienceGate = BlockBuilder(Materials.SOLID, MaterialColor.GREEN, SoundType.METAL).apply {
@@ -217,8 +164,6 @@ object BlockBuilders {
// Interactive (Uncategorized) // Interactive (Uncategorized)
val buildIgneousPlate = BlockBuilder(Materials.IGNEOUS_ROCK_PLATE, MaterialColor.AIR, SoundType.STONE)
val buildBrewingStand = BlockBuilder(Material.IRON, MaterialColor.YELLOW, SoundType.STONE).apply { val buildBrewingStand = BlockBuilder(Material.IRON, MaterialColor.YELLOW, SoundType.STONE).apply {
isSolid = false isSolid = false
harvestHardness = 0.5F harvestHardness = 0.5F
@@ -232,24 +177,6 @@ object BlockBuilders {
requiresTool = true 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 { val buildIgneousRockOre = buildEndOre.clone {
harvestTool = Pair(DIAMOND, PICKAXE) harvestTool = Pair(DIAMOND, PICKAXE)
harvestHardness = 1.6F harvestHardness = 1.6F
@@ -315,25 +242,6 @@ object BlockBuilders {
noDrops = true 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 // Energy
val buildEnergyCluster = BlockBuilder(Materials.ENERGY_CLUSTER, MaterialColor.SNOW, SoundType.GLASS.clone(volume = 1.25F, pitch = 1.35F)).apply { val buildEnergyCluster = BlockBuilder(Materials.ENERGY_CLUSTER, MaterialColor.SNOW, SoundType.GLASS.clone(volume = 1.25F, pitch = 1.35F)).apply {
@@ -342,12 +250,6 @@ object BlockBuilders {
noDrops = true noDrops = true
} }
val buildCorruptedEnergy = BlockBuilder(Materials.CORRUPTED_ENERGY, MaterialColor.PURPLE, SoundType.SAND).apply {
isSolid = false
randomTicks = true // just to be safe
noDrops = true
}
// Tables // Tables
val buildTablePedestal = buildGloomrock.clone { val buildTablePedestal = buildGloomrock.clone {
@@ -372,14 +274,6 @@ object BlockBuilders {
lightLevel = 15 lightLevel = 15
} }
val buildScaffolding = BlockBuilder(Materials.SCAFFOLDING, MaterialColor.AIR, SoundType.STONE).apply {
makeIndestructible()
isSolid = false
isOpaque = false
suffocates = false
blocksVision = false
}
// Overrides // Overrides
val buildEndPortalOverride = BlockBuilder(Material.PORTAL, MaterialColor.BLACK, SoundType.STONE).apply { val buildEndPortalOverride = BlockBuilder(Material.PORTAL, MaterialColor.BLACK, SoundType.STONE).apply {

View File

@@ -160,7 +160,7 @@ class EntityItemIgneousRock : EntityItemNoBob {
if (!world.isRemote && age > 4 && (world.gameTime - 1L) % BlockPuzzleLogic.UPDATE_RATE == 0L) { if (!world.isRemote && age > 4 && (world.gameTime - 1L) % BlockPuzzleLogic.UPDATE_RATE == 0L) {
val posBelow = currentPos.down() val posBelow = currentPos.down()
if (posBelow.getBlock(world) is BlockPuzzleLogic) { if (BlockPuzzleLogic.isPuzzleBlock(posBelow.getBlock(world))) {
val entity = EntityTechnicalPuzzle(world) val entity = EntityTechnicalPuzzle(world)
if (entity.startChain(posBelow, throwFacing)) { if (entity.startChain(posBelow, throwFacing)) {

View File

@@ -2,11 +2,11 @@ package chylex.hee.game.entity.living
import chylex.hee.client.text.LocalizationStrategy import chylex.hee.client.text.LocalizationStrategy
import chylex.hee.game.Resource import chylex.hee.game.Resource
import chylex.hee.game.block.BlockCorruptedEnergy
import chylex.hee.game.entity.util.DefaultEntityAttributes import chylex.hee.game.entity.util.DefaultEntityAttributes
import chylex.hee.game.entity.util.with import chylex.hee.game.entity.util.with
import chylex.hee.game.mechanics.instability.Instability import chylex.hee.game.mechanics.instability.Instability
import chylex.hee.game.world.util.isPeaceful import chylex.hee.game.world.util.isPeaceful
import chylex.hee.init.ModBlocks
import chylex.hee.init.ModEntities import chylex.hee.init.ModEntities
import chylex.hee.system.heeTag import chylex.hee.system.heeTag
import chylex.hee.util.forge.Side import chylex.hee.util.forge.Side
@@ -78,7 +78,7 @@ class EntityMobEndermiteInstability(type: EntityType<EntityMobEndermiteInstabili
val pos = Pos(this) val pos = Pos(this)
Instability.get(world).triggerRelief(20u, pos) Instability.get(world).triggerRelief(20u, pos)
ModBlocks.CORRUPTED_ENERGY.spawnCorruptedEnergy(world, pos, 2) BlockCorruptedEnergy.spawn(world, pos, 2)
} }
super.remove() super.remove()

View File

@@ -83,13 +83,10 @@ class EntityTechnicalPuzzle(type: EntityType<EntityTechnicalPuzzle>, world: Worl
} }
private fun moveToBlockAndToggle(pos: BlockPos) { private fun moveToBlockAndToggle(pos: BlockPos) {
val block = pos.getBlock(world) if (BlockPuzzleLogic.isPuzzleBlock(pos.getBlock(world))) {
if (block is BlockPuzzleLogic) {
setPosition(pos) setPosition(pos)
val nextChains = block.onToggled(world, pos, facing) val nextChains = BlockPuzzleLogic.onToggled(world, pos, facing)
if (nextChains.isEmpty()) { if (nextChains.isEmpty()) {
endChain() endChain()
} }
@@ -125,10 +122,7 @@ class EntityTechnicalPuzzle(type: EntityType<EntityTechnicalPuzzle>, world: Worl
} }
fun startChain(pos: BlockPos, facing: Direction): Boolean { fun startChain(pos: BlockPos, facing: Direction): Boolean {
val state = pos.getState(world) if (!BlockPuzzleLogic.isPuzzleBlockEnabled(pos.getState(world))) {
val block = state.block
if (block !is BlockPuzzleLogic || state[BlockPuzzleLogic.STATE] == BlockPuzzleLogic.State.DISABLED) {
return false return false
} }

View File

@@ -10,7 +10,7 @@ import net.minecraft.item.ItemStack
import net.minecraft.util.text.ITextComponent import net.minecraft.util.text.ITextComponent
import net.minecraft.util.text.StringTextComponent import net.minecraft.util.text.StringTextComponent
import net.minecraft.util.text.TranslationTextComponent import net.minecraft.util.text.TranslationTextComponent
import net.minecraft.world.World import net.minecraft.world.IBlockReader
class ItemAbstractTrinket(trinket: ITrinketItem) : HeeItemBuilder() { class ItemAbstractTrinket(trinket: ITrinketItem) : HeeItemBuilder() {
private companion object { private companion object {
@@ -27,7 +27,7 @@ class ItemAbstractTrinket(trinket: ITrinketItem) : HeeItemBuilder() {
localizationExtra[LANG_TOOLTIP_NOT_IN_SLOT_UNCHARGED] = "§cMust be charged and placed in Trinket slot" localizationExtra[LANG_TOOLTIP_NOT_IN_SLOT_UNCHARGED] = "§cMust be charged and placed in Trinket slot"
components.tooltip.add(object : ITooltipComponent { components.tooltip.add(object : ITooltipComponent {
override fun add(lines: MutableList<ITextComponent>, stack: ItemStack, advanced: Boolean, world: World?) { override fun add(lines: MutableList<ITextComponent>, stack: ItemStack, advanced: Boolean, world: IBlockReader?) {
val player = MC.player ?: return val player = MC.player ?: return
if (lines.size > 1) { // first line is item name if (lines.size > 1) { // first line is item name

View File

@@ -19,7 +19,7 @@ import net.minecraft.item.Rarity
import net.minecraft.util.text.ITextComponent import net.minecraft.util.text.ITextComponent
import net.minecraft.util.text.StringTextComponent import net.minecraft.util.text.StringTextComponent
import net.minecraft.util.text.TranslationTextComponent import net.minecraft.util.text.TranslationTextComponent
import net.minecraft.world.World import net.minecraft.world.IBlockReader
object ItemBindingEssence : HeeItemBuilder() { object ItemBindingEssence : HeeItemBuilder() {
init { init {
@@ -57,7 +57,7 @@ object ItemBindingEssence : HeeItemBuilder() {
maxStackSize = 16 maxStackSize = 16
components.tooltip.add(object : ITooltipComponent { components.tooltip.add(object : ITooltipComponent {
override fun add(lines: MutableList<ITextComponent>, stack: ItemStack, advanced: Boolean, world: World?) { override fun add(lines: MutableList<ITextComponent>, stack: ItemStack, advanced: Boolean, world: IBlockReader?) {
val list = InfusionTag.getList(stack) val list = InfusionTag.getList(stack)
if (list.isEmpty) { if (list.isEmpty) {
return return

View File

@@ -1,9 +1,9 @@
package chylex.hee.game.recipe package chylex.hee.game.recipe
import chylex.hee.game.block.BlockJarODust
import chylex.hee.game.inventory.util.nonEmptySlots import chylex.hee.game.inventory.util.nonEmptySlots
import chylex.hee.game.inventory.util.size import chylex.hee.game.inventory.util.size
import chylex.hee.game.mechanics.dust.DustLayers.Side.BOTTOM import chylex.hee.game.mechanics.dust.DustLayers.Side.BOTTOM
import chylex.hee.init.ModBlocks
import net.minecraft.inventory.CraftingInventory import net.minecraft.inventory.CraftingInventory
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.util.NonNullList import net.minecraft.util.NonNullList
@@ -33,10 +33,10 @@ object RecipeJarODustExtract : RecipeBaseDynamic() {
if (layers != null) { if (layers != null) {
layers.removeDust(BOTTOM) layers.removeDust(BOTTOM)
it[first.slot] = first.stack.copy().also { stack -> ModBlocks.JAR_O_DUST.setLayersInStack(stack, layers) } it[first.slot] = first.stack.copy().also { stack -> BlockJarODust.setLayersInStack(stack, layers) }
} }
} }
} }
private fun getLayers(stack: ItemStack) = ModBlocks.JAR_O_DUST.getLayersFromStack(stack) private fun getLayers(stack: ItemStack) = BlockJarODust.getLayersFromStack(stack)
} }

View File

@@ -3,6 +3,7 @@ package chylex.hee.game.territory
import chylex.hee.HEE import chylex.hee.HEE
import chylex.hee.client.util.MC import chylex.hee.client.util.MC
import chylex.hee.game.block.BlockAbstractPortal import chylex.hee.game.block.BlockAbstractPortal
import chylex.hee.game.block.interfaces.getHeeInterface
import chylex.hee.game.entity.damage.Damage import chylex.hee.game.entity.damage.Damage
import chylex.hee.game.entity.damage.IDamageDealer.Companion.TITLE_WITHER import chylex.hee.game.entity.damage.IDamageDealer.Companion.TITLE_WITHER
import chylex.hee.game.entity.damage.IDamageProcessor.Companion.DEAL_CREATIVE import chylex.hee.game.entity.damage.IDamageProcessor.Companion.DEAL_CREATIVE
@@ -149,7 +150,7 @@ object TerritoryVoid {
continue continue
} }
if (entity !is LivingEntity || Pos(entity).getBlock(world) is BlockAbstractPortal) { // protecting entities inside portals should help with server lag frustrations if (entity !is LivingEntity || Pos(entity).getBlock(world).getHeeInterface<BlockAbstractPortal.IInnerPortalBlock>() != null) { // protecting entities inside portals should help with server lag frustrations
continue continue
} }

View File

@@ -1,6 +1,6 @@
package chylex.hee.game.world.generation.feature.basic package chylex.hee.game.world.generation.feature.basic
import chylex.hee.game.block.BlockVoidPortalInner.Companion.TYPE import chylex.hee.game.block.BlockVoidPortalInner.TYPE
import chylex.hee.game.block.BlockVoidPortalInner.Type.HUB import chylex.hee.game.block.BlockVoidPortalInner.Type.HUB
import chylex.hee.game.block.BlockVoidPortalInner.Type.RETURN_ACTIVE import chylex.hee.game.block.BlockVoidPortalInner.Type.RETURN_ACTIVE
import chylex.hee.game.block.BlockVoidPortalInner.Type.RETURN_INACTIVE import chylex.hee.game.block.BlockVoidPortalInner.Type.RETURN_INACTIVE

View File

@@ -1,7 +1,6 @@
package chylex.hee.game.world.generation.feature.energyshrine.piece package chylex.hee.game.world.generation.feature.energyshrine.piece
import chylex.hee.game.Environment import chylex.hee.game.Environment
import chylex.hee.game.block.BlockGloomrock
import chylex.hee.game.entity.technical.EntityTechnicalTrigger import chylex.hee.game.entity.technical.EntityTechnicalTrigger
import chylex.hee.game.entity.technical.EntityTechnicalTrigger.ITriggerHandler import chylex.hee.game.entity.technical.EntityTechnicalTrigger.ITriggerHandler
import chylex.hee.game.entity.technical.EntityTechnicalTrigger.Types.ENERGY_SHRINE_GLOBAL import chylex.hee.game.entity.technical.EntityTechnicalTrigger.Types.ENERGY_SHRINE_GLOBAL
@@ -17,6 +16,7 @@ import chylex.hee.game.world.generation.trigger.EntityStructureTrigger
import chylex.hee.game.world.util.getBlock import chylex.hee.game.world.util.getBlock
import chylex.hee.game.world.util.getState import chylex.hee.game.world.util.getState
import chylex.hee.game.world.util.offsetUntil import chylex.hee.game.world.util.offsetUntil
import chylex.hee.init.ModTags
import chylex.hee.util.color.IColorGenerator import chylex.hee.util.color.IColorGenerator
import chylex.hee.util.color.RGB import chylex.hee.util.color.RGB
import chylex.hee.util.math.Pos import chylex.hee.util.math.Pos
@@ -69,11 +69,11 @@ class EnergyShrineRoom_Main_Start(file: String) : EnergyShrineRoom_Generic(file)
continue continue
} }
if (targetPos.offsetUntil(UP, PARTICLE_GLOOMROCK_CHECK_RANGE) { it.getBlock(world) is BlockGloomrock } == null) { if (targetPos.offsetUntil(UP, PARTICLE_GLOOMROCK_CHECK_RANGE) { ModTags.GLOOMROCK_PARTICLES.contains(it.getBlock(world)) } == null) {
continue continue
} }
if (targetPos.offsetUntil(DOWN, PARTICLE_GLOOMROCK_CHECK_RANGE) { it.getBlock(world) is BlockGloomrock } == null) { if (targetPos.offsetUntil(DOWN, PARTICLE_GLOOMROCK_CHECK_RANGE) { ModTags.GLOOMROCK_PARTICLES.contains(it.getBlock(world)) } == null) {
continue continue
} }

View File

@@ -34,8 +34,6 @@ import chylex.hee.game.block.BlockFlowerPotCustom
import chylex.hee.game.block.BlockFlowerPotDeathFlower import chylex.hee.game.block.BlockFlowerPotDeathFlower
import chylex.hee.game.block.BlockFlowerPotDeathFlowerDecaying import chylex.hee.game.block.BlockFlowerPotDeathFlowerDecaying
import chylex.hee.game.block.BlockGloomrock import chylex.hee.game.block.BlockGloomrock
import chylex.hee.game.block.BlockGloomrockSmooth
import chylex.hee.game.block.BlockGloomrockSmoothColored
import chylex.hee.game.block.BlockGloomrockSmoothSlab import chylex.hee.game.block.BlockGloomrockSmoothSlab
import chylex.hee.game.block.BlockGloomrockSmoothStairs import chylex.hee.game.block.BlockGloomrockSmoothStairs
import chylex.hee.game.block.BlockGloomtorch import chylex.hee.game.block.BlockGloomtorch
@@ -52,7 +50,7 @@ import chylex.hee.game.block.BlockMinersBurialCube
import chylex.hee.game.block.BlockMinersBurialPillar import chylex.hee.game.block.BlockMinersBurialPillar
import chylex.hee.game.block.BlockObsidianCube import chylex.hee.game.block.BlockObsidianCube
import chylex.hee.game.block.BlockObsidianPillar import chylex.hee.game.block.BlockObsidianPillar
import chylex.hee.game.block.BlockPortalFrame import chylex.hee.game.block.BlockPortalFrameIndestructible
import chylex.hee.game.block.BlockPuzzleLogic import chylex.hee.game.block.BlockPuzzleLogic
import chylex.hee.game.block.BlockPuzzleWall import chylex.hee.game.block.BlockPuzzleWall
import chylex.hee.game.block.BlockScaffolding import chylex.hee.game.block.BlockScaffolding
@@ -65,17 +63,17 @@ import chylex.hee.game.block.BlockStardustOre
import chylex.hee.game.block.BlockTableBase import chylex.hee.game.block.BlockTableBase
import chylex.hee.game.block.BlockTablePedestal import chylex.hee.game.block.BlockTablePedestal
import chylex.hee.game.block.BlockTableTile import chylex.hee.game.block.BlockTableTile
import chylex.hee.game.block.BlockVoidPortalCrafted import chylex.hee.game.block.BlockVoidPortalFrame
import chylex.hee.game.block.BlockVoidPortalInner import chylex.hee.game.block.BlockVoidPortalInner
import chylex.hee.game.block.BlockVoidPortalStorage import chylex.hee.game.block.BlockVoidPortalStorage
import chylex.hee.game.block.BlockVoidPortalStorageCrafted
import chylex.hee.game.block.BlockWallCustom import chylex.hee.game.block.BlockWallCustom
import chylex.hee.game.block.BlockWhitebark import chylex.hee.game.block.BlockWhitebark
import chylex.hee.game.block.BlockWhitebarkLeaves import chylex.hee.game.block.BlockWhitebarkLeaves
import chylex.hee.game.block.BlockWhitebarkLog import chylex.hee.game.block.BlockWhitebarkLog
import chylex.hee.game.block.BlockWhitebarkPlanks
import chylex.hee.game.block.BlockWhitebarkSapling import chylex.hee.game.block.BlockWhitebarkSapling
import chylex.hee.game.block.HeeBlock import chylex.hee.game.block.HeeBlock
import chylex.hee.game.block.HeeBlock2
import chylex.hee.game.block.builder.HeeBlockBuilder
import chylex.hee.game.block.entity.TileEntityAccumulationTable import chylex.hee.game.block.entity.TileEntityAccumulationTable
import chylex.hee.game.block.entity.TileEntityExperienceTable import chylex.hee.game.block.entity.TileEntityExperienceTable
import chylex.hee.game.block.entity.TileEntityInfusionTable import chylex.hee.game.block.entity.TileEntityInfusionTable
@@ -84,7 +82,6 @@ import chylex.hee.game.block.fluid.FluidEnderGooPurified
import chylex.hee.game.block.properties.BlockBuilders.buildAncientCobweb import chylex.hee.game.block.properties.BlockBuilders.buildAncientCobweb
import chylex.hee.game.block.properties.BlockBuilders.buildBrewingStand import chylex.hee.game.block.properties.BlockBuilders.buildBrewingStand
import chylex.hee.game.block.properties.BlockBuilders.buildCauldron import chylex.hee.game.block.properties.BlockBuilders.buildCauldron
import chylex.hee.game.block.properties.BlockBuilders.buildCorruptedEnergy
import chylex.hee.game.block.properties.BlockBuilders.buildDarkLoam import chylex.hee.game.block.properties.BlockBuilders.buildDarkLoam
import chylex.hee.game.block.properties.BlockBuilders.buildDragonEgg import chylex.hee.game.block.properties.BlockBuilders.buildDragonEgg
import chylex.hee.game.block.properties.BlockBuilders.buildDryVines import chylex.hee.game.block.properties.BlockBuilders.buildDryVines
@@ -93,49 +90,31 @@ import chylex.hee.game.block.properties.BlockBuilders.buildDustyStoneBricks
import chylex.hee.game.block.properties.BlockBuilders.buildDustyStoneCracked import chylex.hee.game.block.properties.BlockBuilders.buildDustyStoneCracked
import chylex.hee.game.block.properties.BlockBuilders.buildDustyStoneDamaged import chylex.hee.game.block.properties.BlockBuilders.buildDustyStoneDamaged
import chylex.hee.game.block.properties.BlockBuilders.buildEndPortalOverride import chylex.hee.game.block.properties.BlockBuilders.buildEndPortalOverride
import chylex.hee.game.block.properties.BlockBuilders.buildEndPowderOre
import chylex.hee.game.block.properties.BlockBuilders.buildEndStone
import chylex.hee.game.block.properties.BlockBuilders.buildEnderSol import chylex.hee.game.block.properties.BlockBuilders.buildEnderSol
import chylex.hee.game.block.properties.BlockBuilders.buildEndermanHead import chylex.hee.game.block.properties.BlockBuilders.buildEndermanHead
import chylex.hee.game.block.properties.BlockBuilders.buildEndiumBlock
import chylex.hee.game.block.properties.BlockBuilders.buildEndiumOre
import chylex.hee.game.block.properties.BlockBuilders.buildEnergyCluster import chylex.hee.game.block.properties.BlockBuilders.buildEnergyCluster
import chylex.hee.game.block.properties.BlockBuilders.buildEternalFire import chylex.hee.game.block.properties.BlockBuilders.buildEternalFire
import chylex.hee.game.block.properties.BlockBuilders.buildEtherealLantern import chylex.hee.game.block.properties.BlockBuilders.buildEtherealLantern
import chylex.hee.game.block.properties.BlockBuilders.buildExperienceGate import chylex.hee.game.block.properties.BlockBuilders.buildExperienceGate
import chylex.hee.game.block.properties.BlockBuilders.buildFlowerPot import chylex.hee.game.block.properties.BlockBuilders.buildFlowerPot
import chylex.hee.game.block.properties.BlockBuilders.buildGloomrock import chylex.hee.game.block.properties.BlockBuilders.buildGloomrock
import chylex.hee.game.block.properties.BlockBuilders.buildGloomrockBricks
import chylex.hee.game.block.properties.BlockBuilders.buildGloomrockSmooth
import chylex.hee.game.block.properties.BlockBuilders.buildGloomtorch import chylex.hee.game.block.properties.BlockBuilders.buildGloomtorch
import chylex.hee.game.block.properties.BlockBuilders.buildGraveDirt import chylex.hee.game.block.properties.BlockBuilders.buildGraveDirt
import chylex.hee.game.block.properties.BlockBuilders.buildHumus import chylex.hee.game.block.properties.BlockBuilders.buildHumus
import chylex.hee.game.block.properties.BlockBuilders.buildIgneousPlate
import chylex.hee.game.block.properties.BlockBuilders.buildIgneousRockOre import chylex.hee.game.block.properties.BlockBuilders.buildIgneousRockOre
import chylex.hee.game.block.properties.BlockBuilders.buildInfusedGlass import chylex.hee.game.block.properties.BlockBuilders.buildInfusedGlass
import chylex.hee.game.block.properties.BlockBuilders.buildJarODust
import chylex.hee.game.block.properties.BlockBuilders.buildLootChest import chylex.hee.game.block.properties.BlockBuilders.buildLootChest
import chylex.hee.game.block.properties.BlockBuilders.buildMinersBurial import chylex.hee.game.block.properties.BlockBuilders.buildMinersBurial
import chylex.hee.game.block.properties.BlockBuilders.buildMinersBurialIndestructible
import chylex.hee.game.block.properties.BlockBuilders.buildObsidian import chylex.hee.game.block.properties.BlockBuilders.buildObsidian
import chylex.hee.game.block.properties.BlockBuilders.buildObsidianTowerTop
import chylex.hee.game.block.properties.BlockBuilders.buildObsidianVariation import chylex.hee.game.block.properties.BlockBuilders.buildObsidianVariation
import chylex.hee.game.block.properties.BlockBuilders.buildObsidianVariationLit import chylex.hee.game.block.properties.BlockBuilders.buildObsidianVariationLit
import chylex.hee.game.block.properties.BlockBuilders.buildPlant import chylex.hee.game.block.properties.BlockBuilders.buildPlant
import chylex.hee.game.block.properties.BlockBuilders.buildPortalFrame
import chylex.hee.game.block.properties.BlockBuilders.buildPortalFrameCrafted
import chylex.hee.game.block.properties.BlockBuilders.buildPortalInner
import chylex.hee.game.block.properties.BlockBuilders.buildPuzzleLogic
import chylex.hee.game.block.properties.BlockBuilders.buildPuzzleWall
import chylex.hee.game.block.properties.BlockBuilders.buildScaffolding
import chylex.hee.game.block.properties.BlockBuilders.buildSpawnerObsidianTowers import chylex.hee.game.block.properties.BlockBuilders.buildSpawnerObsidianTowers
import chylex.hee.game.block.properties.BlockBuilders.buildStardustOre
import chylex.hee.game.block.properties.BlockBuilders.buildTable import chylex.hee.game.block.properties.BlockBuilders.buildTable
import chylex.hee.game.block.properties.BlockBuilders.buildTablePedestal import chylex.hee.game.block.properties.BlockBuilders.buildTablePedestal
import chylex.hee.game.block.properties.BlockBuilders.buildVantablock import chylex.hee.game.block.properties.BlockBuilders.buildVantablock
import chylex.hee.game.block.properties.BlockBuilders.buildWhitebark import chylex.hee.game.block.properties.BlockBuilders.buildWhitebark
import chylex.hee.game.block.properties.BlockBuilders.buildWhitebarkLeaves import chylex.hee.game.block.properties.BlockBuilders.buildWhitebarkLeaves
import chylex.hee.game.block.properties.BlockBuilders.buildWhitebarkPlanks
import chylex.hee.game.block.properties.BlockBuilders.buildWhitebarkSapling import chylex.hee.game.block.properties.BlockBuilders.buildWhitebarkSapling
import chylex.hee.game.block.properties.CustomSkull import chylex.hee.game.block.properties.CustomSkull
import chylex.hee.game.item.ItemAncientCobweb import chylex.hee.game.item.ItemAncientCobweb
@@ -176,28 +155,28 @@ object ModBlocks {
@JvmField val STONE_BRICK_WALL = BlockWallCustom(Blocks.STONE_BRICKS) named "stone_brick_wall" @JvmField val STONE_BRICK_WALL = BlockWallCustom(Blocks.STONE_BRICKS) named "stone_brick_wall"
@JvmField val INFUSED_GLASS = BlockInfusedGlass(buildInfusedGlass) named "infused_glass" @JvmField val INFUSED_GLASS = BlockInfusedGlass(buildInfusedGlass) named "infused_glass"
@JvmField val VANTABLOCK = HeeBlock(buildVantablock) named "vantablock" @JvmField val VANTABLOCK = HeeBlock(buildVantablock) named "vantablock"
@JvmField val ENDIUM_BLOCK = BlockEndium.Block(buildEndiumBlock) named "endium_block" @JvmField val ENDIUM_BLOCK = BlockEndium.Block named "endium_block"
@JvmField val ENDERSOL = BlockEndersol(buildEnderSol, mergeBottom = Blocks.END_STONE) named "endersol" @JvmField val ENDERSOL = BlockEndersol(buildEnderSol, mergeBottom = Blocks.END_STONE) named "endersol"
@JvmField val HUMUS = BlockHumus(buildHumus, mergeBottom = ENDERSOL) named "humus" @JvmField val HUMUS = BlockHumus(buildHumus, mergeBottom = ENDERSOL) named "humus"
// Blocks: Building (Gloomrock) // Blocks: Building (Gloomrock)
@JvmField val GLOOMROCK = BlockGloomrock(buildGloomrock) named "gloomrock" @JvmField val GLOOMROCK = BlockGloomrock named "gloomrock"
@JvmField val GLOOMROCK_BRICKS = BlockGloomrock(buildGloomrockBricks) named "gloomrock_bricks" @JvmField val GLOOMROCK_BRICKS = BlockGloomrock.BRICKS named "gloomrock_bricks"
@JvmField val GLOOMROCK_BRICK_STAIRS = BlockStairsCustom(GLOOMROCK_BRICKS) named "gloomrock_brick_stairs" @JvmField val GLOOMROCK_BRICK_STAIRS = BlockStairsCustom(GLOOMROCK_BRICKS) named "gloomrock_brick_stairs" // TODO tags for all gloomrock?
@JvmField val GLOOMROCK_BRICK_SLAB = BlockSlabCustom(GLOOMROCK_BRICKS) named "gloomrock_brick_slab" @JvmField val GLOOMROCK_BRICK_SLAB = BlockSlabCustom(GLOOMROCK_BRICKS) named "gloomrock_brick_slab"
@JvmField val GLOOMROCK_SMOOTH = BlockGloomrockSmooth(buildGloomrockSmooth) named "gloomrock_smooth" @JvmField val GLOOMROCK_SMOOTH = BlockGloomrock.SMOOTH named "gloomrock_smooth"
@JvmField val GLOOMROCK_SMOOTH_STAIRS = BlockGloomrockSmoothStairs(GLOOMROCK_SMOOTH) named "gloomrock_smooth_stairs" @JvmField val GLOOMROCK_SMOOTH_STAIRS = BlockGloomrockSmoothStairs(GLOOMROCK_SMOOTH) named "gloomrock_smooth_stairs"
@JvmField val GLOOMROCK_SMOOTH_SLAB = BlockGloomrockSmoothSlab(GLOOMROCK_SMOOTH) named "gloomrock_smooth_slab" @JvmField val GLOOMROCK_SMOOTH_SLAB = BlockGloomrockSmoothSlab(GLOOMROCK_SMOOTH) named "gloomrock_smooth_slab"
@JvmField val GLOOMROCK_SMOOTH_RED = BlockGloomrockSmoothColored(buildGloomrockSmooth) named "gloomrock_smooth_red" @JvmField val GLOOMROCK_SMOOTH_RED = BlockGloomrock.SMOOTH_COLORED named "gloomrock_smooth_red"
@JvmField val GLOOMROCK_SMOOTH_ORANGE = BlockGloomrockSmoothColored(buildGloomrockSmooth) named "gloomrock_smooth_orange" @JvmField val GLOOMROCK_SMOOTH_ORANGE = BlockGloomrock.SMOOTH_COLORED named "gloomrock_smooth_orange"
@JvmField val GLOOMROCK_SMOOTH_YELLOW = BlockGloomrockSmoothColored(buildGloomrockSmooth) named "gloomrock_smooth_yellow" @JvmField val GLOOMROCK_SMOOTH_YELLOW = BlockGloomrock.SMOOTH_COLORED named "gloomrock_smooth_yellow"
@JvmField val GLOOMROCK_SMOOTH_GREEN = BlockGloomrockSmoothColored(buildGloomrockSmooth) named "gloomrock_smooth_green" @JvmField val GLOOMROCK_SMOOTH_GREEN = BlockGloomrock.SMOOTH_COLORED named "gloomrock_smooth_green"
@JvmField val GLOOMROCK_SMOOTH_CYAN = BlockGloomrockSmoothColored(buildGloomrockSmooth) named "gloomrock_smooth_cyan" @JvmField val GLOOMROCK_SMOOTH_CYAN = BlockGloomrock.SMOOTH_COLORED named "gloomrock_smooth_cyan"
@JvmField val GLOOMROCK_SMOOTH_BLUE = BlockGloomrockSmoothColored(buildGloomrockSmooth) named "gloomrock_smooth_blue" @JvmField val GLOOMROCK_SMOOTH_BLUE = BlockGloomrock.SMOOTH_COLORED named "gloomrock_smooth_blue"
@JvmField val GLOOMROCK_SMOOTH_PURPLE = BlockGloomrockSmoothColored(buildGloomrockSmooth) named "gloomrock_smooth_purple" @JvmField val GLOOMROCK_SMOOTH_PURPLE = BlockGloomrock.SMOOTH_COLORED named "gloomrock_smooth_purple"
@JvmField val GLOOMROCK_SMOOTH_MAGENTA = BlockGloomrockSmoothColored(buildGloomrockSmooth) named "gloomrock_smooth_magenta" @JvmField val GLOOMROCK_SMOOTH_MAGENTA = BlockGloomrock.SMOOTH_COLORED named "gloomrock_smooth_magenta"
@JvmField val GLOOMROCK_SMOOTH_WHITE = BlockGloomrockSmoothColored(buildGloomrockSmooth) named "gloomrock_smooth_white" @JvmField val GLOOMROCK_SMOOTH_WHITE = BlockGloomrock.SMOOTH_COLORED named "gloomrock_smooth_white"
@JvmField val GLOOMTORCH = BlockGloomtorch(buildGloomtorch) named "gloomtorch" @JvmField val GLOOMTORCH = BlockGloomtorch(buildGloomtorch) named "gloomtorch"
// Blocks: Building (Dusty Stone) // Blocks: Building (Dusty Stone)
@@ -215,19 +194,19 @@ object ModBlocks {
@JvmField val OBSIDIAN_STAIRS = BlockStairsCustom(Blocks.OBSIDIAN) named "obsidian_stairs" @JvmField val OBSIDIAN_STAIRS = BlockStairsCustom(Blocks.OBSIDIAN) named "obsidian_stairs"
@JvmField val OBSIDIAN_FALLING = BlockFallingObsidian(buildObsidian) named "obsidian_falling" @JvmField val OBSIDIAN_FALLING = BlockFallingObsidian(buildObsidian) named "obsidian_falling"
@JvmField val OBSIDIAN_SMOOTH = BlockObsidianCube(buildObsidianVariation) named "obsidian_smooth" @JvmField val OBSIDIAN_SMOOTH = BlockObsidianCube named "obsidian_smooth"
@JvmField val OBSIDIAN_CHISELED = BlockObsidianCube(buildObsidianVariation) named "obsidian_chiseled" @JvmField val OBSIDIAN_CHISELED = BlockObsidianCube named "obsidian_chiseled"
@JvmField val OBSIDIAN_PILLAR = BlockObsidianPillar(buildObsidianVariation) named "obsidian_pillar" @JvmField val OBSIDIAN_PILLAR = BlockObsidianPillar(buildObsidianVariation) named "obsidian_pillar"
@JvmField val OBSIDIAN_SMOOTH_LIT = BlockObsidianCube.Lit(buildObsidianVariationLit, OBSIDIAN_SMOOTH) named "obsidian_smooth_lit" @JvmField val OBSIDIAN_SMOOTH_LIT = BlockObsidianCube.Lit(OBSIDIAN_SMOOTH) named "obsidian_smooth_lit"
@JvmField val OBSIDIAN_CHISELED_LIT = BlockObsidianCube.Lit(buildObsidianVariationLit, OBSIDIAN_CHISELED) named "obsidian_chiseled_lit" @JvmField val OBSIDIAN_CHISELED_LIT = BlockObsidianCube.Lit(OBSIDIAN_CHISELED) named "obsidian_chiseled_lit"
@JvmField val OBSIDIAN_PILLAR_LIT = BlockObsidianPillar.Lit(buildObsidianVariationLit, OBSIDIAN_PILLAR) named "obsidian_pillar_lit" @JvmField val OBSIDIAN_PILLAR_LIT = BlockObsidianPillar.Lit(buildObsidianVariationLit, OBSIDIAN_PILLAR) named "obsidian_pillar_lit"
@JvmField val OBSIDIAN_TOWER_TOP = BlockObsidianCube.TowerTop(buildObsidianTowerTop, OBSIDIAN_CHISELED) named "obsidian_tower_top" @JvmField val OBSIDIAN_TOWER_TOP = BlockObsidianCube.TowerTop(OBSIDIAN_CHISELED) named "obsidian_tower_top"
// Blocks: Building (End Stone) // Blocks: Building (End Stone)
@JvmField val END_STONE_INFESTED = BlockEndStoneCustom(buildEndStone, MaterialColor.RED) named "end_stone_infested" @JvmField val END_STONE_INFESTED = BlockEndStoneCustom.INFESTED named "end_stone_infested"
@JvmField val END_STONE_BURNED = BlockEndStoneCustom(buildEndStone, MaterialColor.ADOBE /* RENAME ORANGE */) named "end_stone_burned" @JvmField val END_STONE_BURNED = BlockEndStoneCustom.BURNED named "end_stone_burned"
@JvmField val END_STONE_ENCHANTED = BlockEndStoneCustom(buildEndStone, MaterialColor.PURPLE) named "end_stone_enchanted" @JvmField val END_STONE_ENCHANTED = BlockEndStoneCustom.ENCHANTED named "end_stone_enchanted"
// Blocks: Building (Dark Loam) // Blocks: Building (Dark Loam)
@@ -243,18 +222,18 @@ object ModBlocks {
// Blocks: Building (Wood) // Blocks: Building (Wood)
@JvmField val WHITEBARK_LOG = BlockWhitebarkLog(buildWhitebark) named "whitebark_log" @JvmField val WHITEBARK_LOG = BlockWhitebarkLog(buildWhitebark) named "whitebark_log"
@JvmField val WHITEBARK = BlockWhitebark(buildWhitebark) named "whitebark" @JvmField val WHITEBARK = BlockWhitebark.BARK named "whitebark"
@JvmField val WHITEBARK_PLANKS = BlockWhitebarkPlanks(buildWhitebarkPlanks) named "whitebark_planks" @JvmField val WHITEBARK_PLANKS = BlockWhitebark.PLANKS named "whitebark_planks"
@JvmField val WHITEBARK_STAIRS = BlockFlammableStairs(WHITEBARK_PLANKS) named "whitebark_stairs" @JvmField val WHITEBARK_STAIRS = BlockFlammableStairs(WHITEBARK_PLANKS) named "whitebark_stairs"
@JvmField val WHITEBARK_SLAB = BlockFlammableSlab(WHITEBARK_PLANKS) named "whitebark_slab" @JvmField val WHITEBARK_SLAB = BlockFlammableSlab(WHITEBARK_PLANKS) named "whitebark_slab"
// Blocks: Building (Miner's Burial) // Blocks: Building (Miner's Burial)
@JvmField val MINERS_BURIAL_BLOCK_PLAIN = BlockMinersBurialCube(buildMinersBurial) named "miners_burial_block_plain" @JvmField val MINERS_BURIAL_BLOCK_PLAIN = BlockMinersBurialCube named "miners_burial_block_plain"
@JvmField val MINERS_BURIAL_BLOCK_CHISELED = BlockMinersBurialCube(buildMinersBurial) named "miners_burial_block_chiseled" @JvmField val MINERS_BURIAL_BLOCK_CHISELED = BlockMinersBurialCube named "miners_burial_block_chiseled"
@JvmField val MINERS_BURIAL_BLOCK_PILLAR = BlockMinersBurialPillar(buildMinersBurial) named "miners_burial_block_pillar" @JvmField val MINERS_BURIAL_BLOCK_PILLAR = BlockMinersBurialPillar(buildMinersBurial) named "miners_burial_block_pillar"
@JvmField val MINERS_BURIAL_BLOCK_JAIL = BlockMinersBurialCube(buildMinersBurialIndestructible) named "miners_burial_block_jail" @JvmField val MINERS_BURIAL_BLOCK_JAIL = BlockMinersBurialCube.INDESCRUCTIBLE named "miners_burial_block_jail"
@JvmField val MINERS_BURIAL_ALTAR = BlockMinersBurialAltar(buildMinersBurialIndestructible) named "miners_burial_altar" @JvmField val MINERS_BURIAL_ALTAR = BlockMinersBurialAltar named "miners_burial_altar"
// Blocks: Fluids // Blocks: Fluids
@@ -267,20 +246,20 @@ object ModBlocks {
// Blocks: Interactive (Storage) // Blocks: Interactive (Storage)
@JvmField val JAR_O_DUST = BlockJarODust(buildJarODust) named "jar_o_dust" @JvmField val JAR_O_DUST = BlockJarODust named "jar_o_dust"
@JvmField val DARK_CHEST = BlockDarkChest(buildGloomrock) named "dark_chest" @JvmField val DARK_CHEST = BlockDarkChest(buildGloomrock) named "dark_chest"
@JvmField val LOOT_CHEST = BlockLootChest(buildLootChest) named "loot_chest" @JvmField val LOOT_CHEST = BlockLootChest(buildLootChest) named "loot_chest"
// Blocks: Interactive (Puzzle) // Blocks: Interactive (Puzzle)
@JvmField val PUZZLE_WALL = BlockPuzzleWall(buildPuzzleWall) named "puzzle_block_wall" @JvmField val PUZZLE_WALL = BlockPuzzleWall named "puzzle_block_wall"
@JvmField val PUZZLE_PLAIN = BlockPuzzleLogic.Plain(buildPuzzleLogic) named "puzzle_block_plain" @JvmField val PUZZLE_PLAIN = BlockPuzzleLogic.Plain named "puzzle_block_plain"
@JvmField val PUZZLE_BURST_3 = BlockPuzzleLogic.Burst(buildPuzzleLogic, radius = 1) named "puzzle_block_burst_3" @JvmField val PUZZLE_BURST_3 = BlockPuzzleLogic.Burst(radius = 1) named "puzzle_block_burst_3"
@JvmField val PUZZLE_BURST_5 = BlockPuzzleLogic.Burst(buildPuzzleLogic, radius = 2) named "puzzle_block_burst_5" @JvmField val PUZZLE_BURST_5 = BlockPuzzleLogic.Burst(radius = 2) named "puzzle_block_burst_5"
@JvmField val PUZZLE_REDIRECT_1 = BlockPuzzleLogic.RedirectSome.R1(buildPuzzleLogic) named "puzzle_block_redirect_1" @JvmField val PUZZLE_REDIRECT_1 = BlockPuzzleLogic.RedirectOne named "puzzle_block_redirect_1"
@JvmField val PUZZLE_REDIRECT_2 = BlockPuzzleLogic.RedirectSome.R2(buildPuzzleLogic) named "puzzle_block_redirect_2" @JvmField val PUZZLE_REDIRECT_2 = BlockPuzzleLogic.RedirectTwo named "puzzle_block_redirect_2"
@JvmField val PUZZLE_REDIRECT_4 = BlockPuzzleLogic.RedirectAll(buildPuzzleLogic) named "puzzle_block_redirect_4" @JvmField val PUZZLE_REDIRECT_4 = BlockPuzzleLogic.RedirectAll named "puzzle_block_redirect_4"
@JvmField val PUZZLE_TELEPORT = BlockPuzzleLogic.Teleport(buildPuzzleLogic) named "puzzle_block_teleport" @JvmField val PUZZLE_TELEPORT = BlockPuzzleLogic.Teleport named "puzzle_block_teleport"
// Blocks: Interactive (Gates) // Blocks: Interactive (Gates)
@@ -290,14 +269,14 @@ object ModBlocks {
// Blocks: Interactive (Uncategorized) // Blocks: Interactive (Uncategorized)
@JvmField val INFUSED_TNT = BlockInfusedTNT() named "infused_tnt" @JvmField val INFUSED_TNT = BlockInfusedTNT() named "infused_tnt"
@JvmField val IGNEOUS_PLATE = BlockIgneousPlate(buildIgneousPlate) named "igneous_plate" @JvmField val IGNEOUS_PLATE = BlockIgneousPlate named "igneous_plate"
@JvmField val ENHANCED_BREWING_STAND = BlockBrewingStandCustom(buildBrewingStand) named "enhanced_brewing_stand" @JvmField val ENHANCED_BREWING_STAND = BlockBrewingStandCustom(buildBrewingStand) named "enhanced_brewing_stand"
// Blocks: Ores // Blocks: Ores
@JvmField val END_POWDER_ORE = BlockEndPowderOre(buildEndPowderOre) named "end_powder_ore" @JvmField val END_POWDER_ORE = BlockEndPowderOre named "end_powder_ore"
@JvmField val ENDIUM_ORE = BlockEndium.Ore(buildEndiumOre) named "endium_ore" @JvmField val ENDIUM_ORE = BlockEndium.Ore named "endium_ore"
@JvmField val STARDUST_ORE = BlockStardustOre(buildStardustOre) named "stardust_ore" @JvmField val STARDUST_ORE = BlockStardustOre named "stardust_ore"
@JvmField val IGNEOUS_ROCK_ORE = BlockIgneousRockOre(buildIgneousRockOre) named "igneous_rock_ore" @JvmField val IGNEOUS_ROCK_ORE = BlockIgneousRockOre(buildIgneousRockOre) named "igneous_rock_ore"
// Blocks: Decorative (Trees) // Blocks: Decorative (Trees)
@@ -340,21 +319,21 @@ object ModBlocks {
// Blocks: Portals // Blocks: Portals
@JvmField val END_PORTAL_INNER = BlockEndPortalInner(buildPortalInner) named "end_portal_inner" @JvmField val END_PORTAL_INNER = BlockEndPortalInner named "end_portal_inner"
@JvmField val END_PORTAL_FRAME = BlockPortalFrame(buildPortalFrame) named "end_portal_frame" @JvmField val END_PORTAL_FRAME = BlockPortalFrameIndestructible named "end_portal_frame"
@JvmField val END_PORTAL_ACCEPTOR = BlockEndPortalAcceptor(buildPortalFrame) named "end_portal_acceptor" @JvmField val END_PORTAL_ACCEPTOR = BlockEndPortalAcceptor named "end_portal_acceptor"
@JvmField val VOID_PORTAL_INNER = BlockVoidPortalInner(buildPortalInner) named "void_portal_inner" @JvmField val VOID_PORTAL_INNER = BlockVoidPortalInner named "void_portal_inner"
@JvmField val VOID_PORTAL_FRAME = BlockPortalFrame(buildPortalFrame) named "void_portal_frame" @JvmField val VOID_PORTAL_FRAME = BlockVoidPortalFrame.Indestructible named "void_portal_frame"
@JvmField val VOID_PORTAL_STORAGE = BlockVoidPortalStorage(buildPortalFrame) named "void_portal_storage" @JvmField val VOID_PORTAL_STORAGE = BlockVoidPortalStorage.Indestructible named "void_portal_storage"
@JvmField val VOID_PORTAL_FRAME_CRAFTED = BlockVoidPortalCrafted(buildPortalFrameCrafted) named "void_portal_frame_crafted" @JvmField val VOID_PORTAL_FRAME_CRAFTED = BlockVoidPortalFrame.Crafted named "void_portal_frame_crafted"
@JvmField val VOID_PORTAL_STORAGE_CRAFTED = BlockVoidPortalStorageCrafted(buildPortalFrameCrafted) named "void_portal_storage_crafted" @JvmField val VOID_PORTAL_STORAGE_CRAFTED = BlockVoidPortalStorage.Crafted named "void_portal_storage_crafted"
// Blocks: Energy // Blocks: Energy
@JvmField val ENERGY_CLUSTER = BlockEnergyCluster(buildEnergyCluster) named "energy_cluster" @JvmField val ENERGY_CLUSTER = BlockEnergyCluster(buildEnergyCluster) named "energy_cluster"
@JvmField val CORRUPTED_ENERGY = BlockCorruptedEnergy(buildCorruptedEnergy) named "corrupted_energy" @JvmField val CORRUPTED_ENERGY = BlockCorruptedEnergy named "corrupted_energy"
// Blocks: Tables // Blocks: Tables
@@ -375,7 +354,7 @@ object ModBlocks {
// Blocks: Utilities // Blocks: Utilities
@JvmField val ETERNAL_FIRE = BlockEternalFire(buildEternalFire) named "eternal_fire" @JvmField val ETERNAL_FIRE = BlockEternalFire(buildEternalFire) named "eternal_fire"
@JvmField val SCAFFOLDING = BlockScaffolding.create(buildScaffolding) named "scaffolding" @JvmField val SCAFFOLDING = BlockScaffolding named "scaffolding"
// Registry // Registry
@@ -586,6 +565,10 @@ object ModBlocks {
private val temporaryItemBlocks = mutableListOf<BlockItem>() private val temporaryItemBlocks = mutableListOf<BlockItem>()
private val overrideBlocks = mutableListOf<Block>() private val overrideBlocks = mutableListOf<Block>()
private infix fun HeeBlockBuilder.named(registryName: String): HeeBlock2 {
return this.build() named registryName
}
private inline fun Block.override(vanillaBlock: Block, itemBlockConstructor: ((Block) -> BlockItem?)) = apply { private inline fun Block.override(vanillaBlock: Block, itemBlockConstructor: ((Block) -> BlockItem?)) = apply {
this.useVanillaName(vanillaBlock) this.useVanillaName(vanillaBlock)
overrideBlocks.add(this) overrideBlocks.add(this)

View File

@@ -0,0 +1,15 @@
package chylex.hee.init
import chylex.hee.game.Resource
import net.minecraft.block.Block
import net.minecraft.tags.BlockTags
import net.minecraft.tags.ITag.INamedTag
object ModTags {
@JvmField val GLOOMROCK_PARTICLES = tag("gloomrock_particles")
@JvmField val VOID_PORTAL_FRAME_CRAFTED = tag("void_portal_frame_crafted")
private fun tag(name: String): INamedTag<Block> {
return BlockTags.createOptional(Resource.Custom(name))
}
}

View File

@@ -1,5 +1,6 @@
package chylex.hee.mixin; package chylex.hee.mixin;
import chylex.hee.game.block.interfaces.IBlockWithInterfaces;
import chylex.hee.game.block.logic.IBlockDynamicHardness; import chylex.hee.game.block.logic.IBlockDynamicHardness;
import net.minecraft.block.AbstractBlock.AbstractBlockState; import net.minecraft.block.AbstractBlock.AbstractBlockState;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@@ -19,8 +20,13 @@ public abstract class HookBlockHardness {
final BlockState state = world.getBlockState(pos); final BlockState state = world.getBlockState(pos);
final Block block = state.getBlock(); final Block block = state.getBlock();
if (block instanceof IBlockDynamicHardness) { if (block instanceof IBlockWithInterfaces) {
ci.setReturnValue(Float.valueOf(((IBlockDynamicHardness)block).getBlockHardness(world, pos, state, ci.getReturnValueF()))); final IBlockWithInterfaces blockWithInterfaces = (IBlockWithInterfaces)block;
final IBlockDynamicHardness dynamicHardness = (IBlockDynamicHardness)blockWithInterfaces.getInterface(IBlockDynamicHardness.class);
if (dynamicHardness != null) {
ci.setReturnValue(Float.valueOf(dynamicHardness.getBlockHardness(world, pos, state, ci.getReturnValueF())));
}
} }
} }
} }