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

4 Commits

346 changed files with 4606 additions and 4379 deletions

1
.idea/gradle.xml generated
View File

@@ -12,7 +12,6 @@
<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>

View File

@@ -60,7 +60,6 @@ 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)
} }
@@ -129,6 +128,7 @@ 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,7 +138,6 @@ 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
} }
@@ -146,6 +145,7 @@ 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,7 +155,6 @@ 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
} }
@@ -163,6 +162,7 @@ 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,7 +174,6 @@ 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
@@ -191,12 +190,12 @@ mixin {
dependencies { dependencies {
minecraft "net.minecraftforge:forge:" + mc_version + "-" + forge_version minecraft "net.minecraftforge:forge:" + mc_version + "-" + forge_version
implementation project(":util")
implementation project(":system") implementation project(":system")
implementation project(":util")
implementation "thedarkcolour:kotlinforforge:" + kotlin_mod_version implementation "thedarkcolour:kotlinforforge:" + kotlin_mod_version
testImplementation project(":util")
testImplementation project(":system") testImplementation project(":system")
testImplementation project(":util")
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") {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,74 +0,0 @@
package chylex.hee.debug
import chylex.hee.HEE
import chylex.hee.client.BuildStick
import chylex.hee.client.DebugMenu
import chylex.hee.client.GameModeToggle
import chylex.hee.client.TerritoryVoidDebug
import chylex.hee.game.block.BlockScaffoldingDebug
import chylex.hee.game.block.HeeBlock
import chylex.hee.game.block.properties.BlockBuilder
import chylex.hee.game.command.client.CommandClientDebugToggles
import chylex.hee.game.command.client.CommandClientScaffolding
import chylex.hee.game.command.server.CommandServerInstability
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 fun createScaffoldingBlock(builder: BlockBuilder): HeeBlock {
return BlockScaffoldingDebug(builder)
}
@SubscribeEvent
fun onClientSetup(@Suppress("UNUSED_PARAMETER") e: FMLClientSetupEvent) {
initializeClient()
}
@Sided(Side.CLIENT)
private fun initializeClient() {
if (HEE.debug) {
MinecraftForge.EVENT_BUS.register(DebugMenu)
MinecraftForge.EVENT_BUS.register(BuildStick)
MinecraftForge.EVENT_BUS.register(GameModeToggle)
MinecraftForge.EVENT_BUS.register(TerritoryVoidDebug)
MinecraftForge.EVENT_BUS.register(object : Any() {
@SubscribeEvent
fun onGuiOpen(@Suppress("UNUSED_PARAMETER") e: GuiOpenEvent) {
PowerShell.maximizeWindow()
MinecraftForge.EVENT_BUS.unregister(this)
}
})
}
}
}

View File

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

View File

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

View File

@@ -1,103 +0,0 @@
package chylex.hee.game.block
import chylex.hee.debug.PowerShell
import chylex.hee.game.Environment
import chylex.hee.game.block.properties.BlockBuilder
import chylex.hee.game.command.client.CommandClientScaffolding
import chylex.hee.game.world.generation.structure.file.StructureFile
import chylex.hee.game.world.generation.util.WorldToStructureWorldAdapter
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.math.BlockRayTraceResult
import net.minecraft.util.text.StringTextComponent
import net.minecraft.util.text.TextFormatting
import net.minecraft.world.World
import java.nio.file.Files
class BlockScaffoldingDebug(builder: BlockBuilder) : BlockScaffolding(builder) {
override fun onBlockActivated(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hit: BlockRayTraceResult): ActionResultType {
if (world.isRemote && player.isSneaking && !player.abilities.isFlying) {
val palette = CommandClientScaffolding.currentPalette
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, this)
val structureFile = Files.createTempDirectory("HardcoreEnderExpansion_Structure_").resolve(CommandClientScaffolding.currentFile).toFile()
CompressedStreamTools.write(structureTag, structureFile)
PowerShell.setClipboardContents(structureFile)
if (missingMappings.isNotEmpty()) {
player.sendMessage(StringTextComponent("Missing mappings for states:"), Util.DUMMY_UUID)
for (missingMapping in missingMappings) {
player.sendMessage(StringTextComponent(" - ${TextFormatting.GRAY}$missingMapping"), Util.DUMMY_UUID)
}
}
player.sendMessage(StringTextComponent("Generated structure file of ${box.size}."), Util.DUMMY_UUID)
return SUCCESS
}
return FAIL
}
// Helpers
private fun find(world: World, pos: BlockPos?, direction: Direction): BlockPos? {
return pos?.offsetUntilExcept(direction, 0..255) { it.getBlock(world) === Blocks.AIR }
}
private fun findMinPos(world: World, pos: BlockPos): BlockPos? {
val bottomPos = find(world, pos, DOWN)
val y = bottomPos?.y
val x = find(world, bottomPos, WEST)?.x
val z = find(world, bottomPos, NORTH)?.z
return if (x == null || y == null || z == null) null else Pos(x, y, z)
}
private fun findMaxPos(world: World, pos: BlockPos): BlockPos? {
val topPos = find(world, pos, UP)
val y = topPos?.y
val x = find(world, topPos, EAST)?.x
val z = find(world, topPos, SOUTH)?.z
return if (x == null || y == null || z == null) null else Pos(x, y, z)
}
}

View File

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

View File

@@ -1,7 +1,6 @@
package chylex.hee 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
@@ -13,10 +12,6 @@ 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"))
} }

View File

@@ -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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,6 @@
package chylex.hee.game.item 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
@@ -26,13 +25,4 @@ 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()
}
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,6 +1,5 @@
package chylex.hee.game.item.properties 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
@@ -10,7 +9,6 @@ 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)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,10 +3,10 @@ package chylex.hee.game.world.generation.blob.layouts
import chylex.hee.game.world.generation.blob.BlobGenerator import chylex.hee.game.world.generation.blob.BlobGenerator
import chylex.hee.game.world.generation.blob.IBlobLayout import chylex.hee.game.world.generation.blob.IBlobLayout
import chylex.hee.game.world.generation.structure.world.ScaffoldedWorld import chylex.hee.game.world.generation.structure.world.ScaffoldedWorld
import chylex.hee.system.random.nextVector
import chylex.hee.util.math.Pos import chylex.hee.util.math.Pos
import chylex.hee.util.math.Size import chylex.hee.util.math.Size
import chylex.hee.util.math.center import chylex.hee.util.math.center
import chylex.hee.util.random.nextVector
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import java.util.Random import java.util.Random

View File

@@ -5,8 +5,8 @@ import chylex.hee.game.world.generation.blob.BlobGenerator
import chylex.hee.game.world.generation.blob.IBlobPopulator import chylex.hee.game.world.generation.blob.IBlobPopulator
import chylex.hee.game.world.generation.ore.IOreTechnique import chylex.hee.game.world.generation.ore.IOreTechnique
import chylex.hee.game.world.generation.structure.world.ScaffoldedWorld import chylex.hee.game.world.generation.structure.world.ScaffoldedWorld
import chylex.hee.system.random.nextInt
import chylex.hee.util.math.Pos import chylex.hee.util.math.Pos
import chylex.hee.util.random.nextInt
import java.util.Random import java.util.Random
class BlobPopulatorOre( class BlobPopulatorOre(

View File

@@ -4,8 +4,8 @@ import chylex.hee.game.world.generation.IBlockPlacer
import chylex.hee.game.world.generation.cave.ICaveCarver import chylex.hee.game.world.generation.cave.ICaveCarver
import chylex.hee.game.world.generation.structure.world.SegmentedWorld import chylex.hee.game.world.generation.structure.world.SegmentedWorld
import chylex.hee.game.world.util.allInCenteredBoxMutable import chylex.hee.game.world.util.allInCenteredBoxMutable
import chylex.hee.system.random.nextFloat
import chylex.hee.util.math.Pos import chylex.hee.util.math.Pos
import chylex.hee.util.random.nextFloat
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.vector.Vector3d import net.minecraft.util.math.vector.Vector3d
import kotlin.math.abs import kotlin.math.abs

View File

@@ -5,9 +5,9 @@ import chylex.hee.game.world.generation.cave.ICaveCarver
import chylex.hee.game.world.generation.structure.world.SegmentedWorld import chylex.hee.game.world.generation.structure.world.SegmentedWorld
import chylex.hee.game.world.util.allInCenteredBoxMutable import chylex.hee.game.world.util.allInCenteredBoxMutable
import chylex.hee.game.world.util.distanceSqTo import chylex.hee.game.world.util.distanceSqTo
import chylex.hee.system.random.nextFloat
import chylex.hee.util.math.Pos import chylex.hee.util.math.Pos
import chylex.hee.util.math.square import chylex.hee.util.math.square
import chylex.hee.util.random.nextFloat
import net.minecraft.util.math.vector.Vector3d import net.minecraft.util.math.vector.Vector3d
class CaveCarverSphere(private val maxRandomRadiusReduction: Float) : ICaveCarver { class CaveCarverSphere(private val maxRandomRadiusReduction: Float) : ICaveCarver {

View File

@@ -7,7 +7,7 @@ import java.util.Random
import java.util.stream.IntStream import java.util.stream.IntStream
import kotlin.math.pow import kotlin.math.pow
sealed class NoiseGenerator(private val xScale: Double, private val zScale: Double) { sealed class Noise2D(private val xScale: Double, private val zScale: Double) {
// Generation // Generation
@@ -27,7 +27,7 @@ sealed class NoiseGenerator(private val xScale: Double, private val zScale: Doub
// Implementations // Implementations
open class OldPerlin(rand: Random, private val xScale: Double, private val zScale: Double, octaves: Int) : NoiseGenerator(xScale, zScale) { open class OldPerlin(rand: Random, private val xScale: Double, private val zScale: Double, octaves: Int) : Noise2D(xScale, zScale) {
constructor(rand: Random, scale: Double, octaves: Int) : this(rand, scale, scale, octaves) constructor(rand: Random, scale: Double, octaves: Int) : this(rand, scale, scale, octaves)
private val noiseLevels = Array(octaves) { SimplexNoiseGenerator(rand) } private val noiseLevels = Array(octaves) { SimplexNoiseGenerator(rand) }
@@ -55,7 +55,7 @@ sealed class NoiseGenerator(private val xScale: Double, private val zScale: Doub
override fun getRawValue(x: Double, z: Double) = (super.getRawValue(x, z) + normalizationApproxBoundary) / (2 * normalizationApproxBoundary) override fun getRawValue(x: Double, z: Double) = (super.getRawValue(x, z) + normalizationApproxBoundary) / (2 * normalizationApproxBoundary)
} }
class NewPerlin(rand: Random, private val xScale: Double, private val zScale: Double, octaves: Int) : NoiseGenerator(xScale, zScale) { class NewPerlin(rand: Random, private val xScale: Double, private val zScale: Double, octaves: Int) : Noise2D(xScale, zScale) {
constructor(rand: Random, scale: Double, octaves: Int) : this(rand, scale, scale, octaves) constructor(rand: Random, scale: Double, octaves: Int) : this(rand, scale, scale, octaves)
private val generator = PerlinNoiseGenerator(SharedSeedRandom(rand.nextLong()), IntStream.rangeClosed(-octaves + 1, 0)) private val generator = PerlinNoiseGenerator(SharedSeedRandom(rand.nextLong()), IntStream.rangeClosed(-octaves + 1, 0))

View File

@@ -0,0 +1,75 @@
package chylex.hee.game.world.generation.noise
import chylex.hee.game.world.generation.noise.OpenSimplex2S.GenerateContext3D
import chylex.hee.game.world.generation.noise.OpenSimplex2S.LatticeOrientation3D
import chylex.hee.util.math.MutablePos
import net.minecraft.util.math.BlockPos
import java.util.Random
sealed class Noise3D {
// Generation
abstract fun getRawValue(x: Double, y: Double, z: Double): Double
// Implementations
sealed class SuperSimplex(rand: Random) : Noise3D() {
protected val generator = OpenSimplex2S(rand.nextLong())
protected abstract val orientation: LatticeOrientation3D
class AreaNoise(val buffer: Array<Array<DoubleArray>>) {
operator fun get(x: Int, y: Int, z: Int) = buffer[z][y][x]
inline fun forEach(callback: (BlockPos.Mutable, Double) -> Unit) {
val pos = MutablePos()
for ((z, yArray) in buffer.withIndex()) {
pos.z = z
for ((y, xArray) in yArray.withIndex()) {
pos.y = y
for ((x, value) in xArray.withIndex()) {
pos.x = x
callback(pos, value)
}
}
}
}
}
class AreaGenerator(private val generator: OpenSimplex2S, private val context: GenerateContext3D) {
fun generate(x: Int, y: Int, z: Int, xSize: Int, ySize: Int, zSize: Int): AreaNoise {
val buffer = Array(zSize) { Array(ySize) { DoubleArray(xSize) { 0.0 } } }
return buffer.apply { generator.generate3(context, this, x, y, z) }.let(::AreaNoise)
}
}
fun getAreaGenerator(xFreq: Double, yFreq: Double, zFreq: Double, amplitude: Double): AreaGenerator {
return AreaGenerator(generator, GenerateContext3D(orientation, xFreq, yFreq, zFreq, amplitude))
}
fun getAreaGenerator(xzFreq: Double, yFreq: Double, amplitude: Double): AreaGenerator {
return getAreaGenerator(xzFreq, yFreq, xzFreq, amplitude)
}
class Classic(rand: Random) : SuperSimplex(rand) {
override val orientation
get() = LatticeOrientation3D.Classic
override fun getRawValue(x: Double, y: Double, z: Double): Double {
return generator.noise3_Classic(x, y, z)
}
}
class Terrain(rand: Random) : SuperSimplex(rand) {
override val orientation
get() = LatticeOrientation3D.XZBeforeY
override fun getRawValue(x: Double, y: Double, z: Double): Double {
return generator.noise3_XZBeforeY(x, y, z)
}
}
}
}

View File

@@ -1,7 +1,5 @@
package chylex.hee.game.world.generation.noise package chylex.hee.game.world.generation.noise
import chylex.hee.util.math.FloatRange
import chylex.hee.util.math.range
import chylex.hee.util.math.remapRange import chylex.hee.util.math.remapRange
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.pow import kotlin.math.pow
@@ -28,12 +26,12 @@ class NoiseValue(var value: Double) {
it.coerceIn(minimum, maximum) it.coerceIn(minimum, maximum)
} }
fun remap(oldRange: FloatRange, newRange: FloatRange) = then { fun remap(oldRange: ClosedFloatingPointRange<Double>, newRange: ClosedFloatingPointRange<Double>) = then {
remapRange(it, oldRange, newRange) remapRange(it, oldRange, newRange)
} }
fun remap(newRange: FloatRange) = then { fun remap(newRange: ClosedFloatingPointRange<Double>) = then {
remapRange(it, range(0F, 1F), newRange) remapRange(it, (0.0)..(1.0), newRange)
} }
inline fun ifNonZero(block: NoiseValue.() -> Unit) { inline fun ifNonZero(block: NoiseValue.() -> Unit) {

View File

@@ -2,9 +2,9 @@ package chylex.hee.game.world.generation.ore
import chylex.hee.game.world.generation.IBlockPlacer import chylex.hee.game.world.generation.IBlockPlacer
import chylex.hee.game.world.generation.structure.world.SegmentedWorld import chylex.hee.game.world.generation.structure.world.SegmentedWorld
import chylex.hee.system.random.nextInt
import chylex.hee.util.math.BoundingBox import chylex.hee.util.math.BoundingBox
import chylex.hee.util.math.Pos import chylex.hee.util.math.Pos
import chylex.hee.util.random.nextInt
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import java.util.Random import java.util.Random

View File

@@ -4,8 +4,8 @@ import chylex.hee.game.world.generation.IBlockPlacer
import chylex.hee.game.world.generation.ore.IOreTechnique import chylex.hee.game.world.generation.ore.IOreTechnique
import chylex.hee.game.world.generation.structure.world.SegmentedWorld import chylex.hee.game.world.generation.structure.world.SegmentedWorld
import chylex.hee.game.world.util.Facing6 import chylex.hee.game.world.util.Facing6
import chylex.hee.util.random.nextInt import chylex.hee.system.random.nextInt
import chylex.hee.util.random.nextItem import chylex.hee.system.random.nextItem
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import java.util.Random import java.util.Random
import kotlin.math.abs import kotlin.math.abs

View File

@@ -3,10 +3,10 @@ package chylex.hee.game.world.generation.ore.impl
import chylex.hee.game.world.generation.IBlockPlacer import chylex.hee.game.world.generation.IBlockPlacer
import chylex.hee.game.world.generation.ore.IOreTechnique import chylex.hee.game.world.generation.ore.IOreTechnique
import chylex.hee.game.world.generation.structure.world.SegmentedWorld import chylex.hee.game.world.generation.structure.world.SegmentedWorld
import chylex.hee.system.random.nextVector
import chylex.hee.util.math.Pos import chylex.hee.util.math.Pos
import chylex.hee.util.math.ceilToInt import chylex.hee.util.math.ceilToInt
import chylex.hee.util.math.center import chylex.hee.util.math.center
import chylex.hee.util.random.nextVector
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import java.util.Random import java.util.Random
import kotlin.math.pow import kotlin.math.pow

View File

@@ -4,7 +4,7 @@ import chylex.hee.game.world.generation.structure.piece.StructureBuild.AddMode
import chylex.hee.game.world.generation.structure.piece.StructureBuild.PositionedPiece import chylex.hee.game.world.generation.structure.piece.StructureBuild.PositionedPiece
import chylex.hee.game.world.util.Rotation4 import chylex.hee.game.world.util.Rotation4
import chylex.hee.game.world.util.Transform import chylex.hee.game.world.util.Transform
import chylex.hee.util.random.nextItem import chylex.hee.system.random.nextItem
import java.util.Random import java.util.Random
interface IStructureBuilder<T : IStructureBuild> { interface IStructureBuilder<T : IStructureBuild> {

View File

@@ -7,6 +7,7 @@ import chylex.hee.game.world.generation.structure.piece.IStructurePieceConnectio
import chylex.hee.game.world.generation.structure.piece.StructureBuild.AddMode.APPEND import chylex.hee.game.world.generation.structure.piece.StructureBuild.AddMode.APPEND
import chylex.hee.game.world.generation.structure.piece.StructureBuild.AddMode.MERGE import chylex.hee.game.world.generation.structure.piece.StructureBuild.AddMode.MERGE
import chylex.hee.game.world.generation.structure.world.OffsetStructureWorld import chylex.hee.game.world.generation.structure.world.OffsetStructureWorld
import chylex.hee.system.Debug
import chylex.hee.util.math.Size import chylex.hee.util.math.Size
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
@@ -82,7 +83,7 @@ class StructureBuild<T : StructurePiece<*>.MutableInstance>(val size: Size) {
* [MERGE] mode allows intersection with [targetPiece] but no other pieces. * [MERGE] mode allows intersection with [targetPiece] but no other pieces.
*/ */
fun addPiece(newPiece: T, newPieceConnection: IStructurePieceConnection, targetPiece: PositionedPiece<T>, targetPieceConnection: IStructurePieceConnection, mode: AddMode = APPEND): PositionedPiece<T>? { fun addPiece(newPiece: T, newPieceConnection: IStructurePieceConnection, targetPiece: PositionedPiece<T>, targetPieceConnection: IStructurePieceConnection, mode: AddMode = APPEND): PositionedPiece<T>? {
if (HEE.debug && !pieces.contains(targetPiece)) { if (Debug.enabled && !pieces.contains(targetPiece)) {
HEE.log.error("[StructureBuild] attempted to connect to a piece that is not present in the structure") HEE.log.error("[StructureBuild] attempted to connect to a piece that is not present in the structure")
} }

View File

@@ -6,67 +6,59 @@ import chylex.hee.game.world.generation.structure.IStructureWorld
import chylex.hee.game.world.generation.structure.world.segments.ISegment import chylex.hee.game.world.generation.structure.world.segments.ISegment
import chylex.hee.game.world.generation.structure.world.segments.ISegment.Companion.index import chylex.hee.game.world.generation.structure.world.segments.ISegment.Companion.index
import chylex.hee.game.world.util.Transform import chylex.hee.game.world.util.Transform
import chylex.hee.system.Debug
import chylex.hee.util.math.Pos import chylex.hee.util.math.Pos
import chylex.hee.util.math.Size import chylex.hee.util.math.Size
import chylex.hee.util.math.ceilToInt import chylex.hee.util.math.ceilToInt
import chylex.hee.util.math.component1
import chylex.hee.util.math.component2
import chylex.hee.util.math.component3
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.block.Blocks import net.minecraft.block.Blocks
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
import java.util.Random import java.util.Random
open class SegmentedWorld(override val rand: Random, val worldSize: Size, segmentSize: Size, defaultSegmentFactory: (Size) -> ISegment) : IStructureWorld { open class SegmentedWorld(override val rand: Random, val worldSize: Size, private val segmentSize: Size, defaultSegmentFactory: (Size) -> ISegment) : IStructureWorld {
private val segmentSizeX = segmentSize.x
private val segmentSizeY = segmentSize.y
private val segmentSizeZ = segmentSize.z
private val segmentCounts = Size( private val segmentCounts = Size(
(worldSize.x.toFloat() / segmentSizeX).ceilToInt(), (worldSize.x.toFloat() / segmentSize.x).ceilToInt(),
(worldSize.y.toFloat() / segmentSizeY).ceilToInt(), (worldSize.y.toFloat() / segmentSize.y).ceilToInt(),
(worldSize.z.toFloat() / segmentSizeZ).ceilToInt() (worldSize.z.toFloat() / segmentSize.z).ceilToInt()
) )
private val segments = Array(segmentCounts.x * segmentCounts.y * segmentCounts.z) { defaultSegmentFactory(segmentSize) } private val segments = Array(segmentCounts.x * segmentCounts.y * segmentCounts.z) { defaultSegmentFactory(segmentSize) }
private val triggers = mutableListOf<Pair<BlockPos, IStructureTrigger>>() private val triggers = mutableListOf<Pair<BlockPos, IStructureTrigger>>()
private fun getSegmentIndex(pos: BlockPos): Int { private fun mapPos(pos: BlockPos): Pair<Int, BlockPos>? {
return index(pos.x / segmentSizeX, pos.y / segmentSizeY, pos.z / segmentSizeZ, segmentCounts) if (!isInside(pos)) {
} HEE.log.warn("[SegmentedWorld] attempted to access position outside bounds: $pos is outside $worldSize")
private fun getSegmentOffset(pos: BlockPos): BlockPos { if (Debug.enabled) {
return Pos(pos.x % segmentSizeX, pos.y % segmentSizeY, pos.z % segmentSizeZ) Thread.dumpStack()
}
return null
}
val (x, y, z) = pos
val (sizeX, sizeY, sizeZ) = segmentSize
val segmentIndex = index(x / sizeX, y / sizeY, z / sizeZ, segmentCounts)
val segmentOffset = Pos(x % sizeX, y % sizeY, z % sizeZ)
return Pair(segmentIndex, segmentOffset)
} }
fun isInside(pos: BlockPos): Boolean { fun isInside(pos: BlockPos): Boolean {
return pos.x in 0..worldSize.maxX && pos.y in 0..worldSize.maxY && pos.z in 0..worldSize.maxZ return pos.x in 0..worldSize.maxX && pos.y in 0..worldSize.maxY && pos.z in 0..worldSize.maxZ
} }
private fun warnNotInside(pos: BlockPos) {
HEE.log.warn("[SegmentedWorld] attempted to access position outside bounds: $pos is outside $worldSize")
if (HEE.debug) {
Thread.dumpStack()
}
}
override fun getState(pos: BlockPos): BlockState { override fun getState(pos: BlockPos): BlockState {
if (!isInside(pos)) { val (segmentIndex, segmentOffset) = mapPos(pos) ?: return Blocks.AIR.defaultState
warnNotInside(pos)
return Blocks.AIR.defaultState
}
val segmentIndex = getSegmentIndex(pos)
val segmentOffset = getSegmentOffset(pos)
return segments[segmentIndex].getState(segmentOffset) return segments[segmentIndex].getState(segmentOffset)
} }
override fun setState(pos: BlockPos, state: BlockState) { override fun setState(pos: BlockPos, state: BlockState) {
if (!isInside(pos)) { val (segmentIndex, segmentOffset) = mapPos(pos) ?: return
warnNotInside(pos)
return
}
val segmentIndex = getSegmentIndex(pos)
val segmentOffset = getSegmentOffset(pos)
segments[segmentIndex] = segments[segmentIndex].withState(segmentOffset, state) segments[segmentIndex] = segments[segmentIndex].withState(segmentOffset, state)
} }

View File

@@ -16,9 +16,10 @@ class SegmentMultiState(private val size: Size, private val fillState: BlockStat
constructor(size: Size, block: Block) : this(size, block.defaultState) constructor(size: Size, block: Block) : this(size, block.defaultState)
/** /**
* The threshold power was determined by careful experimentation and profiling. * The threshold power was determined using the WorldSegmentProfiling test.
* The segment gets converted when the amount of memory used by the [exceptions] map reaches roughly half of the memory used by the [SegmentFull] array.
*/ */
private val threshold = (size.x * size.y * size.z).toDouble().pow(0.69).floorToInt() private val threshold = (size.x * size.y * size.z).toDouble().pow(0.825).floorToInt()
private val exceptions = Long2ObjectOpenHashMap<BlockState>(threshold, 0.75F).apply { defaultReturnValue(fillState) } private val exceptions = Long2ObjectOpenHashMap<BlockState>(threshold, 0.75F).apply { defaultReturnValue(fillState) }
override fun getState(pos: BlockPos): BlockState { override fun getState(pos: BlockPos): BlockState {

View File

@@ -0,0 +1,206 @@
package chylex.hee.system
import chylex.hee.client.render.RenderStateBuilder
import chylex.hee.client.render.RenderStateBuilder.Companion.LAYERING_OFFSET_Z
import chylex.hee.client.render.RenderStateBuilder.Companion.MASK_COLOR
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.Environment
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.forge.Side
import chylex.hee.util.forge.Sided
import chylex.hee.util.forge.SubscribeEvent
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.client.event.GuiOpenEvent
import net.minecraftforge.client.event.InputEvent.KeyInputEvent
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.event.entity.player.PlayerInteractEvent.LeftClickBlock
import net.minecraftforge.event.entity.player.PlayerInteractEvent.RightClickBlock
import net.minecraftforge.event.world.BlockEvent.BreakEvent
import org.apache.commons.lang3.SystemUtils
import org.lwjgl.glfw.GLFW
import org.lwjgl.opengl.GL11
import java.io.File
import java.lang.management.ManagementFactory
object Debug {
@JvmField
val enabled = System.getProperty("hee.debug") != null
@Sided(Side.CLIENT)
fun initializeClient() {
if (enabled) {
MinecraftForge.EVENT_BUS.register(object : Any() {
@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")
}
}
}
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)
}
}
}
}
private val RENDER_TYPE_LINE = with(RenderStateBuilder()) {
line(2.25)
blend(SF_SRC_ALPHA, DF_ONE, SF_ONE_MINUS_SRC_ALPHA, DF_ZERO)
layering(LAYERING_OFFSET_Z)
mask(MASK_COLOR)
buildType("hee:debug_line", DefaultVertexFormats.POSITION_COLOR, GL11.GL_LINES, bufferSize = 256)
}
@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
}
}
})
if (canExecutePowershell("maximize.ps1")) {
MinecraftForge.EVENT_BUS.register(object : Any() {
@SubscribeEvent
fun onGuiOpen(@Suppress("UNUSED_PARAMETER") e: GuiOpenEvent) {
val pid = ManagementFactory.getRuntimeMXBean().name.split("@")[0]
ProcessBuilder("powershell.exe", "-ExecutionPolicy", "Unrestricted", "-File", "maximize.ps1", pid).start()
MinecraftForge.EVENT_BUS.unregister(this)
}
})
}
}
}
fun setClipboardContents(file: File) {
if (canExecutePowershell("filecopy.ps1")) {
ProcessBuilder("powershell.exe", "-ExecutionPolicy", "Unrestricted", "-Sta", "-File", "filecopy.ps1", file.absolutePath).start()
}
}
private fun canExecutePowershell(scriptName: String): Boolean {
return SystemUtils.IS_OS_WINDOWS && Environment.side == Side.CLIENT && File(scriptName).exists()
}
}

View File

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

View File

@@ -19,7 +19,7 @@ object MinecraftForgeEventBus {
} }
for (listener in item.javaClass.methods.filter { !Modifier.isStatic(it.modifiers) && it.isAnnotationPresent(SubscribeEvent::class.java) }) { for (listener in item.javaClass.methods.filter { !Modifier.isStatic(it.modifiers) && it.isAnnotationPresent(SubscribeEvent::class.java) }) {
if (HEE.debug) { if (Debug.enabled) {
HEE.log.info("[MinecraftForgeEventBus] registering ${listener.parameterTypes.firstOrNull()?.name?.substringAfterLast('.')} for ${item.javaClass.simpleName}") HEE.log.info("[MinecraftForgeEventBus] registering ${listener.parameterTypes.firstOrNull()?.name?.substringAfterLast('.')} for ${item.javaClass.simpleName}")
} }

View File

@@ -15,8 +15,8 @@ fun <C, T : ArgumentBuilder<CommandSource, T>> ArgumentBuilder<CommandSource, T>
} }
inline fun simpleCommand(code: () -> Unit): Int { inline fun simpleCommand(code: () -> Unit): Int {
code() code();
return 1 return 1;
} }
inline fun <reified T : Enum<T>> CommandContext<CommandSource>.getEnum(name: String): T { inline fun <reified T : Enum<T>> CommandContext<CommandSource>.getEnum(name: String): T {

View File

@@ -1,6 +1,6 @@
package chylex.hee.game.world.util package chylex.hee.game.world.util
import chylex.hee.util.random.nextItem import chylex.hee.system.random.nextItem
import com.google.common.collect.Collections2 import com.google.common.collect.Collections2
import net.minecraft.util.Direction import net.minecraft.util.Direction
import net.minecraft.util.math.vector.Vector3d import net.minecraft.util.math.vector.Vector3d

View File

@@ -1,6 +1,6 @@
package chylex.hee.game.world.util package chylex.hee.game.world.util
import chylex.hee.util.random.nextItem import chylex.hee.system.random.nextItem
import com.google.common.collect.Collections2 import com.google.common.collect.Collections2
import net.minecraft.util.Rotation import net.minecraft.util.Rotation
import java.util.Random import java.util.Random

View File

@@ -1,6 +1,6 @@
package chylex.hee.util.collection package chylex.hee.util.collection
import chylex.hee.util.random.nextLong import chylex.hee.system.random.nextLong
import java.util.Random import java.util.Random
class WeightedList<T>(val items: List<Pair<Int, T>>) { class WeightedList<T>(val items: List<Pair<Int, T>>) {

View File

@@ -48,15 +48,15 @@ fun lerp(from: Double, to: Double, progress: Double): Double {
/** /**
* Maps a range of values in [from] range to values in [to] range using linear interpolation. * Maps a range of values in [from] range to values in [to] range using linear interpolation.
*/ */
fun remapRange(value: Float, from: FloatRange, to: FloatRange): Float { fun remapRange(value: Float, from: ClosedFloatingPointRange<Float>, to: ClosedFloatingPointRange<Float>): Float {
val remappedBetween0And1 = (value - from.start) / (from.end - from.start) val remappedBetween0And1 = (value - from.start) / (from.endInclusive - from.start)
return to.start + remappedBetween0And1 * (to.end - to.start) return to.start + remappedBetween0And1 * (to.endInclusive - to.start)
} }
/** /**
* Maps a range of values in [from] range to values in [to] range using linear interpolation. * Maps a range of values in [from] range to values in [to] range using linear interpolation.
*/ */
fun remapRange(value: Double, from: FloatRange, to: FloatRange): Double { fun remapRange(value: Double, from: ClosedFloatingPointRange<Double>, to: ClosedFloatingPointRange<Double>): Double {
val remappedBetween0And1 = (value - from.start) / (from.end - from.start) val remappedBetween0And1 = (value - from.start) / (from.endInclusive - from.start)
return to.start + remappedBetween0And1 * (to.end - to.start) return to.start + remappedBetween0And1 * (to.endInclusive - to.start)
} }

View File

@@ -1,14 +0,0 @@
package chylex.hee.util.math
@JvmInline
value class FloatRange(private val combined: Long) {
constructor(start: Float, end: Float) : this((start.toRawBits() shlong 32) or (end.toRawBits().toLong() and 0xFFFF_FFFFL))
val start
get() = Float.fromBits((combined ushr 32).toInt())
val end
get() = Float.fromBits((combined and 0xFFFF_FFFFL).toInt())
}
fun range(start: Float, end: Float) = FloatRange(start, end)

View File

@@ -1,6 +1,5 @@
package chylex.hee.util.random package chylex.hee.util.random
import chylex.hee.util.math.range
import chylex.hee.util.math.remapRange import chylex.hee.util.math.remapRange
import java.util.Random import java.util.Random
import kotlin.math.pow import kotlin.math.pow
@@ -30,7 +29,7 @@ abstract class RandomDouble private constructor(val min: Double, val max: Double
fun Exp(min: Double, max: Double, exp: Double) = object : RandomDouble(min, max) { fun Exp(min: Double, max: Double, exp: Double) = object : RandomDouble(min, max) {
override fun invoke(rand: Random): Double { override fun invoke(rand: Random): Double {
return remapRange(rand.nextDouble().pow(exp), range(0F, 1F), range(min.toFloat(), max.toFloat())) return remapRange(rand.nextDouble().pow(exp), (0.0)..(1.0), min..max)
} }
} }
} }

View File

@@ -1,4 +1,4 @@
package chylex.hee.util.random package chylex.hee.system.random
import chylex.hee.util.math.Vec import chylex.hee.util.math.Vec
import chylex.hee.util.math.Vec3 import chylex.hee.util.math.Vec3

View File

@@ -1,5 +1,7 @@
package chylex.hee.util.random package chylex.hee.util.random
import chylex.hee.system.random.nextBiasedFloat
import chylex.hee.system.random.nextInt
import chylex.hee.util.math.floorToInt import chylex.hee.util.math.floorToInt
import java.util.Random import java.util.Random

View File

@@ -1,9 +1,7 @@
include ":util"
include ":system" include ":system"
include ":debug" include ":util"
include ":datagen" include ":datagen"
project(":util").projectDir = file("./modules/util")
project(":system").projectDir = file("./modules/system") project(":system").projectDir = file("./modules/system")
project(":debug").projectDir = file("./modules/debug") project(":util").projectDir = file("./modules/util")
project(":datagen").projectDir = file("./data") project(":datagen").projectDir = file("./data")

View File

@@ -19,6 +19,7 @@ import chylex.hee.init.ModPackets
import chylex.hee.init.ModPotions import chylex.hee.init.ModPotions
import chylex.hee.init.ModTileEntities import chylex.hee.init.ModTileEntities
import chylex.hee.network.NetworkManager import chylex.hee.network.NetworkManager
import chylex.hee.system.Debug
import chylex.hee.util.forge.Side import chylex.hee.util.forge.Side
import chylex.hee.util.forge.SubscribeAllEvents import chylex.hee.util.forge.SubscribeAllEvents
import chylex.hee.util.forge.SubscribeEvent import chylex.hee.util.forge.SubscribeEvent
@@ -28,6 +29,7 @@ import net.minecraftforge.fml.DistExecutor.SafeRunnable
import net.minecraftforge.fml.ModLoadingContext import net.minecraftforge.fml.ModLoadingContext
import net.minecraftforge.fml.common.Mod import net.minecraftforge.fml.common.Mod
import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus.MOD import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus.MOD
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent
import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent import net.minecraftforge.fml.event.lifecycle.FMLLoadCompleteEvent
@@ -39,10 +41,6 @@ object Mod {
HEE.version = activeContainer.modInfo.version.toString() HEE.version = activeContainer.modInfo.version.toString()
} }
try {
Class.forName("chylex.hee.debug.Debug")
} catch (e: ClassNotFoundException) {}
@Suppress("ConvertLambdaToReference") @Suppress("ConvertLambdaToReference")
DistExecutor.safeRunWhenOn(Side.CLIENT) { DistExecutor.safeRunWhenOn(Side.CLIENT) {
SafeRunnable { VanillaResourceOverrides.register() } SafeRunnable { VanillaResourceOverrides.register() }
@@ -53,6 +51,11 @@ object Mod {
ModCreativeTabs ModCreativeTabs
} }
@SubscribeEvent
fun onClientSetup(@Suppress("UNUSED_PARAMETER") e: FMLClientSetupEvent) {
Debug.initializeClient()
}
@SubscribeEvent @SubscribeEvent
fun onCommonSetup(@Suppress("UNUSED_PARAMETER") e: FMLCommonSetupEvent) { fun onCommonSetup(@Suppress("UNUSED_PARAMETER") e: FMLCommonSetupEvent) {
NetworkManager.initialize(ModPackets.ALL) NetworkManager.initialize(ModPackets.ALL)
@@ -83,7 +86,7 @@ object Mod {
for (block in BlockShulkerBoxOverride.ALL_BLOCKS) { for (block in BlockShulkerBoxOverride.ALL_BLOCKS) {
crashIfFalse(block.javaClass === BlockShulkerBoxOverride::class.java, "invalid Shulker Box block: ${block.javaClass}") crashIfFalse(block.javaClass === BlockShulkerBoxOverride::class.java, "invalid Shulker Box block: ${block.javaClass}")
crashIfFalse(ItemShulkerBoxOverride.isItemValid(block.asItem()), "invalid Shulker Box item: ${block.asItem().javaClass}") crashIfFalse(block.asItem().javaClass === ItemShulkerBoxOverride::class.java, "invalid Shulker Box item: ${block.asItem().javaClass}")
} }
} }

View File

@@ -11,13 +11,13 @@ import chylex.hee.game.Resource
import chylex.hee.game.block.BlockAbstractPortal import chylex.hee.game.block.BlockAbstractPortal
import chylex.hee.game.block.entity.TileEntityEnergyCluster import chylex.hee.game.block.entity.TileEntityEnergyCluster
import chylex.hee.game.block.properties.Materials import chylex.hee.game.block.properties.Materials
import chylex.hee.game.mechanics.energy.IClusterOracleItem
import chylex.hee.game.mechanics.energy.IEnergyQuantity import chylex.hee.game.mechanics.energy.IEnergyQuantity
import chylex.hee.game.mechanics.energy.IEnergyQuantity.Companion.MAX_POSSIBLE_VALUE import chylex.hee.game.mechanics.energy.IEnergyQuantity.Companion.MAX_POSSIBLE_VALUE
import chylex.hee.game.mechanics.energy.IEnergyQuantity.Companion.displayString import chylex.hee.game.mechanics.energy.IEnergyQuantity.Companion.displayString
import chylex.hee.game.world.util.getBlock import chylex.hee.game.world.util.getBlock
import chylex.hee.game.world.util.getTile import chylex.hee.game.world.util.getTile
import chylex.hee.init.ModBlocks import chylex.hee.init.ModBlocks
import chylex.hee.init.ModItems
import chylex.hee.util.color.IntColor import chylex.hee.util.color.IntColor
import chylex.hee.util.color.RGB import chylex.hee.util.color.RGB
import chylex.hee.util.color.RGBA import chylex.hee.util.color.RGBA
@@ -118,7 +118,7 @@ object OverlayRenderer {
quantity.displayString quantity.displayString
} }
val isIgnored = MC.player?.let { player -> IClusterOracleItem.isPositionIgnored(player, it.pos) } == true val isIgnored = MC.player?.let { player -> ModItems.ENERGY_ORACLE.isClusterIgnored(player, it.pos) } == true
val firstLine = if (isIgnored) -1 else 0 val firstLine = if (isIgnored) -1 else 0
val health = it.currentHealth val health = it.currentHealth

View File

@@ -17,6 +17,7 @@ import chylex.hee.game.territory.TerritoryType
import chylex.hee.game.territory.TerritoryVoid import chylex.hee.game.territory.TerritoryVoid
import chylex.hee.game.territory.system.properties.TerritoryEnvironment import chylex.hee.game.territory.system.properties.TerritoryEnvironment
import chylex.hee.game.world.isInEndDimension import chylex.hee.game.world.isInEndDimension
import chylex.hee.system.Debug
import chylex.hee.util.color.IntColor import chylex.hee.util.color.IntColor
import chylex.hee.util.color.RGB import chylex.hee.util.color.RGB
import chylex.hee.util.forge.EventPriority import chylex.hee.util.forge.EventPriority
@@ -25,7 +26,6 @@ import chylex.hee.util.forge.SubscribeAllEvents
import chylex.hee.util.forge.SubscribeEvent import chylex.hee.util.forge.SubscribeEvent
import chylex.hee.util.math.LerpedFloat import chylex.hee.util.math.LerpedFloat
import chylex.hee.util.math.floorToInt import chylex.hee.util.math.floorToInt
import chylex.hee.util.math.range
import chylex.hee.util.math.remapRange import chylex.hee.util.math.remapRange
import chylex.hee.util.math.scale import chylex.hee.util.math.scale
import com.mojang.blaze3d.matrix.MatrixStack import com.mojang.blaze3d.matrix.MatrixStack
@@ -36,6 +36,7 @@ import net.minecraft.entity.player.PlayerEntity
import net.minecraft.util.math.vector.Vector3f import net.minecraft.util.math.vector.Vector3f
import net.minecraftforge.client.event.EntityViewRenderEvent.RenderFogEvent import net.minecraftforge.client.event.EntityViewRenderEvent.RenderFogEvent
import net.minecraftforge.client.event.RenderGameOverlayEvent import net.minecraftforge.client.event.RenderGameOverlayEvent
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.event.TickEvent.ClientTickEvent import net.minecraftforge.event.TickEvent.ClientTickEvent
import net.minecraftforge.event.TickEvent.Phase import net.minecraftforge.event.TickEvent.Phase
import org.lwjgl.opengl.GL11.GL_GREATER import org.lwjgl.opengl.GL11.GL_GREATER
@@ -118,7 +119,7 @@ object TerritoryRenderer {
// Fog rendering // Fog rendering
private val currentFogDensityMp private val currentFogDensityMp
get() = 1F + (9F * remapRange(currentVoidFactor, range(-0.5F, 1F), range(0F, 1F)).coerceIn(0F, 1F).pow(1.5F)) get() = 1F + (9F * remapRange(currentVoidFactor, (-0.5F)..(1F), (0F)..(1F)).coerceIn(0F, 1F).pow(1.5F))
private val currentRenderDistanceMp private val currentRenderDistanceMp
get() = MC.settings.renderDistanceChunks.let { if (it > 12) 0F else (1F - (it / 16.5F)).pow((it - 1) * 0.25F) } get() = MC.settings.renderDistanceChunks.let { if (it > 12) 0F else (1F - (it / 16.5F)).pow((it - 1) * 0.25F) }
@@ -148,7 +149,7 @@ object TerritoryRenderer {
get() = Void.voidFactor.get(MC.partialTicks) get() = Void.voidFactor.get(MC.partialTicks)
val currentSkyAlpha val currentSkyAlpha
get() = remapRange(currentVoidFactor, range(-1F, 0.5F), range(1F, 0F)).coerceIn(0F, 1F) get() = remapRange(currentVoidFactor, (-1F)..(0.5F), (1F)..(0F)).coerceIn(0F, 1F)
private object Void { private object Void {
private val VOID_PARTICLE = ParticleSpawnerCustom( private val VOID_PARTICLE = ParticleSpawnerCustom(
@@ -158,6 +159,12 @@ object TerritoryRenderer {
val voidFactor = LerpedFloat(TerritoryVoid.OUTSIDE_VOID_FACTOR) val voidFactor = LerpedFloat(TerritoryVoid.OUTSIDE_VOID_FACTOR)
init {
if (Debug.enabled) {
MinecraftForge.EVENT_BUS.register(this)
}
}
fun tick(player: PlayerEntity) { fun tick(player: PlayerEntity) {
val factor = TerritoryVoid.getVoidFactor(player).also(voidFactor::update) val factor = TerritoryVoid.getVoidFactor(player).also(voidFactor::update)
@@ -179,6 +186,16 @@ object TerritoryRenderer {
fun reset() { fun reset() {
voidFactor.updateImmediately(TerritoryVoid.OUTSIDE_VOID_FACTOR) voidFactor.updateImmediately(TerritoryVoid.OUTSIDE_VOID_FACTOR)
} }
@SubscribeEvent
fun onRenderGameOverlayText(e: RenderGameOverlayEvent.Text) {
if (MC.settings.showDebugInfo && MC.player?.isInEndDimension == true) {
with(e.left) {
add("")
add("End Void Factor: ${"%.3f".format(voidFactor.currentValue)}")
}
}
}
} }
// Text rendering // Text rendering

View File

@@ -17,10 +17,10 @@ import chylex.hee.game.Resource
import chylex.hee.game.block.BlockTablePedestal import chylex.hee.game.block.BlockTablePedestal
import chylex.hee.game.block.entity.TileEntityTablePedestal import chylex.hee.game.block.entity.TileEntityTablePedestal
import chylex.hee.game.item.util.size import chylex.hee.game.item.util.size
import chylex.hee.system.random.nextFloat
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 chylex.hee.util.math.toRadians import chylex.hee.util.math.toRadians
import chylex.hee.util.random.nextFloat
import com.mojang.blaze3d.matrix.MatrixStack import com.mojang.blaze3d.matrix.MatrixStack
import net.minecraft.client.renderer.IRenderTypeBuffer import net.minecraft.client.renderer.IRenderTypeBuffer
import net.minecraft.client.renderer.ItemRenderer import net.minecraft.client.renderer.ItemRenderer

View File

@@ -9,9 +9,9 @@ import chylex.hee.client.render.RenderStateBuilder.Companion.OVERLAY_DISABLED
import chylex.hee.client.render.util.DF_ONE_MINUS_SRC_ALPHA import chylex.hee.client.render.util.DF_ONE_MINUS_SRC_ALPHA
import chylex.hee.client.render.util.SF_SRC_ALPHA import chylex.hee.client.render.util.SF_SRC_ALPHA
import chylex.hee.game.entity.living.EntityMobAbstractEnderman import chylex.hee.game.entity.living.EntityMobAbstractEnderman
import chylex.hee.system.random.nextFloat
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 chylex.hee.util.random.nextFloat
import com.mojang.blaze3d.matrix.MatrixStack import com.mojang.blaze3d.matrix.MatrixStack
import com.mojang.blaze3d.vertex.IVertexBuilder import com.mojang.blaze3d.vertex.IVertexBuilder
import net.minecraft.client.renderer.IRenderTypeBuffer import net.minecraft.client.renderer.IRenderTypeBuffer

View File

@@ -15,9 +15,9 @@ import chylex.hee.game.Resource
import chylex.hee.game.entity.living.EntityMobBlobby import chylex.hee.game.entity.living.EntityMobBlobby
import chylex.hee.game.item.util.isNotEmpty import chylex.hee.game.item.util.isNotEmpty
import chylex.hee.game.world.util.Facing6 import chylex.hee.game.world.util.Facing6
import chylex.hee.system.random.nextFloat
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 chylex.hee.util.random.nextFloat
import com.mojang.blaze3d.matrix.MatrixStack import com.mojang.blaze3d.matrix.MatrixStack
import com.mojang.blaze3d.vertex.IVertexBuilder import com.mojang.blaze3d.vertex.IVertexBuilder
import net.minecraft.block.AbstractChestBlock import net.minecraft.block.AbstractChestBlock

View File

@@ -1,9 +1,9 @@
package chylex.hee.client.sound package chylex.hee.client.sound
import chylex.hee.game.entity.projectile.EntityProjectileSpatialDash import chylex.hee.game.entity.projectile.EntityProjectileSpatialDash
import chylex.hee.system.random.nextFloat
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 chylex.hee.util.random.nextFloat
import net.minecraft.client.audio.TickableSound import net.minecraft.client.audio.TickableSound
import net.minecraft.util.SoundCategory import net.minecraft.util.SoundCategory
import net.minecraft.util.SoundEvents import net.minecraft.util.SoundEvents

View File

@@ -2,9 +2,9 @@ package chylex.hee.client.sound
import chylex.hee.game.entity.living.EntityMobUndread import chylex.hee.game.entity.living.EntityMobUndread
import chylex.hee.init.ModSounds import chylex.hee.init.ModSounds
import chylex.hee.system.random.nextFloat
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 chylex.hee.util.random.nextFloat
import net.minecraft.client.audio.ISound.AttenuationType import net.minecraft.client.audio.ISound.AttenuationType
import net.minecraft.client.audio.TickableSound import net.minecraft.client.audio.TickableSound
import net.minecraft.util.SoundCategory import net.minecraft.util.SoundCategory

View File

@@ -14,7 +14,7 @@ class BlockCauldronWithDragonsBreath(builder: BlockBuilder) : BlockAbstractCauld
return null return null
} }
override fun createFilledBottle(): ItemStack { override fun createFilledBottle(): ItemStack? {
return ItemStack(Items.DRAGON_BREATH) return ItemStack(Items.DRAGON_BREATH)
} }
} }

View File

@@ -35,10 +35,10 @@ import chylex.hee.game.world.util.getTile
import chylex.hee.game.world.util.removeBlock import chylex.hee.game.world.util.removeBlock
import chylex.hee.game.world.util.setState import chylex.hee.game.world.util.setState
import chylex.hee.init.ModBlocks import chylex.hee.init.ModBlocks
import chylex.hee.system.random.nextInt
import chylex.hee.system.random.removeItem
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 chylex.hee.util.random.nextInt
import chylex.hee.util.random.removeItem
import net.minecraft.block.Block import net.minecraft.block.Block
import net.minecraft.block.BlockRenderType.INVISIBLE import net.minecraft.block.BlockRenderType.INVISIBLE
import net.minecraft.block.BlockState import net.minecraft.block.BlockState

View File

@@ -18,9 +18,9 @@ import chylex.hee.game.world.util.removeBlock
import chylex.hee.game.world.util.setState import chylex.hee.game.world.util.setState
import chylex.hee.init.ModSounds import chylex.hee.init.ModSounds
import chylex.hee.network.client.PacketClientFX import chylex.hee.network.client.PacketClientFX
import chylex.hee.system.random.nextInt
import chylex.hee.util.math.Vec3 import chylex.hee.util.math.Vec3
import chylex.hee.util.math.center import chylex.hee.util.math.center
import chylex.hee.util.random.nextInt
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.block.Blocks import net.minecraft.block.Blocks
import net.minecraft.block.DragonEggBlock import net.minecraft.block.DragonEggBlock

View File

@@ -11,9 +11,9 @@ import chylex.hee.game.particle.spawner.properties.IOffset.InBox
import chylex.hee.game.particle.spawner.properties.IShape.Point import chylex.hee.game.particle.spawner.properties.IShape.Point
import chylex.hee.game.world.util.getState import chylex.hee.game.world.util.getState
import chylex.hee.game.world.util.isFullBlock import chylex.hee.game.world.util.isFullBlock
import chylex.hee.system.random.nextInt
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 chylex.hee.util.random.nextInt
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.client.particle.ParticleManager import net.minecraft.client.particle.ParticleManager
import net.minecraft.entity.player.PlayerEntity import net.minecraft.entity.player.PlayerEntity

View File

@@ -13,9 +13,9 @@ import chylex.hee.game.world.util.isTopSolid
import chylex.hee.game.world.util.setAir import chylex.hee.game.world.util.setAir
import chylex.hee.game.world.util.setBlock import chylex.hee.game.world.util.setBlock
import chylex.hee.init.ModBlocks import chylex.hee.init.ModBlocks
import chylex.hee.system.random.nextInt
import chylex.hee.util.math.Pos import chylex.hee.util.math.Pos
import chylex.hee.util.math.floorToInt import chylex.hee.util.math.floorToInt
import chylex.hee.util.random.nextInt
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.enchantment.EnchantmentHelper import net.minecraft.enchantment.EnchantmentHelper
import net.minecraft.enchantment.Enchantments import net.minecraft.enchantment.Enchantments

View File

@@ -2,7 +2,7 @@ package chylex.hee.game.block
import chylex.hee.game.block.properties.BlockBuilder import chylex.hee.game.block.properties.BlockBuilder
import chylex.hee.game.block.properties.BlockDrop import chylex.hee.game.block.properties.BlockDrop
import chylex.hee.util.random.nextInt import chylex.hee.system.random.nextInt
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.IWorldReader import net.minecraft.world.IWorldReader

View File

@@ -14,13 +14,13 @@ import chylex.hee.game.potion.PurityEffect.MIN_DURATION
import chylex.hee.game.potion.brewing.PotionBrewing.INFINITE_DURATION_THRESHOLD import chylex.hee.game.potion.brewing.PotionBrewing.INFINITE_DURATION_THRESHOLD
import chylex.hee.network.client.PacketClientFX import chylex.hee.network.client.PacketClientFX
import chylex.hee.network.client.PacketClientPotionDuration import chylex.hee.network.client.PacketClientPotionDuration
import chylex.hee.system.random.nextInt
import chylex.hee.system.random.nextItemOrNull
import chylex.hee.util.color.RGB 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 chylex.hee.util.math.floorToInt import chylex.hee.util.math.floorToInt
import chylex.hee.util.math.scaleXZ import chylex.hee.util.math.scaleXZ
import chylex.hee.util.random.nextInt
import chylex.hee.util.random.nextItemOrNull
import net.minecraft.block.BlockState import net.minecraft.block.BlockState
import net.minecraft.entity.Entity import net.minecraft.entity.Entity
import net.minecraft.entity.LivingEntity import net.minecraft.entity.LivingEntity

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