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

4 Commits

420 changed files with 5838 additions and 6557 deletions

1
.idea/gradle.xml generated
View File

@@ -12,7 +12,6 @@
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/data" />
<option value="$PROJECT_DIR$/modules/debug" />
<option value="$PROJECT_DIR$/modules/system" />
<option value="$PROJECT_DIR$/modules/util" />
</set>

View File

@@ -60,7 +60,6 @@ idea {
["out", "src/main/kotlin", "src/test/kotlin"].each {
excludeDirs += file(it)
excludeDirs += file("modules/debug/" + it)
excludeDirs += file("modules/system/" + it)
excludeDirs += file("modules/util/" + it)
}
@@ -129,6 +128,7 @@ minecraft {
runs {
client {
property "hee.debug", ""
property "mixin.env.remapRefMap", "true"
property "mixin.env.refMapRemappingFile", "${projectDir}/build/createSrgToMcp/output.srg"
arg "-mixin.config=hee.mixins.json"
@@ -138,7 +138,6 @@ minecraft {
mods {
hee {
source sourceSets.main
source project(":debug").sourceSets.main
source project(":system").sourceSets.main
source project(":util").sourceSets.main
}
@@ -146,6 +145,7 @@ minecraft {
}
server {
property "hee.debug", ""
property "mixin.env.remapRefMap", "true"
property "mixin.env.refMapRemappingFile", "${projectDir}/build/createSrgToMcp/output.srg"
arg "-mixin.config=hee.mixins.json"
@@ -155,7 +155,6 @@ minecraft {
mods {
hee {
source sourceSets.main
source project(":debug").sourceSets.main
source project(":system").sourceSets.main
source project(":util").sourceSets.main
}
@@ -163,6 +162,7 @@ minecraft {
}
data {
property "hee.debug", ""
args "--mod", "hee"
args "--all"
args "--output", file("data/gen")
@@ -174,7 +174,6 @@ minecraft {
mods {
hee {
source sourceSets.main
source project(":debug").sourceSets.main
source project(":system").sourceSets.main
source project(":util").sourceSets.main
source project(":datagen").sourceSets.main
@@ -191,12 +190,12 @@ mixin {
dependencies {
minecraft "net.minecraftforge:forge:" + mc_version + "-" + forge_version
implementation project(":util")
implementation project(":system")
implementation project(":util")
implementation "thedarkcolour:kotlinforforge:" + kotlin_mod_version
testImplementation project(":util")
testImplementation project(":system")
testImplementation project(":util")
testImplementation "org.junit.jupiter:junit-jupiter-api:5.3.0-RC1"
if (System.getProperty("idea.sync.active") != "true") {

View File

@@ -580,8 +580,6 @@ e66091a13a6e7593eb5bd971978d24a5a0e375b3 data/hee/loot_tables/blocks/whitebark.j
9bd3a9e24162d2c81047b834f8f79d6cabec86be data/hee/loot_tables/blocks/whitebark_planks.json
7d84dc443a052e349593b71d2c0a523e75396cdf data/hee/loot_tables/blocks/whitebark_slab.json
83e0b81adb3f9dd488397e8459b95f7b0ce19927 data/hee/loot_tables/blocks/whitebark_stairs.json
37f3c55266db3db8dc6d22fdbaf3d53243016b77 data/hee/tags/blocks/gloomrock_particles.json
1a70c674d979a59cea18d92f2227ab8a5ed2ccc7 data/hee/tags/blocks/void_portal_frame_crafted.json
f5996244831ab38fe1fae2f304bbd7825d6ad98b data/minecraft/tags/blocks/bamboo_plantable_on.json
479189f9b35a3c8f795539daf6a1809130242c5b data/minecraft/tags/blocks/flower_pots.json
424e2e03cf62f23f4496468a97b9f0df060df9fe data/minecraft/tags/blocks/impermeable.json

View File

@@ -1,17 +0,0 @@
{
"replace": false,
"values": [
"hee:gloomrock",
"hee:gloomrock_bricks",
"hee:gloomrock_smooth",
"hee:gloomrock_smooth_red",
"hee:gloomrock_smooth_orange",
"hee:gloomrock_smooth_yellow",
"hee:gloomrock_smooth_green",
"hee:gloomrock_smooth_cyan",
"hee:gloomrock_smooth_blue",
"hee:gloomrock_smooth_purple",
"hee:gloomrock_smooth_magenta",
"hee:gloomrock_smooth_white"
]
}

View File

@@ -1,7 +0,0 @@
{
"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) {
override fun registerModels() {
for (block in ModBlocks.ALL) {
(block as? IHeeBlock)?.let { registerModel(block, it.model.generate(block).blockModel) { builder -> builder } }
(block as? IHeeBlock)?.model?.let { registerModel(block, it.blockModel) { builder -> builder } }
}
}

View File

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

View File

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

View File

@@ -91,7 +91,7 @@ class LangEnglish(generator: DataGenerator, modid: String) : LanguageProvider(ge
}
}
for (command in ClientCommandHandler.all.values) {
for (command in ClientCommandHandler.nonHelpCommands.values) {
val name = command.name
add("commands.hee.$name.info", command.description)
}

View File

@@ -9,7 +9,7 @@ import net.minecraft.tags.ITag.INamedTag
import net.minecraft.tags.ItemTags
import net.minecraftforge.common.data.ExistingFileHelper
class ItemTags(dataGenerator: DataGenerator, private val blockTags: BlockTags, modId: String, existingFileHelper: ExistingFileHelper?) : ItemTagsProvider(dataGenerator, blockTags, modId, existingFileHelper) {
class ItemTags(dataGenerator: DataGenerator, private val blockTags: chylex.hee.datagen.server.BlockTags, modId: String, existingFileHelper: ExistingFileHelper?) : ItemTagsProvider(dataGenerator, blockTags, modId, existingFileHelper) {
override fun registerTags() {
val itemTags = ItemTags.getAllTags().associateBy { it.name }

View File

@@ -1,33 +0,0 @@
buildscript {
repositories {
mavenCentral()
maven { url = "https://files.minecraftforge.net/maven" }
}
dependencies {
classpath group: "net.minecraftforge.gradle", name: "ForgeGradle", version: forge_gradle_version, changing: true
classpath group: "org.jetbrains.kotlin", name: "kotlin-gradle-plugin", version: kotlin_version
}
}
apply plugin: "net.minecraftforge.gradle"
minecraft {
mappings channel: "snapshot", version: rootProject.mapping_version
setAccessTransformers(rootProject.access_transformers)
}
dependencies {
minecraft "net.minecraftforge:forge:" + mc_version + "-" + forge_version
implementation rootProject
implementation project(":system")
implementation project(":util")
}
jar {
manifest {
attributes([
"FMLModType": "LIBRARY"
])
}
}

View File

@@ -1,143 +0,0 @@
package chylex.hee.client
import chylex.hee.client.render.RenderStateBuilder
import chylex.hee.client.render.util.DF_ONE
import chylex.hee.client.render.util.DF_ZERO
import chylex.hee.client.render.util.SF_ONE_MINUS_SRC_ALPHA
import chylex.hee.client.render.util.SF_SRC_ALPHA
import chylex.hee.client.util.MC
import chylex.hee.game.item.util.nbtOrNull
import chylex.hee.game.world.util.floodFill
import chylex.hee.game.world.util.getBlock
import chylex.hee.game.world.util.getState
import chylex.hee.game.world.util.isAir
import chylex.hee.game.world.util.removeBlock
import chylex.hee.game.world.util.setState
import chylex.hee.util.nbt.hasKey
import net.minecraft.block.BlockState
import net.minecraft.client.renderer.vertex.DefaultVertexFormats
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.BlockItem
import net.minecraft.item.Items
import net.minecraft.util.Direction
import net.minecraft.util.Direction.DOWN
import net.minecraft.util.Direction.EAST
import net.minecraft.util.Direction.NORTH
import net.minecraft.util.Direction.SOUTH
import net.minecraft.util.Direction.UP
import net.minecraft.util.Direction.WEST
import net.minecraft.util.Hand.MAIN_HAND
import net.minecraft.util.Hand.OFF_HAND
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.BlockRayTraceResult
import net.minecraft.util.math.shapes.ISelectionContext
import net.minecraft.world.IWorld
import net.minecraftforge.client.event.DrawHighlightEvent
import net.minecraftforge.event.entity.player.PlayerInteractEvent.LeftClickBlock
import net.minecraftforge.event.entity.player.PlayerInteractEvent.RightClickBlock
import net.minecraftforge.event.world.BlockEvent.BreakEvent
import net.minecraftforge.eventbus.api.SubscribeEvent
import org.lwjgl.opengl.GL11
object BuildStick {
private val RENDER_TYPE_LINE = with(RenderStateBuilder()) {
line(2.25)
blend(SF_SRC_ALPHA, DF_ONE, SF_ONE_MINUS_SRC_ALPHA, DF_ZERO)
layering(RenderStateBuilder.LAYERING_OFFSET_Z)
mask(RenderStateBuilder.MASK_COLOR)
buildType("hee:debug_line", DefaultVertexFormats.POSITION_COLOR, GL11.GL_LINES, bufferSize = 256)
}
private fun isHoldingBuildStick(player: PlayerEntity): Boolean {
val heldItem = player.getHeldItem(MAIN_HAND)
return heldItem.item === Items.STICK && heldItem.nbtOrNull.hasKey("HEE_BUILD")
}
private fun getBuildStickBlocks(world: IWorld, pos: BlockPos, state: BlockState, face: Direction): List<BlockPos> {
val floodFaces = when (face) {
UP, DOWN -> listOf(NORTH, SOUTH, EAST, WEST)
NORTH, SOUTH -> listOf(UP, DOWN, EAST, WEST)
EAST, WEST -> listOf(UP, DOWN, NORTH, SOUTH)
else -> emptyList()
}
val limit = 1000
val block = state.block
return pos.floodFill(floodFaces, limit) { it.getBlock(world) === block }.takeIf { it.size < limit }.orEmpty()
}
private var lastLeftClickHit: BlockRayTraceResult? = null
@SubscribeEvent
fun onLeftClickBlock(e: LeftClickBlock) {
val world = e.world
if (isHoldingBuildStick(e.player) && !world.isRemote) {
lastLeftClickHit = MC.instance.objectMouseOver as? BlockRayTraceResult
}
}
@SubscribeEvent
fun onBlockBreak(e: BreakEvent) {
val world = e.world
if (isHoldingBuildStick(e.player) && !world.isRemote) {
val hit = lastLeftClickHit ?: return
for (pos in getBuildStickBlocks(world, e.pos, e.state, hit.face)) {
pos.removeBlock(world)
}
}
}
@SubscribeEvent
fun onRightClickBlock(e: RightClickBlock) {
val world = e.world
val player = e.player
if (isHoldingBuildStick(player) && !world.isRemote) {
val state = e.pos.getState(world)
val face = e.face!!
val place = (player.getHeldItem(OFF_HAND).item as? BlockItem)?.block?.defaultState ?: state
for (pos in getBuildStickBlocks(world, e.pos, state, face)) {
val offset = pos.offset(face)
if (offset.isAir(world)) {
offset.setState(world, place)
}
}
}
}
@SubscribeEvent
fun onRenderOverlay(e: DrawHighlightEvent.HighlightBlock) {
val player = MC.player!!
if (isHoldingBuildStick(player)) {
val hit = MC.instance.objectMouseOver as? BlockRayTraceResult ?: return
val world = player.world
val center = hit.pos
val info = e.info
val matrix = e.matrix.last.matrix
val builder = e.buffers.getBuffer(RENDER_TYPE_LINE)
for (pos in getBuildStickBlocks(world, center, center.getState(world), hit.face)) {
val x = pos.x - info.projectedView.x
val y = pos.y - info.projectedView.y
val z = pos.z - info.projectedView.z
val shape = pos.getState(world).getShape(world, pos, ISelectionContext.forEntity(info.renderViewEntity))
shape.forEachEdge { x1, y1, z1, x2, y2, z2 ->
builder.pos(matrix, (x1 + x).toFloat(), (y1 + y).toFloat(), (z1 + z).toFloat()).color(1F, 1F, 1F, 1F).endVertex()
builder.pos(matrix, (x2 + x).toFloat(), (y2 + y).toFloat(), (z2 + z).toFloat()).color(1F, 1F, 1F, 1F).endVertex()
}
}
e.isCanceled = true
}
}
}

View File

@@ -1,42 +0,0 @@
package chylex.hee.client
import chylex.hee.client.util.MC
import chylex.hee.debug.benchmark.TerritoryGenerationBenchmarkScreen
import chylex.hee.util.color.RGB
import com.mojang.blaze3d.matrix.MatrixStack
import net.minecraft.client.gui.screen.Screen
import net.minecraft.client.gui.widget.button.Button
import net.minecraft.util.text.StringTextComponent
import net.minecraftforge.client.event.InputEvent.KeyInputEvent
import net.minecraftforge.eventbus.api.SubscribeEvent
import org.lwjgl.glfw.GLFW
object DebugMenu {
@SubscribeEvent
fun onKeyPressed(e: KeyInputEvent) {
if (e.action != GLFW.GLFW_RELEASE) {
return
}
if (e.key == GLFW.GLFW_KEY_F12) {
MC.instance.displayGuiScreen(DebugMenuScreen(MC.currentScreen))
}
}
private class DebugMenuScreen(private val parentScreen: Screen?) : Screen(StringTextComponent("HEE 2 Debug")) {
override fun init() {
addButton(Button(width / 2 - 100, 36, 200, 20, StringTextComponent("Territory Generation Benchmark")) { MC.instance.displayGuiScreen(TerritoryGenerationBenchmarkScreen(this)) })
addButton(Button(width / 2 - 100, height - 40, 200, 20, StringTextComponent("Close")) { closeScreen() })
}
override fun render(matrix: MatrixStack, mouseX: Int, mouseY: Int, partialTicks: Float) {
renderBackground(matrix)
drawCenteredString(matrix, font, title, width / 2, 15, RGB(255u).i)
super.render(matrix, mouseX, mouseY, partialTicks)
}
override fun closeScreen() {
MC.instance.displayGuiScreen(parentScreen)
}
}
}

View File

@@ -1,27 +0,0 @@
package chylex.hee.client
import chylex.hee.client.util.MC
import net.minecraftforge.client.event.InputEvent.KeyInputEvent
import net.minecraftforge.eventbus.api.SubscribeEvent
import org.lwjgl.glfw.GLFW
object GameModeToggle {
@SubscribeEvent
fun onKeyPressed(e: KeyInputEvent) {
if (e.action != GLFW.GLFW_PRESS) {
return
}
if (e.key == GLFW.GLFW_KEY_GRAVE_ACCENT) {
val player = MC.player ?: return
if (player.isCreative) {
val ctrl = (e.modifiers and GLFW.GLFW_MOD_CONTROL) != 0
player.sendChatMessage(if (ctrl) "/gamemode spectator" else "/gamemode survival")
}
else {
player.sendChatMessage("/gamemode creative")
}
}
}
}

View File

@@ -1,19 +0,0 @@
package chylex.hee.client
import chylex.hee.client.render.TerritoryRenderer
import chylex.hee.client.util.MC
import chylex.hee.game.world.isInEndDimension
import net.minecraftforge.client.event.RenderGameOverlayEvent
import net.minecraftforge.eventbus.api.SubscribeEvent
object TerritoryVoidDebug {
@SubscribeEvent
fun onRenderGameOverlayText(e: RenderGameOverlayEvent.Text) {
if (MC.settings.showDebugInfo && MC.player?.isInEndDimension == true) {
with(e.left) {
add("")
add("End Void Factor: ${"%.3f".format(TerritoryRenderer.currentVoidFactor)}")
}
}
}
}

View File

@@ -1,71 +0,0 @@
package chylex.hee.debug
import chylex.hee.HEE
import chylex.hee.client.BuildStick
import chylex.hee.client.DebugMenu
import chylex.hee.client.GameModeToggle
import chylex.hee.client.TerritoryVoidDebug
import chylex.hee.game.block.BlockScaffoldingDebug
import chylex.hee.game.command.client.CommandClientDebugToggles
import chylex.hee.game.command.client.CommandClientScaffolding
import chylex.hee.game.command.server.CommandServerInstability
import chylex.hee.game.command.server.CommandServerStructure
import chylex.hee.game.command.server.CommandServerTerritory
import chylex.hee.game.command.server.CommandServerTestWorld
import chylex.hee.system.IDebugModule
import chylex.hee.util.forge.Side
import chylex.hee.util.forge.Sided
import chylex.hee.util.forge.SubscribeAllEvents
import chylex.hee.util.forge.SubscribeEvent
import net.minecraftforge.client.event.GuiOpenEvent
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus.MOD
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent
@SubscribeAllEvents(modid = HEE.ID, bus = MOD)
internal object Debug : IDebugModule {
init {
HEE.debug = true
HEE.debugModule = this
}
override val clientCommands
get() = listOf(
CommandClientScaffolding,
CommandClientDebugToggles
)
override val serverCommands
get() = listOf(
CommandServerInstability,
CommandServerStructure,
CommandServerTerritory,
CommandServerTestWorld
)
override val scaffoldingBlockBehavior
get() = BlockScaffoldingDebug
@SubscribeEvent
fun onClientSetup(@Suppress("UNUSED_PARAMETER") e: FMLClientSetupEvent) {
initializeClient()
}
@Sided(Side.CLIENT)
private fun initializeClient() {
if (HEE.debug) {
MinecraftForge.EVENT_BUS.register(DebugMenu)
MinecraftForge.EVENT_BUS.register(BuildStick)
MinecraftForge.EVENT_BUS.register(GameModeToggle)
MinecraftForge.EVENT_BUS.register(TerritoryVoidDebug)
MinecraftForge.EVENT_BUS.register(object : Any() {
@SubscribeEvent
fun onGuiOpen(@Suppress("UNUSED_PARAMETER") e: GuiOpenEvent) {
PowerShell.maximizeWindow()
MinecraftForge.EVENT_BUS.unregister(this)
}
})
}
}
}

View File

@@ -1,26 +0,0 @@
package chylex.hee.debug
import chylex.hee.game.Environment
import chylex.hee.util.forge.Side
import org.apache.commons.lang3.SystemUtils
import java.io.File
import java.lang.management.ManagementFactory
internal object PowerShell {
private fun canExecutePowershell(scriptName: String): Boolean {
return SystemUtils.IS_OS_WINDOWS && Environment.side == Side.CLIENT && File(scriptName).exists()
}
fun setClipboardContents(file: File) {
if (canExecutePowershell("filecopy.ps1")) {
ProcessBuilder("powershell.exe", "-ExecutionPolicy", "Unrestricted", "-Sta", "-File", "filecopy.ps1", file.absolutePath).start()
}
}
fun maximizeWindow() {
if (canExecutePowershell("maximize.ps1")) {
val pid = ManagementFactory.getRuntimeMXBean().name.split("@")[0]
ProcessBuilder("powershell.exe", "-ExecutionPolicy", "Unrestricted", "-File", "maximize.ps1", pid).start()
}
}
}

View File

@@ -1,80 +0,0 @@
package chylex.hee.debug.benchmark
import chylex.hee.HEE
import chylex.hee.client.util.MC
import chylex.hee.game.Environment
import chylex.hee.game.territory.TerritoryType
import chylex.hee.game.world.generation.structure.world.SegmentedWorld
import chylex.hee.util.color.RGB
import com.mojang.blaze3d.matrix.MatrixStack
import net.minecraft.client.gui.screen.Screen
import net.minecraft.client.gui.widget.button.Button
import net.minecraft.util.text.StringTextComponent
import net.minecraft.util.text.TranslationTextComponent
import net.minecraft.world.World
import java.util.Random
class TerritoryGenerationBenchmarkScreen(private val parentScreen: Screen) : Screen(StringTextComponent("Territory Generation Benchmark")) {
private val generated = mutableListOf<SegmentedWorld>()
override fun init() {
try {
Environment.getDimension(World.OVERWORLD)
} catch (e: NullPointerException) {
println("Must be in a world!")
closeScreen()
return
}
val x = width / 2 - 100
addButton(Button(x, 36, 200, 20, StringTextComponent("(All)")) { runAll() })
for ((index, territory) in TerritoryType.ALL.withIndex()) {
val y = 36 + (22 * (index + 1))
addButton(Button(x, y, 200, 20, TranslationTextComponent(territory.translationKey)) { runOnce(territory) })
}
addButton(Button(x, height - 40, 200, 20, StringTextComponent("Close")) { closeScreen() })
}
override fun render(matrix: MatrixStack, mouseX: Int, mouseY: Int, partialTicks: Float) {
renderBackground(matrix)
drawCenteredString(matrix, font, title, width / 2, 15, RGB(255u).i)
super.render(matrix, mouseX, mouseY, partialTicks)
}
override fun closeScreen() {
MC.instance.displayGuiScreen(parentScreen)
}
private fun runAll() {
generated.clear()
for (territory in TerritoryType.ALL) {
if (territory.gen === TerritoryType.Companion.GeneratorDummy) {
continue
}
for (seed in 0L until 5L) {
runImpl(territory, seed)
}
}
HEE.log.info("[TerritoryGenerationBenchmarkScreen] done!")
}
private fun runOnce(territory: TerritoryType) {
generated.clear()
runImpl(territory, 0L)
}
private fun runImpl(territory: TerritoryType, seed: Long) {
HEE.log.info("[TerritoryGenerationBenchmarkScreen] generating " + territory.name)
val timeStart = System.currentTimeMillis()
generated.add(territory.generate(Random(seed)).first)
val timeEnd = System.currentTimeMillis()
HEE.log.info("[TerritoryGenerationBenchmarkScreen] finished in ${timeEnd - timeStart} ms")
}
}

View File

@@ -1,102 +0,0 @@
package chylex.hee.game.block
import chylex.hee.debug.PowerShell
import chylex.hee.game.Environment
import chylex.hee.game.block.components.IPlayerUseBlockComponent
import chylex.hee.game.command.client.CommandClientScaffolding
import chylex.hee.game.world.generation.structure.file.StructureFile
import chylex.hee.game.world.generation.util.WorldToStructureWorldAdapter
import chylex.hee.game.world.util.getBlock
import chylex.hee.game.world.util.offsetUntilExcept
import chylex.hee.util.math.BoundingBox
import chylex.hee.util.math.Pos
import net.minecraft.block.BlockState
import net.minecraft.block.Blocks
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.nbt.CompressedStreamTools
import net.minecraft.util.ActionResultType
import net.minecraft.util.ActionResultType.FAIL
import net.minecraft.util.ActionResultType.SUCCESS
import net.minecraft.util.Direction
import net.minecraft.util.Direction.DOWN
import net.minecraft.util.Direction.EAST
import net.minecraft.util.Direction.NORTH
import net.minecraft.util.Direction.SOUTH
import net.minecraft.util.Direction.UP
import net.minecraft.util.Direction.WEST
import net.minecraft.util.Hand
import net.minecraft.util.Util
import net.minecraft.util.math.BlockPos
import net.minecraft.util.text.StringTextComponent
import net.minecraft.util.text.TextFormatting
import net.minecraft.world.World
import java.nio.file.Files
object BlockScaffoldingDebug : IPlayerUseBlockComponent {
override fun use(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand): ActionResultType {
if (world.isRemote && player.isSneaking && !player.abilities.isFlying) {
val palette = CommandClientScaffolding.currentPalette
if (palette == null) {
player.sendMessage(StringTextComponent("No structure set."), Util.DUMMY_UUID)
return FAIL
}
val minPos = findMinPos(world, pos)?.let { findMinPos(world, it) } // double pass to find min from any side
val maxPos = minPos?.let { findMaxPos(world, it) }
if (minPos == null || maxPos == null) {
player.sendMessage(StringTextComponent("Could not find structure boundaries."), Util.DUMMY_UUID)
return FAIL
}
val box = BoundingBox(minPos, maxPos)
val serverWorld = Environment.getDimension(world.dimensionKey)
val (structureTag, missingMappings) = StructureFile.save(WorldToStructureWorldAdapter(serverWorld, serverWorld.rand, box.min), box.size, palette, state.block)
val structureFile = Files.createTempDirectory("HardcoreEnderExpansion_Structure_").resolve(CommandClientScaffolding.currentFile).toFile()
CompressedStreamTools.write(structureTag, structureFile)
PowerShell.setClipboardContents(structureFile)
if (missingMappings.isNotEmpty()) {
player.sendMessage(StringTextComponent("Missing mappings for states:"), Util.DUMMY_UUID)
for (missingMapping in missingMappings) {
player.sendMessage(StringTextComponent(" - ${TextFormatting.GRAY}$missingMapping"), Util.DUMMY_UUID)
}
}
player.sendMessage(StringTextComponent("Generated structure file of ${box.size}."), Util.DUMMY_UUID)
return SUCCESS
}
return FAIL
}
// Helpers
private fun find(world: World, pos: BlockPos?, direction: Direction): BlockPos? {
return pos?.offsetUntilExcept(direction, 0..255) { it.getBlock(world) === Blocks.AIR }
}
private fun findMinPos(world: World, pos: BlockPos): BlockPos? {
val bottomPos = find(world, pos, DOWN)
val y = bottomPos?.y
val x = find(world, bottomPos, WEST)?.x
val z = find(world, bottomPos, NORTH)?.z
return if (x == null || y == null || z == null) null else Pos(x, y, z)
}
private fun findMaxPos(world: World, pos: BlockPos): BlockPos? {
val topPos = find(world, pos, UP)
val y = topPos?.y
val x = find(world, topPos, EAST)?.x
val z = find(world, topPos, SOUTH)?.z
return if (x == null || y == null || z == null) null else Pos(x, y, z)
}
}

View File

@@ -1,7 +0,0 @@
{
"pack": {
"description": "Hardcore Ender Expansion 2 (Debug Library)",
"pack_format": 6,
"_comment": ""
}
}

View File

@@ -1,7 +1,6 @@
package chylex.hee
import chylex.hee.game.Resource
import chylex.hee.system.IDebugModule
import net.minecraft.util.RegistryKey
import net.minecraft.util.registry.Registry
import net.minecraft.world.World
@@ -13,10 +12,6 @@ object HEE {
lateinit var version: String
@JvmField
var debug = false
var debugModule: IDebugModule? = null
val log: Logger = LogManager.getLogger("HardcoreEnderExpansion")
val dim: RegistryKey<World> = RegistryKey.getOrCreateKey(Registry.WORLD_KEY, Resource.Custom("end"))
}

View File

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

View File

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

View File

@@ -1,229 +0,0 @@
package chylex.hee.game.block
import chylex.hee.game.block.builder.HeeBlockComponents
import chylex.hee.game.world.util.getBlock
import chylex.hee.util.forge.Side
import chylex.hee.util.forge.Sided
import chylex.hee.util.forge.asBool
import net.minecraft.block.Block
import net.minecraft.block.BlockRenderType
import net.minecraft.block.BlockState
import net.minecraft.client.util.ITooltipFlag
import net.minecraft.entity.Entity
import net.minecraft.entity.EntitySpawnPlacementRegistry.PlacementType
import net.minecraft.entity.EntityType
import net.minecraft.entity.LivingEntity
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.BlockItemUseContext
import net.minecraft.item.ItemStack
import net.minecraft.loot.LootContext
import net.minecraft.state.StateContainer.Builder
import net.minecraft.tileentity.TileEntity
import net.minecraft.util.ActionResultType
import net.minecraft.util.Direction
import net.minecraft.util.Hand
import net.minecraft.util.Mirror
import net.minecraft.util.Rotation
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.BlockRayTraceResult
import net.minecraft.util.math.RayTraceResult
import net.minecraft.util.math.shapes.ISelectionContext
import net.minecraft.util.math.shapes.VoxelShape
import net.minecraft.util.text.ITextComponent
import net.minecraft.world.Explosion
import net.minecraft.world.IBlockReader
import net.minecraft.world.IWorld
import net.minecraft.world.IWorldReader
import net.minecraft.world.World
import net.minecraft.world.server.ServerWorld
import java.util.Random
abstract class HeeBlockWithComponents(properties: Properties, components: HeeBlockComponents) : HeeBlock2(properties) {
private companion object {
private val RAND = Random()
}
private val states = components.states.build()
private val name = components.name
private val tooltip = components.tooltip
private val shape = components.shape
private val renderType = components.renderType
private val ambientOcclusionValue = components.ambientOcclusionValue
private val clientEffects = components.clientEffects
private val drops = components.drops
private val harvestability = components.harvestability
private val experience = components.experience
private val flammability = components.flammability
private val entity = components.entity
private val placement = components.placement
private val onAdded = components.onAdded
private val onNeighborChanged = components.onNeighborChanged
private val setStateFromNeighbor = components.setStateFromNeighbor
private val scheduledTick = components.scheduledTick
private val randomTick = components.randomTick
private val playerUse = components.playerUse
private val onExploded = components.onExploded
private val onCreatureSpawning = components.onCreatureSpawning
private val collideWithEntity = components.collideWithEntity
private var isAir = components.isAir
init {
defaultState = states.applyDefaults(stateContainer.baseState)
}
abstract override fun fillStateContainer(builder: Builder<Block, BlockState>)
override fun rotate(state: BlockState, rotation: Rotation): BlockState {
return states.getRotatedState(state, rotation)
}
override fun mirror(state: BlockState, mirror: Mirror): BlockState {
return states.getMirroredState(state, mirror)
}
override fun getTranslationKey(): String {
return name?.translationKey ?: super.getTranslationKey()
}
@Sided(Side.CLIENT)
override fun addInformation(stack: ItemStack, world: IBlockReader?, lines: MutableList<ITextComponent>, flags: ITooltipFlag) {
tooltip?.add(lines, stack, flags.isAdvanced, world)
}
@Suppress("DEPRECATION")
override fun getShape(state: BlockState, worldIn: IBlockReader, pos: BlockPos, context: ISelectionContext): VoxelShape {
return shape?.getShape(state) ?: super.getShape(state, worldIn, pos, context)
}
@Suppress("DEPRECATION")
override fun getCollisionShape(state: BlockState, worldIn: IBlockReader, pos: BlockPos, context: ISelectionContext): VoxelShape {
return shape?.getCollisionShape(state) ?: super.getCollisionShape(state, worldIn, pos, context)
}
override fun getRaytraceShape(state: BlockState, worldIn: IBlockReader, pos: BlockPos): VoxelShape {
return super.getRaytraceShape(state, worldIn, pos)
}
@Suppress("DEPRECATION")
override fun getRenderType(state: BlockState): BlockRenderType {
return renderType ?: super.getRenderType(state)
}
@Sided(Side.CLIENT)
@Suppress("DEPRECATION")
override fun getAmbientOcclusionLightValue(state: BlockState, worldIn: IBlockReader, pos: BlockPos): Float {
return ambientOcclusionValue ?: super.getAmbientOcclusionLightValue(state, worldIn, pos)
}
@Sided(Side.CLIENT)
override fun animateTick(state: BlockState, world: World, pos: BlockPos, rand: Random) {
clientEffects?.randomTick(state, world, pos, rand)
}
@Suppress("DEPRECATION")
override fun getDrops(state: BlockState, context: LootContext.Builder): MutableList<ItemStack> {
return drops?.getDrops(state, context) ?: super.getDrops(state, context)
}
override fun getPickBlock(state: BlockState, target: RayTraceResult, world: IBlockReader, pos: BlockPos, player: PlayerEntity): ItemStack {
return drops?.getPickBlock(state, world, pos) ?: super.getPickBlock(state, target, world, pos, player)
}
override fun canHarvestBlock(state: BlockState, world: IBlockReader, pos: BlockPos, player: PlayerEntity): Boolean {
return harvestability?.canHarvest(player)?.asBool ?: super.canHarvestBlock(state, world, pos, player)
}
override fun getExpDrop(state: BlockState, world: IWorldReader, pos: BlockPos, fortune: Int, silktouch: Int): Int {
return experience?.getExperience((world as? World)?.rand ?: RAND) ?: 0
}
override fun getFlammability(state: BlockState, world: IBlockReader, pos: BlockPos, face: Direction): Int {
return flammability?.takeIfFlammable(state)?.flammability ?: 0
}
override fun getFireSpreadSpeed(state: BlockState, world: IBlockReader, pos: BlockPos, face: Direction): Int {
return flammability?.takeIfFlammable(state)?.fireSpread ?: 0
}
override fun hasTileEntity(state: BlockState): Boolean {
return entity != null
}
override fun createTileEntity(state: BlockState, world: IBlockReader): TileEntity? {
return entity?.create()
}
@Suppress("DEPRECATION")
override fun isValidPosition(state: BlockState, world: IWorldReader, pos: BlockPos): Boolean {
return placement?.isPositionValid(state, world, pos) ?: super.isValidPosition(state, world, pos)
}
override fun getStateForPlacement(context: BlockItemUseContext): BlockState? {
return placement?.getPlacedState(defaultState, context.world, context.pos, context) ?: super.getStateForPlacement(context)
}
override fun onBlockPlacedBy(world: World, pos: BlockPos, state: BlockState, placer: LivingEntity?, stack: ItemStack) {
placement?.onPlacedBy(state, world, pos, placer, stack)
}
override fun onBlockAdded(state: BlockState, world: World, pos: BlockPos, oldState: BlockState, isMoving: Boolean) {
onAdded?.onAdded(state, world, pos)
scheduledTick?.onAdded(state, world, pos, world.rand)
}
@Suppress("DEPRECATION")
override fun neighborChanged(state: BlockState, world: World, pos: BlockPos, neighborBlock: Block, neighborPos: BlockPos, isMoving: Boolean) {
super.neighborChanged(state, world, pos, neighborBlock, neighborPos, isMoving)
onNeighborChanged?.onNeighborChanged(state, world, pos, neighborBlock, neighborPos.getBlock(world), neighborPos)
}
@Suppress("DEPRECATION")
override fun updatePostPlacement(state: BlockState, neighborFacing: Direction, neighborState: BlockState, world: IWorld, currentPos: BlockPos, neighborPos: BlockPos): BlockState {
return setStateFromNeighbor?.getNewState(state, world, currentPos, neighborFacing, neighborPos) ?: super.updatePostPlacement(state, neighborFacing, neighborState, world, currentPos, neighborPos)
}
override fun tick(state: BlockState, world: ServerWorld, pos: BlockPos, rand: Random) {
scheduledTick?.onTick(state, world, pos, rand)
}
override fun randomTick(state: BlockState, world: ServerWorld, pos: BlockPos, rand: Random) {
randomTick?.onTick(state, world, pos, rand)
}
@Suppress("DEPRECATION")
override fun onBlockActivated(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hit: BlockRayTraceResult): ActionResultType {
return playerUse?.use(state, world, pos, player, hand) ?: super.onBlockActivated(state, world, pos, player, hand, hit)
}
override fun canDropFromExplosion(state: BlockState, world: IBlockReader, pos: BlockPos, explosion: Explosion): Boolean {
return onExploded?.canDrop(explosion) ?: super.canDropFromExplosion(state, world, pos, explosion)
}
override fun onBlockExploded(state: BlockState, world: World, pos: BlockPos, explosion: Explosion) {
onExploded?.onExploded(state, world, pos, explosion)
super.onBlockExploded(state, world, pos, explosion)
}
override fun canCreatureSpawn(state: BlockState, world: IBlockReader, pos: BlockPos, type: PlacementType?, entityType: EntityType<*>?): Boolean {
return onCreatureSpawning?.canSpawn(world, pos, type, entityType)?.asBool ?: super.canCreatureSpawn(state, world, pos, type, entityType)
}
override fun onEntityCollision(state: BlockState, world: World, pos: BlockPos, entity: Entity) {
collideWithEntity?.collide(state, world, pos, entity)
}
override fun isAir(state: BlockState, world: IBlockReader, pos: BlockPos): Boolean {
return isAir ?: super.isAir(state, world, pos)
}
override fun propagatesSkylightDown(state: BlockState, world: IBlockReader, pos: BlockPos): Boolean {
return isAir == true || super.propagatesSkylightDown(state, world, pos)
}
}

View File

@@ -1,13 +1,12 @@
package chylex.hee.game.block
import chylex.hee.client.text.LocalizationStrategy
import chylex.hee.game.block.builder.AbstractHeeBlockBuilder
import chylex.hee.game.block.properties.BlockDrop
import chylex.hee.game.block.properties.BlockModel
import chylex.hee.game.block.properties.BlockRenderLayer
import chylex.hee.game.block.properties.BlockRenderLayer.SOLID
import chylex.hee.game.block.properties.BlockTint
import chylex.hee.game.block.properties.IBlockStateModelSupplier
import chylex.hee.game.block.properties.IBlockStateModel
import net.minecraft.block.Block
import net.minecraft.tags.ITag.INamedTag
@@ -18,7 +17,7 @@ interface IHeeBlock {
val localizationExtra: Map<String, String>
get() = emptyMap()
val model: IBlockStateModelSupplier
val model: IBlockStateModel
get() = BlockModel.Cube
val renderLayer: BlockRenderLayer
@@ -32,14 +31,4 @@ interface IHeeBlock {
val tags: List<INamedTag<Block>>
get() = emptyList()
class FromBuilder(builder: AbstractHeeBlockBuilder<*>) : IHeeBlock {
override val localization = builder.localization ?: super.localization
override val localizationExtra = builder.localizationExtra.toMap()
override val model = builder.model ?: super.model
override val renderLayer = builder.renderLayer ?: super.renderLayer
override val tint = builder.tint
override val drop = builder.drop ?: super.drop
override val tags = builder.tags.toList()
}
}

View File

@@ -1,149 +0,0 @@
package chylex.hee.game.block.builder
import chylex.hee.client.text.LocalizationStrategy
import chylex.hee.game.block.IHeeBlock
import chylex.hee.game.block.properties.BlockDrop
import chylex.hee.game.block.properties.BlockHardness
import chylex.hee.game.block.properties.BlockHarvestTool
import chylex.hee.game.block.properties.BlockRenderLayer
import chylex.hee.game.block.properties.BlockTint
import chylex.hee.game.block.properties.IBlockStateModelSupplier
import net.minecraft.block.AbstractBlock.IPositionPredicate
import net.minecraft.block.AbstractBlock.Properties
import net.minecraft.block.Block
import net.minecraft.block.SoundType
import net.minecraft.block.material.Material
import net.minecraft.block.material.MaterialColor
import net.minecraft.tags.ITag.INamedTag
abstract class AbstractHeeBlockBuilder<T : Block> {
private companion object {
private val DEFAULT_MATERIAL = Material.Builder(MaterialColor.AIR).build()
private fun always(value: Boolean): IPositionPredicate {
return IPositionPredicate { _, _, _ -> value }
}
}
var localization: LocalizationStrategy? = null
val localizationExtra = mutableMapOf<String, String>()
var model: IBlockStateModelSupplier? = null
var renderLayer: BlockRenderLayer? = null
var material: Material? = null
var color: MaterialColor? = null
var sound: SoundType? = null
var tint: BlockTint? = null
var light: Int? = null
var isSolid: Boolean? = null
var isOpaque: Boolean? = null
var suffocates: Boolean? = null
var blocksVision: Boolean? = null
var drop: BlockDrop? = null
var tool: BlockHarvestTool? = null
var hardness: BlockHardness? = null
private val lazyComponents = lazy(::HeeBlockComponents)
val components
get() = lazyComponents.value
val tags = mutableListOf<INamedTag<Block>>()
val interfaces = HeeBlockInterfaces()
fun includeFrom(source: AbstractHeeBlockBuilder<*>) {
source.localization?.let { this.localization = it }
this.localizationExtra.putAll(source.localizationExtra)
source.model?.let { this.model = it }
source.renderLayer?.let { this.renderLayer = it }
source.material?.let { this.material = it }
source.color?.let { this.color = it }
source.sound?.let { this.sound = it }
source.tint?.let { this.tint = it }
source.light?.let { this.light = it }
source.isSolid?.let { this.isSolid = it }
source.isOpaque?.let { this.isOpaque = it }
source.suffocates?.let { this.suffocates = it }
source.blocksVision?.let { this.blocksVision = it }
source.drop?.let { this.drop = it }
source.tool?.let { this.tool = it }
source.hardness?.let { this.hardness = it }
if (source.lazyComponents.isInitialized()) {
this.components.includeFrom(source.components)
}
this.tags.addAll(source.tags)
this.interfaces.includeFrom(source.interfaces)
}
protected val heeDelegate
get() = object : IHeeBlock {
override val localization = this@AbstractHeeBlockBuilder.localization ?: super.localization
override val localizationExtra = this@AbstractHeeBlockBuilder.localizationExtra.toMap()
override val model = this@AbstractHeeBlockBuilder.model ?: super.model
override val renderLayer = this@AbstractHeeBlockBuilder.renderLayer ?: super.renderLayer
override val tint = this@AbstractHeeBlockBuilder.tint
override val drop = this@AbstractHeeBlockBuilder.drop ?: super.drop
override val tags = this@AbstractHeeBlockBuilder.tags.toList()
}
private fun buildProperties(setup: ((Properties) -> Properties)?): Properties {
val material = material ?: DEFAULT_MATERIAL
val color = color ?: material.color
val tool = tool ?: BlockHarvestTool.NONE
var properties = Properties.create(material, color)
if (setup != null) {
properties = setup(properties)
}
properties = tool.applyTo(properties)
properties = properties.apply(sound, Properties::sound)
properties = properties.apply(light) { level -> setLightLevel { level } }
properties = properties.apply(isOpaque) { setOpaque(always(it)) }
properties = properties.apply(suffocates) { setSuffocates(always(it)) }
properties = properties.apply(blocksVision) { setBlocksVision(always(it)) }
properties = properties.apply(hardness) { it.applyTo(this) }
if (isSolid == false) {
properties = properties.notSolid()
}
if (!material.blocksMovement()) {
if (isSolid == true) {
throw UnsupportedOperationException("[AbstractHeeBlockBuilder] cannot create a block that does not block movement and is solid at the same time")
}
properties = properties.doesNotBlockMovement()
}
if (drop === BlockDrop.Nothing) {
properties = properties.noDrops()
}
if (lazyComponents.isInitialized() && components.randomTick != null) {
properties = properties.tickRandomly()
}
return properties
}
private inline fun <T> Properties.apply(value: T?, function: Properties.(T) -> Properties): Properties {
return if (value == null) this else function(value)
}
fun build(propertiesSetup: (Properties.() -> Properties)? = null): T {
val components = if (lazyComponents.isInitialized()) components else null
return buildBlock(buildProperties(propertiesSetup), components)
}
internal abstract fun buildBlock(properties: Properties, components: HeeBlockComponents?): T
}

View File

@@ -1,26 +0,0 @@
package chylex.hee.game.block.builder
import chylex.hee.game.block.HeeBlock2
import chylex.hee.game.block.HeeBlockWithComponents
import chylex.hee.game.block.IHeeBlock
import chylex.hee.game.block.interfaces.IBlockWithInterfaces
import net.minecraft.block.AbstractBlock.Properties
import net.minecraft.block.Block
import net.minecraft.block.BlockState
import net.minecraft.state.StateContainer.Builder
open class HeeBlockBuilder : AbstractHeeBlockBuilder<HeeBlock2>() {
override fun buildBlock(properties: Properties, components: HeeBlockComponents?): HeeBlock2 {
if (components != null) {
return object : HeeBlockWithComponents(properties, components), IHeeBlock by IHeeBlock.FromBuilder(this@HeeBlockBuilder), IBlockWithInterfaces by interfaces.delegate {
override fun fillStateContainer(builder: Builder<Block, BlockState>) {
components.states.fillContainer(builder)
}
}
}
return object : HeeBlock2(properties), IHeeBlock by IHeeBlock.FromBuilder(this), IBlockWithInterfaces by interfaces.delegate {}
}
}
inline fun HeeBlockBuilder(setup: HeeBlockBuilder.() -> Unit) = HeeBlockBuilder().apply(setup)

View File

@@ -1,86 +0,0 @@
package chylex.hee.game.block.builder
import chylex.hee.game.block.components.IBlockAddedComponent
import chylex.hee.game.block.components.IBlockClientEffectsComponent
import chylex.hee.game.block.components.IBlockCollideWithEntityComponent
import chylex.hee.game.block.components.IBlockDropsComponent
import chylex.hee.game.block.components.IBlockEntityComponent
import chylex.hee.game.block.components.IBlockExperienceComponent
import chylex.hee.game.block.components.IBlockExplodedComponent
import chylex.hee.game.block.components.IBlockHarvestabilityComponent
import chylex.hee.game.block.components.IBlockNameComponent
import chylex.hee.game.block.components.IBlockNeighborChanged
import chylex.hee.game.block.components.IBlockPlacementComponent
import chylex.hee.game.block.components.IBlockRandomTickComponent
import chylex.hee.game.block.components.IBlockScheduledTickComponent
import chylex.hee.game.block.components.IBlockShapeComponent
import chylex.hee.game.block.components.ICreatureSpawningOnBlockComponent
import chylex.hee.game.block.components.IFlammableBlockComponent
import chylex.hee.game.block.components.IPlayerUseBlockComponent
import chylex.hee.game.block.components.ISetBlockStateFromNeighbor
import chylex.hee.game.item.components.ITooltipComponent
import net.minecraft.block.BlockRenderType
class HeeBlockComponents {
val states = HeeBlockStates.Builder()
var name: IBlockNameComponent? = null
var tooltip: ITooltipComponent? = null
var shape: IBlockShapeComponent? = null
var renderType: BlockRenderType? = null
var ambientOcclusionValue: Float? = null
var clientEffects: IBlockClientEffectsComponent? = null
var drops: IBlockDropsComponent? = null
var harvestability: IBlockHarvestabilityComponent? = null
var experience: IBlockExperienceComponent? = null
var flammability: IFlammableBlockComponent? = null
var entity: IBlockEntityComponent? = null
var placement: IBlockPlacementComponent? = null
var onAdded: IBlockAddedComponent? = null
var onNeighborChanged: IBlockNeighborChanged? = null
var setStateFromNeighbor: ISetBlockStateFromNeighbor? = null
var scheduledTick: IBlockScheduledTickComponent? = null
var randomTick: IBlockRandomTickComponent? = null
var playerUse: IPlayerUseBlockComponent? = null
var onExploded: IBlockExplodedComponent? = null
var onCreatureSpawning: ICreatureSpawningOnBlockComponent? = null
var collideWithEntity: IBlockCollideWithEntityComponent? = null
var isAir: Boolean? = null
fun includeFrom(source: HeeBlockComponents) {
source.name?.let { this.name = it }
source.tooltip?.let { this.tooltip = it }
source.shape?.let { this.shape = it }
source.renderType?.let { this.renderType = it }
source.ambientOcclusionValue?.let { this.ambientOcclusionValue = it }
source.clientEffects?.let { this.clientEffects = it }
source.drops?.let { this.drops = it }
source.harvestability?.let { this.harvestability = it }
source.experience?.let { this.experience = it }
source.flammability?.let { this.flammability = it }
source.entity?.let { this.entity = it }
source.placement?.let { this.placement = it }
source.onAdded?.let { this.onAdded = it }
source.onNeighborChanged?.let { this.onNeighborChanged = it }
source.setStateFromNeighbor?.let { this.setStateFromNeighbor = it }
source.scheduledTick?.let { this.scheduledTick = it }
source.randomTick?.let { this.randomTick = it }
source.playerUse?.let { this.playerUse = it }
source.onExploded?.let { this.onExploded = it }
source.onCreatureSpawning?.let { this.onCreatureSpawning = it }
source.collideWithEntity?.let { this.collideWithEntity = it }
source.isAir?.let { this.isAir = it }
}
}

View File

@@ -1,23 +0,0 @@
package chylex.hee.game.block.builder
import chylex.hee.game.block.interfaces.BlockInterfaceContainer
import chylex.hee.game.block.interfaces.IBlockInterface
import chylex.hee.game.block.interfaces.NoBlockInterfaces
class HeeBlockInterfaces {
private val interfaces = mutableMapOf<Class<out IBlockInterface>, Any>()
internal val delegate
get() = if (interfaces.isEmpty())
NoBlockInterfaces
else
BlockInterfaceContainer(interfaces)
operator fun <T : IBlockInterface> set(type: Class<T>, impl: T) {
interfaces[type] = impl
}
fun includeFrom(source: HeeBlockInterfaces) {
this.interfaces.putAll(source.interfaces)
}
}

View File

@@ -1,50 +0,0 @@
package chylex.hee.game.block.builder
import chylex.hee.game.block.util.BlockStateGenerics
import net.minecraft.block.Block
import net.minecraft.block.BlockState
import net.minecraft.state.Property
import net.minecraft.state.StateContainer
import net.minecraft.util.Direction
import net.minecraft.util.Mirror
import net.minecraft.util.Rotation
class HeeBlockStates private constructor(private val statesWithDefaults: Map<Property<*>, Comparable<*>>, private val facingProperty: Property<Direction>?) {
fun applyDefaults(state: BlockState): BlockState {
if (statesWithDefaults.isEmpty()) {
return state
}
return statesWithDefaults.entries.fold(state) { acc, entry ->
BlockStateGenerics.withProperty(acc, entry.key, entry.value)
}
}
fun getRotatedState(state: BlockState, rotation: Rotation): BlockState {
return facingProperty?.let { state.with(it, rotation.rotate(state[it])) } ?: state
}
fun getMirroredState(state: BlockState, mirror: Mirror): BlockState {
return facingProperty?.let { state.with(it, mirror.mirror(state[it])) } ?: state
}
class Builder {
private val statesWithDefaults = mutableMapOf<Property<*>, Comparable<*>>()
var facingProperty: Property<Direction>? = null
fun <T : Comparable<T>> set(state: Property<T>, default: T) {
statesWithDefaults[state] = default
}
fun fillContainer(builder: StateContainer.Builder<Block, BlockState>) {
for (property in statesWithDefaults.keys) {
builder.add(property)
}
}
fun build(): HeeBlockStates {
return HeeBlockStates(statesWithDefaults.toMap(), facingProperty)
}
}
}

View File

@@ -1,9 +0,0 @@
package chylex.hee.game.block.components
import net.minecraft.block.BlockState
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
fun interface IBlockAddedComponent {
fun onAdded(state: BlockState, world: World, pos: BlockPos)
}

View File

@@ -1,10 +0,0 @@
package chylex.hee.game.block.components
import net.minecraft.block.BlockState
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
import java.util.Random
interface IBlockClientEffectsComponent {
fun randomTick(state: BlockState, world: World, pos: BlockPos, rand: Random) {}
}

View File

@@ -1,10 +0,0 @@
package chylex.hee.game.block.components
import net.minecraft.block.BlockState
import net.minecraft.entity.Entity
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
fun interface IBlockCollideWithEntityComponent {
fun collide(state: BlockState, world: World, pos: BlockPos, entity: Entity)
}

View File

@@ -1,15 +0,0 @@
package chylex.hee.game.block.components
import net.minecraft.block.BlockState
import net.minecraft.item.ItemStack
import net.minecraft.loot.LootContext
import net.minecraft.util.math.BlockPos
import net.minecraft.world.IBlockReader
interface IBlockDropsComponent {
fun getDrops(state: BlockState, context: LootContext.Builder): MutableList<ItemStack>
fun getPickBlock(state: BlockState, world: IBlockReader, pos: BlockPos): ItemStack? {
return null
}
}

View File

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

View File

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

View File

@@ -1,11 +0,0 @@
package chylex.hee.game.block.components
import net.minecraft.block.BlockState
import net.minecraft.util.math.BlockPos
import net.minecraft.world.Explosion
import net.minecraft.world.World
interface IBlockExplodedComponent {
fun canDrop(explosion: Explosion): Boolean
fun onExploded(state: BlockState, world: World, pos: BlockPos, explosion: Explosion)
}

View File

@@ -1,8 +0,0 @@
package chylex.hee.game.block.components
import chylex.hee.util.forge.EventResult
import net.minecraft.entity.player.PlayerEntity
fun interface IBlockHarvestabilityComponent {
fun canHarvest(player: PlayerEntity): EventResult
}

View File

@@ -1,19 +0,0 @@
package chylex.hee.game.block.components
import net.minecraft.block.Block
interface IBlockNameComponent {
val translationKey: String
companion object {
fun of(translationKey: String) = object : IBlockNameComponent {
override val translationKey
get() = translationKey
}
fun of(block: Block) = object : IBlockNameComponent {
override val translationKey
get() = block.translationKey
}
}
}

View File

@@ -1,10 +0,0 @@
package chylex.hee.game.block.components
import net.minecraft.block.Block
import net.minecraft.block.BlockState
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
fun interface IBlockNeighborChanged {
fun onNeighborChanged(state: BlockState, world: World, pos: BlockPos, oldNeighborBlock: Block, newNeighborBlock: Block, neighborPos: BlockPos)
}

View File

@@ -1,21 +0,0 @@
package chylex.hee.game.block.components
import net.minecraft.block.BlockState
import net.minecraft.entity.LivingEntity
import net.minecraft.item.BlockItemUseContext
import net.minecraft.item.ItemStack
import net.minecraft.util.math.BlockPos
import net.minecraft.world.IWorldReader
import net.minecraft.world.World
interface IBlockPlacementComponent {
fun isPositionValid(state: BlockState, world: IWorldReader, pos: BlockPos): Boolean {
return true
}
fun getPlacedState(defaultState: BlockState, world: World, pos: BlockPos, context: BlockItemUseContext): BlockState {
return defaultState
}
fun onPlacedBy(state: BlockState, world: World, pos: BlockPos, placer: LivingEntity?, stack: ItemStack) {}
}

View File

@@ -1,10 +0,0 @@
package chylex.hee.game.block.components
import net.minecraft.block.BlockState
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
import java.util.Random
fun interface IBlockRandomTickComponent {
fun onTick(state: BlockState, world: World, pos: BlockPos, rand: Random)
}

View File

@@ -1,19 +0,0 @@
package chylex.hee.game.block.components
import chylex.hee.game.block.properties.TickSchedule
import net.minecraft.block.BlockState
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
import java.util.Random
interface IBlockScheduledTickComponent {
/**
* Return the amount of ticks before the first [onTick] call after the block is added to the world.
*/
fun onAdded(state: BlockState, world: World, pos: BlockPos, rand: Random): TickSchedule
/**
* Return the amount of ticks before the next [onTick] call.
*/
fun onTick(state: BlockState, world: World, pos: BlockPos, rand: Random): TickSchedule
}

View File

@@ -1,30 +0,0 @@
package chylex.hee.game.block.components
import chylex.hee.game.block.util.asVoxelShape
import net.minecraft.block.BlockState
import net.minecraft.util.math.AxisAlignedBB
import net.minecraft.util.math.shapes.VoxelShape
interface IBlockShapeComponent {
fun getShape(state: BlockState): VoxelShape
fun getCollisionShape(state: BlockState): VoxelShape? {
return null
}
fun getRaytraceShape(state: BlockState): VoxelShape? {
return null
}
companion object {
fun of(shape: VoxelShape) = object : IBlockShapeComponent {
override fun getShape(state: BlockState): VoxelShape {
return shape
}
}
fun of(aabb: AxisAlignedBB): IBlockShapeComponent {
return of(aabb.asVoxelShape)
}
}
}

View File

@@ -1,11 +0,0 @@
package chylex.hee.game.block.components
import chylex.hee.util.forge.EventResult
import net.minecraft.entity.EntitySpawnPlacementRegistry.PlacementType
import net.minecraft.entity.EntityType
import net.minecraft.util.math.BlockPos
import net.minecraft.world.IBlockReader
fun interface ICreatureSpawningOnBlockComponent {
fun canSpawn(world: IBlockReader, pos: BlockPos, placementType: PlacementType?, entityType: EntityType<*>?): EventResult
}

View File

@@ -1,20 +0,0 @@
package chylex.hee.game.block.components
import net.minecraft.block.BlockState
import net.minecraft.state.properties.BlockStateProperties
interface IFlammableBlockComponent {
val flammability: Int
val fireSpread: Int
fun takeIfFlammable(state: BlockState): IFlammableBlockComponent? {
return this.takeUnless { state.hasProperty(BlockStateProperties.WATERLOGGED) && state[BlockStateProperties.WATERLOGGED] }
}
companion object {
fun of(flammability: Int, fireSpread: Int) = object : IFlammableBlockComponent {
override val flammability = flammability
override val fireSpread = fireSpread
}
}
}

View File

@@ -1,12 +0,0 @@
package chylex.hee.game.block.components
import net.minecraft.block.BlockState
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.util.ActionResultType
import net.minecraft.util.Hand
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
fun interface IPlayerUseBlockComponent {
fun use(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand): ActionResultType
}

View File

@@ -1,10 +0,0 @@
package chylex.hee.game.block.components
import net.minecraft.block.BlockState
import net.minecraft.util.Direction
import net.minecraft.util.math.BlockPos
import net.minecraft.world.IWorld
fun interface ISetBlockStateFromNeighbor {
fun getNewState(state: BlockState, world: IWorld, pos: BlockPos, neighborFacing: Direction, neighborPos: BlockPos): BlockState
}

View File

@@ -1,9 +0,0 @@
package chylex.hee.game.block.interfaces
internal class BlockInterfaceContainer(interfaces: Map<Class<out IBlockInterface>, Any>) : IBlockWithInterfaces {
private val interfaces = interfaces.toMap()
override fun getInterface(type: Class<out IBlockInterface>): Any? {
return interfaces[type]
}
}

View File

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

View File

@@ -1,15 +0,0 @@
package chylex.hee.game.block.interfaces
import net.minecraft.block.Block
interface IBlockWithInterfaces {
fun getInterface(type: Class<out IBlockInterface>): Any?
}
inline fun <reified T : IBlockInterface> IBlockWithInterfaces.getHeeInterface(): T? {
return this.getInterface(T::class.java) as? T
}
inline fun <reified T : IBlockInterface> Block.getHeeInterface(): T? {
return (this as? IBlockWithInterfaces)?.getHeeInterface()
}

View File

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

View File

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

View File

@@ -1,11 +0,0 @@
package chylex.hee.game.block.properties
import net.minecraft.block.AbstractBlock.Properties
data class BlockHardness(val hardness: Float, val resistance: Float) {
constructor(hardnessAndResistance: Float) : this(hardnessAndResistance, hardnessAndResistance)
fun applyTo(properties: Properties): Properties {
return properties.hardnessAndResistance(hardness, resistance)
}
}

View File

@@ -1,21 +0,0 @@
package chylex.hee.game.block.properties
import net.minecraft.block.AbstractBlock.Properties
import net.minecraftforge.common.ToolType
@Suppress("DataClassPrivateConstructor")
data class BlockHarvestTool private constructor(val tier: Int, val toolType: ToolType?, val requiresTool: Boolean) {
fun applyTo(properties: Properties): Properties {
return properties
.harvestLevel(tier)
.let { if (toolType != null) it.harvestTool(toolType) else it }
.let { if (requiresTool) it.setRequiresTool() else it }
}
companion object {
val NONE = BlockHarvestTool(-1, null, requiresTool = false)
fun required(tier: Int, toolType: ToolType) = BlockHarvestTool(tier, toolType, requiresTool = true)
fun optional(tier: Int, toolType: ToolType) = BlockHarvestTool(tier, toolType, requiresTool = false)
}
}

View File

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

View File

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

View File

@@ -1,19 +0,0 @@
package chylex.hee.game.block.properties
import net.minecraft.block.Block
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
sealed class TickSchedule {
abstract fun schedule(world: World, pos: BlockPos, block: Block)
object Never : TickSchedule() {
override fun schedule(world: World, pos: BlockPos, block: Block) {}
}
class InTicks(private val ticks: Int) : TickSchedule() {
override fun schedule(world: World, pos: BlockPos, block: Block) {
world.pendingBlockTicks.scheduleTick(pos, block, ticks)
}
}
}

View File

@@ -1,10 +1,10 @@
package chylex.hee.game.entity.living.path
import chylex.hee.game.entity.util.posVec
import chylex.hee.system.random.nextInt
import chylex.hee.util.math.Vec
import chylex.hee.util.math.Vec3
import chylex.hee.util.math.square
import chylex.hee.util.random.nextInt
import net.minecraft.entity.Entity
import net.minecraft.entity.MobEntity
import net.minecraft.pathfinding.GroundPathNavigator

View File

@@ -1,7 +0,0 @@
package chylex.hee.game.item
import chylex.hee.game.item.interfaces.IItemWithInterfaces
import net.minecraft.block.Block
import net.minecraft.item.BlockItem
abstract class HeeBlockItem(block: Block, properties: Properties) : BlockItem(block, properties), IHeeItem, IItemWithInterfaces

View File

@@ -1,156 +0,0 @@
package chylex.hee.game.item
import chylex.hee.game.item.builder.HeeItemComponents
import chylex.hee.util.forge.Side
import chylex.hee.util.forge.Sided
import net.minecraft.block.Block
import net.minecraft.block.DispenserBlock
import net.minecraft.client.util.ITooltipFlag
import net.minecraft.entity.Entity
import net.minecraft.entity.LivingEntity
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemGroup
import net.minecraft.item.ItemStack
import net.minecraft.item.ItemUseContext
import net.minecraft.item.Rarity
import net.minecraft.item.UseAction
import net.minecraft.util.ActionResult
import net.minecraft.util.ActionResultType
import net.minecraft.util.Hand
import net.minecraft.util.NonNullList
import net.minecraft.util.text.ITextComponent
import net.minecraft.world.World
abstract class HeeBlockItemWithComponents(block: Block, properties: Properties, components: HeeItemComponents) : HeeBlockItem(block, properties) {
private val name = components.name
private val tooltip = components.tooltip.toTypedArray()
private val glint = components.glint
private val rarity = components.rarity
private val reequipAnimation = components.reequipAnimation
private val creativeTab = components.creativeTab
private val useOnAir = components.useOnAir
private val beforeUseOnBlock = components.beforeUseOnBlock
private val useOnBlock = components.useOnBlock
private val useOnEntity = components.useOnEntity
private val consume = components.consume
private val tickInInventory = components.tickInInventory.toTypedArray()
private val itemEntity = components.itemEntity
private val burnTime = components.furnaceBurnTime
private val durability = components.durability
private val repair = components.repair
init {
components.dispenserBehavior?.let { DispenserBlock.registerDispenseBehavior(this, it) }
}
override fun getDefaultTranslationKey(): String {
return name?.defaultTranslationKey ?: super.getDefaultTranslationKey()
}
override fun getTranslationKey(stack: ItemStack): String {
return name?.getTranslationKey(stack) ?: super.getTranslationKey(stack)
}
override fun getDisplayName(stack: ItemStack): ITextComponent {
return name?.getDisplayName(stack) ?: super.getDisplayName(stack)
}
@Sided(Side.CLIENT)
override fun addInformation(stack: ItemStack, world: World?, lines: MutableList<ITextComponent>, flags: ITooltipFlag) {
super.addInformation(stack, world, lines, flags)
for (tooltipComponent in tooltip) {
tooltipComponent.add(lines, stack, flags.isAdvanced, world)
}
}
override fun hasEffect(stack: ItemStack): Boolean {
return glint?.hasGlint(stack) ?: super.hasEffect(stack)
}
override fun getRarity(stack: ItemStack): Rarity {
return rarity ?: super.getRarity(stack)
}
override fun shouldCauseReequipAnimation(oldStack: ItemStack, newStack: ItemStack, slotChanged: Boolean): Boolean {
return reequipAnimation?.shouldAnimate(oldStack, newStack, slotChanged) ?: super.shouldCauseReequipAnimation(oldStack, newStack, slotChanged)
}
override fun fillItemGroup(group: ItemGroup, items: NonNullList<ItemStack>) {
if (creativeTab == null) {
super.fillItemGroup(group, items)
}
else if (isInGroup(group)) {
creativeTab.addItems(items, this)
}
}
override fun onItemRightClick(world: World, player: PlayerEntity, hand: Hand): ActionResult<ItemStack> {
return useOnAir?.use(world, player, hand, player.getHeldItem(hand)) ?: super.onItemRightClick(world, player, hand)
}
override fun onItemUseFirst(stack: ItemStack, context: ItemUseContext): ActionResultType {
return beforeUseOnBlock?.beforeUse(context.world, context.pos, context, stack) ?: super.onItemUseFirst(stack, context)
}
override fun onItemUse(context: ItemUseContext): ActionResultType {
return useOnBlock?.use(context.world, context.pos, context) ?: super.onItemUse(context)
}
override fun itemInteractionForEntity(stack: ItemStack, player: PlayerEntity, target: LivingEntity, hand: Hand): ActionResultType {
return useOnEntity?.use(target.world, target, player, hand, stack) ?: super.itemInteractionForEntity(stack, player, target, hand)
}
override fun getUseAction(stack: ItemStack): UseAction {
return consume?.action ?: super.getUseAction(stack)
}
override fun getUseDuration(stack: ItemStack): Int {
return consume?.getDuration(stack) ?: super.getUseDuration(stack)
}
override fun onUsingTick(stack: ItemStack, entity: LivingEntity, tick: Int) {
consume?.tick(stack, entity, tick)
}
override fun onItemUseFinish(stack: ItemStack, world: World, entity: LivingEntity): ItemStack {
return consume?.finish(stack, entity) ?: super.onItemUseFinish(stack, world, entity)
}
override fun inventoryTick(stack: ItemStack, world: World, entity: Entity, slot: Int, isSelected: Boolean) {
for (component in tickInInventory) {
component.tick(world, entity, stack, slot, isSelected)
}
}
override fun hasCustomEntity(stack: ItemStack): Boolean {
return itemEntity != null && itemEntity.hasEntity(stack)
}
override fun createEntity(world: World, replacee: Entity, stack: ItemStack): Entity? {
return itemEntity?.createEntity(world, stack, replacee)
}
override fun getBurnTime(stack: ItemStack): Int {
return burnTime ?: super.getBurnTime(stack)
}
override fun showDurabilityBar(stack: ItemStack): Boolean {
return durability?.showBar(stack) ?: super.showDurabilityBar(stack)
}
override fun getDurabilityForDisplay(stack: ItemStack): Double {
return durability?.getDisplayDurability(stack) ?: super.getDurabilityForDisplay(stack)
}
override fun getRGBDurabilityForDisplay(stack: ItemStack): Int {
return durability?.getDisplayDurabilityRGB(stack) ?: super.getRGBDurabilityForDisplay(stack)
}
override fun getIsRepairable(toRepair: ItemStack, repairWith: ItemStack): Boolean {
return repair != null && repair.isRepairable(toRepair, repairWith)
}
}

View File

@@ -1,6 +1,5 @@
package chylex.hee.game.item
import chylex.hee.game.item.interfaces.IItemWithInterfaces
import net.minecraft.item.Item
abstract class HeeItem(properties: Properties) : Item(properties), IHeeItem, IItemWithInterfaces
open class HeeItem(properties: Properties) : Item(properties), IHeeItem

View File

@@ -1,155 +0,0 @@
package chylex.hee.game.item
import chylex.hee.game.item.builder.HeeItemComponents
import chylex.hee.util.forge.Side
import chylex.hee.util.forge.Sided
import net.minecraft.block.DispenserBlock
import net.minecraft.client.util.ITooltipFlag
import net.minecraft.entity.Entity
import net.minecraft.entity.LivingEntity
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemGroup
import net.minecraft.item.ItemStack
import net.minecraft.item.ItemUseContext
import net.minecraft.item.Rarity
import net.minecraft.item.UseAction
import net.minecraft.util.ActionResult
import net.minecraft.util.ActionResultType
import net.minecraft.util.Hand
import net.minecraft.util.NonNullList
import net.minecraft.util.text.ITextComponent
import net.minecraft.world.World
abstract class HeeItemWithComponents(properties: Properties, components: HeeItemComponents) : HeeItem(properties) {
private val name = components.name
private val tooltip = components.tooltip.toTypedArray()
private val glint = components.glint
private val rarity = components.rarity
private val reequipAnimation = components.reequipAnimation
private val creativeTab = components.creativeTab
private val useOnAir = components.useOnAir
private val beforeUseOnBlock = components.beforeUseOnBlock
private val useOnBlock = components.useOnBlock
private val useOnEntity = components.useOnEntity
private val consume = components.consume
private val tickInInventory = components.tickInInventory.toTypedArray()
private val itemEntity = components.itemEntity
private val burnTime = components.furnaceBurnTime
private val durability = components.durability
private val repair = components.repair
init {
components.dispenserBehavior?.let { DispenserBlock.registerDispenseBehavior(this, it) }
}
override fun getDefaultTranslationKey(): String {
return name?.defaultTranslationKey ?: super.getDefaultTranslationKey()
}
override fun getTranslationKey(stack: ItemStack): String {
return name?.getTranslationKey(stack) ?: super.getTranslationKey(stack)
}
override fun getDisplayName(stack: ItemStack): ITextComponent {
return name?.getDisplayName(stack) ?: super.getDisplayName(stack)
}
@Sided(Side.CLIENT)
override fun addInformation(stack: ItemStack, world: World?, lines: MutableList<ITextComponent>, flags: ITooltipFlag) {
super.addInformation(stack, world, lines, flags)
for (tooltipComponent in tooltip) {
tooltipComponent.add(lines, stack, flags.isAdvanced, world)
}
}
override fun hasEffect(stack: ItemStack): Boolean {
return glint?.hasGlint(stack) ?: super.hasEffect(stack)
}
override fun getRarity(stack: ItemStack): Rarity {
return rarity ?: super.getRarity(stack)
}
override fun shouldCauseReequipAnimation(oldStack: ItemStack, newStack: ItemStack, slotChanged: Boolean): Boolean {
return reequipAnimation?.shouldAnimate(oldStack, newStack, slotChanged) ?: super.shouldCauseReequipAnimation(oldStack, newStack, slotChanged)
}
override fun fillItemGroup(group: ItemGroup, items: NonNullList<ItemStack>) {
if (creativeTab == null) {
super.fillItemGroup(group, items)
}
else if (isInGroup(group)) {
creativeTab.addItems(items, this)
}
}
override fun onItemRightClick(world: World, player: PlayerEntity, hand: Hand): ActionResult<ItemStack> {
return useOnAir?.use(world, player, hand, player.getHeldItem(hand)) ?: super.onItemRightClick(world, player, hand)
}
override fun onItemUseFirst(stack: ItemStack, context: ItemUseContext): ActionResultType {
return beforeUseOnBlock?.beforeUse(context.world, context.pos, context, stack) ?: super.onItemUseFirst(stack, context)
}
override fun onItemUse(context: ItemUseContext): ActionResultType {
return useOnBlock?.use(context.world, context.pos, context) ?: super.onItemUse(context)
}
override fun itemInteractionForEntity(stack: ItemStack, player: PlayerEntity, target: LivingEntity, hand: Hand): ActionResultType {
return useOnEntity?.use(target.world, target, player, hand, stack) ?: super.itemInteractionForEntity(stack, player, target, hand)
}
override fun getUseAction(stack: ItemStack): UseAction {
return consume?.action ?: super.getUseAction(stack)
}
override fun getUseDuration(stack: ItemStack): Int {
return consume?.getDuration(stack) ?: super.getUseDuration(stack)
}
override fun onUsingTick(stack: ItemStack, entity: LivingEntity, tick: Int) {
consume?.tick(stack, entity, tick)
}
override fun onItemUseFinish(stack: ItemStack, world: World, entity: LivingEntity): ItemStack {
return consume?.finish(stack, entity) ?: super.onItemUseFinish(stack, world, entity)
}
override fun inventoryTick(stack: ItemStack, world: World, entity: Entity, slot: Int, isSelected: Boolean) {
for (component in tickInInventory) {
component.tick(world, entity, stack, slot, isSelected)
}
}
override fun hasCustomEntity(stack: ItemStack): Boolean {
return itemEntity != null && itemEntity.hasEntity(stack)
}
override fun createEntity(world: World, replacee: Entity, stack: ItemStack): Entity? {
return itemEntity?.createEntity(world, stack, replacee)
}
override fun getBurnTime(stack: ItemStack): Int {
return burnTime ?: super.getBurnTime(stack)
}
override fun showDurabilityBar(stack: ItemStack): Boolean {
return durability?.showBar(stack) ?: super.showDurabilityBar(stack)
}
override fun getDurabilityForDisplay(stack: ItemStack): Double {
return durability?.getDisplayDurability(stack) ?: super.getDurabilityForDisplay(stack)
}
override fun getRGBDurabilityForDisplay(stack: ItemStack): Int {
return durability?.getDisplayDurabilityRGB(stack) ?: super.getRGBDurabilityForDisplay(stack)
}
override fun getIsRepairable(toRepair: ItemStack, repairWith: ItemStack): Boolean {
return repair != null && repair.isRepairable(toRepair, repairWith)
}
}

View File

@@ -1,7 +1,6 @@
package chylex.hee.game.item
import chylex.hee.client.text.LocalizationStrategy
import chylex.hee.game.item.builder.AbstractHeeItemBuilder
import chylex.hee.game.item.properties.ItemModel
import chylex.hee.game.item.properties.ItemTint
import chylex.hee.game.item.util.ItemProperty
@@ -26,13 +25,4 @@ interface IHeeItem {
val tags: List<INamedTag<Item>>
get() = emptyList()
class FromBuilder(builder: AbstractHeeItemBuilder<*>) : IHeeItem {
override val localization = builder.localization ?: super.localization
override val localizationExtra = builder.localizationExtra.toMap()
override val model = builder.model ?: super.model
override val tint = builder.tint
override val properties = builder.properties.toList()
override val tags = builder.tags.toList()
}
}

View File

@@ -1,95 +0,0 @@
package chylex.hee.game.item.builder
import chylex.hee.client.text.LocalizationStrategy
import chylex.hee.game.item.properties.ItemModel
import chylex.hee.game.item.properties.ItemTint
import chylex.hee.game.item.util.ItemProperty
import net.minecraft.item.Food
import net.minecraft.item.Item
import net.minecraft.item.Item.Properties
import net.minecraft.tags.ITag.INamedTag
abstract class AbstractHeeItemBuilder<T : Item> {
var localization: LocalizationStrategy? = null
val localizationExtra = mutableMapOf<String, String>()
var model: ItemModel? = null
var tint: ItemTint? = null
val properties = mutableListOf<ItemProperty>()
var maxStackSize: Int? = null
var maxDamage: Int? = null
var food: Food? = null
var immuneToFire = false
var noRepair = false
private val lazyComponents = lazy(::HeeItemComponents)
val components
get() = lazyComponents.value
val tags = mutableListOf<INamedTag<Item>>()
val interfaces = HeeItemInterfaces()
val callbacks = mutableListOf<Item.() -> Unit>()
fun includeFrom(source: AbstractHeeItemBuilder<*>) {
source.localization?.let { this.localization = it }
this.localizationExtra.putAll(source.localizationExtra)
source.model?.let { this.model = it }
source.tint?.let { this.tint = it }
this.properties.addAll(source.properties)
source.maxStackSize?.let { this.maxStackSize = it }
source.maxDamage?.let { this.maxDamage = it }
source.food?.let { this.food = it }
this.immuneToFire = source.immuneToFire
this.noRepair = source.noRepair
if (source.lazyComponents.isInitialized()) {
this.components.includeFrom(source.components)
}
this.tags.addAll(source.tags)
this.interfaces.includeFrom(source.interfaces)
this.callbacks.addAll(source.callbacks)
}
private fun buildProperties(setup: ((Properties) -> Properties)?): Properties {
var properties = Properties()
if (setup != null) {
properties = setup(properties)
}
properties = properties.apply(maxStackSize, Properties::maxStackSize)
properties = properties.apply(maxDamage, Properties::maxDamage)
properties = properties.apply(food, Properties::food)
if (immuneToFire) {
properties = properties.isImmuneToFire
}
if (noRepair) {
properties = properties.setNoRepair()
}
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
val item = buildItem(buildProperties(propertiesSetup), components)
for (callback in callbacks) {
callback(item)
}
return item
}
internal abstract fun buildItem(properties: Properties, components: HeeItemComponents?): T
}

View File

@@ -1,19 +0,0 @@
package chylex.hee.game.item.builder
import chylex.hee.game.item.HeeBlockItem
import chylex.hee.game.item.HeeBlockItemWithComponents
import chylex.hee.game.item.IHeeItem
import chylex.hee.game.item.interfaces.IItemWithInterfaces
import net.minecraft.block.Block
import net.minecraft.item.Item.Properties
open class HeeBlockItemBuilder(private val block: Block) : AbstractHeeItemBuilder<HeeBlockItem>() {
override fun buildItem(properties: Properties, components: HeeItemComponents?): HeeBlockItem {
return if (components != null)
object : HeeBlockItemWithComponents(block, properties, components), IHeeItem by IHeeItem.FromBuilder(this), IItemWithInterfaces by interfaces.delegate {}
else
object : HeeBlockItem(block, properties), IHeeItem by IHeeItem.FromBuilder(this), IItemWithInterfaces by interfaces.delegate {}
}
}
inline fun HeeBlockItemBuilder(block: Block, setup: HeeBlockItemBuilder.() -> Unit) = HeeBlockItemBuilder(block).apply(setup)

View File

@@ -1,18 +0,0 @@
package chylex.hee.game.item.builder
import chylex.hee.game.item.HeeItem
import chylex.hee.game.item.HeeItemWithComponents
import chylex.hee.game.item.IHeeItem
import chylex.hee.game.item.interfaces.IItemWithInterfaces
import net.minecraft.item.Item.Properties
open class HeeItemBuilder : AbstractHeeItemBuilder<HeeItem>() {
override fun buildItem(properties: Properties, components: HeeItemComponents?): HeeItem {
return if (components != null)
object : HeeItemWithComponents(properties, components), IHeeItem by IHeeItem.FromBuilder(this), IItemWithInterfaces by interfaces.delegate {}
else
object : HeeItem(properties), IHeeItem by IHeeItem.FromBuilder(this), IItemWithInterfaces by interfaces.delegate {}
}
}
inline fun HeeItemBuilder(setup: HeeItemBuilder.() -> Unit) = HeeItemBuilder().apply(setup)

View File

@@ -1,66 +0,0 @@
package chylex.hee.game.item.builder
import chylex.hee.game.item.components.IBeforeUseItemOnBlockComponent
import chylex.hee.game.item.components.IConsumeItemComponent
import chylex.hee.game.item.components.ICreativeTabComponent
import chylex.hee.game.item.components.IItemDurabilityComponent
import chylex.hee.game.item.components.IItemEntityComponent
import chylex.hee.game.item.components.IItemGlintComponent
import chylex.hee.game.item.components.IItemNameComponent
import chylex.hee.game.item.components.IReequipAnimationComponent
import chylex.hee.game.item.components.IRepairItemComponent
import chylex.hee.game.item.components.ITickInInventoryComponent
import chylex.hee.game.item.components.ITooltipComponent
import chylex.hee.game.item.components.IUseItemOnAirComponent
import chylex.hee.game.item.components.IUseItemOnBlockComponent
import chylex.hee.game.item.components.IUseItemOnEntityComponent
import net.minecraft.dispenser.IDispenseItemBehavior
import net.minecraft.item.Rarity
class HeeItemComponents {
var name: IItemNameComponent? = null
val tooltip = mutableListOf<ITooltipComponent>()
var glint: IItemGlintComponent? = null
var rarity: Rarity? = null
var reequipAnimation: IReequipAnimationComponent? = null
var creativeTab: ICreativeTabComponent? = null
var useOnAir: IUseItemOnAirComponent? = null
var beforeUseOnBlock: IBeforeUseItemOnBlockComponent? = null
var useOnBlock: IUseItemOnBlockComponent? = null
var useOnEntity: IUseItemOnEntityComponent? = null
var consume: IConsumeItemComponent? = null
val tickInInventory = mutableListOf<ITickInInventoryComponent>()
var itemEntity: IItemEntityComponent? = null
var furnaceBurnTime: Int? = null
var durability: IItemDurabilityComponent? = null
var repair: IRepairItemComponent? = null
var dispenserBehavior: IDispenseItemBehavior? = null
fun includeFrom(source: HeeItemComponents) {
source.name?.let { this.name = it }
this.tooltip.addAll(source.tooltip)
source.glint?.let { this.glint = it }
source.rarity?.let { this.rarity = it }
source.reequipAnimation?.let { this.reequipAnimation = it }
source.creativeTab?.let { this.creativeTab = it }
source.useOnAir?.let { this.useOnAir = it }
source.beforeUseOnBlock?.let { this.beforeUseOnBlock = it }
source.useOnBlock?.let { this.useOnBlock = it }
source.useOnEntity?.let { this.useOnEntity = it }
source.consume?.let { this.consume = it }
this.tickInInventory.addAll(source.tickInInventory)
source.itemEntity?.let { this.itemEntity = it }
source.furnaceBurnTime?.let { this.furnaceBurnTime = it }
source.durability?.let { this.durability = it }
source.repair?.let { this.repair = it }
source.dispenserBehavior?.let { this.dispenserBehavior = it }
}
}

View File

@@ -1,23 +0,0 @@
package chylex.hee.game.item.builder
import chylex.hee.game.item.interfaces.IItemInterface
import chylex.hee.game.item.interfaces.ItemInterfaceContainer
import chylex.hee.game.item.interfaces.NoItemInterfaces
class HeeItemInterfaces {
private val interfaces = mutableMapOf<Class<out IItemInterface>, Any>()
internal val delegate
get() = if (interfaces.isEmpty())
NoItemInterfaces
else
ItemInterfaceContainer(interfaces)
operator fun <T : IItemInterface> set(type: Class<T>, impl: T) {
interfaces[type] = impl
}
fun includeFrom(source: HeeItemInterfaces) {
this.interfaces.putAll(source.interfaces)
}
}

View File

@@ -1,19 +0,0 @@
package chylex.hee.game.item.components
import net.minecraft.entity.LivingEntity
import net.minecraft.item.Food
import net.minecraft.item.ItemStack
import net.minecraft.item.UseAction
abstract class ConsumeFoodComponent(private val food: Food) : IConsumeItemComponent {
override val action
get() = UseAction.EAT
override fun getDuration(stack: ItemStack): Int {
return if (food.isFastEating) 16 else 32
}
override fun finish(stack: ItemStack, entity: LivingEntity): ItemStack {
return entity.onFoodEaten(entity.world, stack)
}
}

View File

@@ -1,9 +0,0 @@
package chylex.hee.game.item.components
import net.minecraft.item.ItemStack
object EnchantmentGlintComponent : IItemGlintComponent {
override fun hasGlint(stack: ItemStack): Boolean {
return stack.isEnchanted
}
}

View File

@@ -1,11 +0,0 @@
package chylex.hee.game.item.components
import net.minecraft.item.ItemStack
import net.minecraft.item.ItemUseContext
import net.minecraft.util.ActionResultType
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
fun interface IBeforeUseItemOnBlockComponent {
fun beforeUse(world: World, pos: BlockPos, context: ItemUseContext, stack: ItemStack): ActionResultType
}

View File

@@ -1,13 +0,0 @@
package chylex.hee.game.item.components
import net.minecraft.entity.LivingEntity
import net.minecraft.item.ItemStack
import net.minecraft.item.UseAction
interface IConsumeItemComponent {
val action: UseAction
fun getDuration(stack: ItemStack): Int
fun tick(stack: ItemStack, entity: LivingEntity, tick: Int) {}
fun finish(stack: ItemStack, entity: LivingEntity): ItemStack
}

View File

@@ -1,9 +0,0 @@
package chylex.hee.game.item.components
import net.minecraft.item.Item
import net.minecraft.item.ItemStack
import net.minecraft.util.NonNullList
fun interface ICreativeTabComponent {
fun addItems(tab: NonNullList<ItemStack>, item: Item)
}

View File

@@ -1,18 +0,0 @@
package chylex.hee.game.item.components
import net.minecraft.item.ItemStack
import net.minecraft.util.math.MathHelper
interface IItemDurabilityComponent {
fun showBar(stack: ItemStack): Boolean {
return stack.isDamaged
}
fun getDisplayDurability(stack: ItemStack): Double {
return stack.damage.toDouble() / stack.maxDamage.toDouble()
}
fun getDisplayDurabilityRGB(stack: ItemStack): Int {
return MathHelper.hsvToRGB((1F - getDisplayDurability(stack)).toFloat().coerceAtLeast(0F) / 3F, 1F, 1F)
}
}

View File

@@ -1,22 +0,0 @@
package chylex.hee.game.item.components
import net.minecraft.entity.Entity
import net.minecraft.entity.item.ItemEntity
import net.minecraft.item.ItemStack
import net.minecraft.world.World
interface IItemEntityComponent {
fun hasEntity(stack: ItemStack): Boolean {
return true
}
fun createEntity(world: World, stack: ItemStack, replacee: Entity): ItemEntity
companion object {
fun fromConstructor(constructor: (World, ItemStack, Entity) -> ItemEntity) = object : IItemEntityComponent {
override fun createEntity(world: World, stack: ItemStack, replacee: Entity): ItemEntity {
return constructor(world, stack, replacee)
}
}
}
}

View File

@@ -1,13 +0,0 @@
package chylex.hee.game.item.components
import net.minecraft.item.ItemStack
fun interface IItemGlintComponent {
fun hasGlint(stack: ItemStack): Boolean
companion object {
fun either(left: IItemGlintComponent, right: IItemGlintComponent) = IItemGlintComponent {
left.hasGlint(it) || right.hasGlint(it)
}
}
}

View File

@@ -1,30 +0,0 @@
package chylex.hee.game.item.components
import net.minecraft.item.Item
import net.minecraft.item.ItemStack
import net.minecraft.util.text.ITextComponent
interface IItemNameComponent {
val defaultTranslationKey: String?
get() = null
fun getTranslationKey(stack: ItemStack): String? {
return null
}
fun getDisplayName(stack: ItemStack): ITextComponent? {
return null
}
companion object {
fun of(translationKey: String) = object : IItemNameComponent {
override val defaultTranslationKey
get() = translationKey
}
fun of(item: Item) = object : IItemNameComponent {
override val defaultTranslationKey
get() = item.translationKey
}
}
}

View File

@@ -1,16 +0,0 @@
package chylex.hee.game.item.components
import net.minecraft.item.ItemStack
interface IReequipAnimationComponent {
fun shouldAnimate(oldStack: ItemStack, newStack: ItemStack, slotChanged: Boolean): Boolean {
return oldStack != newStack
}
object AnimateIfSlotChanged : IReequipAnimationComponent {
@Suppress("KotlinConstantConditions")
override fun shouldAnimate(oldStack: ItemStack, newStack: ItemStack, slotChanged: Boolean): Boolean {
return slotChanged && super.shouldAnimate(oldStack, newStack, slotChanged)
}
}
}

View File

@@ -1,7 +0,0 @@
package chylex.hee.game.item.components
import net.minecraft.item.ItemStack
fun interface IRepairItemComponent {
fun isRepairable(toRepair: ItemStack, repairWith: ItemStack): Boolean
}

View File

@@ -1,9 +0,0 @@
package chylex.hee.game.item.components
import net.minecraft.entity.Entity
import net.minecraft.item.ItemStack
import net.minecraft.world.World
fun interface ITickInInventoryComponent {
fun tick(world: World, entity: Entity, stack: ItemStack, slot: Int, isSelected: Boolean)
}

View File

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

View File

@@ -1,11 +0,0 @@
package chylex.hee.game.item.components
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
import net.minecraft.util.ActionResult
import net.minecraft.util.Hand
import net.minecraft.world.World
fun interface IUseItemOnAirComponent {
fun use(world: World, player: PlayerEntity, hand: Hand, heldItem: ItemStack): ActionResult<ItemStack>
}

View File

@@ -1,10 +0,0 @@
package chylex.hee.game.item.components
import net.minecraft.item.ItemUseContext
import net.minecraft.util.ActionResultType
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
fun interface IUseItemOnBlockComponent {
fun use(world: World, pos: BlockPos, context: ItemUseContext): ActionResultType
}

View File

@@ -1,12 +0,0 @@
package chylex.hee.game.item.components
import net.minecraft.entity.LivingEntity
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
import net.minecraft.util.ActionResultType
import net.minecraft.util.Hand
import net.minecraft.world.World
fun interface IUseItemOnEntityComponent {
fun use(world: World, target: LivingEntity, player: PlayerEntity, hand: Hand, heldItem: ItemStack): ActionResultType
}

View File

@@ -1,28 +0,0 @@
package chylex.hee.game.item.components
import chylex.hee.game.world.util.BlockEditor
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
import net.minecraft.item.ItemUseContext
import net.minecraft.util.ActionResultType
import net.minecraft.util.ActionResultType.FAIL
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
abstract class PlayerUseItemOnBlockComponent : IUseItemOnBlockComponent {
protected open val requiresEditPermission
get() = true
final override fun use(world: World, pos: BlockPos, context: ItemUseContext): ActionResultType {
val player = context.player ?: return FAIL
val heldItem = player.getHeldItem(context.hand)
if (requiresEditPermission && !BlockEditor.canEdit(pos, player, heldItem)) {
return FAIL
}
return use(world, pos, player, heldItem, context)
}
protected abstract fun use(world: World, pos: BlockPos, player: PlayerEntity, heldItem: ItemStack, context: ItemUseContext): ActionResultType
}

View File

@@ -1,27 +0,0 @@
package chylex.hee.game.item.components
import net.minecraft.entity.Entity
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
import net.minecraft.stats.Stats
import net.minecraft.util.ActionResult
import net.minecraft.util.Hand
import net.minecraft.world.World
abstract class ShootProjectileComponent : IUseItemOnAirComponent {
override fun use(world: World, player: PlayerEntity, hand: Hand, heldItem: ItemStack): ActionResult<ItemStack> {
if (!world.isRemote) {
world.addEntity(createEntity(world, player, hand, heldItem))
}
player.addStat(Stats.ITEM_USED[heldItem.item])
if (!player.abilities.isCreativeMode) {
heldItem.shrink(1)
}
return ActionResult.func_233538_a_(heldItem, world.isRemote)
}
protected abstract fun createEntity(world: World, player: PlayerEntity, hand: Hand, heldItem: ItemStack): Entity
}

View File

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

View File

@@ -1,6 +0,0 @@
package chylex.hee.game.item.interfaces
/**
* Marks interfaces that can be attached to items.
*/
interface IItemInterface

View File

@@ -1,15 +0,0 @@
package chylex.hee.game.item.interfaces
import net.minecraft.item.Item
interface IItemWithInterfaces {
fun getInterface(type: Class<out IItemInterface>): Any?
}
inline fun <reified T : IItemInterface> IItemWithInterfaces.getHeeInterface(): T? {
return this.getInterface(T::class.java) as? T
}
inline fun <reified T : IItemInterface> Item.getHeeInterface(): T? {
return (this as? IItemWithInterfaces)?.getHeeInterface()
}

View File

@@ -1,9 +0,0 @@
package chylex.hee.game.item.interfaces
internal class ItemInterfaceContainer(interfaces: Map<Class<out IItemInterface>, Any>) : IItemWithInterfaces {
private val interfaces = interfaces.toMap()
override fun getInterface(type: Class<out IItemInterface>): Any? {
return interfaces[type]
}
}

View File

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

View File

@@ -1,6 +1,5 @@
package chylex.hee.game.item.properties
import chylex.hee.util.color.RGB
import chylex.hee.util.forge.Side
import chylex.hee.util.forge.Sided
import net.minecraft.client.renderer.color.IItemColor
@@ -10,7 +9,6 @@ import net.minecraft.item.ItemStack
abstract class ItemTint : IItemColor {
protected companion object {
const val NO_TINT = -1
val WHITE = RGB(255u).i
}
@Sided(Side.CLIENT)

View File

@@ -1,7 +1,5 @@
package chylex.hee.game.item.repair
import chylex.hee.game.item.interfaces.IItemInterface
fun interface ICustomRepairBehavior : IItemInterface {
interface ICustomRepairBehavior {
fun onRepairUpdate(instance: RepairInstance)
}

View File

@@ -1,7 +1,6 @@
package chylex.hee.game.item.repair
import chylex.hee.HEE
import chylex.hee.game.item.interfaces.getHeeInterface
import chylex.hee.util.forge.SubscribeAllEvents
import chylex.hee.util.forge.SubscribeEvent
import net.minecraft.util.text.StringTextComponent
@@ -17,10 +16,9 @@ object RepairHandler {
val ingredient = e.right
val item = target.item
val repairBehavior = item.getHeeInterface() ?: item as? ICustomRepairBehavior
if (repairBehavior != null && item.getIsRepairable(target, ingredient)) {
val instance = RepairInstance(target, ingredient).apply(repairBehavior::onRepairUpdate)
if (item is ICustomRepairBehavior && item.getIsRepairable(target, ingredient)) {
val instance = RepairInstance(target, ingredient).apply(item::onRepairUpdate)
if (instance.repaired.isEmpty || (instance.experienceCost > MAX_EXPERIENCE_COST && !e.player.let { it != null && it.abilities.isCreativeMode })) {
e.isCanceled = true

View File

@@ -1,7 +1,7 @@
package chylex.hee.game.loot.rng
import chylex.hee.game.Resource
import chylex.hee.util.random.nextBiasedFloat
import chylex.hee.system.random.nextBiasedFloat
import net.minecraft.loot.IRandomRange
import net.minecraft.util.ResourceLocation
import java.util.Random

View File

@@ -1,7 +1,7 @@
package chylex.hee.game.loot.rng
import chylex.hee.game.Resource
import chylex.hee.util.random.nextRounded
import chylex.hee.system.random.nextRounded
import net.minecraft.loot.IRandomRange
import net.minecraft.util.ResourceLocation
import java.util.Random

View File

@@ -1,10 +1,10 @@
package chylex.hee.game.particle.data
import chylex.hee.game.particle.spawner.IParticleMaker
import chylex.hee.system.random.nextFloat
import chylex.hee.system.random.nextInt
import chylex.hee.util.color.IColorGenerator
import chylex.hee.util.color.IntColor
import chylex.hee.util.random.nextFloat
import chylex.hee.util.random.nextInt
import java.util.Random
data class ParticleDataColorLifespanScale(val color: IntColor, val lifespan: Int, val scale: Float) {

View File

@@ -1,9 +1,9 @@
package chylex.hee.game.particle.data
import chylex.hee.game.particle.spawner.IParticleMaker
import chylex.hee.system.random.nextFloat
import chylex.hee.util.color.IColorGenerator
import chylex.hee.util.color.IntColor
import chylex.hee.util.random.nextFloat
import java.util.Random
data class ParticleDataColorScale(val color: IntColor, val scale: Float) {

View File

@@ -1,7 +1,7 @@
package chylex.hee.game.particle.spawner.properties
import chylex.hee.util.random.nextFloat
import chylex.hee.util.random.nextVector
import chylex.hee.system.random.nextFloat
import chylex.hee.system.random.nextVector
import net.minecraft.entity.Entity
import net.minecraft.util.Direction
import net.minecraft.util.math.vector.Vector3d

Some files were not shown because too many files have changed in this diff Show More