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

4 Commits

367 changed files with 4852 additions and 4593 deletions

1
.idea/gradle.xml generated
View File

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

View File

@@ -16,7 +16,7 @@ buildscript {
ext {
forge_gradle_version = "4.1.+"
mixin_gradle_version = "0.7-SNAPSHOT"
kotlin_version = "1.7.0"
kotlin_version = "1.5.20"
}
repositories {
@@ -60,7 +60,6 @@ idea {
["out", "src/main/kotlin", "src/test/kotlin"].each {
excludeDirs += file(it)
excludeDirs += file("modules/debug/" + it)
excludeDirs += file("modules/system/" + it)
excludeDirs += file("modules/util/" + it)
}
@@ -83,13 +82,16 @@ allprojects {
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile) {
kotlinOptions {
jvmTarget = "1.8"
apiVersion = "1.7"
languageVersion = "1.7"
apiVersion = "1.5"
languageVersion = "1.5"
useIR = true
freeCompilerArgs = [
"-Xno-call-assertions",
"-Xno-param-assertions",
"-Xno-receiver-assertions",
"-XXLanguage:+InlineClasses",
"-Xjvm-default=all",
"-Xuse-experimental=kotlin.contracts.ExperimentalContracts",
"-XXLanguage:+InlineClasses"
]
}
}
@@ -126,6 +128,7 @@ minecraft {
runs {
client {
property "hee.debug", ""
property "mixin.env.remapRefMap", "true"
property "mixin.env.refMapRemappingFile", "${projectDir}/build/createSrgToMcp/output.srg"
arg "-mixin.config=hee.mixins.json"
@@ -135,7 +138,6 @@ minecraft {
mods {
hee {
source sourceSets.main
source project(":debug").sourceSets.main
source project(":system").sourceSets.main
source project(":util").sourceSets.main
}
@@ -143,6 +145,7 @@ minecraft {
}
server {
property "hee.debug", ""
property "mixin.env.remapRefMap", "true"
property "mixin.env.refMapRemappingFile", "${projectDir}/build/createSrgToMcp/output.srg"
arg "-mixin.config=hee.mixins.json"
@@ -152,7 +155,6 @@ minecraft {
mods {
hee {
source sourceSets.main
source project(":debug").sourceSets.main
source project(":system").sourceSets.main
source project(":util").sourceSets.main
}
@@ -160,6 +162,7 @@ minecraft {
}
data {
property "hee.debug", ""
args "--mod", "hee"
args "--all"
args "--output", file("data/gen")
@@ -171,7 +174,6 @@ minecraft {
mods {
hee {
source sourceSets.main
source project(":debug").sourceSets.main
source project(":system").sourceSets.main
source project(":util").sourceSets.main
source project(":datagen").sourceSets.main
@@ -188,12 +190,12 @@ mixin {
dependencies {
minecraft "net.minecraftforge:forge:" + mc_version + "-" + forge_version
implementation project(":util")
implementation project(":system")
implementation project(":util")
implementation "thedarkcolour:kotlinforforge:" + kotlin_mod_version
testImplementation project(":util")
testImplementation project(":system")
testImplementation project(":util")
testImplementation "org.junit.jupiter:junit-jupiter-api:5.3.0-RC1"
if (System.getProperty("idea.sync.active") != "true") {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,9 +0,0 @@
package chylex.hee.game.item.components
import net.minecraft.item.ItemStack
import net.minecraft.util.text.ITextComponent
import net.minecraft.world.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
import chylex.hee.util.color.RGB
import chylex.hee.util.forge.Side
import chylex.hee.util.forge.Sided
import net.minecraft.client.renderer.color.IItemColor
@@ -10,7 +9,6 @@ import net.minecraft.item.ItemStack
abstract class ItemTint : IItemColor {
protected companion object {
const val NO_TINT = -1
val WHITE = RGB(255u).i
}
@Sided(Side.CLIENT)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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.IBlobLayout
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.Size
import chylex.hee.util.math.center
import chylex.hee.util.random.nextVector
import net.minecraft.util.math.BlockPos
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.ore.IOreTechnique
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.random.nextInt
import java.util.Random
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.structure.world.SegmentedWorld
import chylex.hee.game.world.util.allInCenteredBoxMutable
import chylex.hee.system.random.nextFloat
import chylex.hee.util.math.Pos
import chylex.hee.util.random.nextFloat
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.vector.Vector3d
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.util.allInCenteredBoxMutable
import chylex.hee.game.world.util.distanceSqTo
import chylex.hee.system.random.nextFloat
import chylex.hee.util.math.Pos
import chylex.hee.util.math.square
import chylex.hee.util.random.nextFloat
import net.minecraft.util.math.vector.Vector3d
class CaveCarverSphere(private val maxRandomRadiusReduction: Float) : ICaveCarver {

View File

@@ -7,7 +7,7 @@ import java.util.Random
import java.util.stream.IntStream
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
@@ -27,7 +27,7 @@ sealed class NoiseGenerator(private val xScale: Double, private val zScale: Doub
// 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)
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)
}
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)
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,6 +1,6 @@
package chylex.hee.game.world.generation.noise
import chylex.hee.util.math.remap
import chylex.hee.util.math.remapRange
import kotlin.math.abs
import kotlin.math.pow
import kotlin.math.roundToInt
@@ -26,12 +26,12 @@ class NoiseValue(var value: Double) {
it.coerceIn(minimum, maximum)
}
fun remap(fromMin: Double, fromMax: Double, toMin: Double, toMax: Double) = then {
it.remap(fromMin, fromMax, toMin, toMax)
fun remap(oldRange: ClosedFloatingPointRange<Double>, newRange: ClosedFloatingPointRange<Double>) = then {
remapRange(it, oldRange, newRange)
}
fun remap(toMin: Double, toMax: Double) = then {
it.remap(fromMin = 0.0, fromMax = 1.0, toMin, toMax)
fun remap(newRange: ClosedFloatingPointRange<Double>) = then {
remapRange(it, (0.0)..(1.0), newRange)
}
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.structure.world.SegmentedWorld
import chylex.hee.system.random.nextInt
import chylex.hee.util.math.BoundingBox
import chylex.hee.util.math.Pos
import chylex.hee.util.random.nextInt
import net.minecraft.util.math.BlockPos
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.structure.world.SegmentedWorld
import chylex.hee.game.world.util.Facing6
import chylex.hee.util.random.nextInt
import chylex.hee.util.random.nextItem
import chylex.hee.system.random.nextInt
import chylex.hee.system.random.nextItem
import net.minecraft.util.math.BlockPos
import java.util.Random
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.ore.IOreTechnique
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.ceilToInt
import chylex.hee.util.math.center
import chylex.hee.util.random.nextVector
import net.minecraft.util.math.BlockPos
import java.util.Random
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.util.Rotation4
import chylex.hee.game.world.util.Transform
import chylex.hee.util.random.nextItem
import chylex.hee.system.random.nextItem
import java.util.Random
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.MERGE
import chylex.hee.game.world.generation.structure.world.OffsetStructureWorld
import chylex.hee.system.Debug
import chylex.hee.util.math.Size
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.
*/
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")
}

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.Companion.index
import chylex.hee.game.world.util.Transform
import chylex.hee.system.Debug
import chylex.hee.util.math.Pos
import chylex.hee.util.math.Size
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.Blocks
import net.minecraft.util.math.BlockPos
import java.util.Random
open class SegmentedWorld(override val rand: Random, val worldSize: Size, segmentSize: Size, defaultSegmentFactory: (Size) -> ISegment) : IStructureWorld {
private val segmentSizeX = segmentSize.x
private val segmentSizeY = segmentSize.y
private val segmentSizeZ = segmentSize.z
open class SegmentedWorld(override val rand: Random, val worldSize: Size, private val segmentSize: Size, defaultSegmentFactory: (Size) -> ISegment) : IStructureWorld {
private val segmentCounts = Size(
(worldSize.x.toFloat() / segmentSizeX).ceilToInt(),
(worldSize.y.toFloat() / segmentSizeY).ceilToInt(),
(worldSize.z.toFloat() / segmentSizeZ).ceilToInt()
(worldSize.x.toFloat() / segmentSize.x).ceilToInt(),
(worldSize.y.toFloat() / segmentSize.y).ceilToInt(),
(worldSize.z.toFloat() / segmentSize.z).ceilToInt()
)
private val segments = Array(segmentCounts.x * segmentCounts.y * segmentCounts.z) { defaultSegmentFactory(segmentSize) }
private val triggers = mutableListOf<Pair<BlockPos, IStructureTrigger>>()
private fun getSegmentIndex(pos: BlockPos): Int {
return index(pos.x / segmentSizeX, pos.y / segmentSizeY, pos.z / segmentSizeZ, segmentCounts)
}
private fun mapPos(pos: BlockPos): Pair<Int, BlockPos>? {
if (!isInside(pos)) {
HEE.log.warn("[SegmentedWorld] attempted to access position outside bounds: $pos is outside $worldSize")
private fun getSegmentOffset(pos: BlockPos): BlockPos {
return Pos(pos.x % segmentSizeX, pos.y % segmentSizeY, pos.z % segmentSizeZ)
if (Debug.enabled) {
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 {
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 {
if (!isInside(pos)) {
warnNotInside(pos)
return Blocks.AIR.defaultState
}
val segmentIndex = getSegmentIndex(pos)
val segmentOffset = getSegmentOffset(pos)
val (segmentIndex, segmentOffset) = mapPos(pos) ?: return Blocks.AIR.defaultState
return segments[segmentIndex].getState(segmentOffset)
}
override fun setState(pos: BlockPos, state: BlockState) {
if (!isInside(pos)) {
warnNotInside(pos)
return
}
val segmentIndex = getSegmentIndex(pos)
val segmentOffset = getSegmentOffset(pos)
val (segmentIndex, segmentOffset) = mapPos(pos) ?: return
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)
/**
* 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) }
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) }) {
if (HEE.debug) {
if (Debug.enabled) {
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 {
code()
return 1
code();
return 1;
}
inline fun <reified T : Enum<T>> CommandContext<CommandSource>.getEnum(name: String): T {

View File

@@ -1,6 +1,6 @@
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 net.minecraft.util.Direction
import net.minecraft.util.math.vector.Vector3d

View File

@@ -1,6 +1,6 @@
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 net.minecraft.util.Rotation
import java.util.Random

View File

@@ -18,65 +18,54 @@ import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.vector.Vector3d
import org.apache.logging.log4j.Logger
inline fun <T : PacketBuffer> T.use(block: T.() -> Unit) {
block()
}
// BlockPos
inline fun ByteBuf.writePos(pos: BlockPos) {
inline fun PacketBuffer.writePos(pos: BlockPos) {
this.writeLong(pos.toLong())
}
inline fun ByteBuf.readPos(): BlockPos {
inline fun PacketBuffer.readPos(): BlockPos {
return Pos(this.readLong())
}
// Vec3d (Full)
fun ByteBuf.writeVec(vec: Vector3d) {
fun PacketBuffer.writeVec(vec: Vector3d) {
this.writeDouble(vec.x)
this.writeDouble(vec.y)
this.writeDouble(vec.z)
}
fun ByteBuf.readVec(): Vector3d {
return Vec(this.readDouble(), this.readDouble(), this.readDouble())
fun PacketBuffer.readVec(): Vector3d {
return Vec(readDouble(), readDouble(), readDouble())
}
// Vec3d (Float)
fun ByteBuf.writeFloatVec(vec: Vector3d) {
fun PacketBuffer.writeFloatVec(vec: Vector3d) {
this.writeFloat(vec.x.toFloat())
this.writeFloat(vec.y.toFloat())
this.writeFloat(vec.z.toFloat())
}
fun ByteBuf.readFloatVec(): Vector3d {
return Vec(this.readFloat().toDouble(), this.readFloat().toDouble(), this.readFloat().toDouble())
fun PacketBuffer.readFloatVec(): Vector3d {
return Vec(readFloat().toDouble(), readFloat().toDouble(), readFloat().toDouble())
}
// Vec3d (Compact)
fun ByteBuf.writeCompactVec(vec: Vector3d) {
fun PacketBuffer.writeCompactVec(vec: Vector3d) {
this.writeInt((vec.x * 8.0).floorToInt())
this.writeInt((vec.y * 8.0).floorToInt())
this.writeInt((vec.z * 8.0).floorToInt())
}
fun ByteBuf.readCompactVec(): Vector3d {
return Vec(this.readInt() * 0.125, this.readInt() * 0.125, this.readInt() * 0.125)
}
// Enum
fun <T : Enum<T>> PacketBuffer.writeEnum(value: T?) {
this.writeVarInt(value?.ordinal ?: -1)
}
inline fun <reified T : Enum<T>> PacketBuffer.readEnum(): T? {
val ordinal = this.readVarInt()
return if (ordinal >= 0)
T::class.java.enumConstants.getOrNull(ordinal)
else
null
fun PacketBuffer.readCompactVec(): Vector3d {
return Vec(readInt() * 0.125, readInt() * 0.125, readInt() * 0.125)
}
// NBT

View File

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

View File

@@ -46,17 +46,17 @@ fun lerp(from: Double, to: Double, progress: Double): Double {
}
/**
* Remaps a value from the range [[fromMin], [fromMax]] to a value in the range [[toMin], [toMax]] using linear interpolation.
* Maps a range of values in [from] range to values in [to] range using linear interpolation.
*/
fun Float.remap(fromMin: Float, fromMax: Float, toMin: Float, toMax: Float): Float {
val remappedBetween0And1 = (this - fromMin) / (fromMax - fromMin)
return toMin + remappedBetween0And1 * (toMax - toMin)
fun remapRange(value: Float, from: ClosedFloatingPointRange<Float>, to: ClosedFloatingPointRange<Float>): Float {
val remappedBetween0And1 = (value - from.start) / (from.endInclusive - from.start)
return to.start + remappedBetween0And1 * (to.endInclusive - to.start)
}
/**
* Remaps a value from the range [[fromMin], [fromMax]] to a value in the range [[toMin], [toMax]] using linear interpolation.
* Maps a range of values in [from] range to values in [to] range using linear interpolation.
*/
fun Double.remap(fromMin: Double, fromMax: Double, toMin: Double, toMax: Double): Double {
val remappedBetween0And1 = (this - fromMin) / (fromMax - fromMin)
return toMin + remappedBetween0And1 * (toMax - toMin)
fun remapRange(value: Double, from: ClosedFloatingPointRange<Double>, to: ClosedFloatingPointRange<Double>): Double {
val remappedBetween0And1 = (value - from.start) / (from.endInclusive - from.start)
return to.start + remappedBetween0And1 * (to.endInclusive - to.start)
}

View File

@@ -15,7 +15,6 @@ import net.minecraftforge.common.util.Constants.NBT
import org.apache.logging.log4j.Logger
import java.util.Locale
import java.util.UUID
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract
typealias NBTBase = net.minecraft.nbt.INBT
@@ -55,14 +54,12 @@ inline fun TagCompound.hasKey(key: String, type: Int): Boolean {
return this.contains(key, type)
}
@OptIn(ExperimentalContracts::class)
@JvmName("isNotNullAndHasKey")
inline fun TagCompound?.hasKey(key: String): Boolean {
contract { returns(true) implies (this@hasKey != null) }
return this != null && this.hasKey(key)
}
@OptIn(ExperimentalContracts::class)
@JvmName("isNotNullAndHasKey")
inline fun TagCompound?.hasKey(key: String, type: Int): Boolean {
contract { returns(true) implies (this@hasKey != null) }

View File

@@ -1,6 +1,6 @@
package chylex.hee.util.random
import chylex.hee.util.math.remap
import chylex.hee.util.math.remapRange
import java.util.Random
import kotlin.math.pow
@@ -29,7 +29,7 @@ abstract class RandomDouble private constructor(val min: Double, val max: Double
fun Exp(min: Double, max: Double, exp: Double) = object : RandomDouble(min, max) {
override fun invoke(rand: Random): Double {
return rand.nextDouble().pow(exp).remap(fromMin = 0.0, fromMax = 1.0, toMin = min, toMax = max)
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.Vec3

View File

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

View File

@@ -1,11 +1,7 @@
rootProject.name = "HEE"
include ":util"
include ":system"
include ":debug"
include ":util"
include ":datagen"
project(":util").projectDir = file("./modules/util")
project(":system").projectDir = file("./modules/system")
project(":debug").projectDir = file("./modules/debug")
project(":util").projectDir = file("./modules/util")
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.ModTileEntities
import chylex.hee.network.NetworkManager
import chylex.hee.system.Debug
import chylex.hee.util.forge.Side
import chylex.hee.util.forge.SubscribeAllEvents
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.common.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.FMLLoadCompleteEvent
@@ -39,10 +41,6 @@ object Mod {
HEE.version = activeContainer.modInfo.version.toString()
}
try {
Class.forName("chylex.hee.debug.Debug")
} catch (e: ClassNotFoundException) {}
@Suppress("ConvertLambdaToReference")
DistExecutor.safeRunWhenOn(Side.CLIENT) {
SafeRunnable { VanillaResourceOverrides.register() }
@@ -53,6 +51,11 @@ object Mod {
ModCreativeTabs
}
@SubscribeEvent
fun onClientSetup(@Suppress("UNUSED_PARAMETER") e: FMLClientSetupEvent) {
Debug.initializeClient()
}
@SubscribeEvent
fun onCommonSetup(@Suppress("UNUSED_PARAMETER") e: FMLCommonSetupEvent) {
NetworkManager.initialize(ModPackets.ALL)
@@ -83,7 +86,7 @@ object Mod {
for (block in BlockShulkerBoxOverride.ALL_BLOCKS) {
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.entity.TileEntityEnergyCluster
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.Companion.MAX_POSSIBLE_VALUE
import chylex.hee.game.mechanics.energy.IEnergyQuantity.Companion.displayString
import chylex.hee.game.world.util.getBlock
import chylex.hee.game.world.util.getTile
import chylex.hee.init.ModBlocks
import chylex.hee.init.ModItems
import chylex.hee.util.color.IntColor
import chylex.hee.util.color.RGB
import chylex.hee.util.color.RGBA
@@ -118,7 +118,7 @@ object OverlayRenderer {
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 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.system.properties.TerritoryEnvironment
import chylex.hee.game.world.isInEndDimension
import chylex.hee.system.Debug
import chylex.hee.util.color.IntColor
import chylex.hee.util.color.RGB
import chylex.hee.util.forge.EventPriority
@@ -25,7 +26,7 @@ import chylex.hee.util.forge.SubscribeAllEvents
import chylex.hee.util.forge.SubscribeEvent
import chylex.hee.util.math.LerpedFloat
import chylex.hee.util.math.floorToInt
import chylex.hee.util.math.remap
import chylex.hee.util.math.remapRange
import chylex.hee.util.math.scale
import com.mojang.blaze3d.matrix.MatrixStack
import com.mojang.blaze3d.platform.GlStateManager.FogMode.EXP2
@@ -35,6 +36,7 @@ import net.minecraft.entity.player.PlayerEntity
import net.minecraft.util.math.vector.Vector3f
import net.minecraftforge.client.event.EntityViewRenderEvent.RenderFogEvent
import net.minecraftforge.client.event.RenderGameOverlayEvent
import net.minecraftforge.common.MinecraftForge
import net.minecraftforge.event.TickEvent.ClientTickEvent
import net.minecraftforge.event.TickEvent.Phase
import org.lwjgl.opengl.GL11.GL_GREATER
@@ -117,7 +119,7 @@ object TerritoryRenderer {
// Fog rendering
private val currentFogDensityMp
get() = 1F + (9F * currentVoidFactor.remap(fromMin = -0.5F, fromMax = 1F, toMin = 0F, toMax = 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
get() = MC.settings.renderDistanceChunks.let { if (it > 12) 0F else (1F - (it / 16.5F)).pow((it - 1) * 0.25F) }
@@ -147,7 +149,7 @@ object TerritoryRenderer {
get() = Void.voidFactor.get(MC.partialTicks)
val currentSkyAlpha
get() = currentVoidFactor.remap(fromMin = -1F, fromMax = 0.5F, toMin = 1F, toMax = 0F).coerceIn(0F, 1F)
get() = remapRange(currentVoidFactor, (-1F)..(0.5F), (1F)..(0F)).coerceIn(0F, 1F)
private object Void {
private val VOID_PARTICLE = ParticleSpawnerCustom(
@@ -157,6 +159,12 @@ object TerritoryRenderer {
val voidFactor = LerpedFloat(TerritoryVoid.OUTSIDE_VOID_FACTOR)
init {
if (Debug.enabled) {
MinecraftForge.EVENT_BUS.register(this)
}
}
fun tick(player: PlayerEntity) {
val factor = TerritoryVoid.getVoidFactor(player).also(voidFactor::update)
@@ -178,6 +186,16 @@ object TerritoryRenderer {
fun reset() {
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

View File

@@ -17,10 +17,10 @@ import chylex.hee.game.Resource
import chylex.hee.game.block.BlockTablePedestal
import chylex.hee.game.block.entity.TileEntityTablePedestal
import chylex.hee.game.item.util.size
import chylex.hee.system.random.nextFloat
import chylex.hee.util.forge.Side
import chylex.hee.util.forge.Sided
import chylex.hee.util.math.toRadians
import chylex.hee.util.random.nextFloat
import com.mojang.blaze3d.matrix.MatrixStack
import net.minecraft.client.renderer.IRenderTypeBuffer
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.SF_SRC_ALPHA
import chylex.hee.game.entity.living.EntityMobAbstractEnderman
import chylex.hee.system.random.nextFloat
import chylex.hee.util.forge.Side
import chylex.hee.util.forge.Sided
import chylex.hee.util.random.nextFloat
import com.mojang.blaze3d.matrix.MatrixStack
import com.mojang.blaze3d.vertex.IVertexBuilder
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.item.util.isNotEmpty
import chylex.hee.game.world.util.Facing6
import chylex.hee.system.random.nextFloat
import chylex.hee.util.forge.Side
import chylex.hee.util.forge.Sided
import chylex.hee.util.random.nextFloat
import com.mojang.blaze3d.matrix.MatrixStack
import com.mojang.blaze3d.vertex.IVertexBuilder
import net.minecraft.block.AbstractChestBlock

View File

@@ -49,13 +49,13 @@ class RenderEntityTokenHolder(manager: EntityRendererManager) : EntityRenderer<E
matrix.rotateX(55F)
matrix.rotateZ(55F)
ModelEntityTokenHolder.render(matrix, buffer.getBuffer(RenderType.getEntityTranslucent(getEntityTexture(entity))), combinedLight, OverlayTexture.NO_OVERLAY, 1F, 1F, 1F, alpha)
ModelEntityTokenHolder.render(matrix, buffer.getBuffer(RenderType.getEntityTranslucent(getEntityTexture(entity) ?: textures.getValue(NORMAL))), combinedLight, OverlayTexture.NO_OVERLAY, 1F, 1F, 1F, alpha)
matrix.pop()
matrix.pop()
}
override fun getEntityTexture(entity: EntityTokenHolder): ResourceLocation {
return textures.getValue(entity.tokenType)
override fun getEntityTexture(entity: EntityTokenHolder): ResourceLocation? {
return textures[entity.tokenType]
}
}

View File

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

View File

@@ -14,7 +14,7 @@ class BlockCauldronWithDragonsBreath(builder: BlockBuilder) : BlockAbstractCauld
return null
}
override fun createFilledBottle(): ItemStack {
override fun createFilledBottle(): ItemStack? {
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.setState
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.Sided
import chylex.hee.util.random.nextInt
import chylex.hee.util.random.removeItem
import net.minecraft.block.Block
import net.minecraft.block.BlockRenderType.INVISIBLE
import net.minecraft.block.BlockState

View File

@@ -18,9 +18,9 @@ import chylex.hee.game.world.util.removeBlock
import chylex.hee.game.world.util.setState
import chylex.hee.init.ModSounds
import chylex.hee.network.client.PacketClientFX
import chylex.hee.system.random.nextInt
import chylex.hee.util.math.Vec3
import chylex.hee.util.math.center
import chylex.hee.util.random.nextInt
import net.minecraft.block.BlockState
import net.minecraft.block.Blocks
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.world.util.getState
import chylex.hee.game.world.util.isFullBlock
import chylex.hee.system.random.nextInt
import chylex.hee.util.forge.Side
import chylex.hee.util.forge.Sided
import chylex.hee.util.random.nextInt
import net.minecraft.block.BlockState
import net.minecraft.client.particle.ParticleManager
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.setBlock
import chylex.hee.init.ModBlocks
import chylex.hee.system.random.nextInt
import chylex.hee.util.math.Pos
import chylex.hee.util.math.floorToInt
import chylex.hee.util.random.nextInt
import net.minecraft.block.BlockState
import net.minecraft.enchantment.EnchantmentHelper
import net.minecraft.enchantment.Enchantments

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