mirror of
https://github.com/chylex/Hardcore-Ender-Expansion-2.git
synced 2025-10-22 19:23:43 +02:00
Compare commits
10 Commits
dev-territ
...
components
Author | SHA1 | Date | |
---|---|---|---|
1135c192bb
|
|||
8933d8d8cc
|
|||
5564fc4a24
|
|||
f0b6fd2fac
|
|||
ec76799a67
|
|||
e73ac4e3d1
|
|||
858fa672ec
|
|||
77f759e0d0
|
|||
f077f11c32
|
|||
e0c3ed6bc3
|
1
.idea/gradle.xml
generated
1
.idea/gradle.xml
generated
@@ -12,6 +12,7 @@
|
|||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
<option value="$PROJECT_DIR$/data" />
|
<option value="$PROJECT_DIR$/data" />
|
||||||
|
<option value="$PROJECT_DIR$/modules/debug" />
|
||||||
<option value="$PROJECT_DIR$/modules/system" />
|
<option value="$PROJECT_DIR$/modules/system" />
|
||||||
<option value="$PROJECT_DIR$/modules/util" />
|
<option value="$PROJECT_DIR$/modules/util" />
|
||||||
</set>
|
</set>
|
||||||
|
11
build.gradle
11
build.gradle
@@ -60,6 +60,7 @@ idea {
|
|||||||
|
|
||||||
["out", "src/main/kotlin", "src/test/kotlin"].each {
|
["out", "src/main/kotlin", "src/test/kotlin"].each {
|
||||||
excludeDirs += file(it)
|
excludeDirs += file(it)
|
||||||
|
excludeDirs += file("modules/debug/" + it)
|
||||||
excludeDirs += file("modules/system/" + it)
|
excludeDirs += file("modules/system/" + it)
|
||||||
excludeDirs += file("modules/util/" + it)
|
excludeDirs += file("modules/util/" + it)
|
||||||
}
|
}
|
||||||
@@ -128,7 +129,6 @@ minecraft {
|
|||||||
|
|
||||||
runs {
|
runs {
|
||||||
client {
|
client {
|
||||||
property "hee.debug", ""
|
|
||||||
property "mixin.env.remapRefMap", "true"
|
property "mixin.env.remapRefMap", "true"
|
||||||
property "mixin.env.refMapRemappingFile", "${projectDir}/build/createSrgToMcp/output.srg"
|
property "mixin.env.refMapRemappingFile", "${projectDir}/build/createSrgToMcp/output.srg"
|
||||||
arg "-mixin.config=hee.mixins.json"
|
arg "-mixin.config=hee.mixins.json"
|
||||||
@@ -138,6 +138,7 @@ minecraft {
|
|||||||
mods {
|
mods {
|
||||||
hee {
|
hee {
|
||||||
source sourceSets.main
|
source sourceSets.main
|
||||||
|
source project(":debug").sourceSets.main
|
||||||
source project(":system").sourceSets.main
|
source project(":system").sourceSets.main
|
||||||
source project(":util").sourceSets.main
|
source project(":util").sourceSets.main
|
||||||
}
|
}
|
||||||
@@ -145,7 +146,6 @@ minecraft {
|
|||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
property "hee.debug", ""
|
|
||||||
property "mixin.env.remapRefMap", "true"
|
property "mixin.env.remapRefMap", "true"
|
||||||
property "mixin.env.refMapRemappingFile", "${projectDir}/build/createSrgToMcp/output.srg"
|
property "mixin.env.refMapRemappingFile", "${projectDir}/build/createSrgToMcp/output.srg"
|
||||||
arg "-mixin.config=hee.mixins.json"
|
arg "-mixin.config=hee.mixins.json"
|
||||||
@@ -155,6 +155,7 @@ minecraft {
|
|||||||
mods {
|
mods {
|
||||||
hee {
|
hee {
|
||||||
source sourceSets.main
|
source sourceSets.main
|
||||||
|
source project(":debug").sourceSets.main
|
||||||
source project(":system").sourceSets.main
|
source project(":system").sourceSets.main
|
||||||
source project(":util").sourceSets.main
|
source project(":util").sourceSets.main
|
||||||
}
|
}
|
||||||
@@ -162,7 +163,6 @@ minecraft {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data {
|
data {
|
||||||
property "hee.debug", ""
|
|
||||||
args "--mod", "hee"
|
args "--mod", "hee"
|
||||||
args "--all"
|
args "--all"
|
||||||
args "--output", file("data/gen")
|
args "--output", file("data/gen")
|
||||||
@@ -174,6 +174,7 @@ minecraft {
|
|||||||
mods {
|
mods {
|
||||||
hee {
|
hee {
|
||||||
source sourceSets.main
|
source sourceSets.main
|
||||||
|
source project(":debug").sourceSets.main
|
||||||
source project(":system").sourceSets.main
|
source project(":system").sourceSets.main
|
||||||
source project(":util").sourceSets.main
|
source project(":util").sourceSets.main
|
||||||
source project(":datagen").sourceSets.main
|
source project(":datagen").sourceSets.main
|
||||||
@@ -190,12 +191,12 @@ mixin {
|
|||||||
dependencies {
|
dependencies {
|
||||||
minecraft "net.minecraftforge:forge:" + mc_version + "-" + forge_version
|
minecraft "net.minecraftforge:forge:" + mc_version + "-" + forge_version
|
||||||
|
|
||||||
implementation project(":system")
|
|
||||||
implementation project(":util")
|
implementation project(":util")
|
||||||
|
implementation project(":system")
|
||||||
implementation "thedarkcolour:kotlinforforge:" + kotlin_mod_version
|
implementation "thedarkcolour:kotlinforforge:" + kotlin_mod_version
|
||||||
|
|
||||||
testImplementation project(":system")
|
|
||||||
testImplementation project(":util")
|
testImplementation project(":util")
|
||||||
|
testImplementation project(":system")
|
||||||
testImplementation "org.junit.jupiter:junit-jupiter-api:5.3.0-RC1"
|
testImplementation "org.junit.jupiter:junit-jupiter-api:5.3.0-RC1"
|
||||||
|
|
||||||
if (System.getProperty("idea.sync.active") != "true") {
|
if (System.getProperty("idea.sync.active") != "true") {
|
||||||
|
@@ -580,6 +580,8 @@ e66091a13a6e7593eb5bd971978d24a5a0e375b3 data/hee/loot_tables/blocks/whitebark.j
|
|||||||
9bd3a9e24162d2c81047b834f8f79d6cabec86be data/hee/loot_tables/blocks/whitebark_planks.json
|
9bd3a9e24162d2c81047b834f8f79d6cabec86be data/hee/loot_tables/blocks/whitebark_planks.json
|
||||||
7d84dc443a052e349593b71d2c0a523e75396cdf data/hee/loot_tables/blocks/whitebark_slab.json
|
7d84dc443a052e349593b71d2c0a523e75396cdf data/hee/loot_tables/blocks/whitebark_slab.json
|
||||||
83e0b81adb3f9dd488397e8459b95f7b0ce19927 data/hee/loot_tables/blocks/whitebark_stairs.json
|
83e0b81adb3f9dd488397e8459b95f7b0ce19927 data/hee/loot_tables/blocks/whitebark_stairs.json
|
||||||
|
37f3c55266db3db8dc6d22fdbaf3d53243016b77 data/hee/tags/blocks/gloomrock_particles.json
|
||||||
|
1a70c674d979a59cea18d92f2227ab8a5ed2ccc7 data/hee/tags/blocks/void_portal_frame_crafted.json
|
||||||
f5996244831ab38fe1fae2f304bbd7825d6ad98b data/minecraft/tags/blocks/bamboo_plantable_on.json
|
f5996244831ab38fe1fae2f304bbd7825d6ad98b data/minecraft/tags/blocks/bamboo_plantable_on.json
|
||||||
479189f9b35a3c8f795539daf6a1809130242c5b data/minecraft/tags/blocks/flower_pots.json
|
479189f9b35a3c8f795539daf6a1809130242c5b data/minecraft/tags/blocks/flower_pots.json
|
||||||
424e2e03cf62f23f4496468a97b9f0df060df9fe data/minecraft/tags/blocks/impermeable.json
|
424e2e03cf62f23f4496468a97b9f0df060df9fe data/minecraft/tags/blocks/impermeable.json
|
||||||
|
17
data/gen/data/hee/tags/blocks/gloomrock_particles.json
Normal file
17
data/gen/data/hee/tags/blocks/gloomrock_particles.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"replace": false,
|
||||||
|
"values": [
|
||||||
|
"hee:gloomrock",
|
||||||
|
"hee:gloomrock_bricks",
|
||||||
|
"hee:gloomrock_smooth",
|
||||||
|
"hee:gloomrock_smooth_red",
|
||||||
|
"hee:gloomrock_smooth_orange",
|
||||||
|
"hee:gloomrock_smooth_yellow",
|
||||||
|
"hee:gloomrock_smooth_green",
|
||||||
|
"hee:gloomrock_smooth_cyan",
|
||||||
|
"hee:gloomrock_smooth_blue",
|
||||||
|
"hee:gloomrock_smooth_purple",
|
||||||
|
"hee:gloomrock_smooth_magenta",
|
||||||
|
"hee:gloomrock_smooth_white"
|
||||||
|
]
|
||||||
|
}
|
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"replace": false,
|
||||||
|
"values": [
|
||||||
|
"hee:void_portal_frame_crafted",
|
||||||
|
"hee:void_portal_storage_crafted"
|
||||||
|
]
|
||||||
|
}
|
@@ -37,7 +37,7 @@ import net.minecraftforge.common.data.ExistingFileHelper
|
|||||||
class BlockModels(generator: DataGenerator, modid: String, existingFileHelper: ExistingFileHelper) : BlockModelProvider(generator, modid, existingFileHelper) {
|
class BlockModels(generator: DataGenerator, modid: String, existingFileHelper: ExistingFileHelper) : BlockModelProvider(generator, modid, existingFileHelper) {
|
||||||
override fun registerModels() {
|
override fun registerModels() {
|
||||||
for (block in ModBlocks.ALL) {
|
for (block in ModBlocks.ALL) {
|
||||||
(block as? IHeeBlock)?.model?.let { registerModel(block, it.blockModel) { builder -> builder } }
|
(block as? IHeeBlock)?.let { registerModel(block, it.model.generate(block).blockModel) { builder -> builder } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -32,7 +32,7 @@ import net.minecraftforge.common.data.ExistingFileHelper
|
|||||||
class BlockStates(generator: DataGenerator, modid: String, existingFileHelper: ExistingFileHelper) : BlockStateProvider(generator, modid, existingFileHelper) {
|
class BlockStates(generator: DataGenerator, modid: String, existingFileHelper: ExistingFileHelper) : BlockStateProvider(generator, modid, existingFileHelper) {
|
||||||
override fun registerStatesAndModels() {
|
override fun registerStatesAndModels() {
|
||||||
for (block in ModBlocks.ALL) {
|
for (block in ModBlocks.ALL) {
|
||||||
(block as? IHeeBlock)?.model?.let { registerState(block, it.blockState) }
|
(block as? IHeeBlock)?.let { registerState(block, it.model.generate(block).blockState) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -39,15 +39,13 @@ import net.minecraftforge.common.data.ExistingFileHelper
|
|||||||
class ItemModels(generator: DataGenerator, modid: String, existingFileHelper: ExistingFileHelper) : ItemModelProvider(generator, modid, existingFileHelper) {
|
class ItemModels(generator: DataGenerator, modid: String, existingFileHelper: ExistingFileHelper) : ItemModelProvider(generator, modid, existingFileHelper) {
|
||||||
override fun registerModels() {
|
override fun registerModels() {
|
||||||
for (item in ModItems.ALL) {
|
for (item in ModItems.ALL) {
|
||||||
(item as? IHeeItem)?.model?.let {
|
(item as? IHeeItem)?.let { registerModel(item, it.model) }
|
||||||
registerModel(item, it)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (block in ModBlocks.ALL) {
|
for (block in ModBlocks.ALL) {
|
||||||
(block as? IHeeBlock)?.model?.itemModel?.let {
|
(block as? IHeeBlock)
|
||||||
registerModel(if (it.asItem) block.asItem() else block, it.model)
|
?.let { it.model.generate(block).itemModel }
|
||||||
}
|
?.let { registerModel(if (it.asItem) block.asItem() else block, it.model) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -91,7 +91,7 @@ class LangEnglish(generator: DataGenerator, modid: String) : LanguageProvider(ge
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (command in ClientCommandHandler.nonHelpCommands.values) {
|
for (command in ClientCommandHandler.all.values) {
|
||||||
val name = command.name
|
val name = command.name
|
||||||
add("commands.hee.$name.info", command.description)
|
add("commands.hee.$name.info", command.description)
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,7 @@ import net.minecraft.tags.ITag.INamedTag
|
|||||||
import net.minecraft.tags.ItemTags
|
import net.minecraft.tags.ItemTags
|
||||||
import net.minecraftforge.common.data.ExistingFileHelper
|
import net.minecraftforge.common.data.ExistingFileHelper
|
||||||
|
|
||||||
class ItemTags(dataGenerator: DataGenerator, private val blockTags: chylex.hee.datagen.server.BlockTags, modId: String, existingFileHelper: ExistingFileHelper?) : ItemTagsProvider(dataGenerator, blockTags, modId, existingFileHelper) {
|
class ItemTags(dataGenerator: DataGenerator, private val blockTags: BlockTags, modId: String, existingFileHelper: ExistingFileHelper?) : ItemTagsProvider(dataGenerator, blockTags, modId, existingFileHelper) {
|
||||||
override fun registerTags() {
|
override fun registerTags() {
|
||||||
val itemTags = ItemTags.getAllTags().associateBy { it.name }
|
val itemTags = ItemTags.getAllTags().associateBy { it.name }
|
||||||
|
|
||||||
|
33
modules/debug/build.gradle
Normal file
33
modules/debug/build.gradle
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
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"
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
143
modules/debug/src/main/java/chylex/hee/client/BuildStick.kt
Normal file
143
modules/debug/src/main/java/chylex/hee/client/BuildStick.kt
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
42
modules/debug/src/main/java/chylex/hee/client/DebugMenu.kt
Normal file
42
modules/debug/src/main/java/chylex/hee/client/DebugMenu.kt
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,27 @@
|
|||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,19 @@
|
|||||||
|
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)}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
71
modules/debug/src/main/java/chylex/hee/debug/Debug.kt
Normal file
71
modules/debug/src/main/java/chylex/hee/debug/Debug.kt
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
modules/debug/src/main/java/chylex/hee/debug/PowerShell.kt
Normal file
26
modules/debug/src/main/java/chylex/hee/debug/PowerShell.kt
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,80 @@
|
|||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,102 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
@@ -1,13 +1,13 @@
|
|||||||
package chylex.hee.game.command.client
|
package chylex.hee.game.command.client
|
||||||
|
|
||||||
import chylex.hee.client.render.TerritoryRenderer
|
import chylex.hee.client.render.TerritoryRenderer
|
||||||
|
import chylex.hee.game.block.BlockScaffolding
|
||||||
import chylex.hee.game.command.IClientCommand
|
import chylex.hee.game.command.IClientCommand
|
||||||
import chylex.hee.game.territory.TerritoryVoid
|
import chylex.hee.game.territory.TerritoryVoid
|
||||||
import chylex.hee.init.ModBlocks
|
|
||||||
import net.minecraft.command.CommandSource
|
import net.minecraft.command.CommandSource
|
||||||
import net.minecraft.util.text.StringTextComponent
|
import net.minecraft.util.text.StringTextComponent
|
||||||
|
|
||||||
object CommandDebugToggles : IClientCommand {
|
object CommandClientDebugToggles : IClientCommand {
|
||||||
override val name = "debug"
|
override val name = "debug"
|
||||||
override val description = "access to debug toggles"
|
override val description = "access to debug toggles"
|
||||||
|
|
||||||
@@ -23,8 +23,8 @@ object CommandDebugToggles : IClientCommand {
|
|||||||
sender.sendFeedback(StringTextComponent("Territory debugging ${if (debug) "enabled" else "disabled"}."), false)
|
sender.sendFeedback(StringTextComponent("Territory debugging ${if (debug) "enabled" else "disabled"}."), false)
|
||||||
}
|
}
|
||||||
else if (name == "scaffolding") {
|
else if (name == "scaffolding") {
|
||||||
ModBlocks.SCAFFOLDING.enableShape = !ModBlocks.SCAFFOLDING.enableShape
|
BlockScaffolding.enableShape = !BlockScaffolding.enableShape
|
||||||
sender.sendFeedback(StringTextComponent("Scaffolding shape ${if (ModBlocks.SCAFFOLDING.enableShape) "enabled" else "disabled"}."), false)
|
sender.sendFeedback(StringTextComponent("Scaffolding shape ${if (BlockScaffolding.enableShape) "enabled" else "disabled"}."), false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
package chylex.hee.game.command.client
|
package chylex.hee.game.command.client
|
||||||
|
|
||||||
import chylex.hee.game.command.IClientCommand
|
import chylex.hee.game.command.IClientCommand
|
||||||
import chylex.hee.game.command.server.CommandDebugStructure
|
import chylex.hee.game.command.server.CommandServerStructure
|
||||||
import net.minecraft.command.CommandSource
|
import net.minecraft.command.CommandSource
|
||||||
import net.minecraft.util.text.StringTextComponent
|
import net.minecraft.util.text.StringTextComponent
|
||||||
import java.util.prefs.Preferences
|
import java.util.prefs.Preferences
|
||||||
@@ -14,7 +14,7 @@ object CommandClientScaffolding : IClientCommand {
|
|||||||
get() = Preferences.userRoot().node("chylex-hee-scaffolding")
|
get() = Preferences.userRoot().node("chylex-hee-scaffolding")
|
||||||
|
|
||||||
val currentPalette
|
val currentPalette
|
||||||
get() = data.get("Structure", null)?.let(CommandDebugStructure.structureDescriptions::get)?.PALETTE
|
get() = data.get("Structure", null)?.let(CommandServerStructure.structureDescriptions::get)?.PALETTE
|
||||||
|
|
||||||
val currentFile
|
val currentFile
|
||||||
get() = data.get("File", "")!!.ifBlank { "structure.nbt" }
|
get() = data.get("File", "")!!.ifBlank { "structure.nbt" }
|
||||||
@@ -22,7 +22,7 @@ object CommandClientScaffolding : IClientCommand {
|
|||||||
override fun executeCommand(sender: CommandSource, args: Array<String>) {
|
override fun executeCommand(sender: CommandSource, args: Array<String>) {
|
||||||
val structure = args.getOrNull(0) ?: return
|
val structure = args.getOrNull(0) ?: return
|
||||||
|
|
||||||
if (!CommandDebugStructure.structureDescriptions.containsKey(structure)) {
|
if (!CommandServerStructure.structureDescriptions.containsKey(structure)) {
|
||||||
sender.sendFeedback(StringTextComponent("Unknown structure."), false)
|
sender.sendFeedback(StringTextComponent("Unknown structure."), false)
|
||||||
return
|
return
|
||||||
}
|
}
|
@@ -15,7 +15,7 @@ import net.minecraft.command.Commands.argument
|
|||||||
import net.minecraft.command.Commands.literal
|
import net.minecraft.command.Commands.literal
|
||||||
import net.minecraft.util.text.StringTextComponent
|
import net.minecraft.util.text.StringTextComponent
|
||||||
|
|
||||||
object CommandDebugInstability : ICommand {
|
object CommandServerInstability : ICommand {
|
||||||
override val name = "instability"
|
override val name = "instability"
|
||||||
override val description = "utilities for instability"
|
override val description = "utilities for instability"
|
||||||
|
|
@@ -31,7 +31,7 @@ import net.minecraft.util.Rotation
|
|||||||
import net.minecraft.util.text.StringTextComponent
|
import net.minecraft.util.text.StringTextComponent
|
||||||
import java.util.Random
|
import java.util.Random
|
||||||
|
|
||||||
object CommandDebugStructure : ICommand {
|
object CommandServerStructure : ICommand {
|
||||||
val structureDescriptions = mapOf(
|
val structureDescriptions = mapOf(
|
||||||
"stronghold" to StrongholdPieces,
|
"stronghold" to StrongholdPieces,
|
||||||
"energyshrine" to EnergyShrinePieces,
|
"energyshrine" to EnergyShrinePieces,
|
@@ -23,7 +23,7 @@ import net.minecraft.entity.player.PlayerEntity
|
|||||||
import net.minecraft.util.text.StringTextComponent
|
import net.minecraft.util.text.StringTextComponent
|
||||||
import java.util.Random
|
import java.util.Random
|
||||||
|
|
||||||
object CommandDebugTerritory : ICommand {
|
object CommandServerTerritory : ICommand {
|
||||||
override val name = "territory"
|
override val name = "territory"
|
||||||
override val description = "utilities for territories"
|
override val description = "utilities for territories"
|
||||||
|
|
@@ -7,7 +7,7 @@ import com.mojang.brigadier.builder.ArgumentBuilder
|
|||||||
import com.mojang.brigadier.context.CommandContext
|
import com.mojang.brigadier.context.CommandContext
|
||||||
import net.minecraft.command.CommandSource
|
import net.minecraft.command.CommandSource
|
||||||
|
|
||||||
object CommandDebugTestWorld : ICommand, CommandExecutionFunction {
|
object CommandServerTestWorld : ICommand, CommandExecutionFunction {
|
||||||
override val name = "testworld"
|
override val name = "testworld"
|
||||||
override val description = "converts overworld into a test world"
|
override val description = "converts overworld into a test world"
|
||||||
|
|
7
modules/debug/src/main/resources/pack.mcmeta
Normal file
7
modules/debug/src/main/resources/pack.mcmeta
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"pack": {
|
||||||
|
"description": "Hardcore Ender Expansion 2 (Debug Library)",
|
||||||
|
"pack_format": 6,
|
||||||
|
"_comment": ""
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,7 @@
|
|||||||
package chylex.hee
|
package chylex.hee
|
||||||
|
|
||||||
import chylex.hee.game.Resource
|
import chylex.hee.game.Resource
|
||||||
|
import chylex.hee.system.IDebugModule
|
||||||
import net.minecraft.util.RegistryKey
|
import net.minecraft.util.RegistryKey
|
||||||
import net.minecraft.util.registry.Registry
|
import net.minecraft.util.registry.Registry
|
||||||
import net.minecraft.world.World
|
import net.minecraft.world.World
|
||||||
@@ -12,6 +13,10 @@ object HEE {
|
|||||||
|
|
||||||
lateinit var version: String
|
lateinit var version: String
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
var debug = false
|
||||||
|
var debugModule: IDebugModule? = null
|
||||||
|
|
||||||
val log: Logger = LogManager.getLogger("HardcoreEnderExpansion")
|
val log: Logger = LogManager.getLogger("HardcoreEnderExpansion")
|
||||||
val dim: RegistryKey<World> = RegistryKey.getOrCreateKey(Registry.WORLD_KEY, Resource.Custom("end"))
|
val dim: RegistryKey<World> = RegistryKey.getOrCreateKey(Registry.WORLD_KEY, Resource.Custom("end"))
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,7 @@ import chylex.hee.game.block.properties.BlockDrop
|
|||||||
import net.minecraft.block.Block
|
import net.minecraft.block.Block
|
||||||
import net.minecraft.loot.LootTables
|
import net.minecraft.loot.LootTables
|
||||||
|
|
||||||
open class HeeBlock(builder: BlockBuilder) : Block(builder.p), IHeeBlock {
|
open class HeeBlock(builder: BlockBuilder) : Block(builder.p), IHeeBlock { // TODO abstract
|
||||||
override val drop
|
override val drop
|
||||||
get() = if (lootTable == LootTables.EMPTY) BlockDrop.Nothing else BlockDrop.Self
|
get() = if (lootTable == LootTables.EMPTY) BlockDrop.Nothing else BlockDrop.Self
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,5 @@
|
|||||||
|
package chylex.hee.game.block
|
||||||
|
|
||||||
|
import net.minecraft.block.Block
|
||||||
|
|
||||||
|
abstract class HeeBlock2(properties: Properties) : Block(properties), IHeeBlock
|
@@ -0,0 +1,229 @@
|
|||||||
|
package chylex.hee.game.block
|
||||||
|
|
||||||
|
import chylex.hee.game.block.builder.HeeBlockComponents
|
||||||
|
import chylex.hee.game.world.util.getBlock
|
||||||
|
import chylex.hee.util.forge.Side
|
||||||
|
import chylex.hee.util.forge.Sided
|
||||||
|
import chylex.hee.util.forge.asBool
|
||||||
|
import net.minecraft.block.Block
|
||||||
|
import net.minecraft.block.BlockRenderType
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.client.util.ITooltipFlag
|
||||||
|
import net.minecraft.entity.Entity
|
||||||
|
import net.minecraft.entity.EntitySpawnPlacementRegistry.PlacementType
|
||||||
|
import net.minecraft.entity.EntityType
|
||||||
|
import net.minecraft.entity.LivingEntity
|
||||||
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
|
import net.minecraft.item.BlockItemUseContext
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.loot.LootContext
|
||||||
|
import net.minecraft.state.StateContainer.Builder
|
||||||
|
import net.minecraft.tileentity.TileEntity
|
||||||
|
import net.minecraft.util.ActionResultType
|
||||||
|
import net.minecraft.util.Direction
|
||||||
|
import net.minecraft.util.Hand
|
||||||
|
import net.minecraft.util.Mirror
|
||||||
|
import net.minecraft.util.Rotation
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.util.math.BlockRayTraceResult
|
||||||
|
import net.minecraft.util.math.RayTraceResult
|
||||||
|
import net.minecraft.util.math.shapes.ISelectionContext
|
||||||
|
import net.minecraft.util.math.shapes.VoxelShape
|
||||||
|
import net.minecraft.util.text.ITextComponent
|
||||||
|
import net.minecraft.world.Explosion
|
||||||
|
import net.minecraft.world.IBlockReader
|
||||||
|
import net.minecraft.world.IWorld
|
||||||
|
import net.minecraft.world.IWorldReader
|
||||||
|
import net.minecraft.world.World
|
||||||
|
import net.minecraft.world.server.ServerWorld
|
||||||
|
import java.util.Random
|
||||||
|
|
||||||
|
abstract class HeeBlockWithComponents(properties: Properties, components: HeeBlockComponents) : HeeBlock2(properties) {
|
||||||
|
private companion object {
|
||||||
|
private val RAND = Random()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val states = components.states.build()
|
||||||
|
|
||||||
|
private val name = components.name
|
||||||
|
private val tooltip = components.tooltip
|
||||||
|
|
||||||
|
private val shape = components.shape
|
||||||
|
private val renderType = components.renderType
|
||||||
|
private val ambientOcclusionValue = components.ambientOcclusionValue
|
||||||
|
private val clientEffects = components.clientEffects
|
||||||
|
|
||||||
|
private val drops = components.drops
|
||||||
|
private val harvestability = components.harvestability
|
||||||
|
private val experience = components.experience
|
||||||
|
private val flammability = components.flammability
|
||||||
|
|
||||||
|
private val entity = components.entity
|
||||||
|
private val placement = components.placement
|
||||||
|
private val onAdded = components.onAdded
|
||||||
|
private val onNeighborChanged = components.onNeighborChanged
|
||||||
|
private val setStateFromNeighbor = components.setStateFromNeighbor
|
||||||
|
|
||||||
|
private val scheduledTick = components.scheduledTick
|
||||||
|
private val randomTick = components.randomTick
|
||||||
|
|
||||||
|
private val playerUse = components.playerUse
|
||||||
|
private val onExploded = components.onExploded
|
||||||
|
private val onCreatureSpawning = components.onCreatureSpawning
|
||||||
|
private val collideWithEntity = components.collideWithEntity
|
||||||
|
|
||||||
|
private var isAir = components.isAir
|
||||||
|
|
||||||
|
init {
|
||||||
|
defaultState = states.applyDefaults(stateContainer.baseState)
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract override fun fillStateContainer(builder: Builder<Block, BlockState>)
|
||||||
|
|
||||||
|
override fun rotate(state: BlockState, rotation: Rotation): BlockState {
|
||||||
|
return states.getRotatedState(state, rotation)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mirror(state: BlockState, mirror: Mirror): BlockState {
|
||||||
|
return states.getMirroredState(state, mirror)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTranslationKey(): String {
|
||||||
|
return name?.translationKey ?: super.getTranslationKey()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sided(Side.CLIENT)
|
||||||
|
override fun addInformation(stack: ItemStack, world: IBlockReader?, lines: MutableList<ITextComponent>, flags: ITooltipFlag) {
|
||||||
|
tooltip?.add(lines, stack, flags.isAdvanced, world)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
override fun getShape(state: BlockState, worldIn: IBlockReader, pos: BlockPos, context: ISelectionContext): VoxelShape {
|
||||||
|
return shape?.getShape(state) ?: super.getShape(state, worldIn, pos, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
override fun getCollisionShape(state: BlockState, worldIn: IBlockReader, pos: BlockPos, context: ISelectionContext): VoxelShape {
|
||||||
|
return shape?.getCollisionShape(state) ?: super.getCollisionShape(state, worldIn, pos, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getRaytraceShape(state: BlockState, worldIn: IBlockReader, pos: BlockPos): VoxelShape {
|
||||||
|
return super.getRaytraceShape(state, worldIn, pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
override fun getRenderType(state: BlockState): BlockRenderType {
|
||||||
|
return renderType ?: super.getRenderType(state)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sided(Side.CLIENT)
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
override fun getAmbientOcclusionLightValue(state: BlockState, worldIn: IBlockReader, pos: BlockPos): Float {
|
||||||
|
return ambientOcclusionValue ?: super.getAmbientOcclusionLightValue(state, worldIn, pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sided(Side.CLIENT)
|
||||||
|
override fun animateTick(state: BlockState, world: World, pos: BlockPos, rand: Random) {
|
||||||
|
clientEffects?.randomTick(state, world, pos, rand)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
override fun getDrops(state: BlockState, context: LootContext.Builder): MutableList<ItemStack> {
|
||||||
|
return drops?.getDrops(state, context) ?: super.getDrops(state, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPickBlock(state: BlockState, target: RayTraceResult, world: IBlockReader, pos: BlockPos, player: PlayerEntity): ItemStack {
|
||||||
|
return drops?.getPickBlock(state, world, pos) ?: super.getPickBlock(state, target, world, pos, player)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canHarvestBlock(state: BlockState, world: IBlockReader, pos: BlockPos, player: PlayerEntity): Boolean {
|
||||||
|
return harvestability?.canHarvest(player)?.asBool ?: super.canHarvestBlock(state, world, pos, player)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getExpDrop(state: BlockState, world: IWorldReader, pos: BlockPos, fortune: Int, silktouch: Int): Int {
|
||||||
|
return experience?.getExperience((world as? World)?.rand ?: RAND) ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getFlammability(state: BlockState, world: IBlockReader, pos: BlockPos, face: Direction): Int {
|
||||||
|
return flammability?.takeIfFlammable(state)?.flammability ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getFireSpreadSpeed(state: BlockState, world: IBlockReader, pos: BlockPos, face: Direction): Int {
|
||||||
|
return flammability?.takeIfFlammable(state)?.fireSpread ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hasTileEntity(state: BlockState): Boolean {
|
||||||
|
return entity != null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createTileEntity(state: BlockState, world: IBlockReader): TileEntity? {
|
||||||
|
return entity?.create()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
override fun isValidPosition(state: BlockState, world: IWorldReader, pos: BlockPos): Boolean {
|
||||||
|
return placement?.isPositionValid(state, world, pos) ?: super.isValidPosition(state, world, pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getStateForPlacement(context: BlockItemUseContext): BlockState? {
|
||||||
|
return placement?.getPlacedState(defaultState, context.world, context.pos, context) ?: super.getStateForPlacement(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBlockPlacedBy(world: World, pos: BlockPos, state: BlockState, placer: LivingEntity?, stack: ItemStack) {
|
||||||
|
placement?.onPlacedBy(state, world, pos, placer, stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBlockAdded(state: BlockState, world: World, pos: BlockPos, oldState: BlockState, isMoving: Boolean) {
|
||||||
|
onAdded?.onAdded(state, world, pos)
|
||||||
|
scheduledTick?.onAdded(state, world, pos, world.rand)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
override fun neighborChanged(state: BlockState, world: World, pos: BlockPos, neighborBlock: Block, neighborPos: BlockPos, isMoving: Boolean) {
|
||||||
|
super.neighborChanged(state, world, pos, neighborBlock, neighborPos, isMoving)
|
||||||
|
onNeighborChanged?.onNeighborChanged(state, world, pos, neighborBlock, neighborPos.getBlock(world), neighborPos)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
override fun updatePostPlacement(state: BlockState, neighborFacing: Direction, neighborState: BlockState, world: IWorld, currentPos: BlockPos, neighborPos: BlockPos): BlockState {
|
||||||
|
return setStateFromNeighbor?.getNewState(state, world, currentPos, neighborFacing, neighborPos) ?: super.updatePostPlacement(state, neighborFacing, neighborState, world, currentPos, neighborPos)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tick(state: BlockState, world: ServerWorld, pos: BlockPos, rand: Random) {
|
||||||
|
scheduledTick?.onTick(state, world, pos, rand)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun randomTick(state: BlockState, world: ServerWorld, pos: BlockPos, rand: Random) {
|
||||||
|
randomTick?.onTick(state, world, pos, rand)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
override fun onBlockActivated(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hit: BlockRayTraceResult): ActionResultType {
|
||||||
|
return playerUse?.use(state, world, pos, player, hand) ?: super.onBlockActivated(state, world, pos, player, hand, hit)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canDropFromExplosion(state: BlockState, world: IBlockReader, pos: BlockPos, explosion: Explosion): Boolean {
|
||||||
|
return onExploded?.canDrop(explosion) ?: super.canDropFromExplosion(state, world, pos, explosion)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBlockExploded(state: BlockState, world: World, pos: BlockPos, explosion: Explosion) {
|
||||||
|
onExploded?.onExploded(state, world, pos, explosion)
|
||||||
|
super.onBlockExploded(state, world, pos, explosion)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canCreatureSpawn(state: BlockState, world: IBlockReader, pos: BlockPos, type: PlacementType?, entityType: EntityType<*>?): Boolean {
|
||||||
|
return onCreatureSpawning?.canSpawn(world, pos, type, entityType)?.asBool ?: super.canCreatureSpawn(state, world, pos, type, entityType)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onEntityCollision(state: BlockState, world: World, pos: BlockPos, entity: Entity) {
|
||||||
|
collideWithEntity?.collide(state, world, pos, entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isAir(state: BlockState, world: IBlockReader, pos: BlockPos): Boolean {
|
||||||
|
return isAir ?: super.isAir(state, world, pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun propagatesSkylightDown(state: BlockState, world: IBlockReader, pos: BlockPos): Boolean {
|
||||||
|
return isAir == true || super.propagatesSkylightDown(state, world, pos)
|
||||||
|
}
|
||||||
|
}
|
@@ -1,12 +1,13 @@
|
|||||||
package chylex.hee.game.block
|
package chylex.hee.game.block
|
||||||
|
|
||||||
import chylex.hee.client.text.LocalizationStrategy
|
import chylex.hee.client.text.LocalizationStrategy
|
||||||
|
import chylex.hee.game.block.builder.AbstractHeeBlockBuilder
|
||||||
import chylex.hee.game.block.properties.BlockDrop
|
import chylex.hee.game.block.properties.BlockDrop
|
||||||
import chylex.hee.game.block.properties.BlockModel
|
import chylex.hee.game.block.properties.BlockModel
|
||||||
import chylex.hee.game.block.properties.BlockRenderLayer
|
import chylex.hee.game.block.properties.BlockRenderLayer
|
||||||
import chylex.hee.game.block.properties.BlockRenderLayer.SOLID
|
import chylex.hee.game.block.properties.BlockRenderLayer.SOLID
|
||||||
import chylex.hee.game.block.properties.BlockTint
|
import chylex.hee.game.block.properties.BlockTint
|
||||||
import chylex.hee.game.block.properties.IBlockStateModel
|
import chylex.hee.game.block.properties.IBlockStateModelSupplier
|
||||||
import net.minecraft.block.Block
|
import net.minecraft.block.Block
|
||||||
import net.minecraft.tags.ITag.INamedTag
|
import net.minecraft.tags.ITag.INamedTag
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ interface IHeeBlock {
|
|||||||
val localizationExtra: Map<String, String>
|
val localizationExtra: Map<String, String>
|
||||||
get() = emptyMap()
|
get() = emptyMap()
|
||||||
|
|
||||||
val model: IBlockStateModel
|
val model: IBlockStateModelSupplier
|
||||||
get() = BlockModel.Cube
|
get() = BlockModel.Cube
|
||||||
|
|
||||||
val renderLayer: BlockRenderLayer
|
val renderLayer: BlockRenderLayer
|
||||||
@@ -31,4 +32,14 @@ interface IHeeBlock {
|
|||||||
|
|
||||||
val tags: List<INamedTag<Block>>
|
val tags: List<INamedTag<Block>>
|
||||||
get() = emptyList()
|
get() = emptyList()
|
||||||
|
|
||||||
|
class FromBuilder(builder: AbstractHeeBlockBuilder<*>) : IHeeBlock {
|
||||||
|
override val localization = builder.localization ?: super.localization
|
||||||
|
override val localizationExtra = builder.localizationExtra.toMap()
|
||||||
|
override val model = builder.model ?: super.model
|
||||||
|
override val renderLayer = builder.renderLayer ?: super.renderLayer
|
||||||
|
override val tint = builder.tint
|
||||||
|
override val drop = builder.drop ?: super.drop
|
||||||
|
override val tags = builder.tags.toList()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,149 @@
|
|||||||
|
package chylex.hee.game.block.builder
|
||||||
|
|
||||||
|
import chylex.hee.client.text.LocalizationStrategy
|
||||||
|
import chylex.hee.game.block.IHeeBlock
|
||||||
|
import chylex.hee.game.block.properties.BlockDrop
|
||||||
|
import chylex.hee.game.block.properties.BlockHardness
|
||||||
|
import chylex.hee.game.block.properties.BlockHarvestTool
|
||||||
|
import chylex.hee.game.block.properties.BlockRenderLayer
|
||||||
|
import chylex.hee.game.block.properties.BlockTint
|
||||||
|
import chylex.hee.game.block.properties.IBlockStateModelSupplier
|
||||||
|
import net.minecraft.block.AbstractBlock.IPositionPredicate
|
||||||
|
import net.minecraft.block.AbstractBlock.Properties
|
||||||
|
import net.minecraft.block.Block
|
||||||
|
import net.minecraft.block.SoundType
|
||||||
|
import net.minecraft.block.material.Material
|
||||||
|
import net.minecraft.block.material.MaterialColor
|
||||||
|
import net.minecraft.tags.ITag.INamedTag
|
||||||
|
|
||||||
|
abstract class AbstractHeeBlockBuilder<T : Block> {
|
||||||
|
private companion object {
|
||||||
|
private val DEFAULT_MATERIAL = Material.Builder(MaterialColor.AIR).build()
|
||||||
|
|
||||||
|
private fun always(value: Boolean): IPositionPredicate {
|
||||||
|
return IPositionPredicate { _, _, _ -> value }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var localization: LocalizationStrategy? = null
|
||||||
|
val localizationExtra = mutableMapOf<String, String>()
|
||||||
|
|
||||||
|
var model: IBlockStateModelSupplier? = null
|
||||||
|
var renderLayer: BlockRenderLayer? = null
|
||||||
|
|
||||||
|
var material: Material? = null
|
||||||
|
var color: MaterialColor? = null
|
||||||
|
var sound: SoundType? = null
|
||||||
|
var tint: BlockTint? = null
|
||||||
|
var light: Int? = null
|
||||||
|
|
||||||
|
var isSolid: Boolean? = null
|
||||||
|
var isOpaque: Boolean? = null
|
||||||
|
var suffocates: Boolean? = null
|
||||||
|
var blocksVision: Boolean? = null
|
||||||
|
|
||||||
|
var drop: BlockDrop? = null
|
||||||
|
var tool: BlockHarvestTool? = null
|
||||||
|
var hardness: BlockHardness? = null
|
||||||
|
|
||||||
|
private val lazyComponents = lazy(::HeeBlockComponents)
|
||||||
|
val components
|
||||||
|
get() = lazyComponents.value
|
||||||
|
|
||||||
|
val tags = mutableListOf<INamedTag<Block>>()
|
||||||
|
val interfaces = HeeBlockInterfaces()
|
||||||
|
|
||||||
|
fun includeFrom(source: AbstractHeeBlockBuilder<*>) {
|
||||||
|
source.localization?.let { this.localization = it }
|
||||||
|
this.localizationExtra.putAll(source.localizationExtra)
|
||||||
|
|
||||||
|
source.model?.let { this.model = it }
|
||||||
|
source.renderLayer?.let { this.renderLayer = it }
|
||||||
|
|
||||||
|
source.material?.let { this.material = it }
|
||||||
|
source.color?.let { this.color = it }
|
||||||
|
source.sound?.let { this.sound = it }
|
||||||
|
source.tint?.let { this.tint = it }
|
||||||
|
source.light?.let { this.light = it }
|
||||||
|
|
||||||
|
source.isSolid?.let { this.isSolid = it }
|
||||||
|
source.isOpaque?.let { this.isOpaque = it }
|
||||||
|
source.suffocates?.let { this.suffocates = it }
|
||||||
|
source.blocksVision?.let { this.blocksVision = it }
|
||||||
|
|
||||||
|
source.drop?.let { this.drop = it }
|
||||||
|
source.tool?.let { this.tool = it }
|
||||||
|
source.hardness?.let { this.hardness = it }
|
||||||
|
|
||||||
|
if (source.lazyComponents.isInitialized()) {
|
||||||
|
this.components.includeFrom(source.components)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.tags.addAll(source.tags)
|
||||||
|
this.interfaces.includeFrom(source.interfaces)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected val heeDelegate
|
||||||
|
get() = object : IHeeBlock {
|
||||||
|
override val localization = this@AbstractHeeBlockBuilder.localization ?: super.localization
|
||||||
|
override val localizationExtra = this@AbstractHeeBlockBuilder.localizationExtra.toMap()
|
||||||
|
override val model = this@AbstractHeeBlockBuilder.model ?: super.model
|
||||||
|
override val renderLayer = this@AbstractHeeBlockBuilder.renderLayer ?: super.renderLayer
|
||||||
|
override val tint = this@AbstractHeeBlockBuilder.tint
|
||||||
|
override val drop = this@AbstractHeeBlockBuilder.drop ?: super.drop
|
||||||
|
override val tags = this@AbstractHeeBlockBuilder.tags.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildProperties(setup: ((Properties) -> Properties)?): Properties {
|
||||||
|
val material = material ?: DEFAULT_MATERIAL
|
||||||
|
val color = color ?: material.color
|
||||||
|
val tool = tool ?: BlockHarvestTool.NONE
|
||||||
|
|
||||||
|
var properties = Properties.create(material, color)
|
||||||
|
|
||||||
|
if (setup != null) {
|
||||||
|
properties = setup(properties)
|
||||||
|
}
|
||||||
|
|
||||||
|
properties = tool.applyTo(properties)
|
||||||
|
properties = properties.apply(sound, Properties::sound)
|
||||||
|
properties = properties.apply(light) { level -> setLightLevel { level } }
|
||||||
|
properties = properties.apply(isOpaque) { setOpaque(always(it)) }
|
||||||
|
properties = properties.apply(suffocates) { setSuffocates(always(it)) }
|
||||||
|
properties = properties.apply(blocksVision) { setBlocksVision(always(it)) }
|
||||||
|
properties = properties.apply(hardness) { it.applyTo(this) }
|
||||||
|
|
||||||
|
if (isSolid == false) {
|
||||||
|
properties = properties.notSolid()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!material.blocksMovement()) {
|
||||||
|
if (isSolid == true) {
|
||||||
|
throw UnsupportedOperationException("[AbstractHeeBlockBuilder] cannot create a block that does not block movement and is solid at the same time")
|
||||||
|
}
|
||||||
|
|
||||||
|
properties = properties.doesNotBlockMovement()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (drop === BlockDrop.Nothing) {
|
||||||
|
properties = properties.noDrops()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lazyComponents.isInitialized() && components.randomTick != null) {
|
||||||
|
properties = properties.tickRandomly()
|
||||||
|
}
|
||||||
|
|
||||||
|
return properties
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <T> Properties.apply(value: T?, function: Properties.(T) -> Properties): Properties {
|
||||||
|
return if (value == null) this else function(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun build(propertiesSetup: (Properties.() -> Properties)? = null): T {
|
||||||
|
val components = if (lazyComponents.isInitialized()) components else null
|
||||||
|
return buildBlock(buildProperties(propertiesSetup), components)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal abstract fun buildBlock(properties: Properties, components: HeeBlockComponents?): T
|
||||||
|
}
|
@@ -0,0 +1,26 @@
|
|||||||
|
package chylex.hee.game.block.builder
|
||||||
|
|
||||||
|
import chylex.hee.game.block.HeeBlock2
|
||||||
|
import chylex.hee.game.block.HeeBlockWithComponents
|
||||||
|
import chylex.hee.game.block.IHeeBlock
|
||||||
|
import chylex.hee.game.block.interfaces.IBlockWithInterfaces
|
||||||
|
import net.minecraft.block.AbstractBlock.Properties
|
||||||
|
import net.minecraft.block.Block
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.state.StateContainer.Builder
|
||||||
|
|
||||||
|
open class HeeBlockBuilder : AbstractHeeBlockBuilder<HeeBlock2>() {
|
||||||
|
override fun buildBlock(properties: Properties, components: HeeBlockComponents?): HeeBlock2 {
|
||||||
|
if (components != null) {
|
||||||
|
return object : HeeBlockWithComponents(properties, components), IHeeBlock by IHeeBlock.FromBuilder(this@HeeBlockBuilder), IBlockWithInterfaces by interfaces.delegate {
|
||||||
|
override fun fillStateContainer(builder: Builder<Block, BlockState>) {
|
||||||
|
components.states.fillContainer(builder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return object : HeeBlock2(properties), IHeeBlock by IHeeBlock.FromBuilder(this), IBlockWithInterfaces by interfaces.delegate {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun HeeBlockBuilder(setup: HeeBlockBuilder.() -> Unit) = HeeBlockBuilder().apply(setup)
|
@@ -0,0 +1,86 @@
|
|||||||
|
package chylex.hee.game.block.builder
|
||||||
|
|
||||||
|
import chylex.hee.game.block.components.IBlockAddedComponent
|
||||||
|
import chylex.hee.game.block.components.IBlockClientEffectsComponent
|
||||||
|
import chylex.hee.game.block.components.IBlockCollideWithEntityComponent
|
||||||
|
import chylex.hee.game.block.components.IBlockDropsComponent
|
||||||
|
import chylex.hee.game.block.components.IBlockEntityComponent
|
||||||
|
import chylex.hee.game.block.components.IBlockExperienceComponent
|
||||||
|
import chylex.hee.game.block.components.IBlockExplodedComponent
|
||||||
|
import chylex.hee.game.block.components.IBlockHarvestabilityComponent
|
||||||
|
import chylex.hee.game.block.components.IBlockNameComponent
|
||||||
|
import chylex.hee.game.block.components.IBlockNeighborChanged
|
||||||
|
import chylex.hee.game.block.components.IBlockPlacementComponent
|
||||||
|
import chylex.hee.game.block.components.IBlockRandomTickComponent
|
||||||
|
import chylex.hee.game.block.components.IBlockScheduledTickComponent
|
||||||
|
import chylex.hee.game.block.components.IBlockShapeComponent
|
||||||
|
import chylex.hee.game.block.components.ICreatureSpawningOnBlockComponent
|
||||||
|
import chylex.hee.game.block.components.IFlammableBlockComponent
|
||||||
|
import chylex.hee.game.block.components.IPlayerUseBlockComponent
|
||||||
|
import chylex.hee.game.block.components.ISetBlockStateFromNeighbor
|
||||||
|
import chylex.hee.game.item.components.ITooltipComponent
|
||||||
|
import net.minecraft.block.BlockRenderType
|
||||||
|
|
||||||
|
class HeeBlockComponents {
|
||||||
|
val states = HeeBlockStates.Builder()
|
||||||
|
|
||||||
|
var name: IBlockNameComponent? = null
|
||||||
|
var tooltip: ITooltipComponent? = null
|
||||||
|
|
||||||
|
var shape: IBlockShapeComponent? = null
|
||||||
|
var renderType: BlockRenderType? = null
|
||||||
|
var ambientOcclusionValue: Float? = null
|
||||||
|
var clientEffects: IBlockClientEffectsComponent? = null
|
||||||
|
|
||||||
|
var drops: IBlockDropsComponent? = null
|
||||||
|
var harvestability: IBlockHarvestabilityComponent? = null
|
||||||
|
var experience: IBlockExperienceComponent? = null
|
||||||
|
var flammability: IFlammableBlockComponent? = null
|
||||||
|
|
||||||
|
var entity: IBlockEntityComponent? = null
|
||||||
|
var placement: IBlockPlacementComponent? = null
|
||||||
|
var onAdded: IBlockAddedComponent? = null
|
||||||
|
var onNeighborChanged: IBlockNeighborChanged? = null
|
||||||
|
var setStateFromNeighbor: ISetBlockStateFromNeighbor? = null
|
||||||
|
|
||||||
|
var scheduledTick: IBlockScheduledTickComponent? = null
|
||||||
|
var randomTick: IBlockRandomTickComponent? = null
|
||||||
|
|
||||||
|
var playerUse: IPlayerUseBlockComponent? = null
|
||||||
|
var onExploded: IBlockExplodedComponent? = null
|
||||||
|
var onCreatureSpawning: ICreatureSpawningOnBlockComponent? = null
|
||||||
|
var collideWithEntity: IBlockCollideWithEntityComponent? = null
|
||||||
|
|
||||||
|
var isAir: Boolean? = null
|
||||||
|
|
||||||
|
fun includeFrom(source: HeeBlockComponents) {
|
||||||
|
source.name?.let { this.name = it }
|
||||||
|
source.tooltip?.let { this.tooltip = it }
|
||||||
|
|
||||||
|
source.shape?.let { this.shape = it }
|
||||||
|
source.renderType?.let { this.renderType = it }
|
||||||
|
source.ambientOcclusionValue?.let { this.ambientOcclusionValue = it }
|
||||||
|
source.clientEffects?.let { this.clientEffects = it }
|
||||||
|
|
||||||
|
source.drops?.let { this.drops = it }
|
||||||
|
source.harvestability?.let { this.harvestability = it }
|
||||||
|
source.experience?.let { this.experience = it }
|
||||||
|
source.flammability?.let { this.flammability = it }
|
||||||
|
|
||||||
|
source.entity?.let { this.entity = it }
|
||||||
|
source.placement?.let { this.placement = it }
|
||||||
|
source.onAdded?.let { this.onAdded = it }
|
||||||
|
source.onNeighborChanged?.let { this.onNeighborChanged = it }
|
||||||
|
source.setStateFromNeighbor?.let { this.setStateFromNeighbor = it }
|
||||||
|
|
||||||
|
source.scheduledTick?.let { this.scheduledTick = it }
|
||||||
|
source.randomTick?.let { this.randomTick = it }
|
||||||
|
|
||||||
|
source.playerUse?.let { this.playerUse = it }
|
||||||
|
source.onExploded?.let { this.onExploded = it }
|
||||||
|
source.onCreatureSpawning?.let { this.onCreatureSpawning = it }
|
||||||
|
source.collideWithEntity?.let { this.collideWithEntity = it }
|
||||||
|
|
||||||
|
source.isAir?.let { this.isAir = it }
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,23 @@
|
|||||||
|
package chylex.hee.game.block.builder
|
||||||
|
|
||||||
|
import chylex.hee.game.block.interfaces.BlockInterfaceContainer
|
||||||
|
import chylex.hee.game.block.interfaces.IBlockInterface
|
||||||
|
import chylex.hee.game.block.interfaces.NoBlockInterfaces
|
||||||
|
|
||||||
|
class HeeBlockInterfaces {
|
||||||
|
private val interfaces = mutableMapOf<Class<out IBlockInterface>, Any>()
|
||||||
|
|
||||||
|
internal val delegate
|
||||||
|
get() = if (interfaces.isEmpty())
|
||||||
|
NoBlockInterfaces
|
||||||
|
else
|
||||||
|
BlockInterfaceContainer(interfaces)
|
||||||
|
|
||||||
|
operator fun <T : IBlockInterface> set(type: Class<T>, impl: T) {
|
||||||
|
interfaces[type] = impl
|
||||||
|
}
|
||||||
|
|
||||||
|
fun includeFrom(source: HeeBlockInterfaces) {
|
||||||
|
this.interfaces.putAll(source.interfaces)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,50 @@
|
|||||||
|
package chylex.hee.game.block.builder
|
||||||
|
|
||||||
|
import chylex.hee.game.block.util.BlockStateGenerics
|
||||||
|
import net.minecraft.block.Block
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.state.Property
|
||||||
|
import net.minecraft.state.StateContainer
|
||||||
|
import net.minecraft.util.Direction
|
||||||
|
import net.minecraft.util.Mirror
|
||||||
|
import net.minecraft.util.Rotation
|
||||||
|
|
||||||
|
class HeeBlockStates private constructor(private val statesWithDefaults: Map<Property<*>, Comparable<*>>, private val facingProperty: Property<Direction>?) {
|
||||||
|
fun applyDefaults(state: BlockState): BlockState {
|
||||||
|
if (statesWithDefaults.isEmpty()) {
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
return statesWithDefaults.entries.fold(state) { acc, entry ->
|
||||||
|
BlockStateGenerics.withProperty(acc, entry.key, entry.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getRotatedState(state: BlockState, rotation: Rotation): BlockState {
|
||||||
|
return facingProperty?.let { state.with(it, rotation.rotate(state[it])) } ?: state
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getMirroredState(state: BlockState, mirror: Mirror): BlockState {
|
||||||
|
return facingProperty?.let { state.with(it, mirror.mirror(state[it])) } ?: state
|
||||||
|
}
|
||||||
|
|
||||||
|
class Builder {
|
||||||
|
private val statesWithDefaults = mutableMapOf<Property<*>, Comparable<*>>()
|
||||||
|
|
||||||
|
var facingProperty: Property<Direction>? = null
|
||||||
|
|
||||||
|
fun <T : Comparable<T>> set(state: Property<T>, default: T) {
|
||||||
|
statesWithDefaults[state] = default
|
||||||
|
}
|
||||||
|
|
||||||
|
fun fillContainer(builder: StateContainer.Builder<Block, BlockState>) {
|
||||||
|
for (property in statesWithDefaults.keys) {
|
||||||
|
builder.add(property)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun build(): HeeBlockStates {
|
||||||
|
return HeeBlockStates(statesWithDefaults.toMap(), facingProperty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,9 @@
|
|||||||
|
package chylex.hee.game.block.components
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.world.World
|
||||||
|
|
||||||
|
fun interface IBlockAddedComponent {
|
||||||
|
fun onAdded(state: BlockState, world: World, pos: BlockPos)
|
||||||
|
}
|
@@ -0,0 +1,10 @@
|
|||||||
|
package chylex.hee.game.block.components
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.world.World
|
||||||
|
import java.util.Random
|
||||||
|
|
||||||
|
interface IBlockClientEffectsComponent {
|
||||||
|
fun randomTick(state: BlockState, world: World, pos: BlockPos, rand: Random) {}
|
||||||
|
}
|
@@ -0,0 +1,10 @@
|
|||||||
|
package chylex.hee.game.block.components
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.entity.Entity
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.world.World
|
||||||
|
|
||||||
|
fun interface IBlockCollideWithEntityComponent {
|
||||||
|
fun collide(state: BlockState, world: World, pos: BlockPos, entity: Entity)
|
||||||
|
}
|
@@ -0,0 +1,15 @@
|
|||||||
|
package chylex.hee.game.block.components
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.loot.LootContext
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.world.IBlockReader
|
||||||
|
|
||||||
|
interface IBlockDropsComponent {
|
||||||
|
fun getDrops(state: BlockState, context: LootContext.Builder): MutableList<ItemStack>
|
||||||
|
|
||||||
|
fun getPickBlock(state: BlockState, world: IBlockReader, pos: BlockPos): ItemStack? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,7 @@
|
|||||||
|
package chylex.hee.game.block.components
|
||||||
|
|
||||||
|
import net.minecraft.tileentity.TileEntity
|
||||||
|
|
||||||
|
fun interface IBlockEntityComponent {
|
||||||
|
fun create(): TileEntity
|
||||||
|
}
|
@@ -0,0 +1,7 @@
|
|||||||
|
package chylex.hee.game.block.components
|
||||||
|
|
||||||
|
import java.util.Random
|
||||||
|
|
||||||
|
fun interface IBlockExperienceComponent {
|
||||||
|
fun getExperience(rand: Random): Int
|
||||||
|
}
|
@@ -0,0 +1,11 @@
|
|||||||
|
package chylex.hee.game.block.components
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.world.Explosion
|
||||||
|
import net.minecraft.world.World
|
||||||
|
|
||||||
|
interface IBlockExplodedComponent {
|
||||||
|
fun canDrop(explosion: Explosion): Boolean
|
||||||
|
fun onExploded(state: BlockState, world: World, pos: BlockPos, explosion: Explosion)
|
||||||
|
}
|
@@ -0,0 +1,8 @@
|
|||||||
|
package chylex.hee.game.block.components
|
||||||
|
|
||||||
|
import chylex.hee.util.forge.EventResult
|
||||||
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
|
|
||||||
|
fun interface IBlockHarvestabilityComponent {
|
||||||
|
fun canHarvest(player: PlayerEntity): EventResult
|
||||||
|
}
|
@@ -0,0 +1,19 @@
|
|||||||
|
package chylex.hee.game.block.components
|
||||||
|
|
||||||
|
import net.minecraft.block.Block
|
||||||
|
|
||||||
|
interface IBlockNameComponent {
|
||||||
|
val translationKey: String
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun of(translationKey: String) = object : IBlockNameComponent {
|
||||||
|
override val translationKey
|
||||||
|
get() = translationKey
|
||||||
|
}
|
||||||
|
|
||||||
|
fun of(block: Block) = object : IBlockNameComponent {
|
||||||
|
override val translationKey
|
||||||
|
get() = block.translationKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,10 @@
|
|||||||
|
package chylex.hee.game.block.components
|
||||||
|
|
||||||
|
import net.minecraft.block.Block
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.world.World
|
||||||
|
|
||||||
|
fun interface IBlockNeighborChanged {
|
||||||
|
fun onNeighborChanged(state: BlockState, world: World, pos: BlockPos, oldNeighborBlock: Block, newNeighborBlock: Block, neighborPos: BlockPos)
|
||||||
|
}
|
@@ -0,0 +1,21 @@
|
|||||||
|
package chylex.hee.game.block.components
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.entity.LivingEntity
|
||||||
|
import net.minecraft.item.BlockItemUseContext
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.world.IWorldReader
|
||||||
|
import net.minecraft.world.World
|
||||||
|
|
||||||
|
interface IBlockPlacementComponent {
|
||||||
|
fun isPositionValid(state: BlockState, world: IWorldReader, pos: BlockPos): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPlacedState(defaultState: BlockState, world: World, pos: BlockPos, context: BlockItemUseContext): BlockState {
|
||||||
|
return defaultState
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onPlacedBy(state: BlockState, world: World, pos: BlockPos, placer: LivingEntity?, stack: ItemStack) {}
|
||||||
|
}
|
@@ -0,0 +1,10 @@
|
|||||||
|
package chylex.hee.game.block.components
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.world.World
|
||||||
|
import java.util.Random
|
||||||
|
|
||||||
|
fun interface IBlockRandomTickComponent {
|
||||||
|
fun onTick(state: BlockState, world: World, pos: BlockPos, rand: Random)
|
||||||
|
}
|
@@ -0,0 +1,19 @@
|
|||||||
|
package chylex.hee.game.block.components
|
||||||
|
|
||||||
|
import chylex.hee.game.block.properties.TickSchedule
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.world.World
|
||||||
|
import java.util.Random
|
||||||
|
|
||||||
|
interface IBlockScheduledTickComponent {
|
||||||
|
/**
|
||||||
|
* Return the amount of ticks before the first [onTick] call after the block is added to the world.
|
||||||
|
*/
|
||||||
|
fun onAdded(state: BlockState, world: World, pos: BlockPos, rand: Random): TickSchedule
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the amount of ticks before the next [onTick] call.
|
||||||
|
*/
|
||||||
|
fun onTick(state: BlockState, world: World, pos: BlockPos, rand: Random): TickSchedule
|
||||||
|
}
|
@@ -0,0 +1,30 @@
|
|||||||
|
package chylex.hee.game.block.components
|
||||||
|
|
||||||
|
import chylex.hee.game.block.util.asVoxelShape
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.util.math.AxisAlignedBB
|
||||||
|
import net.minecraft.util.math.shapes.VoxelShape
|
||||||
|
|
||||||
|
interface IBlockShapeComponent {
|
||||||
|
fun getShape(state: BlockState): VoxelShape
|
||||||
|
|
||||||
|
fun getCollisionShape(state: BlockState): VoxelShape? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getRaytraceShape(state: BlockState): VoxelShape? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun of(shape: VoxelShape) = object : IBlockShapeComponent {
|
||||||
|
override fun getShape(state: BlockState): VoxelShape {
|
||||||
|
return shape
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun of(aabb: AxisAlignedBB): IBlockShapeComponent {
|
||||||
|
return of(aabb.asVoxelShape)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,11 @@
|
|||||||
|
package chylex.hee.game.block.components
|
||||||
|
|
||||||
|
import chylex.hee.util.forge.EventResult
|
||||||
|
import net.minecraft.entity.EntitySpawnPlacementRegistry.PlacementType
|
||||||
|
import net.minecraft.entity.EntityType
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.world.IBlockReader
|
||||||
|
|
||||||
|
fun interface ICreatureSpawningOnBlockComponent {
|
||||||
|
fun canSpawn(world: IBlockReader, pos: BlockPos, placementType: PlacementType?, entityType: EntityType<*>?): EventResult
|
||||||
|
}
|
@@ -0,0 +1,20 @@
|
|||||||
|
package chylex.hee.game.block.components
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.state.properties.BlockStateProperties
|
||||||
|
|
||||||
|
interface IFlammableBlockComponent {
|
||||||
|
val flammability: Int
|
||||||
|
val fireSpread: Int
|
||||||
|
|
||||||
|
fun takeIfFlammable(state: BlockState): IFlammableBlockComponent? {
|
||||||
|
return this.takeUnless { state.hasProperty(BlockStateProperties.WATERLOGGED) && state[BlockStateProperties.WATERLOGGED] }
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun of(flammability: Int, fireSpread: Int) = object : IFlammableBlockComponent {
|
||||||
|
override val flammability = flammability
|
||||||
|
override val fireSpread = fireSpread
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,12 @@
|
|||||||
|
package chylex.hee.game.block.components
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.entity.player.PlayerEntity
|
||||||
|
import net.minecraft.util.ActionResultType
|
||||||
|
import net.minecraft.util.Hand
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.world.World
|
||||||
|
|
||||||
|
fun interface IPlayerUseBlockComponent {
|
||||||
|
fun use(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand): ActionResultType
|
||||||
|
}
|
@@ -0,0 +1,10 @@
|
|||||||
|
package chylex.hee.game.block.components
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState
|
||||||
|
import net.minecraft.util.Direction
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.world.IWorld
|
||||||
|
|
||||||
|
fun interface ISetBlockStateFromNeighbor {
|
||||||
|
fun getNewState(state: BlockState, world: IWorld, pos: BlockPos, neighborFacing: Direction, neighborPos: BlockPos): BlockState
|
||||||
|
}
|
@@ -0,0 +1,9 @@
|
|||||||
|
package chylex.hee.game.block.interfaces
|
||||||
|
|
||||||
|
internal class BlockInterfaceContainer(interfaces: Map<Class<out IBlockInterface>, Any>) : IBlockWithInterfaces {
|
||||||
|
private val interfaces = interfaces.toMap()
|
||||||
|
|
||||||
|
override fun getInterface(type: Class<out IBlockInterface>): Any? {
|
||||||
|
return interfaces[type]
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,6 @@
|
|||||||
|
package chylex.hee.game.block.interfaces
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks interfaces that can be attached to blocks.
|
||||||
|
*/
|
||||||
|
interface IBlockInterface
|
@@ -0,0 +1,15 @@
|
|||||||
|
package chylex.hee.game.block.interfaces
|
||||||
|
|
||||||
|
import net.minecraft.block.Block
|
||||||
|
|
||||||
|
interface IBlockWithInterfaces {
|
||||||
|
fun getInterface(type: Class<out IBlockInterface>): Any?
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : IBlockInterface> IBlockWithInterfaces.getHeeInterface(): T? {
|
||||||
|
return this.getInterface(T::class.java) as? T
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : IBlockInterface> Block.getHeeInterface(): T? {
|
||||||
|
return (this as? IBlockWithInterfaces)?.getHeeInterface()
|
||||||
|
}
|
@@ -0,0 +1,7 @@
|
|||||||
|
package chylex.hee.game.block.interfaces
|
||||||
|
|
||||||
|
internal object NoBlockInterfaces : IBlockWithInterfaces {
|
||||||
|
override fun getInterface(type: Class<out IBlockInterface>): Any? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
@@ -1,9 +1,10 @@
|
|||||||
package chylex.hee.game.block.logic
|
package chylex.hee.game.block.logic
|
||||||
|
|
||||||
|
import chylex.hee.game.block.interfaces.IBlockInterface
|
||||||
import net.minecraft.block.BlockState
|
import net.minecraft.block.BlockState
|
||||||
import net.minecraft.util.math.BlockPos
|
import net.minecraft.util.math.BlockPos
|
||||||
import net.minecraft.world.IBlockReader
|
import net.minecraft.world.IBlockReader
|
||||||
|
|
||||||
interface IBlockDynamicHardness {
|
interface IBlockDynamicHardness : IBlockInterface {
|
||||||
fun getBlockHardness(world: IBlockReader, pos: BlockPos, state: BlockState, originalHardness: Float): Float
|
fun getBlockHardness(world: IBlockReader, pos: BlockPos, state: BlockState, originalHardness: Float): Float
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,11 @@
|
|||||||
|
package chylex.hee.game.block.properties
|
||||||
|
|
||||||
|
import net.minecraft.block.AbstractBlock.Properties
|
||||||
|
|
||||||
|
data class BlockHardness(val hardness: Float, val resistance: Float) {
|
||||||
|
constructor(hardnessAndResistance: Float) : this(hardnessAndResistance, hardnessAndResistance)
|
||||||
|
|
||||||
|
fun applyTo(properties: Properties): Properties {
|
||||||
|
return properties.hardnessAndResistance(hardness, resistance)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,21 @@
|
|||||||
|
package chylex.hee.game.block.properties
|
||||||
|
|
||||||
|
import net.minecraft.block.AbstractBlock.Properties
|
||||||
|
import net.minecraftforge.common.ToolType
|
||||||
|
|
||||||
|
@Suppress("DataClassPrivateConstructor")
|
||||||
|
data class BlockHarvestTool private constructor(val tier: Int, val toolType: ToolType?, val requiresTool: Boolean) {
|
||||||
|
fun applyTo(properties: Properties): Properties {
|
||||||
|
return properties
|
||||||
|
.harvestLevel(tier)
|
||||||
|
.let { if (toolType != null) it.harvestTool(toolType) else it }
|
||||||
|
.let { if (requiresTool) it.setRequiresTool() else it }
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val NONE = BlockHarvestTool(-1, null, requiresTool = false)
|
||||||
|
|
||||||
|
fun required(tier: Int, toolType: ToolType) = BlockHarvestTool(tier, toolType, requiresTool = true)
|
||||||
|
fun optional(tier: Int, toolType: ToolType) = BlockHarvestTool(tier, toolType, requiresTool = false)
|
||||||
|
}
|
||||||
|
}
|
@@ -1,7 +1,13 @@
|
|||||||
package chylex.hee.game.block.properties
|
package chylex.hee.game.block.properties
|
||||||
|
|
||||||
interface IBlockStateModel {
|
import net.minecraft.block.Block
|
||||||
|
|
||||||
|
interface IBlockStateModel : IBlockStateModelSupplier {
|
||||||
val blockState: BlockStatePreset
|
val blockState: BlockStatePreset
|
||||||
val blockModel: BlockModel
|
val blockModel: BlockModel
|
||||||
val itemModel: BlockItemModel?
|
val itemModel: BlockItemModel?
|
||||||
|
|
||||||
|
override fun generate(block: Block): IBlockStateModel {
|
||||||
|
return this
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,7 @@
|
|||||||
|
package chylex.hee.game.block.properties
|
||||||
|
|
||||||
|
import net.minecraft.block.Block
|
||||||
|
|
||||||
|
fun interface IBlockStateModelSupplier {
|
||||||
|
fun generate(block: Block): IBlockStateModel
|
||||||
|
}
|
@@ -0,0 +1,19 @@
|
|||||||
|
package chylex.hee.game.block.properties
|
||||||
|
|
||||||
|
import net.minecraft.block.Block
|
||||||
|
import net.minecraft.util.math.BlockPos
|
||||||
|
import net.minecraft.world.World
|
||||||
|
|
||||||
|
sealed class TickSchedule {
|
||||||
|
abstract fun schedule(world: World, pos: BlockPos, block: Block)
|
||||||
|
|
||||||
|
object Never : TickSchedule() {
|
||||||
|
override fun schedule(world: World, pos: BlockPos, block: Block) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InTicks(private val ticks: Int) : TickSchedule() {
|
||||||
|
override fun schedule(world: World, pos: BlockPos, block: Block) {
|
||||||
|
world.pendingBlockTicks.scheduleTick(pos, block, ticks)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,10 +1,10 @@
|
|||||||
package chylex.hee.game.entity.living.path
|
package chylex.hee.game.entity.living.path
|
||||||
|
|
||||||
import chylex.hee.game.entity.util.posVec
|
import chylex.hee.game.entity.util.posVec
|
||||||
import chylex.hee.system.random.nextInt
|
|
||||||
import chylex.hee.util.math.Vec
|
import chylex.hee.util.math.Vec
|
||||||
import chylex.hee.util.math.Vec3
|
import chylex.hee.util.math.Vec3
|
||||||
import chylex.hee.util.math.square
|
import chylex.hee.util.math.square
|
||||||
|
import chylex.hee.util.random.nextInt
|
||||||
import net.minecraft.entity.Entity
|
import net.minecraft.entity.Entity
|
||||||
import net.minecraft.entity.MobEntity
|
import net.minecraft.entity.MobEntity
|
||||||
import net.minecraft.pathfinding.GroundPathNavigator
|
import net.minecraft.pathfinding.GroundPathNavigator
|
||||||
|
@@ -0,0 +1,7 @@
|
|||||||
|
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
|
@@ -0,0 +1,156 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
@@ -1,5 +1,6 @@
|
|||||||
package chylex.hee.game.item
|
package chylex.hee.game.item
|
||||||
|
|
||||||
|
import chylex.hee.game.item.interfaces.IItemWithInterfaces
|
||||||
import net.minecraft.item.Item
|
import net.minecraft.item.Item
|
||||||
|
|
||||||
open class HeeItem(properties: Properties) : Item(properties), IHeeItem
|
abstract class HeeItem(properties: Properties) : Item(properties), IHeeItem, IItemWithInterfaces
|
||||||
|
@@ -0,0 +1,155 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,7 @@
|
|||||||
package chylex.hee.game.item
|
package chylex.hee.game.item
|
||||||
|
|
||||||
import chylex.hee.client.text.LocalizationStrategy
|
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.ItemModel
|
||||||
import chylex.hee.game.item.properties.ItemTint
|
import chylex.hee.game.item.properties.ItemTint
|
||||||
import chylex.hee.game.item.util.ItemProperty
|
import chylex.hee.game.item.util.ItemProperty
|
||||||
@@ -25,4 +26,13 @@ interface IHeeItem {
|
|||||||
|
|
||||||
val tags: List<INamedTag<Item>>
|
val tags: List<INamedTag<Item>>
|
||||||
get() = emptyList()
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,95 @@
|
|||||||
|
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
|
||||||
|
}
|
@@ -0,0 +1,19 @@
|
|||||||
|
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)
|
@@ -0,0 +1,18 @@
|
|||||||
|
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)
|
@@ -0,0 +1,66 @@
|
|||||||
|
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 }
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,23 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,19 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,9 @@
|
|||||||
|
package chylex.hee.game.item.components
|
||||||
|
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
|
||||||
|
object EnchantmentGlintComponent : IItemGlintComponent {
|
||||||
|
override fun hasGlint(stack: ItemStack): Boolean {
|
||||||
|
return stack.isEnchanted
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,11 @@
|
|||||||
|
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
|
||||||
|
}
|
@@ -0,0 +1,13 @@
|
|||||||
|
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
|
||||||
|
}
|
@@ -0,0 +1,9 @@
|
|||||||
|
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)
|
||||||
|
}
|
@@ -0,0 +1,18 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,22 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,13 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,30 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,16 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,7 @@
|
|||||||
|
package chylex.hee.game.item.components
|
||||||
|
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
|
|
||||||
|
fun interface IRepairItemComponent {
|
||||||
|
fun isRepairable(toRepair: ItemStack, repairWith: ItemStack): Boolean
|
||||||
|
}
|
@@ -0,0 +1,9 @@
|
|||||||
|
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)
|
||||||
|
}
|
@@ -0,0 +1,9 @@
|
|||||||
|
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?)
|
||||||
|
}
|
@@ -0,0 +1,11 @@
|
|||||||
|
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>
|
||||||
|
}
|
@@ -0,0 +1,10 @@
|
|||||||
|
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
|
||||||
|
}
|
@@ -0,0 +1,12 @@
|
|||||||
|
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
|
||||||
|
}
|
@@ -0,0 +1,28 @@
|
|||||||
|
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
|
||||||
|
}
|
@@ -0,0 +1,27 @@
|
|||||||
|
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
|
||||||
|
}
|
@@ -0,0 +1,11 @@
|
|||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,6 @@
|
|||||||
|
package chylex.hee.game.item.interfaces
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks interfaces that can be attached to items.
|
||||||
|
*/
|
||||||
|
interface IItemInterface
|
@@ -0,0 +1,15 @@
|
|||||||
|
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()
|
||||||
|
}
|
@@ -0,0 +1,9 @@
|
|||||||
|
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]
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,7 @@
|
|||||||
|
package chylex.hee.game.item.interfaces
|
||||||
|
|
||||||
|
internal object NoItemInterfaces : IItemWithInterfaces {
|
||||||
|
override fun getInterface(type: Class<out IItemInterface>): Any? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
@@ -1,5 +1,6 @@
|
|||||||
package chylex.hee.game.item.properties
|
package chylex.hee.game.item.properties
|
||||||
|
|
||||||
|
import chylex.hee.util.color.RGB
|
||||||
import chylex.hee.util.forge.Side
|
import chylex.hee.util.forge.Side
|
||||||
import chylex.hee.util.forge.Sided
|
import chylex.hee.util.forge.Sided
|
||||||
import net.minecraft.client.renderer.color.IItemColor
|
import net.minecraft.client.renderer.color.IItemColor
|
||||||
@@ -9,6 +10,7 @@ import net.minecraft.item.ItemStack
|
|||||||
abstract class ItemTint : IItemColor {
|
abstract class ItemTint : IItemColor {
|
||||||
protected companion object {
|
protected companion object {
|
||||||
const val NO_TINT = -1
|
const val NO_TINT = -1
|
||||||
|
val WHITE = RGB(255u).i
|
||||||
}
|
}
|
||||||
|
|
||||||
@Sided(Side.CLIENT)
|
@Sided(Side.CLIENT)
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
package chylex.hee.game.item.repair
|
package chylex.hee.game.item.repair
|
||||||
|
|
||||||
interface ICustomRepairBehavior {
|
import chylex.hee.game.item.interfaces.IItemInterface
|
||||||
|
|
||||||
|
fun interface ICustomRepairBehavior : IItemInterface {
|
||||||
fun onRepairUpdate(instance: RepairInstance)
|
fun onRepairUpdate(instance: RepairInstance)
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user