commit
						e79cfd7e62
					
				
					 18 changed files with 454 additions and 82 deletions
				
			
		| 
						 | 
					@ -6,4 +6,5 @@ public interface EntityPropertyRegistry {
 | 
				
			||||||
    Collection<EntityProperty<?>> getAll();
 | 
					    Collection<EntityProperty<?>> getAll();
 | 
				
			||||||
    EntityProperty<?> getByName(String name);
 | 
					    EntityProperty<?> getByName(String name);
 | 
				
			||||||
    <T> EntityProperty<T> getByName(String name, Class<T> type);
 | 
					    <T> EntityProperty<T> getByName(String name, Class<T> type);
 | 
				
			||||||
 | 
					    void registerDummy(String name, Class<?> type);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,10 @@
 | 
				
			||||||
 | 
					package lol.pyr.znpcsplus.util;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public enum AttachDirection {
 | 
				
			||||||
 | 
					    DOWN,
 | 
				
			||||||
 | 
					    UP,
 | 
				
			||||||
 | 
					    NORTH,
 | 
				
			||||||
 | 
					    SOUTH,
 | 
				
			||||||
 | 
					    WEST,
 | 
				
			||||||
 | 
					    EAST
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										22
									
								
								api/src/main/java/lol/pyr/znpcsplus/util/RabbitType.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								api/src/main/java/lol/pyr/znpcsplus/util/RabbitType.java
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,22 @@
 | 
				
			||||||
 | 
					package lol.pyr.znpcsplus.util;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public enum RabbitType {
 | 
				
			||||||
 | 
					    BROWN(0),
 | 
				
			||||||
 | 
					    WHITE(1),
 | 
				
			||||||
 | 
					    BLACK(2),
 | 
				
			||||||
 | 
					    BLACK_AND_WHITE(3),
 | 
				
			||||||
 | 
					    GOLD(4),
 | 
				
			||||||
 | 
					    SALT_AND_PEPPER(5),
 | 
				
			||||||
 | 
					    THE_KILLER_BUNNY(99),
 | 
				
			||||||
 | 
					    TOAST(100);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final int id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    RabbitType(int id) {
 | 
				
			||||||
 | 
					        this.id = id;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public int getId() {
 | 
				
			||||||
 | 
					        return id;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								api/src/main/java/lol/pyr/znpcsplus/util/SnifferState.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								api/src/main/java/lol/pyr/znpcsplus/util/SnifferState.java
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					package lol.pyr.znpcsplus.util;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public enum SnifferState {
 | 
				
			||||||
 | 
					    IDLING,
 | 
				
			||||||
 | 
					    FEELING_HAPPY,
 | 
				
			||||||
 | 
					    SCENTING,
 | 
				
			||||||
 | 
					    SNIFFING,
 | 
				
			||||||
 | 
					    SEARCHING,
 | 
				
			||||||
 | 
					    DIGGING,
 | 
				
			||||||
 | 
					    RISING
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,104 @@
 | 
				
			||||||
 | 
					package lol.pyr.znpcsplus.util;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.bukkit.DyeColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.function.IntFunction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class TropicalFishVariant {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private final TropicalFishPattern pattern;
 | 
				
			||||||
 | 
					    private final DyeColor bodyColor;
 | 
				
			||||||
 | 
					    private final DyeColor patternColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public TropicalFishVariant(TropicalFishPattern pattern, DyeColor bodyColor, DyeColor patternColor) {
 | 
				
			||||||
 | 
					        this.pattern = pattern;
 | 
				
			||||||
 | 
					        this.bodyColor = bodyColor;
 | 
				
			||||||
 | 
					        this.patternColor = patternColor;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public int getVariant() {
 | 
				
			||||||
 | 
					        return pattern.getId() & '\uffff' | (bodyColor.ordinal() & 255) << 16 | (patternColor.ordinal() & 255) << 24;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public enum TropicalFishPattern {
 | 
				
			||||||
 | 
					        KOB(0, 0),
 | 
				
			||||||
 | 
					        SUNSTREAK(0, 1),
 | 
				
			||||||
 | 
					        SNOOPER(0, 2),
 | 
				
			||||||
 | 
					        DASHER(0, 3),
 | 
				
			||||||
 | 
					        BRINELY(0, 4),
 | 
				
			||||||
 | 
					        SPOTTY(0, 5),
 | 
				
			||||||
 | 
					        FLOPPER(1, 0),
 | 
				
			||||||
 | 
					        STRIPEY(1, 1),
 | 
				
			||||||
 | 
					        GLITTER(1, 2),
 | 
				
			||||||
 | 
					        BLOCKFISH(1, 3),
 | 
				
			||||||
 | 
					        BETTY(1, 4),
 | 
				
			||||||
 | 
					        CLAYFISH(1, 5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private final int size;
 | 
				
			||||||
 | 
					        private final int id;
 | 
				
			||||||
 | 
					        private static final IntFunction<TropicalFishPattern> BY_ID = (id) -> {
 | 
				
			||||||
 | 
					            for (TropicalFishPattern pattern : values()) {
 | 
				
			||||||
 | 
					                if (pattern.id == id) {
 | 
				
			||||||
 | 
					                    return pattern;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        TropicalFishPattern(int size, int pattern) {
 | 
				
			||||||
 | 
					            this.size = size;
 | 
				
			||||||
 | 
					            this.id = size | pattern << 8;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public int getSize() {
 | 
				
			||||||
 | 
					            return size;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public int getId() {
 | 
				
			||||||
 | 
					            return id;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static TropicalFishPattern fromVariant(int variant) {
 | 
				
			||||||
 | 
					            return BY_ID.apply(variant & '\uffff');
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static class Builder {
 | 
				
			||||||
 | 
					        private TropicalFishPattern pattern;
 | 
				
			||||||
 | 
					        private DyeColor bodyColor;
 | 
				
			||||||
 | 
					        private DyeColor patternColor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Builder() {
 | 
				
			||||||
 | 
					            this.pattern = TropicalFishPattern.KOB;
 | 
				
			||||||
 | 
					            this.bodyColor = DyeColor.WHITE;
 | 
				
			||||||
 | 
					            this.patternColor = DyeColor.WHITE;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Builder pattern(TropicalFishPattern pattern) {
 | 
				
			||||||
 | 
					            this.pattern = pattern;
 | 
				
			||||||
 | 
					            return this;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Builder bodyColor(DyeColor bodyColor) {
 | 
				
			||||||
 | 
					            this.bodyColor = bodyColor;
 | 
				
			||||||
 | 
					            return this;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public Builder patternColor(DyeColor patternColor) {
 | 
				
			||||||
 | 
					            this.patternColor = patternColor;
 | 
				
			||||||
 | 
					            return this;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public static Builder fromInt(int variant) {
 | 
				
			||||||
 | 
					            Builder builder = new Builder();
 | 
				
			||||||
 | 
					            builder.pattern = TropicalFishPattern.fromVariant(variant);
 | 
				
			||||||
 | 
					            builder.bodyColor = DyeColor.values()[(variant >> 16) & 0xFF];
 | 
				
			||||||
 | 
					            builder.patternColor = DyeColor.values()[(variant >> 24) & 0xFF];
 | 
				
			||||||
 | 
					            return builder;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public TropicalFishVariant build() {
 | 
				
			||||||
 | 
					            return new TropicalFishVariant(pattern, bodyColor, patternColor);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -65,10 +65,7 @@ import java.io.PrintWriter;
 | 
				
			||||||
import java.io.Reader;
 | 
					import java.io.Reader;
 | 
				
			||||||
import java.nio.file.Files;
 | 
					import java.nio.file.Files;
 | 
				
			||||||
import java.nio.file.StandardOpenOption;
 | 
					import java.nio.file.StandardOpenOption;
 | 
				
			||||||
import java.util.ArrayList;
 | 
					import java.util.*;
 | 
				
			||||||
import java.util.Collection;
 | 
					 | 
				
			||||||
import java.util.HashMap;
 | 
					 | 
				
			||||||
import java.util.List;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class ZNpcsPlus extends JavaPlugin {
 | 
					public class ZNpcsPlus extends JavaPlugin {
 | 
				
			||||||
    private final LegacyComponentSerializer textSerializer = LegacyComponentSerializer.builder()
 | 
					    private final LegacyComponentSerializer textSerializer = LegacyComponentSerializer.builder()
 | 
				
			||||||
| 
						 | 
					@ -253,6 +250,7 @@ public class ZNpcsPlus extends JavaPlugin {
 | 
				
			||||||
        manager.registerParser(InteractionType.class, new InteractionTypeParser(incorrectUsageMessage));
 | 
					        manager.registerParser(InteractionType.class, new InteractionTypeParser(incorrectUsageMessage));
 | 
				
			||||||
        manager.registerParser(Color.class, new ColorParser(incorrectUsageMessage));
 | 
					        manager.registerParser(Color.class, new ColorParser(incorrectUsageMessage));
 | 
				
			||||||
        manager.registerParser(Vector3f.class, new Vector3fParser(incorrectUsageMessage));
 | 
					        manager.registerParser(Vector3f.class, new Vector3fParser(incorrectUsageMessage));
 | 
				
			||||||
 | 
					        manager.registerParser(String.class, new StringParser(incorrectUsageMessage));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // TODO: Need to find a better way to do this
 | 
					        // TODO: Need to find a better way to do this
 | 
				
			||||||
        registerEnumParser(manager, NpcPose.class, incorrectUsageMessage);
 | 
					        registerEnumParser(manager, NpcPose.class, incorrectUsageMessage);
 | 
				
			||||||
| 
						 | 
					@ -277,6 +275,10 @@ public class ZNpcsPlus extends JavaPlugin {
 | 
				
			||||||
        registerEnumParser(manager, PandaGene.class, incorrectUsageMessage);
 | 
					        registerEnumParser(manager, PandaGene.class, incorrectUsageMessage);
 | 
				
			||||||
        registerEnumParser(manager, PuffState.class, incorrectUsageMessage);
 | 
					        registerEnumParser(manager, PuffState.class, incorrectUsageMessage);
 | 
				
			||||||
        registerEnumParser(manager, LookType.class, incorrectUsageMessage);
 | 
					        registerEnumParser(manager, LookType.class, incorrectUsageMessage);
 | 
				
			||||||
 | 
					        registerEnumParser(manager, TropicalFishVariant.TropicalFishPattern.class, incorrectUsageMessage);
 | 
				
			||||||
 | 
					        registerEnumParser(manager, SnifferState.class, incorrectUsageMessage);
 | 
				
			||||||
 | 
					        registerEnumParser(manager, RabbitType.class, incorrectUsageMessage);
 | 
				
			||||||
 | 
					        registerEnumParser(manager, AttachDirection.class, incorrectUsageMessage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        manager.registerCommand("npc", new MultiCommand(loadHelpMessage("root"))
 | 
					        manager.registerCommand("npc", new MultiCommand(loadHelpMessage("root"))
 | 
				
			||||||
                .addSubcommand("center", new CenterCommand(npcRegistry))
 | 
					                .addSubcommand("center", new CenterCommand(npcRegistry))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,7 +37,7 @@ public class PropertyRemoveCommand implements CommandHandler {
 | 
				
			||||||
    public List<String> suggest(CommandContext context) throws CommandExecutionException {
 | 
					    public List<String> suggest(CommandContext context) throws CommandExecutionException {
 | 
				
			||||||
        if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds());
 | 
					        if (context.argSize() == 1) return context.suggestCollection(npcRegistry.getModifiableIds());
 | 
				
			||||||
        if (context.argSize() == 2) return context.suggestStream(context.suggestionParse(0, NpcEntryImpl.class)
 | 
					        if (context.argSize() == 2) return context.suggestStream(context.suggestionParse(0, NpcEntryImpl.class)
 | 
				
			||||||
                .getNpc().getAppliedProperties().stream().filter(EntityProperty::isPlayerModifiable).map(EntityProperty::getName));
 | 
					                .getNpc().getAllProperties().stream().filter(EntityProperty::isPlayerModifiable).map(EntityProperty::getName));
 | 
				
			||||||
        return Collections.emptyList();
 | 
					        return Collections.emptyList();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,10 +3,12 @@ package lol.pyr.znpcsplus.entity;
 | 
				
			||||||
import com.github.retrooper.packetevents.PacketEvents;
 | 
					import com.github.retrooper.packetevents.PacketEvents;
 | 
				
			||||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
 | 
					import com.github.retrooper.packetevents.manager.server.ServerVersion;
 | 
				
			||||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
 | 
					import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
 | 
				
			||||||
 | 
					import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose;
 | 
				
			||||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
 | 
					import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
 | 
				
			||||||
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
 | 
					import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
 | 
				
			||||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
 | 
					import com.github.retrooper.packetevents.protocol.nbt.NBTString;
 | 
				
			||||||
import com.github.retrooper.packetevents.protocol.player.EquipmentSlot;
 | 
					import com.github.retrooper.packetevents.protocol.player.EquipmentSlot;
 | 
				
			||||||
 | 
					import com.github.retrooper.packetevents.protocol.world.BlockFace;
 | 
				
			||||||
import lol.pyr.znpcsplus.api.entity.EntityProperty;
 | 
					import lol.pyr.znpcsplus.api.entity.EntityProperty;
 | 
				
			||||||
import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry;
 | 
					import lol.pyr.znpcsplus.api.entity.EntityPropertyRegistry;
 | 
				
			||||||
import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
 | 
					import lol.pyr.znpcsplus.api.skin.SkinDescriptor;
 | 
				
			||||||
| 
						 | 
					@ -76,6 +78,10 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
 | 
				
			||||||
        registerEnumSerializer(OcelotType.class);
 | 
					        registerEnumSerializer(OcelotType.class);
 | 
				
			||||||
        registerEnumSerializer(PandaGene.class);
 | 
					        registerEnumSerializer(PandaGene.class);
 | 
				
			||||||
        registerEnumSerializer(PuffState.class);
 | 
					        registerEnumSerializer(PuffState.class);
 | 
				
			||||||
 | 
					        registerEnumSerializer(TropicalFishVariant.TropicalFishPattern.class);
 | 
				
			||||||
 | 
					        registerEnumSerializer(SnifferState.class);
 | 
				
			||||||
 | 
					        registerEnumSerializer(RabbitType.class);
 | 
				
			||||||
 | 
					        registerEnumSerializer(AttachDirection.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        registerPrimitiveSerializers(Integer.class, Boolean.class, Double.class, Float.class, Long.class, Short.class, Byte.class, String.class);
 | 
					        registerPrimitiveSerializers(Integer.class, Boolean.class, Double.class, Float.class, Long.class, Short.class, Byte.class, String.class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -96,38 +102,6 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
 | 
				
			||||||
        // Guardian
 | 
					        // Guardian
 | 
				
			||||||
        registerType("is_elder", false); // TODO: ensure it only works till 1.10. Note: index is wrong on wiki.vg
 | 
					        registerType("is_elder", false); // TODO: ensure it only works till 1.10. Note: index is wrong on wiki.vg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Tropical Fish
 | 
					 | 
				
			||||||
        registerType("tropical_fish_variant", null); // TODO: Maybe make an enum class for this? its just an int on wiki.vg
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Sniffer
 | 
					 | 
				
			||||||
        registerType("sniffer_state", null); // TODO: Nothing on wiki.vg, look in mc source
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Rabbit
 | 
					 | 
				
			||||||
        registerType("rabbit_type", 0); // TODO: Figure this out
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Sheep
 | 
					 | 
				
			||||||
        registerType("sheep_color", DyeColor.WHITE); // TODO: Figure this out
 | 
					 | 
				
			||||||
        registerType("sheep_sheared", false); // TODO
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Strider
 | 
					 | 
				
			||||||
        registerType("strider_shaking", false); // TODO
 | 
					 | 
				
			||||||
        registerType("strider_saddle", false); // TODO
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Wolf
 | 
					 | 
				
			||||||
        registerType("wolf_collar_color", DyeColor.RED); // TODO
 | 
					 | 
				
			||||||
        registerType("wolf_angry", false); // TODO
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Show Golem
 | 
					 | 
				
			||||||
        registerType("pumpkin", true); // TODO
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Shulker
 | 
					 | 
				
			||||||
        registerType("attach_direction", null); // TODO: make a direction enum
 | 
					 | 
				
			||||||
        registerType("shield_height", 0); // TODO: figure this out
 | 
					 | 
				
			||||||
        registerType("shulker_color", DyeColor.RED); // TODO
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Wither
 | 
					 | 
				
			||||||
        registerType("invulnerable_time", 0); // TODO
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -158,14 +132,15 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
 | 
				
			||||||
        linkProperties("glow", "fire", "invisible");
 | 
					        linkProperties("glow", "fire", "invisible");
 | 
				
			||||||
        register(new BooleanProperty("silent", 4, false, legacyBooleans));
 | 
					        register(new BooleanProperty("silent", 4, false, legacyBooleans));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final int tamedIndex;
 | 
					        final int tameableIndex;
 | 
				
			||||||
        if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) tamedIndex = 17;
 | 
					        if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) tameableIndex = 17;
 | 
				
			||||||
        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) tamedIndex = 16;
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) tameableIndex = 16;
 | 
				
			||||||
        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) tamedIndex = 15;
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) tameableIndex = 15;
 | 
				
			||||||
        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) tamedIndex = 13;
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) tameableIndex = 13;
 | 
				
			||||||
        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) tamedIndex = 12;
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) tameableIndex = 12;
 | 
				
			||||||
        else tamedIndex = 16;
 | 
					        else tameableIndex = 16;
 | 
				
			||||||
        register(new BitsetProperty("tamed", tamedIndex, 0x04));
 | 
					        register(new BitsetProperty("sitting", tameableIndex, 0x01));
 | 
				
			||||||
 | 
					        register(new BitsetProperty("tamed", tameableIndex, 0x04));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        int potionIndex;
 | 
					        int potionIndex;
 | 
				
			||||||
        if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) potionIndex = 10;
 | 
					        if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) potionIndex = 10;
 | 
				
			||||||
| 
						 | 
					@ -340,6 +315,82 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
 | 
				
			||||||
        else pigIndex = 16;
 | 
					        else pigIndex = 16;
 | 
				
			||||||
        register(new BooleanProperty("pig_saddled", pigIndex, false, legacyBooleans));
 | 
					        register(new BooleanProperty("pig_saddled", pigIndex, false, legacyBooleans));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Rabbit
 | 
				
			||||||
 | 
					        int rabbitIndex;
 | 
				
			||||||
 | 
					        if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) rabbitIndex = 17;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) rabbitIndex = 16;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) rabbitIndex = 15;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) rabbitIndex = 13;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) rabbitIndex = 12;
 | 
				
			||||||
 | 
					        else rabbitIndex = 18;
 | 
				
			||||||
 | 
					        register(new RabbitTypeProperty(rabbitIndex, legacyBooleans, legacyNames, optionalComponents));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Sheep
 | 
				
			||||||
 | 
					        int sheepIndex;
 | 
				
			||||||
 | 
					        if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) sheepIndex = 17;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) sheepIndex = 16;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) sheepIndex = 15;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) sheepIndex = 13;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) sheepIndex = 12;
 | 
				
			||||||
 | 
					        else sheepIndex = 16;
 | 
				
			||||||
 | 
					        // noinspection deprecation
 | 
				
			||||||
 | 
					        register(new EncodedByteProperty<>("sheep_color", DyeColor.WHITE, sheepIndex, DyeColor::getWoolData));
 | 
				
			||||||
 | 
					        register(new BitsetProperty("sheep_sheared", sheepIndex, 0x10, false, legacyBooleans)); // no need to link because sheep_sheared is only visible when sheep_color is WHITE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Wolf
 | 
				
			||||||
 | 
					        int wolfIndex;
 | 
				
			||||||
 | 
					        if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) wolfIndex = 19;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) wolfIndex = 18;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) wolfIndex = 16;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) wolfIndex = 15;
 | 
				
			||||||
 | 
					        else wolfIndex = 19;
 | 
				
			||||||
 | 
					        register(new BooleanProperty("wolf_begging", wolfIndex++, false, legacyBooleans));
 | 
				
			||||||
 | 
					        if (legacyBooleans) {
 | 
				
			||||||
 | 
					            // noinspection deprecation
 | 
				
			||||||
 | 
					            register(new EncodedByteProperty<>("wolf_collar", DyeColor.BLUE, wolfIndex++, DyeColor::getDyeData));
 | 
				
			||||||
 | 
					        } else register(new EncodedIntegerProperty<>("wolf_collar", DyeColor.RED, wolfIndex++, Enum::ordinal));
 | 
				
			||||||
 | 
					        if (ver.isNewerThanOrEquals(ServerVersion.V_1_16)) {
 | 
				
			||||||
 | 
					            register(new EncodedIntegerProperty<>("wolf_angry", false, wolfIndex, b -> b ? 1 : 0));
 | 
				
			||||||
 | 
					            linkProperties("tamed", "sitting");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            register(new BitsetProperty("wolf_angry", tameableIndex, 0x02));
 | 
				
			||||||
 | 
					            linkProperties("wolf_angry", "tamed", "sitting");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Wither
 | 
				
			||||||
 | 
					        int witherIndex;
 | 
				
			||||||
 | 
					        if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) witherIndex = 16; // using the first index, so we can add the other properties later if needed
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) witherIndex = 15;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) witherIndex = 14;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) witherIndex = 12;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) witherIndex = 11;
 | 
				
			||||||
 | 
					        else witherIndex = 17;
 | 
				
			||||||
 | 
					        witherIndex += 3; // skip the first 3 indexes, will be used for the other properties later
 | 
				
			||||||
 | 
					        register(new IntegerProperty("invulnerable_time", witherIndex++, 0, false));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!ver.isNewerThanOrEquals(ServerVersion.V_1_9)) return;
 | 
				
			||||||
 | 
					        // Shulker
 | 
				
			||||||
 | 
					        int shulkerIndex;
 | 
				
			||||||
 | 
					        if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) shulkerIndex = 16;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) shulkerIndex = 15;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) shulkerIndex = 14;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) shulkerIndex = 12;
 | 
				
			||||||
 | 
					        else shulkerIndex = 11;
 | 
				
			||||||
 | 
					        register(new CustomTypeProperty<>("attach_direction", shulkerIndex++, AttachDirection.DOWN, EntityDataTypes.BLOCK_FACE, attachDir -> BlockFace.valueOf(attachDir.name())));
 | 
				
			||||||
 | 
					        register(new EncodedByteProperty<>("shield_height", 0, shulkerIndex++, value -> (byte) Math.max(0, Math.min(100, value))));
 | 
				
			||||||
 | 
					        // noinspection deprecation
 | 
				
			||||||
 | 
					        register(new EncodedByteProperty<>("shulker_color", DyeColor.class, shulkerIndex, DyeColor::getWoolData));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Snow Golem
 | 
				
			||||||
 | 
					        int snowGolemIndex;
 | 
				
			||||||
 | 
					        if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) snowGolemIndex = 16;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) snowGolemIndex = 15;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) snowGolemIndex = 14;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) snowGolemIndex = 12;
 | 
				
			||||||
 | 
					        else snowGolemIndex = 10;
 | 
				
			||||||
 | 
					        register(new CustomTypeProperty<>("derpy_snowgolem", snowGolemIndex, false, EntityDataTypes.BYTE, b -> (byte) (b ? 0x00 : 0x10)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!ver.isNewerThanOrEquals(ServerVersion.V_1_10)) return;
 | 
					        if (!ver.isNewerThanOrEquals(ServerVersion.V_1_10)) return;
 | 
				
			||||||
        // Polar Bear
 | 
					        // Polar Bear
 | 
				
			||||||
        int polarBearIndex;
 | 
					        int polarBearIndex;
 | 
				
			||||||
| 
						 | 
					@ -398,9 +449,20 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
 | 
				
			||||||
        else pufferfishIndex = 13;
 | 
					        else pufferfishIndex = 13;
 | 
				
			||||||
        register(new EncodedIntegerProperty<>("puff_state", PuffState.DEFLATED, pufferfishIndex, Enum::ordinal));
 | 
					        register(new EncodedIntegerProperty<>("puff_state", PuffState.DEFLATED, pufferfishIndex, Enum::ordinal));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Tropical Fish
 | 
				
			||||||
 | 
					        int tropicalFishIndex;
 | 
				
			||||||
 | 
					        if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) tropicalFishIndex = 17;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) tropicalFishIndex = 16;
 | 
				
			||||||
 | 
					        else if (ver.isNewerThanOrEquals(ServerVersion.V_1_14)) tropicalFishIndex = 15;
 | 
				
			||||||
 | 
					        else tropicalFishIndex = 13;
 | 
				
			||||||
 | 
					        register(new TropicalFishVariantProperty<>("tropical_fish_pattern", TropicalFishVariant.TropicalFishPattern.KOB, tropicalFishIndex, TropicalFishVariant.Builder::pattern));
 | 
				
			||||||
 | 
					        register(new TropicalFishVariantProperty<>("tropical_fish_body_color", DyeColor.WHITE, tropicalFishIndex, TropicalFishVariant.Builder::bodyColor));
 | 
				
			||||||
 | 
					        register(new TropicalFishVariantProperty<>("tropical_fish_pattern_color", DyeColor.WHITE, tropicalFishIndex, TropicalFishVariant.Builder::patternColor));
 | 
				
			||||||
 | 
					        linkProperties("tropical_fish_pattern", "tropical_fish_body_color", "tropical_fish_pattern_color");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!ver.isNewerThanOrEquals(ServerVersion.V_1_14)) return;
 | 
					        if (!ver.isNewerThanOrEquals(ServerVersion.V_1_14)) return;
 | 
				
			||||||
        // Pose
 | 
					        // Pose
 | 
				
			||||||
        register(new NpcPoseProperty());
 | 
					        register(new CustomTypeProperty<>("pose", 6, NpcPose.STANDING, EntityDataTypes.ENTITY_POSE, npcPose -> EntityPose.valueOf(npcPose.name())));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Villager
 | 
					        // Villager
 | 
				
			||||||
        final int villagerIndex;
 | 
					        final int villagerIndex;
 | 
				
			||||||
| 
						 | 
					@ -478,7 +540,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Hoglin and Piglin Zombification
 | 
					        // Hoglin and Piglin Zombification
 | 
				
			||||||
        final int zombificationIndex;
 | 
					        final int zombificationIndex;
 | 
				
			||||||
        if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) zombificationIndex = 17; // Change piglinIndex and pillagerIndex if you change this
 | 
					        if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) zombificationIndex = 17; // Change piglinIndex, pillagerIndex, striderIndex and vindicatorIndex if you change this
 | 
				
			||||||
        else zombificationIndex = 16;
 | 
					        else zombificationIndex = 16;
 | 
				
			||||||
        register(new BooleanProperty("hoglin_immune_to_zombification", zombificationIndex, false, legacyBooleans));
 | 
					        register(new BooleanProperty("hoglin_immune_to_zombification", zombificationIndex, false, legacyBooleans));
 | 
				
			||||||
        register(new BooleanProperty("piglin_immune_to_zombification", zombificationIndex-1, false, legacyBooleans));
 | 
					        register(new BooleanProperty("piglin_immune_to_zombification", zombificationIndex-1, false, legacyBooleans));
 | 
				
			||||||
| 
						 | 
					@ -492,6 +554,11 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
 | 
				
			||||||
        // Pillager
 | 
					        // Pillager
 | 
				
			||||||
        register(new BooleanProperty("pillager_charging", zombificationIndex, false, legacyBooleans));
 | 
					        register(new BooleanProperty("pillager_charging", zombificationIndex, false, legacyBooleans));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Strider
 | 
				
			||||||
 | 
					        int striderIndex = zombificationIndex + 1;
 | 
				
			||||||
 | 
					        register(new BooleanProperty("strider_shaking", striderIndex++, false, legacyBooleans)); // TODO: Fix this, it needs to be set constantly i guess
 | 
				
			||||||
 | 
					        register(new BooleanProperty("strider_saddled", striderIndex, false, legacyBooleans));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Vindicator
 | 
					        // Vindicator
 | 
				
			||||||
        int vindicatorIndex = zombificationIndex -1;
 | 
					        int vindicatorIndex = zombificationIndex -1;
 | 
				
			||||||
        register(new BooleanProperty("celebrating", vindicatorIndex, false, legacyBooleans));
 | 
					        register(new BooleanProperty("celebrating", vindicatorIndex, false, legacyBooleans));
 | 
				
			||||||
| 
						 | 
					@ -514,6 +581,9 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Camel
 | 
					        // Camel
 | 
				
			||||||
        register(new BooleanProperty("bashing", 18, false, legacyBooleans));
 | 
					        register(new BooleanProperty("bashing", 18, false, legacyBooleans));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Sniffer
 | 
				
			||||||
 | 
					        register(new CustomTypeProperty<>("sniffer_state", 17, SnifferState.IDLING, EntityDataTypes.SNIFFER_STATE, state -> com.github.retrooper.packetevents.protocol.entity.sniffer.SnifferState.valueOf(state.name())));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private void registerSerializer(PropertySerializer<?> serializer) {
 | 
					    private void registerSerializer(PropertySerializer<?> serializer) {
 | 
				
			||||||
| 
						 | 
					@ -569,6 +639,11 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
 | 
				
			||||||
        return (EntityPropertyImpl<T>) getByName(name);
 | 
					        return (EntityPropertyImpl<T>) getByName(name);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void registerDummy(String name, Class<?> type) {
 | 
				
			||||||
 | 
					        register(new DummyProperty<>(name, type));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public EntityPropertyImpl<?> getByName(String name) {
 | 
					    public EntityPropertyImpl<?> getByName(String name) {
 | 
				
			||||||
        return byName.get(name.toLowerCase());
 | 
					        return byName.get(name.toLowerCase());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,32 @@
 | 
				
			||||||
 | 
					package lol.pyr.znpcsplus.entity.properties;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
 | 
				
			||||||
 | 
					import com.github.retrooper.packetevents.protocol.entity.data.EntityDataType;
 | 
				
			||||||
 | 
					import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
 | 
				
			||||||
 | 
					import lol.pyr.znpcsplus.entity.PacketEntity;
 | 
				
			||||||
 | 
					import org.bukkit.entity.Player;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class CustomTypeProperty<T, U> extends EntityPropertyImpl<T> {
 | 
				
			||||||
 | 
					    private final int index;
 | 
				
			||||||
 | 
					    private final EntityDataType<U> type;
 | 
				
			||||||
 | 
					    private final TypeDecoder<T, U> decoder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @SuppressWarnings("unchecked")
 | 
				
			||||||
 | 
					    public CustomTypeProperty(String name, int index, T def, EntityDataType<U> type, TypeDecoder<T, U> decoder) {
 | 
				
			||||||
 | 
					        super(name, def, (Class<T>) def.getClass());
 | 
				
			||||||
 | 
					        this.index = index;
 | 
				
			||||||
 | 
					        this.type = type;
 | 
				
			||||||
 | 
					        this.decoder = decoder;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void apply(Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) {
 | 
				
			||||||
 | 
					        properties.put(index, newEntityData(index, type, decoder.decode(entity.getProperty(this))));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public interface TypeDecoder<T, U> {
 | 
				
			||||||
 | 
					        U decode(T obj);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,23 +0,0 @@
 | 
				
			||||||
package lol.pyr.znpcsplus.entity.properties;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
 | 
					 | 
				
			||||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
 | 
					 | 
				
			||||||
import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose;
 | 
					 | 
				
			||||||
import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
 | 
					 | 
				
			||||||
import lol.pyr.znpcsplus.entity.PacketEntity;
 | 
					 | 
				
			||||||
import lol.pyr.znpcsplus.util.NpcPose;
 | 
					 | 
				
			||||||
import org.bukkit.entity.Player;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.util.Map;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
public class NpcPoseProperty extends EntityPropertyImpl<NpcPose> {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public NpcPoseProperty() {
 | 
					 | 
				
			||||||
        super("pose", NpcPose.STANDING, NpcPose.class);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @Override
 | 
					 | 
				
			||||||
    public void apply(Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) {
 | 
					 | 
				
			||||||
        properties.put(6, newEntityData(6, EntityDataTypes.ENTITY_POSE, EntityPose.valueOf(entity.getProperty(this).name())));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,47 @@
 | 
				
			||||||
 | 
					package lol.pyr.znpcsplus.entity.properties;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
 | 
				
			||||||
 | 
					import com.github.retrooper.packetevents.protocol.entity.data.EntityDataType;
 | 
				
			||||||
 | 
					import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
 | 
				
			||||||
 | 
					import com.github.retrooper.packetevents.util.adventure.AdventureSerializer;
 | 
				
			||||||
 | 
					import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
 | 
				
			||||||
 | 
					import lol.pyr.znpcsplus.entity.PacketEntity;
 | 
				
			||||||
 | 
					import lol.pyr.znpcsplus.util.RabbitType;
 | 
				
			||||||
 | 
					import net.kyori.adventure.text.Component;
 | 
				
			||||||
 | 
					import org.bukkit.entity.Player;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					import java.util.Optional;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class RabbitTypeProperty extends EntityPropertyImpl<RabbitType> {
 | 
				
			||||||
 | 
					    private final int index;
 | 
				
			||||||
 | 
					    private final boolean legacyBooleans;
 | 
				
			||||||
 | 
					    private final Object serialized;
 | 
				
			||||||
 | 
					    private final EntityDataType<?> type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public RabbitTypeProperty(int index, boolean legacyBooleans, boolean legacyNames, boolean optional) {
 | 
				
			||||||
 | 
					        super("rabbit_type", RabbitType.BROWN, RabbitType.class);
 | 
				
			||||||
 | 
					        this.index = index;
 | 
				
			||||||
 | 
					        this.legacyBooleans = legacyBooleans;
 | 
				
			||||||
 | 
					        Component name = Component.text("Toast");
 | 
				
			||||||
 | 
					        String serialized = legacyNames ?
 | 
				
			||||||
 | 
					                AdventureSerializer.getLegacyGsonSerializer().serialize(name) :
 | 
				
			||||||
 | 
					                AdventureSerializer.getGsonSerializer().serialize(name);
 | 
				
			||||||
 | 
					        this.serialized = optional ? Optional.of(serialized) : serialized;
 | 
				
			||||||
 | 
					        this.type = optional ? EntityDataTypes.OPTIONAL_COMPONENT : EntityDataTypes.STRING;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void apply(Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) {
 | 
				
			||||||
 | 
					        RabbitType rabbitType = entity.getProperty(this);
 | 
				
			||||||
 | 
					        if (rabbitType == null) return;
 | 
				
			||||||
 | 
					        if (!rabbitType.equals(RabbitType.TOAST)) {
 | 
				
			||||||
 | 
					            properties.put(index, legacyBooleans ?
 | 
				
			||||||
 | 
					                    newEntityData(index, EntityDataTypes.BYTE, (byte) rabbitType.getId()) :
 | 
				
			||||||
 | 
					                    newEntityData(index, EntityDataTypes.INT, rabbitType.getId()));
 | 
				
			||||||
 | 
					            properties.put(2, new EntityData(2, type, null));
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            properties.put(2, new EntityData(2, type, serialized));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,49 @@
 | 
				
			||||||
 | 
					package lol.pyr.znpcsplus.entity.properties;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
 | 
				
			||||||
 | 
					import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
 | 
				
			||||||
 | 
					import lol.pyr.znpcsplus.entity.EntityPropertyImpl;
 | 
				
			||||||
 | 
					import lol.pyr.znpcsplus.entity.PacketEntity;
 | 
				
			||||||
 | 
					import lol.pyr.znpcsplus.util.TropicalFishVariant;
 | 
				
			||||||
 | 
					import org.bukkit.entity.Player;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class TropicalFishVariantProperty<T> extends EntityPropertyImpl<T> {
 | 
				
			||||||
 | 
					    private final int index;
 | 
				
			||||||
 | 
					    private final BuilderDecoder<T> decoder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public TropicalFishVariantProperty(String name, T defaultValue, Class<T> type, int index, BuilderDecoder<T> decoder) {
 | 
				
			||||||
 | 
					        super(name, defaultValue, type);
 | 
				
			||||||
 | 
					        this.index = index;
 | 
				
			||||||
 | 
					        this.decoder = decoder;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @SuppressWarnings("unchecked")
 | 
				
			||||||
 | 
					    public TropicalFishVariantProperty(String name, T defaultValue, int index, BuilderDecoder<T> decoder) {
 | 
				
			||||||
 | 
					        this(name, defaultValue, (Class<T>) defaultValue.getClass(), index, decoder);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void apply(Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) {
 | 
				
			||||||
 | 
					        T value = entity.getProperty(this);
 | 
				
			||||||
 | 
					        if (value == null) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        EntityData oldData = properties.get(index);
 | 
				
			||||||
 | 
					        TropicalFishVariant.Builder builder;
 | 
				
			||||||
 | 
					        if (oldData != null && oldData.getType() == EntityDataTypes.INT && oldData.getValue() != null) {
 | 
				
			||||||
 | 
					            int oldVal = (int) oldData.getValue();
 | 
				
			||||||
 | 
					            builder = TropicalFishVariant.Builder.fromInt(oldVal);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            builder = new TropicalFishVariant.Builder();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        builder = decoder.decode(builder, value);
 | 
				
			||||||
 | 
					        int variant = builder.build().getVariant();
 | 
				
			||||||
 | 
					        properties.put(index, newEntityData(index, EntityDataTypes.INT, variant));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public interface BuilderDecoder<T> {
 | 
				
			||||||
 | 
					        TropicalFishVariant.Builder decode(TropicalFishVariant.Builder builder, T obj);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,7 @@ import org.bukkit.World;
 | 
				
			||||||
import org.bukkit.entity.Player;
 | 
					import org.bukkit.entity.Player;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.*;
 | 
					import java.util.*;
 | 
				
			||||||
 | 
					import java.util.stream.Collectors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class NpcImpl extends Viewable implements Npc {
 | 
					public class NpcImpl extends Viewable implements Npc {
 | 
				
			||||||
    private final PacketFactory packetFactory;
 | 
					    private final PacketFactory packetFactory;
 | 
				
			||||||
| 
						 | 
					@ -163,9 +164,13 @@ public class NpcImpl extends Viewable implements Npc {
 | 
				
			||||||
        setProperty((EntityPropertyImpl<T>) property, (T) value);
 | 
					        setProperty((EntityPropertyImpl<T>) property, (T) value);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public Set<EntityProperty<?>> getAllProperties() {
 | 
				
			||||||
 | 
					        return Collections.unmodifiableSet(propertyMap.keySet());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Override
 | 
					    @Override
 | 
				
			||||||
    public Set<EntityProperty<?>> getAppliedProperties() {
 | 
					    public Set<EntityProperty<?>> getAppliedProperties() {
 | 
				
			||||||
        return Collections.unmodifiableSet(propertyMap.keySet());
 | 
					        return Collections.unmodifiableSet(propertyMap.keySet()).stream().filter(type::isAllowedProperty).collect(Collectors.toSet());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public List<InteractionActionImpl> getActions() {
 | 
					    public List<InteractionActionImpl> getActions() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,6 +50,10 @@ public class NpcTypeImpl implements NpcType {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public boolean isAllowedProperty(EntityPropertyImpl<?> entityProperty) {
 | 
				
			||||||
 | 
					        return !entityProperty.isPlayerModifiable() || allowedProperties.contains(entityProperty);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected static final class Builder {
 | 
					    protected static final class Builder {
 | 
				
			||||||
        private final static Logger logger = Logger.getLogger("NpcTypeBuilder");
 | 
					        private final static Logger logger = Logger.getLogger("NpcTypeBuilder");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -154,6 +158,9 @@ public class NpcTypeImpl implements NpcType {
 | 
				
			||||||
                    addProperties("panda_eating");
 | 
					                    addProperties("panda_eating");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            if (EntityTypes.isTypeInstanceOf(type, EntityTypes.ABSTRACT_TAMEABLE_ANIMAL)) {
 | 
				
			||||||
 | 
					                addProperties("tamed", "sitting");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            return new NpcTypeImpl(name, type, hologramOffset, new HashSet<>(allowedProperties), defaultProperties);
 | 
					            return new NpcTypeImpl(name, type, hologramOffset, new HashSet<>(allowedProperties), defaultProperties);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -115,10 +115,12 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
 | 
				
			||||||
                .addProperties("pig_saddled"));
 | 
					                .addProperties("pig_saddled"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        register(builder(p, "rabbit", EntityTypes.RABBIT)
 | 
					        register(builder(p, "rabbit", EntityTypes.RABBIT)
 | 
				
			||||||
                .setHologramOffset(-1.475));
 | 
					                .setHologramOffset(-1.475)
 | 
				
			||||||
 | 
					                .addProperties("rabbit_type"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        register(builder(p, "sheep", EntityTypes.SHEEP)
 | 
					        register(builder(p, "sheep", EntityTypes.SHEEP)
 | 
				
			||||||
                .setHologramOffset(-0.675));
 | 
					                .setHologramOffset(-0.675)
 | 
				
			||||||
 | 
					                .addProperties("sheep_color", "sheep_sheared"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        register(builder(p, "silverfish", EntityTypes.SILVERFISH)
 | 
					        register(builder(p, "silverfish", EntityTypes.SILVERFISH)
 | 
				
			||||||
                .setHologramOffset(-1.675));
 | 
					                .setHologramOffset(-1.675));
 | 
				
			||||||
| 
						 | 
					@ -133,7 +135,8 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
 | 
				
			||||||
        register(builder(p, "slime", EntityTypes.SLIME)); // TODO: Hologram offset scaling with size property
 | 
					        register(builder(p, "slime", EntityTypes.SLIME)); // TODO: Hologram offset scaling with size property
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        register(builder(p, "snow_golem", EntityTypes.SNOW_GOLEM)
 | 
					        register(builder(p, "snow_golem", EntityTypes.SNOW_GOLEM)
 | 
				
			||||||
                .setHologramOffset(-0.075));
 | 
					                .setHologramOffset(-0.075)
 | 
				
			||||||
 | 
					                .addProperties("derpy_snowgolem"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        register(builder(p, "spider", EntityTypes.SPIDER)
 | 
					        register(builder(p, "spider", EntityTypes.SPIDER)
 | 
				
			||||||
                .setHologramOffset(-1.075));
 | 
					                .setHologramOffset(-1.075));
 | 
				
			||||||
| 
						 | 
					@ -150,11 +153,12 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
 | 
				
			||||||
                .addProperties("hand"));
 | 
					                .addProperties("hand"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        register(builder(p, "wither", EntityTypes.WITHER)
 | 
					        register(builder(p, "wither", EntityTypes.WITHER)
 | 
				
			||||||
                .setHologramOffset(1.525));
 | 
					                .setHologramOffset(1.525)
 | 
				
			||||||
 | 
					                .addProperties("invulnerable_time"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        register(builder(p, "wolf", EntityTypes.WOLF)
 | 
					        register(builder(p, "wolf", EntityTypes.WOLF)
 | 
				
			||||||
                .setHologramOffset(-1.125)
 | 
					                .setHologramOffset(-1.125)
 | 
				
			||||||
                .addProperties("tamed"));
 | 
					                .addProperties("wolf_begging", "wolf_collar", "wolf_angry"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        register(builder(p, "zombie", EntityTypes.ZOMBIE)
 | 
					        register(builder(p, "zombie", EntityTypes.ZOMBIE)
 | 
				
			||||||
                .setHologramOffset(-0.025)
 | 
					                .setHologramOffset(-0.025)
 | 
				
			||||||
| 
						 | 
					@ -170,7 +174,8 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
 | 
				
			||||||
        if (!version.isNewerThanOrEquals(ServerVersion.V_1_9)) return;
 | 
					        if (!version.isNewerThanOrEquals(ServerVersion.V_1_9)) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        register(builder(p, "shulker", EntityTypes.SHULKER)
 | 
					        register(builder(p, "shulker", EntityTypes.SHULKER)
 | 
				
			||||||
                .setHologramOffset(-0.975));
 | 
					                .setHologramOffset(-0.975)
 | 
				
			||||||
 | 
					                .addProperties("attach_direction", "shield_height", "shulker_color"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!version.isNewerThanOrEquals(ServerVersion.V_1_10)) return;
 | 
					        if (!version.isNewerThanOrEquals(ServerVersion.V_1_10)) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -257,7 +262,8 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
 | 
				
			||||||
                .setHologramOffset(-1.575));
 | 
					                .setHologramOffset(-1.575));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        register(builder(p, "tropical_fish", EntityTypes.TROPICAL_FISH)
 | 
					        register(builder(p, "tropical_fish", EntityTypes.TROPICAL_FISH)
 | 
				
			||||||
                .setHologramOffset(-1.575));
 | 
					                .setHologramOffset(-1.575)
 | 
				
			||||||
 | 
					                .addProperties("tropical_fish_pattern", "tropical_fish_body_color", "tropical_fish_pattern_color"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        register(builder(p, "turtle", EntityTypes.TURTLE)
 | 
					        register(builder(p, "turtle", EntityTypes.TURTLE)
 | 
				
			||||||
                .setHologramOffset(-1.575));
 | 
					                .setHologramOffset(-1.575));
 | 
				
			||||||
| 
						 | 
					@ -266,7 +272,7 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        register(builder(p, "cat", EntityTypes.CAT)
 | 
					        register(builder(p, "cat", EntityTypes.CAT)
 | 
				
			||||||
                .setHologramOffset(-1.275)
 | 
					                .setHologramOffset(-1.275)
 | 
				
			||||||
                .addProperties("cat_variant", "cat_laying", "cat_relaxed", "cat_collar", "tamed"));
 | 
					                .addProperties("cat_variant", "cat_laying", "cat_relaxed", "cat_collar"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        register(builder(p, "fox", EntityTypes.FOX)
 | 
					        register(builder(p, "fox", EntityTypes.FOX)
 | 
				
			||||||
                .setHologramOffset(-1.275)
 | 
					                .setHologramOffset(-1.275)
 | 
				
			||||||
| 
						 | 
					@ -314,7 +320,8 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
 | 
				
			||||||
                .addEquipmentProperties());
 | 
					                .addEquipmentProperties());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        register(builder(p, "strider", EntityTypes.STRIDER)
 | 
					        register(builder(p, "strider", EntityTypes.STRIDER)
 | 
				
			||||||
                .setHologramOffset(-0.275));
 | 
					                .setHologramOffset(-0.275)
 | 
				
			||||||
 | 
					                .addProperties("strider_shaking", "strider_saddled"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        register(builder(p, "zoglin", EntityTypes.ZOGLIN)
 | 
					        register(builder(p, "zoglin", EntityTypes.ZOGLIN)
 | 
				
			||||||
                .setHologramOffset(-0.575));
 | 
					                .setHologramOffset(-0.575));
 | 
				
			||||||
| 
						 | 
					@ -351,7 +358,8 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
 | 
				
			||||||
        if (!version.isNewerThanOrEquals(ServerVersion.V_1_20)) return;
 | 
					        if (!version.isNewerThanOrEquals(ServerVersion.V_1_20)) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        register(builder(p, "sniffer", EntityTypes.SNIFFER)
 | 
					        register(builder(p, "sniffer", EntityTypes.SNIFFER)
 | 
				
			||||||
                .setHologramOffset(0.125));
 | 
					                .setHologramOffset(0.125)
 | 
				
			||||||
 | 
					                .addProperties("sniffer_state"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        register(builder(p, "camel", EntityTypes.CAMEL)
 | 
					        register(builder(p, "camel", EntityTypes.CAMEL)
 | 
				
			||||||
                .setHologramOffset(0.25)
 | 
					                .setHologramOffset(0.25)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					package lol.pyr.znpcsplus.parsers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import lol.pyr.director.adventure.command.CommandContext;
 | 
				
			||||||
 | 
					import lol.pyr.director.adventure.parse.ParserType;
 | 
				
			||||||
 | 
					import lol.pyr.director.common.command.CommandExecutionException;
 | 
				
			||||||
 | 
					import lol.pyr.director.common.message.Message;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.Deque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class StringParser extends ParserType<String> {
 | 
				
			||||||
 | 
					    public StringParser(Message<CommandContext> message) {
 | 
				
			||||||
 | 
					        super(message);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public String parse(Deque<String> deque) throws CommandExecutionException {
 | 
				
			||||||
 | 
					        return deque.pollFirst();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -111,7 +111,7 @@ public class YamlStorage implements NpcStorage {
 | 
				
			||||||
            config.set("location", serializeLocation(npc.getLocation()));
 | 
					            config.set("location", serializeLocation(npc.getLocation()));
 | 
				
			||||||
            config.set("type", npc.getType().getName());
 | 
					            config.set("type", npc.getType().getName());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for (EntityProperty<?> property : npc.getAppliedProperties()) try {
 | 
					            for (EntityProperty<?> property : npc.getAllProperties()) try {
 | 
				
			||||||
                PropertySerializer<?> serializer = propertyRegistry.getSerializer(((EntityPropertyImpl<?>) property).getType());
 | 
					                PropertySerializer<?> serializer = propertyRegistry.getSerializer(((EntityPropertyImpl<?>) property).getType());
 | 
				
			||||||
                if (serializer == null) {
 | 
					                if (serializer == null) {
 | 
				
			||||||
                    Bukkit.getLogger().log(Level.WARNING, "Unknown serializer for property '" + property.getName() + "' for npc '" + entry.getId() + "'. skipping ...");
 | 
					                    Bukkit.getLogger().log(Level.WARNING, "Unknown serializer for property '" + property.getName() + "' for npc '" + entry.getId() + "'. skipping ...");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +21,9 @@ softdepend:
 | 
				
			||||||
  - ViaRewind
 | 
					  - ViaRewind
 | 
				
			||||||
  - Geyser-Spigot
 | 
					  - Geyser-Spigot
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					loadbefore:
 | 
				
			||||||
 | 
					  - Quests
 | 
				
			||||||
 | 
					
 | 
				
			||||||
commands:
 | 
					commands:
 | 
				
			||||||
  npc:
 | 
					  npc:
 | 
				
			||||||
    aliases:
 | 
					    aliases:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue