mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-12 18:57:32 +00:00
Merge branch 'dev' into syntax-highlighter-unified
This commit is contained in:
commit
5669fe2fda
19 files changed
+529
-16
No files matched your search
@@ -52,6 +52,7 @@ import noppes.npcs.api.ability.IChainedAbility;
|
||||
import noppes.npcs.api.handler.IAbilityHandler;
|
||||
import noppes.npcs.controllers.PlayerDataController;
|
||||
import noppes.npcs.controllers.CategoryManager;
|
||||
import noppes.npcs.controllers.TagController;
|
||||
import noppes.npcs.controllers.data.PlayerData;
|
||||
import noppes.npcs.util.NBTJsonUtil;
|
||||
import kamkeel.npcs.util.FileNameHelper;
|
||||
@@ -369,6 +370,8 @@ public class AbilityController implements IAbilityHandler {
|
||||
}
|
||||
}
|
||||
|
||||
TagController.validateTagUUIDs(ability.getTagUUIDs());
|
||||
|
||||
File dir = getCustomAbilityDir(name);
|
||||
File fileNew = new File(dir, name + ".json_new");
|
||||
File fileCurrent = new File(dir, name + ".json");
|
||||
@@ -526,6 +529,17 @@ public class AbilityController implements IAbilityHandler {
|
||||
return map;
|
||||
}
|
||||
|
||||
public HashMap<String, HashSet<UUID>> getCustomAbilityTagMapForCategory(int catId) {
|
||||
HashMap<String, HashSet<UUID>> tagMap = new HashMap<>();
|
||||
for (Map.Entry<String, Ability> entry : customAbilities.entrySet()) {
|
||||
int assignedCat = customAbilityCatMap.getOrDefault(entry.getKey(), CategoryManager.UNCATEGORIZED_ID);
|
||||
if (assignedCat == catId && !entry.getValue().getTagUUIDs().isEmpty()) {
|
||||
tagMap.put(entry.getKey(), entry.getValue().getTagUUIDs());
|
||||
}
|
||||
}
|
||||
return tagMap;
|
||||
}
|
||||
|
||||
public void moveCustomAbilityToCategory(String name, int destCatId) {
|
||||
Ability ability = customAbilities.get(name);
|
||||
if (ability == null) return;
|
||||
|
||||
@@ -47,6 +47,7 @@ import noppes.npcs.client.gui.builder.FieldDef;
|
||||
import noppes.npcs.client.gui.util.IAbilityConfigCallback;
|
||||
import noppes.npcs.controllers.AnimationController;
|
||||
import noppes.npcs.controllers.ScriptContainer;
|
||||
import noppes.npcs.controllers.TagController;
|
||||
import noppes.npcs.controllers.data.Animation;
|
||||
import noppes.npcs.controllers.data.Frame;
|
||||
import noppes.npcs.controllers.data.AbilityScript;
|
||||
@@ -63,8 +64,10 @@ import noppes.npcs.scripted.event.AbilityEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public abstract class Ability implements IAbility, IAbilityAction {
|
||||
@@ -129,6 +132,9 @@ public abstract class Ability implements IAbility, IAbilityAction {
|
||||
// Custom data for external mods
|
||||
protected NBTTagCompound customData = new NBTTagCompound();
|
||||
|
||||
// Tags
|
||||
protected HashSet<UUID> tagUUIDs = new HashSet<>();
|
||||
|
||||
// Magic data — defines magic types and damage splits for this ability
|
||||
protected MagicData magicData = new MagicData();
|
||||
|
||||
@@ -1526,6 +1532,7 @@ public abstract class Ability implements IAbility, IAbilityAction {
|
||||
nbt.setString("telegraphType", telegraphType.name());
|
||||
nbt.setFloat("telegraphHeightOffset", telegraphHeightOffset);
|
||||
nbt.setTag("customData", (NBTTagCompound) customData.copy());
|
||||
TagController.writeTagUUIDs(nbt, "TagUUIDs", tagUUIDs);
|
||||
magicData.writeToNBT(nbt);
|
||||
nbt.setInteger("allowedBy", allowedBy.ordinal());
|
||||
nbt.setBoolean("ignoreCooldown", ignoreCooldown);
|
||||
@@ -1625,6 +1632,7 @@ public abstract class Ability implements IAbility, IAbilityAction {
|
||||
}
|
||||
telegraphHeightOffset = nbt.getFloat("telegraphHeightOffset");
|
||||
customData = (NBTTagCompound) nbt.getCompoundTag("customData").copy();
|
||||
tagUUIDs = TagController.readTagUUIDs(nbt, "TagUUIDs");
|
||||
magicData.readToNBT(nbt);
|
||||
allowedBy = UserType.fromOrdinal(nbt.getInteger("allowedBy"));
|
||||
ignoreCooldown = nbt.getBoolean("ignoreCooldown");
|
||||
@@ -2330,6 +2338,14 @@ public abstract class Ability implements IAbility, IAbilityAction {
|
||||
return customData;
|
||||
}
|
||||
|
||||
public HashSet<UUID> getTagUUIDs() {
|
||||
return tagUUIDs;
|
||||
}
|
||||
|
||||
public void setTagUUIDs(HashSet<UUID> tagUUIDs) {
|
||||
this.tagUUIDs = tagUUIDs;
|
||||
}
|
||||
|
||||
public MagicData getMagicData() {
|
||||
return magicData;
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import noppes.npcs.controllers.AnimationController;
|
||||
import kamkeel.npcs.controllers.data.ability.enums.UserType;
|
||||
import kamkeel.npcs.controllers.data.ability.gui.AbilityFieldDefs;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import noppes.npcs.controllers.data.Animation;
|
||||
import noppes.npcs.api.ability.type.IAbilityCounter;
|
||||
@@ -65,7 +64,7 @@ public class AbilityCounter extends AbilityDefend implements IAbilityCounter {
|
||||
protected float performDefend(EntityLivingBase attacker, float amount) {
|
||||
// For PERCENT mode with DBC, use the full DBC-calculated damage, not vanilla base
|
||||
float incomingDamage = amount;
|
||||
if (DBCAddon.IsAvailable() && attacker instanceof EntityPlayer) {
|
||||
if (DBCAddon.IsAvailable()) {
|
||||
incomingDamage = DBCAddon.instance.getAttackerDBCDamage(amount);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,9 @@ public final class AbilityTogglePacket extends AbstractPacket {
|
||||
|
||||
int newState = playerData.abilityData.toggleAbility(key);
|
||||
|
||||
// Sync toggle states to client (toggle may have side effects like mutual exclusivity)
|
||||
playerData.abilityData.syncToClient();
|
||||
|
||||
String displayName = ability.getDisplayName();
|
||||
if (newState > 0) {
|
||||
String stateLabel = ability.getToggleStateLabel(newState);
|
||||
|
||||
+18
@@ -18,10 +18,13 @@ import noppes.npcs.constants.EnumScrollData;
|
||||
import noppes.npcs.controllers.AnimationController;
|
||||
import noppes.npcs.controllers.CustomEffectController;
|
||||
import noppes.npcs.controllers.LinkedItemController;
|
||||
import noppes.npcs.controllers.TagController;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class CategoryItemsRequestPacket extends AbstractPacket {
|
||||
public static String packetName = "NPC|CatItems";
|
||||
@@ -67,6 +70,12 @@ public final class CategoryItemsRequestPacket extends AbstractPacket {
|
||||
|
||||
Map<String, Integer> items = getItemsByCat(type, categoryId);
|
||||
ScrollDataPacket.sendScrollData((EntityPlayerMP) player, items, EnumScrollData.CATEGORY_GROUP);
|
||||
|
||||
// Send tag map for the items
|
||||
HashMap<String, HashSet<UUID>> tagMap = getTagMapByCat(type, categoryId);
|
||||
if (tagMap != null && !tagMap.isEmpty()) {
|
||||
TagController.sendCategoryTagMap((EntityPlayerMP) player, tagMap);
|
||||
}
|
||||
}
|
||||
|
||||
private static Map<String, Integer> getItemsByCat(int type, int catId) {
|
||||
@@ -79,4 +88,13 @@ public final class CategoryItemsRequestPacket extends AbstractPacket {
|
||||
}
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
private static HashMap<String, HashSet<UUID>> getTagMapByCat(int type, int catId) {
|
||||
switch (type) {
|
||||
case EnumCategoryType.EFFECT: return CustomEffectController.getInstance().getItemTagMapForCategory(catId);
|
||||
case EnumCategoryType.LINKED_ITEM: return LinkedItemController.getInstance().getItemTagMapForCategory(catId);
|
||||
case EnumCategoryType.ABILITY: return AbilityController.Instance.getCustomAbilityTagMapForCategory(catId);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@ import noppes.npcs.client.gui.util.GuiNpcLabel;
|
||||
import noppes.npcs.client.gui.util.GuiNpcTextField;
|
||||
import noppes.npcs.client.gui.util.GuiScrollWindow;
|
||||
import noppes.npcs.client.gui.util.ITextfieldListener;
|
||||
import noppes.npcs.client.gui.SubGuiTagSelect;
|
||||
import noppes.npcs.client.gui.util.GuiNpcButton;
|
||||
import noppes.npcs.client.gui.util.SubGuiInterface;
|
||||
import noppes.npcs.client.renderer.ImageData;
|
||||
import noppes.npcs.controllers.data.CustomEffect;
|
||||
@@ -63,12 +65,14 @@ public class SubGuiEffectGeneral extends SubGuiInterface implements ITextfieldLi
|
||||
guiTop += 7;
|
||||
int y = guiTop + 7;
|
||||
int x = guiLeft + 4 + 4;
|
||||
addTextField(new GuiNpcTextField(1, this, this.fontRendererObj, x + 36, y, 280, 20, effect.name));
|
||||
addTextField(new GuiNpcTextField(1, this, this.fontRendererObj, x + 36, y, 210, 20, effect.name));
|
||||
getTextField(1).setMaxStringLength(40);
|
||||
addLabel(new GuiNpcLabel(1, "gui.name", x, y + 5));
|
||||
|
||||
addLabel(new GuiNpcLabel(-1, "ID", x + 320, y + 1));
|
||||
addLabel(new GuiNpcLabel(-2, effect.id + "", x + 320, y + 11));
|
||||
addLabel(new GuiNpcLabel(-1, "ID", x + 250, y + 1));
|
||||
addLabel(new GuiNpcLabel(-2, effect.id + "", x + 250, y + 11));
|
||||
|
||||
addButton(new GuiNpcButton(40, getTextField(1).xPosition + getTextField(1).width + 30, y, 70, 20, "gui.tags"));
|
||||
|
||||
y += 23;
|
||||
|
||||
@@ -243,6 +247,10 @@ public class SubGuiEffectGeneral extends SubGuiInterface implements ITextfieldLi
|
||||
PacketClient.sendClient(new EffectSavePacket(effect.writeToNBT(false), originalName));
|
||||
GuiScriptInterface.open(parent, new EffectScript(effect.id));
|
||||
}
|
||||
if (id == 40) {
|
||||
setSubGui(new SubGuiTagSelect(effect.tagUUIDs));
|
||||
return;
|
||||
}
|
||||
if (id == 10) {
|
||||
GuiNpcButtonYesNo button = (GuiNpcButtonYesNo) guibutton;
|
||||
effect.lossOnDeath = button.getBoolean();
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
package noppes.npcs.client.gui;
|
||||
|
||||
import kamkeel.npcs.network.PacketClient;
|
||||
import kamkeel.npcs.network.packets.request.tags.TagsGetPacket;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.util.StatCollector;
|
||||
import noppes.npcs.client.gui.util.GuiCustomScroll;
|
||||
import noppes.npcs.client.gui.util.GuiNpcButton;
|
||||
import noppes.npcs.client.gui.util.GuiNpcLabel;
|
||||
import noppes.npcs.client.gui.util.GuiNpcTextField;
|
||||
import noppes.npcs.client.gui.util.ICustomScrollListener;
|
||||
import noppes.npcs.client.gui.util.IScrollData;
|
||||
import noppes.npcs.client.gui.util.ITextfieldListener;
|
||||
import noppes.npcs.client.gui.util.SubGuiInterface;
|
||||
import noppes.npcs.constants.EnumScrollData;
|
||||
import noppes.npcs.controllers.TagController;
|
||||
import noppes.npcs.controllers.data.Tag;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* Reusable SubGui for selecting tags on any taggable object.
|
||||
* Pass in the current tagUUIDs, get back the modified set on close.
|
||||
*/
|
||||
public class SubGuiTagSelect extends SubGuiInterface implements IScrollData, ICustomScrollListener, ITextfieldListener {
|
||||
private GuiCustomScroll scrollAllTags;
|
||||
private GuiCustomScroll scrollSelectedTags;
|
||||
private final ArrayList<String> allTagNames = new ArrayList<>();
|
||||
private final ArrayList<String> selectedTagNames = new ArrayList<>();
|
||||
private final HashSet<UUID> tagUUIDs;
|
||||
private String search = "";
|
||||
|
||||
public SubGuiTagSelect(HashSet<UUID> tagUUIDs) {
|
||||
this.tagUUIDs = tagUUIDs;
|
||||
setBackground("menubg.png");
|
||||
xSize = 430;
|
||||
ySize = 220;
|
||||
|
||||
// Populate selected tag names from UUIDs
|
||||
TagController tc = TagController.getInstance();
|
||||
if (tc != null) {
|
||||
for (UUID uuid : tagUUIDs) {
|
||||
Tag tag = tc.getTagFromUUID(uuid);
|
||||
if (tag != null) {
|
||||
selectedTagNames.add(tag.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PacketClient.sendClient(new TagsGetPacket());
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
super.initGui();
|
||||
|
||||
addLabel(new GuiNpcLabel(1, StatCollector.translateToLocal("tags.allTags"), guiLeft + 22, guiTop + 11));
|
||||
if (scrollAllTags == null) {
|
||||
scrollAllTags = new GuiCustomScroll(this, 0);
|
||||
scrollAllTags.setSize(150, 155);
|
||||
}
|
||||
scrollAllTags.guiLeft = guiLeft + 20;
|
||||
scrollAllTags.guiTop = guiTop + 24;
|
||||
this.addScroll(scrollAllTags);
|
||||
addTextField(new GuiNpcTextField(4, this, fontRendererObj, guiLeft + 20, guiTop + 24 + 160, 150, 20, search));
|
||||
|
||||
addLabel(new GuiNpcLabel(2, StatCollector.translateToLocal("tags.selectedTags"), guiLeft + 252, guiTop + 11));
|
||||
if (scrollSelectedTags == null) {
|
||||
scrollSelectedTags = new GuiCustomScroll(this, 1);
|
||||
scrollSelectedTags.setSize(150, 180);
|
||||
}
|
||||
scrollSelectedTags.guiLeft = guiLeft + 250;
|
||||
scrollSelectedTags.guiTop = guiTop + 24;
|
||||
scrollSelectedTags.setList(selectedTagNames);
|
||||
this.addScroll(scrollSelectedTags);
|
||||
|
||||
addButton(new GuiNpcButton(10, guiLeft + 185, guiTop + 90, 55, 20, ">"));
|
||||
addButton(new GuiNpcButton(11, guiLeft + 185, guiTop + 112, 55, 20, "<"));
|
||||
addButton(new GuiNpcButton(12, guiLeft + 185, guiTop + 140, 55, 20, ">>"));
|
||||
addButton(new GuiNpcButton(13, guiLeft + 185, guiTop + 162, 55, 20, "<<"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buttonEvent(GuiButton guibutton) {
|
||||
if (guibutton.id == 10 && scrollAllTags.hasSelected() && !selectedTagNames.contains(scrollAllTags.getSelected())) {
|
||||
selectedTagNames.add(scrollAllTags.getSelected());
|
||||
}
|
||||
if (guibutton.id == 12) {
|
||||
selectedTagNames.clear();
|
||||
selectedTagNames.addAll(allTagNames);
|
||||
}
|
||||
if (guibutton.id == 11 && scrollSelectedTags.hasSelected()) {
|
||||
selectedTagNames.remove(scrollSelectedTags.getSelected());
|
||||
}
|
||||
if (guibutton.id == 13) {
|
||||
selectedTagNames.clear();
|
||||
}
|
||||
initGui();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setData(Vector<String> list, HashMap<String, Integer> data, EnumScrollData type) {
|
||||
allTagNames.clear();
|
||||
allTagNames.addAll(data.keySet());
|
||||
allTagNames.sort(String.CASE_INSENSITIVE_ORDER);
|
||||
scrollAllTags.setList(getSearchList());
|
||||
initGui();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
tagUUIDs.clear();
|
||||
TagController tc = TagController.getInstance();
|
||||
if (tc != null) {
|
||||
for (String name : selectedTagNames) {
|
||||
Tag tag = tc.getTagFromName(name);
|
||||
if (tag != null) {
|
||||
tagUUIDs.add(tag.uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void mouseClicked(int i, int j, int k) {
|
||||
super.mouseClicked(i, j, k);
|
||||
if (k == 0 && scrollAllTags != null)
|
||||
scrollAllTags.mouseClicked(i, j, k);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(String selected) {
|
||||
if (scrollAllTags != null)
|
||||
scrollAllTags.setSelected(selected);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customScrollClicked(int i, int j, int k, GuiCustomScroll guiCustomScroll) {
|
||||
}
|
||||
|
||||
public void keyTyped(char c, int i) {
|
||||
super.keyTyped(c, i);
|
||||
if (getTextField(4) != null) {
|
||||
if (search.equals(getTextField(4).getText()))
|
||||
return;
|
||||
search = getTextField(4).getText().toLowerCase();
|
||||
scrollAllTags.setList(getSearchList());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unFocused(GuiNpcTextField guiNpcTextField) {
|
||||
}
|
||||
|
||||
private List<String> getSearchList() {
|
||||
if (search.isEmpty()) {
|
||||
return new ArrayList<>(allTagNames);
|
||||
}
|
||||
List<String> list = new ArrayList<>();
|
||||
for (String name : allTagNames) {
|
||||
if (name.toLowerCase().contains(search))
|
||||
list.add(name);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import noppes.npcs.controllers.data.AbilityScript;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.StatCollector;
|
||||
import noppes.npcs.client.gui.SubGuiTagSelect;
|
||||
import noppes.npcs.client.gui.builder.FieldDef;
|
||||
import noppes.npcs.client.gui.util.GuiMenuTopButton;
|
||||
import noppes.npcs.client.gui.util.GuiNpcButton;
|
||||
@@ -193,6 +194,11 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
}
|
||||
}
|
||||
|
||||
// Tags button on general tab
|
||||
if (activeTab == TAB_GENERAL) {
|
||||
sw.addButton(new GuiNpcButton(40, sw.clipWidth - 95, 5, 80, 20, "gui.tags"));
|
||||
}
|
||||
|
||||
// Conditions on target tab — appended after field defs
|
||||
if (activeTab == TAB_TARGET) {
|
||||
int condY = renderConditions(sw, builder.getLastBuildY(), builder.getNextLabelId());
|
||||
@@ -323,6 +329,10 @@ public class SubGuiAbilityConfig extends SubGuiInterface implements ITextfieldLi
|
||||
GuiScriptInterface.open(parent, new AbilityScript(ability.getId()));
|
||||
return;
|
||||
}
|
||||
if (id == 40) {
|
||||
setSubGui(new SubGuiTagSelect(ability.getTagUUIDs()));
|
||||
return;
|
||||
}
|
||||
if (id == -1000) {
|
||||
close();
|
||||
return;
|
||||
|
||||
@@ -111,6 +111,17 @@ public class AbilityHotbarSlotRenderer extends Gui {
|
||||
drawCircle(radius, fillR, fillG, fillB, alpha * 0.8f, true);
|
||||
}
|
||||
|
||||
// Toggle active indicator: subtle green outline
|
||||
int toggleState = getToggleState();
|
||||
if (toggleState > 0) {
|
||||
float glowAlpha = 0.45f * slotAlpha;
|
||||
if (altTexture) {
|
||||
drawRoundedRect(-radius, -radius, radius, radius, 0.2f, 0.85f, 0.3f, glowAlpha, true);
|
||||
} else {
|
||||
drawCircle(radius, 0.2f, 0.85f, 0.3f, glowAlpha, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Ability icon
|
||||
if (icon != null) {
|
||||
GL11.glPushMatrix();
|
||||
@@ -119,7 +130,7 @@ public class AbilityHotbarSlotRenderer extends Gui {
|
||||
if (iconNaturalSize <= 0) iconNaturalSize = 16f;
|
||||
float iconScale = targetSize / iconNaturalSize;
|
||||
GL11.glScalef(iconScale, iconScale, 1);
|
||||
icon.draw(getToggleState(), slotAlpha);
|
||||
icon.draw(toggleState, slotAlpha);
|
||||
GL11.glColor4f(1, 1, 1, 1);
|
||||
GL11.glPopMatrix();
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import noppes.npcs.client.ClientCacheHandler;
|
||||
import noppes.npcs.client.CustomNpcResourceListener;
|
||||
import noppes.npcs.client.renderer.AnimationHelper;
|
||||
import noppes.npcs.client.gui.SubGuiColorSelector;
|
||||
import noppes.npcs.client.gui.SubGuiTagSelect;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import noppes.npcs.client.gui.script.GuiScriptInterface;
|
||||
import noppes.npcs.client.gui.util.GuiButtonBiDirectional;
|
||||
@@ -159,6 +160,8 @@ public class SubGuiLinkedItem extends SubGuiInterface implements ITextfieldListe
|
||||
}
|
||||
GuiButtonBiDirectional useActionButton = new GuiButtonBiDirectional(6, x + 120, y, 100, 20, useActions, useActionIndex);
|
||||
addButton(useActionButton);
|
||||
|
||||
addButton(new GuiNpcButton(40, x + 230, y, 100, 20, "gui.tags"));
|
||||
y += spacing;
|
||||
|
||||
// Armor Type: BiDirectional button (None, All, Head, Chestplate, Leggings, Boots)
|
||||
@@ -336,6 +339,9 @@ public class SubGuiLinkedItem extends SubGuiInterface implements ITextfieldListe
|
||||
PacketClient.sendClient(new LinkedItemSavePacket(linkedItem.writeToNBT(false), originalName));
|
||||
GuiScriptInterface.open(this.parent, new LinkedItemScript(linkedItem.id));
|
||||
return;
|
||||
} else if (id == 40) {
|
||||
setSubGui(new SubGuiTagSelect(linkedItem.tagUUIDs));
|
||||
return;
|
||||
} else if (id == 20) {
|
||||
// Open confirmation for version bump.
|
||||
GuiYesNo guiyesno = new GuiYesNo(this, "Confirm", "Bump version and update all linked items?", 20);
|
||||
|
||||
@@ -399,6 +399,14 @@ public class GuiAbilities extends GuiCNPCInventory implements ISubGuiListener {
|
||||
boolean isDragSource = isDragging && dragSourceSlot == -1 && draggedKey != null
|
||||
&& draggedKey.equals(filteredKeys.get(absIndex));
|
||||
|
||||
// Compute toggle state early so border can reflect it
|
||||
int cellToggleState = 0;
|
||||
Ability cellAbility = filteredAbilities.get(absIndex);
|
||||
PlayerData cellPlayerData = ClientCacheHandler.playerData;
|
||||
if (cellAbility != null && cellAbility.isToggleable() && cellPlayerData != null && cellPlayerData.abilityData != null) {
|
||||
cellToggleState = cellPlayerData.abilityData.getToggleState(filteredKeys.get(absIndex));
|
||||
}
|
||||
|
||||
// Cell background
|
||||
int bgColor;
|
||||
if (isDragSource) bgColor = 0x40333333;
|
||||
@@ -409,7 +417,8 @@ public class GuiAbilities extends GuiCNPCInventory implements ISubGuiListener {
|
||||
|
||||
// Cell border
|
||||
int borderColor;
|
||||
if (isSelected) borderColor = 0xAA9999DD;
|
||||
if (cellToggleState > 0) borderColor = 0x7733DD55;
|
||||
else if (isSelected) borderColor = 0xAA9999DD;
|
||||
else if (isHovered) borderColor = 0xAA8888CC;
|
||||
else borderColor = 0x40404060;
|
||||
drawHorizontalLine(cellX, cellX + gridCellSize - 2, cellY, borderColor);
|
||||
@@ -430,13 +439,6 @@ public class GuiAbilities extends GuiCNPCInventory implements ISubGuiListener {
|
||||
int iconCenterX = cellX + (gridCellSize - 1) / 2;
|
||||
int iconCenterY = cellY + (gridCellSize - 1) / 2;
|
||||
|
||||
int cellToggleState = 0;
|
||||
Ability cellAbility = filteredAbilities.get(absIndex);
|
||||
PlayerData cellPlayerData = ClientCacheHandler.playerData;
|
||||
if (cellAbility != null && cellAbility.isToggleable() && cellPlayerData != null && cellPlayerData.abilityData != null) {
|
||||
cellToggleState = cellPlayerData.abilityData.getToggleState(filteredKeys.get(absIndex));
|
||||
}
|
||||
|
||||
GL11.glPushMatrix();
|
||||
GL11.glTranslatef(iconCenterX, iconCenterY, 0);
|
||||
GL11.glScalef(iconScale, iconScale, 1);
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
package noppes.npcs.client.gui.util;
|
||||
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.util.StatCollector;
|
||||
import noppes.npcs.controllers.TagController;
|
||||
import noppes.npcs.controllers.data.Tag;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Scroll list that renders CNPC tags next to item names.
|
||||
* Used in directory/fullscreen GUIs for Forms, Auras, Outlines, etc.
|
||||
*/
|
||||
public class GuiCustomScrollTagged extends GuiCustomScroll {
|
||||
private HashMap<String, HashSet<UUID>> itemTagMap = new HashMap<>();
|
||||
private boolean showTags = true;
|
||||
|
||||
public GuiCustomScrollTagged(GuiScreen parent, int id) {
|
||||
super(parent, id);
|
||||
}
|
||||
|
||||
public void setItemTagMap(HashMap<String, HashSet<UUID>> tagMap) {
|
||||
this.itemTagMap = tagMap != null ? tagMap : new HashMap<>();
|
||||
}
|
||||
|
||||
public HashMap<String, HashSet<UUID>> getItemTagMap() {
|
||||
return itemTagMap;
|
||||
}
|
||||
|
||||
public void setShowTags(boolean show) {
|
||||
this.showTags = show;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawItems() {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
int j = 4;
|
||||
int k = (14 * i + 4) - scrollY;
|
||||
if (k >= 4 && k + 12 < ySize) {
|
||||
int xOffset = scrollHeight < ySize - 8 ? 0 : 10;
|
||||
String rawEntry = list.get(i);
|
||||
String displayString = StatCollector.translateToLocal(rawEntry);
|
||||
|
||||
String text = "";
|
||||
float maxWidth = showTags && itemTagMap.containsKey(rawEntry)
|
||||
? (xSize + xOffset - 8) * 0.5f
|
||||
: (xSize + xOffset - 8) * 0.8f;
|
||||
|
||||
if (fontRendererObj.getStringWidth(displayString) > maxWidth) {
|
||||
for (int h = 0; h < displayString.length(); h++) {
|
||||
char c = displayString.charAt(h);
|
||||
text += c;
|
||||
if (fontRendererObj.getStringWidth(text) > maxWidth)
|
||||
break;
|
||||
}
|
||||
if (displayString.length() > text.length())
|
||||
text += "...";
|
||||
} else {
|
||||
text = displayString;
|
||||
}
|
||||
|
||||
Integer customColor = colors.get(rawEntry);
|
||||
if (customColor != null) {
|
||||
if (!text.isEmpty())
|
||||
fontRendererObj.drawString(text, j, k, customColor);
|
||||
} 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);
|
||||
} else if (i == hover) {
|
||||
fontRendererObj.drawString(text, j, k, 0x00ff00);
|
||||
} else {
|
||||
fontRendererObj.drawString(text, j, k, 0xffffff);
|
||||
}
|
||||
|
||||
// Draw tags after item name
|
||||
if (showTags && itemTagMap.containsKey(rawEntry)) {
|
||||
int tagStartX = j + fontRendererObj.getStringWidth(text) + 3;
|
||||
int maxX = j + xSize - 18 + xOffset;
|
||||
HashSet<UUID> tagUUIDs = itemTagMap.get(rawEntry);
|
||||
TagController tc = TagController.getInstance();
|
||||
if (tc != null && tagUUIDs != null) {
|
||||
for (UUID uuid : tagUUIDs) {
|
||||
Tag tag = tc.getTagFromUUID(uuid);
|
||||
if (tag != null && !tag.hideTag) {
|
||||
String tagText = "[" + tag.name + "]";
|
||||
int tagWidth = fontRendererObj.getStringWidth(tagText);
|
||||
if (tagStartX + tagWidth > maxX) break;
|
||||
fontRendererObj.drawString(tagText, tagStartX, k, tag.color);
|
||||
tagStartX += tagWidth + 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
package noppes.npcs.client.gui.util;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import noppes.npcs.controllers.TagController;
|
||||
import noppes.npcs.controllers.data.Category;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
@@ -20,6 +22,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
@@ -32,7 +35,7 @@ public abstract class GuiDirectoryCategorized extends GuiDirectory
|
||||
|
||||
// ========== Scrolls ==========
|
||||
protected GuiCustomScrollIcons catScroll = new GuiCustomScrollIcons(this, 2);
|
||||
protected GuiCustomScroll itemScroll = new GuiCustomScroll(this, 0);
|
||||
protected GuiCustomScrollTagged itemScroll = new GuiCustomScrollTagged(this, 0);
|
||||
|
||||
// ========== Data ==========
|
||||
protected HashMap<String, Integer> catData = new HashMap<>();
|
||||
@@ -463,8 +466,24 @@ public abstract class GuiDirectoryCategorized extends GuiDirectory
|
||||
if (selectedCatId < 0) return new ArrayList<>();
|
||||
if (itemSearch.isEmpty()) return new ArrayList<>(itemData.keySet());
|
||||
List<String> list = new ArrayList<>();
|
||||
HashMap<String, HashSet<UUID>> tagMap = itemScroll.getItemTagMap();
|
||||
for (String name : itemData.keySet()) {
|
||||
if (name.toLowerCase().contains(itemSearch)) list.add(name);
|
||||
if (name.toLowerCase().contains(itemSearch)) {
|
||||
list.add(name);
|
||||
} else if (tagMap != null && tagMap.containsKey(name)) {
|
||||
// Search by tag name — match [tagname] or just tagname
|
||||
HashSet<UUID> uuids = tagMap.get(name);
|
||||
TagController tc = TagController.getInstance();
|
||||
if (tc != null) {
|
||||
for (UUID uuid : uuids) {
|
||||
noppes.npcs.controllers.data.Tag tag = tc.getTagFromUUID(uuid);
|
||||
if (tag != null && tag.name.toLowerCase().contains(itemSearch.replace("[", "").replace("]", ""))) {
|
||||
list.add(name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@@ -693,6 +712,21 @@ public abstract class GuiDirectoryCategorized extends GuiDirectory
|
||||
|
||||
@Override
|
||||
public void setGuiData(NBTTagCompound compound) {
|
||||
if (compound.hasKey("CategoryTagMap")) {
|
||||
// Tag map for category items
|
||||
HashMap<String, HashSet<UUID>> tagMap = new HashMap<>();
|
||||
NBTTagList entries = compound.getTagList("CategoryTagMap", 10);
|
||||
for (int i = 0; i < entries.tagCount(); i++) {
|
||||
NBTTagCompound entry = entries.getCompoundTagAt(i);
|
||||
String itemName = entry.getString("Name");
|
||||
HashSet<UUID> uuids = TagController.readTagUUIDs(entry, "Tags");
|
||||
if (!uuids.isEmpty()) {
|
||||
tagMap.put(itemName, uuids);
|
||||
}
|
||||
}
|
||||
itemScroll.setItemTagMap(tagMap);
|
||||
return;
|
||||
}
|
||||
onItemReceived(compound);
|
||||
if (pendingNewItemCatId > 0 && hasSelectedItem() && getSelectedItemId() >= 0) {
|
||||
sendMovePacket(getSelectedItemId(), pendingNewItemCatId);
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -657,6 +658,18 @@ public class CustomEffectController implements ICustomEffectHandler {
|
||||
return map;
|
||||
}
|
||||
|
||||
public HashMap<String, HashSet<UUID>> getItemTagMapForCategory(int catId) {
|
||||
HashMap<String, HashSet<UUID>> tagMap = new HashMap<>();
|
||||
List<Integer> itemIds = categoryManager.getItemsInCategory(catId, getCustomEffects().keySet());
|
||||
for (int itemId : itemIds) {
|
||||
CustomEffect effect = getCustomEffects().get(itemId);
|
||||
if (effect != null && !effect.tagUUIDs.isEmpty()) {
|
||||
tagMap.put(effect.name, effect.tagUUIDs);
|
||||
}
|
||||
}
|
||||
return tagMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICustomEffect saveEffect(ICustomEffect customEffect) {
|
||||
if (customEffect.getID() < 0) {
|
||||
@@ -668,6 +681,7 @@ public class CustomEffectController implements ICustomEffectHandler {
|
||||
while (hasOther(customEffect.getName(), customEffect.getID()))
|
||||
customEffect.setName(customEffect.getName() + "_");
|
||||
|
||||
TagController.validateTagUUIDs(((CustomEffect) customEffect).tagUUIDs);
|
||||
getCustomEffects().remove(customEffect.getID());
|
||||
getCustomEffects().put(customEffect.getID(), (CustomEffect) customEffect);
|
||||
|
||||
|
||||
@@ -20,8 +20,10 @@ import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
public class LinkedItemController implements ILinkedItemHandler {
|
||||
@@ -215,6 +217,7 @@ public class LinkedItemController implements ILinkedItemHandler {
|
||||
while (hasOther(linkedItem.getName(), linkedItem.getId()))
|
||||
linkedItem.setName(linkedItem.getName() + "_");
|
||||
|
||||
TagController.validateTagUUIDs(((LinkedItem) linkedItem).tagUUIDs);
|
||||
linkedItems.remove(linkedItem.getId());
|
||||
linkedItems.put(linkedItem.getId(), (LinkedItem) linkedItem);
|
||||
saveLinkedItemsMap();
|
||||
@@ -387,4 +390,16 @@ public class LinkedItemController implements ILinkedItemHandler {
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public HashMap<String, HashSet<UUID>> getItemTagMapForCategory(int catId) {
|
||||
HashMap<String, HashSet<UUID>> tagMap = new HashMap<>();
|
||||
List<Integer> itemIds = categoryManager.getItemsInCategory(catId, linkedItems.keySet());
|
||||
for (int itemId : itemIds) {
|
||||
LinkedItem item = linkedItems.get(itemId);
|
||||
if (item != null && !item.tagUUIDs.isEmpty()) {
|
||||
tagMap.put(item.name, item.tagUUIDs);
|
||||
}
|
||||
}
|
||||
return tagMap;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package noppes.npcs.controllers;
|
||||
|
||||
import kamkeel.npcs.network.PacketHandler;
|
||||
import kamkeel.npcs.network.packets.data.large.GuiDataPacket;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.nbt.CompressedStreamTools;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
@@ -9,6 +12,9 @@ import noppes.npcs.api.handler.ITagHandler;
|
||||
import noppes.npcs.api.handler.data.ITag;
|
||||
import noppes.npcs.controllers.data.Tag;
|
||||
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
import net.minecraft.nbt.NBTTagString;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.File;
|
||||
@@ -18,6 +24,7 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
@@ -234,4 +241,69 @@ public class TagController implements ITagHandler {
|
||||
public HashSet<Tag> getAllTags() {
|
||||
return new HashSet<Tag>(this.tags.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a set of tag UUIDs to an NBT compound under the given key.
|
||||
*/
|
||||
public static void writeTagUUIDs(NBTTagCompound compound, String key, HashSet<UUID> tagUUIDs) {
|
||||
if (tagUUIDs != null && !tagUUIDs.isEmpty()) {
|
||||
NBTTagList list = new NBTTagList();
|
||||
for (UUID uuid : tagUUIDs) {
|
||||
list.appendTag(new NBTTagString(uuid.toString()));
|
||||
}
|
||||
compound.setTag(key, list);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a set of tag UUIDs from an NBT compound under the given key.
|
||||
*/
|
||||
public static HashSet<UUID> readTagUUIDs(NBTTagCompound compound, String key) {
|
||||
HashSet<UUID> uuids = new HashSet<>();
|
||||
if (compound.hasKey(key)) {
|
||||
NBTTagList list = compound.getTagList(key, 8);
|
||||
for (int i = 0; i < list.tagCount(); i++) {
|
||||
try {
|
||||
uuids.add(UUID.fromString(list.getStringTagAt(i)));
|
||||
} catch (IllegalArgumentException ignored) {}
|
||||
}
|
||||
}
|
||||
return uuids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove invalid tag UUIDs (those not in the tag registry).
|
||||
*/
|
||||
public static void validateTagUUIDs(HashSet<UUID> tagUUIDs) {
|
||||
TagController tc = getInstance();
|
||||
if (tc == null) return;
|
||||
tagUUIDs.removeIf(uuid -> tc.getTagFromUUID(uuid) == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and send a CategoryTagMap GuiData packet for a set of items.
|
||||
* @param player the target player
|
||||
* @param itemTags map of item name -> tag UUIDs (only validated tags are sent)
|
||||
*/
|
||||
public static void sendCategoryTagMap(EntityPlayerMP player, HashMap<String, HashSet<UUID>> itemTags) {
|
||||
NBTTagCompound compound = new NBTTagCompound();
|
||||
NBTTagList entries = new NBTTagList();
|
||||
TagController tc = getInstance();
|
||||
for (Map.Entry<String, HashSet<UUID>> entry : itemTags.entrySet()) {
|
||||
HashSet<UUID> valid = new HashSet<>();
|
||||
for (UUID uuid : entry.getValue()) {
|
||||
if (tc != null && tc.getTagFromUUID(uuid) != null) {
|
||||
valid.add(uuid);
|
||||
}
|
||||
}
|
||||
if (!valid.isEmpty()) {
|
||||
NBTTagCompound itemEntry = new NBTTagCompound();
|
||||
itemEntry.setString("Name", entry.getKey());
|
||||
writeTagUUIDs(itemEntry, "Tags", valid);
|
||||
entries.appendTag(itemEntry);
|
||||
}
|
||||
}
|
||||
compound.setTag("CategoryTagMap", entries);
|
||||
GuiDataPacket.sendGuiData(player, compound);
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,11 @@ import noppes.npcs.api.entity.IPlayer;
|
||||
import noppes.npcs.api.handler.data.ICustomEffect;
|
||||
import noppes.npcs.constants.EnumScriptType;
|
||||
import noppes.npcs.controllers.CustomEffectController;
|
||||
import noppes.npcs.controllers.TagController;
|
||||
import noppes.npcs.scripted.event.player.PlayerEvent;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class CustomEffect implements ICustomEffect {
|
||||
@@ -36,6 +39,8 @@ public class CustomEffect implements ICustomEffect {
|
||||
|
||||
public int index = 0;
|
||||
|
||||
public HashSet<UUID> tagUUIDs = new HashSet<>();
|
||||
|
||||
public CustomEffect() {
|
||||
}
|
||||
|
||||
@@ -261,6 +266,8 @@ public class CustomEffect implements ICustomEffect {
|
||||
compound.setInteger("iconFrameCount", frameCount);
|
||||
compound.setInteger("iconFrameTime", frametime);
|
||||
|
||||
TagController.writeTagUUIDs(compound, "TagUUIDs", tagUUIDs);
|
||||
|
||||
if (saveScripts) {
|
||||
NBTTagCompound scriptData = new NBTTagCompound();
|
||||
EffectScript handler = getScriptHandler();
|
||||
@@ -309,6 +316,8 @@ public class CustomEffect implements ICustomEffect {
|
||||
if (compound.hasKey("iconFrameTime"))
|
||||
frametime = Math.max(1, compound.getInteger("iconFrameTime"));
|
||||
|
||||
tagUUIDs = TagController.readTagUUIDs(compound, "TagUUIDs");
|
||||
|
||||
if (compound.hasKey("ScriptData", Constants.NBT.TAG_COMPOUND)) {
|
||||
EffectScript handler = new EffectScript();
|
||||
handler.readFromNBT(compound.getCompoundTag("ScriptData"));
|
||||
|
||||
@@ -8,9 +8,13 @@ import noppes.npcs.EventHooks;
|
||||
import noppes.npcs.api.handler.data.ILinkedItem;
|
||||
import noppes.npcs.api.item.IItemStack;
|
||||
import noppes.npcs.controllers.LinkedItemController;
|
||||
import noppes.npcs.controllers.TagController;
|
||||
import noppes.npcs.scripted.NpcAPI;
|
||||
import noppes.npcs.scripted.item.ScriptLinkedItem;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.UUID;
|
||||
|
||||
public class LinkedItem implements ILinkedItem {
|
||||
public static final String LINKED_VERSION_VERSION_TAG = "LinkedVersion";
|
||||
public static final String LINKED_DATA_NBT_TAG = "LinkedData";
|
||||
@@ -33,6 +37,8 @@ public class LinkedItem implements ILinkedItem {
|
||||
public int armorType = -2; //-2: Fits in no armor slot, -1: Fits in all slots, 0 - 3: Fits in Head -> Boots slot respectively
|
||||
public int enchantability;
|
||||
|
||||
public HashSet<UUID> tagUUIDs = new HashSet<>();
|
||||
|
||||
public LinkedItem() {
|
||||
this("New");
|
||||
}
|
||||
@@ -67,6 +73,8 @@ public class LinkedItem implements ILinkedItem {
|
||||
compound.setInteger("MaxItemUseDuration", this.maxItemUseDuration);
|
||||
compound.setInteger("ItemUseAction", this.itemUseAction);
|
||||
|
||||
TagController.writeTagUUIDs(compound, "TagUUIDs", tagUUIDs);
|
||||
|
||||
if (saveScripts) {
|
||||
NBTTagCompound scriptData = new NBTTagCompound();
|
||||
LinkedItemScript handler = getScriptHandler();
|
||||
@@ -97,6 +105,8 @@ public class LinkedItem implements ILinkedItem {
|
||||
this.maxItemUseDuration = compound.getInteger("MaxItemUseDuration");
|
||||
this.itemUseAction = compound.getInteger("ItemUseAction");
|
||||
|
||||
tagUUIDs = TagController.readTagUUIDs(compound, "TagUUIDs");
|
||||
|
||||
if (compound.hasKey("ScriptData", Constants.NBT.TAG_COMPOUND)) {
|
||||
LinkedItemScript handler = new LinkedItemScript();
|
||||
handler.readFromNBT(compound.getCompoundTag("ScriptData"));
|
||||
|
||||
@@ -2208,6 +2208,7 @@ ability.icon.layer=Layer
|
||||
|
||||
gui.both=Both
|
||||
gui.players=Players
|
||||
gui.tags=Tags
|
||||
|
||||
# Conditions
|
||||
condition.edit=Edit Condition
|
||||
|
||||
Reference in new issue
Block a user