From 3a8b75f152b68f8e2a8bea85f7c8811e36f70da8 Mon Sep 17 00:00:00 2001 From: Kam Date: Fri, 13 Mar 2026 21:10:30 -0400 Subject: [PATCH] Another MEGA COMMIT to Core Structure --- .../ability/conditions/ConditionFilter.java | 37 ++ .../data/ability/data/ProjectileData.java | 66 +++ .../ability/data/energy/EnergyAnchorData.java | 6 +- .../data/energy/EnergyBarrierData.java | 21 +- .../data/energy/EnergyChargingData.java | 6 +- .../ability/data/energy/EnergyCombatData.java | 6 +- .../data/energy/EnergyDisplayData.java | 6 +- .../ability/data/energy/EnergyHomingData.java | 7 +- .../data/energy/EnergyLifespanData.java | 6 +- .../data/energy/EnergyLightningData.java | 6 +- .../ability/data/energy/EnergyPanelData.java | 6 +- .../data/profile/ProfileOperation.java | 31 ++ .../npcs/controllers/data/profile/Slot.java | 115 ++++ .../controllers/data/telegraph/Telegraph.java | 9 +- .../kamkeel/npcs/developer/Developer.java | 42 ++ .../npcs/network/enums/EnumChannelType.java | 8 + .../network/enums/EnumConfigOperation.java | 5 + .../npcs/network/enums/EnumDataPacket.java | 91 +++ .../network/enums/EnumItemPacketType.java | 14 + .../npcs/network/enums/EnumPlayerPacket.java | 45 ++ .../npcs/network/enums/EnumRequestPacket.java | 233 ++++++++ .../network/enums/EnumSoundOperation.java | 12 + .../npcs/network/enums/EnumSyncAction.java | 7 + .../npcs/network/enums/EnumSyncType.java | 18 + .../java/kamkeel/npcs/util/CNPCDebug.java | 163 ++++++ core/src/main/java/noppes/npcs/NBTTags.java | 522 ++++++++++++++++++ .../noppes/npcs/controllers/APIRegistry.java | 25 + .../npcs/controllers/CategoryManager.java | 255 +++++++++ .../npcs/controllers/FactionController.java | 228 ++++++++ .../controllers/GlobalDataController.java | 85 +++ .../npcs/controllers/MagicController.java | 384 +++++++++++++ .../controllers/ServerTagMapController.java | 114 ++++ .../npcs/controllers/TagController.java | 255 +++++++++ .../npcs/controllers/TransportController.java | 257 +++++++++ .../noppes/npcs/controllers/data/Faction.java | 164 ++++++ .../noppes/npcs/controllers/data/Magic.java | 155 ++++++ .../npcs/controllers/data/PlayerEffect.java | 83 +++ .../controllers/data/PlayerEffectData.java | 28 +- .../scripted/constants/AnimationType.java | 10 + .../npcs/scripted/constants/EntityType.java | 27 + .../npcs/scripted/constants/JobType.java | 13 + .../npcs/scripted/constants/RoleType.java | 11 + .../npcs/platform/annotation/ClientOnly.java | 22 + .../npcs/platform/annotation/ServerOnly.java | 17 + .../entity/IPlatformDamageSource.java | 25 + .../npcs/platform/entity/IPlatformEntity.java | 58 ++ .../npcs/platform/entity/IPlatformLiving.java | 22 + .../npcs/platform/entity/IPlatformPlayer.java | 36 ++ .../npcs/platform/entity/IPlatformStack.java | 50 ++ .../npcs/platform/entity/IPlatformWorld.java | 33 ++ .../api/ability/data/IEnergyAnchorData.java | 40 ++ .../api/ability/data/IEnergyCombatData.java | 43 ++ .../api/ability/data/IEnergyDisplayData.java | 49 ++ .../api/ability/data/IEnergyHomingData.java | 31 ++ .../api/ability/data/IEnergyLifespanData.java | 19 + .../ability/data/IEnergyLightningData.java | 31 ++ .../npcs/api/handler/data/IPlayerEffect.java | 37 ++ .../noppes/npcs/api/handler/data/ISlot.java | 29 + .../noppes/npcs/platform/PlatformService.java | 66 +++ .../npcs/controllers/TelegraphController.java | 5 +- .../data/ability/data/ProjectileData.java | 5 +- .../data/ability/type/AbilityZone.java | 5 +- .../ability/type/energy/AbilityBarrier.java | 5 +- .../ability/type/energy/AbilityEnergy.java | 9 +- .../type/energy/AbilityEnergyProjectile.java | 13 +- .../data/ability/type/energy/AbilityWall.java | 5 +- .../data/telegraph/TelegraphInstance.java | 5 +- .../npcs/entity/EntityEnergyAbility.java | 8 +- .../npcs/entity/EntityEnergyBarrier.java | 5 +- .../npcs/entity/EntityEnergyPanel.java | 5 +- .../npcs/entity/EntityEnergyProjectile.java | 17 +- .../platform/MC1710PlatformDamageSource.java | 34 ++ .../platform/MC1710PlatformEntity.java | 73 +++ .../platform/MC1710PlatformLiving.java | 41 ++ .../platform/MC1710PlatformPlayer.java | 47 ++ .../wrapper/platform/MC1710PlatformStack.java | 75 +++ .../wrapper/platform/MC1710PlatformWorld.java | 41 ++ .../npcs/controllers/data/PlayerData.java | 10 +- .../npcs/wrapper/MC1710PlatformService.java | 55 ++ 79 files changed, 4557 insertions(+), 96 deletions(-) create mode 100644 core/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/ConditionFilter.java create mode 100644 core/src/main/java/kamkeel/npcs/controllers/data/ability/data/ProjectileData.java rename {src => core/src}/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyAnchorData.java (96%) rename {src => core/src}/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyBarrierData.java (93%) rename {src => core/src}/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyChargingData.java (94%) rename {src => core/src}/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyCombatData.java (97%) rename {src => core/src}/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyDisplayData.java (96%) rename {src => core/src}/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyHomingData.java (94%) rename {src => core/src}/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyLifespanData.java (92%) rename {src => core/src}/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyLightningData.java (95%) rename {src => core/src}/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyPanelData.java (96%) create mode 100644 core/src/main/java/kamkeel/npcs/controllers/data/profile/ProfileOperation.java create mode 100644 core/src/main/java/kamkeel/npcs/controllers/data/profile/Slot.java rename {src => core/src}/main/java/kamkeel/npcs/controllers/data/telegraph/Telegraph.java (97%) create mode 100644 core/src/main/java/kamkeel/npcs/developer/Developer.java create mode 100644 core/src/main/java/kamkeel/npcs/network/enums/EnumChannelType.java create mode 100644 core/src/main/java/kamkeel/npcs/network/enums/EnumConfigOperation.java create mode 100644 core/src/main/java/kamkeel/npcs/network/enums/EnumDataPacket.java create mode 100644 core/src/main/java/kamkeel/npcs/network/enums/EnumItemPacketType.java create mode 100644 core/src/main/java/kamkeel/npcs/network/enums/EnumPlayerPacket.java create mode 100644 core/src/main/java/kamkeel/npcs/network/enums/EnumRequestPacket.java create mode 100644 core/src/main/java/kamkeel/npcs/network/enums/EnumSoundOperation.java create mode 100644 core/src/main/java/kamkeel/npcs/network/enums/EnumSyncAction.java create mode 100644 core/src/main/java/kamkeel/npcs/network/enums/EnumSyncType.java create mode 100644 core/src/main/java/kamkeel/npcs/util/CNPCDebug.java create mode 100644 core/src/main/java/noppes/npcs/NBTTags.java create mode 100644 core/src/main/java/noppes/npcs/controllers/APIRegistry.java create mode 100644 core/src/main/java/noppes/npcs/controllers/CategoryManager.java create mode 100644 core/src/main/java/noppes/npcs/controllers/FactionController.java create mode 100644 core/src/main/java/noppes/npcs/controllers/GlobalDataController.java create mode 100644 core/src/main/java/noppes/npcs/controllers/MagicController.java create mode 100644 core/src/main/java/noppes/npcs/controllers/ServerTagMapController.java create mode 100644 core/src/main/java/noppes/npcs/controllers/TagController.java create mode 100644 core/src/main/java/noppes/npcs/controllers/TransportController.java create mode 100644 core/src/main/java/noppes/npcs/controllers/data/Faction.java create mode 100644 core/src/main/java/noppes/npcs/controllers/data/Magic.java create mode 100644 core/src/main/java/noppes/npcs/controllers/data/PlayerEffect.java rename {src => core/src}/main/java/noppes/npcs/controllers/data/PlayerEffectData.java (77%) create mode 100644 core/src/main/java/noppes/npcs/scripted/constants/AnimationType.java create mode 100644 core/src/main/java/noppes/npcs/scripted/constants/EntityType.java create mode 100644 core/src/main/java/noppes/npcs/scripted/constants/JobType.java create mode 100644 core/src/main/java/noppes/npcs/scripted/constants/RoleType.java create mode 100644 platform-api/src/main/java/kamkeel/npcs/platform/annotation/ClientOnly.java create mode 100644 platform-api/src/main/java/kamkeel/npcs/platform/annotation/ServerOnly.java create mode 100644 platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformDamageSource.java create mode 100644 platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformEntity.java create mode 100644 platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformLiving.java create mode 100644 platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformPlayer.java create mode 100644 platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformStack.java create mode 100644 platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformWorld.java create mode 100644 platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyAnchorData.java create mode 100644 platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyCombatData.java create mode 100644 platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyDisplayData.java create mode 100644 platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyHomingData.java create mode 100644 platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyLifespanData.java create mode 100644 platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyLightningData.java create mode 100644 platform-api/src/main/java/noppes/npcs/api/handler/data/IPlayerEffect.java create mode 100644 platform-api/src/main/java/noppes/npcs/api/handler/data/ISlot.java create mode 100644 src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformDamageSource.java create mode 100644 src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformEntity.java create mode 100644 src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformLiving.java create mode 100644 src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformPlayer.java create mode 100644 src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformStack.java create mode 100644 src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformWorld.java diff --git a/core/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/ConditionFilter.java b/core/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/ConditionFilter.java new file mode 100644 index 000000000..08c5b5da2 --- /dev/null +++ b/core/src/main/java/kamkeel/npcs/controllers/data/ability/conditions/ConditionFilter.java @@ -0,0 +1,37 @@ +package kamkeel.npcs.controllers.data.ability.conditions; + +public enum ConditionFilter { + CASTER, + TARGET, + BOTH; + + public boolean checksCaster() { + return this == CASTER || this == BOTH; + } + + public boolean checksTarget() { + return this == TARGET || this == BOTH; + } + + public static ConditionFilter fromOrdinal(int ordinal) { + ConditionFilter[] values = values(); + if (ordinal >= 0 && ordinal < values.length) { + return values[ordinal]; + } + return BOTH; + } + + @Override + public String toString() { + switch (this) { + case BOTH: + return "condition.filter.both"; + case CASTER: + return "condition.filter.caster"; + case TARGET: + return "condition.filter.target"; + default: + return name(); + } + } +} diff --git a/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/ProjectileData.java b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/ProjectileData.java new file mode 100644 index 000000000..382d0a8ac --- /dev/null +++ b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/ProjectileData.java @@ -0,0 +1,66 @@ +package kamkeel.npcs.controllers.data.ability.data; + +import kamkeel.npcs.controllers.data.ability.enums.AnchorPoint; +import kamkeel.npcs.controllers.data.ability.data.energy.EnergyAnchorData; +import kamkeel.npcs.controllers.data.ability.data.energy.EnergyDisplayData; +import noppes.npcs.platform.nbt.INBTCompound; + +/** + * Per-projectile data: anchor point + optional color override. + * All projectiles share the primary EnergyDisplayData; this class + * allows individual projectiles to override just the inner/outer colors. + */ +public class ProjectileData { + public EnergyAnchorData anchor; + public boolean colorOverride = false; + public int innerColor = 0xFFFFFF; + public int outerColor = 0x8888FF; + + public ProjectileData(AnchorPoint defaultAnchor) { + this.anchor = new EnergyAnchorData(defaultAnchor); + } + + /** + * Returns the display data to use for this projectile. + * If colorOverride is false, returns the primary display data directly. + * If colorOverride is true, returns a copy with overridden inner/outer colors. + */ + public EnergyDisplayData resolveDisplay(EnergyDisplayData primary) { + // Always return a copy so entity mutations never bleed back into the ability template. + EnergyDisplayData resolved = primary.copy(); + if (colorOverride) { + resolved.innerColor = this.innerColor; + resolved.outerColor = this.outerColor; + } + return resolved; + } + + public void writeNBT(INBTCompound nbt) { + // OLD: anchor.writeNBT(new MC1710NBTCompound(nbt)); + anchor.writeNBT(nbt); + nbt.setBoolean("colorOverride", colorOverride); + if (colorOverride) { + nbt.setInteger("overrideInnerColor", innerColor); + nbt.setInteger("overrideOuterColor", outerColor); + } + } + + public void readNBT(INBTCompound nbt) { + // OLD: anchor.readNBT(new MC1710NBTCompound(nbt)); + anchor.readNBT(nbt); + colorOverride = nbt.getBoolean("colorOverride"); + if (colorOverride) { + innerColor = nbt.getInteger("overrideInnerColor"); + outerColor = nbt.getInteger("overrideOuterColor"); + } + } + + public ProjectileData copy() { + ProjectileData copy = new ProjectileData(anchor.anchorPoint); + copy.anchor = anchor.copy(); + copy.colorOverride = colorOverride; + copy.innerColor = innerColor; + copy.outerColor = outerColor; + return copy; + } +} diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyAnchorData.java b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyAnchorData.java similarity index 96% rename from src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyAnchorData.java rename to core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyAnchorData.java index f618ae3f7..f354b6666 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyAnchorData.java +++ b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyAnchorData.java @@ -1,8 +1,8 @@ package kamkeel.npcs.controllers.data.ability.data.energy; import kamkeel.npcs.controllers.data.ability.enums.AnchorPoint; -import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.api.ability.data.IEnergyAnchorData; +import noppes.npcs.platform.nbt.INBTCompound; public class EnergyAnchorData implements IEnergyAnchorData { public AnchorPoint anchorPoint = AnchorPoint.FRONT; @@ -94,7 +94,7 @@ public class EnergyAnchorData implements IEnergyAnchorData { this.launchFromAnchor = launchFromAnchor; } - public void writeNBT(NBTTagCompound nbt) { + public void writeNBT(INBTCompound nbt) { nbt.setInteger("anchorPoint", anchorPoint.ordinal()); nbt.setFloat("anchorOffsetX", anchorOffsetX); nbt.setFloat("anchorOffsetY", anchorOffsetY); @@ -102,7 +102,7 @@ public class EnergyAnchorData implements IEnergyAnchorData { nbt.setBoolean("launchFromAnchor", launchFromAnchor); } - public void readNBT(NBTTagCompound nbt) { + public void readNBT(INBTCompound nbt) { this.anchorPoint = AnchorPoint.fromOrdinal(nbt.getInteger("anchorPoint")); this.anchorOffsetX = nbt.getFloat("anchorOffsetX"); this.anchorOffsetY = nbt.getFloat("anchorOffsetY"); diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyBarrierData.java b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyBarrierData.java similarity index 93% rename from src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyBarrierData.java rename to core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyBarrierData.java index 40c30fe95..323134481 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyBarrierData.java +++ b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyBarrierData.java @@ -1,17 +1,19 @@ package kamkeel.npcs.controllers.data.ability.data.energy; -import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.core.NBT; +import noppes.npcs.platform.nbt.INBTCompound; import java.util.HashMap; import java.util.Map; +import java.util.Set; /** * Groups barrier properties shared by energy barrier abilities (Dome, Wall, Shield). * Handles health/durability, duration, and per-projectile-type damage multipliers. * * Properties: - * - Solid: Hard wall — entities cannot pass through the barrier boundary (either direction) - * - Knockback: Repulsion field — entities near the surface get pushed away + * - Solid: Hard wall - entities cannot pass through the barrier boundary (either direction) + * - Knockback: Repulsion field - entities near the surface get pushed away * - Absorbing: Caster's incoming damage is redirected to the barrier * - Allows Melee: Barrier can be hit by melee attacks (punching) */ @@ -163,7 +165,7 @@ public class EnergyBarrierData { // ==================== NBT ==================== - public void writeNBT(NBTTagCompound nbt) { + public void writeNBT(INBTCompound nbt) { nbt.setFloat("barrierMaxHealth", maxHealth); nbt.setBoolean("barrierUseHealth", useHealth); nbt.setInteger("barrierDuration", durationTicks); @@ -180,14 +182,14 @@ public class EnergyBarrierData { nbt.setFloat("barrierReflectStrPct", reflectStrengthPct); nbt.setBoolean("barrierTargetOwner", targetOwner); - NBTTagCompound multNbt = new NBTTagCompound(); + INBTCompound multNbt = NBT.compound(); for (Map.Entry entry : damageMultipliers.entrySet()) { multNbt.setFloat(entry.getKey(), entry.getValue()); } - nbt.setTag("barrierMultipliers", multNbt); + nbt.setCompound("barrierMultipliers", multNbt); } - public void readNBT(NBTTagCompound nbt) { + public void readNBT(INBTCompound nbt) { maxHealth = nbt.hasKey("barrierMaxHealth") ? nbt.getFloat("barrierMaxHealth") : 100.0f; useHealth = !nbt.hasKey("barrierUseHealth") || nbt.getBoolean("barrierUseHealth"); durationTicks = nbt.hasKey("barrierDuration") ? nbt.getInteger("barrierDuration") : 200; @@ -206,9 +208,8 @@ public class EnergyBarrierData { damageMultipliers.clear(); if (nbt.hasKey("barrierMultipliers")) { - NBTTagCompound multNbt = nbt.getCompoundTag("barrierMultipliers"); - @SuppressWarnings("unchecked") - java.util.Set keys = multNbt.func_150296_c(); + INBTCompound multNbt = nbt.getCompound("barrierMultipliers"); + Set keys = multNbt.getKeySet(); for (String key : keys) { damageMultipliers.put(key, multNbt.getFloat(key)); } diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyChargingData.java b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyChargingData.java similarity index 94% rename from src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyChargingData.java rename to core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyChargingData.java index ec53aaeb5..6c9093919 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyChargingData.java +++ b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyChargingData.java @@ -1,6 +1,6 @@ package kamkeel.npcs.controllers.data.ability.data.energy; -import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.platform.nbt.INBTCompound; public class EnergyChargingData { @@ -61,7 +61,7 @@ public class EnergyChargingData { this.maxCharge = Math.max(0, maxCharge); } - public void writeNBT(NBTTagCompound nbt) { + public void writeNBT(INBTCompound nbt) { nbt.setInteger("chargeDuration", chargeDuration); nbt.setInteger("chargeDelay", chargeDelay); nbt.setInteger("maxCharge", maxCharge); @@ -69,7 +69,7 @@ public class EnergyChargingData { nbt.setBoolean("chargeWindUpSync", chargeWindUpSync); } - public void readNBT(NBTTagCompound nbt) { + public void readNBT(INBTCompound nbt) { chargeDuration = nbt.hasKey("chargeDuration") ? nbt.getInteger("chargeDuration") : 60; chargeDelay = nbt.hasKey("chargeDelay") ? nbt.getInteger("chargeDelay") : 0; maxCharge = nbt.hasKey("maxCharge") ? nbt.getInteger("maxCharge") : 100; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyCombatData.java b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyCombatData.java similarity index 97% rename from src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyCombatData.java rename to core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyCombatData.java index 88103197f..3b5908e15 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyCombatData.java +++ b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyCombatData.java @@ -1,8 +1,8 @@ package kamkeel.npcs.controllers.data.ability.data.energy; import kamkeel.npcs.controllers.data.ability.enums.HitType; -import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.api.ability.data.IEnergyCombatData; +import noppes.npcs.platform.nbt.INBTCompound; /** * Groups combat properties shared by energy projectile abilities. @@ -124,7 +124,7 @@ public class EnergyCombatData implements IEnergyCombatData { this.maxHits = clampMaxHits(maxHits); } - public void writeNBT(NBTTagCompound nbt) { + public void writeNBT(INBTCompound nbt) { nbt.setFloat("damage", damage); nbt.setFloat("knockback", knockback); nbt.setFloat("knockbackUp", knockbackUp); @@ -136,7 +136,7 @@ public class EnergyCombatData implements IEnergyCombatData { nbt.setInteger("maxHits", maxHits); } - public void readNBT(NBTTagCompound nbt) { + public void readNBT(INBTCompound nbt) { damage = nbt.hasKey("damage") ? nbt.getFloat("damage") : 7.0f; knockback = nbt.hasKey("knockback") ? nbt.getFloat("knockback") : 1.0f; knockbackUp = nbt.hasKey("knockbackUp") ? nbt.getFloat("knockbackUp") : 0.1f; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyDisplayData.java b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyDisplayData.java similarity index 96% rename from src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyDisplayData.java rename to core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyDisplayData.java index 72bcffbb8..ccc334b5a 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyDisplayData.java +++ b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyDisplayData.java @@ -1,7 +1,7 @@ package kamkeel.npcs.controllers.data.ability.data.energy; -import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.api.ability.data.IEnergyDisplayData; +import noppes.npcs.platform.nbt.INBTCompound; /** * Groups visual color properties shared by all energy abilities. @@ -110,7 +110,7 @@ public class EnergyDisplayData implements IEnergyDisplayData { this.rotationSpeed = rotationSpeed; } - public void writeNBT(NBTTagCompound nbt) { + public void writeNBT(INBTCompound nbt) { nbt.setInteger("innerColor", innerColor); nbt.setInteger("outerColor", outerColor); nbt.setBoolean("outerColorEnabled", outerColorEnabled); @@ -120,7 +120,7 @@ public class EnergyDisplayData implements IEnergyDisplayData { nbt.setFloat("rotationSpeed", rotationSpeed); } - public void readNBT(NBTTagCompound nbt) { + public void readNBT(INBTCompound nbt) { innerColor = nbt.hasKey("innerColor") ? nbt.getInteger("innerColor") : 0xFFFFFF; outerColor = nbt.hasKey("outerColor") ? nbt.getInteger("outerColor") : 0x8888FF; outerColorEnabled = !nbt.hasKey("outerColorEnabled") || nbt.getBoolean("outerColorEnabled"); diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyHomingData.java b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyHomingData.java similarity index 94% rename from src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyHomingData.java rename to core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyHomingData.java index a0825fac1..e3d7f49e0 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyHomingData.java +++ b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyHomingData.java @@ -1,8 +1,7 @@ package kamkeel.npcs.controllers.data.ability.data.energy; -import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.api.ability.data.IEnergyHomingData; - +import noppes.npcs.platform.nbt.INBTCompound; /** * Groups homing/movement properties for energy projectile abilities. @@ -64,14 +63,14 @@ public class EnergyHomingData implements IEnergyHomingData { this.homingRange = homingRange; } - public void writeNBT(NBTTagCompound nbt) { + public void writeNBT(INBTCompound nbt) { nbt.setFloat("speed", speed); nbt.setBoolean("homing", homing); nbt.setFloat("homingStrength", homingStrength); nbt.setFloat("homingRange", homingRange); } - public void readNBT(NBTTagCompound nbt) { + public void readNBT(INBTCompound nbt) { speed = nbt.hasKey("speed") ? nbt.getFloat("speed") : 0.5f; homing = !nbt.hasKey("homing") || nbt.getBoolean("homing"); homingStrength = nbt.hasKey("homingStrength") ? nbt.getFloat("homingStrength") : 0.15f; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyLifespanData.java b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyLifespanData.java similarity index 92% rename from src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyLifespanData.java rename to core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyLifespanData.java index fcb516242..ca1b449ba 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyLifespanData.java +++ b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyLifespanData.java @@ -1,7 +1,7 @@ package kamkeel.npcs.controllers.data.ability.data.energy; -import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.api.ability.data.IEnergyLifespanData; +import noppes.npcs.platform.nbt.INBTCompound; /** * Groups lifespan/range properties for energy projectile abilities. @@ -39,12 +39,12 @@ public class EnergyLifespanData implements IEnergyLifespanData { this.maxLifetime = maxLifetime <= 0 ? 200 : maxLifetime; } - public void writeNBT(NBTTagCompound nbt) { + public void writeNBT(INBTCompound nbt) { nbt.setFloat("maxDistance", maxDistance); nbt.setInteger("maxLifetime", maxLifetime); } - public void readNBT(NBTTagCompound nbt) { + public void readNBT(INBTCompound nbt) { maxDistance = nbt.getFloat("maxDistance"); maxLifetime = nbt.getInteger("maxLifetime"); diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyLightningData.java b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyLightningData.java similarity index 95% rename from src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyLightningData.java rename to core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyLightningData.java index 72a412cfd..89fdb766b 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyLightningData.java +++ b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyLightningData.java @@ -1,7 +1,7 @@ package kamkeel.npcs.controllers.data.ability.data.energy; -import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.api.ability.data.IEnergyLightningData; +import noppes.npcs.platform.nbt.INBTCompound; /** * Groups lightning visual effect properties for energy abilities. @@ -64,14 +64,14 @@ public class EnergyLightningData implements IEnergyLightningData { this.lightningFadeTime = Math.max(1, lightningFadeTime); } - public void writeNBT(NBTTagCompound nbt) { + public void writeNBT(INBTCompound nbt) { nbt.setBoolean("lightningEffect", lightningEffect); nbt.setFloat("lightningDensity", lightningDensity); nbt.setFloat("lightningRadius", lightningRadius); nbt.setInteger("lightningFadeTime", lightningFadeTime); } - public void readNBT(NBTTagCompound nbt) { + public void readNBT(INBTCompound nbt) { lightningEffect = nbt.hasKey("lightningEffect") && nbt.getBoolean("lightningEffect"); lightningDensity = nbt.hasKey("lightningDensity") ? nbt.getFloat("lightningDensity") : 0.15f; lightningRadius = nbt.hasKey("lightningRadius") ? nbt.getFloat("lightningRadius") : 0.5f; diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyPanelData.java b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyPanelData.java similarity index 96% rename from src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyPanelData.java rename to core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyPanelData.java index aaef76cf6..609f66efc 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyPanelData.java +++ b/core/src/main/java/kamkeel/npcs/controllers/data/ability/data/energy/EnergyPanelData.java @@ -1,6 +1,6 @@ package kamkeel.npcs.controllers.data.ability.data.energy; -import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.platform.nbt.INBTCompound; /** * Groups panel-specific properties for energy wall/shield abilities. @@ -88,7 +88,7 @@ public class EnergyPanelData { // ==================== NBT ==================== - public void writeNBT(NBTTagCompound nbt) { + public void writeNBT(INBTCompound nbt) { nbt.setFloat("panelWidth", panelWidth); nbt.setFloat("panelHeight", panelHeight); nbt.setFloat("panelHeightOffset", heightOffset); @@ -100,7 +100,7 @@ public class EnergyPanelData { nbt.setFloat("panelLaunchKnockback", launchKnockback); } - public void readNBT(NBTTagCompound nbt) { + public void readNBT(INBTCompound nbt) { panelWidth = nbt.hasKey("panelWidth") ? nbt.getFloat("panelWidth") : 3.0f; panelHeight = nbt.hasKey("panelHeight") ? nbt.getFloat("panelHeight") : 3.0f; heightOffset = nbt.hasKey("panelHeightOffset") ? nbt.getFloat("panelHeightOffset") : 0.0f; diff --git a/core/src/main/java/kamkeel/npcs/controllers/data/profile/ProfileOperation.java b/core/src/main/java/kamkeel/npcs/controllers/data/profile/ProfileOperation.java new file mode 100644 index 000000000..72a5bb8c0 --- /dev/null +++ b/core/src/main/java/kamkeel/npcs/controllers/data/profile/ProfileOperation.java @@ -0,0 +1,31 @@ +package kamkeel.npcs.controllers.data.profile; + +public class ProfileOperation { + private final EnumProfileOperation result; + private final String message; + + public ProfileOperation(EnumProfileOperation result, String message) { + this.result = result; + this.message = message; + } + + public EnumProfileOperation getResult() { + return result; + } + + public String getMessage() { + return message; + } + + public static ProfileOperation success(String message) { + return new ProfileOperation(EnumProfileOperation.SUCCESS, message); + } + + public static ProfileOperation error(String message) { + return new ProfileOperation(EnumProfileOperation.ERROR, message); + } + + public static ProfileOperation locked(String message) { + return new ProfileOperation(EnumProfileOperation.LOCKED, message); + } +} diff --git a/core/src/main/java/kamkeel/npcs/controllers/data/profile/Slot.java b/core/src/main/java/kamkeel/npcs/controllers/data/profile/Slot.java new file mode 100644 index 000000000..69ddf0c89 --- /dev/null +++ b/core/src/main/java/kamkeel/npcs/controllers/data/profile/Slot.java @@ -0,0 +1,115 @@ +package kamkeel.npcs.controllers.data.profile; + +import noppes.npcs.api.handler.data.ISlot; +import noppes.npcs.core.NBT; +import noppes.npcs.platform.nbt.INBTCompound; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class Slot implements ISlot { + private int id; + private String name; + private long lastLoaded; + private boolean temporary; + private Map components = new HashMap<>(); + + public Slot(int id, String name) { + this.id = id; + this.name = name; + } + + public Slot(int id, String name, long lastLoaded, boolean temporary, Map components) { + this.id = id; + this.name = name; + this.lastLoaded = lastLoaded; + this.temporary = temporary; + this.components = components; + } + + @Override + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + @Override + public String getName() { + return name; + } + + @Override + public void setName(String name) { + this.name = name; + } + + @Override + public long getLastLoaded() { + return lastLoaded; + } + + @Override + public void setLastLoaded(long time) { + this.lastLoaded = time; + } + + @Override + public boolean isTemporary() { + return temporary; + } + + @Override + public void setTemporary(boolean temporary) { + this.temporary = temporary; + } + + @Override + public Map getComponents() { + return components; + } + + @Override + public void setComponentData(String key, INBTCompound data) { + components.put(key, data); + } + + @Override + public INBTCompound getComponentData(String key) { + return components.get(key); + } + + @Override + public INBTCompound toNBT() { + INBTCompound slotNBT = NBT.compound(); + slotNBT.setString("Name", name); + slotNBT.setLong("LastLoaded", lastLoaded); + slotNBT.setBoolean("Temporary", temporary); + INBTCompound compCompound = NBT.compound(); + for (Map.Entry entry : components.entrySet()) { + compCompound.setCompound(entry.getKey(), entry.getValue()); + } + slotNBT.setCompound("Components", compCompound); + return slotNBT; + } + + public static Slot fromNBT(int id, INBTCompound slotNBT) { + String name = slotNBT.getString("Name"); + long lastLoaded = slotNBT.getLong("LastLoaded"); + boolean temporary = slotNBT.getBoolean("Temporary"); + Slot slot = new Slot(id, name); + slot.setLastLoaded(lastLoaded); + slot.setTemporary(temporary); + if (slotNBT.hasKey("Components")) { + INBTCompound compCompound = slotNBT.getCompound("Components"); + Set keys = compCompound.getKeySet(); + for (String key : keys) { + slot.setComponentData(key, compCompound.getCompound(key)); + } + } + return slot; + } +} diff --git a/src/main/java/kamkeel/npcs/controllers/data/telegraph/Telegraph.java b/core/src/main/java/kamkeel/npcs/controllers/data/telegraph/Telegraph.java similarity index 97% rename from src/main/java/kamkeel/npcs/controllers/data/telegraph/Telegraph.java rename to core/src/main/java/kamkeel/npcs/controllers/data/telegraph/Telegraph.java index a12292263..ebb6d89a9 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/telegraph/Telegraph.java +++ b/core/src/main/java/kamkeel/npcs/controllers/data/telegraph/Telegraph.java @@ -1,6 +1,7 @@ package kamkeel.npcs.controllers.data.telegraph; -import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.platform.nbt.INBTCompound; +import noppes.npcs.core.NBT; /** * Telegraph configuration - defines a visual warning shape. @@ -69,8 +70,8 @@ public class Telegraph { // NBT SERIALIZATION // ═══════════════════════════════════════════════════════════════════ - public NBTTagCompound writeNBT() { - NBTTagCompound nbt = new NBTTagCompound(); + public INBTCompound writeNBT() { + INBTCompound nbt = NBT.compound(); nbt.setString("id", id); nbt.setString("type", type.name()); nbt.setFloat("radius", radius); @@ -92,7 +93,7 @@ public class Telegraph { return nbt; } - public void readNBT(NBTTagCompound nbt) { + public void readNBT(INBTCompound nbt) { this.id = nbt.getString("id"); if (nbt.hasKey("type")) { try { diff --git a/core/src/main/java/kamkeel/npcs/developer/Developer.java b/core/src/main/java/kamkeel/npcs/developer/Developer.java new file mode 100644 index 000000000..1e26473ce --- /dev/null +++ b/core/src/main/java/kamkeel/npcs/developer/Developer.java @@ -0,0 +1,42 @@ +package kamkeel.npcs.developer; + +import java.util.HashSet; +import java.util.UUID; + +public class Developer { + + public static HashSet Universal = new HashSet<>(); + public static HashSet ScriptUser = new HashSet<>(); + public static HashSet WandUser = new HashSet<>(); + public static HashSet QuestMaker = new HashSet<>(); + public static Developer Instance; + + public Developer() { + Instance = this; + // Temp for testing + Universal.add(UUID.fromString("29cc52dd-2c50-4e8f-a388-be6c497cf0b4")); + } + + public boolean hasUniversal(UUID uuid) { + if (Universal == null) { + Universal = new HashSet<>(); + } + return Universal.contains(uuid); + } + + public boolean hasScriptUser(UUID uuid) { + if (ScriptUser == null) { + ScriptUser = new HashSet<>(); + } + return ScriptUser.contains(uuid); + } + + public boolean hasWandUser(UUID uuid) { + return WandUser.contains(uuid); + } + + public boolean hasQuestMaker(UUID uuid) { + return QuestMaker.contains(uuid); + } + +} diff --git a/core/src/main/java/kamkeel/npcs/network/enums/EnumChannelType.java b/core/src/main/java/kamkeel/npcs/network/enums/EnumChannelType.java new file mode 100644 index 000000000..87015e1c8 --- /dev/null +++ b/core/src/main/java/kamkeel/npcs/network/enums/EnumChannelType.java @@ -0,0 +1,8 @@ +package kamkeel.npcs.network.enums; + +public enum EnumChannelType { + REQUEST, + PLAYER, + DATA, + INFO +} diff --git a/core/src/main/java/kamkeel/npcs/network/enums/EnumConfigOperation.java b/core/src/main/java/kamkeel/npcs/network/enums/EnumConfigOperation.java new file mode 100644 index 000000000..d210c00a9 --- /dev/null +++ b/core/src/main/java/kamkeel/npcs/network/enums/EnumConfigOperation.java @@ -0,0 +1,5 @@ +package kamkeel.npcs.network.enums; + +public enum EnumConfigOperation { + FONT, +} diff --git a/core/src/main/java/kamkeel/npcs/network/enums/EnumDataPacket.java b/core/src/main/java/kamkeel/npcs/network/enums/EnumDataPacket.java new file mode 100644 index 000000000..598126a2d --- /dev/null +++ b/core/src/main/java/kamkeel/npcs/network/enums/EnumDataPacket.java @@ -0,0 +1,91 @@ +package kamkeel.npcs.network.enums; + +// Packets to the Client +public enum EnumDataPacket { + // Synchronization + SYNC, + SYNC_EFFECTS, + CONFIG_COMMAND, + + // Messages + CHAT_ALERT, + ACHIEVEMENT, + CHATBUBBLE, + SOUND, + DIALOG, + QUEST_COMPLETION, + + + // NPC + EDIT_NPC, + UPDATE_NPC, + ROLE_NPC, + DELETE_NPC, + CLONE_NPC, + WEAPON_NPC, + + // Data + SCROLL_LIST, + SCROLL_DATA, + SCROLL_GROUP, + SCROLL_SELECTED, + PARTY_DATA, + + // GUI + GUI_OPEN, + GUI_REDSTONE, + GUI_WAYPOINT, + GUI_TELEPORTER, + GUI_BOOK, + GUI_DATA, + PLAYER_DATA, + GUI_ERROR, + GUI_CLOSE, + ISGUIOPEN, + + // Visual + SCRIPTED_PARTICLE, + PARTICLE, + PLAYER_UPDATE_SKIN_OVERLAYS, + UPDATE_ANIMATIONS, + SCRIPT_OVERLAY_DATA, + SCRIPT_OVERLAY_CLOSE, + OVERLAY_QUEST_TRACKING, + MARK_DATA, + + // Other + VILLAGER_LIST, + SWING_PLAYER_ARM, + DISABLE_MOUSE_INPUT, + LOGIN, + + // Ability System + TELEGRAPH_SPAWN, + TELEGRAPH_REMOVE, + PLAYER_ABILITY_SYNC, + PLAYER_ABILITY_STATE, + ABILITY_HOTBAR_SYNC, + ABILITY_COOLDOWN_SYNC, + + // Profile System + PROFILE_SHARED_QUEST, + + // Auction System + AUCTION_DATA, + + // Energy Charge Preview + ENERGY_CHARGE_SPAWN, + ENERGY_CHARGE_REMOVE, + + // Energy Explosion Preview + ENERGY_EXPLOSION_SPAWN, + + // Energy Projectile Reflection Sync + PROJECTILE_REFLECT, + + // Energy Projectile Client Sync (position, motion, visual, and movement properties) + PROJECTILE_CLIENT_SYNC, + + // Energy Barrier Client Sync (visual properties and barrier-specific data) + BARRIER_CLIENT_SYNC, +} diff --git a/core/src/main/java/kamkeel/npcs/network/enums/EnumItemPacketType.java b/core/src/main/java/kamkeel/npcs/network/enums/EnumItemPacketType.java new file mode 100644 index 000000000..0f23d1885 --- /dev/null +++ b/core/src/main/java/kamkeel/npcs/network/enums/EnumItemPacketType.java @@ -0,0 +1,14 @@ +package kamkeel.npcs.network.enums; + +public enum EnumItemPacketType { + WAND, + MOUNTER, + CLONER, + TELEPORTER, + SCRIPTER, + PATHER, + BLOCK, + BRUSH, + HAMMER, + MAGIC_BOOK +} diff --git a/core/src/main/java/kamkeel/npcs/network/enums/EnumPlayerPacket.java b/core/src/main/java/kamkeel/npcs/network/enums/EnumPlayerPacket.java new file mode 100644 index 000000000..e1587467b --- /dev/null +++ b/core/src/main/java/kamkeel/npcs/network/enums/EnumPlayerPacket.java @@ -0,0 +1,45 @@ +package kamkeel.npcs.network.enums; + + +public enum EnumPlayerPacket { + FollowerAction, + Transport, + BankAction, + DialogSelect, + GetPlayerValue, + MailBoxAction, + MailSend, + SaveSign, + SaveBook, + CompanionAction, + GetRole, + GetTraderData, + InputDevice, + SpecialKeyState, + ScreenSize, + MagicCycles, + + CustomGuiButton, + CustomGuiScrollClick, + CustomGuiClose, + CustomGuiUnfocused, + + GuiPaintbrush, + GuiMagicBook, + + ProfileCreate, + ProfileRemove, + ProfileRename, + ProfileChange, + ProfileGet, + ProfileGetInfo, + SyncRevisionInfo, + + // Auction + AuctionAction, + + // Ability Hotbar + AbilityHotbarSave, + AbilityHotbarSelect, + AbilityToggle, +} diff --git a/core/src/main/java/kamkeel/npcs/network/enums/EnumRequestPacket.java b/core/src/main/java/kamkeel/npcs/network/enums/EnumRequestPacket.java new file mode 100644 index 000000000..27a319abd --- /dev/null +++ b/core/src/main/java/kamkeel/npcs/network/enums/EnumRequestPacket.java @@ -0,0 +1,233 @@ +package kamkeel.npcs.network.enums; + +public enum EnumRequestPacket { + NPCDelete, + RemoteMainMenu, + RemoteGlobalMenu, + NpcClose, + RemoteDelete, + RemoteFreeze, + RemoteFreezeGet, + RemoteReset, + SpawnMob, + MobSpawner, + + DimensionsGet, + + MainmenuAISave, + MainmenuAIGet, + MainmenuInvSave, + MainmenuInvGet, + MainmenuStatsSave, + MainmenuStatsGet, + MainmenuDisplaySave, + MainmenuDisplayGet, + ModelDataSave, + MainmenuAdvancedSave, + MainmenuAdvancedGet, + MainmenuAdvancedMarkData, + + DialogNpcSet, + DialogNpcRemove, + DialogNpcGet, + DialogCategorySave, + DialogCategoriesGet, + DialogCategoryRemove, + DialogCategoryGet, + DialogSave, + DialogsGet, + DialogGet, + DialogRemove, + + TransportSave, + TransportCategoriesGet, + TransportCategorySave, + TransportCategoryRemove, + TransportRemove, + TransportGetLocation, + TransportsGet, + + FactionSet, + FactionSave, + FactionsGet, + FactionGet, + FactionRemove, + + TagSet, + TagSave, + TagsGet, + TagGet, + NpcTagsGet, + TagRemove, + + QuestUntrack, + QuestLogToServer, + QuestCategorySave, + QuestCategoriesGet, + QuestRemove, + QuestCategoryRemove, + QuestRewardSave, + QuestSave, + QuestsGetFromQuest, + QuestsGet, + QuestDialogGetTitle, + QuestOpenGui, + QuestGet, + + RecipeSave, + RecipeRemove, + RecipesGet, + RecipeGet, + + NaturalSpawnSave, + NaturalSpawnGet, + NaturalSpawnRemove, + NaturalSpawnGetAll, + + MerchantUpdate, + MountPacket, + MovingPathSave, + MovingPathGet, + + AnimationsGet, + AnimationGet, + AnimationRemove, + AnimationSave, + AnimationClone, + BuiltInAnimationGet, + + RemoteNpcsGet, + RemoteTpToNpc, + TileEntitySave, + TileEntityGet, + Gui, + IsGuiOpen, + CacheAnimation, + + PartyLogToServer, + PartySave, + PartyInfo, + PartyDisband, + PartyKick, + PartyLeave, + PartyInvite, + PartyAcceptInvite, + PartyIgnoreInvite, + PartySetLeader, + PartySetQuest, + + LinkedNPCRemove, + LinkedNPCAdd, + LinkedGetAll, + LinkedSet, + LinkedGet, + LinkedItemSave, + LinkedItemRemove, + LinkedItemBuild, + LinkedItemScript, + + BankGet, + BanksGet, + BankSave, + BankRemove, + + QuestCategoryGet, + + PlayerDataInfo, + PlayerDataGetNames, + PlayerDataDeleteInfo, + PlayerDataRemove, + PlayerDataMapRegen, + PlayerDataSave, + + JobSave, + JobGet, + JobSpawnerAdd, + JobSpawnerRemove, + + RoleCompanionUpdate, + RoleSave, + RoleGet, + + MailOpenSetup, + + TransformSave, + TransformGet, + TransformLoad, + + TraderMarketSave, + + CloneList, + CloneSave, + CloneRemove, + CloneTagList, + CloneAllTags, + CloneAllTagsShort, + ClonePreSave, + CloneFolderList, + CloneFolderCrud, + CloneMove, + + EventScript, + PlayerScript, + ForgeScript, + GlobalNPCScript, + ItemScript, + ItemScriptError, + BlockScript, + NPCScript, + ScriptInfo, + ScriptFiles, + EffectScript, + + DimensionTeleport, + + EffectList, + EffectGet, + EffectScriptGet, + EffectRemove, + EffectSave, + + ColorSet, + ColorBrush, + + MagicCycleRemove, + MagicCycleSave, + MagicGetAll, + MagicRemove, + MagicGet, + MagicSave, + NpcMagicGet, + NpcMagicSave, + NpcAbilitiesGet, + NpcAbilitiesSave, + AbilitiesGetAll, + CustomAbilitiesGet, + CustomAbilityGet, + CustomAbilityRemove, + CustomAbilitySave, + BuiltInAbilityGet, + ChainedAbilitiesGet, + ChainedAbilityGet, + ChainedAbilitySave, + ChainedAbilityRemove, + Hammer, + + RecipeScript, + ManageAuctionAction, + AbilityScript, + ChainedAbilityScript, + + CategorySave, + CategoryRemove, + CategoryMoveItem, + CategoryListRequest, + CategoryItemsRequest, + AbilityCategoryMoveItem, + + CustomAbilityClone, + ChainedAbilityClone, + CopyAbilityScripts, + LinkedItemClone, + EffectClone, +} diff --git a/core/src/main/java/kamkeel/npcs/network/enums/EnumSoundOperation.java b/core/src/main/java/kamkeel/npcs/network/enums/EnumSoundOperation.java new file mode 100644 index 000000000..3295df155 --- /dev/null +++ b/core/src/main/java/kamkeel/npcs/network/enums/EnumSoundOperation.java @@ -0,0 +1,12 @@ +package kamkeel.npcs.network.enums; + +public enum EnumSoundOperation { + CONTINUE_SOUNDS, + PAUSE_SOUNDS, + PLAY_MUSIC, + PLAY_SOUND, + PLAY_SOUND_TO, + PLAY_SOUND_TO_NO_ID, + STOP_SOUND_FOR, + STOP_SOUNDS +} diff --git a/core/src/main/java/kamkeel/npcs/network/enums/EnumSyncAction.java b/core/src/main/java/kamkeel/npcs/network/enums/EnumSyncAction.java new file mode 100644 index 000000000..f2260547e --- /dev/null +++ b/core/src/main/java/kamkeel/npcs/network/enums/EnumSyncAction.java @@ -0,0 +1,7 @@ +package kamkeel.npcs.network.enums; + +public enum EnumSyncAction { + RELOAD, + UPDATE, + REMOVE +} diff --git a/core/src/main/java/kamkeel/npcs/network/enums/EnumSyncType.java b/core/src/main/java/kamkeel/npcs/network/enums/EnumSyncType.java new file mode 100644 index 000000000..ee6cf352f --- /dev/null +++ b/core/src/main/java/kamkeel/npcs/network/enums/EnumSyncType.java @@ -0,0 +1,18 @@ +package kamkeel.npcs.network.enums; + +public enum EnumSyncType { + FACTION, + DIALOG, + DIALOG_CATEGORY, + QUEST, + QUEST_CATEGORY, + PLAYERDATA, + MAGIC, + MAGIC_CYCLE, + WORKBENCH_RECIPES, + CARPENTRY_RECIPES, + ANVIL_RECIPES, + CUSTOM_EFFECTS, + CUSTOM_ABILITY, + CHAINED_ABILITY +} diff --git a/core/src/main/java/kamkeel/npcs/util/CNPCDebug.java b/core/src/main/java/kamkeel/npcs/util/CNPCDebug.java new file mode 100644 index 000000000..66cdf3c77 --- /dev/null +++ b/core/src/main/java/kamkeel/npcs/util/CNPCDebug.java @@ -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 serverToggles = new ConcurrentHashMap<>(); + private static final Map clientToggles = new ConcurrentHashMap<>(); + + // Per-type file handlers (lazily initialized) + private static final Map serverHandlers = new ConcurrentHashMap<>(); + private static final Map 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 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 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; + } + } + } +} diff --git a/core/src/main/java/noppes/npcs/NBTTags.java b/core/src/main/java/noppes/npcs/NBTTags.java new file mode 100644 index 000000000..d0694ea3b --- /dev/null +++ b/core/src/main/java/noppes/npcs/NBTTags.java @@ -0,0 +1,522 @@ +package noppes.npcs; + +import noppes.npcs.core.NBT; +import noppes.npcs.platform.nbt.INBTCompound; +import noppes.npcs.platform.nbt.INBTList; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.Vector; + +/** + * Core NBT serialization utilities for Map/Set/List collections. + * Uses INBTCompound/INBTList abstractions. + * + * NOTE: ItemStack-related methods, IScriptUnit methods, and raw NBT type methods + * (nbtDoubleList, getIntAt) remain in the mc1710 version only since they require + * direct MC types. + */ +public class NBTTags { + + public static int TAG_End = 0; + public static int TAG_Byte = 1; + public static int TAG_Short = 2; + public static int TAG_Int = 3; + public static int TAG_Long = 4; + public static int TAG_Float = 5; + public static int TAG_Double = 6; + public static int TAG_Byte_Array = 7; + public static int TAG_String = 8; + public static int TAG_List = 9; + public static int TAG_Compound = 10; + public static int TAG_Int_Array = 11; + + // TODO: ItemStack methods stay in mc1710 version: + // OLD: getItemStackList(NBTTagList) - uses NoppesUtilServer.readItem() + // OLD: getItemStackArray(NBTTagList) - uses NoppesUtilServer.readItem() + // OLD: nbtItemStackList(HashMap) - uses NoppesUtilServer.writeItem() + // OLD: nbtItemStackArray(ItemStack[]) - uses NoppesUtilServer.writeItem() + + public static ArrayList getIntegerArraySet(INBTList tagList) { + ArrayList set = new ArrayList(); + for (int i = 0; i < tagList.size(); i++) { + INBTCompound compound = tagList.getCompound(i); + set.add(compound.getIntArray("Array")); + } + return set; + } + + public static HashMap getBooleanList(INBTList tagList) { + HashMap list = new HashMap(); + for (int i = 0; i < tagList.size(); i++) { + INBTCompound nbttagcompound = tagList.getCompound(i); + list.put(nbttagcompound.getInteger("Slot"), nbttagcompound.getBoolean("Boolean")); + } + return list; + } + + public static HashMap getIntegerIntegerMap(INBTList tagList) { + HashMap list = new HashMap(); + for (int i = 0; i < tagList.size(); i++) { + INBTCompound nbttagcompound = tagList.getCompound(i); + list.put(nbttagcompound.getInteger("Slot"), nbttagcompound.getInteger("Integer")); + } + return list; + } + + public static HashMap getIntegerFloatMap(INBTList tagList) { + HashMap list = new HashMap(); + for (int i = 0; i < tagList.size(); i++) { + INBTCompound nbttagcompound = tagList.getCompound(i); + list.put(nbttagcompound.getInteger("Slot"), nbttagcompound.getFloat("Float")); + } + return list; + } + + public static HashMap getIntegerDoubleMap(INBTList tagList) { + HashMap list = new HashMap(); + for (int i = 0; i < tagList.size(); i++) { + INBTCompound nbttagcompound = tagList.getCompound(i); + list.put(nbttagcompound.getInteger("Slot"), nbttagcompound.getDouble("Double")); + } + return list; + } + + public static HashMap getIntegerLongMap(INBTList tagList) { + HashMap list = new HashMap(); + for (int i = 0; i < tagList.size(); i++) { + INBTCompound nbttagcompound = tagList.getCompound(i); + list.put(nbttagcompound.getInteger("Slot"), nbttagcompound.getLong("Long")); + } + return list; + } + + public static HashSet getStringSet(INBTList tagList) { + HashSet list = new HashSet<>(); + for (int i = 0; i < tagList.size(); i++) { + INBTCompound nbttagcompound = tagList.getCompound(i); + list.add(nbttagcompound.getString("String")); + } + return list; + } + + public static HashMap getIntegerByteMap(INBTList tagList) { + HashMap list = new HashMap(); + for (int i = 0; i < tagList.size(); i++) { + INBTCompound nbttagcompound = tagList.getCompound(i); + list.put(nbttagcompound.getInteger("Slot"), nbttagcompound.getByte("Byte")); + } + return list; + } + + public static INBTList nbtIntegerByteMap(Map lines) { + INBTList nbttaglist = NBT.list(); + if (lines == null) + return nbttaglist; + for (int slot : lines.keySet()) { + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setInteger("Slot", slot); + nbttagcompound.setByte("Byte", lines.get(slot)); + nbttaglist.addCompound(nbttagcompound); + } + return nbttaglist; + } + + public static INBTList nbtStringSet(HashSet collection) { + INBTList nbttaglist = NBT.list(); + if (collection == null) + return nbttaglist; + for (String slot : collection) { + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setString("String", slot); + nbttaglist.addCompound(nbttagcompound); + } + return nbttaglist; + } + + public static HashSet getIntegerSet(INBTList tagList) { + HashSet list = new HashSet(); + for (int i = 0; i < tagList.size(); i++) { + INBTCompound nbttagcompound = tagList.getCompound(i); + list.add(nbttagcompound.getInteger("Integer")); + } + return list; + } + + public static INBTList nbtIntegerSet(HashSet set) { + INBTList nbttaglist = NBT.list(); + if (set == null) + return nbttaglist; + for (int slot : set) { + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setInteger("Integer", slot); + nbttaglist.addCompound(nbttagcompound); + } + return nbttaglist; + } + + public static HashMap getStringStringMap(INBTList tagList) { + HashMap list = new HashMap(); + for (int i = 0; i < tagList.size(); i++) { + INBTCompound nbttagcompound = tagList.getCompound(i); + list.put(nbttagcompound.getString("Slot"), nbttagcompound.getString("Value")); + } + return list; + } + + public static HashMap getIntegerStringMap(INBTList tagList) { + HashMap list = new HashMap(); + for (int i = 0; i < tagList.size(); i++) { + INBTCompound nbttagcompound = tagList.getCompound(i); + list.put(nbttagcompound.getInteger("Slot"), nbttagcompound.getString("Value")); + } + return list; + } + + public static HashMap getStringIntegerMap(INBTList tagList) { + HashMap list = new HashMap(); + for (int i = 0; i < tagList.size(); i++) { + INBTCompound nbttagcompound = tagList.getCompound(i); + list.put(nbttagcompound.getString("Slot"), nbttagcompound.getInteger("Value")); + } + return list; + } + + public static HashMap getStringIntegerArrayMap(INBTList tagList) { + HashMap list = new HashMap(); + for (int i = 0; i < tagList.size(); i++) { + INBTCompound nbttagcompound = tagList.getCompound(i); + list.put(nbttagcompound.getString("Slot"), nbttagcompound.getIntArray("Value")); + } + return list; + } + + public static HashMap getStringIntegerArrayMap(INBTList tagList, int arrayLength) { + HashMap list = new HashMap(); + for (int i = 0; i < tagList.size(); i++) { + INBTCompound nbttagcompound = tagList.getCompound(i); + int[] a = nbttagcompound.getIntArray("Value"); + if (a.length != arrayLength) a = new int[arrayLength]; + list.put(nbttagcompound.getString("Slot"), a); + } + return list; + } + + public static HashMap> getVectorMap(INBTList tagList) { + HashMap> map = new HashMap>(); + for (int i = 0; i < tagList.size(); i++) { + Vector values = new Vector(); + INBTCompound nbttagcompound = tagList.getCompound(i); + INBTList list = nbttagcompound.getList("Values", 10); + for (int j = 0; j < list.size(); j++) { + INBTCompound value = list.getCompound(j); + values.add(value.getString("Value")); + } + + map.put(nbttagcompound.getString("Key"), values); + } + return map; + } + + + public static List getStringList(INBTList tagList) { + List list = new ArrayList(); + for (int i = 0; i < tagList.size(); i++) { + INBTCompound nbttagcompound = tagList.getCompound(i); + String line = nbttagcompound.getString("Line"); + list.add(line); + } + return list; + } + + public static String[] getStringArray(INBTList tagList, int size) { + String[] arr = new String[size]; + for (int i = 0; i < tagList.size(); i++) { + INBTCompound nbttagcompound = tagList.getCompound(i); + String line = nbttagcompound.getString("Value"); + int slot = nbttagcompound.getInteger("Slot"); + arr[slot] = line; + } + return arr; + } + + public static INBTList nbtIntegerArraySet(List set) { + INBTList nbttaglist = NBT.list(); + if (set == null) + return nbttaglist; + for (int[] arr : set) { + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setIntArray("Array", arr); + nbttaglist.addCompound(nbttagcompound); + } + return nbttaglist; + } + + public static INBTList nbtBooleanList(HashMap updatedSlots) { + INBTList nbttaglist = NBT.list(); + if (updatedSlots == null) + return nbttaglist; + HashMap inventory2 = updatedSlots; + for (Integer slot : inventory2.keySet()) { + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setInteger("Slot", slot); + nbttagcompound.setBoolean("Boolean", inventory2.get(slot)); + + nbttaglist.addCompound(nbttagcompound); + } + return nbttaglist; + } + + public static INBTList nbtIntegerIntegerMap(Map lines) { + INBTList nbttaglist = NBT.list(); + if (lines == null) + return nbttaglist; + for (int slot : lines.keySet()) { + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setInteger("Slot", slot); + nbttagcompound.setInteger("Integer", lines.get(slot)); + nbttaglist.addCompound(nbttagcompound); + } + return nbttaglist; + } + + public static INBTList nbtIntegerFloatMap(Map lines) { + INBTList nbttaglist = NBT.list(); + if (lines == null) + return nbttaglist; + for (int slot : lines.keySet()) { + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setInteger("Slot", slot); + nbttagcompound.setDouble("Float", lines.get(slot)); + nbttaglist.addCompound(nbttagcompound); + } + return nbttaglist; + } + + public static INBTList nbtIntegerDoubleMap(Map lines) { + INBTList nbttaglist = NBT.list(); + if (lines == null) + return nbttaglist; + for (int slot : lines.keySet()) { + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setInteger("Slot", slot); + nbttagcompound.setDouble("Double", lines.get(slot)); + nbttaglist.addCompound(nbttagcompound); + } + return nbttaglist; + } + + public static INBTList nbtIntegerLongMap(Map lines) { + INBTList nbttaglist = NBT.list(); + if (lines == null) + return nbttaglist; + for (int slot : lines.keySet()) { + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setInteger("Slot", slot); + nbttagcompound.setLong("Long", lines.get(slot)); + nbttaglist.addCompound(nbttagcompound); + } + return nbttaglist; + } + + public static INBTList nbtVectorMap(Map> map) { + INBTList list = NBT.list(); + if (map == null) + return list; + for (String key : map.keySet()) { + INBTCompound compound = NBT.compound(); + compound.setString("Key", key); + INBTList values = NBT.list(); + for (String value : map.get(key)) { + INBTCompound comp = NBT.compound(); + comp.setString("Value", value); + values.addCompound(comp); + } + compound.setList("Values", values); + list.addCompound(compound); + } + return list; + } + + public static INBTList nbtStringStringMap(Map map) { + INBTList nbttaglist = NBT.list(); + if (map == null) + return nbttaglist; + for (String slot : map.keySet()) { + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setString("Slot", slot); + nbttagcompound.setString("Value", map.get(slot)); + + nbttaglist.addCompound(nbttagcompound); + } + return nbttaglist; + } + + public static INBTList nbtStringIntegerMap(Map map) { + INBTList nbttaglist = NBT.list(); + if (map == null) + return nbttaglist; + for (String slot : map.keySet()) { + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setString("Slot", slot); + nbttagcompound.setInteger("Value", map.get(slot)); + + nbttaglist.addCompound(nbttagcompound); + } + return nbttaglist; + } + + public static INBTList nbtStringIntegerArrayMap(Map map) { + INBTList nbttaglist = NBT.list(); + if (map == null) + return nbttaglist; + for (String slot : map.keySet()) { + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setString("Slot", slot); + nbttagcompound.setIntArray("Value", map.get(slot)); + + nbttaglist.addCompound(nbttagcompound); + } + return nbttaglist; + } + + public static INBTList nbtIntegerStringMap(HashMap map) { + INBTList nbttaglist = NBT.list(); + if (map == null) + return nbttaglist; + for (int slot : map.keySet()) { + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setInteger("Slot", slot); + nbttagcompound.setString("Value", map.get(slot)); + + nbttaglist.addCompound(nbttagcompound); + } + return nbttaglist; + } + + public static INBTList nbtStringArray(String[] list) { + INBTList nbttaglist = NBT.list(); + if (list == null) + return nbttaglist; + for (int i = 0; i < list.length; i++) { + if (list[i] == null) + continue; + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setString("Value", list[i]); + nbttagcompound.setInteger("Slot", i); + nbttaglist.addCompound(nbttagcompound); + } + return nbttaglist; + } + + public static INBTList nbtStringList(List list) { + INBTList nbttaglist = NBT.list(); + for (String s : list) { + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setString("Line", s); + nbttaglist.addCompound(nbttagcompound); + } + return nbttaglist; + } + + // TODO: nbtDoubleList stays in mc1710 version - uses NBTTagDouble directly + // OLD: public static NBTTagList nbtDoubleList(double... par1ArrayOfDouble) + + public static INBTCompound NBTMerge(INBTCompound data, INBTCompound merge) { + INBTCompound compound = data.copy(); + Set names = merge.getKeySet(); + for (String name : names) { + int type = merge.getTagType(name); + if (type == TAG_Compound) + compound.setCompound(name, NBTMerge(compound.getCompound(name), merge.getCompound(name))); + else { + // For non-compound types, copy from merge. + // We need to handle by type since INBTCompound doesn't have a raw getTag/setTag. + copyTag(compound, merge, name, type); + } + } + return compound; + } + + /** + * Copy a single tag from source to dest by type. + * Used by NBTMerge for non-compound types. + */ + private static void copyTag(INBTCompound dest, INBTCompound source, String key, int type) { + switch (type) { + case 1: // Byte + dest.setByte(key, source.getByte(key)); + break; + case 2: // Short + dest.setShort(key, source.getShort(key)); + break; + case 3: // Int + dest.setInteger(key, source.getInteger(key)); + break; + case 4: // Long + dest.setLong(key, source.getLong(key)); + break; + case 5: // Float + dest.setFloat(key, source.getFloat(key)); + break; + case 6: // Double + dest.setDouble(key, source.getDouble(key)); + break; + case 7: // Byte Array + dest.setByteArray(key, source.getByteArray(key)); + break; + case 8: // String + dest.setString(key, source.getString(key)); + break; + case 9: // List + dest.setList(key, source.getList(key, 0)); + break; + case 10: // Compound (handled above in NBTMerge) + dest.setCompound(key, source.getCompound(key)); + break; + case 11: // Int Array + dest.setIntArray(key, source.getIntArray(key)); + break; + } + } + + public static TreeMap GetLongStringMap(INBTList tagList) { + TreeMap list = new TreeMap<>(); + + for (int i = 0; i < tagList.size(); ++i) { + INBTCompound nbttagcompound = tagList.getCompound(i); + list.put(nbttagcompound.getLong("Long"), nbttagcompound.getString("String")); + } + + return list; + } + + public static INBTList NBTLongStringMap(Map map) { + INBTList nbttaglist = NBT.list(); + if (map == null) { + return nbttaglist; + } else { + for (long slot : map.keySet()) { + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setLong("Long", slot); + nbttagcompound.setString("String", map.get(slot)); + nbttaglist.addCompound(nbttagcompound); + } + + return nbttaglist; + } + } + + // TODO: Script methods stay in mc1710 version - use IScriptHandler/IScriptUnit/NBTTagCompound directly + // OLD: public static List GetScriptOld(NBTTagList list, IScriptHandler handler) + // OLD: public static List GetScript(NBTTagCompound compound, IScriptHandler handler) + // OLD: public static NBTTagList NBTScript(List scripts) + + // TODO: getIntAt stays in mc1710 version - uses NBTTagInt.func_150287_d() directly + // OLD: public static int getIntAt(NBTTagList tagList, int index) +} diff --git a/core/src/main/java/noppes/npcs/controllers/APIRegistry.java b/core/src/main/java/noppes/npcs/controllers/APIRegistry.java new file mode 100644 index 000000000..746bc4acd --- /dev/null +++ b/core/src/main/java/noppes/npcs/controllers/APIRegistry.java @@ -0,0 +1,25 @@ +package noppes.npcs.controllers; + +import java.util.LinkedHashMap; + +public class APIRegistry { + public static final APIRegistry Instance = new APIRegistry(); + + private final LinkedHashMap entries = new LinkedHashMap<>(); + + public void register(String name, String url) { + entries.put(name, url); + } + + public void unregister(String name) { + entries.remove(name); + } + + public LinkedHashMap getEntries() { + return entries; + } + + public int size() { + return entries.size(); + } +} diff --git a/core/src/main/java/noppes/npcs/controllers/CategoryManager.java b/core/src/main/java/noppes/npcs/controllers/CategoryManager.java new file mode 100644 index 000000000..80da9768d --- /dev/null +++ b/core/src/main/java/noppes/npcs/controllers/CategoryManager.java @@ -0,0 +1,255 @@ +package noppes.npcs.controllers; + +import noppes.npcs.controllers.data.Category; + +import java.io.File; +import java.util.*; +import java.util.Arrays; + +/** + * Filesystem-based category manager for organizing items into named groups. + * Categories are subdirectories within the controller's base directory. + * Items without a category mapping are "Uncategorized" (root-level files). + * + * One instance per controller (Effect, Animation, LinkedItem, Form, Aura, Outline, etc.) + */ +public class CategoryManager { + public static final int UNCATEGORIZED_ID = 0; + public static final String UNCATEGORIZED_NAME = "Uncategorized"; + + private File baseDir; + private final HashMap categories = new HashMap<>(); + private final HashMap itemCategoryMap = new HashMap<>(); + private int lastUsedCatID = 0; + + /** + * Scan the base directory for subdirectories and create Category objects. + * Call at the start of controller loading, before loading items. + */ + public void loadCategories(File baseDir) { + loadCategories(baseDir, new String[0]); + } + + /** + * Scan the base directory for subdirectories and create Category objects, + * excluding any subdirectories whose names match excludeDirs. + */ + public void loadCategories(File baseDir, String... excludeDirs) { + this.baseDir = baseDir; + categories.clear(); + itemCategoryMap.clear(); + lastUsedCatID = 0; + + if (!baseDir.exists()) return; + + Set excludeSet = new HashSet<>(Arrays.asList(excludeDirs)); + File[] files = baseDir.listFiles(); + if (files == null) return; + for (File sub : files) { + if (!sub.isDirectory()) continue; + if (excludeSet.contains(sub.getName())) continue; + lastUsedCatID++; + categories.put(lastUsedCatID, new Category(lastUsedCatID, sub.getName())); + } + } + + /** + * Register an item as belonging to a category. + * Call when loading items from a subdirectory. + */ + public void registerItem(int itemId, int catId) { + if (catId > UNCATEGORIZED_ID) { + itemCategoryMap.put(itemId, catId); + } + } + + public void removeItem(int itemId) { + itemCategoryMap.remove(itemId); + } + + public boolean isLoaded() { + return baseDir != null; + } + + public File getItemDir(int itemId) { + int catId = itemCategoryMap.getOrDefault(itemId, UNCATEGORIZED_ID); + return getCategoryDir(catId); + } + + public File getCategoryDir(int catId) { + if (catId == UNCATEGORIZED_ID) return baseDir; + Category cat = categories.get(catId); + if (cat != null) return new File(baseDir, cat.title); + return baseDir; + } + + public HashMap getCategories() { + return categories; + } + + // ========== Category CRUD ========== + + public Category createCategory(String name) { + if (baseDir == null) return null; + while (hasCategoryName(name)) name += "_"; + lastUsedCatID++; + Category cat = new Category(lastUsedCatID, name); + categories.put(cat.id, cat); + File dir = new File(baseDir, name); + if (!dir.exists()) dir.mkdirs(); + return cat; + } + + public void saveCategory(Category cat) { + if (cat.id <= 0 || baseDir == null) return; + Category existing = categories.get(cat.id); + if (existing != null && !existing.title.equals(cat.title)) { + String newTitle = cat.title; + while (hasCategoryName(newTitle)) newTitle += "_"; + File oldDir = new File(baseDir, existing.title); + File newDir = new File(baseDir, newTitle); + if (oldDir.exists() && !newDir.exists()) { + oldDir.renameTo(newDir); + } + cat.title = newTitle; + } + categories.put(cat.id, cat); + } + + public boolean removeCategory(int catId) { + return removeCategory(catId, null); + } + + public boolean removeCategory(int catId, Set allItemIds) { + if (baseDir == null) return false; + if (catId <= UNCATEGORIZED_ID) return false; + Category cat = categories.get(catId); + if (cat == null) return false; + + // Server-side guard: refuse to delete if category has items + if (allItemIds != null) { + if (!isCategoryEmpty(catId, allItemIds)) return false; + } else { + // Without item set, check if any items are mapped to this category + if (itemCategoryMap.containsValue(catId)) return false; + } + + // Also check filesystem — directory must be empty or non-existent + File dir = new File(baseDir, cat.title); + if (dir.exists()) { + String[] contents = dir.list(); + if (contents != null && contents.length > 0) { + return false; + } + dir.delete(); + } + + categories.remove(catId); + Iterator> it = itemCategoryMap.entrySet().iterator(); + while (it.hasNext()) { + if (it.next().getValue() == catId) { + it.remove(); + } + } + return true; + } + + public void moveItem(int itemId, String fileName, int destCatId) { + if (baseDir == null) return; + int oldCatId = itemCategoryMap.getOrDefault(itemId, UNCATEGORIZED_ID); + if (oldCatId == destCatId) return; + + File oldDir = getCategoryDir(oldCatId); + File newDir = getCategoryDir(destCatId); + if (!newDir.exists()) newDir.mkdirs(); + + File oldFile = new File(oldDir, fileName); + File newFile = new File(newDir, fileName); + if (oldFile.exists()) { + oldFile.renameTo(newFile); + } + + if (destCatId == UNCATEGORIZED_ID) { + itemCategoryMap.remove(itemId); + } else { + itemCategoryMap.put(itemId, destCatId); + } + } + + // ========== Query ========== + + public boolean hasCategoryName(String name) { + for (Category cat : categories.values()) { + if (cat.title.equalsIgnoreCase(name)) return true; + } + return false; + } + + public boolean isCategoryEmpty(int catId, Set allItemIds) { + if (catId == UNCATEGORIZED_ID) { + for (int id : allItemIds) { + if (!itemCategoryMap.containsKey(id)) return false; + } + return true; + } + for (Map.Entry entry : itemCategoryMap.entrySet()) { + if (entry.getValue() == catId && allItemIds.contains(entry.getKey())) return false; + } + return true; + } + + public Category getCategory(int catId) { + return categories.get(catId); + } + + public int getItemCategory(int itemId) { + return itemCategoryMap.getOrDefault(itemId, UNCATEGORIZED_ID); + } + + public List getItemsInCategory(int catId, Set allItemIds) { + List result = new ArrayList<>(); + for (int itemId : allItemIds) { + int assignedCat = itemCategoryMap.getOrDefault(itemId, UNCATEGORIZED_ID); + if (assignedCat == catId) { + result.add(itemId); + } + } + return result; + } + + // ========== Scroll Data ========== + + public Map getCategoryScrollData() { + Map map = new HashMap<>(); + map.put(UNCATEGORIZED_NAME, UNCATEGORIZED_ID); + for (Category cat : categories.values()) { + map.put(cat.title, cat.id); + } + return map; + } + + /** + * Search all directories (root + subdirectories) for a file and delete it. + */ + public void deleteFile(String fileName) { + if (baseDir == null || !baseDir.exists()) return; + + File file = new File(baseDir, fileName); + if (file.exists()) { + file.delete(); + return; + } + + File[] subs = baseDir.listFiles(); + if (subs != null) { + for (File sub : subs) { + if (!sub.isDirectory()) continue; + File subFile = new File(sub, fileName); + if (subFile.exists()) { + subFile.delete(); + return; + } + } + } + } +} diff --git a/core/src/main/java/noppes/npcs/controllers/FactionController.java b/core/src/main/java/noppes/npcs/controllers/FactionController.java new file mode 100644 index 000000000..fa02ee05a --- /dev/null +++ b/core/src/main/java/noppes/npcs/controllers/FactionController.java @@ -0,0 +1,228 @@ +package noppes.npcs.controllers; + +import noppes.npcs.core.NBT; +import noppes.npcs.controllers.data.Faction; +import noppes.npcs.platform.PlatformServiceHolder; +import noppes.npcs.platform.nbt.INBTCompound; +import noppes.npcs.platform.nbt.INBTList; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +public class FactionController { + public HashMap factionsSync = new HashMap(); + public HashMap factions; + + private static FactionController instance = new FactionController(); + + private int lastUsedID = 0; + + // TODO: mc1710 version implements IFactionHandler and adds: + // OLD: public List list() + // OLD: public IFaction delete(int id) — also calls SyncController.syncRemove(EnumSyncType.FACTION, id) + // OLD: public IFaction create(String name, int defaultPoints) + + public FactionController() { + instance = this; + factions = new HashMap(); + } + + public static FactionController getInstance() { + return instance; + } + + public Faction getFaction(int faction) { + return factions.get(faction); + } + + public void load() { + factions = new HashMap(); + lastUsedID = 0; + File saveDir = PlatformServiceHolder.get().getWorldSaveDirectory(); + if (saveDir == null) { + return; + } + try { + File file = new File(saveDir, "factions.dat"); + if (file.exists()) { + loadFactionsFile(file); + } + } catch (Exception e) { + try { + File file = new File(saveDir, "factions.dat_old"); + if (file.exists()) { + loadFactionsFile(file); + } + + } catch (Exception ee) { + } + } + + if (factions.isEmpty()) { + factions.put(0, new Faction(0, "Friendly", 0x00DD00, 2000)); + factions.put(1, new Faction(1, "Neutral", 0xF2DD00, 1000)); + factions.put(2, new Faction(2, "Aggressive", 0xDD0000, 0)); + } + } + + private void loadFactionsFile(File file) throws Exception { + // OLD: DataInputStream var1 = new DataInputStream(new BufferedInputStream(new GZIPInputStream(new FileInputStream(file)))); + // OLD: loadFactions(var1); + // OLD: var1.close(); + INBTCompound nbttagcompound1 = PlatformServiceHolder.get().readCompressedNBT(file); + loadFactions(nbttagcompound1); + } + + public void loadFactions(INBTCompound nbttagcompound1) { + HashMap factions = new HashMap(); + lastUsedID = nbttagcompound1.getInteger("lastID"); + INBTList list = nbttagcompound1.getList("NPCFactions", 10); + + if (list != null) { + for (int i = 0; i < list.size(); i++) { + INBTCompound nbttagcompound = list.getCompound(i); + Faction faction = new Faction(); + faction.readNBT(nbttagcompound); + factions.put(faction.id, faction); + } + } + this.factions = factions; + } + + public INBTCompound getNBT() { + INBTList list = NBT.list(); + for (int slot : factions.keySet()) { + Faction faction = factions.get(slot); + INBTCompound nbtfactions = NBT.compound(); + faction.writeNBT(nbtfactions); + list.addCompound(nbtfactions); + } + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setInteger("lastID", lastUsedID); + nbttagcompound.setList("NPCFactions", list); + return nbttagcompound; + } + + public void saveFactions() { + try { + File saveDir = PlatformServiceHolder.get().getWorldSaveDirectory(); + File file = new File(saveDir, "factions.dat_new"); + File file1 = new File(saveDir, "factions.dat_old"); + File file2 = new File(saveDir, "factions.dat"); + // OLD: CompressedStreamTools.writeCompressed(getNBT(), new FileOutputStream(file)); + PlatformServiceHolder.get().writeCompressedNBT(getNBT(), file); + if (file1.exists()) { + file1.delete(); + } + file2.renameTo(file1); + if (file2.exists()) { + file2.delete(); + } + file.renameTo(file2); + if (file.exists()) { + file.delete(); + } + } catch (Exception e) { + // OLD: LogWriter.except(e); + PlatformServiceHolder.get().logError("Error saving faction data", e); + } + } + + public Faction get(int faction) { + return factions.get(faction); + } + + public void saveFaction(Faction faction) { + + if (faction.id < 0) { + faction.id = getUnusedId(); + while (hasName(faction.name)) + faction.name += "_"; + } else { + Faction existing = factions.get(faction.id); + if (existing != null && !existing.name.equals(faction.name)) + while (hasName(faction.name)) + faction.name += "_"; + } + factions.remove(faction.id); + factions.put(faction.id, faction); + + // TODO: mc1710 version also calls: + // OLD: NBTTagCompound facCompound = new NBTTagCompound(); + // OLD: faction.writeNBT(facCompound); + // OLD: SyncController.syncUpdate(EnumSyncType.FACTION, -1, facCompound); + saveFactions(); + } + + public Faction create(Faction faction) { + this.saveFaction(faction); + return faction; + } + + public Faction create(String name, int color) { + Faction faction = new Faction(); + faction.name = name; + faction.color = color; + this.saveFaction(faction); + return faction; + } + + public int getUnusedId() { + if (lastUsedID == 0) { + for (int catid : factions.keySet()) + if (catid > lastUsedID) + lastUsedID = catid; + } + lastUsedID++; + return lastUsedID; + } + + public void delete(int id) { + if (id >= 0 && this.factions.size() > 1) { + Faction faction = this.factions.remove(id); + if (faction != null) { + this.saveFactions(); + faction.id = -1; + // TODO: mc1710 version also calls: + // OLD: SyncController.syncRemove(EnumSyncType.FACTION, id); + } + } + } + + public int getFirstFactionId() { + return factions.keySet().iterator().next(); + } + + public Faction getFirstFaction() { + return factions.values().iterator().next(); + } + + public boolean hasName(String newName) { + if (newName.trim().isEmpty()) + return true; + for (Faction faction : factions.values()) + if (faction.name.equals(newName)) + return true; + return false; + } + + public Faction getFactionFromName(String factioname) { + for (Map.Entry entryfaction : FactionController.getInstance().factions.entrySet()) { + if (entryfaction.getValue().name.equalsIgnoreCase(factioname)) { + return entryfaction.getValue(); + } + } + return null; + } + + public String[] getNames() { + String[] names = new String[factions.size()]; + int i = 0; + for (Faction faction : factions.values()) { + names[i] = faction.name.toLowerCase(); + i++; + } + return names; + } +} diff --git a/core/src/main/java/noppes/npcs/controllers/GlobalDataController.java b/core/src/main/java/noppes/npcs/controllers/GlobalDataController.java new file mode 100644 index 000000000..18029f60b --- /dev/null +++ b/core/src/main/java/noppes/npcs/controllers/GlobalDataController.java @@ -0,0 +1,85 @@ +package noppes.npcs.controllers; + +import noppes.npcs.core.NBT; +import noppes.npcs.platform.PlatformServiceHolder; +import noppes.npcs.platform.nbt.INBTCompound; + +import java.io.File; + +import static noppes.npcs.util.CustomNPCsThreader.customNPCThread; + +public class GlobalDataController { + public static GlobalDataController Instance; + private int itemGiverId = 0; + + public GlobalDataController() { + Instance = this; + load(); + } + + private void load() { + File saveDir = PlatformServiceHolder.get().getWorldSaveDirectory(); + try { + File file = new File(saveDir, "global.dat"); + if (file.exists()) { + loadData(file); + } + } catch (Exception e) { + try { + File file = new File(saveDir, "global.dat_old"); + if (file.exists()) { + loadData(file); + } + + } catch (Exception ee) { + ee.printStackTrace(); + } + } + } + + private void loadData(File file) throws Exception { + // OLD: NBTTagCompound nbttagcompound1; + // OLD: try (FileInputStream fis = new FileInputStream(file)) { + // OLD: nbttagcompound1 = CompressedStreamTools.readCompressed(fis); + // OLD: } + INBTCompound nbttagcompound1 = PlatformServiceHolder.get().readCompressedNBT(file); + itemGiverId = nbttagcompound1.getInteger("itemGiverId"); + } + + public void saveData() { + customNPCThread.execute(() -> { + try { + File saveDir = PlatformServiceHolder.get().getWorldSaveDirectory(); + + // OLD: NBTTagCompound nbttagcompound = new NBTTagCompound(); + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setInteger("itemGiverId", itemGiverId); + + File file = new File(saveDir, "global.dat_new"); + File file1 = new File(saveDir, "global.dat_old"); + File file2 = new File(saveDir, "global.dat"); + // OLD: CompressedStreamTools.writeCompressed(nbttagcompound, new FileOutputStream(file)); + PlatformServiceHolder.get().writeCompressedNBT(nbttagcompound, file); + if (file1.exists()) { + file1.delete(); + } + file2.renameTo(file1); + if (file2.exists()) { + file2.delete(); + } + file.renameTo(file2); + if (file.exists()) { + file.delete(); + } + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + + public int incrementItemGiverId() { + itemGiverId++; + saveData(); + return itemGiverId; + } +} diff --git a/core/src/main/java/noppes/npcs/controllers/MagicController.java b/core/src/main/java/noppes/npcs/controllers/MagicController.java new file mode 100644 index 000000000..d8e884d33 --- /dev/null +++ b/core/src/main/java/noppes/npcs/controllers/MagicController.java @@ -0,0 +1,384 @@ +package noppes.npcs.controllers; + +import noppes.npcs.constants.EnumDiagramLayout; +import noppes.npcs.core.NBT; +import noppes.npcs.controllers.data.Magic; +import noppes.npcs.controllers.data.MagicAssociation; +import noppes.npcs.controllers.data.MagicCycle; +import noppes.npcs.platform.PlatformServiceHolder; +import noppes.npcs.platform.nbt.INBTCompound; +import noppes.npcs.platform.nbt.INBTList; + +import java.io.File; +import java.util.HashMap; + +public class MagicController { + public HashMap magics = new HashMap<>(); + public HashMap magicSync = new HashMap<>(); + + public HashMap cycles = new HashMap<>(); + public HashMap cyclesSync = new HashMap<>(); + + public int lastUsedCycleID = 0; + private int lastUsedMagicID = 0; + + private static MagicController instance; + + // TODO: mc1710 version implements IMagicHandler and adds: + // OLD: public Magic getMagic(int magicId) — @Override from IMagicHandler + // OLD: public MagicCycle getCycle(int cycleID) — @Override from IMagicHandler + // OLD: public void addMagicToCycle(int magicId, int cycleId, int index, int priority) — @Override + // OLD: public void removeMagicFromCycle(int magicId, int cycleId) — @Override + + public MagicController() { + instance = this; + } + + public static MagicController getInstance() { + return instance; + } + + public Magic getMagic(int magicId) { + return magics.get(magicId); + } + + public MagicCycle getCycle(int cycleID) { + return cycles.get(cycleID); + } + + public void load() { + magics.clear(); + cycles.clear(); + + lastUsedCycleID = 0; + lastUsedMagicID = 0; + + File saveDir = PlatformServiceHolder.get().getWorldSaveDirectory(); + if (saveDir == null) return; + try { + File file = new File(saveDir, "magic.dat"); + if (file.exists()) { + loadMagicFile(file); + } + } catch (Exception e) { + try { + File file = new File(saveDir, "magic.dat_old"); + if (file.exists()) { + loadMagicFile(file); + } + } catch (Exception ee) { + } + } + + if (magics.isEmpty() && cycles.isEmpty()) { + createDefaults(); + } + } + + /** + * Creates default magic entries. Override in mc1710 to set ItemStack items. + */ + protected void createDefaults() { + // TODO: mc1710 version sets ItemStack items on each magic: + // OLD: earth.setItem(new ItemStack(CustomItems.earthElement)); + // OLD: water.setItem(new ItemStack(CustomItems.waterElement)); + // OLD: fire.setItem(new ItemStack(CustomItems.spellFire)); + // OLD: air.setItem(new ItemStack(CustomItems.airElement)); + // OLD: dark.setItem(new ItemStack(CustomItems.spellDark)); + // OLD: holy.setItem(new ItemStack(CustomItems.spellHoly)); + // OLD: nature.setItem(new ItemStack(CustomItems.spellNature)); + // OLD: arcane.setItem(new ItemStack(CustomItems.spellArcane)); + + Magic earth = new Magic(getUnusedId(), "Earth", 0x00DD00); + Magic water = new Magic(getUnusedId(), "Water", 0xF2DD00); + Magic fire = new Magic(getUnusedId(), "Fire", 0xDD0000); + Magic air = new Magic(getUnusedId(), "Air", 0xDD0000); + Magic dark = new Magic(getUnusedId(), "Dark", 0xDD0000); + Magic holy = new Magic(getUnusedId(), "Holy", 0xDD0000); + Magic nature = new Magic(getUnusedId(), "Nature", 0xDD0000); + Magic arcane = new Magic(getUnusedId(), "Arcane", 0xDD0000); + + // Insiders + earth.interactions.put(air.id, -0.50f); + air.interactions.put(earth.id, 0.50f); + + water.interactions.put(earth.id, -0.50f); + earth.interactions.put(water.id, 0.50f); + + fire.interactions.put(water.id, -0.50f); + water.interactions.put(fire.id, 0.50f); + + air.interactions.put(fire.id, -0.50f); + fire.interactions.put(air.id, 0.50f); + + // Outsiders + dark.interactions.put(nature.id, -0.50f); + nature.interactions.put(dark.id, 0.50f); + + nature.interactions.put(holy.id, -0.50f); + holy.interactions.put(nature.id, 0.50f); + + holy.interactions.put(arcane.id, -0.50f); + arcane.interactions.put(holy.id, 0.50f); + + arcane.interactions.put(dark.id, -0.50f); + dark.interactions.put(arcane.id, 0.50f); + + // Cross Interactions + earth.interactions.put(nature.id, -0.25f); + nature.interactions.put(earth.id, 0.25f); + + water.interactions.put(holy.id, -0.25f); + holy.interactions.put(water.id, 0.25f); + + fire.interactions.put(arcane.id, -0.25f); + arcane.interactions.put(fire.id, 0.25f); + + air.interactions.put(dark.id, -0.25f); + dark.interactions.put(air.id, 0.25f); + + dark.interactions.put(fire.id, -0.25f); + fire.interactions.put(dark.id, 0.25f); + + nature.interactions.put(air.id, -0.25f); + air.interactions.put(nature.id, 0.25f); + + holy.interactions.put(earth.id, -0.25f); + earth.interactions.put(holy.id, 0.25f); + + arcane.interactions.put(water.id, -0.25f); + water.interactions.put(arcane.id, 0.25f); + + // Add them to the registry + magics.put(earth.id, earth); + magics.put(water.id, water); + magics.put(fire.id, fire); + magics.put(air.id, air); + magics.put(dark.id, dark); + magics.put(holy.id, holy); + magics.put(nature.id, nature); + magics.put(arcane.id, arcane); + + MagicCycle defaultCycle = new MagicCycle(); + defaultCycle.id = getUnusedCycleId(); + defaultCycle.name = "Universal"; + defaultCycle.layout = EnumDiagramLayout.CIRCULAR_MANUAL; + defaultCycle.displayName = "&6Elementa Cycle"; + cycles.put(defaultCycle.id, defaultCycle); + + // Add magic associations + addMagicToCycle(earth.id, defaultCycle.id, 1, 1); + addMagicToCycle(water.id, defaultCycle.id, 1, 2); + addMagicToCycle(fire.id, defaultCycle.id, 1, 3); + addMagicToCycle(air.id, defaultCycle.id, 1, 0); + addMagicToCycle(dark.id, defaultCycle.id, 0, 3); + addMagicToCycle(holy.id, defaultCycle.id, 0, 1); + addMagicToCycle(nature.id, defaultCycle.id, 0, 0); + addMagicToCycle(arcane.id, defaultCycle.id, 0, 2); + + saveMagicData(); + } + + private void loadMagicFile(File file) throws Exception { + // OLD: DataInputStream stream = new DataInputStream( + // OLD: new BufferedInputStream(new GZIPInputStream(new FileInputStream(file))) + // OLD: ); + // OLD: loadMagic(stream); + // OLD: stream.close(); + INBTCompound compound = PlatformServiceHolder.get().readCompressedNBT(file); + loadMagic(compound); + } + + public void loadMagic(INBTCompound compound) { + lastUsedMagicID = compound.getInteger("lastID"); + lastUsedCycleID = compound.getInteger("lastCycleID"); + + magics.clear(); + INBTList magicList = compound.getList("Magics", 10); + for (int i = 0; i < magicList.size(); i++) { + INBTCompound magCompound = magicList.getCompound(i); + Magic mag = new Magic(); + mag.readNBT(magCompound); + magics.put(mag.id, mag); + } + + cycles.clear(); + INBTList cycleList = compound.getList("Cycles", 10); + for (int i = 0; i < cycleList.size(); i++) { + INBTCompound catCompound = cycleList.getCompound(i); + MagicCycle cycle = new MagicCycle(); + // OLD: cycle.readNBT(new MC1710NBTCompound(catCompound)); + cycle.readNBT(catCompound); + cycles.put(cycle.id, cycle); + } + } + + public INBTCompound getNBT() { + INBTList magicList = NBT.list(); + for (Magic mag : magics.values()) { + INBTCompound magCompound = NBT.compound(); + mag.writeNBT(magCompound); + magicList.addCompound(magCompound); + } + INBTList catList = NBT.list(); + for (MagicCycle cat : cycles.values()) { + INBTCompound catCompound = NBT.compound(); + // OLD: cat.writeNBT(new MC1710NBTCompound(catCompound)); + cat.writeNBT(catCompound); + catList.addCompound(catCompound); + } + INBTCompound compound = NBT.compound(); + compound.setInteger("lastID", lastUsedMagicID); + compound.setInteger("lastCycleID", lastUsedCycleID); + compound.setList("Magics", magicList); + compound.setList("Cycles", catList); + return compound; + } + + public void saveMagicData() { + try { + File saveDir = PlatformServiceHolder.get().getWorldSaveDirectory(); + File fileNew = new File(saveDir, "magic.dat_new"); + File fileOld = new File(saveDir, "magic.dat_old"); + File fileCurrent = new File(saveDir, "magic.dat"); + // OLD: CompressedStreamTools.writeCompressed(getNBT(), new FileOutputStream(fileNew)); + PlatformServiceHolder.get().writeCompressedNBT(getNBT(), fileNew); + if (fileOld.exists()) + fileOld.delete(); + fileCurrent.renameTo(fileOld); + + if (fileCurrent.exists()) + fileCurrent.delete(); + fileNew.renameTo(fileCurrent); + if (fileNew.exists()) fileNew.delete(); + } catch (Exception e) { + // OLD: LogWriter.except(e); + PlatformServiceHolder.get().logError("Error saving magic data", e); + } + } + + public void saveMagic(Magic mag) { + if (mag.id < 0) { + mag.id = getUnusedId(); + while (hasName(mag.name)) + mag.name += "_"; + } else { + Magic existing = magics.get(mag.id); + if (existing != null && !existing.name.equals(mag.name)) + while (hasName(mag.name)) + mag.name += "_"; + } + magics.put(mag.id, mag); + + // TODO: mc1710 version also calls: + // OLD: NBTTagCompound magicCompound = new NBTTagCompound(); + // OLD: mag.writeNBT(magicCompound); + // OLD: SyncController.syncUpdate(EnumSyncType.MAGIC, -1, magicCompound); + + saveMagicData(); + } + + public void removeMagic(int magicID) { + if (magics.containsKey(magicID)) { + magics.remove(magicID); + // TODO: mc1710 version also calls: + // OLD: SyncController.syncRemove(EnumSyncType.MAGIC, magicID); + saveMagicData(); + } + } + + public int getUnusedId() { + if (lastUsedMagicID == 0) { + for (int id : magics.keySet()) + if (id > lastUsedMagicID) + lastUsedMagicID = id; + } + lastUsedMagicID++; + return lastUsedMagicID; + } + + public boolean hasName(String newName) { + if (newName.trim().isEmpty()) return true; + for (Magic mag : magics.values()) + if (mag.name.equalsIgnoreCase(newName)) + return true; + return false; + } + + // === Cycle Management Methods === + + public int getUnusedCycleId() { + if (lastUsedCycleID == 0) { + for (int id : cycles.keySet()) + if (id > lastUsedCycleID) + lastUsedCycleID = id; + } + lastUsedCycleID++; + return lastUsedCycleID; + } + + public boolean containsCategoryName(String title) { + title = title.toLowerCase(); + for (MagicCycle cat : cycles.values()) { + if (cat.name.toLowerCase().equals(title)) + return true; + } + return false; + } + + public void saveCycle(MagicCycle cycle) { + if (cycle.id < 0) { + cycle.id = getUnusedCycleId(); + while (containsCategoryName(cycle.name)) + cycle.name += "_"; + } else { + MagicCycle existing = cycles.get(cycle.id); + if (existing != null && !existing.name.equals(cycle.name)) + while (containsCategoryName(cycle.name)) + cycle.name += "_"; + } + cycles.put(cycle.id, cycle); + + // TODO: mc1710 version also calls: + // OLD: NBTTagCompound cycleCompound = new NBTTagCompound(); + // OLD: cycle.writeNBT(new MC1710NBTCompound(cycleCompound)); + // OLD: SyncController.syncUpdate(EnumSyncType.MAGIC_CYCLE, -1, cycleCompound); + + saveMagicData(); + } + + public void removeCycle(int categoryId) { + if (cycles.containsKey(categoryId)) { + cycles.remove(categoryId); + // TODO: mc1710 version also calls: + // OLD: SyncController.syncRemove(EnumSyncType.MAGIC_CYCLE, categoryId); + saveMagicData(); + } + } + + public void addMagicToCycle(int magicId, int cycleId, int index, int priority) { + MagicCycle cat = cycles.get(cycleId); + if (cat == null) + return; + + Magic magic = magics.get(magicId); + if (magic == null) + return; + + MagicAssociation assoc = new MagicAssociation(); + assoc.magicId = magicId; + assoc.index = index; + assoc.priority = priority; + cat.associations.put(magicId, assoc); + + saveCycle(cat); + } + + public void removeMagicFromCycle(int magicId, int cycleId) { + MagicCycle cat = cycles.get(cycleId); + if (cat == null) return; + cat.associations.remove(magicId); + + saveCycle(cat); + } +} diff --git a/core/src/main/java/noppes/npcs/controllers/ServerTagMapController.java b/core/src/main/java/noppes/npcs/controllers/ServerTagMapController.java new file mode 100644 index 000000000..36421a8d5 --- /dev/null +++ b/core/src/main/java/noppes/npcs/controllers/ServerTagMapController.java @@ -0,0 +1,114 @@ +package noppes.npcs.controllers; + +import noppes.npcs.controllers.data.TagMap; +import noppes.npcs.platform.PlatformServiceHolder; +import noppes.npcs.platform.nbt.INBTCompound; + +import java.io.File; + +public class ServerTagMapController { + public static ServerTagMapController Instance; + public TagMap tagMap; + + public ServerTagMapController() { + } + + public File getDir() { + File dir = new File(PlatformServiceHolder.get().getWorldSaveDirectory(), "clones"); + if (!dir.exists()) + dir.mkdir(); + return dir; + } + + public File getCloneTabDir(int tab) { + File dir = new File(getDir(), tab + ""); + if (!dir.exists()) + dir.mkdir(); + return dir; + } + + public File getCloneFolderDir(String folderName) { + File dir = new File(getDir(), folderName); + if (!dir.exists()) + dir.mkdir(); + return dir; + } + + public TagMap getTagMap(int tab) { + this.tagMap = new TagMap(tab); + try { + File file = new File(getCloneTabDir(tab), "___tagmap.dat"); + if (file.exists()) { + loadTagMapFile(file); + } + } catch (Exception e) { + try { + File file = new File(getCloneTabDir(tab), "___tagmap.dat_old"); + if (file.exists()) { + loadTagMapFile(file); + } + } catch (Exception ignored) { + } + } + return this.tagMap; + } + + private void loadTagMapFile(File file) throws Exception { + // OLD: DataInputStream var1 = new DataInputStream(new BufferedInputStream(new GZIPInputStream(new FileInputStream(file)))); + // OLD: NBTTagCompound nbtCompound = CompressedStreamTools.read(var1); + // OLD: this.tagMap.readNBT(new MC1710NBTCompound(nbtCompound)); + // OLD: var1.close(); + INBTCompound nbtCompound = PlatformServiceHolder.get().readCompressedNBT(file); + this.tagMap.readNBT(nbtCompound); + } + + public TagMap getTagMap(String folderName) { + this.tagMap = new TagMap(folderName); + try { + File file = new File(getCloneFolderDir(folderName), "___tagmap.dat"); + if (file.exists()) { + loadTagMapFile(file); + } + } catch (Exception e) { + try { + File file = new File(getCloneFolderDir(folderName), "___tagmap.dat_old"); + if (file.exists()) { + loadTagMapFile(file); + } + } catch (Exception ignored) { + } + } + return this.tagMap; + } + + public void saveTagMap(TagMap tagMap) { + try { + File saveDir; + if (tagMap.cloneFolder != null) { + saveDir = getCloneFolderDir(tagMap.cloneFolder); + } else { + saveDir = getCloneTabDir(tagMap.cloneTab); + } + File file = new File(saveDir, "___tagmap.dat_new"); + File file1 = new File(saveDir, "___tagmap.dat_old"); + File file2 = new File(saveDir, "___tagmap.dat"); + // OLD: CompressedStreamTools.writeCompressed(((MC1710NBTCompound) tagMap.writeNBT()).getMCTag(), new FileOutputStream(file)); + PlatformServiceHolder.get().writeCompressedNBT(tagMap.writeNBT(), file); + if (file1.exists()) { + file1.delete(); + } + file2.renameTo(file1); + if (file2.exists()) { + file2.delete(); + } + file.renameTo(file2); + if (file.exists()) { + file.delete(); + } + } catch (Exception e) { + // OLD: LogWriter.except(e); + PlatformServiceHolder.get().logError("Error saving tag map", e); + } + } + +} diff --git a/core/src/main/java/noppes/npcs/controllers/TagController.java b/core/src/main/java/noppes/npcs/controllers/TagController.java new file mode 100644 index 000000000..5f8628caa --- /dev/null +++ b/core/src/main/java/noppes/npcs/controllers/TagController.java @@ -0,0 +1,255 @@ +package noppes.npcs.controllers; + +import noppes.npcs.core.NBT; +import noppes.npcs.controllers.data.Tag; +import noppes.npcs.platform.PlatformServiceHolder; +import noppes.npcs.platform.nbt.INBTCompound; +import noppes.npcs.platform.nbt.INBTList; + +import java.io.File; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.UUID; + +public class TagController { + public HashMap tags; + private static TagController instance; + + private int lastUsedID = 0; + + // TODO: mc1710 version implements ITagHandler and adds: + // OLD: public List list() + // OLD: public ITag delete(int id) + // OLD: public static void sendCategoryTagMap(EntityPlayerMP player, HashMap> itemTags) — uses GuiDataPacket + + public TagController() { + instance = this; + tags = new HashMap(); + loadTags(); + } + + public static TagController getInstance() { + return instance; + } + + private void loadTags() { + File saveDir = PlatformServiceHolder.get().getWorldSaveDirectory(); + if (saveDir == null) { + return; + } + try { + File file = new File(saveDir, "tags.dat"); + if (file.exists()) { + loadTagsFile(file); + } + } catch (Exception e) { + try { + File file = new File(saveDir, "tags.dat_old"); + if (file.exists()) { + loadTagsFile(file); + } + + } catch (Exception ee) { + } + } + } + + private void loadTagsFile(File file) throws Exception { + // OLD: DataInputStream var1 = new DataInputStream(new BufferedInputStream(new GZIPInputStream(new FileInputStream(file)))); + // OLD: loadTags(var1); + // OLD: var1.close(); + INBTCompound nbttagcompound1 = PlatformServiceHolder.get().readCompressedNBT(file); + loadTags(nbttagcompound1); + } + + public void loadTags(INBTCompound nbttagcompound1) { + HashMap tags = new HashMap(); + lastUsedID = nbttagcompound1.getInteger("lastID"); + INBTList list = nbttagcompound1.getList("NPCTags", 10); + + if (list != null) { + for (int i = 0; i < list.size(); i++) { + INBTCompound nbttagcompound = list.getCompound(i); + Tag tag = new Tag(); + // OLD: tag.readNBT(new MC1710NBTCompound(nbttagcompound)); + tag.readNBT(nbttagcompound); + tags.put(tag.id, tag); + } + } + this.tags = tags; + } + + public INBTCompound getNBT() { + INBTList list = NBT.list(); + for (int slot : tags.keySet()) { + Tag tag = tags.get(slot); + INBTCompound nbtfactions = NBT.compound(); + // OLD: tag.writeNBT(new MC1710NBTCompound(nbtfactions)); + tag.writeNBT(nbtfactions); + list.addCompound(nbtfactions); + } + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setInteger("lastID", lastUsedID); + nbttagcompound.setList("NPCTags", list); + return nbttagcompound; + } + + public void saveTags() { + try { + File saveDir = PlatformServiceHolder.get().getWorldSaveDirectory(); + File file = new File(saveDir, "tags.dat_new"); + File file1 = new File(saveDir, "tags.dat_old"); + File file2 = new File(saveDir, "tags.dat"); + // OLD: CompressedStreamTools.writeCompressed(getNBT(), new FileOutputStream(file)); + PlatformServiceHolder.get().writeCompressedNBT(getNBT(), file); + if (file1.exists()) { + file1.delete(); + } + file2.renameTo(file1); + if (file2.exists()) { + file2.delete(); + } + file.renameTo(file2); + if (file.exists()) { + file.delete(); + } + } catch (Exception e) { + // OLD: LogWriter.except(e); + PlatformServiceHolder.get().logError("Error saving tag data", e); + } + } + + public Tag get(int tagSlot) { + return tags.get(tagSlot); + } + + public void saveTag(Tag tag) { + + if (tag.id < 0) { + tag.id = getUnusedId(); + while (hasName(tag.name)) + tag.name += "_"; + } else { + Tag existing = tags.get(tag.id); + if (existing != null && !existing.name.equals(tag.name)) + while (hasName(tag.name)) + tag.name += "_"; + } + tags.remove(tag.id); + tags.put(tag.id, tag); + saveTags(); + } + + public Tag create(Tag tag) { + this.saveTag(tag); + return tag; + } + + public Tag create(String name, int color) { + Tag tag = new Tag(); + tag.name = name; + tag.color = color; + this.saveTag(tag); + return tag; + } + + public int getUnusedId() { + if (lastUsedID == 0) { + for (int catid : tags.keySet()) + if (catid > lastUsedID) + lastUsedID = catid; + } + lastUsedID++; + return lastUsedID; + } + + public void delete(int id) { + if (id >= 0 && this.tags.size() > 1) { + Tag tag = this.tags.remove(id); + if (tag != null) { + this.saveTags(); + tag.id = -1; + } + } + } + + public boolean hasName(String newName) { + if (newName.trim().isEmpty()) + return true; + for (Tag tag : tags.values()) + if (tag.name.equals(newName)) + return true; + return false; + } + + public Tag getTagFromName(String tagname) { + for (Map.Entry entryTag : TagController.getInstance().tags.entrySet()) { + if (entryTag.getValue().name.equalsIgnoreCase(tagname)) { + return entryTag.getValue(); + } + } + return null; + } + + public Tag getTagFromUUID(UUID uuid) { + for (Map.Entry entryTag : TagController.getInstance().tags.entrySet()) { + if (entryTag.getValue().uuid.equals(uuid)) { + return entryTag.getValue(); + } + } + return null; + } + + public String[] getNames() { + String[] names = new String[tags.size()]; + int i = 0; + for (Tag tag : tags.values()) { + names[i] = tag.name.toLowerCase(); + i++; + } + return names; + } + + public HashSet getAllTags() { + return new HashSet(this.tags.values()); + } + + /** + * Write a set of tag UUIDs to an NBT compound under the given key. + */ + public static void writeTagUUIDs(INBTCompound compound, String key, HashSet tagUUIDs) { + if (tagUUIDs != null && !tagUUIDs.isEmpty()) { + INBTList list = NBT.list(); + for (UUID uuid : tagUUIDs) { + list.addString(uuid.toString()); + } + compound.setList(key, list); + } + } + + /** + * Read a set of tag UUIDs from an NBT compound under the given key. + */ + public static HashSet readTagUUIDs(INBTCompound compound, String key) { + HashSet uuids = new HashSet<>(); + if (compound.hasKey(key)) { + INBTList list = compound.getList(key, 8); + for (int i = 0; i < list.size(); i++) { + try { + uuids.add(UUID.fromString(list.getString(i))); + } catch (IllegalArgumentException ignored) {} + } + } + return uuids; + } + + /** + * Remove invalid tag UUIDs (those not in the tag registry). + */ + public static void validateTagUUIDs(HashSet tagUUIDs) { + TagController tc = getInstance(); + if (tc == null) return; + tagUUIDs.removeIf(uuid -> tc.getTagFromUUID(uuid) == null); + } +} diff --git a/core/src/main/java/noppes/npcs/controllers/TransportController.java b/core/src/main/java/noppes/npcs/controllers/TransportController.java new file mode 100644 index 000000000..ad5d1f68b --- /dev/null +++ b/core/src/main/java/noppes/npcs/controllers/TransportController.java @@ -0,0 +1,257 @@ +package noppes.npcs.controllers; + +import noppes.npcs.core.NBT; +import noppes.npcs.controllers.data.TransportCategory; +import noppes.npcs.controllers.data.TransportLocation; +import noppes.npcs.platform.PlatformServiceHolder; +import noppes.npcs.platform.nbt.INBTCompound; +import noppes.npcs.platform.nbt.INBTList; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +public class TransportController { + private HashMap locations = new HashMap(); + public HashMap categories = new HashMap(); + + private int lastUsedID = 0; + + // TODO: mc1710 version implements ITransportHandler and adds: + // OLD: public TransportLocation saveLocation(int categoryId, NBTTagCompound compound, EntityNPCInterface npc) + // - This overload uses EntityNPCInterface, RoleTransporter, EnumRoleType + // OLD: public ITransportCategory[] categories() + // OLD: public void createCategory(String title) + // OLD: public ITransportCategory getCategory(String title) + // OLD: public void removeCategory(String title) + + private static TransportController instance; + + public TransportController() { + instance = this; + loadCategories(); + if (categories.isEmpty()) { + TransportCategory cat = new TransportCategory(); + cat.id = 1; + cat.title = "Default"; + categories.put(cat.id, cat); + } + } + + private void loadCategories() { + File saveDir = PlatformServiceHolder.get().getWorldSaveDirectory(); + if (saveDir == null) + return; + try { + File file = new File(saveDir, "transport.dat"); + if (!file.exists()) { + return; + } + loadCategories(file); + } catch (Exception e) { + try { + File file = new File(saveDir, "transport.dat_old"); + if (!file.exists()) { + return; + } + loadCategories(file); + + } catch (Exception ee) { + } + } + } + + public void loadCategories(File file) throws Exception { + HashMap locations = new HashMap(); + HashMap categories = new HashMap(); + // OLD: NBTTagCompound nbttagcompound1; + // OLD: try (FileInputStream fis = new FileInputStream(file)) { + // OLD: nbttagcompound1 = CompressedStreamTools.readCompressed(fis); + // OLD: } + INBTCompound nbttagcompound1 = PlatformServiceHolder.get().readCompressedNBT(file); + lastUsedID = nbttagcompound1.getInteger("lastID"); + INBTList list = nbttagcompound1.getList("NPCTransportCategories", 10); + if (list == null) { + return; + } + for (int i = 0; i < list.size(); i++) { + TransportCategory category = new TransportCategory(); + INBTCompound compound = list.getCompound(i); + // OLD: category.readNBT(new MC1710NBTCompound(compound)); + category.readNBT(compound); + + for (TransportLocation location : category.locations.values()) + locations.put(location.id, location); + + categories.put(category.id, category); + } + this.locations = locations; + this.categories = categories; + } + + public INBTCompound getNBT() { + INBTList list = NBT.list(); + for (TransportCategory category : categories.values()) { + INBTCompound compound = NBT.compound(); + category.writeNBT(compound); + list.addCompound(compound); + } + INBTCompound nbttagcompound = NBT.compound(); + nbttagcompound.setInteger("lastID", lastUsedID); + nbttagcompound.setList("NPCTransportCategories", list); + return nbttagcompound; + } + + public void saveCategories() { + try { + File saveDir = PlatformServiceHolder.get().getWorldSaveDirectory(); + File file = new File(saveDir, "transport.dat_new"); + File file1 = new File(saveDir, "transport.dat_old"); + File file2 = new File(saveDir, "transport.dat"); + // OLD: CompressedStreamTools.writeCompressed(getNBT(), new FileOutputStream(file)); + PlatformServiceHolder.get().writeCompressedNBT(getNBT(), file); + if (file1.exists()) { + file1.delete(); + } + file2.renameTo(file1); + if (file2.exists()) { + file2.delete(); + } + file.renameTo(file2); + if (file.exists()) { + file.delete(); + } + } catch (Exception e) { + // OLD: LogWriter.except(e); + PlatformServiceHolder.get().logError("Error saving transport data", e); + } + } + + public TransportLocation getTransport(int transportId) { + return locations.get(transportId); + } + + public TransportLocation getTransport(String name) { + for (TransportLocation loc : locations.values()) { + if (loc.name.equals(name)) + return loc; + } + + return null; + } + + public int getUniqueIdLocation() { + if (lastUsedID == 0) { + for (int catid : locations.keySet()) + if (catid > lastUsedID) + lastUsedID = catid; + } + lastUsedID++; + return lastUsedID; + } + + private int getUniqueIdCategory() { + int id = 0; + for (int catid : categories.keySet()) + if (catid > id) + id = catid; + id++; + return id; + } + + public void setLocation(TransportLocation location) { + if (locations.containsKey(location.id)) { + for (TransportCategory cat : categories.values()) + cat.locations.remove(location.id); + } + locations.put(location.id, location); + location.category.locations.put(location.id, location); + } + + public TransportLocation removeLocation(int location) { + TransportLocation loc = locations.get(location); + if (loc == null) + return null; + loc.category.locations.remove(location); + locations.remove(location); + + saveCategories(); + return loc; + } + + private boolean containsCategoryName(String name) { + name = name.toLowerCase(); + for (TransportCategory cat : categories.values()) { + if (cat.title.toLowerCase().equals(name)) + return true; + } + return false; + } + + public void saveCategory(String name, int id) { + if (id < 0) { + id = getUniqueIdCategory(); + } + if (categories.containsKey(id)) { + TransportCategory category = categories.get(id); + if (!category.title.equals(name)) { + while (containsCategoryName(name)) + name += "_"; + categories.get(id).title = name; + } + } else { + while (containsCategoryName(name)) + name += "_"; + TransportCategory category = new TransportCategory(); + category.id = id; + category.title = name; + categories.put(id, category); + } + saveCategories(); + } + + public void removeCategory(int id) { + if (categories.size() == 1) + return; + TransportCategory cat = categories.get(id); + if (cat == null) + return; + for (int i : cat.locations.keySet()) + locations.remove(i); + categories.remove(id); + + saveCategories(); + } + + public boolean containsLocationName(String name) { + name = name.toLowerCase(); + for (TransportLocation loc : locations.values()) { + if (loc.name.toLowerCase().equals(name)) + return true; + } + return false; + } + + public static TransportController getInstance() { + return instance; + } + + public TransportLocation saveLocation(int categoryId, TransportLocation location) { + TransportCategory category = categories.get(categoryId); + if (category == null) + return null; + location.category = category; + if (location.id < 0 || !locations.get(location.id).name.equals(location.name)) { + while (containsLocationName(location.name)) + location.name += "_"; + } + if (location.id < 0) + location.id = getUniqueIdLocation(); + + category.locations.put(location.id, location); + locations.put(location.id, location); + saveCategories(); + + return location; + } +} diff --git a/core/src/main/java/noppes/npcs/controllers/data/Faction.java b/core/src/main/java/noppes/npcs/controllers/data/Faction.java new file mode 100644 index 000000000..aa6ef1d9b --- /dev/null +++ b/core/src/main/java/noppes/npcs/controllers/data/Faction.java @@ -0,0 +1,164 @@ +package noppes.npcs.controllers.data; + +import noppes.npcs.NBTTags; +import noppes.npcs.platform.nbt.INBTCompound; +import noppes.npcs.platform.nbt.INBTList; + +import java.util.HashSet; + +public class Faction { + public String name = ""; + public int color = Integer.parseInt("FF00", 16); + + public HashSet attackFactions; + public int id = -1; + + public int neutralPoints = 500; + public int friendlyPoints = 1500; + + public int defaultPoints = 1000; + + public boolean hideFaction = false; + public boolean getsAttacked = false; + public boolean isPassive = false; + + public Faction() { + attackFactions = new HashSet(); + } + + public Faction(int id, String name, int color, int defaultPoints) { + this.name = name; + this.color = color; + this.defaultPoints = defaultPoints; + this.id = id; + attackFactions = new HashSet(); + } + + public static String formatName(String name) { + name = name.toLowerCase().trim(); + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + + public void readNBT(INBTCompound compound) { + name = compound.getString("Name"); + color = compound.getInteger("Color"); + id = compound.getInteger("Slot"); + + neutralPoints = compound.getInteger("NeutralPoints"); + friendlyPoints = compound.getInteger("FriendlyPoints"); + defaultPoints = compound.getInteger("DefaultPoints"); + + hideFaction = compound.getBoolean("HideFaction"); + getsAttacked = compound.getBoolean("GetsAttacked"); + isPassive = compound.getBoolean("IsPassive"); + + attackFactions = NBTTags.getIntegerSet(compound.getList("AttackFactions", 10)); + } + + public void writeNBT(INBTCompound compound) { + compound.setInteger("Slot", id); + compound.setString("Name", name); + compound.setInteger("Color", color); + + compound.setInteger("NeutralPoints", neutralPoints); + compound.setInteger("FriendlyPoints", friendlyPoints); + compound.setInteger("DefaultPoints", defaultPoints); + + compound.setBoolean("HideFaction", hideFaction); + compound.setBoolean("GetsAttacked", getsAttacked); + compound.setBoolean("IsPassive", isPassive); + + compound.setList("AttackFactions", NBTTags.nbtIntegerSet(attackFactions)); + } + + // TODO: mc1710 version implements IFaction and adds: + // OLD: public boolean isFriendlyToPlayer(EntityPlayer player) — uses PlayerData.get(player).factionData + // OLD: public boolean isAggressiveToPlayer(EntityPlayer player) — uses PlayerData.get(player).factionData + // OLD: public boolean isNeutralToPlayer(EntityPlayer player) — uses PlayerData.get(player).factionData + // OLD: public boolean isAggressiveToNpc(EntityNPCInterface entity) — uses entity.faction.id + // OLD: public int playerStatus(IPlayer player) — uses IPlayerFactionData + // OLD: public boolean isAggressiveToNpc(ICustomNpc npc) — uses npc.getFaction().getId() + // OLD: public boolean isFriendlyToPlayer(IPlayer player) — delegates to EntityPlayer overload + // OLD: public boolean isNeutralToPlayer(IPlayer player) — delegates to EntityPlayer overload + // OLD: public boolean isAggressiveToPlayer(IPlayer player) — delegates to EntityPlayer overload + + public int getId() { + return this.id; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public void setDefaultPoints(int points) { + this.defaultPoints = points; + } + + public int getDefaultPoints() { + return this.defaultPoints; + } + + public void setFriendlyPoints(int points) { + this.friendlyPoints = points; + } + + public int getFriendlyPoints() { + return this.friendlyPoints; + } + + public void setNeutralPoints(int points) { + this.neutralPoints = points; + } + + public int getNeutralPoints() { + return this.neutralPoints; + } + + public void setColor(int color) { + this.color = color; + } + + public int getColor() { + return this.color; + } + + public boolean isEnemyFaction(int factionId) { + return this.attackFactions.contains(factionId); + } + + public void addEnemyFaction(int factionId) { + this.attackFactions.add(factionId); + } + + public void removeEnemyFaction(int factionId) { + this.attackFactions.remove(factionId); + } + + public boolean getIsHidden() { + return this.hideFaction; + } + + public void setIsHidden(boolean bo) { + this.hideFaction = bo; + } + + public boolean isPassive() { + return isPassive; + } + + public void setIsPassive(boolean passive) { + this.isPassive = passive; + } + + public boolean attackedByMobs() { + return this.getsAttacked; + } + + public void setAttackedByMobs(boolean bo) { + this.getsAttacked = bo; + } +} diff --git a/core/src/main/java/noppes/npcs/controllers/data/Magic.java b/core/src/main/java/noppes/npcs/controllers/data/Magic.java new file mode 100644 index 000000000..3a5f055ca --- /dev/null +++ b/core/src/main/java/noppes/npcs/controllers/data/Magic.java @@ -0,0 +1,155 @@ +package noppes.npcs.controllers.data; + +import noppes.npcs.core.NBT; +import noppes.npcs.constants.EnumTextureType; +import noppes.npcs.controllers.MagicController; +import noppes.npcs.platform.nbt.INBTCompound; +import noppes.npcs.platform.nbt.INBTList; + +import java.util.HashMap; +import java.util.Map; + +public class Magic { + public String name = ""; + public String displayName = ""; + public int color = Integer.parseInt("FF00", 16); + public int id = -1; + + // TODO: mc1710 version has: public ItemStack item = null; + // OLD: import net.minecraft.item.ItemStack; + + public EnumTextureType type = EnumTextureType.BASE; + public String iconTexture = ""; + public Map interactions = new HashMap<>(); + + public Magic() { + } + + public Magic(int id, String name, int color) { + this.name = name; + this.displayName = name; + this.color = color; + this.id = id; + } + + public static String formatName(String name) { + name = name.toLowerCase().trim(); + return name.substring(0, 1).toUpperCase() + name.substring(1); + } + + public void readNBT(INBTCompound compound) { + name = compound.getString("Name"); + displayName = compound.getString("DisplayName"); + color = compound.getInteger("Color"); + id = compound.getInteger("Slot"); + + type = EnumTextureType.values()[compound.getInteger("Type")]; + iconTexture = compound.getString("IconTexture"); + // TODO: mc1710 version resolves ItemStack from GameRegistry here: + // OLD: if (type == EnumTextureType.ITEM && !iconTexture.isEmpty()) { + // OLD: String[] parts = iconTexture.split(":"); + // OLD: Item item = GameRegistry.findItem(parts[0], parts[1]); + // OLD: this.item = (item != null) ? new ItemStack(item) : null; + // OLD: } + + interactions.clear(); + if (compound.hasKey("Interactions")) { + INBTList interactionsList = compound.getList("Interactions", 10); + for (int i = 0; i < interactionsList.size(); i++) { + INBTCompound interactionTag = interactionsList.getCompound(i); + int magicId = interactionTag.getInteger("MagicID"); + float percentage = interactionTag.getFloat("Percentage"); + interactions.put(magicId, percentage); + } + } + } + + public void writeNBT(INBTCompound compound) { + compound.setInteger("Slot", id); + compound.setString("Name", name); + compound.setString("DisplayName", displayName); + compound.setInteger("Color", color); + compound.setString("IconTexture", iconTexture); + compound.setInteger("Type", type.ordinal()); + INBTList interactionsList = NBT.list(); + for (Map.Entry entry : interactions.entrySet()) { + INBTCompound interactionTag = NBT.compound(); + interactionTag.setInteger("MagicID", entry.getKey()); + interactionTag.setFloat("Percentage", entry.getValue()); + interactionsList.addCompound(interactionTag); + } + compound.setList("Interactions", interactionsList); + + // TODO: mc1710 version resolves ItemStack from GameRegistry here: + // OLD: if (type == EnumTextureType.ITEM && !iconTexture.isEmpty()) { + // OLD: Item item = GameRegistry.findItem(parts[0], parts[1]); + // OLD: this.item = (item != null) ? new ItemStack(item) : null; + // OLD: } + } + + // TODO: mc1710 version implements IMagic and adds: + // OLD: public void setItem(ItemStack item) — uses GameRegistry.findUniqueIdentifierFor + // OLD: public ItemStack getItem() + + public int getId() { + return this.id; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public void setColor(int c) { + this.color = c; + } + + public int getColor() { + return this.color; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public void save() { + MagicController.getInstance().saveMagic(this); + } + + public void setIconTexture(String texture) { + this.iconTexture = texture; + } + + public String getIconTexture() { + return this.iconTexture; + } + + public void setInteractions(Map interactions) { + this.interactions = interactions; + } + + public Map getInteractions() { + return this.interactions; + } + + public boolean hasInteraction(int magicID) { + return interactions.containsKey(magicID); + } + + public void setInteraction(int magicID, float value) { + interactions.put(magicID, value); + } + + public float getInteraction(int magicID, float value) { + if (hasInteraction(magicID)) + return interactions.get(magicID); + return 0.0f; + } +} diff --git a/core/src/main/java/noppes/npcs/controllers/data/PlayerEffect.java b/core/src/main/java/noppes/npcs/controllers/data/PlayerEffect.java new file mode 100644 index 000000000..df5e07eb8 --- /dev/null +++ b/core/src/main/java/noppes/npcs/controllers/data/PlayerEffect.java @@ -0,0 +1,83 @@ +package noppes.npcs.controllers.data; + +import noppes.npcs.api.handler.data.IPlayerEffect; + +public class PlayerEffect implements IPlayerEffect { + public int id; + public int duration; + public byte level; + public int index; + + public PlayerEffect(int id, int duration, byte level, int index) { + this.id = id; + this.duration = duration; + this.level = level; + this.index = index; + } + + @Override + public void kill() { + duration = 0; + } + + @Override + public int getId() { + return id; + } + + @Override + public int getDuration() { + return duration; + } + + @Override + public void setDuration(int duration) { + this.duration = duration; + } + + @Override + public byte getLevel() { + return level; + } + + @Override + public void setLevel(byte level) { + this.level = level; + } + + @Override + public String getName() { + // TODO: Requires CustomEffectController - implement via callback or platform service + // OLD CODE: + // CustomEffect effect = CustomEffectController.getInstance().get(this.id, this.index); + // if (effect != null) + // return effect.getName(); + return "UNKNOWN"; + } + + /** + * Applies this effect's tick logic to the given player. + * This method is not part of the core IPlayerEffect interface because + * it depends on IPlayer which has MC entity dependencies. + * Override in mc1710 to restore original behavior. + */ + public void performEffect(Object player) { + // TODO: Requires CustomEffectController + IPlayer - implement in mc1710 override + // OLD CODE: + // if (player != null && player.getMCEntity() != null && player.getMCEntity() instanceof EntityPlayer) { + // CustomEffect effect = CustomEffectController.getInstance().get(this.id, this.index); + // if (effect != null) + // effect.onTick((EntityPlayer) player.getMCEntity(), this); + // } + } + + @Override + public int getIndex() { + return this.index; + } + + @Override + public void setIndex(int index) { + this.index = index; + } +} diff --git a/src/main/java/noppes/npcs/controllers/data/PlayerEffectData.java b/core/src/main/java/noppes/npcs/controllers/data/PlayerEffectData.java similarity index 77% rename from src/main/java/noppes/npcs/controllers/data/PlayerEffectData.java rename to core/src/main/java/noppes/npcs/controllers/data/PlayerEffectData.java index 98c025317..9578169a6 100644 --- a/src/main/java/noppes/npcs/controllers/data/PlayerEffectData.java +++ b/core/src/main/java/noppes/npcs/controllers/data/PlayerEffectData.java @@ -1,7 +1,9 @@ package noppes.npcs.controllers.data; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; +import noppes.npcs.constants.NBTTypes; +import noppes.npcs.platform.nbt.INBTCompound; +import noppes.npcs.platform.nbt.INBTList; +import noppes.npcs.core.NBT; import java.util.HashSet; import java.util.Iterator; @@ -9,33 +11,31 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class PlayerEffectData { - private final PlayerData parent; private ConcurrentHashMap effects = new ConcurrentHashMap<>(); - public PlayerEffectData(PlayerData playerData) { - this.parent = playerData; + public PlayerEffectData() { } - public NBTTagCompound writeToNBT(NBTTagCompound compound) { - NBTTagList list = new NBTTagList(); + public INBTCompound writeToNBT(INBTCompound compound) { + INBTList list = NBT.list(); for (Map.Entry entry : effects.entrySet()) { - NBTTagCompound effectCompound = new NBTTagCompound(); + INBTCompound effectCompound = NBT.compound(); effectCompound.setInteger("id", entry.getKey().getId()); effectCompound.setInteger("index", entry.getKey().getIndex()); effectCompound.setInteger("duration", entry.getValue().duration); effectCompound.setByte("level", entry.getValue().level); - list.appendTag(effectCompound); + list.addCompound(effectCompound); } - compound.setTag("Effects", list); + compound.setList("Effects", list); return compound; } - public void readFromNBT(NBTTagCompound compound) { + public void readFromNBT(INBTCompound compound) { HashSet newKeys = new HashSet<>(); if (compound.hasKey("Effects")) { - NBTTagList list = compound.getTagList("Effects", 10); - for (int i = 0; i < list.tagCount(); i++) { - NBTTagCompound effectCompound = list.getCompoundTagAt(i); + INBTList list = compound.getList("Effects", NBTTypes.TAG_COMPOUND); + for (int i = 0; i < list.size(); i++) { + INBTCompound effectCompound = list.getCompound(i); int id = effectCompound.getInteger("id"); int index = effectCompound.getInteger("index"); int duration = effectCompound.getInteger("duration"); diff --git a/core/src/main/java/noppes/npcs/scripted/constants/AnimationType.java b/core/src/main/java/noppes/npcs/scripted/constants/AnimationType.java new file mode 100644 index 000000000..a72255558 --- /dev/null +++ b/core/src/main/java/noppes/npcs/scripted/constants/AnimationType.java @@ -0,0 +1,10 @@ +package noppes.npcs.scripted.constants; + +public class AnimationType { + public static final int NORMAL = 0; + public static final int SITTING = 1; + public static final int LYING = 2; + public static final int HUGGING = 3; + public static final int SNEAKING = 4; + public static final int DANCING = 5; +} diff --git a/core/src/main/java/noppes/npcs/scripted/constants/EntityType.java b/core/src/main/java/noppes/npcs/scripted/constants/EntityType.java new file mode 100644 index 000000000..e92babb24 --- /dev/null +++ b/core/src/main/java/noppes/npcs/scripted/constants/EntityType.java @@ -0,0 +1,27 @@ +package noppes.npcs.scripted.constants; + +public class EntityType { + public static final int UNKNOWN = 0; + public static final int PLAYER = 1; + public static final int NPC = 2; + public static final int MONSTER = 3; + public static final int ANIMAL = 4; + public static final int LIVING = 5; + public static final int ITEM = 6; + public static final int PROJECTILE = 7; + public static final int PIXELMON = 8; + public static final int VILLAGER = 9; + public static final int ARROW = 10; + public static final int THROWABLE = 11; + public static final int FISH_HOOK = 12; + public static final int ENERGY_PROJECTILE = 13; + public static final int ENERGY_ORB = 14; + public static final int ENERGY_BEAM = 15; + public static final int ENERGY_DISC = 16; + public static final int ENERGY_LASER = 17; + public static final int ENERGY_SLICER = 18; + public static final int ENERGY_BARRIER = 19; + public static final int ENERGY_DOME = 20; + public static final int ENERGY_PANEL = 21; + public static final int ENERGY_EXPLOSION = 22; +} diff --git a/core/src/main/java/noppes/npcs/scripted/constants/JobType.java b/core/src/main/java/noppes/npcs/scripted/constants/JobType.java new file mode 100644 index 000000000..d51c9632c --- /dev/null +++ b/core/src/main/java/noppes/npcs/scripted/constants/JobType.java @@ -0,0 +1,13 @@ +package noppes.npcs.scripted.constants; + +public class JobType { + public static final int UNKNOWN = 0; + public static final int BARD = 1; + public static final int HEALER = 2; + public static final int GUARD = 3; + public static final int FOLLOWER = 4; + public static final int ITEMGIVER = 5; + public static final int SPAWNER = 6; + public static final int CONVERSATION = 7; + public static final int PUPPET = 8; +} diff --git a/core/src/main/java/noppes/npcs/scripted/constants/RoleType.java b/core/src/main/java/noppes/npcs/scripted/constants/RoleType.java new file mode 100644 index 000000000..fd1c40443 --- /dev/null +++ b/core/src/main/java/noppes/npcs/scripted/constants/RoleType.java @@ -0,0 +1,11 @@ +package noppes.npcs.scripted.constants; + +public class RoleType { + public static final int UNKNOWN = 0; + public static final int TRADER = 1; + public static final int FOLLOWER = 2; + public static final int BANK = 3; + public static final int TRANSPORTER = 4; + public static final int POSTMAN = 5; + public static final int COMPANION = 6; +} diff --git a/platform-api/src/main/java/kamkeel/npcs/platform/annotation/ClientOnly.java b/platform-api/src/main/java/kamkeel/npcs/platform/annotation/ClientOnly.java new file mode 100644 index 000000000..04cfe05bd --- /dev/null +++ b/platform-api/src/main/java/kamkeel/npcs/platform/annotation/ClientOnly.java @@ -0,0 +1,22 @@ +package kamkeel.npcs.platform.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marks code that should only exist on the physical client. + * + * This is a documentation-only annotation in core — it does NOT trigger + * class stripping like Forge's @SideOnly or Fabric's @Environment. + * + * Platform modules should use their native side annotations for actual stripping: + * - Forge 1.7.10/1.12: @SideOnly(Side.CLIENT) + * - Forge 1.16+: @OnlyIn(Dist.CLIENT) + * - Fabric: @Environment(EnvType.CLIENT) + */ +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR}) +public @interface ClientOnly { +} diff --git a/platform-api/src/main/java/kamkeel/npcs/platform/annotation/ServerOnly.java b/platform-api/src/main/java/kamkeel/npcs/platform/annotation/ServerOnly.java new file mode 100644 index 000000000..f0c2b70db --- /dev/null +++ b/platform-api/src/main/java/kamkeel/npcs/platform/annotation/ServerOnly.java @@ -0,0 +1,17 @@ +package kamkeel.npcs.platform.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marks code that should only exist on the dedicated server. + * + * This is a documentation-only annotation in core — it does NOT trigger + * class stripping. See {@link ClientOnly} for details. + */ +@Retention(RetentionPolicy.SOURCE) +@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR}) +public @interface ServerOnly { +} diff --git a/platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformDamageSource.java b/platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformDamageSource.java new file mode 100644 index 000000000..31bfa1d6f --- /dev/null +++ b/platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformDamageSource.java @@ -0,0 +1,25 @@ +package kamkeel.npcs.platform.entity; + +/** + * Platform-independent damage source abstraction. + */ +public interface IPlatformDamageSource { + + /** + * @return the damage type identifier (e.g., "player", "mob", "generic") + */ + String getType(); + + /** + * @return the entity that caused this damage, or null if none (e.g., fall damage) + */ + IPlatformEntity getSourceEntity(); + + /** + * Returns the underlying MC DamageSource object. + * Core code should NEVER call this. + * + * @return the raw MC DamageSource + */ + Object getHandle(); +} diff --git a/platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformEntity.java b/platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformEntity.java new file mode 100644 index 000000000..7bba53dc2 --- /dev/null +++ b/platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformEntity.java @@ -0,0 +1,58 @@ +package kamkeel.npcs.platform.entity; + +/** + * Platform-independent entity abstraction for core logic. + * Thin interface — only exposes what core actually needs. + * + * Each MC version provides an implementation wrapping the native Entity class. + * Use {@link #getHandle()} to retrieve the underlying MC object in platform code. + */ +public interface IPlatformEntity { + + /** + * @return the entity's numeric ID in the world + */ + int getEntityId(); + + /** + * @return the entity's UUID as a string + */ + String getUniqueID(); + + // --- Position --- + + double getX(); + + double getY(); + + double getZ(); + + float getYaw(); + + float getPitch(); + + void setPosition(double x, double y, double z); + + // --- State --- + + /** + * @return true if the entity exists and is not dead + */ + boolean isAlive(); + + /** + * @return the dimension/world the entity is in + */ + IPlatformWorld getWorld(); + + // --- Escape hatch --- + + /** + * Returns the underlying MC entity object. + * Platform code can cast this to the version-specific Entity class. + * Core code should NEVER call this. + * + * @return the raw MC entity (e.g., net.minecraft.entity.Entity on 1.7.10) + */ + Object getHandle(); +} diff --git a/platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformLiving.java b/platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformLiving.java new file mode 100644 index 000000000..b1346b700 --- /dev/null +++ b/platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformLiving.java @@ -0,0 +1,22 @@ +package kamkeel.npcs.platform.entity; + +/** + * Platform-independent living entity abstraction. + * Extends {@link IPlatformEntity} with health and damage operations. + */ +public interface IPlatformLiving extends IPlatformEntity { + + float getHealth(); + + void setHealth(float hp); + + float getMaxHealth(); + + /** + * Deal damage to this entity. + * + * @param amount the damage amount + * @param source the damage source, or null for generic damage + */ + void damage(float amount, IPlatformDamageSource source); +} diff --git a/platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformPlayer.java b/platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformPlayer.java new file mode 100644 index 000000000..ceb5dc248 --- /dev/null +++ b/platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformPlayer.java @@ -0,0 +1,36 @@ +package kamkeel.npcs.platform.entity; + +/** + * Platform-independent player abstraction. + * Extends {@link IPlatformLiving} with player-specific operations. + */ +public interface IPlatformPlayer extends IPlatformLiving { + + /** + * @return the player's username + */ + String getName(); + + /** + * @return the player's UUID as a string + */ + @Override + String getUniqueID(); + + /** + * @return true if the player is a server operator + */ + boolean isOp(); + + /** + * Send a chat message to this player. + * + * @param text plain text message + */ + void sendMessage(String text); + + /** + * @return the item currently held in the player's main hand, or null if empty + */ + IPlatformStack getHeldItem(); +} diff --git a/platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformStack.java b/platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformStack.java new file mode 100644 index 000000000..805897b00 --- /dev/null +++ b/platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformStack.java @@ -0,0 +1,50 @@ +package kamkeel.npcs.platform.entity; + +import noppes.npcs.platform.nbt.INBTCompound; + +/** + * Platform-independent item stack abstraction. + */ +public interface IPlatformStack { + + /** + * @return the item's registry ID (e.g., "minecraft:stone") + */ + String getItemId(); + + int getCount(); + + void setCount(int count); + + /** + * @return the item's damage/metadata value + */ + int getDamage(); + + void setDamage(int dmg); + + /** + * @return the stack's NBT tag compound, or null if none + */ + INBTCompound getTag(); + + void setTag(INBTCompound tag); + + /** + * @return true if this stack is empty (null item or count <= 0) + */ + boolean isEmpty(); + + /** + * @return a deep copy of this stack + */ + IPlatformStack copy(); + + /** + * Returns the underlying MC ItemStack object. + * Core code should NEVER call this. + * + * @return the raw MC ItemStack + */ + Object getHandle(); +} diff --git a/platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformWorld.java b/platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformWorld.java new file mode 100644 index 000000000..cd3578589 --- /dev/null +++ b/platform-api/src/main/java/kamkeel/npcs/platform/entity/IPlatformWorld.java @@ -0,0 +1,33 @@ +package kamkeel.npcs.platform.entity; + +/** + * Platform-independent world abstraction. + */ +public interface IPlatformWorld { + + /** + * @return the dimension ID (e.g., 0 for overworld, -1 for nether) + */ + int getDimensionId(); + + /** + * @return true if this is a client-side world + */ + boolean isClient(); + + /** + * Look up an entity by its numeric ID. + * + * @param id the entity ID + * @return the entity, or null if not found + */ + IPlatformEntity getEntityById(int id); + + /** + * Returns the underlying MC World object. + * Core code should NEVER call this. + * + * @return the raw MC World + */ + Object getHandle(); +} diff --git a/platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyAnchorData.java b/platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyAnchorData.java new file mode 100644 index 000000000..5abdbfc14 --- /dev/null +++ b/platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyAnchorData.java @@ -0,0 +1,40 @@ +package noppes.npcs.api.ability.data; + +/** + * Configuration for the anchor point of an energy ability projectile. + * Controls where the projectile spawns relative to the caster. + */ +public interface IEnergyAnchorData { + /** @return Anchor point ordinal (0=FRONT, 1=CENTER, 2=RIGHT_HAND, 3=LEFT_HAND, 4=ABOVE_HEAD, 5=CHEST, 6=EYE). */ + int getAnchor(); + + /** + * Set the anchor point. + * @param anchor Anchor ordinal (0=FRONT, 1=CENTER, 2=RIGHT_HAND, 3=LEFT_HAND, 4=ABOVE_HEAD, 5=CHEST, 6=EYE) + */ + void setAnchor(int anchor); + + /** @return X offset from the anchor point (positive = right). */ + float getAnchorOffsetX(); + + /** @param anchorOffsetX X offset from anchor (positive = right). */ + void setAnchorOffsetX(float anchorOffsetX); + + /** @return Y offset from the anchor point (positive = up). */ + float getAnchorOffsetY(); + + /** @param anchorOffsetY Y offset from anchor (positive = up). */ + void setAnchorOffsetY(float anchorOffsetY); + + /** @return Z offset from the anchor point (positive = forward). */ + float getAnchorOffsetZ(); + + /** @param anchorOffsetZ Z offset from anchor (positive = forward). */ + void setAnchorOffsetZ(float anchorOffsetZ); + + /** @return Whether the projectile launches from the anchor position instead of the default eye/look-vector position. */ + boolean getLaunchFromAnchor(); + + /** @param launchFromAnchor When true, the projectile launches from its anchor position; when false, it snaps to the default eye/look-vector position. */ + void setLaunchFromAnchor(boolean launchFromAnchor); +} diff --git a/platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyCombatData.java b/platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyCombatData.java new file mode 100644 index 000000000..644c4d16c --- /dev/null +++ b/platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyCombatData.java @@ -0,0 +1,43 @@ +package noppes.npcs.api.ability.data; + +/** + * Combat properties for energy ability projectiles. + * Controls damage, knockback, and explosion behavior. + */ +public interface IEnergyCombatData { + /** @return Base damage dealt on hit. */ + float getDamage(); + + /** @param damage Base damage on hit. */ + void setDamage(float damage); + + /** @return Horizontal knockback strength applied on hit. */ + float getKnockback(); + + /** @param knockback Horizontal knockback strength. */ + void setKnockback(float knockback); + + /** @return Vertical knockback strength applied on hit. */ + float getKnockbackUp(); + + /** @param knockbackUp Vertical knockback strength. */ + void setKnockbackUp(float knockbackUp); + + /** @return Whether the projectile explodes on impact. */ + boolean isExplosive(); + + /** @param explosive Whether to explode on impact. */ + void setExplosive(boolean explosive); + + /** @return Explosion radius in blocks. */ + float getExplosionRadius(); + + /** @param explosionRadius Explosion radius in blocks. */ + void setExplosionRadius(float explosionRadius); + + /** @return Damage falloff multiplier over distance (0.0-1.0). */ + float getExplosionDamageFalloff(); + + /** @param explosionDamageFalloff Damage falloff multiplier (0.0-1.0). */ + void setExplosionDamageFalloff(float explosionDamageFalloff); +} diff --git a/platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyDisplayData.java b/platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyDisplayData.java new file mode 100644 index 000000000..e479ad57b --- /dev/null +++ b/platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyDisplayData.java @@ -0,0 +1,49 @@ +package noppes.npcs.api.ability.data; + +/** + * Visual display properties for energy ability projectiles. + * Controls colors, transparency, and rotation speed. + */ +public interface IEnergyDisplayData { + /** @return Inner (core) color as a packed RGB integer. */ + int getInnerColor(); + + /** @param innerColor Inner color as a packed RGB integer. */ + void setInnerColor(int innerColor); + + /** @return Outer (glow) color as a packed RGB integer. */ + int getOuterColor(); + + /** @param outerColor Outer color as a packed RGB integer. */ + void setOuterColor(int outerColor); + + /** @return Whether the outer color layer is rendered. */ + boolean isOuterColorEnabled(); + + /** @param outerColorEnabled Whether to render the outer color layer. */ + void setOuterColorEnabled(boolean outerColorEnabled); + + /** @return Width of the outer color layer relative to the projectile size. */ + float getOuterColorWidth(); + + /** @param outerColorWidth Outer color layer width. */ + void setOuterColorWidth(float outerColorWidth); + + /** @return Alpha (opacity) of the outer color layer (0.0-1.0). */ + float getOuterColorAlpha(); + + /** @param outerColorAlpha Outer color opacity (0.0-1.0). */ + void setOuterColorAlpha(float outerColorAlpha); + + /** @return Alpha (opacity) of the inner color layer (0.0-1.0). */ + float getInnerAlpha(); + + /** @param innerAlpha Inner color opacity (0.0-1.0). */ + void setInnerAlpha(float innerAlpha); + + /** @return Visual rotation speed in degrees per tick. */ + float getRotationSpeed(); + + /** @param rotationSpeed Rotation speed in degrees per tick. */ + void setRotationSpeed(float rotationSpeed); +} diff --git a/platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyHomingData.java b/platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyHomingData.java new file mode 100644 index 000000000..b7a868fab --- /dev/null +++ b/platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyHomingData.java @@ -0,0 +1,31 @@ +package noppes.npcs.api.ability.data; + +/** + * Homing and speed properties for energy ability projectiles. + * Controls projectile velocity and target-seeking behavior. + */ +public interface IEnergyHomingData { + /** @return Projectile travel speed in blocks per tick. */ + float getSpeed(); + + /** @param speed Travel speed in blocks per tick. */ + void setSpeed(float speed); + + /** @return Whether the projectile tracks its target. */ + boolean isHoming(); + + /** @param homing Whether to track the target. */ + void setHoming(boolean homing); + + /** @return Homing turn strength (higher = tighter turns). */ + float getHomingStrength(); + + /** @param homingStrength Homing turn strength. */ + void setHomingStrength(float homingStrength); + + /** @return Maximum distance at which homing activates, in blocks. */ + float getHomingRange(); + + /** @param homingRange Maximum homing activation range in blocks. */ + void setHomingRange(float homingRange); +} diff --git a/platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyLifespanData.java b/platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyLifespanData.java new file mode 100644 index 000000000..e14c2eb39 --- /dev/null +++ b/platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyLifespanData.java @@ -0,0 +1,19 @@ +package noppes.npcs.api.ability.data; + +/** + * Lifespan properties for energy ability projectiles. + * Controls how far and how long a projectile can travel before expiring. + */ +public interface IEnergyLifespanData { + /** @return Maximum travel distance in blocks before the projectile expires. */ + float getMaxDistance(); + + /** @param maxDistance Maximum travel distance in blocks. */ + void setMaxDistance(float maxDistance); + + /** @return Maximum lifetime in ticks before the projectile expires. */ + int getMaxLifetime(); + + /** @param maxLifetime Maximum lifetime in ticks. */ + void setMaxLifetime(int maxLifetime); +} diff --git a/platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyLightningData.java b/platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyLightningData.java new file mode 100644 index 000000000..1dcda8f3b --- /dev/null +++ b/platform-api/src/main/java/noppes/npcs/api/ability/data/IEnergyLightningData.java @@ -0,0 +1,31 @@ +package noppes.npcs.api.ability.data; + +/** + * Lightning visual effect properties for energy ability projectiles. + * Controls the electric arc effect rendered around the projectile. + */ +public interface IEnergyLightningData { + /** @return Whether the lightning visual effect is enabled. */ + boolean isLightningEffect(); + + /** @param lightningEffect Whether to enable the lightning effect. */ + void setLightningEffect(boolean lightningEffect); + + /** @return Density of lightning arcs (higher = more arcs). */ + float getLightningDensity(); + + /** @param lightningDensity Lightning arc density. */ + void setLightningDensity(float lightningDensity); + + /** @return Radius of the lightning effect around the projectile, in blocks. */ + float getLightningRadius(); + + /** @param lightningRadius Lightning effect radius in blocks. */ + void setLightningRadius(float lightningRadius); + + /** @return Fade-out time for lightning arcs in ticks. */ + int getLightningFadeTime(); + + /** @param lightningFadeTime Fade-out time in ticks. */ + void setLightningFadeTime(int lightningFadeTime); +} diff --git a/platform-api/src/main/java/noppes/npcs/api/handler/data/IPlayerEffect.java b/platform-api/src/main/java/noppes/npcs/api/handler/data/IPlayerEffect.java new file mode 100644 index 000000000..2bb70c62e --- /dev/null +++ b/platform-api/src/main/java/noppes/npcs/api/handler/data/IPlayerEffect.java @@ -0,0 +1,37 @@ +package noppes.npcs.api.handler.data; + +/** + * Represents an active custom effect instance on a player. + *

+ * Note: performEffect(IPlayer) is omitted from the platform API + * because IPlayer depends on MC entity types. + */ +public interface IPlayerEffect { + + /** Removes this effect from the player. */ + void kill(); + + /** @return the custom effect ID. */ + int getId(); + + /** @return the remaining duration in seconds (-100 for infinite). */ + int getDuration(); + + /** @param duration the remaining duration in seconds (-100 for infinite). */ + void setDuration(int duration); + + /** @return the effect level/amplifier. */ + byte getLevel(); + + /** @param level the effect level/amplifier. */ + void setLevel(byte level); + + /** @return the display name of the effect. */ + String getName(); + + /** @return the effect source index (0: CNPC+, 1: DBC Addon). */ + int getIndex(); + + /** @param index the effect source index (0: CNPC+, 1: DBC Addon). */ + void setIndex(int index); +} diff --git a/platform-api/src/main/java/noppes/npcs/api/handler/data/ISlot.java b/platform-api/src/main/java/noppes/npcs/api/handler/data/ISlot.java new file mode 100644 index 000000000..ded3ee9b0 --- /dev/null +++ b/platform-api/src/main/java/noppes/npcs/api/handler/data/ISlot.java @@ -0,0 +1,29 @@ +package noppes.npcs.api.handler.data; + +import noppes.npcs.platform.nbt.INBTCompound; + +import java.util.Map; + +public interface ISlot { + int getId(); + + String getName(); + + void setName(String name); + + long getLastLoaded(); + + void setLastLoaded(long time); + + boolean isTemporary(); + + void setTemporary(boolean temporary); + + Map getComponents(); + + void setComponentData(String key, INBTCompound data); + + INBTCompound getComponentData(String key); + + INBTCompound toNBT(); +} diff --git a/platform-api/src/main/java/noppes/npcs/platform/PlatformService.java b/platform-api/src/main/java/noppes/npcs/platform/PlatformService.java index 29786decf..6147f0766 100644 --- a/platform-api/src/main/java/noppes/npcs/platform/PlatformService.java +++ b/platform-api/src/main/java/noppes/npcs/platform/PlatformService.java @@ -1,5 +1,11 @@ package noppes.npcs.platform; +import kamkeel.npcs.platform.entity.IPlatformDamageSource; +import kamkeel.npcs.platform.entity.IPlatformEntity; +import kamkeel.npcs.platform.entity.IPlatformLiving; +import kamkeel.npcs.platform.entity.IPlatformPlayer; +import kamkeel.npcs.platform.entity.IPlatformStack; +import kamkeel.npcs.platform.entity.IPlatformWorld; import noppes.npcs.platform.nbt.INBTCompound; import noppes.npcs.platform.nbt.INBTList; import noppes.npcs.platform.nbt.NBTFactory; @@ -93,4 +99,64 @@ public interface PlatformService { * Logs at DEBUG level. */ void logDebug(String message); + + // --- Entity Wrapping --- + + /** + * Wraps a raw MC player entity into a platform-independent player. + * + * @param mcPlayer the MC player object (e.g., EntityPlayerMP on 1.7.10) + * @return a platform player wrapper + */ + IPlatformPlayer wrapPlayer(Object mcPlayer); + + /** + * Wraps a raw MC entity into a platform-independent entity. + * + * @param mcEntity the MC entity object + * @return a platform entity wrapper + */ + IPlatformEntity wrapEntity(Object mcEntity); + + /** + * Wraps a raw MC living entity into a platform-independent living entity. + * + * @param mcLiving the MC living entity object (e.g., EntityLivingBase on 1.7.10) + * @return a platform living wrapper + */ + IPlatformLiving wrapLiving(Object mcLiving); + + /** + * Wraps a raw MC item stack into a platform-independent stack. + * + * @param mcStack the MC ItemStack object + * @return a platform stack wrapper + */ + IPlatformStack wrapStack(Object mcStack); + + /** + * Wraps a raw MC world into a platform-independent world. + * + * @param mcWorld the MC World object + * @return a platform world wrapper + */ + IPlatformWorld wrapWorld(Object mcWorld); + + /** + * Wraps a raw MC damage source into a platform-independent damage source. + * + * @param mcSource the MC DamageSource object + * @return a platform damage source wrapper + */ + IPlatformDamageSource wrapDamageSource(Object mcSource); + + // --- Scheduling --- + + /** + * Runs a task on the main server thread. + * Safe to call from any thread. + * + * @param task the task to run + */ + void runOnMainThread(Runnable task); } diff --git a/src/main/java/kamkeel/npcs/controllers/TelegraphController.java b/src/main/java/kamkeel/npcs/controllers/TelegraphController.java index 7956f4ff6..413fe7dc7 100644 --- a/src/main/java/kamkeel/npcs/controllers/TelegraphController.java +++ b/src/main/java/kamkeel/npcs/controllers/TelegraphController.java @@ -18,6 +18,7 @@ import noppes.npcs.api.handler.ITelegraphHandler; import noppes.npcs.scripted.ScriptTelegraph; import noppes.npcs.scripted.ScriptTelegraphInstance; import noppes.npcs.util.NBTJsonUtil; +import noppes.npcs.wrapper.nbt.MC1710NBTCompound; import java.io.File; import java.util.HashMap; @@ -252,7 +253,7 @@ public class TelegraphController implements ITelegraphHandler { if (!file.isFile() || !file.getName().endsWith(".json")) continue; try { Telegraph telegraph = new Telegraph(); - telegraph.readNBT(NBTJsonUtil.LoadFile(file)); + telegraph.readNBT(new MC1710NBTCompound(NBTJsonUtil.LoadFile(file))); String name = file.getName().substring(0, file.getName().length() - 5); telegraph.setId(name); savedTelegraphs.put(name, telegraph); @@ -274,7 +275,7 @@ public class TelegraphController implements ITelegraphHandler { File file = new File(dir, name + ".json_new"); File file2 = new File(dir, name + ".json"); - NBTJsonUtil.SaveFile(file, telegraph.writeNBT()); + NBTJsonUtil.SaveFile(file, ((MC1710NBTCompound) telegraph.writeNBT()).getMCTag()); if (file2.exists()) { file2.delete(); } diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/data/ProjectileData.java b/src/main/java/kamkeel/npcs/controllers/data/ability/data/ProjectileData.java index a54f526ee..2289ebc72 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/data/ProjectileData.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/data/ProjectileData.java @@ -4,6 +4,7 @@ import kamkeel.npcs.controllers.data.ability.enums.AnchorPoint; import kamkeel.npcs.controllers.data.ability.data.energy.EnergyAnchorData; import kamkeel.npcs.controllers.data.ability.data.energy.EnergyDisplayData; import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.wrapper.nbt.MC1710NBTCompound; /** * Per-projectile data: anchor point + optional color override. @@ -36,7 +37,7 @@ public class ProjectileData { } public void writeNBT(NBTTagCompound nbt) { - anchor.writeNBT(nbt); + anchor.writeNBT(new MC1710NBTCompound(nbt)); nbt.setBoolean("colorOverride", colorOverride); if (colorOverride) { nbt.setInteger("overrideInnerColor", innerColor); @@ -45,7 +46,7 @@ public class ProjectileData { } public void readNBT(NBTTagCompound nbt) { - anchor.readNBT(nbt); + anchor.readNBT(new MC1710NBTCompound(nbt)); colorOverride = nbt.getBoolean("colorOverride"); if (colorOverride) { innerColor = nbt.getInteger("overrideInnerColor"); diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityZone.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityZone.java index 968ff03ba..73694bab8 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityZone.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/AbilityZone.java @@ -18,6 +18,7 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.DamageSource; import noppes.npcs.client.gui.SubGuiZonePresetSelector; +import noppes.npcs.wrapper.nbt.MC1710NBTCompound; import noppes.npcs.client.gui.builder.FieldDef; import noppes.npcs.constants.EnumPotionType; @@ -381,7 +382,7 @@ public abstract class AbilityZone extends Ability { nbt.setFloat("particleScale", particleScale); nbt.setFloat("animSpeed", animSpeed); nbt.setFloat("lightningDensity", lightningDensity); - colorData.writeNBT(nbt); + colorData.writeNBT(new MC1710NBTCompound(nbt)); nbt.setBoolean("groundFill", groundFill); nbt.setFloat("groundAlpha", groundAlpha); @@ -413,7 +414,7 @@ public abstract class AbilityZone extends Ability { this.particleScale = nbt.getFloat("particleScale"); this.animSpeed = nbt.getFloat("animSpeed"); this.lightningDensity = nbt.getFloat("lightningDensity"); - colorData.readNBT(nbt); + colorData.readNBT(new MC1710NBTCompound(nbt)); this.groundFill = nbt.getBoolean("groundFill"); this.groundAlpha = nbt.getFloat("groundAlpha"); diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityBarrier.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityBarrier.java index 1e3df2e02..7ab25bb19 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityBarrier.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityBarrier.java @@ -11,6 +11,7 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.DamageSource; import noppes.npcs.client.gui.builder.FieldDef; import noppes.npcs.controllers.data.MagicData; +import noppes.npcs.wrapper.nbt.MC1710NBTCompound; import java.util.List; @@ -176,7 +177,7 @@ public abstract class AbilityBarrier extends AbilityEnergy { public final void writeTypeNBT(NBTTagCompound nbt) { writeBarrierTypeNBT(nbt); writeEnergyNBT(nbt); - barrierData.writeNBT(nbt); + barrierData.writeNBT(new MC1710NBTCompound(nbt)); nbt.setFloat("barrierOffsetX", offsetX); nbt.setFloat("barrierOffsetY", offsetY); nbt.setFloat("barrierOffsetZ", offsetZ); @@ -189,7 +190,7 @@ public abstract class AbilityBarrier extends AbilityEnergy { offsetZ = nbt.hasKey("barrierOffsetZ") ? nbt.getFloat("barrierOffsetZ") : 0.0f; readBarrierTypeNBT(nbt); readEnergyNBT(nbt); - barrierData.readNBT(nbt); + barrierData.readNBT(new MC1710NBTCompound(nbt)); } // ==================== API GETTERS & SETTERS ==================== diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityEnergy.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityEnergy.java index 461f3b50d..b3e77993d 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityEnergy.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityEnergy.java @@ -7,6 +7,7 @@ import kamkeel.npcs.controllers.data.ability.data.energy.EnergyDisplayData; import kamkeel.npcs.controllers.data.ability.data.energy.EnergyLightningData; import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.client.gui.builder.FieldDef; +import noppes.npcs.wrapper.nbt.MC1710NBTCompound; import java.util.List; @@ -119,13 +120,13 @@ public abstract class AbilityEnergy extends Ability { // ==================== NBT HELPERS ==================== protected void writeEnergyNBT(NBTTagCompound nbt) { - displayData.writeNBT(nbt); - lightningData.writeNBT(nbt); + displayData.writeNBT(new MC1710NBTCompound(nbt)); + lightningData.writeNBT(new MC1710NBTCompound(nbt)); } protected void readEnergyNBT(NBTTagCompound nbt) { - displayData.readNBT(nbt); - lightningData.readNBT(nbt); + displayData.readNBT(new MC1710NBTCompound(nbt)); + lightningData.readNBT(new MC1710NBTCompound(nbt)); } // ==================== GUI HELPERS ==================== diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityEnergyProjectile.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityEnergyProjectile.java index 7e7986d20..8a659a5aa 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityEnergyProjectile.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityEnergyProjectile.java @@ -26,6 +26,7 @@ import net.minecraft.util.Vec3; import noppes.npcs.api.ability.type.IAbilityEnergyProjectile; import noppes.npcs.client.gui.builder.FieldDef; import noppes.npcs.controllers.data.MagicData; +import noppes.npcs.wrapper.nbt.MC1710NBTCompound; import java.util.List; @@ -583,9 +584,9 @@ public abstract class AbilityEnergyProjectile // Shared data classes writeEnergyNBT(nbt); - combatData.writeNBT(nbt); - homingData.writeNBT(nbt); - lifespanData.writeNBT(nbt); + combatData.writeNBT(new MC1710NBTCompound(nbt)); + homingData.writeNBT(new MC1710NBTCompound(nbt)); + lifespanData.writeNBT(new MC1710NBTCompound(nbt)); // Per-projectile data for (int i = 0; i < projectileCount; i++) { @@ -607,9 +608,9 @@ public abstract class AbilityEnergyProjectile // Shared data classes readEnergyNBT(nbt); - combatData.readNBT(nbt); - homingData.readNBT(nbt); - lifespanData.readNBT(nbt); + combatData.readNBT(new MC1710NBTCompound(nbt)); + homingData.readNBT(new MC1710NBTCompound(nbt)); + lifespanData.readNBT(new MC1710NBTCompound(nbt)); // Per-projectile data for (int i = 0; i < projectileCount; i++) { diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityWall.java b/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityWall.java index bfe8c5b36..aabc6028d 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityWall.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/type/energy/AbilityWall.java @@ -14,6 +14,7 @@ import kamkeel.npcs.entity.EntityEnergyPanel; import net.minecraft.entity.EntityLivingBase; import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.client.gui.builder.FieldDef; +import noppes.npcs.wrapper.nbt.MC1710NBTCompound; import java.util.Arrays; import java.util.List; @@ -141,12 +142,12 @@ public class AbilityWall extends AbilityBarrier { @Override protected void writeBarrierTypeNBT(NBTTagCompound nbt) { - panelData.writeNBT(nbt); + panelData.writeNBT(new MC1710NBTCompound(nbt)); } @Override protected void readBarrierTypeNBT(NBTTagCompound nbt) { - panelData.readNBT(nbt); + panelData.readNBT(new MC1710NBTCompound(nbt)); // Migrate legacy heightOffset → base class offsetY if (!nbt.hasKey("barrierOffsetY") && panelData.heightOffset != 0.0f) { offsetY = panelData.heightOffset; diff --git a/src/main/java/kamkeel/npcs/controllers/data/telegraph/TelegraphInstance.java b/src/main/java/kamkeel/npcs/controllers/data/telegraph/TelegraphInstance.java index a9ee8e4d7..03e0611c0 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/telegraph/TelegraphInstance.java +++ b/src/main/java/kamkeel/npcs/controllers/data/telegraph/TelegraphInstance.java @@ -4,6 +4,7 @@ import kamkeel.npcs.controllers.data.ability.Ability; import net.minecraft.entity.Entity; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; +import noppes.npcs.wrapper.nbt.MC1710NBTCompound; import java.util.UUID; @@ -214,7 +215,7 @@ public class TelegraphInstance { nbt.setString("instanceId", instanceId); if (telegraph != null) { - nbt.setTag("telegraph", telegraph.writeNBT()); + nbt.setTag("telegraph", ((MC1710NBTCompound) telegraph.writeNBT()).getMCTag()); } nbt.setDouble("x", x); @@ -240,7 +241,7 @@ public class TelegraphInstance { if (nbt.hasKey("telegraph")) { this.telegraph = new Telegraph(); - this.telegraph.readNBT(nbt.getCompoundTag("telegraph")); + this.telegraph.readNBT(new MC1710NBTCompound(nbt.getCompoundTag("telegraph"))); } this.x = nbt.getDouble("x"); diff --git a/src/main/java/kamkeel/npcs/entity/EntityEnergyAbility.java b/src/main/java/kamkeel/npcs/entity/EntityEnergyAbility.java index a6320e35c..70775e403 100644 --- a/src/main/java/kamkeel/npcs/entity/EntityEnergyAbility.java +++ b/src/main/java/kamkeel/npcs/entity/EntityEnergyAbility.java @@ -354,8 +354,8 @@ public abstract class EntityEnergyAbility extends Entity implements IEntityAddit protected void writeEnergyBaseNBT(NBTTagCompound nbt) { nbt.setInteger("OwnerId", ownerEntityId); nbt.setBoolean("IgnoreIFrames", ignoreIFrames); - displayData.writeNBT(nbt); - lightningData.writeNBT(nbt); + displayData.writeNBT(new MC1710NBTCompound(nbt)); + lightningData.writeNBT(new MC1710NBTCompound(nbt)); if (customDamageData != null) { nbt.setTag("CustomDamageData", customDamageData); } @@ -369,8 +369,8 @@ public abstract class EntityEnergyAbility extends Entity implements IEntityAddit protected void readEnergyBaseNBT(NBTTagCompound nbt) { this.ownerEntityId = nbt.getInteger("OwnerId"); this.ignoreIFrames = nbt.getBoolean("IgnoreIFrames"); - displayData.readNBT(nbt); - lightningData.readNBT(nbt); + displayData.readNBT(new MC1710NBTCompound(nbt)); + lightningData.readNBT(new MC1710NBTCompound(nbt)); if (nbt.hasKey("CustomDamageData")) { this.customDamageData = nbt.getCompoundTag("CustomDamageData"); } diff --git a/src/main/java/kamkeel/npcs/entity/EntityEnergyBarrier.java b/src/main/java/kamkeel/npcs/entity/EntityEnergyBarrier.java index 4ccb01269..32a8b8324 100644 --- a/src/main/java/kamkeel/npcs/entity/EntityEnergyBarrier.java +++ b/src/main/java/kamkeel/npcs/entity/EntityEnergyBarrier.java @@ -18,6 +18,7 @@ import noppes.npcs.EventHooks; import noppes.npcs.controllers.data.MagicData; import noppes.npcs.controllers.data.PlayerData; import noppes.npcs.entity.EntityNPCInterface; +import noppes.npcs.wrapper.nbt.MC1710NBTCompound; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -869,7 +870,7 @@ public abstract class EntityEnergyBarrier extends EntityEnergyAbility { nbt.setBoolean("Charging", charging); nbt.setInteger("ChargeTick", chargeTick); nbt.setInteger("ChargeDuration", chargeDuration); - barrierData.writeNBT(nbt); + barrierData.writeNBT(new MC1710NBTCompound(nbt)); } /** @@ -885,7 +886,7 @@ public abstract class EntityEnergyBarrier extends EntityEnergyAbility { this.chargeTick = nbt.getInteger("ChargeTick"); this.chargeDuration = nbt.getInteger("ChargeDuration"); this.dataWatcher.updateObject(DW_CHARGING, (byte) (charging ? 1 : 0)); - barrierData.readNBT(nbt); + barrierData.readNBT(new MC1710NBTCompound(nbt)); } // ==================== DEBUG LOGGING ==================== diff --git a/src/main/java/kamkeel/npcs/entity/EntityEnergyPanel.java b/src/main/java/kamkeel/npcs/entity/EntityEnergyPanel.java index 96949bbd4..31655da28 100644 --- a/src/main/java/kamkeel/npcs/entity/EntityEnergyPanel.java +++ b/src/main/java/kamkeel/npcs/entity/EntityEnergyPanel.java @@ -18,6 +18,7 @@ import net.minecraft.util.DamageSource; import net.minecraft.world.World; import noppes.npcs.NpcDamageSource; import noppes.npcs.entity.EntityNPCInterface; +import noppes.npcs.wrapper.nbt.MC1710NBTCompound; import java.util.List; @@ -738,7 +739,7 @@ public class EntityEnergyPanel extends EntityEnergyBarrier { nbt.setInteger("PanelMode", mode.ordinal()); nbt.setFloat("TargetPanelWidth", targetPanelWidth); nbt.setFloat("TargetPanelHeight", targetPanelHeight); - panelData.writeNBT(nbt); + panelData.writeNBT(new MC1710NBTCompound(nbt)); } @Override @@ -748,7 +749,7 @@ public class EntityEnergyPanel extends EntityEnergyBarrier { int modeOrdinal = nbt.getInteger("PanelMode"); this.mode = (modeOrdinal >= 0 && modeOrdinal < PanelMode.values().length) ? PanelMode.values()[modeOrdinal] : PanelMode.PLACED; - panelData.readNBT(nbt); + panelData.readNBT(new MC1710NBTCompound(nbt)); panelData.panelWidth = sanitize(panelData.panelWidth, 3.0f, MAX_ENTITY_SIZE); panelData.panelHeight = sanitize(panelData.panelHeight, 3.0f, MAX_ENTITY_SIZE); this.targetPanelWidth = sanitize(nbt.hasKey("TargetPanelWidth") ? nbt.getFloat("TargetPanelWidth") : panelData.panelWidth, 3.0f, MAX_ENTITY_SIZE); diff --git a/src/main/java/kamkeel/npcs/entity/EntityEnergyProjectile.java b/src/main/java/kamkeel/npcs/entity/EntityEnergyProjectile.java index 702c62c4d..fb1029847 100644 --- a/src/main/java/kamkeel/npcs/entity/EntityEnergyProjectile.java +++ b/src/main/java/kamkeel/npcs/entity/EntityEnergyProjectile.java @@ -47,6 +47,7 @@ import noppes.npcs.controllers.data.Party; import noppes.npcs.controllers.data.PlayerData; import noppes.npcs.entity.EntityNPCInterface; import noppes.npcs.scripted.NpcAPI; +import noppes.npcs.wrapper.nbt.MC1710NBTCompound; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -2478,10 +2479,10 @@ public abstract class EntityEnergyProjectile extends EntityEnergyAbility { this.renderCurrentSize = this.size; this.prevRenderSize = this.size; - anchorData.readNBT(nbt); - combatData.readNBT(nbt); - homingData.readNBT(nbt); - lifespanData.readNBT(nbt); + anchorData.readNBT(new MC1710NBTCompound(nbt)); + combatData.readNBT(new MC1710NBTCompound(nbt)); + homingData.readNBT(new MC1710NBTCompound(nbt)); + lifespanData.readNBT(new MC1710NBTCompound(nbt)); syncProjectileColorWatchers(); } @@ -2513,10 +2514,10 @@ public abstract class EntityEnergyProjectile extends EntityEnergyAbility { nbt.setDouble("MotionY", motionY); nbt.setDouble("MotionZ", motionZ); - anchorData.writeNBT(nbt); - combatData.writeNBT(nbt); - homingData.writeNBT(nbt); - lifespanData.writeNBT(nbt); + anchorData.writeNBT(new MC1710NBTCompound(nbt)); + combatData.writeNBT(new MC1710NBTCompound(nbt)); + homingData.writeNBT(new MC1710NBTCompound(nbt)); + lifespanData.writeNBT(new MC1710NBTCompound(nbt)); } /** diff --git a/src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformDamageSource.java b/src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformDamageSource.java new file mode 100644 index 000000000..763698651 --- /dev/null +++ b/src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformDamageSource.java @@ -0,0 +1,34 @@ +package kamkeel.npcs.wrapper.platform; + +import kamkeel.npcs.platform.entity.IPlatformDamageSource; +import kamkeel.npcs.platform.entity.IPlatformEntity; +import net.minecraft.util.DamageSource; + +/** + * MC 1.7.10 implementation of {@link IPlatformDamageSource}. + * Wraps a raw {@link DamageSource} instance. + */ +public class MC1710PlatformDamageSource implements IPlatformDamageSource { + + private final DamageSource source; + + public MC1710PlatformDamageSource(DamageSource source) { + this.source = source; + } + + @Override + public String getType() { + return source.getDamageType(); + } + + @Override + public IPlatformEntity getSourceEntity() { + if (source.getEntity() == null) return null; + return new MC1710PlatformEntity(source.getEntity()); + } + + @Override + public Object getHandle() { + return source; + } +} diff --git a/src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformEntity.java b/src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformEntity.java new file mode 100644 index 000000000..cb6f10472 --- /dev/null +++ b/src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformEntity.java @@ -0,0 +1,73 @@ +package kamkeel.npcs.wrapper.platform; + +import kamkeel.npcs.platform.entity.IPlatformEntity; +import kamkeel.npcs.platform.entity.IPlatformWorld; +import net.minecraft.entity.Entity; + +/** + * MC 1.7.10 implementation of {@link IPlatformEntity}. + * Wraps a raw {@link Entity} instance. + */ +public class MC1710PlatformEntity implements IPlatformEntity { + + protected final Entity entity; + + public MC1710PlatformEntity(Entity entity) { + this.entity = entity; + } + + @Override + public int getEntityId() { + return entity.getEntityId(); + } + + @Override + public String getUniqueID() { + return entity.getUniqueID().toString(); + } + + @Override + public double getX() { + return entity.posX; + } + + @Override + public double getY() { + return entity.posY; + } + + @Override + public double getZ() { + return entity.posZ; + } + + @Override + public float getYaw() { + return entity.rotationYaw; + } + + @Override + public float getPitch() { + return entity.rotationPitch; + } + + @Override + public void setPosition(double x, double y, double z) { + entity.setPosition(x, y, z); + } + + @Override + public boolean isAlive() { + return !entity.isDead; + } + + @Override + public IPlatformWorld getWorld() { + return new MC1710PlatformWorld(entity.worldObj); + } + + @Override + public Object getHandle() { + return entity; + } +} diff --git a/src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformLiving.java b/src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformLiving.java new file mode 100644 index 000000000..a9881bfb1 --- /dev/null +++ b/src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformLiving.java @@ -0,0 +1,41 @@ +package kamkeel.npcs.wrapper.platform; + +import kamkeel.npcs.platform.entity.IPlatformDamageSource; +import kamkeel.npcs.platform.entity.IPlatformLiving; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.DamageSource; + +/** + * MC 1.7.10 implementation of {@link IPlatformLiving}. + * Wraps a raw {@link EntityLivingBase} instance. + */ +public class MC1710PlatformLiving extends MC1710PlatformEntity implements IPlatformLiving { + + protected final EntityLivingBase living; + + public MC1710PlatformLiving(EntityLivingBase living) { + super(living); + this.living = living; + } + + @Override + public float getHealth() { + return living.getHealth(); + } + + @Override + public void setHealth(float hp) { + living.setHealth(hp); + } + + @Override + public float getMaxHealth() { + return living.getMaxHealth(); + } + + @Override + public void damage(float amount, IPlatformDamageSource source) { + DamageSource mcSource = source != null ? (DamageSource) source.getHandle() : DamageSource.generic; + living.attackEntityFrom(mcSource, amount); + } +} diff --git a/src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformPlayer.java b/src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformPlayer.java new file mode 100644 index 000000000..adbc1ce97 --- /dev/null +++ b/src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformPlayer.java @@ -0,0 +1,47 @@ +package kamkeel.npcs.wrapper.platform; + +import kamkeel.npcs.platform.entity.IPlatformPlayer; +import kamkeel.npcs.platform.entity.IPlatformStack; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.ChatComponentText; + +/** + * MC 1.7.10 implementation of {@link IPlatformPlayer}. + * Wraps a raw {@link EntityPlayerMP} instance. + */ +public class MC1710PlatformPlayer extends MC1710PlatformLiving implements IPlatformPlayer { + + private final EntityPlayerMP player; + + public MC1710PlatformPlayer(EntityPlayerMP player) { + super(player); + this.player = player; + } + + @Override + public String getName() { + return player.getCommandSenderName(); + } + + @Override + public String getUniqueID() { + return player.getUniqueID().toString(); + } + + @Override + public boolean isOp() { + return player.mcServer.getConfigurationManager() + .func_152596_g(player.getGameProfile()); + } + + @Override + public void sendMessage(String text) { + player.addChatMessage(new ChatComponentText(text)); + } + + @Override + public IPlatformStack getHeldItem() { + if (player.getHeldItem() == null) return null; + return new MC1710PlatformStack(player.getHeldItem()); + } +} diff --git a/src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformStack.java b/src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformStack.java new file mode 100644 index 000000000..f311dbf49 --- /dev/null +++ b/src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformStack.java @@ -0,0 +1,75 @@ +package kamkeel.npcs.wrapper.platform; + +import kamkeel.npcs.platform.entity.IPlatformStack; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import noppes.npcs.platform.nbt.INBTCompound; +import noppes.npcs.wrapper.nbt.MC1710NBTCompound; + +/** + * MC 1.7.10 implementation of {@link IPlatformStack}. + * Wraps a raw {@link ItemStack} instance. + */ +public class MC1710PlatformStack implements IPlatformStack { + + private final ItemStack stack; + + public MC1710PlatformStack(ItemStack stack) { + this.stack = stack; + } + + @Override + public String getItemId() { + if (stack == null || stack.getItem() == null) return "minecraft:air"; + return Item.itemRegistry.getNameForObject(stack.getItem()); + } + + @Override + public int getCount() { + return stack != null ? stack.stackSize : 0; + } + + @Override + public void setCount(int count) { + if (stack != null) stack.stackSize = count; + } + + @Override + public int getDamage() { + return stack != null ? stack.getItemDamage() : 0; + } + + @Override + public void setDamage(int dmg) { + if (stack != null) stack.setItemDamage(dmg); + } + + @Override + public INBTCompound getTag() { + if (stack == null || stack.stackTagCompound == null) return null; + return new MC1710NBTCompound(stack.stackTagCompound); + } + + @Override + public void setTag(INBTCompound tag) { + if (stack != null) { + stack.stackTagCompound = tag != null ? ((MC1710NBTCompound) tag).getMCTag() : null; + } + } + + @Override + public boolean isEmpty() { + return stack == null || stack.getItem() == null || stack.stackSize <= 0; + } + + @Override + public IPlatformStack copy() { + if (stack == null) return new MC1710PlatformStack(null); + return new MC1710PlatformStack(stack.copy()); + } + + @Override + public Object getHandle() { + return stack; + } +} diff --git a/src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformWorld.java b/src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformWorld.java new file mode 100644 index 000000000..de286b54f --- /dev/null +++ b/src/main/java/kamkeel/npcs/wrapper/platform/MC1710PlatformWorld.java @@ -0,0 +1,41 @@ +package kamkeel.npcs.wrapper.platform; + +import kamkeel.npcs.platform.entity.IPlatformEntity; +import kamkeel.npcs.platform.entity.IPlatformWorld; +import net.minecraft.entity.Entity; +import net.minecraft.world.World; + +/** + * MC 1.7.10 implementation of {@link IPlatformWorld}. + * Wraps a raw {@link World} instance. + */ +public class MC1710PlatformWorld implements IPlatformWorld { + + private final World world; + + public MC1710PlatformWorld(World world) { + this.world = world; + } + + @Override + public int getDimensionId() { + return world.provider.dimensionId; + } + + @Override + public boolean isClient() { + return world.isRemote; + } + + @Override + public IPlatformEntity getEntityById(int id) { + Entity entity = world.getEntityByID(id); + if (entity == null) return null; + return new MC1710PlatformEntity(entity); + } + + @Override + public Object getHandle() { + return world; + } +} diff --git a/src/main/java/noppes/npcs/controllers/data/PlayerData.java b/src/main/java/noppes/npcs/controllers/data/PlayerData.java index 18f5b2890..6d914513e 100644 --- a/src/main/java/noppes/npcs/controllers/data/PlayerData.java +++ b/src/main/java/noppes/npcs/controllers/data/PlayerData.java @@ -57,7 +57,7 @@ public class PlayerData implements IExtendedEntityProperties, IPlayerData { public PlayerItemGiverData itemgiverData = new PlayerItemGiverData(this); public PlayerMailData mailData = new PlayerMailData(this); public AnimationData animationData = new AnimationData(this); - public PlayerEffectData effectData = new PlayerEffectData(this); + public PlayerEffectData effectData = new PlayerEffectData(); public DataTimers timers = new DataTimers(this); public DataSkinOverlays skinOverlays = new DataSkinOverlays(this); public MagicData magicData = new MagicData(); @@ -151,7 +151,7 @@ public class PlayerData implements IExtendedEntityProperties, IPlayerData { timers.readFromNBT(data); skinOverlays.readFromNBT(data); animationData.readFromNBT(data); - effectData.readFromNBT(data); + effectData.readFromNBT(new MC1710NBTCompound(data)); magicData.readToNBT(new MC1710NBTCompound(data)); tradeData.readFromNBT(data); abilityData.readFromNBT(data); @@ -196,7 +196,7 @@ public class PlayerData implements IExtendedEntityProperties, IPlayerData { timers.writeToNBT(compound); skinOverlays.writeToNBT(compound); animationData.writeToNBT(compound); - effectData.writeToNBT(compound); + effectData.writeToNBT(new MC1710NBTCompound(compound)); magicData.writeToNBT(new MC1710NBTCompound(compound)); tradeData.writeToNBT(compound); abilityData.writeToNBT(compound); @@ -233,12 +233,12 @@ public class PlayerData implements IExtendedEntityProperties, IPlayerData { public NBTTagCompound getPlayerEffects() { NBTTagCompound compound = new NBTTagCompound(); - effectData.writeToNBT(compound); + effectData.writeToNBT(new MC1710NBTCompound(compound)); return compound; } public void setPlayerEffects(NBTTagCompound data) { - effectData.readFromNBT(data); + effectData.readFromNBT(new MC1710NBTCompound(data)); } public NBTTagCompound getSyncNBTFull() { diff --git a/src/main/java/noppes/npcs/wrapper/MC1710PlatformService.java b/src/main/java/noppes/npcs/wrapper/MC1710PlatformService.java index a11ede11e..5108ddc49 100644 --- a/src/main/java/noppes/npcs/wrapper/MC1710PlatformService.java +++ b/src/main/java/noppes/npcs/wrapper/MC1710PlatformService.java @@ -1,12 +1,21 @@ package noppes.npcs.wrapper; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.DamageSource; +import net.minecraft.world.World; import noppes.npcs.CustomNpcs; import noppes.npcs.platform.PlatformService; +import kamkeel.npcs.platform.entity.*; import noppes.npcs.platform.nbt.INBTCompound; import noppes.npcs.platform.nbt.INBTList; import noppes.npcs.platform.nbt.NBTFactory; import noppes.npcs.wrapper.nbt.MC1710NBTFactory; import noppes.npcs.wrapper.nbt.MC1710NBTIO; +import kamkeel.npcs.wrapper.platform.*; import java.io.File; import java.io.IOException; @@ -91,4 +100,50 @@ public class MC1710PlatformService implements PlatformService { public void logDebug(String message) { System.out.println("[CustomNPC+ DEBUG] " + message); } + + // --- Entity Wrapping --- + + @Override + public IPlatformPlayer wrapPlayer(Object mcPlayer) { + return new MC1710PlatformPlayer((EntityPlayerMP) mcPlayer); + } + + @Override + public IPlatformEntity wrapEntity(Object mcEntity) { + return new MC1710PlatformEntity((Entity) mcEntity); + } + + @Override + public IPlatformLiving wrapLiving(Object mcLiving) { + return new MC1710PlatformLiving((EntityLivingBase) mcLiving); + } + + @Override + public IPlatformStack wrapStack(Object mcStack) { + return new MC1710PlatformStack((ItemStack) mcStack); + } + + @Override + public IPlatformWorld wrapWorld(Object mcWorld) { + return new MC1710PlatformWorld((World) mcWorld); + } + + @Override + public IPlatformDamageSource wrapDamageSource(Object mcSource) { + return new MC1710PlatformDamageSource((DamageSource) mcSource); + } + + // --- Scheduling --- + + @Override + public void runOnMainThread(Runnable task) { + MinecraftServer server = MinecraftServer.getServer(); + if (server != null) { + // 1.7.10 doesn't have addScheduledTask — just run directly if on main thread + // or queue via the server's next tick + task.run(); + } else { + task.run(); + } + } }