Skip to content

Commit

Permalink
Entity NBT controls and SNBT support (#2573)
Browse files Browse the repository at this point in the history
  • Loading branch information
tal5 committed Dec 18, 2023
1 parent 156ef7e commit 5ef377f
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ public BiomeNMS getBiomeAt(Block block) {

public abstract CompoundTag createCompoundTag(Map<String, Tag> value);

public CompoundTag parseSNBT(String snbt) {
throw new UnsupportedOperationException();
}

public abstract String getTitle(Inventory inventory);

public void setInventoryTitle(InventoryView view, String title) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -468,4 +468,12 @@ public void stopUsingItem(LivingEntity entity) {
}

public abstract void openHorseInventory(Player player, AbstractHorse horse);

public CompoundTag getRawNBT(Entity entity) {
throw new UnsupportedOperationException();
}

public void modifyRawNBT(Entity entity, CompoundTag tag) {
throw new UnsupportedOperationException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
import com.denizenscript.denizen.nms.interfaces.EntityAnimation;
import com.denizenscript.denizen.nms.interfaces.FakePlayer;
import com.denizenscript.denizen.nms.interfaces.PlayerHelper;
import com.denizenscript.denizen.nms.util.jnbt.CompoundTag;
import com.denizenscript.denizen.npc.traits.MirrorTrait;
import com.denizenscript.denizen.objects.properties.entity.EntityAge;
import com.denizenscript.denizen.objects.properties.entity.EntityColor;
import com.denizenscript.denizen.objects.properties.entity.EntityTame;
import com.denizenscript.denizen.objects.properties.item.ItemRawNBT;
import com.denizenscript.denizen.scripts.commands.player.DisguiseCommand;
import com.denizenscript.denizen.scripts.containers.core.EntityScriptContainer;
import com.denizenscript.denizen.scripts.containers.core.EntityScriptHelper;
Expand Down Expand Up @@ -3068,6 +3070,37 @@ else if (object.getBukkitEntity() instanceof Hanging hanging) {
Vector vector = result.getHitPosition().subtract(result.getHitBlock().getLocation().toVector());
return new ElementTag(bookshelfState.getSlot(vector) + 1);
});

// <--[tag]
// @attribute <EntityTag.all_raw_nbt>
// @returns MapTag
// @mechanism EntityTag.raw_nbt
// @description
// Returns the entity's entire raw NBT data as a MapTag.
// See <@link language Raw NBT Encoding> for more information.
// -->
tagProcessor.registerTag(MapTag.class, "all_raw_nbt", (attribute, object) -> {
CompoundTag tag = NMSHandler.entityHelper.getRawNBT(object.getBukkitEntity());
return (MapTag) ItemRawNBT.jnbtTagToObject(tag);
});

// <--[mechanism]
// @object EntityTag
// @name raw_nbt
// @input MapTag
// @description
// Modifies an entity's raw NBT data based on the input MapTag.
// The input MapTag must be in MapTag NBT format (<@link language Raw NBT Encoding>), and needs to be strictly perfect.
// This doesn't override all the entity's data, only the values specified in the input map are set.
// @tags
// <EntityTag.all_raw_nbt>
// -->
tagProcessor.registerMechanism("raw_nbt", false, MapTag.class, (object, mechanism, input) -> {
CompoundTag tag = (CompoundTag) ItemRawNBT.convertObjectToNbt(input.identify(), mechanism.context, "(entity).");
if (tag != null) {
NMSHandler.entityHelper.modifyRawNBT(object.getBukkitEntity(), tag);
}
});
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
package com.denizenscript.denizen.objects.properties.bukkit;

import com.denizenscript.denizen.nms.NMSHandler;
import com.denizenscript.denizen.nms.NMSVersion;
import com.denizenscript.denizen.nms.util.jnbt.CompoundTag;
import com.denizenscript.denizen.objects.*;
import com.denizenscript.denizen.objects.properties.item.ItemRawNBT;
import com.denizenscript.denizen.scripts.containers.core.FormatScriptContainer;
import com.denizenscript.denizen.scripts.containers.core.ItemScriptHelper;
import com.denizenscript.denizen.tags.core.CustomColorTagBase;
import com.denizenscript.denizen.utilities.BukkitImplDeprecations;
import com.denizenscript.denizen.utilities.FormattedTextHelper;
import com.denizenscript.denizen.utilities.TextWidthHelper;
import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData;
import com.denizenscript.denizencore.objects.ArgumentHelper;
import com.denizenscript.denizencore.objects.core.*;
import com.denizenscript.denizencore.tags.TagManager;
import com.denizenscript.denizencore.utilities.AsciiMatcher;
import com.denizenscript.denizencore.utilities.CoreUtilities;
import com.denizenscript.denizen.utilities.implementation.BukkitScriptEntryData;
import com.denizenscript.denizencore.utilities.Deprecations;
import net.md_5.bungee.chat.ComponentSerializer;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.chat.ComponentSerializer;

import java.nio.charset.StandardCharsets;

Expand Down Expand Up @@ -904,6 +908,29 @@ else if (colorName.startsWith("co@")) {
}
return new ElementTag(res);
});

if (NMSHandler.getVersion().isAtLeast(NMSVersion.v1_20)) {

// <--[tag]
// @attribute <ElementTag.snbt_to_map>
// @returns MapTag
// @description
// Parses a raw SNBT string into an NBT MapTag.
// See <@link language Raw NBT Encoding> for more information on the returned MapTag.
// See <@link url https://minecraft.wiki/w/NBT_format#SNBT_format> for more information on SNBT.
// @example
// Use to set certain SNBT data onto an entity.
// - adjust <[entity]> raw_nbt:<[snbt].snbt_to_map>
// -->
ElementTag.tagProcessor.registerStaticTag(MapTag.class, "snbt_to_map", (attribute, object) -> {
CompoundTag tag = NMSHandler.getInstance().parseSNBT(object.asString());
if (tag == null) {
attribute.echoError("Element '<Y>" + object + "<W>' isn't valid SNBT.");
return null;
}
return (MapTag) ItemRawNBT.jnbtTagToObject(tag);
});
}
}

public enum GradientStyle { RGB, HSB }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.denizenscript.denizen.nms.NMSHandler;
import com.denizenscript.denizen.nms.util.jnbt.*;
import com.denizenscript.denizen.objects.ItemTag;
import com.denizenscript.denizencore.utilities.debugging.Debug;
import com.denizenscript.denizencore.objects.Mechanism;
import com.denizenscript.denizencore.objects.ObjectTag;
import com.denizenscript.denizencore.objects.core.ElementTag;
Expand All @@ -12,10 +11,14 @@
import com.denizenscript.denizencore.objects.properties.Property;
import com.denizenscript.denizencore.tags.Attribute;
import com.denizenscript.denizencore.tags.TagContext;
import com.denizenscript.denizencore.utilities.debugging.Debug;
import com.denizenscript.denizencore.utilities.text.StringHolder;
import org.bukkit.Material;

import java.util.*;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class ItemRawNBT implements Property {

Expand Down Expand Up @@ -125,9 +128,9 @@ public MapTag getFullNBTMap() {
// @name Raw NBT Encoding
// @group Useful Lists
// @description
// The item Raw_NBT property encodes and decodes raw NBT data.
// For the sake of inter-compatibility, a special standard format is used to preserve data types.
// This system exists in Denizen primarily for the sake of compatibility with external plugins.
// Several things in Minecraft use NBT to store data, such as items and entities.
// For the sake of inter-compatibility, a special standard format is used in Denizen to preserve data types.
// This system exists in Denizen primarily for the sake of compatibility with external plugins/systems.
// It should not be used in any scripts that don't rely on data from external plugins.
//
// NBT Tags are encoded as follows:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import com.mojang.authlib.yggdrasil.ProfileResult;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.HoverEvent;
Expand Down Expand Up @@ -159,6 +160,16 @@ public CompoundTag createCompoundTag(Map<String, Tag> value) {
return new CompoundTagImpl(value);
}

@Override
public CompoundTag parseSNBT(String snbt) {
try {
return CompoundTagImpl.fromNMSTag(TagParser.parseTag(snbt));
}
catch (CommandSyntaxException e) {
return null;
}
}

@Override
public Sidebar createSidebar(Player player) {
return new SidebarImpl(player);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.dedicated.DedicatedPlayerList;
import net.minecraft.server.level.*;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerEntity;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.CommonListenerCookie;
import net.minecraft.server.network.ServerPlayerConnection;
import net.minecraft.server.players.PlayerList;
Expand Down Expand Up @@ -863,4 +866,23 @@ public void openHorseInventory(Player player, AbstractHorse horse) {
net.minecraft.world.entity.animal.horse.AbstractHorse nmsHorse = ((CraftAbstractHorse) horse).getHandle();
((CraftPlayer) player).getHandle().openHorseInventory(nmsHorse, nmsHorse.inventory);
}

private net.minecraft.nbt.CompoundTag getRawEntityNBT(net.minecraft.world.entity.Entity entity) {
return entity.saveWithoutId(new net.minecraft.nbt.CompoundTag());
}

@Override
public CompoundTag getRawNBT(Entity entity) {
return CompoundTagImpl.fromNMSTag(getRawEntityNBT(((CraftEntity) entity).getHandle()));
}

@Override
public void modifyRawNBT(Entity entity, CompoundTag tag) {
net.minecraft.world.entity.Entity nmsEntity = ((CraftEntity) entity).getHandle();
net.minecraft.nbt.CompoundTag nmsTag = ((CompoundTagImpl) tag).toNMSTag();
net.minecraft.nbt.CompoundTag nmsMergedTag = getRawEntityNBT(nmsEntity).merge(nmsTag);
UUID uuid = nmsEntity.getUUID();
nmsEntity.load(nmsMergedTag);
nmsEntity.setUUID(uuid);
}
}

0 comments on commit 5ef377f

Please sign in to comment.