mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-13 05:27:37 +00:00
Merge branch 'dev' into syntax-highlighter-unified
# Conflicts: # gradle-plugins~dev
This commit is contained in:
commit
476c6724b9
46 files changed
+971
-1269
No files matched your search
@@ -138,6 +138,16 @@ public abstract class Ability implements IAbility {
|
||||
// OPTIONAL OVERRIDES
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* Returns true if this ability type deals damage.
|
||||
* Override in non-damaging subclasses to return false.
|
||||
* Used by external mods to determine whether to show
|
||||
* damage-related configuration (e.g., DBC stats tab).
|
||||
*/
|
||||
public boolean hasDamage() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onWindUpTick(EntityLivingBase caster, EntityLivingBase target, World world, int tick) {
|
||||
}
|
||||
|
||||
@@ -247,12 +257,22 @@ public abstract class Ability implements IAbility {
|
||||
|
||||
// Apply damage
|
||||
if (damage > 0) {
|
||||
if (caster instanceof EntityNPCInterface) {
|
||||
hitEntity.attackEntityFrom(new NpcDamageSource("mob", (EntityNPCInterface) caster), damage);
|
||||
} else if (caster instanceof EntityPlayer) {
|
||||
hitEntity.attackEntityFrom(DamageSource.causePlayerDamage((EntityPlayer) caster), damage);
|
||||
} else {
|
||||
hitEntity.attackEntityFrom(DamageSource.causeMobDamage(caster), damage);
|
||||
// Check for external damage handler first (e.g., DBC Addon)
|
||||
IAbilityDamageHandler handler = AbilityController.Instance.getDamageHandler();
|
||||
boolean handled = false;
|
||||
if (handler != null) {
|
||||
handled = handler.handleDamage(this, caster, hitEntity, damage, knockback, knockbackUp,
|
||||
knockbackDirX, knockbackDirZ);
|
||||
}
|
||||
if (!handled) {
|
||||
// Default damage path
|
||||
if (caster instanceof EntityNPCInterface) {
|
||||
hitEntity.attackEntityFrom(new NpcDamageSource("mob", (EntityNPCInterface) caster), damage);
|
||||
} else if (caster instanceof EntityPlayer) {
|
||||
hitEntity.attackEntityFrom(DamageSource.causePlayerDamage((EntityPlayer) caster), damage);
|
||||
} else {
|
||||
hitEntity.attackEntityFrom(DamageSource.causeMobDamage(caster), damage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,6 +503,11 @@ public abstract class Ability implements IAbility {
|
||||
}
|
||||
}
|
||||
|
||||
// External field providers (e.g., DBC Addon injecting a "DBC" tab)
|
||||
for (IAbilityFieldProvider provider : AbilityController.Instance.getFieldProviders()) {
|
||||
provider.addFieldDefinitions(this, defs);
|
||||
}
|
||||
|
||||
return defs;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,12 @@ public class AbilityController implements IAbilityHandler {
|
||||
* Used by AbilitySlot for cache invalidation. */
|
||||
private int version = 0;
|
||||
|
||||
/** External damage handler (e.g., DBC Addon). */
|
||||
private IAbilityDamageHandler damageHandler = null;
|
||||
|
||||
/** External field providers for ability GUI (e.g., DBC Addon). Client-side only. */
|
||||
private final List<IAbilityFieldProvider> fieldProviders = new ArrayList<>();
|
||||
|
||||
public AbilityController() {
|
||||
registerBuiltinTypes();
|
||||
}
|
||||
@@ -386,4 +392,39 @@ public class AbilityController implements IAbilityHandler {
|
||||
registerType("cnpc:hazard", AbilityHazard::new);
|
||||
registerType("cnpc:trap", AbilityTrap::new);
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// EXTERNAL DAMAGE HANDLER
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* Register an external damage handler for abilities.
|
||||
* When set, the handler is called before default damage application.
|
||||
* If the handler returns true, default damage is skipped.
|
||||
*/
|
||||
public void registerDamageHandler(IAbilityDamageHandler handler) {
|
||||
this.damageHandler = handler;
|
||||
}
|
||||
|
||||
/** Get the registered damage handler, or null if none. */
|
||||
public IAbilityDamageHandler getDamageHandler() {
|
||||
return damageHandler;
|
||||
}
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// EXTERNAL FIELD PROVIDERS
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* Register an external field provider for ability GUIs.
|
||||
* Providers are called during getAllDefinitions() to inject custom tabs/fields.
|
||||
*/
|
||||
public void registerFieldProvider(IAbilityFieldProvider provider) {
|
||||
fieldProviders.add(provider);
|
||||
}
|
||||
|
||||
/** Get all registered field providers. */
|
||||
public List<IAbilityFieldProvider> getFieldProviders() {
|
||||
return fieldProviders;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package kamkeel.npcs.controllers.data.ability;
|
||||
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
|
||||
/**
|
||||
* External damage handler for abilities.
|
||||
* When registered, called AFTER script events but BEFORE default attackEntityFrom.
|
||||
* If handleDamage returns true, default damage is skipped.
|
||||
*/
|
||||
public interface IAbilityDamageHandler {
|
||||
/**
|
||||
* Handle damage from an ability.
|
||||
*
|
||||
* @param ability The ability dealing damage
|
||||
* @param caster The entity executing the ability
|
||||
* @param target The entity being hit
|
||||
* @param damage The damage amount (after script event modifications)
|
||||
* @param knockback The horizontal knockback
|
||||
* @param knockbackUp The vertical knockback
|
||||
* @param knockbackDirX The X component of knockback direction
|
||||
* @param knockbackDirZ The Z component of knockback direction
|
||||
* @return true if damage was handled (skip default), false to use default damage
|
||||
*/
|
||||
boolean handleDamage(Ability ability, EntityLivingBase caster, EntityLivingBase target,
|
||||
float damage, float knockback, float knockbackUp,
|
||||
double knockbackDirX, double knockbackDirZ);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package kamkeel.npcs.controllers.data.ability;
|
||||
|
||||
import noppes.npcs.client.gui.builder.FieldDef;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* External field definition provider for abilities.
|
||||
* Called during getAllDefinitions() to allow mods to inject custom tabs/fields
|
||||
* into the ability configuration GUI.
|
||||
* <p>
|
||||
* Note: Although this interface references FieldDef (client-only), it is safe to
|
||||
* register on both sides because the generic type is erased at bytecode level.
|
||||
* The addFieldDefinitions method is only ever called from client-side GUI code.
|
||||
*/
|
||||
public interface IAbilityFieldProvider {
|
||||
/**
|
||||
* Add field definitions to the ability's GUI.
|
||||
* Fields added here should use .tab() to assign them to a custom tab.
|
||||
*
|
||||
* @param ability The ability being configured
|
||||
* @param defs The mutable list of field definitions to add to
|
||||
*/
|
||||
void addFieldDefinitions(Ability ability, List<FieldDef> defs);
|
||||
}
|
||||
@@ -109,6 +109,7 @@ public class AbilityBeam extends Ability implements IAbilityEnergyBeam {
|
||||
beamEntity.setupCharging(anchorData, windUpTicks, offsetDist);
|
||||
|
||||
beamEntity.setEffects(this.effects);
|
||||
beamEntity.setSourceAbility(this);
|
||||
world.spawnEntityInWorld(beamEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,6 +137,8 @@ public class AbilityBeamDual extends Ability {
|
||||
beamEntity.setEffects(this.effects);
|
||||
if (dualFire) beamEntity2.setEffects(this.effects);
|
||||
|
||||
beamEntity.setSourceAbility(this);
|
||||
beamEntity2.setSourceAbility(this);
|
||||
world.spawnEntityInWorld(beamEntity);
|
||||
world.spawnEntityInWorld(beamEntity2);
|
||||
}
|
||||
|
||||
@@ -111,6 +111,11 @@ public class AbilityDash extends Ability implements IAbilityDash {
|
||||
this.activeSound = "mob.endermen.portal";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDamage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTargetingModeLocked() {
|
||||
return true;
|
||||
|
||||
@@ -110,6 +110,7 @@ public class AbilityDisc extends Ability implements IAbilityDisc {
|
||||
discEntity.setupCharging(anchorData, windUpTicks);
|
||||
|
||||
discEntity.setEffects(this.effects);
|
||||
discEntity.setSourceAbility(this);
|
||||
world.spawnEntityInWorld(discEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,6 +146,8 @@ public class AbilityDiscDual extends Ability {
|
||||
discEntity2.setEffects(this.effects);
|
||||
}
|
||||
|
||||
discEntity.setSourceAbility(this);
|
||||
discEntity2.setSourceAbility(this);
|
||||
world.spawnEntityInWorld(discEntity);
|
||||
world.spawnEntityInWorld(discEntity2);
|
||||
}
|
||||
|
||||
@@ -65,6 +65,11 @@ public class AbilityGuard extends Ability implements IAbilityGuard {
|
||||
this.counterAnimationName = "Ability_Guard_Counter";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDamage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public enum CounterType {
|
||||
FLAT,
|
||||
PERCENT;
|
||||
|
||||
@@ -58,6 +58,11 @@ public class AbilityHeal extends Ability implements IAbilityHeal {
|
||||
this.showTelegraph = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDamage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTargetingModeLocked() {
|
||||
return true;
|
||||
|
||||
@@ -99,6 +99,7 @@ public class AbilityLaserShot extends Ability implements IAbilityLaserShot {
|
||||
laserEntity.setupCharging(anchorData, windUpTicks);
|
||||
|
||||
laserEntity.setEffects(this.effects);
|
||||
laserEntity.setSourceAbility(this);
|
||||
world.spawnEntityInWorld(laserEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,6 +104,7 @@ public class AbilityOrb extends Ability implements IAbilityOrb {
|
||||
orbEntity.setupCharging(anchorData, windUpTicks);
|
||||
|
||||
orbEntity.setEffects(this.effects);
|
||||
orbEntity.setSourceAbility(this);
|
||||
world.spawnEntityInWorld(orbEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +129,7 @@ public class AbilityOrbBarrage extends Ability {
|
||||
);
|
||||
|
||||
orbEntity.setupCharging(anchorData[i], windUpTicks);
|
||||
orbEntity.setSourceAbility(this);
|
||||
|
||||
chargingEntities[i] = orbEntity;
|
||||
world.spawnEntityInWorld(orbEntity);
|
||||
@@ -179,6 +180,7 @@ public class AbilityOrbBarrage extends Ability {
|
||||
orbSize, colorData, combatData, homingData, lightningData, lifespanData, trajectoryData
|
||||
);
|
||||
|
||||
orb.setSourceAbility(this);
|
||||
world.spawnEntityInWorld(orb);
|
||||
|
||||
orbEntities.add(orb);
|
||||
|
||||
@@ -133,6 +133,8 @@ public class AbilityOrbDual extends Ability {
|
||||
orbEntity2.setEffects(this.effects);
|
||||
}
|
||||
|
||||
orbEntity.setSourceAbility(this);
|
||||
orbEntity2.setSourceAbility(this);
|
||||
world.spawnEntityInWorld(orbEntity);
|
||||
world.spawnEntityInWorld(orbEntity2);
|
||||
}
|
||||
|
||||
@@ -84,6 +84,11 @@ public class AbilityTeleport extends Ability implements IAbilityTeleport {
|
||||
this.activeSound = "mob.endermen.portal";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDamage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTargetingModeLocked() {
|
||||
return true;
|
||||
|
||||
@@ -4,8 +4,11 @@ import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData;
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import kamkeel.npcs.controllers.data.ability.Ability;
|
||||
import kamkeel.npcs.controllers.data.ability.AbilityController;
|
||||
import kamkeel.npcs.controllers.data.ability.AbilityEffect;
|
||||
import kamkeel.npcs.controllers.data.ability.AnchorPoint;
|
||||
import kamkeel.npcs.controllers.data.ability.IAbilityDamageHandler;
|
||||
import kamkeel.npcs.controllers.data.ability.data.*;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
@@ -77,6 +80,9 @@ public abstract class EntityAbilityProjectile extends Entity implements IEnergyP
|
||||
protected boolean previewMode = false; // Client-side preview mode (no damage/effects)
|
||||
protected EntityLivingBase previewOwner = null; // Direct reference for GUI preview (no world lookup)
|
||||
|
||||
/** The ability that spawned this projectile. Transient, not saved to NBT. */
|
||||
protected transient Ability sourceAbility = null;
|
||||
|
||||
// ==================== ROTATION INTERPOLATION ====================
|
||||
public float prevRotationValX, prevRotationValY, prevRotationValZ;
|
||||
public float rotationValX, rotationValY, rotationValZ;
|
||||
@@ -322,14 +328,30 @@ public abstract class EntityAbilityProjectile extends Entity implements IEnergyP
|
||||
if (previewMode) return; // Skip damage in preview mode
|
||||
Entity owner = getOwnerEntity();
|
||||
|
||||
if (owner instanceof EntityNPCInterface) {
|
||||
target.attackEntityFrom(new NpcDamageSource("npc_ability", (EntityNPCInterface) owner), dmg);
|
||||
} else if (owner instanceof EntityPlayer) {
|
||||
target.attackEntityFrom(DamageSource.causePlayerDamage((EntityPlayer) owner), dmg);
|
||||
} else if (owner instanceof EntityLivingBase) {
|
||||
target.attackEntityFrom(DamageSource.causeMobDamage((EntityLivingBase) owner), dmg);
|
||||
} else {
|
||||
target.attackEntityFrom(new NpcDamageSource("npc_ability", null), dmg);
|
||||
// Check for external damage handler (e.g., DBC Addon)
|
||||
boolean handled = false;
|
||||
if (sourceAbility != null && owner instanceof EntityLivingBase) {
|
||||
IAbilityDamageHandler handler = AbilityController.Instance.getDamageHandler();
|
||||
if (handler != null) {
|
||||
double dx = target.posX - posX;
|
||||
double dz = target.posZ - posZ;
|
||||
float kbUp = getKnockbackUp() > 0 ? getKnockbackUp() : 0.1f;
|
||||
handled = handler.handleDamage(sourceAbility, (EntityLivingBase) owner, target,
|
||||
dmg, kb, kbUp, dx, dz);
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled) {
|
||||
// Default damage path
|
||||
if (owner instanceof EntityNPCInterface) {
|
||||
target.attackEntityFrom(new NpcDamageSource("npc_ability", (EntityNPCInterface) owner), dmg);
|
||||
} else if (owner instanceof EntityPlayer) {
|
||||
target.attackEntityFrom(DamageSource.causePlayerDamage((EntityPlayer) owner), dmg);
|
||||
} else if (owner instanceof EntityLivingBase) {
|
||||
target.attackEntityFrom(DamageSource.causeMobDamage((EntityLivingBase) owner), dmg);
|
||||
} else {
|
||||
target.attackEntityFrom(new NpcDamageSource("npc_ability", null), dmg);
|
||||
}
|
||||
}
|
||||
|
||||
if (kb > 0) {
|
||||
@@ -361,6 +383,21 @@ public abstract class EntityAbilityProjectile extends Entity implements IEnergyP
|
||||
this.effects = effects != null ? effects : new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the source ability that spawned this projectile.
|
||||
* Used by external damage handlers to access ability-specific data.
|
||||
*/
|
||||
public void setSourceAbility(Ability ability) {
|
||||
this.sourceAbility = ability;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the source ability that spawned this projectile.
|
||||
*/
|
||||
public Ability getSourceAbility() {
|
||||
return sourceAbility;
|
||||
}
|
||||
|
||||
protected void doExplosion() {
|
||||
if (previewMode) return; // Skip explosion in preview mode
|
||||
worldObj.playSoundEffect(posX, posY, posZ, "random.explode", 1.0f, 1.0f);
|
||||
|
||||
@@ -16,7 +16,9 @@ import net.minecraft.nbt.NBTTagCompound;
|
||||
import noppes.npcs.client.AuctionClientConfig;
|
||||
import noppes.npcs.client.ClientCacheHandler;
|
||||
import noppes.npcs.config.ConfigMain;
|
||||
import noppes.npcs.client.ScriptClientConfig;
|
||||
import noppes.npcs.controllers.AuctionConfigSync;
|
||||
import noppes.npcs.controllers.ScriptConfigSync;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.EnumMap;
|
||||
@@ -65,6 +67,11 @@ public final class LoginPacket extends AbstractPacket {
|
||||
NBTTagCompound auctionConfig = new NBTTagCompound();
|
||||
AuctionConfigSync.writeToNBT(auctionConfig);
|
||||
ByteBufUtils.writeNBT(out, auctionConfig);
|
||||
|
||||
// Send script config (server-side sync)
|
||||
NBTTagCompound scriptConfig = new NBTTagCompound();
|
||||
ScriptConfigSync.writeToNBT(scriptConfig);
|
||||
ByteBufUtils.writeNBT(out, scriptConfig);
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@@ -88,6 +95,10 @@ public final class LoginPacket extends AbstractPacket {
|
||||
NBTTagCompound auctionConfig = ByteBufUtils.readNBT(in);
|
||||
AuctionClientConfig.readFromNBT(auctionConfig);
|
||||
|
||||
// Read script config
|
||||
NBTTagCompound scriptConfig = ByteBufUtils.readNBT(in);
|
||||
ScriptClientConfig.readFromNBT(scriptConfig);
|
||||
|
||||
PacketClient.sendClient(new SyncRevisionInfoPacket(
|
||||
serverKey,
|
||||
ClientCacheHandler.getLastServerKey(),
|
||||
|
||||
@@ -13,6 +13,7 @@ import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import noppes.npcs.CustomNpcsPermissions;
|
||||
import noppes.npcs.NBTTags;
|
||||
import noppes.npcs.client.ScriptClientConfig;
|
||||
import noppes.npcs.config.ConfigScript;
|
||||
import noppes.npcs.controllers.ScriptController;
|
||||
|
||||
@@ -69,8 +70,8 @@ public final class ScriptFilesPacket extends AbstractPacket {
|
||||
}
|
||||
|
||||
//Set client side configs
|
||||
ConfigScript.ScriptingEnabled = compound.getBoolean("ScriptingEnabled");
|
||||
ConfigScript.RunLoadedScriptsFirst = compound.getBoolean("LoadedFirst");
|
||||
ScriptClientConfig.setScriptingEnabled(compound.getBoolean("ScriptingEnabled"));
|
||||
ScriptClientConfig.setRunLoadedScriptsFirst(compound.getBoolean("LoadedFirst"));
|
||||
ScriptController.Instance.globalRevision = compound.getInteger("GlobalRevision");
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ import noppes.npcs.containers.ContainerNpcQuestReward;
|
||||
import noppes.npcs.containers.ContainerNpcQuestTypeItem;
|
||||
import noppes.npcs.controllers.data.AnimationData;
|
||||
import noppes.npcs.controllers.data.PlayerData;
|
||||
import noppes.npcs.config.ConfigScript;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
|
||||
public class CommonProxy implements IGuiHandler {
|
||||
@@ -220,4 +221,24 @@ public class CommonProxy implements IGuiHandler {
|
||||
|
||||
public void buildPackageIndex() {
|
||||
}
|
||||
|
||||
public boolean isScriptingEnabled() {
|
||||
return ConfigScript.ScriptingEnabled;
|
||||
}
|
||||
|
||||
public boolean isRunLoadedScriptsFirst() {
|
||||
return ConfigScript.RunLoadedScriptsFirst;
|
||||
}
|
||||
|
||||
public boolean isGlobalPlayerScripts() {
|
||||
return ConfigScript.GlobalPlayerScripts;
|
||||
}
|
||||
|
||||
public boolean isGlobalForgeScripts() {
|
||||
return ConfigScript.GlobalForgeScripts;
|
||||
}
|
||||
|
||||
public boolean isGlobalNPCScripts() {
|
||||
return ConfigScript.GlobalNPCScripts;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ import net.minecraftforge.client.event.RenderGameOverlayEvent;
|
||||
import net.minecraftforge.client.event.RenderHandEvent;
|
||||
import net.minecraftforge.client.event.RenderLivingEvent;
|
||||
import net.minecraftforge.client.event.RenderPlayerEvent;
|
||||
import net.minecraftforge.event.entity.player.ItemTooltipEvent;
|
||||
import noppes.npcs.client.gui.player.AuctionTooltipHandler;
|
||||
import noppes.npcs.client.gui.customoverlay.OverlayCustom;
|
||||
import noppes.npcs.client.gui.hud.ClientHudManager;
|
||||
import noppes.npcs.client.gui.hud.CompassHudComponent;
|
||||
@@ -75,6 +77,11 @@ public class ClientEventHandler {
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onItemTooltip(ItemTooltipEvent event) {
|
||||
AuctionTooltipHandler.onItemTooltip(event);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onMouse(MouseEvent event) {
|
||||
if (Minecraft.getMinecraft().currentScreen != null)
|
||||
|
||||
@@ -194,6 +194,7 @@ import noppes.npcs.client.renderer.items.ItemShortLampRenderer;
|
||||
import noppes.npcs.client.renderer.items.ItemTallLampRenderer;
|
||||
import noppes.npcs.client.renderer.items.ItemToolRenderer;
|
||||
import noppes.npcs.client.renderer.items.ScriptedBlockItemRenderer;
|
||||
import noppes.npcs.client.ScriptClientConfig;
|
||||
import noppes.npcs.config.ConfigClient;
|
||||
import noppes.npcs.config.ConfigItem;
|
||||
import noppes.npcs.config.ConfigMain;
|
||||
@@ -828,6 +829,31 @@ public class ClientProxy extends CommonProxy {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isScriptingEnabled() {
|
||||
return ConfigClient.AllowClientScripts && ScriptClientConfig.isScriptingEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunLoadedScriptsFirst() {
|
||||
return ScriptClientConfig.isRunLoadedScriptsFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGlobalPlayerScripts() {
|
||||
return ConfigClient.AllowClientScripts && ScriptClientConfig.isGlobalPlayerScripts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGlobalForgeScripts() {
|
||||
return ConfigClient.AllowClientScripts && ScriptClientConfig.isGlobalForgeScripts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGlobalNPCScripts() {
|
||||
return ConfigClient.AllowClientScripts && ScriptClientConfig.isGlobalNPCScripts();
|
||||
}
|
||||
|
||||
public static class FontContainer {
|
||||
public StringCache textFont = null;
|
||||
public boolean useCustomFont = true;
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package noppes.npcs.client;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
/**
|
||||
* Client-side cache for script configuration synced from server.
|
||||
* Prevents client from using local ConfigScript which may differ from server settings.
|
||||
*
|
||||
* IMPORTANT: This class is CLIENT-ONLY. Server-side NBT writing is done in
|
||||
* ScriptConfigSync to avoid @SideOnly crashes on dedicated servers.
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class ScriptClientConfig {
|
||||
// Cached values from server
|
||||
private static boolean scriptingEnabled = true;
|
||||
private static boolean runLoadedScriptsFirst = true;
|
||||
private static boolean globalPlayerScripts = true;
|
||||
private static boolean globalForgeScripts = true;
|
||||
private static boolean globalNPCScripts = false;
|
||||
|
||||
/**
|
||||
* Update cached config from server NBT data.
|
||||
* Called when receiving login packet or script sync packets.
|
||||
*/
|
||||
public static void readFromNBT(NBTTagCompound compound) {
|
||||
if (compound == null) return;
|
||||
|
||||
scriptingEnabled = compound.getBoolean("ScriptingEnabled");
|
||||
runLoadedScriptsFirst = compound.getBoolean("RunLoadedScriptsFirst");
|
||||
globalPlayerScripts = compound.getBoolean("GlobalPlayerScripts");
|
||||
globalForgeScripts = compound.getBoolean("GlobalForgeScripts");
|
||||
globalNPCScripts = compound.getBoolean("GlobalNPCScripts");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset to defaults (called on disconnect).
|
||||
*/
|
||||
public static void reset() {
|
||||
scriptingEnabled = true;
|
||||
runLoadedScriptsFirst = true;
|
||||
globalPlayerScripts = true;
|
||||
globalForgeScripts = true;
|
||||
globalNPCScripts = false;
|
||||
}
|
||||
|
||||
// Setters for individual packet updates
|
||||
public static void setScriptingEnabled(boolean value) { scriptingEnabled = value; }
|
||||
public static void setRunLoadedScriptsFirst(boolean value) { runLoadedScriptsFirst = value; }
|
||||
public static void setGlobalPlayerScripts(boolean value) { globalPlayerScripts = value; }
|
||||
public static void setGlobalForgeScripts(boolean value) { globalForgeScripts = value; }
|
||||
public static void setGlobalNPCScripts(boolean value) { globalNPCScripts = value; }
|
||||
|
||||
// Getters
|
||||
public static boolean isScriptingEnabled() { return scriptingEnabled; }
|
||||
public static boolean isRunLoadedScriptsFirst() { return runLoadedScriptsFirst; }
|
||||
public static boolean isGlobalPlayerScripts() { return globalPlayerScripts; }
|
||||
public static boolean isGlobalForgeScripts() { return globalForgeScripts; }
|
||||
public static boolean isGlobalNPCScripts() { return globalNPCScripts; }
|
||||
}
|
||||
@@ -4,14 +4,18 @@ import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import net.minecraft.inventory.Slot;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.util.StatCollector;
|
||||
import net.minecraftforge.event.entity.player.ItemTooltipEvent;
|
||||
import noppes.npcs.client.AuctionClientConfig;
|
||||
import noppes.npcs.constants.EnumClaimType;
|
||||
import noppes.npcs.containers.ContainerAuctionListing;
|
||||
import noppes.npcs.containers.ContainerAuctionSell;
|
||||
import noppes.npcs.containers.ContainerAuctionTrades;
|
||||
import noppes.npcs.containers.SlotAuctionDisplay;
|
||||
import noppes.npcs.controllers.data.AuctionClaim;
|
||||
import noppes.npcs.controllers.data.AuctionListing;
|
||||
|
||||
@@ -19,45 +23,60 @@ import java.util.List;
|
||||
|
||||
/**
|
||||
* Handles adding auction information to item tooltips when viewing auction GUIs.
|
||||
* Called from MixinItem when Item.addInformation is invoked.
|
||||
* Called from ItemTooltipEvent in ClientEventHandler.
|
||||
*
|
||||
* Uses slot-based lookup (slot index) instead of ItemStack comparison to correctly
|
||||
* handle duplicate items with different auction data (e.g., two porkchops at different prices).
|
||||
*/
|
||||
@SideOnly(Side.CLIENT)
|
||||
public class AuctionTooltipHandler {
|
||||
|
||||
/**
|
||||
* Add auction information to an item's tooltip if we're in an auction GUI.
|
||||
* Handle ItemTooltipEvent - append auction info to the end of the tooltip.
|
||||
*/
|
||||
public static void addAuctionInfo(ItemStack stack, List<String> tooltip) {
|
||||
if (stack == null || tooltip == null) return;
|
||||
public static void onItemTooltip(ItemTooltipEvent event) {
|
||||
if (event.itemStack == null) return;
|
||||
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
if (mc == null || mc.currentScreen == null) return;
|
||||
|
||||
GuiScreen screen = mc.currentScreen;
|
||||
|
||||
// Check if we're in an auction listing GUI
|
||||
if (screen instanceof GuiAuctionListing) {
|
||||
addListingTooltip((GuiAuctionListing) screen, stack, tooltip);
|
||||
}
|
||||
// Check if we're in the trades GUI
|
||||
else if (screen instanceof GuiAuctionTrades) {
|
||||
addTradesTooltip((GuiAuctionTrades) screen, stack, tooltip);
|
||||
}
|
||||
// Check if we're in the sell GUI
|
||||
else if (screen instanceof GuiAuctionSell) {
|
||||
addSellTooltip((GuiAuctionSell) screen, stack, tooltip);
|
||||
addListingTooltip((GuiAuctionListing) screen, event.itemStack, event.toolTip);
|
||||
} else if (screen instanceof GuiAuctionTrades) {
|
||||
addTradesTooltip((GuiAuctionTrades) screen, event.itemStack, event.toolTip);
|
||||
} else if (screen instanceof GuiAuctionSell) {
|
||||
addSellTooltip((GuiAuctionSell) screen, event.itemStack, event.toolTip);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add auction info when viewing the main listings page.
|
||||
* Find the slot in the container whose getStack() returns the exact same ItemStack reference.
|
||||
* This avoids the duplicate item bug where ItemStack.areItemStacksEqual matches the wrong listing.
|
||||
*/
|
||||
private static Slot findHoveredSlot(GuiContainer gui, ItemStack stack) {
|
||||
if (stack == null) return null;
|
||||
for (Object obj : gui.inventorySlots.inventorySlots) {
|
||||
Slot slot = (Slot) obj;
|
||||
if (slot.getHasStack() && slot.getStack() == stack) {
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// ========== Listing Page ==========
|
||||
|
||||
private static void addListingTooltip(GuiAuctionListing gui, ItemStack stack, List<String> tooltip) {
|
||||
ContainerAuctionListing container = (ContainerAuctionListing) gui.inventorySlots;
|
||||
Slot slot = findHoveredSlot(gui, stack);
|
||||
if (slot == null || !(slot instanceof SlotAuctionDisplay)) return;
|
||||
|
||||
ContainerAuctionListing container = gui.getListingContainer();
|
||||
if (container == null) return;
|
||||
|
||||
// Find the listing that matches this ItemStack
|
||||
AuctionListing listing = container.getListingForItem(stack);
|
||||
int displayIndex = slot.getSlotIndex();
|
||||
AuctionListing listing = container.getListingAt(displayIndex);
|
||||
if (listing == null) return;
|
||||
|
||||
tooltip.add("");
|
||||
@@ -90,149 +109,153 @@ public class AuctionTooltipHandler {
|
||||
tooltip.add((timeRemaining < 3600000 ? EnumChatFormatting.RED : EnumChatFormatting.WHITE) + timeText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add auction info when viewing the trades page.
|
||||
*/
|
||||
// ========== Trades Page ==========
|
||||
|
||||
private static void addTradesTooltip(GuiAuctionTrades gui, ItemStack stack, List<String> tooltip) {
|
||||
ContainerAuctionTrades container = (ContainerAuctionTrades) gui.inventorySlots;
|
||||
Slot slot = findHoveredSlot(gui, stack);
|
||||
if (slot == null || !(slot instanceof SlotAuctionDisplay)) return;
|
||||
|
||||
ContainerAuctionTrades container = gui.getTradesContainer();
|
||||
if (container == null) return;
|
||||
|
||||
// Check if it's an item I'm selling
|
||||
AuctionListing sellingListing = container.getSellingListingForItem(stack);
|
||||
if (sellingListing != null) {
|
||||
tooltip.add("");
|
||||
tooltip.add(EnumChatFormatting.GREEN + StatCollector.translateToLocal("auction.trades.selling"));
|
||||
int displayIndex = slot.getSlotIndex();
|
||||
|
||||
if (sellingListing.hasBids()) {
|
||||
tooltip.add(EnumChatFormatting.YELLOW + StatCollector.translateToLocal("auction.currentBid")
|
||||
.replace("%s", EnumChatFormatting.GOLD + formatCurrency(sellingListing.currentBid)));
|
||||
tooltip.add(EnumChatFormatting.GRAY + String.format(StatCollector.translateToLocal("auction.bids"), sellingListing.bidCount));
|
||||
} else {
|
||||
tooltip.add(EnumChatFormatting.GRAY + StatCollector.translateToLocal("auction.noBids"));
|
||||
// Check listings first (selling or bidding)
|
||||
AuctionListing listing = container.getListingAt(displayIndex);
|
||||
if (listing != null) {
|
||||
if (container.isSellingAt(displayIndex)) {
|
||||
addSellingTooltip(listing, tooltip);
|
||||
} else if (container.isBiddingAt(displayIndex)) {
|
||||
addBiddingTooltip(listing, tooltip);
|
||||
}
|
||||
|
||||
long timeRemaining = sellingListing.getTimeRemaining();
|
||||
String timeText = StatCollector.translateToLocal("auction.timeLeft")
|
||||
.replace("%s", formatTimeRemaining(timeRemaining));
|
||||
tooltip.add((timeRemaining < 3600000 ? EnumChatFormatting.RED : EnumChatFormatting.WHITE) + timeText);
|
||||
|
||||
tooltip.add("");
|
||||
tooltip.add(EnumChatFormatting.YELLOW + StatCollector.translateToLocal("auction.trades.rightClickToCancel"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if it's an item I'm bidding on
|
||||
AuctionListing biddingListing = container.getBiddingListingForItem(stack);
|
||||
if (biddingListing != null) {
|
||||
tooltip.add("");
|
||||
tooltip.add(EnumChatFormatting.YELLOW + StatCollector.translateToLocal("auction.trades.bidding"));
|
||||
|
||||
tooltip.add(EnumChatFormatting.YELLOW + StatCollector.translateToLocal("auction.currentBid")
|
||||
.replace("%s", EnumChatFormatting.GOLD + formatCurrency(biddingListing.currentBid)));
|
||||
tooltip.add(EnumChatFormatting.GRAY + String.format(StatCollector.translateToLocal("auction.bids"), biddingListing.bidCount));
|
||||
|
||||
long timeRemaining = biddingListing.getTimeRemaining();
|
||||
String timeText = StatCollector.translateToLocal("auction.timeLeft")
|
||||
.replace("%s", formatTimeRemaining(timeRemaining));
|
||||
tooltip.add((timeRemaining < 3600000 ? EnumChatFormatting.RED : EnumChatFormatting.WHITE) + timeText);
|
||||
|
||||
tooltip.add("");
|
||||
tooltip.add(EnumChatFormatting.GRAY + StatCollector.translateToLocal("auction.trades.clickToRebid"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if it's a claim
|
||||
AuctionClaim claim = container.getClaimForItem(stack);
|
||||
// Check claims
|
||||
AuctionClaim claim = container.getClaimAt(displayIndex);
|
||||
if (claim != null) {
|
||||
tooltip.add("");
|
||||
|
||||
// Title based on claim type
|
||||
switch (claim.type) {
|
||||
case ITEM:
|
||||
if (claim.isReturned) {
|
||||
// Expired - returned to seller
|
||||
tooltip.add(EnumChatFormatting.RED + StatCollector.translateToLocal("auction.trades.expired"));
|
||||
} else {
|
||||
// Won item
|
||||
tooltip.add(EnumChatFormatting.GREEN + StatCollector.translateToLocal("auction.trades.won"));
|
||||
}
|
||||
break;
|
||||
case CURRENCY:
|
||||
// Sold - money to claim
|
||||
tooltip.add(EnumChatFormatting.GREEN + StatCollector.translateToLocal("auction.trades.sold"));
|
||||
if (claim.itemName != null && !claim.itemName.isEmpty()) {
|
||||
tooltip.add(EnumChatFormatting.GRAY + StatCollector.translateToLocal("auction.claim.soldItem")
|
||||
.replace("%s", EnumChatFormatting.WHITE + claim.itemName));
|
||||
}
|
||||
if (claim.otherPlayerName != null && !claim.otherPlayerName.isEmpty()) {
|
||||
tooltip.add(EnumChatFormatting.GRAY + StatCollector.translateToLocal("auction.claim.buyer")
|
||||
.replace("%s", EnumChatFormatting.WHITE + claim.otherPlayerName));
|
||||
}
|
||||
break;
|
||||
case REFUND:
|
||||
// Outbid - refund available
|
||||
tooltip.add(EnumChatFormatting.RED + StatCollector.translateToLocal("auction.trades.outbid"));
|
||||
if (claim.otherPlayerName != null && !claim.otherPlayerName.isEmpty()) {
|
||||
tooltip.add(EnumChatFormatting.GRAY + StatCollector.translateToLocal("auction.claim.outbidBy")
|
||||
.replace("%s", EnumChatFormatting.WHITE + claim.otherPlayerName));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Amount for currency claims (including REFUND)
|
||||
if (claim.type.isCurrency()) {
|
||||
tooltip.add(EnumChatFormatting.YELLOW + StatCollector.translateToLocal("auction.claim.amount")
|
||||
.replace("%s", EnumChatFormatting.GOLD + formatCurrency(claim.currency)));
|
||||
}
|
||||
|
||||
// Expiration
|
||||
int expirationDays = AuctionClientConfig.getClaimExpirationDays();
|
||||
long daysLeft = claim.getDaysUntilExpiration(expirationDays);
|
||||
if (daysLeft <= 1) {
|
||||
tooltip.add(EnumChatFormatting.RED + StatCollector.translateToLocal("auction.claim.expiresSoon"));
|
||||
} else {
|
||||
tooltip.add(EnumChatFormatting.GRAY + StatCollector.translateToLocal("auction.claim.expires")
|
||||
.replace("%s", "" + daysLeft));
|
||||
}
|
||||
|
||||
tooltip.add("");
|
||||
|
||||
// Show rebid option for REFUND claims with item (active auction)
|
||||
if (claim.type == EnumClaimType.REFUND && claim.item != null) {
|
||||
tooltip.add(EnumChatFormatting.GREEN + StatCollector.translateToLocal("auction.trades.leftClickRebid"));
|
||||
tooltip.add(EnumChatFormatting.YELLOW + StatCollector.translateToLocal("auction.trades.rightClickRefund"));
|
||||
} else {
|
||||
tooltip.add(EnumChatFormatting.GREEN + StatCollector.translateToLocal("auction.claim.clickToClaim"));
|
||||
}
|
||||
addClaimTooltip(claim, tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add sell page tooltip info.
|
||||
*/
|
||||
private static void addSellingTooltip(AuctionListing listing, List<String> tooltip) {
|
||||
tooltip.add("");
|
||||
tooltip.add(EnumChatFormatting.GREEN + StatCollector.translateToLocal("auction.trades.selling"));
|
||||
|
||||
if (listing.hasBids()) {
|
||||
tooltip.add(EnumChatFormatting.YELLOW + StatCollector.translateToLocal("auction.currentBid")
|
||||
.replace("%s", EnumChatFormatting.GOLD + formatCurrency(listing.currentBid)));
|
||||
tooltip.add(EnumChatFormatting.GRAY + String.format(StatCollector.translateToLocal("auction.bids"), listing.bidCount));
|
||||
} else {
|
||||
tooltip.add(EnumChatFormatting.GRAY + StatCollector.translateToLocal("auction.noBids"));
|
||||
}
|
||||
|
||||
long timeRemaining = listing.getTimeRemaining();
|
||||
String timeText = StatCollector.translateToLocal("auction.timeLeft")
|
||||
.replace("%s", formatTimeRemaining(timeRemaining));
|
||||
tooltip.add((timeRemaining < 3600000 ? EnumChatFormatting.RED : EnumChatFormatting.WHITE) + timeText);
|
||||
|
||||
tooltip.add("");
|
||||
tooltip.add(EnumChatFormatting.YELLOW + StatCollector.translateToLocal("auction.trades.rightClickToCancel"));
|
||||
}
|
||||
|
||||
private static void addBiddingTooltip(AuctionListing listing, List<String> tooltip) {
|
||||
tooltip.add("");
|
||||
tooltip.add(EnumChatFormatting.YELLOW + StatCollector.translateToLocal("auction.trades.bidding"));
|
||||
|
||||
tooltip.add(EnumChatFormatting.YELLOW + StatCollector.translateToLocal("auction.currentBid")
|
||||
.replace("%s", EnumChatFormatting.GOLD + formatCurrency(listing.currentBid)));
|
||||
tooltip.add(EnumChatFormatting.GRAY + String.format(StatCollector.translateToLocal("auction.bids"), listing.bidCount));
|
||||
|
||||
long timeRemaining = listing.getTimeRemaining();
|
||||
String timeText = StatCollector.translateToLocal("auction.timeLeft")
|
||||
.replace("%s", formatTimeRemaining(timeRemaining));
|
||||
tooltip.add((timeRemaining < 3600000 ? EnumChatFormatting.RED : EnumChatFormatting.WHITE) + timeText);
|
||||
|
||||
tooltip.add("");
|
||||
tooltip.add(EnumChatFormatting.GRAY + StatCollector.translateToLocal("auction.trades.clickToRebid"));
|
||||
}
|
||||
|
||||
private static void addClaimTooltip(AuctionClaim claim, List<String> tooltip) {
|
||||
tooltip.add("");
|
||||
|
||||
switch (claim.type) {
|
||||
case ITEM:
|
||||
if (claim.isReturned) {
|
||||
tooltip.add(EnumChatFormatting.RED + StatCollector.translateToLocal("auction.trades.expired"));
|
||||
} else {
|
||||
tooltip.add(EnumChatFormatting.GREEN + StatCollector.translateToLocal("auction.trades.won"));
|
||||
}
|
||||
break;
|
||||
case CURRENCY:
|
||||
tooltip.add(EnumChatFormatting.GREEN + StatCollector.translateToLocal("auction.trades.sold"));
|
||||
if (claim.itemName != null && !claim.itemName.isEmpty()) {
|
||||
tooltip.add(EnumChatFormatting.GRAY + StatCollector.translateToLocal("auction.claim.soldItem")
|
||||
.replace("%s", EnumChatFormatting.WHITE + claim.itemName));
|
||||
}
|
||||
if (claim.otherPlayerName != null && !claim.otherPlayerName.isEmpty()) {
|
||||
tooltip.add(EnumChatFormatting.GRAY + StatCollector.translateToLocal("auction.claim.buyer")
|
||||
.replace("%s", EnumChatFormatting.WHITE + claim.otherPlayerName));
|
||||
}
|
||||
break;
|
||||
case REFUND:
|
||||
tooltip.add(EnumChatFormatting.RED + StatCollector.translateToLocal("auction.trades.outbid"));
|
||||
if (claim.otherPlayerName != null && !claim.otherPlayerName.isEmpty()) {
|
||||
tooltip.add(EnumChatFormatting.GRAY + StatCollector.translateToLocal("auction.claim.outbidBy")
|
||||
.replace("%s", EnumChatFormatting.WHITE + claim.otherPlayerName));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Amount for currency claims
|
||||
if (claim.type.isCurrency()) {
|
||||
tooltip.add(EnumChatFormatting.YELLOW + StatCollector.translateToLocal("auction.claim.amount")
|
||||
.replace("%s", EnumChatFormatting.GOLD + formatCurrency(claim.currency)));
|
||||
}
|
||||
|
||||
// Expiration
|
||||
int expirationDays = AuctionClientConfig.getClaimExpirationDays();
|
||||
long daysLeft = claim.getDaysUntilExpiration(expirationDays);
|
||||
if (daysLeft <= 1) {
|
||||
tooltip.add(EnumChatFormatting.RED + StatCollector.translateToLocal("auction.claim.expiresSoon"));
|
||||
} else {
|
||||
tooltip.add(EnumChatFormatting.GRAY + StatCollector.translateToLocal("auction.claim.expires")
|
||||
.replace("%s", "" + daysLeft));
|
||||
}
|
||||
|
||||
tooltip.add("");
|
||||
|
||||
// Rebid option for REFUND claims with item
|
||||
if (claim.type == EnumClaimType.REFUND && claim.item != null) {
|
||||
tooltip.add(EnumChatFormatting.GREEN + StatCollector.translateToLocal("auction.trades.leftClickRebid"));
|
||||
tooltip.add(EnumChatFormatting.YELLOW + StatCollector.translateToLocal("auction.trades.rightClickRefund"));
|
||||
} else {
|
||||
tooltip.add(EnumChatFormatting.GREEN + StatCollector.translateToLocal("auction.claim.clickToClaim"));
|
||||
}
|
||||
}
|
||||
|
||||
// ========== Sell Page ==========
|
||||
|
||||
private static void addSellTooltip(GuiAuctionSell gui, ItemStack stack, List<String> tooltip) {
|
||||
Slot slot = findHoveredSlot(gui, stack);
|
||||
if (slot == null) return;
|
||||
|
||||
ContainerAuctionSell container = (ContainerAuctionSell) gui.inventorySlots;
|
||||
if (container == null) return;
|
||||
|
||||
// Check if this is the sell slot item
|
||||
ItemStack sellItem = container.getItemToSell();
|
||||
if (sellItem != null && ItemStack.areItemStacksEqual(stack, sellItem)) {
|
||||
// This is the item in the sell slot
|
||||
if (container.isSellSlot(slot.slotNumber)) {
|
||||
tooltip.add("");
|
||||
tooltip.add(EnumChatFormatting.YELLOW + StatCollector.translateToLocal("auction.sell.leftClear"));
|
||||
tooltip.add(EnumChatFormatting.YELLOW + StatCollector.translateToLocal("auction.sell.rightRemove"));
|
||||
return;
|
||||
} else if (container.isPlayerInventorySlot(slot.slotNumber)) {
|
||||
tooltip.add("");
|
||||
tooltip.add(EnumChatFormatting.GRAY + StatCollector.translateToLocal("auction.sell.leftAdd"));
|
||||
tooltip.add(EnumChatFormatting.GRAY + StatCollector.translateToLocal("auction.sell.rightAddOne"));
|
||||
}
|
||||
|
||||
// This is an inventory item - show add controls
|
||||
tooltip.add("");
|
||||
tooltip.add(EnumChatFormatting.GRAY + StatCollector.translateToLocal("auction.sell.leftAdd"));
|
||||
tooltip.add(EnumChatFormatting.GRAY + StatCollector.translateToLocal("auction.sell.rightAddOne"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Format currency with commas.
|
||||
*/
|
||||
// ========== Formatting Utilities ==========
|
||||
|
||||
private static String formatCurrency(long amount) {
|
||||
if (amount < 1000) {
|
||||
return amount + " " + AuctionClientConfig.getCurrencyName();
|
||||
@@ -250,9 +273,6 @@ public class AuctionTooltipHandler {
|
||||
return sb.toString() + " " + AuctionClientConfig.getCurrencyName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Format time remaining.
|
||||
*/
|
||||
private static String formatTimeRemaining(long milliseconds) {
|
||||
if (milliseconds <= 0) {
|
||||
return StatCollector.translateToLocal("auction.ended");
|
||||
|
||||
@@ -112,16 +112,16 @@ public abstract class GuiAuctionInterface extends GuiContainerNPCInterface {
|
||||
mc.renderEngine.bindTexture(AUCTION_BACKGROUND);
|
||||
drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize);
|
||||
|
||||
GL11.glDisable(GL11.GL_LIGHTING);
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
|
||||
drawAuctionContent(partialTicks, mouseX, mouseY);
|
||||
|
||||
RenderHelper.enableGUIStandardItemLighting();
|
||||
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
|
||||
GL11.glEnable(GL11.GL_COLOR_MATERIAL);
|
||||
GL11.glEnable(GL11.GL_LIGHTING);
|
||||
|
||||
drawAuctionContent(partialTicks, mouseX, mouseY);
|
||||
|
||||
GL11.glEnable(GL11.GL_LIGHTING);
|
||||
GL11.glEnable(GL11.GL_DEPTH_TEST);
|
||||
RenderHelper.enableStandardItemLighting();
|
||||
|
||||
super.drawGuiContainerBackgroundLayer(partialTicks, mouseX, mouseY);
|
||||
}
|
||||
@@ -167,12 +167,12 @@ public abstract class GuiAuctionInterface extends GuiContainerNPCInterface {
|
||||
Gui.drawRect(x + 1, y + 1, x + 17, y + 17, color);
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
GL11.glEnable(GL11.GL_DEPTH_TEST);
|
||||
GL11.glEnable(GL11.GL_LIGHTING);
|
||||
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
}
|
||||
|
||||
/** Draw dark overlay for unavailable slots */
|
||||
protected void drawDarkenedOverlay(int x, int y) {
|
||||
drawColoredOverlay(x, y, 0x80000000);
|
||||
drawColoredOverlay(x, y, 0xC0000000);
|
||||
}
|
||||
|
||||
/** Draw icon texture on slot (16x16) */
|
||||
|
||||
@@ -38,10 +38,10 @@ public class GuiAuctionTrades extends GuiAuctionInterface implements IGuiData {
|
||||
private static final int TOTAL_SLOTS = COLS * ROWS;
|
||||
|
||||
// Slot tint colors (ARGB)
|
||||
private static final int TINT_BLUE = 0x303060FF; // Active listing/bid (selling)
|
||||
private static final int TINT_GREEN = 0x3030FF30; // Sold (currency claim) or Won (item claim)
|
||||
private static final int TINT_YELLOW = 0x30FFFF30; // Outbid (refund claim)
|
||||
private static final int TINT_RED = 0x30FF3030; // Expired/Returned (item returned to seller)
|
||||
private static final int TINT_BLUE = 0x605080FF; // Active listing/bid (selling)
|
||||
private static final int TINT_GREEN = 0x6050FF50; // Sold (currency claim) or Won (item claim)
|
||||
private static final int TINT_YELLOW = 0x60FFFF50; // Outbid (refund claim)
|
||||
private static final int TINT_RED = 0x60FF5050; // Expired/Returned (item returned to seller)
|
||||
|
||||
private final ContainerAuctionTrades tradesContainer;
|
||||
private int maxTradeSlots;
|
||||
|
||||
@@ -22,6 +22,9 @@ public class ConfigClient {
|
||||
/**
|
||||
* General Properties
|
||||
**/
|
||||
public static Property AllowClientScriptsProperty;
|
||||
public static boolean AllowClientScripts = true;
|
||||
|
||||
public static Property CacheLifeProperty;
|
||||
public static int CacheLife = 10;
|
||||
|
||||
@@ -185,6 +188,9 @@ public class ConfigClient {
|
||||
|
||||
|
||||
// General
|
||||
AllowClientScriptsProperty = config.get(GENERAL, "Allow Client Scripts", true, "Allow the server to run scripts on the client. If disabled, no server scripts will execute client-side.");
|
||||
AllowClientScripts = AllowClientScriptsProperty.getBoolean(true);
|
||||
|
||||
CacheLifeProperty = config.get(GENERAL, "Cache Life", 10, "How long should downloaded imagery data be saved client side? (In minutes)");
|
||||
CacheLife = CacheLifeProperty.getInt(10);
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package noppes.npcs.controllers;
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import noppes.npcs.config.ConfigScript;
|
||||
|
||||
/**
|
||||
* Server-side utility for syncing script configuration to clients.
|
||||
*
|
||||
* This class is SERVER-SIDE ONLY. Client reads via ScriptClientConfig.
|
||||
*/
|
||||
public class ScriptConfigSync {
|
||||
|
||||
/**
|
||||
* Write script config to NBT for sending to client.
|
||||
* Called on server side when building login packet.
|
||||
*/
|
||||
public static NBTTagCompound writeToNBT(NBTTagCompound compound) {
|
||||
compound.setBoolean("ScriptingEnabled", ConfigScript.ScriptingEnabled);
|
||||
compound.setBoolean("RunLoadedScriptsFirst", ConfigScript.RunLoadedScriptsFirst);
|
||||
compound.setBoolean("GlobalPlayerScripts", ConfigScript.GlobalPlayerScripts);
|
||||
compound.setBoolean("GlobalForgeScripts", ConfigScript.GlobalForgeScripts);
|
||||
compound.setBoolean("GlobalNPCScripts", ConfigScript.GlobalNPCScripts);
|
||||
return compound;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package noppes.npcs.controllers;
|
||||
import cpw.mods.fml.common.eventhandler.Event;
|
||||
import jdk.nashorn.api.scripting.ScriptObjectMirror;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import noppes.npcs.CustomNpcs;
|
||||
import noppes.npcs.NBTTags;
|
||||
import noppes.npcs.config.ConfigScript;
|
||||
import noppes.npcs.constants.EnumScriptType;
|
||||
@@ -104,7 +105,7 @@ public class ScriptContainer implements IScriptUnit {
|
||||
if (!this.evaluated) {
|
||||
// build includes first depending on config setting
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (ConfigScript.RunLoadedScriptsFirst) {
|
||||
if (CustomNpcs.proxy.isRunLoadedScriptsFirst()) {
|
||||
this.appendExternalScripts(sb);
|
||||
}
|
||||
|
||||
@@ -114,7 +115,7 @@ public class ScriptContainer implements IScriptUnit {
|
||||
}
|
||||
|
||||
// build includes last if not built first
|
||||
if (!ConfigScript.RunLoadedScriptsFirst) {
|
||||
if (!CustomNpcs.proxy.isRunLoadedScriptsFirst()) {
|
||||
this.appendExternalScripts(sb);
|
||||
}
|
||||
this.fullscript = sb.toString();
|
||||
@@ -158,14 +159,14 @@ public class ScriptContainer implements IScriptUnit {
|
||||
}
|
||||
|
||||
public void run(EnumScriptType type, Event event) {
|
||||
if (!ConfigScript.ScriptingEnabled)
|
||||
if (!CustomNpcs.proxy.isScriptingEnabled())
|
||||
return;
|
||||
|
||||
this.run((String) type.function, (Object) event);
|
||||
}
|
||||
|
||||
public void run(String type, Object event) {
|
||||
if (!ConfigScript.ScriptingEnabled || errored || !hasCode() || unknownFunctions.contains(type))
|
||||
if (!CustomNpcs.proxy.isScriptingEnabled() || errored || !hasCode() || unknownFunctions.contains(type))
|
||||
return;
|
||||
|
||||
this.setEngine(handler.getLanguage());
|
||||
|
||||
@@ -73,7 +73,7 @@ public class ScriptController {
|
||||
public ScriptController() {
|
||||
Instance = this;
|
||||
manager = new ScriptEngineManager();
|
||||
if (!ConfigScript.ScriptingEnabled)
|
||||
if (!CustomNpcs.proxy.isScriptingEnabled())
|
||||
return;
|
||||
LogWriter.info("Script Engines Available:");
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@ import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import noppes.npcs.CustomNpcs;
|
||||
import noppes.npcs.EventHooks;
|
||||
import noppes.npcs.LogWriter;
|
||||
import noppes.npcs.NBTTags;
|
||||
import noppes.npcs.api.IWorld;
|
||||
import noppes.npcs.api.entity.ICustomNpc;
|
||||
import noppes.npcs.config.ConfigDebug;
|
||||
import noppes.npcs.config.ConfigScript;
|
||||
import noppes.npcs.constants.EnumScriptType;
|
||||
import noppes.npcs.constants.ScriptContext;
|
||||
import noppes.npcs.controllers.ScriptContainer;
|
||||
@@ -207,7 +207,7 @@ public class DataScript implements IScriptHandlerPacket {
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled && ScriptController.HasStart && !npc.worldObj.isRemote && !scripts.isEmpty() && ConfigScript.ScriptingEnabled;
|
||||
return enabled && ScriptController.HasStart && !npc.worldObj.isRemote && !scripts.isEmpty() && CustomNpcs.proxy.isScriptingEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -12,8 +12,8 @@ import net.minecraftforge.event.world.ChunkDataEvent;
|
||||
import net.minecraftforge.event.world.ChunkEvent;
|
||||
import net.minecraftforge.event.world.ChunkWatchEvent;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
import noppes.npcs.CustomNpcs;
|
||||
import noppes.npcs.EventHooks;
|
||||
import noppes.npcs.config.ConfigScript;
|
||||
import noppes.npcs.constants.ScriptContext;
|
||||
import noppes.npcs.controllers.ScriptContainer;
|
||||
import noppes.npcs.controllers.ScriptController;
|
||||
@@ -36,7 +36,7 @@ public class ForgeDataScript extends MultiScriptHandler {
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.enabled && ConfigScript.GlobalForgeScripts && ScriptController.HasStart && this.scripts.size() > 0;
|
||||
return this.enabled && CustomNpcs.proxy.isGlobalForgeScripts() && ScriptController.HasStart && this.scripts.size() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,8 +3,8 @@ package noppes.npcs.controllers.data;
|
||||
import kamkeel.npcs.network.packets.request.script.GlobalNPCScriptPacket;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import noppes.npcs.CustomNpcs;
|
||||
import noppes.npcs.api.entity.ICustomNpc;
|
||||
import noppes.npcs.config.ConfigScript;
|
||||
import noppes.npcs.constants.ScriptContext;
|
||||
import noppes.npcs.controllers.ScriptController;
|
||||
import noppes.npcs.entity.EntityNPCInterface;
|
||||
@@ -28,7 +28,7 @@ public class GlobalNPCDataScript extends MultiScriptHandler {
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return ConfigScript.GlobalNPCScripts && this.enabled && ScriptController.HasStart && this.scripts.size() > 0;
|
||||
return CustomNpcs.proxy.isGlobalNPCScripts() && this.enabled && ScriptController.HasStart && this.scripts.size() > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,6 +5,7 @@ import kamkeel.npcs.network.packets.request.script.PlayerScriptPacket;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import noppes.npcs.CustomNpcs;
|
||||
import noppes.npcs.EventHooks;
|
||||
import noppes.npcs.NBTTags;
|
||||
import noppes.npcs.api.entity.IPlayer;
|
||||
@@ -60,7 +61,7 @@ public class PlayerDataScript extends MultiScriptHandler {
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return ConfigScript.GlobalPlayerScripts && ScriptController.Instance.playerScripts.enabled && ScriptController.HasStart && (this.player == null || !this.player.worldObj.isRemote);
|
||||
return CustomNpcs.proxy.isGlobalPlayerScripts() && ScriptController.Instance.playerScripts.enabled && ScriptController.HasStart && (this.player == null || !this.player.worldObj.isRemote);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package noppes.npcs.controllers.data;
|
||||
|
||||
import cpw.mods.fml.common.eventhandler.Event;
|
||||
import noppes.npcs.config.ConfigScript;
|
||||
import noppes.npcs.CustomNpcs;
|
||||
import noppes.npcs.controllers.ScriptController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -14,7 +14,7 @@ public abstract class ScriptHandler implements IScriptHandler {
|
||||
protected long lastInited = -1;
|
||||
|
||||
protected boolean canRunScripts() {
|
||||
return enabled && ScriptController.HasStart && ConfigScript.ScriptingEnabled && scripts != null && !scripts.isEmpty();
|
||||
return enabled && ScriptController.HasStart && CustomNpcs.proxy.isScriptingEnabled() && scripts != null && !scripts.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,7 +5,7 @@ import io.netty.buffer.ByteBuf;
|
||||
import kamkeel.npcs.util.ByteBufUtils;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
import noppes.npcs.config.ConfigScript;
|
||||
import noppes.npcs.CustomNpcs;
|
||||
import noppes.npcs.controllers.ScriptController;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -32,7 +32,7 @@ public abstract class SingleScriptHandler extends ScriptHandler {
|
||||
}
|
||||
|
||||
protected boolean canRunScripts() {
|
||||
return enabled && ScriptController.HasStart && ConfigScript.ScriptingEnabled && container != null;
|
||||
return enabled && ScriptController.HasStart && CustomNpcs.proxy.isScriptingEnabled() && container != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -7,7 +7,6 @@ import net.minecraft.nbt.NBTTagCompound;
|
||||
import noppes.npcs.CustomNpcs;
|
||||
import noppes.npcs.NBTTags;
|
||||
import noppes.npcs.api.handler.IHookDefinition;
|
||||
import noppes.npcs.config.ConfigScript;
|
||||
import noppes.npcs.constants.EnumScriptType;
|
||||
import noppes.npcs.constants.ScriptContext;
|
||||
import noppes.npcs.controllers.ScriptController;
|
||||
@@ -154,9 +153,9 @@ public abstract class JaninoScript<T> implements IScriptUnit {
|
||||
|
||||
private String getFullCode() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (ConfigScript.RunLoadedScriptsFirst) appendExternalScripts(sb);
|
||||
if (CustomNpcs.proxy.isRunLoadedScriptsFirst()) appendExternalScripts(sb);
|
||||
if (script != null && !script.isEmpty()) sb.append(script).append("\n");
|
||||
if (!ConfigScript.RunLoadedScriptsFirst) appendExternalScripts(sb);
|
||||
if (!CustomNpcs.proxy.isRunLoadedScriptsFirst()) appendExternalScripts(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ public class CustomNPCsMixinPlugin implements IMixinConfigPlugin {
|
||||
}
|
||||
|
||||
mixins.add("MixinItemStack");
|
||||
mixins.add("MixinItem");
|
||||
}
|
||||
return mixins;
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package noppes.npcs.mixin;
|
||||
|
||||
import cpw.mods.fml.relauncher.Side;
|
||||
import cpw.mods.fml.relauncher.SideOnly;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import noppes.npcs.client.gui.player.AuctionTooltipHandler;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Mixin to inject auction information into item tooltips when viewing auction GUIs.
|
||||
*/
|
||||
@Mixin(Item.class)
|
||||
public abstract class MixinItem {
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
@Inject(method = "addInformation", at = @At("HEAD"))
|
||||
public void onAddInformation(ItemStack stack, EntityPlayer player, List tooltip, boolean advanced, CallbackInfo ci) {
|
||||
AuctionTooltipHandler.addAuctionInfo(stack, tooltip);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user