mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-13 05:27:37 +00:00
CNPC+ Debug Command for Energy Projectiles + Compile Fixes
This commit is contained in:
1 parent
744ffc5ab7
commit
d8bc3d4177
16 files changed
+438
-32
No files matched your search
@@ -0,0 +1,42 @@
|
||||
package kamkeel.npcs.client.command;
|
||||
|
||||
import kamkeel.npcs.util.CNPCDebug;
|
||||
import net.minecraft.command.CommandBase;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
|
||||
/**
|
||||
* Client-only command to toggle debug logging.
|
||||
* Registered via ClientCommandHandler so it runs entirely on the client
|
||||
* without sending a packet to the server.
|
||||
*/
|
||||
public class CommandCNPCDebugger extends CommandBase {
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return "cnpcdebugger";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandUsage(ICommandSender sender) {
|
||||
return "/cnpcdebugger <type> - Toggle client debug logging for a type (e.g. energy)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRequiredPermissionLevel() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processCommand(ICommandSender sender, String[] args) {
|
||||
if (args.length == 0) {
|
||||
sender.addChatMessage(new ChatComponentText("\u00A7cUsage: /cnpcdebugger <type>"));
|
||||
return;
|
||||
}
|
||||
|
||||
String type = args[0].toLowerCase();
|
||||
boolean newState = CNPCDebug.toggleClient(type);
|
||||
String stateText = newState ? "\u00A7aENABLED" : "\u00A7cDISABLED";
|
||||
sender.addChatMessage(new ChatComponentText("\u00A77[CNPC+] \u00A7eClient debug '" + type + "' " + stateText));
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@ public class CommandKamkeel extends CommandBase {
|
||||
registerCommand(new AuctionCommand());
|
||||
if (ConfigMain.AttributesEnabled)
|
||||
registerCommand(new AttributeCommand());
|
||||
registerCommand(new DebugCommand());
|
||||
}
|
||||
|
||||
public void registerCommand(CommandKamkeelBase command) {
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package kamkeel.npcs.command;
|
||||
|
||||
import kamkeel.npcs.util.CNPCDebug;
|
||||
import net.minecraft.command.CommandException;
|
||||
import net.minecraft.command.ICommandSender;
|
||||
|
||||
import static kamkeel.npcs.util.ColorUtil.sendResult;
|
||||
|
||||
public class DebugCommand extends CommandKamkeelBase {
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return "debug";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Toggle debug logging types";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage() {
|
||||
return "<type>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean runSubCommands() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processCommand(ICommandSender sender, String[] args) throws CommandException {
|
||||
if (args.length == 0) {
|
||||
throw new CommandException("Usage: /kam debug <type> (e.g. energy)");
|
||||
}
|
||||
|
||||
String type = args[0].toLowerCase();
|
||||
boolean newState = CNPCDebug.toggleServer(type);
|
||||
sendResult(sender, "Server debug '" + type + "' " + (newState ? "\u00A7aENABLED" : "\u00A7cDISABLED"));
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package kamkeel.npcs.entity;
|
||||
|
||||
import kamkeel.npcs.controllers.data.ability.util.AbilityTargetHelper;
|
||||
import kamkeel.npcs.controllers.data.ability.data.energy.EnergyBarrierData;
|
||||
import kamkeel.npcs.util.CNPCDebug;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
@@ -617,4 +618,31 @@ public abstract class EntityAbilityBarrier extends EntityEnergyAbility {
|
||||
this.dataWatcher.updateObject(DW_CHARGING, (byte) (charging ? 1 : 0));
|
||||
barrierData.readNBT(nbt);
|
||||
}
|
||||
|
||||
// ==================== DEBUG LOGGING ====================
|
||||
|
||||
/**
|
||||
* Debug log called every tick for barriers. Subclasses override debugLogBarrierExtra().
|
||||
*/
|
||||
protected void debugLogBarrierTick() {
|
||||
boolean isClient = worldObj.isRemote;
|
||||
if (isClient ? !CNPCDebug.isClientEnabled("energy") : !CNPCDebug.isServerEnabled("energy"))
|
||||
return;
|
||||
|
||||
String className = getClass().getSimpleName();
|
||||
String base = String.format("[%s id=%d tick=%d] pos=(%.2f,%.2f,%.2f) charging=%b health=%.1f",
|
||||
className, getEntityId(), ticksAlive,
|
||||
posX, posY, posZ, isCharging(), currentHealth);
|
||||
|
||||
String extra = debugLogBarrierExtra();
|
||||
String full = extra.isEmpty() ? base : base + " " + extra;
|
||||
CNPCDebug.log("energy", isClient, full);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclass hook for barrier-specific debug data.
|
||||
*/
|
||||
protected String debugLogBarrierExtra() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@ import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.util.AxisAlignedBB;
|
||||
import net.minecraft.util.Vec3;
|
||||
import net.minecraft.world.World;
|
||||
import noppes.npcs.LogWriter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -61,9 +60,6 @@ public class EntityAbilityBeam extends EntityEnergyProjectile {
|
||||
private int trailFadeTime = 20; // Ticks for trail to fully fade
|
||||
private List<Integer> trailPointAges = new ArrayList<>();
|
||||
|
||||
// Debug logging
|
||||
private static final boolean DEBUG_LOGGING = false;
|
||||
|
||||
public EntityAbilityBeam(World world) {
|
||||
super(world);
|
||||
}
|
||||
@@ -160,10 +156,6 @@ public class EntityAbilityBeam extends EntityEnergyProjectile {
|
||||
// Add initial trail point at origin (relative 0,0,0)
|
||||
trailPoints.add(Vec3.createVectorHelper(0, 0, 0));
|
||||
|
||||
if (DEBUG_LOGGING && !world.isRemote) {
|
||||
LogWriter.info("[Beam] Created at origin " + x + ", " + y + ", " + z + " maxDist=" + lifespan.maxDistance);
|
||||
}
|
||||
|
||||
// Calculate initial velocity toward target
|
||||
calculateInitialVelocity(owner, target, x, y, z);
|
||||
}
|
||||
@@ -222,11 +214,6 @@ public class EntityAbilityBeam extends EntityEnergyProjectile {
|
||||
trailPoints.add(Vec3.createVectorHelper(0, 0, 0));
|
||||
if (isFadingMode()) trailPointAges.add(0);
|
||||
|
||||
if (DEBUG_LOGGING && !worldObj.isRemote) {
|
||||
LogWriter.info("[Beam] startFiring: origin=(" + startX + "," + startY + "," + startZ +
|
||||
") headOffset=(" + headOffsetX + "," + headOffsetY + "," + headOffsetZ +
|
||||
") motion=(" + motionX + "," + motionY + "," + motionZ + ")");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -237,11 +224,7 @@ public class EntityAbilityBeam extends EntityEnergyProjectile {
|
||||
headOffsetY * headOffsetY +
|
||||
headOffsetZ * headOffsetZ
|
||||
);
|
||||
boolean exceeded = distFromOrigin >= getMaxDistance();
|
||||
if (exceeded && !worldObj.isRemote && DEBUG_LOGGING) {
|
||||
LogWriter.info("[Beam] DEAD: Max distance exceeded. dist=" + distFromOrigin + " max=" + getMaxDistance());
|
||||
}
|
||||
return exceeded;
|
||||
return distFromOrigin >= getMaxDistance();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -312,17 +295,6 @@ public class EntityAbilityBeam extends EntityEnergyProjectile {
|
||||
// Add trail point
|
||||
addTrailPoint();
|
||||
|
||||
// Debug log periodically
|
||||
if (DEBUG_LOGGING && ticksExisted % 20 == 0) {
|
||||
LogWriter.info("[Beam] Server tick=" + ticksExisted + " headOffset=(" +
|
||||
String.format("%.2f", headOffsetX) + "," +
|
||||
String.format("%.2f", headOffsetY) + "," +
|
||||
String.format("%.2f", headOffsetZ) + ") origin=(" +
|
||||
String.format("%.2f", startX) + "," +
|
||||
String.format("%.2f", startY) + "," +
|
||||
String.format("%.2f", startZ) + ") trail=" + getActiveTrailSize());
|
||||
}
|
||||
|
||||
// Skip collision checks on first few ticks
|
||||
if (ticksExisted > 2) {
|
||||
checkBlockCollision(headWorldX, headWorldY, headWorldZ);
|
||||
@@ -528,9 +500,27 @@ public class EntityAbilityBeam extends EntityEnergyProjectile {
|
||||
Math.max(prevHeadWorldZ, headZ) + hitSize
|
||||
);
|
||||
|
||||
if (processEntitiesInHitBox(hitBox, headX, headY, headZ) && DEBUG_LOGGING) {
|
||||
LogWriter.info("[Beam] DEAD: Entity collision at tick " + ticksExisted);
|
||||
}
|
||||
processEntitiesInHitBox(hitBox, headX, headY, headZ);
|
||||
}
|
||||
|
||||
// ==================== DEBUG ====================
|
||||
|
||||
@Override
|
||||
protected String debugLogExtra() {
|
||||
double headWorldX = startX + headOffsetX;
|
||||
double headWorldY = startY + headOffsetY;
|
||||
double headWorldZ = startZ + headOffsetZ;
|
||||
return String.format("headOff=(%.2f,%.2f,%.2f) prevHead=(%.2f,%.2f,%.2f) " +
|
||||
"origin=(%.2f,%.2f,%.2f) headWorld=(%.2f,%.2f,%.2f) " +
|
||||
"trail=%d mode=%s anchored=%b beamW=%.2f headSz=%.2f " +
|
||||
"motion=(%.3f,%.3f,%.3f)",
|
||||
headOffsetX, headOffsetY, headOffsetZ,
|
||||
prevHeadOffsetX, prevHeadOffsetY, prevHeadOffsetZ,
|
||||
startX, startY, startZ,
|
||||
headWorldX, headWorldY, headWorldZ,
|
||||
getActiveTrailSize(),
|
||||
beamMode.name(), isAnchoredMode(), beamWidth, headSize,
|
||||
motionX, motionY, motionZ);
|
||||
}
|
||||
|
||||
// ==================== GETTERS FOR RENDERER ====================
|
||||
|
||||
@@ -330,6 +330,17 @@ public class EntityAbilityDisc extends EntityEnergyProjectile {
|
||||
updateRotation();
|
||||
}
|
||||
|
||||
// ==================== DEBUG ====================
|
||||
|
||||
@Override
|
||||
protected String debugLogExtra() {
|
||||
return String.format("motion=(%.3f,%.3f,%.3f) radius=%.2f thickness=%.2f " +
|
||||
"boomerang=%b returning=%b vertical=%b ticksSinceMiss=%d",
|
||||
motionX, motionY, motionZ,
|
||||
discRadius, discThickness,
|
||||
boomerang, returning, vertical, ticksSinceMiss);
|
||||
}
|
||||
|
||||
// ==================== GETTERS ====================
|
||||
|
||||
public float getDiscRadius() {
|
||||
|
||||
@@ -122,6 +122,8 @@ public class EntityAbilityDome extends EntityAbilityBarrier {
|
||||
if (worldObj.isRemote && barrierData.meleeEnabled && !isCharging()) {
|
||||
adjustMeleeBoundingBox();
|
||||
}
|
||||
|
||||
debugLogBarrierTick();
|
||||
}
|
||||
|
||||
// ==================== INCOMING CHECK ====================
|
||||
@@ -548,6 +550,14 @@ public class EntityAbilityDome extends EntityAbilityBarrier {
|
||||
return surfaceDist * surfaceDist;
|
||||
}
|
||||
|
||||
// ==================== DEBUG ====================
|
||||
|
||||
@Override
|
||||
protected String debugLogBarrierExtra() {
|
||||
return String.format("radius=%.2f targetRadius=%.2f follow=%b",
|
||||
domeRadius, targetDomeRadius, followCaster);
|
||||
}
|
||||
|
||||
// ==================== GETTERS ====================
|
||||
|
||||
public float getDomeRadius() {
|
||||
|
||||
@@ -624,6 +624,17 @@ public class EntityAbilityLaser extends EntityEnergyProjectile {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// ==================== DEBUG ====================
|
||||
|
||||
@Override
|
||||
protected String debugLogExtra() {
|
||||
return String.format("dir=(%.3f,%.3f,%.3f) desired=%.2f current=%.2f max=%.2f " +
|
||||
"fullyExtended=%b end=(%.2f,%.2f,%.2f) width=%.2f expSpd=%.2f origin=(%.2f,%.2f,%.2f)",
|
||||
dirX, dirY, dirZ, desiredLength, currentLength, maxLength,
|
||||
fullyExtended, endX, endY, endZ, laserWidth, expansionSpeed,
|
||||
startX, startY, startZ);
|
||||
}
|
||||
|
||||
// ==================== GETTERS / SETTERS ====================
|
||||
|
||||
public float getLaserWidth() {
|
||||
|
||||
@@ -150,6 +150,16 @@ public class EntityAbilityOrb extends EntityEnergyProjectile {
|
||||
processEntitiesInHitBox(hitBox, nextX, nextY, nextZ);
|
||||
}
|
||||
|
||||
// ==================== DEBUG ====================
|
||||
|
||||
@Override
|
||||
protected String debugLogExtra() {
|
||||
return String.format("motion=(%.3f,%.3f,%.3f) homing=%b start=(%.2f,%.2f,%.2f)",
|
||||
motionX, motionY, motionZ,
|
||||
homingData != null && homingData.isHoming(),
|
||||
startX, startY, startZ);
|
||||
}
|
||||
|
||||
// ==================== GETTERS ====================
|
||||
|
||||
// Legacy getter for renderer compatibility
|
||||
|
||||
@@ -143,6 +143,8 @@ public class EntityAbilityPanel extends EntityAbilityBarrier {
|
||||
// Stationary, no update needed
|
||||
break;
|
||||
}
|
||||
|
||||
debugLogBarrierTick();
|
||||
}
|
||||
|
||||
private void updateHeld() {
|
||||
@@ -548,6 +550,14 @@ public class EntityAbilityPanel extends EntityAbilityBarrier {
|
||||
return df * df + dr * dr + du * du;
|
||||
}
|
||||
|
||||
// ==================== DEBUG ====================
|
||||
|
||||
@Override
|
||||
protected String debugLogBarrierExtra() {
|
||||
return String.format("mode=%s yaw=%.1f w=%.2f h=%.2f",
|
||||
mode.name(), panelYaw, panelData.panelWidth, panelData.panelHeight);
|
||||
}
|
||||
|
||||
// ==================== GETTERS ====================
|
||||
|
||||
public PanelMode getMode() {
|
||||
|
||||
@@ -3,6 +3,7 @@ package kamkeel.npcs.entity;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import kamkeel.npcs.controllers.data.ability.data.energy.EnergyDisplayData;
|
||||
import kamkeel.npcs.util.CNPCDebug;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
@@ -168,6 +169,19 @@ public class EntityAbilitySweeper extends EntityEnergyAbility {
|
||||
if (!worldObj.isRemote) {
|
||||
handleDamage(owner);
|
||||
}
|
||||
|
||||
// Debug logging
|
||||
{
|
||||
boolean isClient = worldObj.isRemote;
|
||||
if (isClient ? CNPCDebug.isClientEnabled("energy") : CNPCDebug.isServerEnabled("energy")) {
|
||||
CNPCDebug.log("energy", isClient, String.format(
|
||||
"[Sweeper id=%d tick=%d] pos=(%.2f,%.2f,%.2f) angle=%.1f prevAngle=%.1f " +
|
||||
"speed=%.1f rotations=%d/%d length=%.2f width=%.2f",
|
||||
getEntityId(), ticksExisted, posX, posY, posZ,
|
||||
currentAngle, prevAngle, sweepSpeed,
|
||||
completedRotations, numberOfRotations, beamLength, beamWidth));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,6 +4,7 @@ import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import kamkeel.npcs.controllers.data.ability.data.energy.EnergyDisplayData;
|
||||
import kamkeel.npcs.controllers.data.ability.data.energy.EnergyLightningData;
|
||||
import kamkeel.npcs.util.CNPCDebug;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.MathHelper;
|
||||
import net.minecraft.world.World;
|
||||
@@ -57,6 +58,17 @@ public class EntityEnergyExplosion extends EntityEnergyAbility {
|
||||
float eased = 1.0f - (1.0f - progress) * (1.0f - progress);
|
||||
this.renderRadius = maxRadius * eased;
|
||||
|
||||
// Debug logging
|
||||
{
|
||||
boolean isClient = worldObj.isRemote;
|
||||
if (isClient ? CNPCDebug.isClientEnabled("energy") : CNPCDebug.isServerEnabled("energy")) {
|
||||
CNPCDebug.log("energy", isClient, String.format(
|
||||
"[Explosion id=%d tick=%d] pos=(%.2f,%.2f,%.2f) renderRadius=%.2f maxRadius=%.2f progress=%.2f",
|
||||
getEntityId(), ticksExisted, posX, posY, posZ,
|
||||
renderRadius, maxRadius, getLifeProgress(0f)));
|
||||
}
|
||||
}
|
||||
|
||||
if (ticksExisted >= durationTicks) {
|
||||
setDead();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import kamkeel.npcs.controllers.data.ability.data.energy.EnergyLightningData;
|
||||
import kamkeel.npcs.network.packets.data.energy.ProjectileReflectPacket;
|
||||
import kamkeel.npcs.network.packets.data.energyexplosion.EnergyExplosionSpawnPacket;
|
||||
import kamkeel.npcs.util.AnchorPointHelper;
|
||||
import kamkeel.npcs.util.CNPCDebug;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.entity.Entity;
|
||||
@@ -334,6 +335,8 @@ public abstract class EntityEnergyProjectile extends EntityEnergyAbility {
|
||||
if (!previewMode && !worldObj.isRemote) {
|
||||
EventHooks.onEnergyProjectileTick(this);
|
||||
}
|
||||
|
||||
debugLogTick();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -349,6 +352,53 @@ public abstract class EntityEnergyProjectile extends EntityEnergyAbility {
|
||||
if (this.rotationValZ > 360.0f) this.rotationValZ -= 360.0f;
|
||||
}
|
||||
|
||||
// ==================== DEBUG LOGGING ====================
|
||||
|
||||
/**
|
||||
* Debug log called every tick. Logs position/size/charging state.
|
||||
* Subclasses override debugLogExtra() for type-specific data.
|
||||
*/
|
||||
protected void debugLogTick() {
|
||||
boolean isClient = worldObj.isRemote;
|
||||
if (isClient ? !CNPCDebug.isClientEnabled("energy") : !CNPCDebug.isServerEnabled("energy"))
|
||||
return;
|
||||
|
||||
String className = getClass().getSimpleName();
|
||||
boolean dwCharging = isCharging(); // DataWatcher value (what client sees)
|
||||
boolean localCharging = this.charging; // Local field (server truth)
|
||||
|
||||
String base = String.format("[%s id=%d tick=%d] pos=(%.2f,%.2f,%.2f) prev=(%.2f,%.2f,%.2f) " +
|
||||
"size=%.3f renderSize=%.3f prevRenderSize=%.3f " +
|
||||
"charging(dw)=%b charging(local)=%b chargeTick=%d/%d chargeProgress=%.3f",
|
||||
className, getEntityId(), ticksExisted,
|
||||
posX, posY, posZ, prevPosX, prevPosY, prevPosZ,
|
||||
size, renderCurrentSize, prevRenderSize,
|
||||
dwCharging, localCharging, chargeTick, chargeDuration, getChargeProgress());
|
||||
|
||||
// Flag mismatch between DataWatcher and local field
|
||||
if (dwCharging != localCharging) {
|
||||
base += " !!CHARGE_MISMATCH!!";
|
||||
}
|
||||
|
||||
// Client interpolation state (only meaningful on client)
|
||||
if (isClient) {
|
||||
base += String.format(" interp(steps=%d target=(%.2f,%.2f,%.2f))",
|
||||
interpSteps, interpTargetX, interpTargetY, interpTargetZ);
|
||||
}
|
||||
|
||||
String extra = debugLogExtra();
|
||||
String full = extra.isEmpty() ? base : base + " " + extra;
|
||||
CNPCDebug.log("energy", isClient, full);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclass hook for type-specific debug data.
|
||||
* Return empty string if nothing extra to log.
|
||||
*/
|
||||
protected String debugLogExtra() {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if projectile has exceeded max distance.
|
||||
*
|
||||
|
||||
@@ -192,6 +192,14 @@ public class EntityEnergySlicer extends EntityEnergyProjectile {
|
||||
return lastTravelPitch;
|
||||
}
|
||||
|
||||
// ==================== DEBUG ====================
|
||||
|
||||
@Override
|
||||
protected String debugLogExtra() {
|
||||
return String.format("motion=(%.3f,%.3f,%.3f) sliceW=%.2f sliceT=%.2f",
|
||||
motionX, motionY, motionZ, sliceWidth, sliceThickness);
|
||||
}
|
||||
|
||||
// ==================== GETTERS ====================
|
||||
|
||||
public float getSliceWidth() {
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
package kamkeel.npcs.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.StreamHandler;
|
||||
|
||||
/**
|
||||
* Debug logging system for CNPC+ entities.
|
||||
* Writes to logs/cnpc_debug/[type]_[side].log (file only, no console output).
|
||||
* Toggle at runtime via /cnpcdebugger [type] (client) or /kam debug [type] (server).
|
||||
*/
|
||||
public class CNPCDebug {
|
||||
|
||||
private static final String DIR = "logs/cnpc_debug";
|
||||
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("HH:mm:ss");
|
||||
|
||||
// Runtime toggle state per type, separate for client and server
|
||||
private static final Map<String, Boolean> serverToggles = new ConcurrentHashMap<>();
|
||||
private static final Map<String, Boolean> clientToggles = new ConcurrentHashMap<>();
|
||||
|
||||
// Per-type file handlers (lazily initialized)
|
||||
private static final Map<String, Handler> serverHandlers = new ConcurrentHashMap<>();
|
||||
private static final Map<String, Handler> clientHandlers = new ConcurrentHashMap<>();
|
||||
|
||||
// ==================== TOGGLE API ====================
|
||||
|
||||
/**
|
||||
* Toggle server-side debug for given type. Returns new state.
|
||||
*/
|
||||
public static boolean toggleServer(String type) {
|
||||
type = type.toLowerCase();
|
||||
boolean newState = !isServerEnabled(type);
|
||||
serverToggles.put(type, newState);
|
||||
if (newState) {
|
||||
ensureHandler(type, false);
|
||||
}
|
||||
return newState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle client-side debug for given type. Returns new state.
|
||||
*/
|
||||
public static boolean toggleClient(String type) {
|
||||
type = type.toLowerCase();
|
||||
boolean newState = !isClientEnabled(type);
|
||||
clientToggles.put(type, newState);
|
||||
if (newState) {
|
||||
ensureHandler(type, true);
|
||||
}
|
||||
return newState;
|
||||
}
|
||||
|
||||
public static boolean isServerEnabled(String type) {
|
||||
Boolean val = serverToggles.get(type.toLowerCase());
|
||||
return val != null && val;
|
||||
}
|
||||
|
||||
public static boolean isClientEnabled(String type) {
|
||||
Boolean val = clientToggles.get(type.toLowerCase());
|
||||
return val != null && val;
|
||||
}
|
||||
|
||||
// ==================== LOGGING API ====================
|
||||
|
||||
/**
|
||||
* Log a debug message for the given type on the given side.
|
||||
* Callers should guard with isServerEnabled/isClientEnabled for performance.
|
||||
*/
|
||||
public static void log(String type, boolean client, String msg) {
|
||||
type = type.toLowerCase();
|
||||
Map<String, Boolean> toggles = client ? clientToggles : serverToggles;
|
||||
Boolean enabled = toggles.get(type);
|
||||
if (enabled == null || !enabled) return;
|
||||
|
||||
Handler handler = ensureHandler(type, client);
|
||||
if (handler == null) return;
|
||||
|
||||
String side = client ? "CLIENT" : "SERVER";
|
||||
String timestamp;
|
||||
synchronized (DATE_FORMAT) {
|
||||
timestamp = DATE_FORMAT.format(new Date());
|
||||
}
|
||||
String formatted = "[" + timestamp + "][" + side + "][DEBUG-" + type.toUpperCase() + "] " + msg + System.lineSeparator();
|
||||
|
||||
LogRecord record = new LogRecord(Level.INFO, formatted);
|
||||
handler.publish(record);
|
||||
handler.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Log on server side.
|
||||
*/
|
||||
public static void logServer(String type, String msg) {
|
||||
log(type, false, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log on client side.
|
||||
*/
|
||||
public static void logClient(String type, String msg) {
|
||||
log(type, true, msg);
|
||||
}
|
||||
|
||||
// ==================== INTERNALS ====================
|
||||
|
||||
private static Handler ensureHandler(String type, boolean client) {
|
||||
Map<String, Handler> handlers = client ? clientHandlers : serverHandlers;
|
||||
Handler existing = handlers.get(type);
|
||||
if (existing != null) return existing;
|
||||
|
||||
synchronized (CNPCDebug.class) {
|
||||
existing = handlers.get(type);
|
||||
if (existing != null) return existing;
|
||||
|
||||
try {
|
||||
File dir = new File(DIR);
|
||||
if (!dir.exists()) dir.mkdirs();
|
||||
|
||||
String side = client ? "client" : "server";
|
||||
File file = new File(dir, type + "_" + side + ".log");
|
||||
|
||||
// Rotate old log
|
||||
if (file.exists()) {
|
||||
File backup = new File(dir, type + "_" + side + "-prev.log");
|
||||
if (backup.exists()) backup.delete();
|
||||
file.renameTo(backup);
|
||||
}
|
||||
|
||||
Handler handler = new StreamHandler(new FileOutputStream(file), new Formatter() {
|
||||
@Override
|
||||
public String format(LogRecord record) {
|
||||
return record.getMessage();
|
||||
}
|
||||
});
|
||||
handler.setLevel(Level.ALL);
|
||||
handlers.put(type, handler);
|
||||
|
||||
// Log header
|
||||
String timestamp;
|
||||
synchronized (DATE_FORMAT) {
|
||||
timestamp = DATE_FORMAT.format(new Date());
|
||||
}
|
||||
LogRecord header = new LogRecord(Level.INFO,
|
||||
"[" + timestamp + "][" + (client ? "CLIENT" : "SERVER") + "][DEBUG-" + type.toUpperCase() + "] Debug logging started" + System.lineSeparator());
|
||||
handler.publish(header);
|
||||
handler.flush();
|
||||
|
||||
return handler;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import cpw.mods.fml.client.registry.RenderingRegistry;
|
||||
import cpw.mods.fml.common.FMLCommonHandler;
|
||||
import cpw.mods.fml.common.ObfuscationReflectionHelper;
|
||||
import kamkeel.npcs.addon.client.DBCClient;
|
||||
import kamkeel.npcs.client.command.CommandCNPCDebugger;
|
||||
import kamkeel.npcs.client.renderer.RenderAbilityBeam;
|
||||
import kamkeel.npcs.client.renderer.RenderAbilityDisc;
|
||||
import kamkeel.npcs.client.renderer.RenderAbilityLaser;
|
||||
@@ -53,6 +54,7 @@ import net.minecraft.util.ChatComponentText;
|
||||
import net.minecraft.util.ReportedException;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.client.ClientCommandHandler;
|
||||
import net.minecraftforge.client.MinecraftForgeClient;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.common.util.FakePlayer;
|
||||
@@ -360,6 +362,9 @@ public class ClientProxy extends CommonProxy {
|
||||
ClientTagMapController.Instance = new ClientTagMapController();
|
||||
MinecraftForge.EVENT_BUS.register(new ClientEventHandler());
|
||||
|
||||
// Debug commands
|
||||
ClientCommandHandler.instance.registerCommand(new CommandCNPCDebugger());
|
||||
|
||||
// Telegraph rendering system
|
||||
TelegraphManager.initClient();
|
||||
MinecraftForge.EVENT_BUS.register(new TelegraphRenderer());
|
||||
|
||||
Reference in new issue
Block a user