Compare commits
5 Commits
7565443e38
...
e73ac4e3d1
Author | SHA1 | Date |
---|---|---|
chylex | e73ac4e3d1 | |
chylex | 858fa672ec | |
chylex | 77f759e0d0 | |
chylex | f077f11c32 | |
chylex | e0c3ed6bc3 |
|
@ -12,6 +12,7 @@
|
|||
<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>
|
||||
|
|
11
build.gradle
11
build.gradle
|
@ -60,6 +60,7 @@ 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)
|
||||
}
|
||||
|
@ -128,7 +129,6 @@ minecraft {
|
|||
|
||||
runs {
|
||||
client {
|
||||
property "hee.debug", ""
|
||||
property "mixin.env.remapRefMap", "true"
|
||||
property "mixin.env.refMapRemappingFile", "${projectDir}/build/createSrgToMcp/output.srg"
|
||||
arg "-mixin.config=hee.mixins.json"
|
||||
|
@ -138,6 +138,7 @@ minecraft {
|
|||
mods {
|
||||
hee {
|
||||
source sourceSets.main
|
||||
source project(":debug").sourceSets.main
|
||||
source project(":system").sourceSets.main
|
||||
source project(":util").sourceSets.main
|
||||
}
|
||||
|
@ -145,7 +146,6 @@ minecraft {
|
|||
}
|
||||
|
||||
server {
|
||||
property "hee.debug", ""
|
||||
property "mixin.env.remapRefMap", "true"
|
||||
property "mixin.env.refMapRemappingFile", "${projectDir}/build/createSrgToMcp/output.srg"
|
||||
arg "-mixin.config=hee.mixins.json"
|
||||
|
@ -155,6 +155,7 @@ minecraft {
|
|||
mods {
|
||||
hee {
|
||||
source sourceSets.main
|
||||
source project(":debug").sourceSets.main
|
||||
source project(":system").sourceSets.main
|
||||
source project(":util").sourceSets.main
|
||||
}
|
||||
|
@ -162,7 +163,6 @@ minecraft {
|
|||
}
|
||||
|
||||
data {
|
||||
property "hee.debug", ""
|
||||
args "--mod", "hee"
|
||||
args "--all"
|
||||
args "--output", file("data/gen")
|
||||
|
@ -174,6 +174,7 @@ 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
|
||||
|
@ -190,12 +191,12 @@ mixin {
|
|||
dependencies {
|
||||
minecraft "net.minecraftforge:forge:" + mc_version + "-" + forge_version
|
||||
|
||||
implementation project(":system")
|
||||
implementation project(":util")
|
||||
implementation project(":system")
|
||||
implementation "thedarkcolour:kotlinforforge:" + kotlin_mod_version
|
||||
|
||||
testImplementation project(":system")
|
||||
testImplementation project(":util")
|
||||
testImplementation project(":system")
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-api:5.3.0-RC1"
|
||||
|
||||
if (System.getProperty("idea.sync.active") != "true") {
|
||||
|
|
|
@ -91,7 +91,7 @@ class LangEnglish(generator: DataGenerator, modid: String) : LanguageProvider(ge
|
|||
}
|
||||
}
|
||||
|
||||
for (command in ClientCommandHandler.nonHelpCommands.values) {
|
||||
for (command in ClientCommandHandler.all.values) {
|
||||
val name = command.name
|
||||
add("commands.hee.$name.info", command.description)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url = "https://files.minecraftforge.net/maven" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath group: "net.minecraftforge.gradle", name: "ForgeGradle", version: forge_gradle_version, changing: true
|
||||
classpath group: "org.jetbrains.kotlin", name: "kotlin-gradle-plugin", version: kotlin_version
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: "net.minecraftforge.gradle"
|
||||
|
||||
minecraft {
|
||||
mappings channel: "snapshot", version: rootProject.mapping_version
|
||||
setAccessTransformers(rootProject.access_transformers)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
minecraft "net.minecraftforge:forge:" + mc_version + "-" + forge_version
|
||||
implementation rootProject
|
||||
implementation project(":system")
|
||||
implementation project(":util")
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes([
|
||||
"FMLModType": "LIBRARY"
|
||||
])
|
||||
}
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
package chylex.hee.client
|
||||
|
||||
import chylex.hee.client.render.RenderStateBuilder
|
||||
import chylex.hee.client.render.util.DF_ONE
|
||||
import chylex.hee.client.render.util.DF_ZERO
|
||||
import chylex.hee.client.render.util.SF_ONE_MINUS_SRC_ALPHA
|
||||
import chylex.hee.client.render.util.SF_SRC_ALPHA
|
||||
import chylex.hee.client.util.MC
|
||||
import chylex.hee.game.item.util.nbtOrNull
|
||||
import chylex.hee.game.world.util.floodFill
|
||||
import chylex.hee.game.world.util.getBlock
|
||||
import chylex.hee.game.world.util.getState
|
||||
import chylex.hee.game.world.util.isAir
|
||||
import chylex.hee.game.world.util.removeBlock
|
||||
import chylex.hee.game.world.util.setState
|
||||
import chylex.hee.util.nbt.hasKey
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats
|
||||
import net.minecraft.entity.player.PlayerEntity
|
||||
import net.minecraft.item.BlockItem
|
||||
import net.minecraft.item.Items
|
||||
import net.minecraft.util.Direction
|
||||
import net.minecraft.util.Direction.DOWN
|
||||
import net.minecraft.util.Direction.EAST
|
||||
import net.minecraft.util.Direction.NORTH
|
||||
import net.minecraft.util.Direction.SOUTH
|
||||
import net.minecraft.util.Direction.UP
|
||||
import net.minecraft.util.Direction.WEST
|
||||
import net.minecraft.util.Hand.MAIN_HAND
|
||||
import net.minecraft.util.Hand.OFF_HAND
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import net.minecraft.util.math.BlockRayTraceResult
|
||||
import net.minecraft.util.math.shapes.ISelectionContext
|
||||
import net.minecraft.world.IWorld
|
||||
import net.minecraftforge.client.event.DrawHighlightEvent
|
||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent.LeftClickBlock
|
||||
import net.minecraftforge.event.entity.player.PlayerInteractEvent.RightClickBlock
|
||||
import net.minecraftforge.event.world.BlockEvent.BreakEvent
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent
|
||||
import org.lwjgl.opengl.GL11
|
||||
|
||||
object BuildStick {
|
||||
private val RENDER_TYPE_LINE = with(RenderStateBuilder()) {
|
||||
line(2.25)
|
||||
blend(SF_SRC_ALPHA, DF_ONE, SF_ONE_MINUS_SRC_ALPHA, DF_ZERO)
|
||||
layering(RenderStateBuilder.LAYERING_OFFSET_Z)
|
||||
mask(RenderStateBuilder.MASK_COLOR)
|
||||
buildType("hee:debug_line", DefaultVertexFormats.POSITION_COLOR, GL11.GL_LINES, bufferSize = 256)
|
||||
}
|
||||
|
||||
private fun isHoldingBuildStick(player: PlayerEntity): Boolean {
|
||||
val heldItem = player.getHeldItem(MAIN_HAND)
|
||||
return heldItem.item === Items.STICK && heldItem.nbtOrNull.hasKey("HEE_BUILD")
|
||||
}
|
||||
|
||||
private fun getBuildStickBlocks(world: IWorld, pos: BlockPos, state: BlockState, face: Direction): List<BlockPos> {
|
||||
val floodFaces = when (face) {
|
||||
UP, DOWN -> listOf(NORTH, SOUTH, EAST, WEST)
|
||||
NORTH, SOUTH -> listOf(UP, DOWN, EAST, WEST)
|
||||
EAST, WEST -> listOf(UP, DOWN, NORTH, SOUTH)
|
||||
else -> emptyList()
|
||||
}
|
||||
|
||||
val limit = 1000
|
||||
val block = state.block
|
||||
return pos.floodFill(floodFaces, limit) { it.getBlock(world) === block }.takeIf { it.size < limit }.orEmpty()
|
||||
}
|
||||
|
||||
private var lastLeftClickHit: BlockRayTraceResult? = null
|
||||
|
||||
@SubscribeEvent
|
||||
fun onLeftClickBlock(e: LeftClickBlock) {
|
||||
val world = e.world
|
||||
|
||||
if (isHoldingBuildStick(e.player) && !world.isRemote) {
|
||||
lastLeftClickHit = MC.instance.objectMouseOver as? BlockRayTraceResult
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun onBlockBreak(e: BreakEvent) {
|
||||
val world = e.world
|
||||
|
||||
if (isHoldingBuildStick(e.player) && !world.isRemote) {
|
||||
val hit = lastLeftClickHit ?: return
|
||||
|
||||
for (pos in getBuildStickBlocks(world, e.pos, e.state, hit.face)) {
|
||||
pos.removeBlock(world)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun onRightClickBlock(e: RightClickBlock) {
|
||||
val world = e.world
|
||||
val player = e.player
|
||||
|
||||
if (isHoldingBuildStick(player) && !world.isRemote) {
|
||||
val state = e.pos.getState(world)
|
||||
val face = e.face!!
|
||||
|
||||
val place = (player.getHeldItem(OFF_HAND).item as? BlockItem)?.block?.defaultState ?: state
|
||||
|
||||
for (pos in getBuildStickBlocks(world, e.pos, state, face)) {
|
||||
val offset = pos.offset(face)
|
||||
|
||||
if (offset.isAir(world)) {
|
||||
offset.setState(world, place)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
fun onRenderOverlay(e: DrawHighlightEvent.HighlightBlock) {
|
||||
val player = MC.player!!
|
||||
|
||||
if (isHoldingBuildStick(player)) {
|
||||
val hit = MC.instance.objectMouseOver as? BlockRayTraceResult ?: return
|
||||
val world = player.world
|
||||
val center = hit.pos
|
||||
val info = e.info
|
||||
|
||||
val matrix = e.matrix.last.matrix
|
||||
val builder = e.buffers.getBuffer(RENDER_TYPE_LINE)
|
||||
|
||||
for (pos in getBuildStickBlocks(world, center, center.getState(world), hit.face)) {
|
||||
val x = pos.x - info.projectedView.x
|
||||
val y = pos.y - info.projectedView.y
|
||||
val z = pos.z - info.projectedView.z
|
||||
|
||||
val shape = pos.getState(world).getShape(world, pos, ISelectionContext.forEntity(info.renderViewEntity))
|
||||
|
||||
shape.forEachEdge { x1, y1, z1, x2, y2, z2 ->
|
||||
builder.pos(matrix, (x1 + x).toFloat(), (y1 + y).toFloat(), (z1 + z).toFloat()).color(1F, 1F, 1F, 1F).endVertex()
|
||||
builder.pos(matrix, (x2 + x).toFloat(), (y2 + y).toFloat(), (z2 + z).toFloat()).color(1F, 1F, 1F, 1F).endVertex()
|
||||
}
|
||||
}
|
||||
|
||||
e.isCanceled = true
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package chylex.hee.client
|
||||
|
||||
import chylex.hee.client.util.MC
|
||||
import chylex.hee.debug.benchmark.TerritoryGenerationBenchmarkScreen
|
||||
import chylex.hee.util.color.RGB
|
||||
import com.mojang.blaze3d.matrix.MatrixStack
|
||||
import net.minecraft.client.gui.screen.Screen
|
||||
import net.minecraft.client.gui.widget.button.Button
|
||||
import net.minecraft.util.text.StringTextComponent
|
||||
import net.minecraftforge.client.event.InputEvent.KeyInputEvent
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent
|
||||
import org.lwjgl.glfw.GLFW
|
||||
|
||||
object DebugMenu {
|
||||
@SubscribeEvent
|
||||
fun onKeyPressed(e: KeyInputEvent) {
|
||||
if (e.action != GLFW.GLFW_RELEASE) {
|
||||
return
|
||||
}
|
||||
|
||||
if (e.key == GLFW.GLFW_KEY_F12) {
|
||||
MC.instance.displayGuiScreen(DebugMenuScreen(MC.currentScreen))
|
||||
}
|
||||
}
|
||||
|
||||
private class DebugMenuScreen(private val parentScreen: Screen?) : Screen(StringTextComponent("HEE 2 Debug")) {
|
||||
override fun init() {
|
||||
addButton(Button(width / 2 - 100, 36, 200, 20, StringTextComponent("Territory Generation Benchmark")) { MC.instance.displayGuiScreen(TerritoryGenerationBenchmarkScreen(this)) })
|
||||
addButton(Button(width / 2 - 100, height - 40, 200, 20, StringTextComponent("Close")) { closeScreen() })
|
||||
}
|
||||
|
||||
override fun render(matrix: MatrixStack, mouseX: Int, mouseY: Int, partialTicks: Float) {
|
||||
renderBackground(matrix)
|
||||
drawCenteredString(matrix, font, title, width / 2, 15, RGB(255u).i)
|
||||
super.render(matrix, mouseX, mouseY, partialTicks)
|
||||
}
|
||||
|
||||
override fun closeScreen() {
|
||||
MC.instance.displayGuiScreen(parentScreen)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package chylex.hee.client
|
||||
|
||||
import chylex.hee.client.util.MC
|
||||
import net.minecraftforge.client.event.InputEvent.KeyInputEvent
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent
|
||||
import org.lwjgl.glfw.GLFW
|
||||
|
||||
object GameModeToggle {
|
||||
@SubscribeEvent
|
||||
fun onKeyPressed(e: KeyInputEvent) {
|
||||
if (e.action != GLFW.GLFW_PRESS) {
|
||||
return
|
||||
}
|
||||
|
||||
if (e.key == GLFW.GLFW_KEY_GRAVE_ACCENT) {
|
||||
val player = MC.player ?: return
|
||||
|
||||
if (player.isCreative) {
|
||||
val ctrl = (e.modifiers and GLFW.GLFW_MOD_CONTROL) != 0
|
||||
player.sendChatMessage(if (ctrl) "/gamemode spectator" else "/gamemode survival")
|
||||
}
|
||||
else {
|
||||
player.sendChatMessage("/gamemode creative")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package chylex.hee.client
|
||||
|
||||
import chylex.hee.client.render.TerritoryRenderer
|
||||
import chylex.hee.client.util.MC
|
||||
import chylex.hee.game.world.isInEndDimension
|
||||
import net.minecraftforge.client.event.RenderGameOverlayEvent
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent
|
||||
|
||||
object TerritoryVoidDebug {
|
||||
@SubscribeEvent
|
||||
fun onRenderGameOverlayText(e: RenderGameOverlayEvent.Text) {
|
||||
if (MC.settings.showDebugInfo && MC.player?.isInEndDimension == true) {
|
||||
with(e.left) {
|
||||
add("")
|
||||
add("End Void Factor: ${"%.3f".format(TerritoryRenderer.currentVoidFactor)}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package chylex.hee.debug
|
||||
|
||||
import chylex.hee.game.Environment
|
||||
import chylex.hee.util.forge.Side
|
||||
import org.apache.commons.lang3.SystemUtils
|
||||
import java.io.File
|
||||
import java.lang.management.ManagementFactory
|
||||
|
||||
internal object PowerShell {
|
||||
private fun canExecutePowershell(scriptName: String): Boolean {
|
||||
return SystemUtils.IS_OS_WINDOWS && Environment.side == Side.CLIENT && File(scriptName).exists()
|
||||
}
|
||||
|
||||
fun setClipboardContents(file: File) {
|
||||
if (canExecutePowershell("filecopy.ps1")) {
|
||||
ProcessBuilder("powershell.exe", "-ExecutionPolicy", "Unrestricted", "-Sta", "-File", "filecopy.ps1", file.absolutePath).start()
|
||||
}
|
||||
}
|
||||
|
||||
fun maximizeWindow() {
|
||||
if (canExecutePowershell("maximize.ps1")) {
|
||||
val pid = ManagementFactory.getRuntimeMXBean().name.split("@")[0]
|
||||
ProcessBuilder("powershell.exe", "-ExecutionPolicy", "Unrestricted", "-File", "maximize.ps1", pid).start()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package chylex.hee.debug.benchmark
|
||||
|
||||
import chylex.hee.HEE
|
||||
import chylex.hee.client.util.MC
|
||||
import chylex.hee.game.Environment
|
||||
import chylex.hee.game.territory.TerritoryType
|
||||
import chylex.hee.game.world.generation.structure.world.SegmentedWorld
|
||||
import chylex.hee.util.color.RGB
|
||||
import com.mojang.blaze3d.matrix.MatrixStack
|
||||
import net.minecraft.client.gui.screen.Screen
|
||||
import net.minecraft.client.gui.widget.button.Button
|
||||
import net.minecraft.util.text.StringTextComponent
|
||||
import net.minecraft.util.text.TranslationTextComponent
|
||||
import net.minecraft.world.World
|
||||
import java.util.Random
|
||||
|
||||
class TerritoryGenerationBenchmarkScreen(private val parentScreen: Screen) : Screen(StringTextComponent("Territory Generation Benchmark")) {
|
||||
private val generated = mutableListOf<SegmentedWorld>()
|
||||
|
||||
override fun init() {
|
||||
try {
|
||||
Environment.getDimension(World.OVERWORLD)
|
||||
} catch (e: NullPointerException) {
|
||||
println("Must be in a world!")
|
||||
closeScreen()
|
||||
return
|
||||
}
|
||||
|
||||
val x = width / 2 - 100
|
||||
addButton(Button(x, 36, 200, 20, StringTextComponent("(All)")) { runAll() })
|
||||
|
||||
for ((index, territory) in TerritoryType.ALL.withIndex()) {
|
||||
val y = 36 + (22 * (index + 1))
|
||||
addButton(Button(x, y, 200, 20, TranslationTextComponent(territory.translationKey)) { runOnce(territory) })
|
||||
}
|
||||
|
||||
addButton(Button(x, height - 40, 200, 20, StringTextComponent("Close")) { closeScreen() })
|
||||
}
|
||||
|
||||
override fun render(matrix: MatrixStack, mouseX: Int, mouseY: Int, partialTicks: Float) {
|
||||
renderBackground(matrix)
|
||||
drawCenteredString(matrix, font, title, width / 2, 15, RGB(255u).i)
|
||||
super.render(matrix, mouseX, mouseY, partialTicks)
|
||||
}
|
||||
|
||||
override fun closeScreen() {
|
||||
MC.instance.displayGuiScreen(parentScreen)
|
||||
}
|
||||
|
||||
private fun runAll() {
|
||||
generated.clear()
|
||||
|
||||
for (territory in TerritoryType.ALL) {
|
||||
if (territory.gen === TerritoryType.Companion.GeneratorDummy) {
|
||||
continue
|
||||
}
|
||||
|
||||
for (seed in 0L until 5L) {
|
||||
runImpl(territory, seed)
|
||||
}
|
||||
}
|
||||
|
||||
HEE.log.info("[TerritoryGenerationBenchmarkScreen] done!")
|
||||
}
|
||||
|
||||
private fun runOnce(territory: TerritoryType) {
|
||||
generated.clear()
|
||||
runImpl(territory, 0L)
|
||||
}
|
||||
|
||||
private fun runImpl(territory: TerritoryType, seed: Long) {
|
||||
HEE.log.info("[TerritoryGenerationBenchmarkScreen] generating " + territory.name)
|
||||
|
||||
val timeStart = System.currentTimeMillis()
|
||||
generated.add(territory.generate(Random(seed)).first)
|
||||
val timeEnd = System.currentTimeMillis()
|
||||
|
||||
HEE.log.info("[TerritoryGenerationBenchmarkScreen] finished in ${timeEnd - timeStart} ms")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
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)
|
||||
}
|
||||
}
|
|
@ -1,13 +1,13 @@
|
|||
package chylex.hee.game.command.client
|
||||
|
||||
import chylex.hee.client.render.TerritoryRenderer
|
||||
import chylex.hee.game.block.BlockScaffolding
|
||||
import chylex.hee.game.command.IClientCommand
|
||||
import chylex.hee.game.territory.TerritoryVoid
|
||||
import chylex.hee.init.ModBlocks
|
||||
import net.minecraft.command.CommandSource
|
||||
import net.minecraft.util.text.StringTextComponent
|
||||
|
||||
object CommandDebugToggles : IClientCommand {
|
||||
object CommandClientDebugToggles : IClientCommand {
|
||||
override val name = "debug"
|
||||
override val description = "access to debug toggles"
|
||||
|
||||
|
@ -23,8 +23,8 @@ object CommandDebugToggles : IClientCommand {
|
|||
sender.sendFeedback(StringTextComponent("Territory debugging ${if (debug) "enabled" else "disabled"}."), false)
|
||||
}
|
||||
else if (name == "scaffolding") {
|
||||
ModBlocks.SCAFFOLDING.enableShape = !ModBlocks.SCAFFOLDING.enableShape
|
||||
sender.sendFeedback(StringTextComponent("Scaffolding shape ${if (ModBlocks.SCAFFOLDING.enableShape) "enabled" else "disabled"}."), false)
|
||||
BlockScaffolding.enableShape = !BlockScaffolding.enableShape
|
||||
sender.sendFeedback(StringTextComponent("Scaffolding shape ${if (BlockScaffolding.enableShape) "enabled" else "disabled"}."), false)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
package chylex.hee.game.command.client
|
||||
|
||||
import chylex.hee.game.command.IClientCommand
|
||||
import chylex.hee.game.command.server.CommandDebugStructure
|
||||
import chylex.hee.game.command.server.CommandServerStructure
|
||||
import net.minecraft.command.CommandSource
|
||||
import net.minecraft.util.text.StringTextComponent
|
||||
import java.util.prefs.Preferences
|
||||
|
@ -14,7 +14,7 @@ object CommandClientScaffolding : IClientCommand {
|
|||
get() = Preferences.userRoot().node("chylex-hee-scaffolding")
|
||||
|
||||
val currentPalette
|
||||
get() = data.get("Structure", null)?.let(CommandDebugStructure.structureDescriptions::get)?.PALETTE
|
||||
get() = data.get("Structure", null)?.let(CommandServerStructure.structureDescriptions::get)?.PALETTE
|
||||
|
||||
val currentFile
|
||||
get() = data.get("File", "")!!.ifBlank { "structure.nbt" }
|
||||
|
@ -22,7 +22,7 @@ object CommandClientScaffolding : IClientCommand {
|
|||
override fun executeCommand(sender: CommandSource, args: Array<String>) {
|
||||
val structure = args.getOrNull(0) ?: return
|
||||
|
||||
if (!CommandDebugStructure.structureDescriptions.containsKey(structure)) {
|
||||
if (!CommandServerStructure.structureDescriptions.containsKey(structure)) {
|
||||
sender.sendFeedback(StringTextComponent("Unknown structure."), false)
|
||||
return
|
||||
}
|
|
@ -15,7 +15,7 @@ import net.minecraft.command.Commands.argument
|
|||
import net.minecraft.command.Commands.literal
|
||||
import net.minecraft.util.text.StringTextComponent
|
||||
|
||||
object CommandDebugInstability : ICommand {
|
||||
object CommandServerInstability : ICommand {
|
||||
override val name = "instability"
|
||||
override val description = "utilities for instability"
|
||||
|
|
@ -31,7 +31,7 @@ import net.minecraft.util.Rotation
|
|||
import net.minecraft.util.text.StringTextComponent
|
||||
import java.util.Random
|
||||
|
||||
object CommandDebugStructure : ICommand {
|
||||
object CommandServerStructure : ICommand {
|
||||
val structureDescriptions = mapOf(
|
||||
"stronghold" to StrongholdPieces,
|
||||
"energyshrine" to EnergyShrinePieces,
|
|
@ -23,7 +23,7 @@ import net.minecraft.entity.player.PlayerEntity
|
|||
import net.minecraft.util.text.StringTextComponent
|
||||
import java.util.Random
|
||||
|
||||
object CommandDebugTerritory : ICommand {
|
||||
object CommandServerTerritory : ICommand {
|
||||
override val name = "territory"
|
||||
override val description = "utilities for territories"
|
||||
|
|
@ -7,7 +7,7 @@ import com.mojang.brigadier.builder.ArgumentBuilder
|
|||
import com.mojang.brigadier.context.CommandContext
|
||||
import net.minecraft.command.CommandSource
|
||||
|
||||
object CommandDebugTestWorld : ICommand, CommandExecutionFunction {
|
||||
object CommandServerTestWorld : ICommand, CommandExecutionFunction {
|
||||
override val name = "testworld"
|
||||
override val description = "converts overworld into a test world"
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"pack": {
|
||||
"description": "Hardcore Ender Expansion 2 (Debug Library)",
|
||||
"pack_format": 6,
|
||||
"_comment": ""
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
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
|
||||
|
@ -12,6 +13,10 @@ 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"))
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package chylex.hee.game.world.generation.noise
|
||||
|
||||
import chylex.hee.util.math.FloatRange
|
||||
import chylex.hee.util.math.range
|
||||
import chylex.hee.util.math.remapRange
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.pow
|
||||
|
@ -26,12 +28,12 @@ class NoiseValue(var value: Double) {
|
|||
it.coerceIn(minimum, maximum)
|
||||
}
|
||||
|
||||
fun remap(oldRange: ClosedFloatingPointRange<Double>, newRange: ClosedFloatingPointRange<Double>) = then {
|
||||
fun remap(oldRange: FloatRange, newRange: FloatRange) = then {
|
||||
remapRange(it, oldRange, newRange)
|
||||
}
|
||||
|
||||
fun remap(newRange: ClosedFloatingPointRange<Double>) = then {
|
||||
remapRange(it, (0.0)..(1.0), newRange)
|
||||
fun remap(newRange: FloatRange) = then {
|
||||
remapRange(it, range(0F, 1F), newRange)
|
||||
}
|
||||
|
||||
inline fun ifNonZero(block: NoiseValue.() -> Unit) {
|
||||
|
|
|
@ -7,7 +7,6 @@ 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
|
||||
|
||||
|
@ -83,7 +82,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 (Debug.enabled && !pieces.contains(targetPiece)) {
|
||||
if (HEE.debug && !pieces.contains(targetPiece)) {
|
||||
HEE.log.error("[StructureBuild] attempted to connect to a piece that is not present in the structure")
|
||||
}
|
||||
|
||||
|
|
|
@ -6,59 +6,67 @@ 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, private val segmentSize: Size, defaultSegmentFactory: (Size) -> ISegment) : IStructureWorld {
|
||||
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
|
||||
|
||||
private val segmentCounts = Size(
|
||||
(worldSize.x.toFloat() / segmentSize.x).ceilToInt(),
|
||||
(worldSize.y.toFloat() / segmentSize.y).ceilToInt(),
|
||||
(worldSize.z.toFloat() / segmentSize.z).ceilToInt()
|
||||
(worldSize.x.toFloat() / segmentSizeX).ceilToInt(),
|
||||
(worldSize.y.toFloat() / segmentSizeY).ceilToInt(),
|
||||
(worldSize.z.toFloat() / segmentSizeZ).ceilToInt()
|
||||
)
|
||||
|
||||
private val segments = Array(segmentCounts.x * segmentCounts.y * segmentCounts.z) { defaultSegmentFactory(segmentSize) }
|
||||
private val triggers = mutableListOf<Pair<BlockPos, IStructureTrigger>>()
|
||||
|
||||
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")
|
||||
|
||||
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)
|
||||
private fun getSegmentIndex(pos: BlockPos): Int {
|
||||
return index(pos.x / segmentSizeX, pos.y / segmentSizeY, pos.z / segmentSizeZ, segmentCounts)
|
||||
}
|
||||
|
||||
private fun getSegmentOffset(pos: BlockPos): BlockPos {
|
||||
return Pos(pos.x % segmentSizeX, pos.y % segmentSizeY, pos.z % segmentSizeZ)
|
||||
}
|
||||
|
||||
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 {
|
||||
val (segmentIndex, segmentOffset) = mapPos(pos) ?: return Blocks.AIR.defaultState
|
||||
if (!isInside(pos)) {
|
||||
warnNotInside(pos)
|
||||
return Blocks.AIR.defaultState
|
||||
}
|
||||
|
||||
val segmentIndex = getSegmentIndex(pos)
|
||||
val segmentOffset = getSegmentOffset(pos)
|
||||
return segments[segmentIndex].getState(segmentOffset)
|
||||
}
|
||||
|
||||
override fun setState(pos: BlockPos, state: BlockState) {
|
||||
val (segmentIndex, segmentOffset) = mapPos(pos) ?: return
|
||||
if (!isInside(pos)) {
|
||||
warnNotInside(pos)
|
||||
return
|
||||
}
|
||||
|
||||
val segmentIndex = getSegmentIndex(pos)
|
||||
val segmentOffset = getSegmentOffset(pos)
|
||||
segments[segmentIndex] = segments[segmentIndex].withState(segmentOffset, state)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,26 @@
|
|||
package chylex.hee.game.world.generation.structure.world.segments
|
||||
|
||||
import chylex.hee.game.world.generation.structure.world.segments.ISegment.Companion.index
|
||||
import chylex.hee.util.math.MutablePos
|
||||
import chylex.hee.util.math.Size
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.util.math.BlockPos
|
||||
|
||||
/**
|
||||
* A segment that supports arbitrary block states in arbitrary positions.
|
||||
*/
|
||||
class SegmentFull(private val size: Size, fillState: BlockState) : ISegment {
|
||||
constructor(size: Size, fillState: BlockState, posToStateMap: Long2ObjectOpenHashMap<BlockState>) : this(size, fillState) {
|
||||
val pos = MutablePos()
|
||||
val iter = posToStateMap.long2ObjectEntrySet().fastIterator()
|
||||
while (iter.hasNext()) {
|
||||
val entry = iter.next()
|
||||
pos.setPos(entry.longKey)
|
||||
data[index(pos, size)] = entry.value
|
||||
}
|
||||
}
|
||||
|
||||
private val data = Array(size.x * size.y * size.z) { fillState }
|
||||
|
||||
override fun getState(pos: BlockPos): BlockState {
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package chylex.hee.game.world.generation.structure.world.segments
|
||||
|
||||
import chylex.hee.util.math.Size
|
||||
import chylex.hee.util.math.floorToInt
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.util.math.BlockPos
|
||||
import kotlin.math.pow
|
||||
|
||||
/**
|
||||
* A segment mostly filled with one type of block state, but allowing for a few [exceptions].
|
||||
* When the amount of exceptions reaches a [threshold] based on the segment size, it gets converted to [SegmentFull].
|
||||
*/
|
||||
class SegmentMultiState(private val size: Size, private val fillState: BlockState) : ISegment {
|
||||
constructor(size: Size, block: Block) : this(size, block.defaultState)
|
||||
|
||||
/**
|
||||
* The threshold power was determined by careful experimentation and profiling.
|
||||
*/
|
||||
private val threshold = (size.x * size.y * size.z).toDouble().pow(0.69).floorToInt()
|
||||
private val exceptions = Long2ObjectOpenHashMap<BlockState>(threshold, 0.75F).apply { defaultReturnValue(fillState) }
|
||||
|
||||
override fun getState(pos: BlockPos): BlockState {
|
||||
return exceptions.get(pos.toLong())
|
||||
}
|
||||
|
||||
override fun withState(pos: BlockPos, state: BlockState): ISegment {
|
||||
if (state == fillState) {
|
||||
exceptions.remove(pos.toLong())
|
||||
return this
|
||||
}
|
||||
|
||||
@Suppress("ReplacePutWithAssignment")
|
||||
exceptions.put(pos.toLong(), state) // kotlin indexer boxes the values
|
||||
|
||||
return if (exceptions.size < threshold)
|
||||
this
|
||||
else
|
||||
SegmentFull(size, fillState, exceptions)
|
||||
}
|
||||
}
|
|
@ -5,6 +5,10 @@ import net.minecraft.block.Block
|
|||
import net.minecraft.block.BlockState
|
||||
import net.minecraft.util.math.BlockPos
|
||||
|
||||
/**
|
||||
* A segment completely filled with only one type of block state.
|
||||
* When any block state is changed, gets converted to [SegmentMultiState].
|
||||
*/
|
||||
class SegmentSingleState(private val size: Size, private val fillState: BlockState) : ISegment {
|
||||
constructor(size: Size, block: Block) : this(size, block.defaultState)
|
||||
|
||||
|
@ -16,6 +20,6 @@ class SegmentSingleState(private val size: Size, private val fillState: BlockSta
|
|||
return if (state == fillState)
|
||||
this
|
||||
else
|
||||
SegmentFull(size, fillState).withState(pos, state)
|
||||
SegmentMultiState(size, fillState).withState(pos, state)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,206 +0,0 @@
|
|||
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()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
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
|
||||
}
|
|
@ -19,7 +19,7 @@ object MinecraftForgeEventBus {
|
|||
}
|
||||
|
||||
for (listener in item.javaClass.methods.filter { !Modifier.isStatic(it.modifiers) && it.isAnnotationPresent(SubscribeEvent::class.java) }) {
|
||||
if (Debug.enabled) {
|
||||
if (HEE.debug) {
|
||||
HEE.log.info("[MinecraftForgeEventBus] registering ${listener.parameterTypes.firstOrNull()?.name?.substringAfterLast('.')} for ${item.javaClass.simpleName}")
|
||||
}
|
||||
|
||||
|
|
|
@ -48,15 +48,15 @@ fun lerp(from: Double, to: Double, progress: Double): Double {
|
|||
/**
|
||||
* Maps a range of values in [from] range to values in [to] range using linear interpolation.
|
||||
*/
|
||||
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)
|
||||
fun remapRange(value: Float, from: FloatRange, to: FloatRange): Float {
|
||||
val remappedBetween0And1 = (value - from.start) / (from.end - from.start)
|
||||
return to.start + remappedBetween0And1 * (to.end - to.start)
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a range of values in [from] range to values in [to] range using linear interpolation.
|
||||
*/
|
||||
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)
|
||||
fun remapRange(value: Double, from: FloatRange, to: FloatRange): Double {
|
||||
val remappedBetween0And1 = (value - from.start) / (from.end - from.start)
|
||||
return to.start + remappedBetween0And1 * (to.end - to.start)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package chylex.hee.util.math
|
||||
|
||||
@JvmInline
|
||||
value class FloatRange(private val combined: Long) {
|
||||
constructor(start: Float, end: Float) : this((start.toRawBits() shlong 32) or (end.toRawBits().toLong() and 0xFFFF_FFFFL))
|
||||
|
||||
val start
|
||||
get() = Float.fromBits((combined ushr 32).toInt())
|
||||
|
||||
val end
|
||||
get() = Float.fromBits((combined and 0xFFFF_FFFFL).toInt())
|
||||
}
|
||||
|
||||
fun range(start: Float, end: Float) = FloatRange(start, end)
|
|
@ -1,5 +1,6 @@
|
|||
package chylex.hee.util.random
|
||||
|
||||
import chylex.hee.util.math.range
|
||||
import chylex.hee.util.math.remapRange
|
||||
import java.util.Random
|
||||
import kotlin.math.pow
|
||||
|
@ -29,7 +30,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 remapRange(rand.nextDouble().pow(exp), (0.0)..(1.0), min..max)
|
||||
return remapRange(rand.nextDouble().pow(exp), range(0F, 1F), range(min.toFloat(), max.toFloat()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
include ":system"
|
||||
include ":util"
|
||||
include ":system"
|
||||
include ":debug"
|
||||
include ":datagen"
|
||||
|
||||
project(":system").projectDir = file("./modules/system")
|
||||
project(":util").projectDir = file("./modules/util")
|
||||
project(":system").projectDir = file("./modules/system")
|
||||
project(":debug").projectDir = file("./modules/debug")
|
||||
project(":datagen").projectDir = file("./data")
|
||||
|
|
|
@ -19,7 +19,6 @@ 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
|
||||
|
@ -29,7 +28,6 @@ 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
|
||||
|
||||
|
@ -41,6 +39,10 @@ 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() }
|
||||
|
@ -51,11 +53,6 @@ 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)
|
||||
|
|
|
@ -17,7 +17,6 @@ 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
|
||||
|
@ -26,6 +25,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.range
|
||||
import chylex.hee.util.math.remapRange
|
||||
import chylex.hee.util.math.scale
|
||||
import com.mojang.blaze3d.matrix.MatrixStack
|
||||
|
@ -36,7 +36,6 @@ 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
|
||||
|
@ -119,7 +118,7 @@ object TerritoryRenderer {
|
|||
// Fog rendering
|
||||
|
||||
private val currentFogDensityMp
|
||||
get() = 1F + (9F * remapRange(currentVoidFactor, (-0.5F)..(1F), (0F)..(1F)).coerceIn(0F, 1F).pow(1.5F))
|
||||
get() = 1F + (9F * remapRange(currentVoidFactor, range(-0.5F, 1F), range(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) }
|
||||
|
@ -149,7 +148,7 @@ object TerritoryRenderer {
|
|||
get() = Void.voidFactor.get(MC.partialTicks)
|
||||
|
||||
val currentSkyAlpha
|
||||
get() = remapRange(currentVoidFactor, (-1F)..(0.5F), (1F)..(0F)).coerceIn(0F, 1F)
|
||||
get() = remapRange(currentVoidFactor, range(-1F, 0.5F), range(1F, 0F)).coerceIn(0F, 1F)
|
||||
|
||||
private object Void {
|
||||
private val VOID_PARTICLE = ParticleSpawnerCustom(
|
||||
|
@ -159,12 +158,6 @@ 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)
|
||||
|
||||
|
@ -186,16 +179,6 @@ 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
|
||||
|
|
|
@ -1,48 +1,27 @@
|
|||
package chylex.hee.game.block
|
||||
|
||||
import chylex.hee.HEE
|
||||
import chylex.hee.game.Environment
|
||||
import chylex.hee.game.block.properties.BlockBuilder
|
||||
import chylex.hee.game.block.properties.BlockModel
|
||||
import chylex.hee.game.block.properties.BlockRenderLayer.CUTOUT
|
||||
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.system.Debug
|
||||
import chylex.hee.util.forge.Side
|
||||
import chylex.hee.util.forge.Sided
|
||||
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.math.shapes.ISelectionContext
|
||||
import net.minecraft.util.math.shapes.VoxelShape
|
||||
import net.minecraft.util.math.shapes.VoxelShapes
|
||||
import net.minecraft.util.text.StringTextComponent
|
||||
import net.minecraft.util.text.TextFormatting
|
||||
import net.minecraft.world.IBlockReader
|
||||
import net.minecraft.world.World
|
||||
import java.nio.file.Files
|
||||
|
||||
class BlockScaffolding(builder: BlockBuilder) : HeeBlock(builder) {
|
||||
var enableShape = true
|
||||
open class BlockScaffolding protected constructor(builder: BlockBuilder) : HeeBlock(builder) {
|
||||
companion object {
|
||||
var enableShape = true
|
||||
|
||||
fun create(builder: BlockBuilder): HeeBlock {
|
||||
return HEE.debugModule?.createScaffoldingBlock(builder) ?: BlockScaffolding(builder)
|
||||
}
|
||||
}
|
||||
|
||||
override val model
|
||||
get() = BlockModel.Manual
|
||||
|
@ -50,73 +29,6 @@ class BlockScaffolding(builder: BlockBuilder) : HeeBlock(builder) {
|
|||
override val renderLayer
|
||||
get() = CUTOUT
|
||||
|
||||
override fun onBlockActivated(state: BlockState, world: World, pos: BlockPos, player: PlayerEntity, hand: Hand, hit: BlockRayTraceResult): ActionResultType {
|
||||
if (world.isRemote && player.isSneaking && !player.abilities.isFlying && Debug.enabled) {
|
||||
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)
|
||||
Debug.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)
|
||||
}
|
||||
|
||||
// Visuals and physics
|
||||
|
||||
override fun getShape(state: BlockState, world: IBlockReader, pos: BlockPos, context: ISelectionContext): VoxelShape {
|
||||
|
|
|
@ -3,8 +3,6 @@ package chylex.hee.game.command
|
|||
import chylex.hee.HEE
|
||||
import chylex.hee.client.util.MC
|
||||
import chylex.hee.game.command.client.CommandClientHelp
|
||||
import chylex.hee.game.command.client.CommandClientScaffolding
|
||||
import chylex.hee.game.command.client.CommandDebugToggles
|
||||
import chylex.hee.init.ModCommands
|
||||
import chylex.hee.util.forge.EventPriority
|
||||
import chylex.hee.util.forge.Side
|
||||
|
@ -14,11 +12,15 @@ import net.minecraftforge.client.event.ClientChatEvent
|
|||
|
||||
@SubscribeAllEvents(Side.CLIENT, modid = HEE.ID)
|
||||
object ClientCommandHandler { // UPDATE
|
||||
val nonHelpCommands = listOf(
|
||||
CommandClientHelp,
|
||||
CommandClientScaffolding,
|
||||
CommandDebugToggles
|
||||
).associateBy { it.name }
|
||||
private val client
|
||||
get() = listOf(
|
||||
CommandClientHelp
|
||||
)
|
||||
|
||||
private val debug
|
||||
get() = HEE.debugModule?.clientCommands.orEmpty()
|
||||
|
||||
val all = (client + debug).associateBy { it.name }
|
||||
|
||||
@SubscribeEvent(priority = EventPriority.LOWEST)
|
||||
fun onClientChat(e: ClientChatEvent) {
|
||||
|
@ -34,7 +36,7 @@ object ClientCommandHandler { // UPDATE
|
|||
val command = when {
|
||||
arguments.isEmpty() -> CommandClientHelp
|
||||
arguments[0] == CommandClientHelp.name -> CommandClientHelp.takeIf { arguments.size < 2 || arguments[1] == "1" } ?: return
|
||||
else -> nonHelpCommands[arguments[0]] ?: return
|
||||
else -> all[arguments[0]] ?: return
|
||||
}
|
||||
|
||||
command.executeCommand(source, arguments.drop(1).toTypedArray())
|
||||
|
|
|
@ -10,6 +10,6 @@ object CommandClientHelp : IClientCommand {
|
|||
override val description = CommandServerHelp.description
|
||||
|
||||
override fun executeCommand(sender: CommandSource, args: Array<String>) {
|
||||
CommandServerHelp.sendCommandListPage(sender, ClientCommandHandler.nonHelpCommands.keys, emptyMap(), "commands.hee.help.header.client", 1, null)
|
||||
CommandServerHelp.sendCommandListPage(sender, ClientCommandHandler.all.keys, emptyMap(), "commands.hee.help.header.client", 1, null)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import chylex.hee.system.random.nextItem
|
|||
import chylex.hee.system.random.nextRounded
|
||||
import chylex.hee.util.math.Vec
|
||||
import chylex.hee.util.math.center
|
||||
import chylex.hee.util.math.range
|
||||
import chylex.hee.util.math.remapRange
|
||||
import chylex.hee.util.nbt.TagCompound
|
||||
import chylex.hee.util.nbt.use
|
||||
|
@ -268,9 +269,9 @@ class EntityInfusedTNT : TNTEntity {
|
|||
val waterRatio = foundWaterBlocks.size.toFloat() / totalCountedBlocks
|
||||
|
||||
val dropAmount = when {
|
||||
waterRatio < 0.1 -> remapRange(waterRatio, (0.0F)..(0.1F), (1.0F)..(1.6F))
|
||||
waterRatio < 0.4 -> remapRange(waterRatio, (0.1F)..(0.4F), (1.6F)..(4.0F))
|
||||
else -> remapRange(waterRatio, (0.4F)..(1.0F), (4.0F)..(5.8F))
|
||||
waterRatio < 0.1 -> remapRange(waterRatio, range(0.0F, 0.1F), range(1.0F, 1.6F))
|
||||
waterRatio < 0.4 -> remapRange(waterRatio, range(0.1F, 0.4F), range(1.6F, 4.0F))
|
||||
else -> remapRange(waterRatio, range(0.4F, 1.0F), range(4.0F, 5.8F))
|
||||
}
|
||||
|
||||
val lootTable = Environment.getLootTable(LootTables.GAMEPLAY_FISHING)
|
||||
|
|
|
@ -3,6 +3,7 @@ package chylex.hee.game.mechanics.instability.dimension
|
|||
import chylex.hee.game.mechanics.instability.dimension.components.EndermiteSpawnLogic
|
||||
import chylex.hee.util.math.ceilToInt
|
||||
import chylex.hee.util.math.floorToInt
|
||||
import chylex.hee.util.math.range
|
||||
import chylex.hee.util.math.remapRange
|
||||
import chylex.hee.util.nbt.TagCompound
|
||||
import chylex.hee.util.nbt.use
|
||||
|
@ -26,7 +27,7 @@ open class DimensionInstabilityGlobal(private val world: World, private val ende
|
|||
|
||||
private fun calculateActionMultiplier(ticksSinceEndermiteSpawn: Long): Float {
|
||||
return if (ticksSinceEndermiteSpawn < 300L)
|
||||
remapRange(ticksSinceEndermiteSpawn.toFloat(), (0F)..(300F), (0.2F)..(1F))
|
||||
remapRange(ticksSinceEndermiteSpawn.toFloat(), range(0F, 300F), range(0.2F, 1F))
|
||||
else
|
||||
1F
|
||||
}
|
||||
|
|
|
@ -188,7 +188,7 @@ enum class TerritoryType(
|
|||
}
|
||||
}
|
||||
|
||||
private object GeneratorDummy : ITerritoryGenerator {
|
||||
object GeneratorDummy : ITerritoryGenerator {
|
||||
override val segmentSize = Size(1)
|
||||
|
||||
override fun provide(world: SegmentedWorld): TerritoryGenerationInfo {
|
||||
|
|
|
@ -28,6 +28,7 @@ import chylex.hee.util.math.Pos
|
|||
import chylex.hee.util.math.ceilToInt
|
||||
import chylex.hee.util.math.directionTowards
|
||||
import chylex.hee.util.math.floorToInt
|
||||
import chylex.hee.util.math.range
|
||||
import chylex.hee.util.math.remapRange
|
||||
import chylex.hee.util.math.square
|
||||
import net.minecraft.entity.Entity
|
||||
|
@ -128,7 +129,7 @@ object TerritoryVoid {
|
|||
|
||||
private const val PLAYER_NEXT_DAMAGE_TIME_TAG = "VoidNextDamageTime"
|
||||
|
||||
private val FACTOR_DAMAGE_REMAP_FROM = (0.5F)..(3.0F)
|
||||
private val FACTOR_DAMAGE_REMAP_FROM = range(0.5F, 3F)
|
||||
private val DAMAGE = Damage(DEAL_CREATIVE, IGNORE_INVINCIBILITY())
|
||||
|
||||
fun onWorldTick(world: ServerWorld) {
|
||||
|
@ -157,10 +158,10 @@ object TerritoryVoid {
|
|||
val nextDamageTime = getLong(PLAYER_NEXT_DAMAGE_TIME_TAG)
|
||||
|
||||
if (currentTime >= nextDamageTime) {
|
||||
val amount = remapRange(factor, FACTOR_DAMAGE_REMAP_FROM, (2F)..(6F)).ceilToInt().toFloat()
|
||||
val amount = remapRange(factor, FACTOR_DAMAGE_REMAP_FROM, range(2F, 6F)).ceilToInt().toFloat()
|
||||
|
||||
if (DAMAGE.dealTo(amount, entity, TITLE_WITHER)) {
|
||||
val cooldown = min(30, remapRange(factor, FACTOR_DAMAGE_REMAP_FROM, (30F)..(6F)).floorToInt())
|
||||
val cooldown = min(30, remapRange(factor, FACTOR_DAMAGE_REMAP_FROM, range(30F, 6F)).floorToInt())
|
||||
putLong(PLAYER_NEXT_DAMAGE_TIME_TAG, currentTime + cooldown)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import chylex.hee.util.math.Size
|
|||
import chylex.hee.util.math.component1
|
||||
import chylex.hee.util.math.component2
|
||||
import chylex.hee.util.math.component3
|
||||
import chylex.hee.util.math.range
|
||||
import chylex.hee.util.math.remapRange
|
||||
import chylex.hee.util.math.square
|
||||
import chylex.hee.util.math.xz
|
||||
|
@ -121,9 +122,9 @@ object Generator_ForgottenTombs : ITerritoryGenerator {
|
|||
val noiseY = NoiseGenerator.OldPerlinNormalized(rand, scale = 48.0, octaves = 2)
|
||||
|
||||
for ((x, y, z) in BlockPos.ZERO.allInCenteredBoxMutable(RADIUS_XZ, RADIUS_Y, RADIUS_XZ)) {
|
||||
val normalizedY = remapRange(y.toFloat(), -radY..radY, 0F..1F)
|
||||
val normalizedY = remapRange(y.toFloat(), range(-radY, radY), range(0F, 1F))
|
||||
|
||||
val powerY = remapRange(sqrt(normalizedY), 0F..1F, (4.8F)..(1.6F))
|
||||
val powerY = remapRange(sqrt(normalizedY), range(0F, 1F), range(4.8F, 1.6F))
|
||||
val powerXZ = powerY * 0.8F
|
||||
|
||||
val corner = 1 + ((abs(x) + abs(z)) / (3F * radXZ)).pow(2F)
|
||||
|
|
|
@ -56,6 +56,7 @@ import chylex.hee.util.math.addY
|
|||
import chylex.hee.util.math.ceilToInt
|
||||
import chylex.hee.util.math.center
|
||||
import chylex.hee.util.math.floorToInt
|
||||
import chylex.hee.util.math.range
|
||||
import chylex.hee.util.math.remapRange
|
||||
import chylex.hee.util.math.scale
|
||||
import chylex.hee.util.math.scaleY
|
||||
|
@ -207,7 +208,7 @@ object Generator_LostGarden : ITerritoryGenerator {
|
|||
}
|
||||
|
||||
val edgeMpXZ = if (distRatioXZ > 0.86)
|
||||
remapRange(distRatioXZ.coerceAtMost(1.0), (0.86)..(1.0), (1.0)..(0.86 * noiseXZ.getRawValue(-x * 3, -z * 3)))
|
||||
remapRange(distRatioXZ.coerceAtMost(1.0), range(0.86F, 1F), range(1F, 0.86F * noiseXZ.getRawValue(-x * 3, -z * 3).toFloat()))
|
||||
else
|
||||
1.0
|
||||
|
||||
|
@ -217,10 +218,10 @@ object Generator_LostGarden : ITerritoryGenerator {
|
|||
}
|
||||
|
||||
val valueValley = 1.0 - noiseValley.getValue(x, z) {
|
||||
remap((0.5)..(1.0), (0.0)..(1.0))
|
||||
remap(range(0.5F, 1F), range(0F, 1F))
|
||||
coerce()
|
||||
redistribute(0.5)
|
||||
remap((0.0)..(0.75))
|
||||
remap(range(0F, 0.75F))
|
||||
|
||||
if (valueXZ < 0.6) {
|
||||
multiply(valueXZ / 0.6)
|
||||
|
@ -228,7 +229,7 @@ object Generator_LostGarden : ITerritoryGenerator {
|
|||
}
|
||||
|
||||
val valueThreshold = noiseThreshold.getValue(x, z) {
|
||||
remap((0.14)..(0.29))
|
||||
remap(range(0.14F, 0.29F))
|
||||
}
|
||||
|
||||
val valueTotalXZ = valueXZ * valueValley
|
||||
|
@ -236,7 +237,7 @@ object Generator_LostGarden : ITerritoryGenerator {
|
|||
val edgeMpY = (0.5 - (1.0 - edgeMpXZ))
|
||||
val endersolY = -0.125 + (0.575 * noiseEndersol.getValue(x, z) {
|
||||
if (value > 0.6) {
|
||||
remap((0.6)..(1.0), (0.6)..(5.0))
|
||||
remap(range(0.6F, 1F), range(0.6F, 5F))
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -276,20 +277,20 @@ object Generator_LostGarden : ITerritoryGenerator {
|
|||
|
||||
private fun NoiseValue.distanceReshapeXZ(distance: Double) {
|
||||
value = when (distance) {
|
||||
in (0.00)..(0.40) -> value * remapRange(distance, (0.0)..(0.4), (0.8)..(1.0))
|
||||
in (0.00)..(0.40) -> value * remapRange(distance, range(0F, 0.4F), range(0.8F, 1F))
|
||||
in (0.40)..(0.85) -> value
|
||||
in (0.85)..(1.00) -> value * remapRange(distance, (0.85)..(1.0), (1.0)..(0.0))
|
||||
in (0.85)..(1.00) -> value * remapRange(distance, range(0.85F, 1F), range(1F, 0F))
|
||||
else -> 0.0
|
||||
}
|
||||
}
|
||||
|
||||
private fun NoiseValue.distanceReshapeY(distance: Double) {
|
||||
value = when (distance) {
|
||||
in (-1.0)..(-0.6) -> value * square(remapRange(distance, (-1.0)..(-0.5), (0.0)..(1.0)))
|
||||
in (-1.0)..(-0.6) -> value * square(remapRange(distance, range(-1F, -0.5F), range(0F, 1F)))
|
||||
in (-0.6)..( 0.5) -> value
|
||||
in ( 0.5)..( 0.8) -> value * remapRange(distance, (0.5)..(0.8), (1.0)..(0.5))
|
||||
in ( 0.5)..( 0.8) -> value * remapRange(distance, range(0.5F, 0.8F), range(1F, 0.5F))
|
||||
in ( 0.8)..( 1.4) -> value * 0.5
|
||||
in ( 1.4)..( 2.0) -> value * remapRange(distance, (1.4)..(2.0), (0.5)..(0.1))
|
||||
in ( 1.4)..( 2.0) -> value * remapRange(distance, range(1.4F, 2F), range(0.5F, 0.1F))
|
||||
else -> 0.0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ import chylex.hee.util.math.Vec
|
|||
import chylex.hee.util.math.ceilToInt
|
||||
import chylex.hee.util.math.center
|
||||
import chylex.hee.util.math.directionTowards
|
||||
import chylex.hee.util.math.range
|
||||
import chylex.hee.util.math.remapRange
|
||||
import chylex.hee.util.math.square
|
||||
import chylex.hee.util.math.toRadians
|
||||
|
@ -414,7 +415,7 @@ object Generator_ObsidianTowers : ITerritoryGenerator {
|
|||
ENDIUM_ORES {
|
||||
override fun beforePillars(world: SegmentedWorld, rand: Random, island: Island) {
|
||||
val piles = if (island.radius >= 5.0)
|
||||
rand.nextRounded(remapRange(island.radius, (5.0)..(7.0), (2.0)..(4.0)).toFloat())
|
||||
rand.nextRounded(remapRange(island.radius, range(5F, 7F), range(2F, 4F)).toFloat())
|
||||
else
|
||||
1
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ import chylex.hee.util.math.addY
|
|||
import chylex.hee.util.math.ceilToInt
|
||||
import chylex.hee.util.math.center
|
||||
import chylex.hee.util.math.floorToInt
|
||||
import chylex.hee.util.math.range
|
||||
import chylex.hee.util.math.remapRange
|
||||
import chylex.hee.util.math.scale
|
||||
import chylex.hee.util.math.scaleY
|
||||
|
@ -128,7 +129,7 @@ object Generator_TheHub : ITerritoryGenerator {
|
|||
redistribute(0.4)
|
||||
|
||||
ifNonZero {
|
||||
remap((0.2)..(1.0))
|
||||
remap(range(0.2F, 1F))
|
||||
multiply(ELEVATION_BOTTOM)
|
||||
}
|
||||
}
|
||||
|
@ -154,7 +155,7 @@ object Generator_TheHub : ITerritoryGenerator {
|
|||
private fun NoiseValue.distanceReshape(distance: Double) {
|
||||
value = when (distance) {
|
||||
in (0.00)..(0.85) -> value
|
||||
in (0.85)..(1.00) -> value * remapRange(distance, (0.85)..(1.0), (1.0)..(0.0))
|
||||
in (0.85)..(1.00) -> value * remapRange(distance, range(0.85F, 1F), range(1F, 0F))
|
||||
else -> 0.0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -375,7 +375,7 @@ object ModBlocks {
|
|||
// Blocks: Utilities
|
||||
|
||||
@JvmField val ETERNAL_FIRE = BlockEternalFire(buildEternalFire) named "eternal_fire"
|
||||
@JvmField val SCAFFOLDING = BlockScaffolding(buildScaffolding) named "scaffolding"
|
||||
@JvmField val SCAFFOLDING = BlockScaffolding.create(buildScaffolding) named "scaffolding"
|
||||
|
||||
// Registry
|
||||
|
||||
|
|
|
@ -3,17 +3,12 @@ package chylex.hee.init
|
|||
import chylex.hee.HEE
|
||||
import chylex.hee.game.command.argument.EnumArgument
|
||||
import chylex.hee.game.command.argument.ValidatedStringArgument
|
||||
import chylex.hee.game.command.server.CommandDebugInstability
|
||||
import chylex.hee.game.command.server.CommandDebugStructure
|
||||
import chylex.hee.game.command.server.CommandDebugTerritory
|
||||
import chylex.hee.game.command.server.CommandDebugTestWorld
|
||||
import chylex.hee.game.command.server.CommandServerCausatum
|
||||
import chylex.hee.game.command.server.CommandServerHelp
|
||||
import chylex.hee.game.command.server.CommandServerInfusions
|
||||
import chylex.hee.game.command.server.CommandServerLootChest
|
||||
import chylex.hee.game.command.server.CommandServerPortalToken
|
||||
import chylex.hee.game.command.util.executes
|
||||
import chylex.hee.system.Debug
|
||||
import chylex.hee.util.forge.SubscribeAllEvents
|
||||
import chylex.hee.util.forge.SubscribeEvent
|
||||
import net.minecraft.command.Commands.literal
|
||||
|
@ -32,13 +27,7 @@ object ModCommands {
|
|||
CommandServerPortalToken
|
||||
)
|
||||
|
||||
val debug = if (Debug.enabled) listOf(
|
||||
CommandDebugInstability,
|
||||
CommandDebugStructure,
|
||||
CommandDebugTerritory,
|
||||
CommandDebugTestWorld
|
||||
)
|
||||
else emptyList()
|
||||
val debug = HEE.debugModule?.serverCommands.orEmpty()
|
||||
|
||||
init {
|
||||
ArgumentTypes.register("hee:enum", EnumArgument::class.java, EnumArgument.Serializer)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package chylex.hee.mixin;
|
||||
|
||||
import chylex.hee.HEE;
|
||||
import chylex.hee.client.util.MC;
|
||||
import chylex.hee.system.Debug;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.Minecraft.WorldSelectionType;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
@ -14,7 +14,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||
public abstract class HookUselessExperimentalWorldWarning { // UPDATE remove when https://github.com/MinecraftForge/MinecraftForge/pull/7275 is pulled
|
||||
@Inject(method = "deleteWorld", at = @At("HEAD"), cancellable = true)
|
||||
private void ignoreUselessWarning(final WorldSelectionType selectionType, final String worldName, final boolean customized, final Runnable runnable, final CallbackInfo ci) {
|
||||
if (Debug.enabled) {
|
||||
if (HEE.debug) {
|
||||
ci.cancel();
|
||||
MC.instance.enqueue(runnable);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package chylex.hee.network.client
|
||||
|
||||
import chylex.hee.HEE
|
||||
import chylex.hee.game.block.BlockDragonEggOverride
|
||||
import chylex.hee.game.block.BlockEnderGooPurified
|
||||
import chylex.hee.game.block.BlockPuzzleLogic
|
||||
|
@ -35,7 +36,6 @@ import chylex.hee.game.mechanics.table.TableParticleHandler
|
|||
import chylex.hee.game.potion.BanishmentEffect
|
||||
import chylex.hee.game.world.generation.feature.tombdungeon.piece.TombDungeonRoom_Tomb
|
||||
import chylex.hee.network.BaseClientPacket
|
||||
import chylex.hee.system.Debug
|
||||
import chylex.hee.util.forge.Side
|
||||
import chylex.hee.util.forge.Sided
|
||||
import io.netty.buffer.ByteBuf
|
||||
|
@ -114,7 +114,7 @@ class PacketClientFX<T : IFxData>() : BaseClientPacket() {
|
|||
val index = buffer.readByte().toInt()
|
||||
|
||||
if (index == -1) {
|
||||
if (Debug.enabled) {
|
||||
if (HEE.debug) {
|
||||
throw IndexOutOfBoundsException("could not find FX handler")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package chylex.hee.test.main
|
||||
|
||||
import chylex.hee.game.world.generation.structure.world.segments.ISegment
|
||||
import chylex.hee.game.world.generation.structure.world.segments.SegmentFull
|
||||
import chylex.hee.game.world.generation.structure.world.segments.SegmentMultiState
|
||||
import chylex.hee.game.world.util.allInBoxMutable
|
||||
import chylex.hee.util.math.Pos
|
||||
import chylex.hee.util.math.Size
|
||||
import net.minecraft.block.Blocks
|
||||
import net.minecraft.util.registry.Bootstrap
|
||||
|
||||
fun main() {
|
||||
println("Initializing...")
|
||||
Bootstrap.register()
|
||||
|
||||
val segments = mutableListOf<ISegment>()
|
||||
val thresholdField = SegmentMultiState::class.java.getDeclaredField("threshold").also { it.isAccessible = true }
|
||||
|
||||
println("Waiting 20 seconds for data fixers...")
|
||||
Thread.sleep(20000L)
|
||||
println("Waiting 4 seconds to start memory profiling...")
|
||||
Thread.sleep(4000L)
|
||||
|
||||
for (s in 8..128 step 12) {
|
||||
var segment: ISegment = SegmentMultiState(Size(s), Blocks.AIR).also(segments::add)
|
||||
val threshold = thresholdField.getInt(segment)
|
||||
|
||||
println("Testing size $s (total ${s * s * s} threshold $threshold)")
|
||||
|
||||
for ((index, pos) in Pos(0, 0, 0).allInBoxMutable(Pos(s - 1, s - 1, s - 1)).withIndex()) {
|
||||
if (index < threshold - 1) {
|
||||
segment = segment.withState(pos, Blocks.END_STONE.defaultState)
|
||||
continue
|
||||
}
|
||||
|
||||
check(segment is SegmentMultiState)
|
||||
segment = segment.withState(pos, Blocks.END_STONE.defaultState).also(segments::add)
|
||||
check(segment is SegmentFull)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
println("Done!")
|
||||
readLine()
|
||||
segments.toString()
|
||||
}
|
Loading…
Reference in New Issue