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

Move debug utilities to a separate module

This commit is contained in:
chylex 2021-09-05 04:23:35 +02:00
parent 7565443e38
commit e0c3ed6bc3
Signed by: chylex
GPG Key ID: 4DE42C8F19A80548
33 changed files with 504 additions and 378 deletions

View File

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

View File

@ -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") {

View File

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

View File

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

View File

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

View File

@ -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")
}
}
}
}

View File

@ -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)}")
}
}
}
}

View File

@ -0,0 +1,72 @@
package chylex.hee.debug
import chylex.hee.HEE
import chylex.hee.client.BuildStick
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(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

@ -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()
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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"))
}

View File

@ -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")
}

View File

@ -6,7 +6,6 @@ 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
@ -32,7 +31,7 @@ open class SegmentedWorld(override val rand: Random, val worldSize: Size, privat
if (!isInside(pos)) {
HEE.log.warn("[SegmentedWorld] attempted to access position outside bounds: $pos is outside $worldSize")
if (Debug.enabled) {
if (HEE.debug) {
Thread.dumpStack()
}

View File

@ -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()
}
}

View File

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

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 (Debug.enabled) {
if (HEE.debug) {
HEE.log.info("[MinecraftForgeEventBus] registering ${listener.parameterTypes.firstOrNull()?.name?.substringAfterLast('.')} for ${item.javaClass.simpleName}")
}

View File

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

View File

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

View File

@ -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
@ -36,7 +35,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
@ -159,12 +157,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 +178,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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
}

View File

@ -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")
}
}