mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-13 06:37:34 +00:00
Merge remote-tracking branch 'origin/syntax-highlighter-unified' into syntax-highlighter-unified
This commit is contained in:
commit
81d5cc25a6
59 files changed
+905
-211
No files matched your search
@@ -401,6 +401,24 @@ public class AbilityController implements IAbilityHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public Ability cloneCustomAbility(String originalName) {
|
||||
Ability original = customAbilities.get(originalName);
|
||||
if (original == null || original.isBuiltIn()) return null;
|
||||
|
||||
NBTTagCompound nbt = original.writeNBT(true);
|
||||
nbt.setString("id", UUID.randomUUID().toString());
|
||||
|
||||
Ability clone = fromNBT(nbt);
|
||||
if (clone == null) return null;
|
||||
|
||||
String name = clone.getName();
|
||||
while (customAbilities.containsKey(name)) name += "_";
|
||||
clone.setName(name);
|
||||
|
||||
saveCustomAbility(clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
public boolean deleteCustomAbility(String name) {
|
||||
if (name == null || name.isEmpty()) return false;
|
||||
|
||||
@@ -748,6 +766,24 @@ public class AbilityController implements IAbilityHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public ChainedAbility cloneChainedAbility(String originalName) {
|
||||
ChainedAbility original = chainedAbilities.get(originalName);
|
||||
if (original == null) return null;
|
||||
|
||||
NBTTagCompound nbt = original.writeNBT(true);
|
||||
nbt.setString("Id", UUID.randomUUID().toString());
|
||||
|
||||
ChainedAbility clone = new ChainedAbility();
|
||||
clone.readNBT(nbt);
|
||||
|
||||
String name = clone.getName();
|
||||
while (chainedAbilities.containsKey(name)) name += "_";
|
||||
clone.setName(name);
|
||||
|
||||
saveChainedAbility(clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
public boolean deleteChainedAbility(String name) {
|
||||
if (name == null || name.isEmpty()) return false;
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package kamkeel.npcs.controllers;
|
||||
|
||||
import kamkeel.npcs.controllers.data.energy.IEnergyHandler;
|
||||
import kamkeel.npcs.controllers.data.energy.IEnergyExtender;
|
||||
import kamkeel.npcs.entity.*;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.world.World;
|
||||
import noppes.npcs.api.IEnergyController;
|
||||
import noppes.npcs.api.IEnergyHandler;
|
||||
import noppes.npcs.api.IWorld;
|
||||
import noppes.npcs.api.entity.*;
|
||||
import noppes.npcs.api.entity.IEnergyExplosion;
|
||||
@@ -22,22 +22,22 @@ import java.util.List;
|
||||
* damage through registered handlers when entities have customDamageData
|
||||
* but no sourceAbility.
|
||||
*/
|
||||
public class EnergyController implements IEnergyController {
|
||||
public class EnergyController implements IEnergyHandler {
|
||||
|
||||
public static EnergyController Instance = new EnergyController();
|
||||
|
||||
private final List<IEnergyHandler> handlers = new ArrayList<>();
|
||||
private final List<IEnergyExtender> extenders = new ArrayList<>();
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// HANDLER REGISTRATION
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
public void registerHandler(IEnergyHandler handler) {
|
||||
handlers.add(handler);
|
||||
public void registerExtender(IEnergyExtender handler) {
|
||||
extenders.add(handler);
|
||||
}
|
||||
|
||||
public List<IEnergyHandler> getHandlers() {
|
||||
return handlers;
|
||||
public List<IEnergyExtender> getExtenders() {
|
||||
return extenders;
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
@@ -53,7 +53,7 @@ public class EnergyController implements IEnergyController {
|
||||
double kbDirX, double kbDirZ,
|
||||
float damageMultiplier,
|
||||
NBTTagCompound damageData) {
|
||||
for (IEnergyHandler handler : handlers) {
|
||||
for (IEnergyExtender handler : extenders) {
|
||||
if (handler.onEnergyDamage(energyEntity, owner, target, damage,
|
||||
knockback, knockbackUp, kbDirX, kbDirZ, damageMultiplier, damageData)) {
|
||||
return true;
|
||||
@@ -68,7 +68,7 @@ public class EnergyController implements IEnergyController {
|
||||
public float fireModifyEnergyDamage(Entity energyEntity, EntityLivingBase owner,
|
||||
float baseDamage, NBTTagCompound damageData) {
|
||||
float damage = baseDamage;
|
||||
for (IEnergyHandler handler : handlers) {
|
||||
for (IEnergyExtender handler : extenders) {
|
||||
damage = handler.modifyEnergyDamage(energyEntity, owner, damage, damageData);
|
||||
}
|
||||
return damage;
|
||||
@@ -150,7 +150,7 @@ public class EnergyController implements IEnergyController {
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// IEnergyController (Script API methods)
|
||||
// IEnergyHandler (Script API methods)
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
@Override
|
||||
|
||||
@@ -184,6 +184,14 @@ public class SyncController {
|
||||
DBCAddon.instance.syncPlayer(player);
|
||||
syncPlayerData(player, false);
|
||||
PartyInfoPacket.sendPartyData(player);
|
||||
|
||||
// Sync skin overlays after full handshake to ensure the client is ready.
|
||||
// Overlays are not part of getSyncNBTFull(), and packets sent during
|
||||
// PlayerLoggedInEvent can arrive before the client entity exists.
|
||||
PlayerData data = PlayerData.get(player);
|
||||
if (data != null) {
|
||||
data.skinOverlays.updateClient();
|
||||
}
|
||||
}
|
||||
|
||||
private static EnumMap<EnumSyncType, Integer> getServerRevisionSnapshot() {
|
||||
|
||||
@@ -308,6 +308,11 @@ public class TelegraphController implements ITelegraphHandler {
|
||||
return new ScriptTelegraph(Telegraph.cone(length, angle));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITelegraph createSquare(float radius) {
|
||||
return new ScriptTelegraph(Telegraph.square(radius));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITelegraph createPoint() {
|
||||
return new ScriptTelegraph(Telegraph.point());
|
||||
@@ -332,6 +337,9 @@ public class TelegraphController implements ITelegraphHandler {
|
||||
case CONE:
|
||||
telegraph = Telegraph.cone(5.0f, 45.0f);
|
||||
break;
|
||||
case SQUARE:
|
||||
telegraph = Telegraph.square(3.0f);
|
||||
break;
|
||||
case POINT:
|
||||
telegraph = Telegraph.point();
|
||||
break;
|
||||
|
||||
@@ -5,6 +5,8 @@ import kamkeel.npcs.controllers.data.ability.data.ChainedAbility;
|
||||
import kamkeel.npcs.controllers.data.ability.data.IAbilityAction;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Unified slot for storing any combat action: inline ability, ability reference, or chain reference.
|
||||
* Support for all {@link IAbilityAction} types.
|
||||
@@ -218,7 +220,9 @@ public class AbilityAction {
|
||||
Ability resolved = getAbility();
|
||||
if (resolved == null) return false;
|
||||
|
||||
inlineAbility = AbilityController.Instance.fromNBT(resolved.writeNBT(true));
|
||||
NBTTagCompound nbt = resolved.writeNBT(true);
|
||||
nbt.setString("id", UUID.randomUUID().toString());
|
||||
inlineAbility = AbilityController.Instance.fromNBT(nbt);
|
||||
slotType = SlotType.INLINE_ABILITY;
|
||||
referenceId = null;
|
||||
cachedAction = null;
|
||||
@@ -230,7 +234,10 @@ public class AbilityAction {
|
||||
ChainedAbility resolved = getChainedAbility();
|
||||
if (resolved == null) return false;
|
||||
|
||||
inlineChain = resolved.deepCopy();
|
||||
inlineChain = new ChainedAbility();
|
||||
NBTTagCompound chainNbt = resolved.writeNBT(true);
|
||||
chainNbt.setString("Id", UUID.randomUUID().toString());
|
||||
inlineChain.readNBT(chainNbt);
|
||||
slotType = SlotType.INLINE_CHAIN;
|
||||
referenceId = null;
|
||||
cachedAction = null;
|
||||
|
||||
+16
@@ -32,6 +32,11 @@ public class EnergyBarrierData {
|
||||
|
||||
// Absorbing: caster's damage is redirected to the barrier
|
||||
public boolean absorbing = false;
|
||||
// Absorb radius: max distance from barrier's current position for absorption to work
|
||||
// -1 = no radius limit (absorb regardless of distance)
|
||||
// 0 = use barrier's own extent as the radius (dome radius, panel half-size, etc.)
|
||||
// positive = owner must be within this many blocks of the barrier entity
|
||||
public float absorbRadius = 0.0f;
|
||||
|
||||
// Melee: barrier can be hit by melee attacks
|
||||
public boolean meleeEnabled = false;
|
||||
@@ -148,6 +153,14 @@ public class EnergyBarrierData {
|
||||
this.targetOwner = targetOwner;
|
||||
}
|
||||
|
||||
public float getAbsorbRadius() {
|
||||
return absorbRadius;
|
||||
}
|
||||
|
||||
public void setAbsorbRadius(float absorbRadius) {
|
||||
this.absorbRadius = absorbRadius;
|
||||
}
|
||||
|
||||
// ==================== NBT ====================
|
||||
|
||||
public void writeNBT(NBTTagCompound nbt) {
|
||||
@@ -160,6 +173,7 @@ public class EnergyBarrierData {
|
||||
nbt.setBoolean("barrierKnockback", knockbackEnabled);
|
||||
nbt.setFloat("barrierKnockbackStr", knockbackStrength);
|
||||
nbt.setBoolean("barrierAbsorbing", absorbing);
|
||||
nbt.setFloat("barrierAbsorbRadius", absorbRadius);
|
||||
nbt.setBoolean("barrierMelee", meleeEnabled);
|
||||
nbt.setFloat("barrierMeleeMult", meleeDamageMultiplier);
|
||||
nbt.setBoolean("barrierReflect", reflect);
|
||||
@@ -183,6 +197,7 @@ public class EnergyBarrierData {
|
||||
knockbackEnabled = nbt.hasKey("barrierKnockback") && nbt.getBoolean("barrierKnockback");
|
||||
knockbackStrength = nbt.hasKey("barrierKnockbackStr") ? nbt.getFloat("barrierKnockbackStr") : 1.0f;
|
||||
absorbing = nbt.hasKey("barrierAbsorbing") && nbt.getBoolean("barrierAbsorbing");
|
||||
absorbRadius = nbt.hasKey("barrierAbsorbRadius") ? nbt.getFloat("barrierAbsorbRadius") : 0.0f;
|
||||
meleeEnabled = nbt.hasKey("barrierMelee") && nbt.getBoolean("barrierMelee");
|
||||
meleeDamageMultiplier = nbt.hasKey("barrierMeleeMult") ? nbt.getFloat("barrierMeleeMult") : 1.0f;
|
||||
reflect = nbt.hasKey("barrierReflect") && nbt.getBoolean("barrierReflect");
|
||||
@@ -207,6 +222,7 @@ public class EnergyBarrierData {
|
||||
copy.knockbackEnabled = knockbackEnabled;
|
||||
copy.knockbackStrength = knockbackStrength;
|
||||
copy.absorbing = absorbing;
|
||||
copy.absorbRadius = absorbRadius;
|
||||
copy.meleeEnabled = meleeEnabled;
|
||||
copy.meleeDamageMultiplier = meleeDamageMultiplier;
|
||||
copy.reflect = reflect;
|
||||
|
||||
+5
-1
@@ -5,6 +5,8 @@ import kamkeel.npcs.controllers.data.ability.Ability;
|
||||
import kamkeel.npcs.controllers.data.ability.data.ChainedAbility;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A single entry in a {@link ChainedAbility}, representing one ability
|
||||
* to execute in sequence along with its delay configuration.
|
||||
@@ -155,7 +157,9 @@ public class ChainedAbilityEntry {
|
||||
Ability resolved = ctrl.resolveAbility(abilityReference);
|
||||
if (resolved == null) return false;
|
||||
|
||||
inlineAbility = ctrl.fromNBT(resolved.writeNBT(true));
|
||||
NBTTagCompound nbt = resolved.writeNBT(true);
|
||||
nbt.setString("id", UUID.randomUUID().toString());
|
||||
inlineAbility = ctrl.fromNBT(nbt);
|
||||
entryType = EntryType.INLINE;
|
||||
abilityReference = "";
|
||||
return true;
|
||||
|
||||
@@ -292,6 +292,14 @@ public abstract class AbilityBarrier extends AbilityEnergy {
|
||||
barrierData.absorbing = absorbing;
|
||||
}
|
||||
|
||||
public float getAbsorbRadius() {
|
||||
return barrierData.absorbRadius;
|
||||
}
|
||||
|
||||
public void setAbsorbRadius(float radius) {
|
||||
barrierData.absorbRadius = radius;
|
||||
}
|
||||
|
||||
// Reflection data
|
||||
public boolean isReflect() {
|
||||
return barrierData.reflect;
|
||||
@@ -395,6 +403,9 @@ public abstract class AbilityBarrier extends AbilityEnergy {
|
||||
.range(0, 10).visibleWhen(this::isKnockbackEnabled));
|
||||
defs.add(FieldDef.boolField("ability.absorbing", this::isAbsorbing, this::setAbsorbing)
|
||||
.hover("ability.hover.absorbing"));
|
||||
defs.add(FieldDef.floatField("ability.absorbRadius", this::getAbsorbRadius, this::setAbsorbRadius)
|
||||
.range(-1, 128).visibleWhen(this::isAbsorbing)
|
||||
.hover("ability.hover.absorbRadius"));
|
||||
defs.add(FieldDef.boolField("ability.reflect", this::isReflect, this::setReflect)
|
||||
.hover("ability.hover.reflect"));
|
||||
defs.add(FieldDef.floatField("ability.reflectStrength", this::getReflectStrengthPct, this::setReflectStrengthPct)
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ import net.minecraft.nbt.NBTTagCompound;
|
||||
* Registered with EnergyController. DBC Addon implements this to route
|
||||
* script-created energy entity damage through the DBC damage pipeline.
|
||||
*/
|
||||
public interface IEnergyHandler {
|
||||
public interface IEnergyExtender {
|
||||
|
||||
/**
|
||||
* Handle damage for an energy entity with custom damage data.
|
||||
@@ -201,7 +201,7 @@ public class EntityAbilityZone extends Entity implements IEntityAdditionalSpawnD
|
||||
double x, double y, double z) {
|
||||
this(world);
|
||||
this.zoneType = type;
|
||||
this.ownerEntityId = owner.getEntityId();
|
||||
this.ownerEntityId = owner != null ? owner.getEntityId() : -1;
|
||||
// Snap to ground with tiny offset to prevent z-clipping
|
||||
double groundY = Ability.findGroundLevel(world, x, y, z) + GROUND_OFFSET;
|
||||
this.setPosition(x, groundY, z);
|
||||
@@ -213,7 +213,7 @@ public class EntityAbilityZone extends Entity implements IEntityAdditionalSpawnD
|
||||
*/
|
||||
public void initAsHazard(Entity owner, double x, double y, double z) {
|
||||
this.zoneType = ZoneType.HAZARD;
|
||||
this.ownerEntityId = owner.getEntityId();
|
||||
this.ownerEntityId = owner != null ? owner.getEntityId() : -1;
|
||||
double groundY = Ability.findGroundLevel(worldObj, x, y, z) + GROUND_OFFSET;
|
||||
this.setPosition(x, groundY, z);
|
||||
this.ticksSinceDamage = damageInterval;
|
||||
@@ -225,7 +225,7 @@ public class EntityAbilityZone extends Entity implements IEntityAdditionalSpawnD
|
||||
*/
|
||||
public void initAsTrap(Entity owner, double x, double y, double z) {
|
||||
this.zoneType = ZoneType.TRAP;
|
||||
this.ownerEntityId = owner.getEntityId();
|
||||
this.ownerEntityId = owner != null ? owner.getEntityId() : -1;
|
||||
double groundY = Ability.findGroundLevel(worldObj, x, y, z) + GROUND_OFFSET;
|
||||
this.setPosition(x, groundY, z);
|
||||
this.ticksSinceLastTrigger = triggerCooldown;
|
||||
@@ -321,6 +321,16 @@ public class EntityAbilityZone extends Entity implements IEntityAdditionalSpawnD
|
||||
protected void entityInit() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readEntityFromNBT(NBTTagCompound nbt) {
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeEntityToNBT(NBTTagCompound nbt) {
|
||||
// Intentionally empty — ability entities are transient (not saved to world)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleHealthUpdate(byte id) {
|
||||
if (id == TRIGGER_FLASH_STATUS) {
|
||||
@@ -834,15 +844,6 @@ public class EntityAbilityZone extends Entity implements IEntityAdditionalSpawnD
|
||||
// NBT SERIALIZATION
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
@Override
|
||||
protected void readEntityFromNBT(NBTTagCompound nbt) {
|
||||
// Intentionally empty — ability entities are transient (not saved to world)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeEntityToNBT(NBTTagCompound nbt) {
|
||||
// Intentionally empty — ability entities are transient (not saved to world)
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// SPAWN DATA (ByteBuf for client sync)
|
||||
|
||||
@@ -376,6 +376,22 @@ public abstract class EntityEnergyAbility extends Entity implements IEntityAddit
|
||||
magicData.readToNBT(nbt);
|
||||
}
|
||||
|
||||
// ==================== WORLD NBT (INTENTIONALLY EMPTY) ====================
|
||||
|
||||
/**
|
||||
* Ability entities are transient — they must not survive world saves.
|
||||
* If Minecraft deserializes one from a chunk, kill it immediately.
|
||||
*/
|
||||
@Override
|
||||
protected void readEntityFromNBT(NBTTagCompound nbt) {
|
||||
this.setDead();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeEntityToNBT(NBTTagCompound nbt) {
|
||||
// Intentionally empty — ability entities are transient (not saved to world)
|
||||
}
|
||||
|
||||
// ==================== SPAWN DATA ====================
|
||||
|
||||
/**
|
||||
|
||||
@@ -630,7 +630,13 @@ public abstract class EntityEnergyBarrier extends EntityEnergyAbility {
|
||||
|
||||
/**
|
||||
* Find a barrier that would absorb damage for the given entity (its caster).
|
||||
* Returns the barrier if: absorbing is enabled AND entity is the barrier's owner.
|
||||
* Returns the barrier if: absorbing is enabled, entity is the barrier's owner,
|
||||
* and entity is within the barrier's absorb radius of the barrier's current position.
|
||||
*
|
||||
* Absorb radius behavior:
|
||||
* -1 = no limit (absorb regardless of distance)
|
||||
* 0 = uses the barrier's extent as the radius (dome radius, panel half-size, etc.)
|
||||
* >0 = owner must be within this many blocks of the barrier entity
|
||||
*/
|
||||
public static EntityEnergyBarrier getAbsorbingBarrier(Entity entity) {
|
||||
if (entity == null || entity.worldObj == null) return null;
|
||||
@@ -638,7 +644,33 @@ public abstract class EntityEnergyBarrier extends EntityEnergyAbility {
|
||||
for (EntityEnergyBarrier barrier : barriers) {
|
||||
if (barrier.isDead) continue;
|
||||
if (!barrier.barrierData.absorbing) continue;
|
||||
if (barrier.ownerEntityId == entity.getEntityId()) {
|
||||
if (barrier.ownerEntityId != entity.getEntityId()) continue;
|
||||
|
||||
float absorbRadius = barrier.barrierData.absorbRadius;
|
||||
|
||||
// -1 = unlimited range
|
||||
if (absorbRadius < 0) {
|
||||
return barrier;
|
||||
}
|
||||
|
||||
// 0 = use barrier's own extent as the effective radius
|
||||
// Domes: dome radius. Panels: max(width, height) * 0.5 + 1.0, doubled.
|
||||
float effectiveRadius;
|
||||
if (absorbRadius > 0) {
|
||||
effectiveRadius = absorbRadius;
|
||||
} else if (barrier instanceof EntityEnergyDome) {
|
||||
effectiveRadius = barrier.getMaxExtent();
|
||||
} else {
|
||||
effectiveRadius = barrier.getMaxExtent() * 3.0f;
|
||||
}
|
||||
|
||||
// Distance check from barrier's current position to the owner
|
||||
double dx = entity.posX - barrier.posX;
|
||||
double dy = (entity.posY + entity.height * 0.5) - barrier.posY;
|
||||
double dz = entity.posZ - barrier.posZ;
|
||||
double distSq = dx * dx + dy * dy + dz * dz;
|
||||
|
||||
if (distSq <= (double) effectiveRadius * effectiveRadius) {
|
||||
return barrier;
|
||||
}
|
||||
}
|
||||
@@ -709,6 +741,13 @@ public abstract class EntityEnergyBarrier extends EntityEnergyAbility {
|
||||
double px = ent.posX + dirX * probe;
|
||||
double py = ent.posY + dirY * probe;
|
||||
double pz = ent.posZ + dirZ * probe;
|
||||
// Never probe below the entity's feet — a downward probe always detects the
|
||||
// block the entity is already standing/hovering above (false positive).
|
||||
// MC's own collision system prevents entities from falling through floors,
|
||||
// so the downward check is redundant. Upward probes (ceiling detection) still work.
|
||||
if (py < ent.posY) {
|
||||
py = ent.posY;
|
||||
}
|
||||
AxisAlignedBB box = AxisAlignedBB.getBoundingBox(
|
||||
px - halfW, py, pz - halfW,
|
||||
px + halfW, py + ent.height, pz + halfW
|
||||
|
||||
@@ -51,7 +51,7 @@ public class EntityEnergyDome extends EntityEnergyBarrier {
|
||||
this(world);
|
||||
this.noClip = true;
|
||||
this.stepHeight = 0.0F;
|
||||
this.ownerEntityId = owner.getEntityId();
|
||||
this.ownerEntityId = owner != null ? owner.getEntityId() : -1;
|
||||
this.setDomeRadius(domeRadius);
|
||||
// Defensive copy: entities must never share data objects with the source ability.
|
||||
this.displayData = display != null ? display.copy() : new EnergyDisplayData();
|
||||
@@ -351,8 +351,10 @@ public class EntityEnergyDome extends EntityEnergyBarrier {
|
||||
double radialVel = ent.motionX * nx + ent.motionY * ny + ent.motionZ * nz;
|
||||
|
||||
if (wasInside != isInside) {
|
||||
// Entity crossed the boundary this tick — push back to original side
|
||||
double pushDist = wasInside ? (r - 0.3) : (r + 0.3);
|
||||
// Entity crossed the boundary this tick — push back to original side.
|
||||
// Use a larger buffer (1.0) to prevent flying entities from crossing
|
||||
// again in a single tick (their AI hard-sets motionY every tick).
|
||||
double pushDist = wasInside ? (r - 1.0) : (r + 0.3);
|
||||
double surfaceX = posX + nx * pushDist;
|
||||
double surfaceY = posY + ny * pushDist - ent.height * 0.5;
|
||||
double surfaceZ = posZ + nz * pushDist;
|
||||
@@ -366,13 +368,16 @@ public class EntityEnergyDome extends EntityEnergyBarrier {
|
||||
|
||||
teleportEntity(ent, surfaceX, surfaceY, surfaceZ);
|
||||
|
||||
// Cancel radial velocity and add corrective push
|
||||
// Cancel radial velocity and add corrective push (all 3 axes).
|
||||
// The Y component is critical for the dome top where nx/nz ≈ 0:
|
||||
// without it, flying entities get no inward push at the apex.
|
||||
ent.motionX -= radialVel * nx;
|
||||
ent.motionY -= radialVel * ny;
|
||||
ent.motionZ -= radialVel * nz;
|
||||
double pushForce = wasInside ? -0.15 : 0.15;
|
||||
if (canPushInDirection(ent, nx * pushForce, 0, nz * pushForce)) {
|
||||
if (canPushInDirection(ent, nx * pushForce, ny * pushForce, nz * pushForce)) {
|
||||
ent.motionX += nx * pushForce;
|
||||
ent.motionY += ny * pushForce;
|
||||
ent.motionZ += nz * pushForce;
|
||||
}
|
||||
ent.velocityChanged = true;
|
||||
@@ -387,8 +392,9 @@ public class EntityEnergyDome extends EntityEnergyBarrier {
|
||||
ent.motionY -= radialVel * ny;
|
||||
ent.motionZ -= radialVel * nz;
|
||||
double pushForce = isInside ? -0.05 : 0.05;
|
||||
if (canPushInDirection(ent, nx * pushForce, 0, nz * pushForce)) {
|
||||
if (canPushInDirection(ent, nx * pushForce, ny * pushForce, nz * pushForce)) {
|
||||
ent.motionX += nx * pushForce;
|
||||
ent.motionY += ny * pushForce;
|
||||
ent.motionZ += nz * pushForce;
|
||||
}
|
||||
ent.velocityChanged = true;
|
||||
@@ -695,15 +701,6 @@ public class EntityEnergyDome extends EntityEnergyBarrier {
|
||||
|
||||
// ==================== NBT ====================
|
||||
|
||||
@Override
|
||||
protected void readEntityFromNBT(NBTTagCompound nbt) {
|
||||
// Intentionally empty — ability entities are transient (not saved to world)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeEntityToNBT(NBTTagCompound nbt) {
|
||||
// Intentionally empty — ability entities are transient (not saved to world)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeSpawnNBT(NBTTagCompound nbt) {
|
||||
|
||||
@@ -289,15 +289,6 @@ public class EntityEnergyExplosion extends EntityEnergyAbility {
|
||||
|
||||
// ==================== NBT ====================
|
||||
|
||||
@Override
|
||||
protected void readEntityFromNBT(NBTTagCompound nbt) {
|
||||
// Intentionally empty - transient visual entity.
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeEntityToNBT(NBTTagCompound nbt) {
|
||||
// Intentionally empty - transient visual entity.
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeSpawnNBT(NBTTagCompound nbt) {
|
||||
|
||||
@@ -55,7 +55,7 @@ public class EntityEnergyPanel extends EntityEnergyBarrier {
|
||||
EnergyBarrierData barrier, EnergyPanelData panel) {
|
||||
this(world);
|
||||
this.setPosition(x, y + panel.heightOffset, z);
|
||||
this.ownerEntityId = owner.getEntityId();
|
||||
this.ownerEntityId = owner != null ? owner.getEntityId() : -1;
|
||||
this.panelYaw = yaw;
|
||||
this.prevPanelYaw = yaw;
|
||||
this.mode = mode;
|
||||
@@ -730,15 +730,6 @@ public class EntityEnergyPanel extends EntityEnergyBarrier {
|
||||
|
||||
// ==================== NBT ====================
|
||||
|
||||
@Override
|
||||
protected void readEntityFromNBT(NBTTagCompound nbt) {
|
||||
// Intentionally empty — ability entities are transient (not saved to world)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeEntityToNBT(NBTTagCompound nbt) {
|
||||
// Intentionally empty — ability entities are transient (not saved to world)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeSpawnNBT(NBTTagCompound nbt) {
|
||||
|
||||
@@ -184,7 +184,7 @@ public abstract class EntityEnergyProjectile extends EntityEnergyAbility {
|
||||
this.startY = y;
|
||||
this.startZ = z;
|
||||
|
||||
this.ownerEntityId = owner.getEntityId();
|
||||
this.ownerEntityId = owner != null ? owner.getEntityId() : -1;
|
||||
this.targetEntityId = target != null ? target.getEntityId() : -1;
|
||||
|
||||
// Visual
|
||||
@@ -2413,15 +2413,6 @@ public abstract class EntityEnergyProjectile extends EntityEnergyAbility {
|
||||
|
||||
// ==================== NBT ====================
|
||||
|
||||
@Override
|
||||
protected void readEntityFromNBT(NBTTagCompound nbt) {
|
||||
// Intentionally empty — ability entities are transient (not saved to world)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeEntityToNBT(NBTTagCompound nbt) {
|
||||
// Intentionally empty — ability entities are transient (not saved to world)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeSpawnNBT(NBTTagCompound nbt) {
|
||||
|
||||
@@ -78,7 +78,7 @@ public class EntityEnergySweeper extends EntityEnergyAbility {
|
||||
boolean lockOnTarget) {
|
||||
this(world);
|
||||
|
||||
this.ownerEntityId = owner.getEntityId();
|
||||
this.ownerEntityId = owner != null ? owner.getEntityId() : -1;
|
||||
this.targetEntityId = target != null ? target.getEntityId() : -1;
|
||||
this.beamLength = beamLength;
|
||||
this.beamWidth = beamWidth;
|
||||
@@ -95,16 +95,18 @@ public class EntityEnergySweeper extends EntityEnergyAbility {
|
||||
this.maxTicks = (int) ((360.0f * numberOfRotations) / sweepSpeed) + 10;
|
||||
|
||||
// Calculate base yaw
|
||||
if (lockOnTarget && target != null) {
|
||||
if (lockOnTarget && target != null && owner != null) {
|
||||
double dx = target.posX - owner.posX;
|
||||
double dz = target.posZ - owner.posZ;
|
||||
this.baseYaw = (float) Math.toDegrees(Math.atan2(-dx, dz));
|
||||
} else {
|
||||
} else if (owner != null) {
|
||||
this.baseYaw = owner.rotationYaw;
|
||||
}
|
||||
|
||||
// Position at beam center (bottom at feet, top at feet + beamHeight)
|
||||
this.setPosition(owner.posX, owner.posY + beamHeight / 2.0, owner.posZ);
|
||||
if (owner != null) {
|
||||
this.setPosition(owner.posX, owner.posY + beamHeight / 2.0, owner.posZ);
|
||||
}
|
||||
|
||||
// Ready to deal damage immediately
|
||||
this.ticksSinceDamage = damageInterval;
|
||||
@@ -423,15 +425,6 @@ public class EntityEnergySweeper extends EntityEnergyAbility {
|
||||
|
||||
// ==================== NBT ====================
|
||||
|
||||
@Override
|
||||
protected void readEntityFromNBT(NBTTagCompound nbt) {
|
||||
// Intentionally empty — ability entities are transient (not saved to world)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeEntityToNBT(NBTTagCompound nbt) {
|
||||
// Intentionally empty — ability entities are transient (not saved to world)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeSpawnNBT(NBTTagCompound nbt) {
|
||||
|
||||
@@ -90,6 +90,7 @@ import kamkeel.npcs.network.packets.request.ability.AbilitiesNpcGetPacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.AbilitiesNpcSavePacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.BuiltInAbilityGetPacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.ChainedAbilitiesGetPacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.ChainedAbilityClonePacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.ChainedAbilityGetPacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.ChainedAbilityRemovePacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.ChainedAbilitySavePacket;
|
||||
@@ -100,6 +101,7 @@ import kamkeel.npcs.network.packets.request.category.CategoryListRequestPacket;
|
||||
import kamkeel.npcs.network.packets.request.category.CategoryMoveItemPacket;
|
||||
import kamkeel.npcs.network.packets.request.category.CategoryRemovePacket;
|
||||
import kamkeel.npcs.network.packets.request.category.CategorySavePacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.CustomAbilityClonePacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.CustomAbilityGetPacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.CustomAbilityRemovePacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.CustomAbilitySavePacket;
|
||||
@@ -136,6 +138,7 @@ import kamkeel.npcs.network.packets.request.dialog.DialogNpcSetPacket;
|
||||
import kamkeel.npcs.network.packets.request.dialog.DialogRemovePacket;
|
||||
import kamkeel.npcs.network.packets.request.dialog.DialogSavePacket;
|
||||
import kamkeel.npcs.network.packets.request.dialog.DialogsGetPacket;
|
||||
import kamkeel.npcs.network.packets.request.effects.EffectClonePacket;
|
||||
import kamkeel.npcs.network.packets.request.effects.EffectGetPacket;
|
||||
import kamkeel.npcs.network.packets.request.effects.EffectRemovePacket;
|
||||
import kamkeel.npcs.network.packets.request.effects.EffectSavePacket;
|
||||
@@ -156,6 +159,7 @@ import kamkeel.npcs.network.packets.request.jobs.JobSpawnerRemovePacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedGetAllPacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedGetPacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedItemBuildPacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedItemClonePacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedItemRemovePacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedItemSavePacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedNPCAddPacket;
|
||||
@@ -353,6 +357,7 @@ public class PacketHandler {
|
||||
REQUEST_PACKET.registerPacket(new LinkedItemSavePacket());
|
||||
REQUEST_PACKET.registerPacket(new LinkedItemRemovePacket());
|
||||
REQUEST_PACKET.registerPacket(new LinkedItemBuildPacket());
|
||||
REQUEST_PACKET.registerPacket(new LinkedItemClonePacket());
|
||||
|
||||
|
||||
// Bank Packets
|
||||
@@ -509,6 +514,7 @@ public class PacketHandler {
|
||||
REQUEST_PACKET.registerPacket(new EffectsGetPacket());
|
||||
REQUEST_PACKET.registerPacket(new EffectSavePacket());
|
||||
REQUEST_PACKET.registerPacket(new EffectRemovePacket());
|
||||
REQUEST_PACKET.registerPacket(new EffectClonePacket());
|
||||
|
||||
// Magic Packets
|
||||
REQUEST_PACKET.registerPacket(new MagicCycleRemovePacket());
|
||||
@@ -533,6 +539,8 @@ public class PacketHandler {
|
||||
REQUEST_PACKET.registerPacket(new ChainedAbilityGetPacket());
|
||||
REQUEST_PACKET.registerPacket(new ChainedAbilitySavePacket());
|
||||
REQUEST_PACKET.registerPacket(new ChainedAbilityRemovePacket());
|
||||
REQUEST_PACKET.registerPacket(new CustomAbilityClonePacket());
|
||||
REQUEST_PACKET.registerPacket(new ChainedAbilityClonePacket());
|
||||
|
||||
// Category Packets
|
||||
REQUEST_PACKET.registerPacket(new CategorySavePacket());
|
||||
|
||||
@@ -223,4 +223,9 @@ public enum EnumRequestPacket {
|
||||
CategoryListRequest,
|
||||
CategoryItemsRequest,
|
||||
AbilityCategoryMoveItem,
|
||||
|
||||
CustomAbilityClone,
|
||||
ChainedAbilityClone,
|
||||
LinkedItemClone,
|
||||
EffectClone,
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package kamkeel.npcs.network.packets.request.ability;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import kamkeel.npcs.controllers.AbilityController;
|
||||
import kamkeel.npcs.controllers.data.ability.data.ChainedAbility;
|
||||
import kamkeel.npcs.network.AbstractPacket;
|
||||
import kamkeel.npcs.network.PacketChannel;
|
||||
import kamkeel.npcs.network.PacketHandler;
|
||||
import kamkeel.npcs.network.PacketUtil;
|
||||
import kamkeel.npcs.network.enums.EnumItemPacketType;
|
||||
import kamkeel.npcs.network.enums.EnumRequestPacket;
|
||||
import kamkeel.npcs.network.packets.data.large.GuiDataPacket;
|
||||
import kamkeel.npcs.util.ByteBufUtils;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import noppes.npcs.CustomNpcsPermissions;
|
||||
import noppes.npcs.NoppesUtilServer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public final class ChainedAbilityClonePacket extends AbstractPacket {
|
||||
public static String packetName = "Request|ChainedAbilityClone";
|
||||
|
||||
private String name;
|
||||
|
||||
public ChainedAbilityClonePacket() {
|
||||
}
|
||||
|
||||
public ChainedAbilityClonePacket(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getType() {
|
||||
return EnumRequestPacket.ChainedAbilityClone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketChannel getChannel() {
|
||||
return PacketHandler.REQUEST_PACKET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomNpcsPermissions.Permission getPermission() {
|
||||
return CustomNpcsPermissions.GLOBAL_ABILITY;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public void sendData(ByteBuf out) throws IOException {
|
||||
ByteBufUtils.writeString(out, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveData(ByteBuf in, EntityPlayer player) throws IOException {
|
||||
if (!(player instanceof EntityPlayerMP))
|
||||
return;
|
||||
|
||||
if (!PacketUtil.verifyItemPacket(packetName, EnumItemPacketType.WAND, player))
|
||||
return;
|
||||
|
||||
String chainName = ByteBufUtils.readString(in);
|
||||
ChainedAbility clone = AbilityController.Instance.cloneChainedAbility(chainName);
|
||||
if (clone != null) {
|
||||
NoppesUtilServer.sendChainedAbilitiesData((EntityPlayerMP) player);
|
||||
GuiDataPacket.sendGuiData((EntityPlayerMP) player, clone.writeNBT(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package kamkeel.npcs.network.packets.request.ability;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import kamkeel.npcs.controllers.AbilityController;
|
||||
import kamkeel.npcs.controllers.data.ability.Ability;
|
||||
import kamkeel.npcs.network.AbstractPacket;
|
||||
import kamkeel.npcs.network.PacketChannel;
|
||||
import kamkeel.npcs.network.PacketHandler;
|
||||
import kamkeel.npcs.network.PacketUtil;
|
||||
import kamkeel.npcs.network.enums.EnumItemPacketType;
|
||||
import kamkeel.npcs.network.enums.EnumRequestPacket;
|
||||
import kamkeel.npcs.network.packets.data.large.GuiDataPacket;
|
||||
import kamkeel.npcs.util.ByteBufUtils;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import noppes.npcs.CustomNpcsPermissions;
|
||||
import noppes.npcs.NoppesUtilServer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public final class CustomAbilityClonePacket extends AbstractPacket {
|
||||
public static String packetName = "Request|CustomAbilityClone";
|
||||
|
||||
private String name;
|
||||
|
||||
public CustomAbilityClonePacket() {
|
||||
}
|
||||
|
||||
public CustomAbilityClonePacket(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getType() {
|
||||
return EnumRequestPacket.CustomAbilityClone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketChannel getChannel() {
|
||||
return PacketHandler.REQUEST_PACKET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomNpcsPermissions.Permission getPermission() {
|
||||
return CustomNpcsPermissions.GLOBAL_ABILITY;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public void sendData(ByteBuf out) throws IOException {
|
||||
ByteBufUtils.writeString(out, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveData(ByteBuf in, EntityPlayer player) throws IOException {
|
||||
if (!(player instanceof EntityPlayerMP))
|
||||
return;
|
||||
|
||||
if (!PacketUtil.verifyItemPacket(packetName, EnumItemPacketType.WAND, player))
|
||||
return;
|
||||
|
||||
String abilityName = ByteBufUtils.readString(in);
|
||||
Ability clone = AbilityController.Instance.cloneCustomAbility(abilityName);
|
||||
if (clone != null) {
|
||||
NoppesUtilServer.sendCustomAbilitiesData((EntityPlayerMP) player);
|
||||
GuiDataPacket.sendGuiData((EntityPlayerMP) player, clone.writeNBT(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -14,6 +14,7 @@ import kamkeel.npcs.util.ByteBufUtils;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import noppes.npcs.constants.EnumCategoryType;
|
||||
import noppes.npcs.controllers.CategoryManager;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -63,6 +64,11 @@ public final class AbilityCategoryMovePacket extends AbstractPacket {
|
||||
String itemName = ByteBufUtils.readString(in);
|
||||
int cat = in.readInt();
|
||||
|
||||
// Validate target category exists (0 = Uncategorized is always valid)
|
||||
CategoryManager cm = CategorySavePacket.getManager(type);
|
||||
if (cm == null) return;
|
||||
if (cat != CategoryManager.UNCATEGORIZED_ID && cm.getCategory(cat) == null) return;
|
||||
|
||||
switch (type) {
|
||||
case EnumCategoryType.ABILITY:
|
||||
AbilityController.Instance.moveCustomAbilityToCategory(itemName, cat);
|
||||
|
||||
+6
@@ -14,6 +14,7 @@ import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import kamkeel.npcs.controllers.AbilityController;
|
||||
import noppes.npcs.constants.EnumCategoryType;
|
||||
import noppes.npcs.controllers.AnimationController;
|
||||
import noppes.npcs.controllers.CategoryManager;
|
||||
import noppes.npcs.controllers.CustomEffectController;
|
||||
import noppes.npcs.controllers.LinkedItemController;
|
||||
|
||||
@@ -65,6 +66,11 @@ public final class CategoryMoveItemPacket extends AbstractPacket {
|
||||
int item = in.readInt();
|
||||
int cat = in.readInt();
|
||||
|
||||
// Validate target category exists (0 = Uncategorized is always valid)
|
||||
CategoryManager cm = CategorySavePacket.getManager(type);
|
||||
if (cm == null) return;
|
||||
if (cat != CategoryManager.UNCATEGORIZED_ID && cm.getCategory(cat) == null) return;
|
||||
|
||||
switch (type) {
|
||||
case EnumCategoryType.EFFECT: CustomEffectController.getInstance().moveItemToCategory(item, cat); break;
|
||||
case EnumCategoryType.ANIMATION: AnimationController.getInstance().moveItemToCategory(item, cat); break;
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package kamkeel.npcs.network.packets.request.effects;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import kamkeel.npcs.network.AbstractPacket;
|
||||
import kamkeel.npcs.network.PacketChannel;
|
||||
import kamkeel.npcs.network.PacketHandler;
|
||||
import kamkeel.npcs.network.PacketUtil;
|
||||
import kamkeel.npcs.network.enums.EnumItemPacketType;
|
||||
import kamkeel.npcs.network.enums.EnumRequestPacket;
|
||||
import kamkeel.npcs.network.packets.data.large.GuiDataPacket;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import noppes.npcs.CustomNpcsPermissions;
|
||||
import noppes.npcs.NoppesUtilServer;
|
||||
import noppes.npcs.controllers.CustomEffectController;
|
||||
import noppes.npcs.controllers.data.CustomEffect;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public final class EffectClonePacket extends AbstractPacket {
|
||||
public static String packetName = "Request|EffectClone";
|
||||
|
||||
private int id;
|
||||
|
||||
public EffectClonePacket() {
|
||||
}
|
||||
|
||||
public EffectClonePacket(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getType() {
|
||||
return EnumRequestPacket.EffectClone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketChannel getChannel() {
|
||||
return PacketHandler.REQUEST_PACKET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomNpcsPermissions.Permission getPermission() {
|
||||
return CustomNpcsPermissions.GLOBAL_EFFECT;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public void sendData(ByteBuf out) throws IOException {
|
||||
out.writeInt(this.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveData(ByteBuf in, EntityPlayer player) throws IOException {
|
||||
if (!(player instanceof EntityPlayerMP))
|
||||
return;
|
||||
if (!PacketUtil.verifyItemPacket(packetName, EnumItemPacketType.WAND, player))
|
||||
return;
|
||||
|
||||
int effectId = in.readInt();
|
||||
CustomEffect clone = CustomEffectController.getInstance().cloneEffect(effectId);
|
||||
if (clone != null) {
|
||||
NoppesUtilServer.sendCustomEffectDataAll((EntityPlayerMP) player);
|
||||
GuiDataPacket.sendGuiData((EntityPlayerMP) player, clone.writeToNBT(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package kamkeel.npcs.network.packets.request.linked;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import kamkeel.npcs.network.AbstractPacket;
|
||||
import kamkeel.npcs.network.PacketChannel;
|
||||
import kamkeel.npcs.network.PacketHandler;
|
||||
import kamkeel.npcs.network.PacketUtil;
|
||||
import kamkeel.npcs.network.enums.EnumItemPacketType;
|
||||
import kamkeel.npcs.network.enums.EnumRequestPacket;
|
||||
import kamkeel.npcs.network.packets.data.large.GuiDataPacket;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import noppes.npcs.CustomNpcsPermissions;
|
||||
import noppes.npcs.NoppesUtilServer;
|
||||
import noppes.npcs.controllers.LinkedItemController;
|
||||
import noppes.npcs.controllers.data.LinkedItem;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public final class LinkedItemClonePacket extends AbstractPacket {
|
||||
public static String packetName = "Request|LinkedItemClone";
|
||||
|
||||
private int id;
|
||||
|
||||
public LinkedItemClonePacket() {
|
||||
}
|
||||
|
||||
public LinkedItemClonePacket(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enum getType() {
|
||||
return EnumRequestPacket.LinkedItemClone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketChannel getChannel() {
|
||||
return PacketHandler.REQUEST_PACKET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomNpcsPermissions.Permission getPermission() {
|
||||
return CustomNpcsPermissions.GLOBAL_LINKED;
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Override
|
||||
public void sendData(ByteBuf out) throws IOException {
|
||||
out.writeInt(this.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receiveData(ByteBuf in, EntityPlayer player) throws IOException {
|
||||
if (!(player instanceof EntityPlayerMP))
|
||||
return;
|
||||
if (!PacketUtil.verifyItemPacket(packetName, EnumItemPacketType.WAND, player))
|
||||
return;
|
||||
|
||||
int linkedId = in.readInt();
|
||||
LinkedItem clone = LinkedItemController.getInstance().cloneLinkedItem(linkedId);
|
||||
if (clone != null) {
|
||||
NoppesUtilServer.sendLinkedItemDataAll((EntityPlayerMP) player);
|
||||
GuiDataPacket.sendGuiData((EntityPlayerMP) player, clone.writeToNBT(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,7 +124,7 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@Mod(modid = "customnpcs", name = "CustomNPC+", version = "1.11-prerelease1")
|
||||
@Mod(modid = "customnpcs", name = "CustomNPC+", version = "1.11-prerelease3")
|
||||
public class CustomNpcs {
|
||||
|
||||
@SidedProxy(clientSide = "noppes.npcs.client.ClientProxy", serverSide = "noppes.npcs.CommonProxy")
|
||||
|
||||
@@ -199,7 +199,7 @@ public class GuiNpcMobSpawnerFullscreen extends GuiDirectory implements IGuiData
|
||||
navScroll.setSelected(getNavSelection());
|
||||
navScroll.scrollY = Math.min(savedNavScroll, Math.max(0, navScroll.maxScrollY));
|
||||
|
||||
// Phase 2: color nav items orange (selectable) or red (current location, not selectable)
|
||||
// Phase 2: color nav items orange (selectable) or red (current location)
|
||||
if (movePhase == 2) {
|
||||
String currentNav = getNavSelection();
|
||||
for (String name : navNames) {
|
||||
|
||||
@@ -38,6 +38,7 @@ public class SubGuiTagSelect extends SubGuiInterface implements IScrollData, ICu
|
||||
public SubGuiTagSelect(HashSet<UUID> tagUUIDs) {
|
||||
this.tagUUIDs = tagUUIDs;
|
||||
setBackground("menubg.png");
|
||||
closeOnEsc = true;
|
||||
xSize = 430;
|
||||
ySize = 220;
|
||||
|
||||
@@ -142,6 +143,10 @@ public class SubGuiTagSelect extends SubGuiInterface implements IScrollData, ICu
|
||||
}
|
||||
|
||||
public void keyTyped(char c, int i) {
|
||||
if (i == 1) {
|
||||
close();
|
||||
return;
|
||||
}
|
||||
super.keyTyped(c, i);
|
||||
if (getTextField(4) != null) {
|
||||
if (search.equals(getTextField(4).getText()))
|
||||
|
||||
@@ -88,12 +88,15 @@ public class SubGuiAbilityVariantSelect extends SubGuiInterface implements ICust
|
||||
scroll.setSize(190, 155);
|
||||
|
||||
// Mark blank separators and group headers as non-interactive colored entries
|
||||
scroll.nonInteractive.add("");
|
||||
scroll.colors.put("", 0x000000);
|
||||
if (lastGroup != null) {
|
||||
for (int i = 0; i < variants.size(); i++) {
|
||||
String group = variants.get(i).getGroup();
|
||||
if (group != null)
|
||||
if (group != null) {
|
||||
scroll.nonInteractive.add(group);
|
||||
scroll.colors.put(group, 0xFFFF00); // Yellow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,10 +11,12 @@ import kamkeel.npcs.controllers.data.telegraph.TelegraphInstance;
|
||||
import kamkeel.npcs.network.PacketClient;
|
||||
import kamkeel.npcs.network.packets.request.ability.BuiltInAbilityGetPacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.ChainedAbilityGetPacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.ChainedAbilityClonePacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.ChainedAbilityRemovePacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.ChainedAbilitySavePacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.CustomAbilitiesGetPacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.CustomAbilityGetPacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.CustomAbilityClonePacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.CustomAbilityRemovePacket;
|
||||
import kamkeel.npcs.network.packets.request.ability.CustomAbilitySavePacket;
|
||||
import kamkeel.npcs.network.packets.request.category.AbilityCategoryMovePacket;
|
||||
@@ -269,7 +271,14 @@ public class GuiAbilityDirectory extends GuiDirectoryCategorized
|
||||
|
||||
@Override
|
||||
protected void onCloneItem() {
|
||||
// Abilities don't support cloning through this mechanism
|
||||
if (currentIsBuiltIn) return;
|
||||
if (isChainedMode() && selectedChain != null) {
|
||||
PacketClient.sendClient(new ChainedAbilityClonePacket(selectedChain.getName()));
|
||||
if (selectedCatId >= 0) requestItemsInCategory(selectedCatId);
|
||||
} else if (selectedAbility != null) {
|
||||
PacketClient.sendClient(new CustomAbilityClonePacket(selectedAbility.getName()));
|
||||
if (selectedCatId >= 0 && isCustomMode()) requestItemsInCategory(selectedCatId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -672,10 +681,10 @@ public class GuiAbilityDirectory extends GuiDirectoryCategorized
|
||||
|
||||
if (!isPlaying || isPaused) {
|
||||
String statusKey = isPaused ? "animation.paused" : "animation.stopped";
|
||||
addLabel(new GuiNpcLabel(90, statusKey, btnX, playY + 5));
|
||||
addLabel(new GuiNpcLabel(90, statusKey, btnX, playY + 5, 0xFFFFFF));
|
||||
addButton(new GuiTexturedButton(91, "", btnX + 65, playY, 11, 20, animTexture, 18, 71));
|
||||
} else {
|
||||
addLabel(new GuiNpcLabel(90, "animation.playing", btnX, playY + 5));
|
||||
addLabel(new GuiNpcLabel(90, "animation.playing", btnX, playY + 5, 0xFFFFFF));
|
||||
addButton(new GuiTexturedButton(92, "", btnX + 65, playY, 14, 20, animTexture, 0, 71));
|
||||
}
|
||||
if (isActive) {
|
||||
@@ -683,13 +692,19 @@ public class GuiAbilityDirectory extends GuiDirectoryCategorized
|
||||
}
|
||||
}
|
||||
|
||||
// Edit + Remove at bottom
|
||||
int editY = contentY + contentH - btnH * 2 - gap;
|
||||
GuiNpcButton editBtn = new GuiNpcButton(51, rightX, editY, rightPanelW, btnH, "gui.edit");
|
||||
// Edit + Copy on one row, Remove below
|
||||
int btnY = contentY + contentH - btnH * 2 - gap;
|
||||
int halfW = (rightPanelW - gap) / 2;
|
||||
|
||||
GuiNpcButton editBtn = new GuiNpcButton(51, rightX, btnY, halfW, btnH, "gui.edit");
|
||||
editBtn.enabled = hasSelectedItem() && movePhase == 0 && !currentIsBuiltIn;
|
||||
addButton(editBtn);
|
||||
|
||||
int removeY = editY + btnH + gap;
|
||||
GuiNpcButton cloneBtn = new GuiNpcButton(52, rightX + halfW + gap, btnY, halfW, btnH, "gui.copy");
|
||||
cloneBtn.enabled = hasSelectedItem() && movePhase == 0 && !currentIsBuiltIn;
|
||||
addButton(cloneBtn);
|
||||
|
||||
int removeY = btnY + btnH + gap;
|
||||
GuiNpcButton removeBtn = new GuiNpcButton(53, rightX, removeY, rightPanelW, btnH, "gui.remove");
|
||||
removeBtn.enabled = hasSelectedItem() && movePhase == 0 && !currentIsBuiltIn;
|
||||
removeBtn.setTextColor(0xFF5555);
|
||||
@@ -718,6 +733,8 @@ public class GuiAbilityDirectory extends GuiDirectoryCategorized
|
||||
* Matches GuiAbilityInterface's rendering pipeline.
|
||||
*/
|
||||
private void drawAbilityPreview(float partialTicks) {
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
|
||||
// Set NPC facing direction
|
||||
npc.prevRenderYawOffset = npc.renderYawOffset = NPC_FACING_YAW;
|
||||
npc.prevRotationYaw = npc.rotationYaw = NPC_FACING_YAW;
|
||||
@@ -747,44 +764,47 @@ public class GuiAbilityDirectory extends GuiDirectoryCategorized
|
||||
GL11.glEnable(GL11.GL_SCISSOR_TEST);
|
||||
setScissorClip(previewX, previewY, previewW, previewH);
|
||||
|
||||
GL11.glEnable(GL11.GL_COLOR_MATERIAL);
|
||||
GL11.glPushMatrix();
|
||||
|
||||
GL11.glTranslatef(npcScreenX, npcScreenY, 500F);
|
||||
GL11.glScalef(-renderZoom, renderZoom, renderZoom);
|
||||
GL11.glRotatef(180F, 0.0F, 0.0F, 1.0F);
|
||||
GL11.glRotatef(CAMERA_PITCH, 1.0F, 0.0F, 0.0F);
|
||||
GL11.glRotatef(rotation, 0.0F, 1.0F, 0.0F);
|
||||
|
||||
GL11.glRotatef(135F, 0.0F, 1.0F, 0.0F);
|
||||
RenderHelper.enableStandardItemLighting();
|
||||
GL11.glRotatef(-135F, 0.0F, 1.0F, 0.0F);
|
||||
|
||||
GL11.glTranslatef(0.0F, npc.yOffset, 0.0F);
|
||||
RenderManager.instance.playerViewY = 180F;
|
||||
ClientEventHandler.renderingEntityInGUI = true;
|
||||
|
||||
// Render NPC at its position delta
|
||||
try {
|
||||
RenderManager.instance.renderEntityWithPosYaw(npc, npcDeltaX, npcDeltaY, npcDeltaZ, 0.0F, partialTicks);
|
||||
} catch (Exception ignored) {}
|
||||
GL11.glEnable(GL11.GL_COLOR_MATERIAL);
|
||||
GL11.glPushMatrix();
|
||||
|
||||
// Render preview entities
|
||||
renderPreviewEntities(partialTicks);
|
||||
GL11.glTranslatef(npcScreenX, npcScreenY, 500F);
|
||||
GL11.glScalef(-renderZoom, renderZoom, renderZoom);
|
||||
GL11.glRotatef(180F, 0.0F, 0.0F, 1.0F);
|
||||
GL11.glRotatef(CAMERA_PITCH, 1.0F, 0.0F, 0.0F);
|
||||
GL11.glRotatef(rotation, 0.0F, 1.0F, 0.0F);
|
||||
|
||||
// Render telegraph
|
||||
renderPreviewTelegraph(partialTicks);
|
||||
GL11.glRotatef(135F, 0.0F, 1.0F, 0.0F);
|
||||
RenderHelper.enableStandardItemLighting();
|
||||
GL11.glRotatef(-135F, 0.0F, 1.0F, 0.0F);
|
||||
|
||||
ClientEventHandler.renderingEntityInGUI = false;
|
||||
GL11.glPopMatrix();
|
||||
GL11.glTranslatef(0.0F, npc.yOffset, 0.0F);
|
||||
RenderManager.instance.playerViewY = 180F;
|
||||
ClientEventHandler.renderingEntityInGUI = true;
|
||||
|
||||
RenderHelper.disableStandardItemLighting();
|
||||
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
|
||||
OpenGlHelper.setActiveTexture(OpenGlHelper.lightmapTexUnit);
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit);
|
||||
// Render NPC at its position delta
|
||||
try {
|
||||
RenderManager.instance.renderEntityWithPosYaw(npc, npcDeltaX, npcDeltaY, npcDeltaZ, 0.0F, partialTicks);
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
GL11.glDisable(GL11.GL_SCISSOR_TEST);
|
||||
// Render preview entities
|
||||
renderPreviewEntities(partialTicks);
|
||||
|
||||
// Render telegraph
|
||||
renderPreviewTelegraph(partialTicks);
|
||||
|
||||
ClientEventHandler.renderingEntityInGUI = false;
|
||||
GL11.glPopMatrix();
|
||||
|
||||
RenderHelper.disableStandardItemLighting();
|
||||
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
|
||||
OpenGlHelper.setActiveTexture(OpenGlHelper.lightmapTexUnit);
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit);
|
||||
} finally {
|
||||
ClientEventHandler.renderingEntityInGUI = false;
|
||||
GL11.glDisable(GL11.GL_SCISSOR_TEST);
|
||||
}
|
||||
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
@@ -822,14 +842,17 @@ public class GuiAbilityDirectory extends GuiDirectoryCategorized
|
||||
GL11.glTranslatef(0.0F, entity.yOffset, 1F);
|
||||
RenderManager.instance.playerViewY = 180F;
|
||||
|
||||
ClientEventHandler.renderingEntityInGUI = true;
|
||||
try {
|
||||
RenderManager.instance.renderEntityWithPosYaw(entity, 0.0, 0.0, 0.0, 0.0F, 1.0F);
|
||||
} catch (Exception ignored) {}
|
||||
ClientEventHandler.renderingEntityInGUI = false;
|
||||
|
||||
entity.prevRenderYawOffset = entity.renderYawOffset = f2;
|
||||
entity.prevRotationYaw = entity.rotationYaw = f3;
|
||||
entity.rotationPitch = f4;
|
||||
entity.prevRotationYawHead = entity.rotationYawHead = f7;
|
||||
GL11.glPopMatrix();
|
||||
|
||||
RenderHelper.disableStandardItemLighting();
|
||||
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
|
||||
@@ -837,7 +860,6 @@ public class GuiAbilityDirectory extends GuiDirectoryCategorized
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit);
|
||||
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
|
||||
private void renderPreviewEntities(float partialTicks) {
|
||||
@@ -959,32 +981,32 @@ public class GuiAbilityDirectory extends GuiDirectoryCategorized
|
||||
if (isChainedMode() && selectedChain != null) {
|
||||
fontRendererObj.drawString(selectedChain.getDisplayName(), x, y, 0xFFFFFF, true);
|
||||
y += 14;
|
||||
fontRendererObj.drawString("Entries: " + selectedChain.getEntries().size(), x, y, 0xB5B5B5, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("ability.entries") + ": " + selectedChain.getEntries().size(), x, y, 0xB5B5B5, false);
|
||||
y += 12;
|
||||
fontRendererObj.drawString("Cooldown: " + selectedChain.getCooldownTicks() + "t", x, y, 0xB5B5B5, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("ability.cooldown") + ": " + selectedChain.getCooldownTicks() + "t", x, y, 0xB5B5B5, false);
|
||||
y += 12;
|
||||
UserType ut = selectedChain.getAllowedBy();
|
||||
fontRendererObj.drawString("Allowed: " + ut.name(), x, y, 0xB5B5B5, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("ability.allowed") + ": " + ut.name(), x, y, 0xB5B5B5, false);
|
||||
} else if (selectedAbility != null) {
|
||||
fontRendererObj.drawString(selectedAbility.getDisplayName(), x, y, 0xFFFFFF, true);
|
||||
y += 14;
|
||||
String typeId = selectedAbility.getTypeId();
|
||||
String typeName = StatCollector.translateToLocal(typeId);
|
||||
fontRendererObj.drawString("Type: " + typeName, x, y, 0xFFAE0D, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("gui.type") + ": " + typeName, x, y, 0xFFAE0D, false);
|
||||
y += 12;
|
||||
fontRendererObj.drawString("Cooldown: " + selectedAbility.getCooldownTicks() + "t", x, y, 0xB5B5B5, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("ability.cooldown") + ": " + selectedAbility.getCooldownTicks() + "t", x, y, 0xB5B5B5, false);
|
||||
y += 12;
|
||||
fontRendererObj.drawString("Windup: " + selectedAbility.getWindUpTicks() + "t", x, y, 0xB5B5B5, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("ability.windup") + ": " + selectedAbility.getWindUpTicks() + "t", x, y, 0xB5B5B5, false);
|
||||
y += 12;
|
||||
UserType ut = selectedAbility.getAllowedBy();
|
||||
fontRendererObj.drawString("Allowed: " + ut.name(), x, y, 0xB5B5B5, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("ability.allowed") + ": " + ut.name(), x, y, 0xB5B5B5, false);
|
||||
if (selectedAbility.hasDamage()) {
|
||||
y += 12;
|
||||
fontRendererObj.drawString("Damage: " + selectedAbility.getDisplayDamage(), x, y, 0xFF5555, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("ability.damage") + ": " + selectedAbility.getDisplayDamage(), x, y, 0xFF5555, false);
|
||||
}
|
||||
if (currentIsBuiltIn) {
|
||||
y += 12;
|
||||
fontRendererObj.drawString("(Built-in)", x, y, 0x55FF55, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("gui.builtin.tag"), x, y, 0x55FF55, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.client.renderer.entity.RenderManager;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.StatCollector;
|
||||
import noppes.npcs.client.NoppesUtil;
|
||||
import noppes.npcs.client.gui.util.GuiCustomScroll;
|
||||
import noppes.npcs.client.gui.util.GuiDirectoryCategorized;
|
||||
@@ -34,6 +35,7 @@ import noppes.npcs.controllers.data.AnimationData;
|
||||
import noppes.npcs.controllers.data.Category;
|
||||
import noppes.npcs.controllers.data.Frame;
|
||||
import noppes.npcs.controllers.data.FramePart;
|
||||
import noppes.npcs.client.ClientEventHandler;
|
||||
import noppes.npcs.entity.EntityCustomNpc;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
@@ -263,10 +265,13 @@ public class GuiAnimationDirectory extends GuiDirectoryCategorized {
|
||||
|
||||
@Override
|
||||
protected void initRightPanel(int startY) {
|
||||
// Calculate layout: playback row + edit/copy + remove rows
|
||||
// Calculate layout: playback rows + edit/copy + remove rows
|
||||
int bottomRows = 2; // edit+copy, remove
|
||||
boolean hasPlayback = animation != null && !animation.frames.isEmpty() && hasSelectedItem();
|
||||
if (hasPlayback) bottomRows++; // playback row
|
||||
if (hasPlayback) {
|
||||
bottomRows++; // playback controls row
|
||||
if (playingAnimation) bottomRows++; // frame info row
|
||||
}
|
||||
int bottomH = bottomRows * (btnH + gap) + 14;
|
||||
|
||||
previewX = rightX;
|
||||
@@ -283,15 +288,17 @@ public class GuiAnimationDirectory extends GuiDirectoryCategorized {
|
||||
|
||||
if (!playingAnimation || (data.animation != null && data.animation.paused)) {
|
||||
String statusKey = (data.animation != null && data.animation.paused) ? "animation.paused" : "animation.stopped";
|
||||
addLabel(new GuiNpcLabel(90, statusKey, btnX, playY + 5));
|
||||
addLabel(new GuiNpcLabel(90, statusKey, btnX, playY + 5, 0xFFFFFF));
|
||||
addButton(new GuiTexturedButton(91, "", btnX + 65, playY, 11, 20, animTexture, 18, 71));
|
||||
} else {
|
||||
addLabel(new GuiNpcLabel(90, "animation.playing", btnX, playY + 5));
|
||||
addLabel(new GuiNpcLabel(94, "", btnX + 60, playY + 5));
|
||||
addLabel(new GuiNpcLabel(90, "animation.playing", btnX, playY + 5, 0xFFFFFF));
|
||||
addButton(new GuiTexturedButton(92, "", btnX + 65, playY, 14, 20, animTexture, 0, 71));
|
||||
}
|
||||
if (playingAnimation) {
|
||||
addButton(new GuiTexturedButton(93, "", btnX + 85, playY, 14, 20, animTexture, 33, 71));
|
||||
// Frame info on its own line below playback controls
|
||||
int frameInfoY = playY + btnH + gap;
|
||||
addLabel(new GuiNpcLabel(94, "", btnX, frameInfoY + 5, 0xFFFFFF));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -472,15 +479,18 @@ public class GuiAnimationDirectory extends GuiDirectoryCategorized {
|
||||
GL11.glTranslatef(0.0F, entity.yOffset, 1F);
|
||||
RenderManager.instance.playerViewY = 180F;
|
||||
|
||||
ClientEventHandler.renderingEntityInGUI = true;
|
||||
try {
|
||||
RenderManager.instance.renderEntityWithPosYaw(entity, 0.0, 0.0, 0.0, 0.0F, 1.0F);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
ClientEventHandler.renderingEntityInGUI = false;
|
||||
|
||||
entity.prevRenderYawOffset = entity.renderYawOffset = f2;
|
||||
entity.prevRotationYaw = entity.rotationYaw = f3;
|
||||
entity.rotationPitch = f4;
|
||||
entity.prevRotationYawHead = entity.rotationYawHead = f7;
|
||||
GL11.glPopMatrix();
|
||||
|
||||
RenderHelper.disableStandardItemLighting();
|
||||
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
|
||||
@@ -488,7 +498,6 @@ public class GuiAnimationDirectory extends GuiDirectoryCategorized {
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit);
|
||||
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -498,15 +507,15 @@ public class GuiAnimationDirectory extends GuiDirectoryCategorized {
|
||||
|
||||
fontRendererObj.drawString(animation.name, x, y, 0xFFFFFF, true);
|
||||
y += 14;
|
||||
fontRendererObj.drawString("Frames: " + animation.frames.size(), x, y, 0xB5B5B5, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("animation.frames") + ": " + animation.frames.size(), x, y, 0xB5B5B5, false);
|
||||
y += 12;
|
||||
fontRendererObj.drawString("Speed: " + animation.speed, x, y, 0xB5B5B5, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("stats.speed") + ": " + animation.speed, x, y, 0xB5B5B5, false);
|
||||
y += 12;
|
||||
String loopStr = animation.loop == 0 ? "None" : animation.loop == 1 ? "Loop" : "Mirror";
|
||||
fontRendererObj.drawString("Loop: " + loopStr, x, y, 0xB5B5B5, false);
|
||||
String loopStr = animation.loop == 0 ? StatCollector.translateToLocal("gui.none") : animation.loop == 1 ? StatCollector.translateToLocal("animation.loop") : StatCollector.translateToLocal("animation.mirror");
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("animation.loop") + ": " + loopStr, x, y, 0xB5B5B5, false);
|
||||
if (currentIsBuiltIn) {
|
||||
y += 12;
|
||||
fontRendererObj.drawString("(Built-in)", x, y, 0x55FF55, false);
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("gui.builtin.tag"), x, y, 0x55FF55, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import kamkeel.npcs.network.packets.request.category.CategoryRemovePacket;
|
||||
import kamkeel.npcs.network.packets.request.category.CategorySavePacket;
|
||||
import kamkeel.npcs.network.packets.request.effects.EffectGetPacket;
|
||||
import kamkeel.npcs.network.packets.request.effects.EffectRemovePacket;
|
||||
import kamkeel.npcs.network.packets.request.effects.EffectClonePacket;
|
||||
import kamkeel.npcs.network.packets.request.effects.EffectSavePacket;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.renderer.texture.TextureManager;
|
||||
@@ -15,7 +16,6 @@ import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.StatCollector;
|
||||
import noppes.npcs.client.ClientCacheHandler;
|
||||
import noppes.npcs.client.CustomNpcResourceListener;
|
||||
import noppes.npcs.client.gui.SubGuiEffectGeneral;
|
||||
import noppes.npcs.client.gui.util.GuiDirectoryCategorized;
|
||||
import noppes.npcs.client.gui.util.SubGuiInterface;
|
||||
@@ -90,9 +90,7 @@ public class GuiEffectDirectory extends GuiDirectoryCategorized {
|
||||
@Override
|
||||
protected void onCloneItem() {
|
||||
if (effect != null && effect.id >= 0) {
|
||||
CustomEffect clone = effect.cloneEffect();
|
||||
while (itemData.containsKey(clone.name)) clone.name += "_";
|
||||
PacketClient.sendClient(new EffectSavePacket(clone.writeToNBT(false), ""));
|
||||
PacketClient.sendClient(new EffectClonePacket(effect.id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,7 +178,7 @@ public class GuiEffectDirectory extends GuiDirectoryCategorized {
|
||||
if (effect == null || effect.id == -1) return;
|
||||
|
||||
String drawString = effect.getMenuName();
|
||||
fontRendererObj.drawString(drawString, x, y, CustomNpcResourceListener.DefaultTextColor, true);
|
||||
fontRendererObj.drawString(drawString, x, y, 0xFFFFFF, true);
|
||||
|
||||
y += 14;
|
||||
fontRendererObj.drawString(StatCollector.translateToLocal("gui.name") + ": " + effect.name, x, y, 0xFFFFFF, false);
|
||||
|
||||
@@ -9,6 +9,7 @@ import kamkeel.npcs.network.packets.request.category.CategorySavePacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedGetPacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedItemBuildPacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedItemRemovePacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedItemClonePacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedItemSavePacket;
|
||||
import kamkeel.npcs.util.ColorUtil;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
@@ -17,7 +18,6 @@ import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.StatCollector;
|
||||
import noppes.npcs.client.ClientCacheHandler;
|
||||
import noppes.npcs.client.CustomNpcResourceListener;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import noppes.npcs.client.gui.item.SubGuiLinkedItem;
|
||||
import noppes.npcs.client.gui.util.GuiDirectoryCategorized;
|
||||
@@ -91,10 +91,7 @@ public class GuiLinkedItemDirectory extends GuiDirectoryCategorized {
|
||||
@Override
|
||||
protected void onCloneItem() {
|
||||
if (linkedItem != null && linkedItem.id >= 0) {
|
||||
LinkedItem clone = linkedItem.clone();
|
||||
while (itemData.containsKey(clone.name)) clone.name += "_";
|
||||
clone.id = -1;
|
||||
PacketClient.sendClient(new LinkedItemSavePacket(clone.writeToNBT(false), ""));
|
||||
PacketClient.sendClient(new LinkedItemClonePacket(linkedItem.id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,7 +212,7 @@ public class GuiLinkedItemDirectory extends GuiDirectoryCategorized {
|
||||
protected void drawItemDetails(int x, int y, int w) {
|
||||
if (linkedItem == null || linkedItem.id < 0) return;
|
||||
|
||||
fontRendererObj.drawString(linkedItem.name, x, y, CustomNpcResourceListener.DefaultTextColor, true);
|
||||
fontRendererObj.drawString(linkedItem.name, x, y, 0xFFFFFF, true);
|
||||
y += 14;
|
||||
|
||||
int labelColor = 0xffae0d;
|
||||
|
||||
@@ -3,6 +3,7 @@ package noppes.npcs.client.gui.global;
|
||||
import kamkeel.npcs.network.PacketClient;
|
||||
import kamkeel.npcs.network.packets.request.effects.EffectGetPacket;
|
||||
import kamkeel.npcs.network.packets.request.effects.EffectRemovePacket;
|
||||
import kamkeel.npcs.network.packets.request.effects.EffectClonePacket;
|
||||
import kamkeel.npcs.network.packets.request.effects.EffectSavePacket;
|
||||
import kamkeel.npcs.network.packets.request.effects.EffectsGetPacket;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
@@ -106,10 +107,9 @@ public class GuiNPCManageEffects extends GuiNPCInterface2 implements ICustomScro
|
||||
displayGuiScreen(guiyesno);
|
||||
}
|
||||
} else if (button.id == 2) {
|
||||
CustomEffect effect = this.effect.cloneEffect();
|
||||
while (data.containsKey(effect.name))
|
||||
effect.name += "_";
|
||||
PacketClient.sendClient(new EffectSavePacket(effect.writeToNBT(false), ""));
|
||||
if (effect != null && effect.id >= 0) {
|
||||
PacketClient.sendClient(new EffectClonePacket(effect.id));
|
||||
}
|
||||
}
|
||||
|
||||
if (button.id == 66) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import kamkeel.npcs.network.packets.request.linked.LinkedGetAllPacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedGetPacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedItemBuildPacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedItemRemovePacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedItemClonePacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedItemSavePacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedNPCAddPacket;
|
||||
import kamkeel.npcs.network.packets.request.linked.LinkedNPCRemovePacket;
|
||||
@@ -288,13 +289,7 @@ public class GuiNPCManageLinked extends GuiNPCInterface2 implements IScrollData,
|
||||
}
|
||||
if (button.id == 4) {
|
||||
if (data.containsKey(scroll.getSelected()) && linkedItem != null && linkedItem.id >= 0) {
|
||||
String name = linkedItem.name;
|
||||
while (data.containsKey(name))
|
||||
name += "_";
|
||||
LinkedItem linkedItemClone = this.linkedItem.clone();
|
||||
linkedItemClone.name = name;
|
||||
linkedItemClone.id = -1;
|
||||
PacketClient.sendClient(new LinkedItemSavePacket(linkedItemClone.writeToNBT(false), ""));
|
||||
PacketClient.sendClient(new LinkedItemClonePacket(this.linkedItem.id));
|
||||
}
|
||||
}
|
||||
if (button.id == 5) {
|
||||
|
||||
@@ -19,6 +19,7 @@ public class GuiCustomScroll extends GuiScreen {
|
||||
public static final ResourceLocation resource = new ResourceLocation("customnpcs", "textures/gui/misc.png");
|
||||
public List<String> list;
|
||||
public final HashMap<String, Integer> colors = new HashMap<>();
|
||||
public final HashSet<String> nonInteractive = new HashSet<>();
|
||||
|
||||
public int id;
|
||||
public int guiLeft = 0;
|
||||
@@ -217,21 +218,25 @@ public class GuiCustomScroll extends GuiScreen {
|
||||
} else
|
||||
text = displayString;
|
||||
|
||||
// Entries with a custom color are non-interactive (headers/separators)
|
||||
// Non-interactive entries (headers/separators) — colored, no hover/selection
|
||||
Integer customColor = colors.get(rawEntry);
|
||||
if (customColor != null) {
|
||||
if (nonInteractive.contains(rawEntry)) {
|
||||
if (!text.isEmpty())
|
||||
fontRendererObj.drawString(text, j, k, customColor);
|
||||
fontRendererObj.drawString(text, j, k, customColor != null ? customColor : 0xffffff);
|
||||
} else if ((multipleSelection && selectedList.contains(text)) || (!multipleSelection && selected == i)) {
|
||||
drawVerticalLine(j - 2, k - 4, k + 10, 0xffffffff);
|
||||
drawVerticalLine(j + xSize - 18 + xOffset, k - 4, k + 10, 0xffffffff);
|
||||
drawHorizontalLine(j - 2, j + xSize - 18 + xOffset, k - 3, 0xffffffff);
|
||||
drawHorizontalLine(j - 2, j + xSize - 18 + xOffset, k + 10, 0xffffffff);
|
||||
fontRendererObj.drawString(text, j, k, 0xffffff);
|
||||
int selColor = customColor != null ? customColor : 0xffffff;
|
||||
fontRendererObj.drawString(text, j, k, selColor);
|
||||
} else if (i == hover) {
|
||||
fontRendererObj.drawString(text, j, k, 0x00ff00);
|
||||
} else
|
||||
fontRendererObj.drawString(text, j, k, 0xffffff);
|
||||
int hoverColor = customColor != null ? customColor : 0x00ff00;
|
||||
fontRendererObj.drawString(text, j, k, hoverColor);
|
||||
} else {
|
||||
int defaultColor = customColor != null ? customColor : 0xffffff;
|
||||
fontRendererObj.drawString(text, j, k, defaultColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,8 +257,8 @@ public class GuiCustomScroll extends GuiScreen {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip non-interactive entries (colored headers/separators)
|
||||
if (colors.containsKey(list.get(j1))) {
|
||||
// Skip non-interactive entries (headers/separators)
|
||||
if (nonInteractive.contains(list.get(j1))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,10 @@ public abstract class GuiDirectoryCategorized extends GuiDirectory
|
||||
// ========== New Item Category ==========
|
||||
protected int pendingNewItemCatId = -1;
|
||||
|
||||
// ========== Pending Move Destination ==========
|
||||
private int pendingMoveDestCatId = -1;
|
||||
private String pendingMoveDestName = "";
|
||||
|
||||
// ========== Category Data Loaded ==========
|
||||
private boolean itemDataLoaded = false;
|
||||
|
||||
@@ -184,7 +188,7 @@ public abstract class GuiDirectoryCategorized extends GuiDirectory
|
||||
x += topBtnW + 2;
|
||||
|
||||
// MOVE
|
||||
String moveLabel = movePhase > 0 ? "Moving" : "Move";
|
||||
String moveLabel = movePhase > 0 ? "gui.moving" : "gui.move";
|
||||
GuiNpcButton moveBtn = new GuiNpcButton(54, x, topBtnY, topBtnW, btnH, moveLabel);
|
||||
moveBtn.enabled = selectedCatId >= 0 && !leftCollapsed && hasCategories();
|
||||
addButton(moveBtn);
|
||||
@@ -192,8 +196,9 @@ public abstract class GuiDirectoryCategorized extends GuiDirectory
|
||||
|
||||
// Confirm (only during move phase 1)
|
||||
if (movePhase == 1) {
|
||||
GuiNpcButton confirmBtn = new GuiNpcButton(55, x, topBtnY, topBtnW, btnH, "Confirm");
|
||||
GuiNpcButton confirmBtn = new GuiNpcButton(55, x, topBtnY, topBtnW, btnH, "gui.confirm");
|
||||
confirmBtn.enabled = !moveSelection.isEmpty();
|
||||
confirmBtn.setTextColor(0x55FFFF);
|
||||
addButton(confirmBtn);
|
||||
x += topBtnW + 2;
|
||||
}
|
||||
@@ -230,9 +235,18 @@ public abstract class GuiDirectoryCategorized extends GuiDirectory
|
||||
catScroll.setSelected(prevCatName);
|
||||
catScroll.scrollY = Math.max(0, Math.min(savedCatScrollY, catScroll.maxScrollY));
|
||||
|
||||
// Phase 2: ensure scroll is clickable for destination selection
|
||||
// Phase 1: categories locked (not clickable)
|
||||
if (movePhase == 1) {
|
||||
catScroll.setSelectable(false);
|
||||
}
|
||||
// Phase 2: color nav items orange (selectable) or red (current/source category)
|
||||
if (movePhase == 2) {
|
||||
catScroll.setSelectable(true);
|
||||
for (String name : navNames) {
|
||||
catScroll.colors.put(name, name.equals(prevCatName) ? 0xFF5555 : 0xFFAA00);
|
||||
}
|
||||
} else if (movePhase == 0) {
|
||||
catScroll.setSelectable(true);
|
||||
}
|
||||
|
||||
addScroll(catScroll);
|
||||
@@ -391,19 +405,19 @@ public abstract class GuiDirectoryCategorized extends GuiDirectory
|
||||
|
||||
// Draw ID (skip if -1, e.g. abilities use names not IDs)
|
||||
if (hasSelectedItem() && getSelectedItemId() >= 0) {
|
||||
String idStr = "ID: " + getSelectedItemId();
|
||||
int idY = contentY + contentH - btnH - 14;
|
||||
String idStr = StatCollector.translateToLocal("gui.id") + ": " + getSelectedItemId();
|
||||
int idY = contentY + contentH - btnH * 2 - gap - 12;
|
||||
fontRendererObj.drawString(idStr, previewX + 4, idY, 0xFFFFFF, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Move phase overlay text
|
||||
if (movePhase == 1) {
|
||||
String text = "Select Items to Move (max " + MAX_MOVE_ITEMS + ")";
|
||||
String text = String.format(StatCollector.translateToLocal("gui.move.selectItems"), MAX_MOVE_ITEMS);
|
||||
int textW = fontRendererObj.getStringWidth(text);
|
||||
fontRendererObj.drawStringWithShadow(text, width / 2 - textW / 2, height - pad - 10, 0x55FF55);
|
||||
} else if (movePhase == 2) {
|
||||
String text = "Select Destination Category";
|
||||
String text = StatCollector.translateToLocal("gui.move.selectCategory");
|
||||
int textW = fontRendererObj.getStringWidth(text);
|
||||
fontRendererObj.drawStringWithShadow(text, width / 2 - textW / 2, height - pad - 10, 0xFF5555);
|
||||
}
|
||||
@@ -592,15 +606,20 @@ public abstract class GuiDirectoryCategorized extends GuiDirectory
|
||||
public void customScrollClicked(int i, int j, int k, GuiCustomScroll guiCustomScroll) {
|
||||
// Category scroll
|
||||
if (guiCustomScroll.id == 2) {
|
||||
// Block category clicks during move phase 1 (selecting items)
|
||||
if (movePhase == 1) return;
|
||||
|
||||
String selected = catScroll.getSelected();
|
||||
if (selected == null) return;
|
||||
|
||||
// Move phase 2: destination selected
|
||||
// Move phase 2: destination selected — show confirmation
|
||||
if (movePhase == 2) {
|
||||
if (!selected.equals(prevCatName)) {
|
||||
Integer destCatId = catData.get(selected);
|
||||
if (destCatId != null) {
|
||||
executeMoveItems(destCatId);
|
||||
pendingMoveDestCatId = destCatId;
|
||||
pendingMoveDestName = selected;
|
||||
setSubGui(new SubGuiCategoryMoveConfirm(moveSelection.size(), selected));
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -752,7 +771,7 @@ public abstract class GuiDirectoryCategorized extends GuiDirectory
|
||||
if (subgui instanceof SubGuiEditText) {
|
||||
if (!((SubGuiEditText) subgui).cancelled && selectedCatId > 0) {
|
||||
String name = ((SubGuiEditText) subgui).text;
|
||||
if (name != null && !name.isEmpty() && !catData.containsKey(name)) {
|
||||
if (name != null && !name.isEmpty() && !name.equals(prevCatName) && !catData.containsKey(name)) {
|
||||
Category cat = new Category(selectedCatId, name);
|
||||
onSaveCategory(cat);
|
||||
catData.remove(prevCatName);
|
||||
@@ -760,6 +779,18 @@ public abstract class GuiDirectoryCategorized extends GuiDirectory
|
||||
prevCatName = name;
|
||||
}
|
||||
}
|
||||
// Restore category selection to current name (handles validation failure)
|
||||
catScroll.setSelected(prevCatName);
|
||||
}
|
||||
if (subgui instanceof SubGuiCategoryMoveConfirm) {
|
||||
SubGuiCategoryMoveConfirm confirm = (SubGuiCategoryMoveConfirm) subgui;
|
||||
if (confirm.confirmed && !moveSelection.isEmpty() && pendingMoveDestCatId >= 0) {
|
||||
executeMoveItems(pendingMoveDestCatId);
|
||||
} else {
|
||||
// Cancelled — stay in phase 2
|
||||
}
|
||||
pendingMoveDestCatId = -1;
|
||||
pendingMoveDestName = "";
|
||||
}
|
||||
onSubGuiClosed(subgui);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.ScaledResolution;
|
||||
import net.minecraft.client.renderer.OpenGlHelper;
|
||||
import net.minecraft.client.renderer.RenderHelper;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.StatCollector;
|
||||
@@ -166,8 +167,13 @@ public class GuiNpcButton extends GuiButton {
|
||||
}
|
||||
}
|
||||
}
|
||||
// First, draw the button normally using the superclass method.
|
||||
super.drawButton(mc, mouseX, mouseY);
|
||||
// Wide buttons (>396px) break the vanilla 200px button texture.
|
||||
// Draw them with a three-patch approach instead.
|
||||
if (this.width > 396) {
|
||||
drawWideButton(mc, mouseX, mouseY);
|
||||
} else {
|
||||
super.drawButton(mc, mouseX, mouseY);
|
||||
}
|
||||
// Restore original display string
|
||||
this.displayString = original;
|
||||
// Then, if an icon texture is set, draw it.
|
||||
@@ -175,17 +181,58 @@ public class GuiNpcButton extends GuiButton {
|
||||
mc.getTextureManager().bindTexture(iconTexture);
|
||||
GL11.glPushMatrix();
|
||||
RenderHelper.enableGUIStandardItemLighting();
|
||||
// Calculate the icon position so that it's centered in the button.
|
||||
// (Assumes the button's (xPosition,yPosition) is its top left.)
|
||||
int iconX = this.xPosition + (this.width - iconWidth) / 2;
|
||||
int iconY = this.yPosition + (this.height - iconHeight) / 2;
|
||||
// Draw the texture; we assume texture coordinates start at (0,0) with the desired size.
|
||||
this.drawTexturedModalRect(iconX, iconY, iconPosX, iconPosY, iconWidth, iconHeight);
|
||||
RenderHelper.disableStandardItemLighting();
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a button wider than the vanilla 200px texture allows.
|
||||
* Uses three-patch rendering: left cap, tiled center, right cap.
|
||||
*/
|
||||
private void drawWideButton(Minecraft mc, int mouseX, int mouseY) {
|
||||
FontRenderer fontrenderer = mc.fontRenderer;
|
||||
mc.getTextureManager().bindTexture(buttonTextures);
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
this.field_146123_n = mouseX >= this.xPosition && mouseY >= this.yPosition
|
||||
&& mouseX < this.xPosition + this.width && mouseY < this.yPosition + this.height;
|
||||
int k = this.getHoverState(this.field_146123_n);
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
OpenGlHelper.glBlendFunc(770, 771, 1, 0);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
int texY = 46 + k * 20;
|
||||
int cap = 100;
|
||||
|
||||
// Left cap (first 100px of texture)
|
||||
this.drawTexturedModalRect(this.xPosition, this.yPosition, 0, texY, cap, this.height);
|
||||
// Right cap (last 100px of texture)
|
||||
this.drawTexturedModalRect(this.xPosition + this.width - cap, this.yPosition, 200 - cap, texY, cap, this.height);
|
||||
// Tile the center column to fill the gap
|
||||
int gapStart = this.xPosition + cap;
|
||||
int gapEnd = this.xPosition + this.width - cap;
|
||||
for (int x = gapStart; x < gapEnd; x += 2) {
|
||||
int drawW = Math.min(2, gapEnd - x);
|
||||
this.drawTexturedModalRect(x, this.yPosition, 99, texY, drawW, this.height);
|
||||
}
|
||||
|
||||
this.mouseDragged(mc, mouseX, mouseY);
|
||||
|
||||
int l = 14737632;
|
||||
if (packedFGColour != 0) {
|
||||
l = packedFGColour;
|
||||
} else if (!this.enabled) {
|
||||
l = 10526880;
|
||||
} else if (this.field_146123_n) {
|
||||
l = 16777120;
|
||||
}
|
||||
this.drawCenteredString(fontrenderer, this.displayString,
|
||||
this.xPosition + this.width / 2, this.yPosition + (this.height - 8) / 2, l);
|
||||
}
|
||||
|
||||
public void drawHover(int i, int j, boolean hasSubGui) {
|
||||
if (hasSubGui || !visible || hoverableText.isEmpty())
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package noppes.npcs.client.gui.util;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.util.StatCollector;
|
||||
|
||||
public class SubGuiCategoryMoveConfirm extends SubGuiInterface {
|
||||
public boolean confirmed = false;
|
||||
|
||||
private final int count;
|
||||
public final String destCategoryName;
|
||||
|
||||
public SubGuiCategoryMoveConfirm(int count, String destCategoryName) {
|
||||
this.count = count;
|
||||
this.destCategoryName = destCategoryName;
|
||||
xSize = 220;
|
||||
ySize = 90;
|
||||
closeOnEsc = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui() {
|
||||
super.initGui();
|
||||
|
||||
String line1 = String.format(StatCollector.translateToLocal("gui.move.confirmLine"), count);
|
||||
addLabel(new GuiNpcLabel(0, line1, guiLeft + 10, guiTop + 10, 0xFFFFFF));
|
||||
|
||||
String dest = StatCollector.translateToLocal("gui.category") + ": \"" + destCategoryName + "\"";
|
||||
addLabel(new GuiNpcLabel(1, " " + dest, guiLeft + 10, guiTop + 25, 0xFFFFFF));
|
||||
|
||||
addButton(new GuiNpcButton(0, guiLeft + 10, guiTop + 55, 95, 20, "gui.yes"));
|
||||
addButton(new GuiNpcButton(1, guiLeft + 115, guiTop + 55, 95, 20, "gui.cancel"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(GuiButton guibutton) {
|
||||
if (guibutton.id == 0) {
|
||||
confirmed = true;
|
||||
close();
|
||||
}
|
||||
if (guibutton.id == 1) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
}
|
||||
}
|
||||
@@ -708,4 +708,23 @@ public class CustomEffectController implements ICustomEffectHandler {
|
||||
return getCustomEffects().get(customEffect.getID());
|
||||
}
|
||||
|
||||
public CustomEffect cloneEffect(int originalId) {
|
||||
CustomEffect original = getCustomEffects().get(originalId);
|
||||
if (original == null) return null;
|
||||
|
||||
NBTTagCompound nbt = original.writeToNBT(true);
|
||||
int newId = getUnusedId();
|
||||
nbt.setInteger("ID", newId);
|
||||
|
||||
CustomEffect clone = new CustomEffect();
|
||||
clone.readFromNBT(nbt);
|
||||
|
||||
String name = clone.getName();
|
||||
while (has(name)) name += "_";
|
||||
clone.name = name;
|
||||
|
||||
saveEffect(clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -241,6 +241,25 @@ public class LinkedItemController implements ILinkedItemHandler {
|
||||
return linkedItems.get(linkedItem.getId());
|
||||
}
|
||||
|
||||
public LinkedItem cloneLinkedItem(int originalId) {
|
||||
LinkedItem original = linkedItems.get(originalId);
|
||||
if (original == null) return null;
|
||||
|
||||
NBTTagCompound nbt = original.writeToNBT(true);
|
||||
int newId = getUnusedId();
|
||||
nbt.setInteger("Id", newId);
|
||||
|
||||
LinkedItem clone = new LinkedItem();
|
||||
clone.readFromNBT(nbt);
|
||||
|
||||
String name = clone.getName();
|
||||
while (hasName(name)) name += "_";
|
||||
clone.name = name;
|
||||
|
||||
saveLinkedItem(clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
private boolean hasOther(String name, int id) {
|
||||
for (LinkedItem linkedItem : linkedItems.values()) {
|
||||
if (linkedItem.getId() != id && linkedItem.getName().equalsIgnoreCase(name))
|
||||
|
||||
@@ -3,6 +3,7 @@ package noppes.npcs.controllers.data;
|
||||
import kamkeel.npcs.network.packets.request.script.EffectScriptPacket;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import noppes.npcs.constants.ScriptContext;
|
||||
import noppes.npcs.janino.EventJaninoScript;
|
||||
|
||||
/**
|
||||
* Script handler for CustomEffect scripts.
|
||||
@@ -35,6 +36,11 @@ public class EffectScript extends SingleScriptHandler implements IScriptHandlerP
|
||||
return ScriptContext.EFFECT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IScriptUnit createJaninoScriptUnit() {
|
||||
return new EventJaninoScript(ScriptContext.EFFECT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String noticeString() {
|
||||
return effectId >= 0 ? "CustomEffect[" + effectId + "]" : "CustomEffect";
|
||||
|
||||
@@ -3,6 +3,7 @@ package noppes.npcs.controllers.data;
|
||||
import kamkeel.npcs.network.packets.request.script.item.LinkedItemScriptPacket;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import noppes.npcs.constants.ScriptContext;
|
||||
import noppes.npcs.janino.EventJaninoScript;
|
||||
|
||||
/**
|
||||
* Script handler for LinkedItem scripts.
|
||||
@@ -35,6 +36,11 @@ public class LinkedItemScript extends SingleScriptHandler implements IScriptHand
|
||||
return ScriptContext.LINKED_ITEM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IScriptUnit createJaninoScriptUnit() {
|
||||
return new EventJaninoScript(ScriptContext.LINKED_ITEM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String noticeString() {
|
||||
return "LinkedItem";
|
||||
|
||||
@@ -3,6 +3,7 @@ package noppes.npcs.controllers.data;
|
||||
import kamkeel.npcs.network.packets.request.script.RecipeScriptPacket;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import noppes.npcs.constants.ScriptContext;
|
||||
import noppes.npcs.janino.EventJaninoScript;
|
||||
|
||||
/**
|
||||
* Script handler for Recipe scripts (both carpentry and anvil).
|
||||
@@ -42,6 +43,11 @@ public class RecipeScript extends SingleScriptHandler implements IScriptHandlerP
|
||||
return ScriptContext.RECIPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IScriptUnit createJaninoScriptUnit() {
|
||||
return new EventJaninoScript(ScriptContext.RECIPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String noticeString() {
|
||||
return "RecipeScript";
|
||||
|
||||
@@ -183,6 +183,7 @@ public class SkinOverlay implements ISkinOverlay {
|
||||
private void updateClient() {
|
||||
if (this.parent != null) {
|
||||
this.parent.updateClient();
|
||||
this.parent.save();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,7 +86,8 @@ public class EntityCustomNpc extends EntityNPCFlying {
|
||||
worldObj.MAX_ENTITY_RADIUS = newWidth / 2;
|
||||
}
|
||||
|
||||
setSize(newWidth, newHeight);
|
||||
this.width = newWidth;
|
||||
this.height = newHeight;
|
||||
this.setPosition(posX, posY, posZ);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,9 @@ public class EntityNPCGolem extends EntityNPCInterface {
|
||||
newWidth = 1.4f;
|
||||
newHeight = 2.5f;
|
||||
}
|
||||
setSize(newWidth, newHeight);
|
||||
this.width = newWidth;
|
||||
this.height = newHeight;
|
||||
this.setPosition(posX, posY, posZ);
|
||||
if (width / 2 > World.MAX_ENTITY_RADIUS) {
|
||||
World.MAX_ENTITY_RADIUS = width / 2;
|
||||
}
|
||||
|
||||
@@ -1285,7 +1285,8 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti
|
||||
World.MAX_ENTITY_RADIUS = newWidth / 2;
|
||||
}
|
||||
|
||||
setSize(newWidth, newHeight);
|
||||
this.width = newWidth;
|
||||
this.height = newHeight;
|
||||
this.setPosition(posX, posY, posZ);
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,9 @@ public class EntityNpcDragon extends EntityNPCInterface {
|
||||
// }
|
||||
@Override
|
||||
public void updateHitbox() {
|
||||
setSize(1.8f, 1.4f);
|
||||
this.width = 1.8f;
|
||||
this.height = 1.4f;
|
||||
this.setPosition(posX, posY, posZ);
|
||||
if (width / 2 > World.MAX_ENTITY_RADIUS) {
|
||||
World.MAX_ENTITY_RADIUS = width / 2;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,9 @@ public class EntityNpcSlime extends EntityNPCInterface {
|
||||
|
||||
@Override
|
||||
public void updateHitbox() {
|
||||
setSize(0.8f, 0.8f);
|
||||
this.width = 0.8f;
|
||||
this.height = 0.8f;
|
||||
this.setPosition(posX, posY, posZ);
|
||||
if (width / 2 > World.MAX_ENTITY_RADIUS) {
|
||||
World.MAX_ENTITY_RADIUS = width / 2;
|
||||
}
|
||||
|
||||
@@ -49,6 +49,12 @@ public class DataSkinOverlays implements IOverlayHandler {
|
||||
return nbttagcompound;
|
||||
}
|
||||
|
||||
public void save() {
|
||||
if (parent instanceof PlayerData) {
|
||||
((PlayerData) parent).save();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateClient() {
|
||||
if (parent != null) {
|
||||
if (parent instanceof PlayerData && ((PlayerData) parent).player != null) {
|
||||
@@ -69,6 +75,7 @@ public class DataSkinOverlays implements IOverlayHandler {
|
||||
((SkinOverlay) data).parent = this;
|
||||
this.overlayList.put(id, data);
|
||||
updateClient();
|
||||
save();
|
||||
}
|
||||
|
||||
public ISkinOverlay get(int id) {
|
||||
@@ -82,6 +89,7 @@ public class DataSkinOverlays implements IOverlayHandler {
|
||||
public boolean remove(int id) {
|
||||
boolean removed = this.overlayList.remove(id) != null;
|
||||
updateClient();
|
||||
save();
|
||||
return removed;
|
||||
}
|
||||
|
||||
@@ -92,5 +100,6 @@ public class DataSkinOverlays implements IOverlayHandler {
|
||||
public void clear() {
|
||||
this.overlayList.clear();
|
||||
updateClient();
|
||||
save();
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,9 @@ public class EntityNPCEnderman extends EntityNpcEnderchibi {
|
||||
newHeight = (newHeight / 5f) * display.modelSize;
|
||||
newWidth = Math.max(newWidth, 0.00001f);
|
||||
newHeight = Math.max(newHeight, 0.00001f);
|
||||
setSize(newWidth, newHeight);
|
||||
this.width = newWidth;
|
||||
this.height = newHeight;
|
||||
this.setPosition(posX, posY, posZ);
|
||||
if (width / 2 > World.MAX_ENTITY_RADIUS) {
|
||||
World.MAX_ENTITY_RADIUS = width / 2;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ public class JobSpawner extends JobInterface {
|
||||
|
||||
private EntityLivingBase target;
|
||||
|
||||
private boolean isResetting = false;
|
||||
|
||||
public JobSpawner(EntityNPCInterface npc) {
|
||||
super(npc);
|
||||
@@ -314,16 +315,25 @@ public class JobSpawner extends JobInterface {
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
number = 0;
|
||||
if (spawned.isEmpty())
|
||||
spawned = getNearbySpawned();
|
||||
if (isResetting)
|
||||
return;
|
||||
isResetting = true;
|
||||
try {
|
||||
number = 0;
|
||||
if (spawned.isEmpty())
|
||||
spawned = getNearbySpawned();
|
||||
|
||||
target = null;
|
||||
checkSpawns();
|
||||
target = null;
|
||||
checkSpawns();
|
||||
} finally {
|
||||
isResetting = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
if (isResetting)
|
||||
return;
|
||||
if (spawnType == 3 && npc.stats.spawnCycle == 3) {
|
||||
spawnEntity(compound1);
|
||||
spawnEntity(compound2);
|
||||
|
||||
@@ -63,7 +63,7 @@ import noppes.npcs.api.IBlock;
|
||||
import noppes.npcs.api.ICommand;
|
||||
import noppes.npcs.api.IContainer;
|
||||
import noppes.npcs.api.IDamageSource;
|
||||
import noppes.npcs.api.IEnergyController;
|
||||
import noppes.npcs.api.IEnergyHandler;
|
||||
import noppes.npcs.api.INbt;
|
||||
import noppes.npcs.api.IParticle;
|
||||
import noppes.npcs.api.IPos;
|
||||
@@ -623,7 +623,7 @@ public class NpcAPI extends AbstractNpcAPI {
|
||||
}
|
||||
|
||||
@Override
|
||||
public IEnergyController getEnergyController() {
|
||||
public IEnergyHandler getEnergyHandler() {
|
||||
return EnergyController.Instance;
|
||||
}
|
||||
|
||||
|
||||
@@ -121,6 +121,14 @@ public class ScriptEnergyBarrier<T extends EntityEnergyBarrier> extends ScriptEn
|
||||
entity.getBarrierData().absorbing = absorbing;
|
||||
}
|
||||
|
||||
public float getAbsorbRadius() {
|
||||
return entity.getBarrierData().absorbRadius;
|
||||
}
|
||||
|
||||
public void setAbsorbRadius(float radius) {
|
||||
entity.getBarrierData().absorbRadius = radius;
|
||||
}
|
||||
|
||||
public boolean isReflect() {
|
||||
return entity.getBarrierData().reflect;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user