added End Crystal and its properties
This commit is contained in:
parent
f519020c5b
commit
f3c0df41dc
8 changed files with 201 additions and 5 deletions
46
api/src/main/java/lol/pyr/znpcsplus/util/Vector3i.java
Normal file
46
api/src/main/java/lol/pyr/znpcsplus/util/Vector3i.java
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
package lol.pyr.znpcsplus.util;
|
||||||
|
|
||||||
|
public class Vector3i {
|
||||||
|
private final int x;
|
||||||
|
private final int y;
|
||||||
|
private final int z;
|
||||||
|
|
||||||
|
public Vector3i(int x, int y, int z) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getX() {
|
||||||
|
return this.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getY() {
|
||||||
|
return this.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getZ() {
|
||||||
|
return this.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return this.x + "," + this.y + "," + this.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toPrettyString() {
|
||||||
|
return "(" + this.x + ", " + this.y + ", " + this.z + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector3i fromString(String s) {
|
||||||
|
String[] split = s.split(",");
|
||||||
|
if (split.length < 3) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
return new Vector3i(Integer.parseInt(split[0]), Integer.parseInt(split[1]), Integer.parseInt(split[2]));
|
||||||
|
} catch (NumberFormatException var3) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -251,6 +251,7 @@ public class ZNpcsPlus extends JavaPlugin {
|
||||||
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));
|
manager.registerParser(String.class, new StringParser(incorrectUsageMessage));
|
||||||
|
manager.registerParser(Vector3i.class, new Vector3iParser(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);
|
||||||
|
|
|
@ -19,6 +19,9 @@ import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import org.bukkit.Color;
|
import org.bukkit.Color;
|
||||||
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
import com.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -117,9 +120,20 @@ public class PropertySetCommand implements CommandHandler {
|
||||||
value = context.parse(type);
|
value = context.parse(type);
|
||||||
valueName = value == null ? "NONE" : ((NpcEntryImpl) value).getId();
|
valueName = value == null ? "NONE" : ((NpcEntryImpl) value).getId();
|
||||||
}
|
}
|
||||||
else {
|
else if (type == Vector3i.class) {
|
||||||
value = context.parse(type);
|
value = context.parse(type);
|
||||||
valueName = String.valueOf(value);
|
valueName = value == null ? "NONE" : ((Vector3i) value).toPrettyString();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
value = context.parse(type);
|
||||||
|
valueName = String.valueOf(value);
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
context.send(Component.text("An error occurred while trying to parse the value. Please report this to the plugin author.",
|
||||||
|
NamedTextColor.RED));
|
||||||
|
e.printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
npc.UNSAFE_setProperty(property, value);
|
npc.UNSAFE_setProperty(property, value);
|
||||||
|
@ -144,6 +158,17 @@ public class PropertySetCommand implements CommandHandler {
|
||||||
context.suggestEnum(Arrays.stream(SpellType.values()).filter(spellType -> spellType.ordinal() <= 3).toArray(SpellType[]::new)) :
|
context.suggestEnum(Arrays.stream(SpellType.values()).filter(spellType -> spellType.ordinal() <= 3).toArray(SpellType[]::new)) :
|
||||||
context.suggestEnum(SpellType.values());
|
context.suggestEnum(SpellType.values());
|
||||||
|
|
||||||
|
if (type == Vector3i.class) {
|
||||||
|
if (context.getSender() instanceof Player) {
|
||||||
|
Player player = (Player) context.getSender();
|
||||||
|
Block targetBlock = player.getTargetBlock(Collections.singleton(Material.AIR), 5);
|
||||||
|
if (targetBlock.getType().equals(Material.AIR)) return Collections.emptyList();
|
||||||
|
return context.suggestLiteral(
|
||||||
|
targetBlock.getX() + "",
|
||||||
|
targetBlock.getX() + " " + targetBlock.getY(),
|
||||||
|
targetBlock.getX() + " " + targetBlock.getY() + " " + targetBlock.getZ());
|
||||||
|
}
|
||||||
|
}
|
||||||
// Suggest enum values directly
|
// Suggest enum values directly
|
||||||
if (type.isEnum()) {
|
if (type.isEnum()) {
|
||||||
return context.suggestEnum((Enum<?>[]) type.getEnumConstants());
|
return context.suggestEnum((Enum<?>[]) type.getEnumConstants());
|
||||||
|
@ -154,6 +179,25 @@ public class PropertySetCommand implements CommandHandler {
|
||||||
// TODO: suggest block with nbt like minecraft setblock command
|
// TODO: suggest block with nbt like minecraft setblock command
|
||||||
return context.suggestionParse(2, String.class).equals("block") ? context.suggestStream(StateTypes.values().stream().map(StateType::getName)) : Collections.emptyList();
|
return context.suggestionParse(2, String.class).equals("block") ? context.suggestStream(StateTypes.values().stream().map(StateType::getName)) : Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
if (type == Vector3i.class) {
|
||||||
|
if (context.getSender() instanceof Player) {
|
||||||
|
Player player = (Player) context.getSender();
|
||||||
|
Block targetBlock = player.getTargetBlock(Collections.singleton(Material.AIR), 5);
|
||||||
|
if (targetBlock.getType().equals(Material.AIR)) return Collections.emptyList();
|
||||||
|
return context.suggestLiteral(
|
||||||
|
targetBlock.getY() + "",
|
||||||
|
targetBlock.getY() + " " + targetBlock.getZ());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (context.argSize() == 5) {
|
||||||
|
if (type == Vector3i.class) {
|
||||||
|
if (context.getSender() instanceof Player) {
|
||||||
|
Player player = (Player) context.getSender();
|
||||||
|
Block targetBlock = player.getTargetBlock(Collections.singleton(Material.AIR), 5);
|
||||||
|
if (targetBlock.getType().equals(Material.AIR)) return Collections.emptyList();
|
||||||
|
return context.suggestLiteral(targetBlock.getZ() + "");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
|
|
@ -56,6 +56,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
|
||||||
registerSerializer(new Vector3fPropertySerializer());
|
registerSerializer(new Vector3fPropertySerializer());
|
||||||
registerSerializer(new BlockStatePropertySerializer());
|
registerSerializer(new BlockStatePropertySerializer());
|
||||||
registerSerializer(new LookTypeSerializer());
|
registerSerializer(new LookTypeSerializer());
|
||||||
|
registerSerializer(new GenericSerializer<>(Vector3i::toString, Vector3i::fromString, Vector3i.class));
|
||||||
|
|
||||||
registerEnumSerializer(NpcPose.class);
|
registerEnumSerializer(NpcPose.class);
|
||||||
registerEnumSerializer(DyeColor.class);
|
registerEnumSerializer(DyeColor.class);
|
||||||
|
@ -251,6 +252,17 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
|
||||||
register(new BitsetProperty("is_rearing", horseIndex, horseEating << 1, false, legacyBooleans));
|
register(new BitsetProperty("is_rearing", horseIndex, horseEating << 1, false, legacyBooleans));
|
||||||
register(new BitsetProperty("has_mouth_open", horseIndex, horseEating << 2, false, legacyBooleans));
|
register(new BitsetProperty("has_mouth_open", horseIndex, horseEating << 2, false, legacyBooleans));
|
||||||
|
|
||||||
|
// End Crystal
|
||||||
|
if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) {
|
||||||
|
int endCrystalIndex;
|
||||||
|
if (ver.isNewerThanOrEquals(ServerVersion.V_1_17)) endCrystalIndex = 8;
|
||||||
|
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_15)) endCrystalIndex = 7;
|
||||||
|
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_10)) endCrystalIndex = 6;
|
||||||
|
else endCrystalIndex = 5;
|
||||||
|
register(new OptionalBlockPosProperty("beam_target", null, endCrystalIndex++));
|
||||||
|
register(new BooleanProperty("show_base", endCrystalIndex, true, false));
|
||||||
|
}
|
||||||
|
|
||||||
// Horse
|
// Horse
|
||||||
if (ver.isNewerThanOrEquals(ServerVersion.V_1_8) && ver.isOlderThan(ServerVersion.V_1_9)) {
|
if (ver.isNewerThanOrEquals(ServerVersion.V_1_8) && ver.isOlderThan(ServerVersion.V_1_9)) {
|
||||||
register(new EncodedByteProperty<>("horse_type", HorseType.HORSE, 19, obj -> (byte) obj.ordinal()));
|
register(new EncodedByteProperty<>("horse_type", HorseType.HORSE, 19, obj -> (byte) obj.ordinal()));
|
||||||
|
@ -367,7 +379,7 @@ public class EntityPropertyRegistryImpl implements EntityPropertyRegistry {
|
||||||
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) witherIndex = 11;
|
else if (ver.isNewerThanOrEquals(ServerVersion.V_1_9)) witherIndex = 11;
|
||||||
else witherIndex = 17;
|
else witherIndex = 17;
|
||||||
witherIndex += 3; // skip the first 3 indexes, will be used for the other properties later
|
witherIndex += 3; // skip the first 3 indexes, will be used for the other properties later
|
||||||
register(new IntegerProperty("invulnerable_time", witherIndex++, 0, false));
|
register(new IntegerProperty("invulnerable_time", witherIndex, 0, false));
|
||||||
|
|
||||||
if (!ver.isNewerThanOrEquals(ServerVersion.V_1_9)) return;
|
if (!ver.isNewerThanOrEquals(ServerVersion.V_1_9)) return;
|
||||||
// Shulker
|
// Shulker
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
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.Vector3i;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class OptionalBlockPosProperty extends EntityPropertyImpl<Vector3i> {
|
||||||
|
private final int index;
|
||||||
|
|
||||||
|
public OptionalBlockPosProperty(String name, Vector3i defaultValue, int index) {
|
||||||
|
super(name, defaultValue, Vector3i.class);
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(Player player, PacketEntity entity, boolean isSpawned, Map<Integer, EntityData> properties) {
|
||||||
|
Vector3i value = entity.getProperty(this);
|
||||||
|
if (value == null) properties.put(index, new EntityData(index, EntityDataTypes.OPTIONAL_BLOCK_POSITION, Optional.empty()));
|
||||||
|
else properties.put(index, new EntityData(index, EntityDataTypes.OPTIONAL_BLOCK_POSITION,
|
||||||
|
Optional.of(new com.github.retrooper.packetevents.util.Vector3i(value.getX(), value.getY(), value.getZ()))));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package lol.pyr.znpcsplus.entity.serializers;
|
||||||
|
|
||||||
|
import lol.pyr.znpcsplus.entity.PropertySerializer;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class GenericSerializer<T> implements PropertySerializer<T> {
|
||||||
|
private final Function<T, String> encoder;
|
||||||
|
private final Function<String, T> decoder;
|
||||||
|
private final Class<T> typeClass;
|
||||||
|
|
||||||
|
public GenericSerializer(Function<T, String> encoder, Function<String, T> decoder, Class<T> typeClass) {
|
||||||
|
this.encoder = encoder;
|
||||||
|
this.decoder = decoder;
|
||||||
|
this.typeClass = typeClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String serialize(T property) {
|
||||||
|
return encoder.apply(property);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T deserialize(String property) {
|
||||||
|
return decoder.apply(property);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<T> getTypeClass() {
|
||||||
|
return typeClass;
|
||||||
|
}
|
||||||
|
}
|
|
@ -73,6 +73,10 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
|
||||||
.setHologramOffset(-0.275)
|
.setHologramOffset(-0.275)
|
||||||
.addProperties("creeper_state", "creeper_charged"));
|
.addProperties("creeper_state", "creeper_charged"));
|
||||||
|
|
||||||
|
register(builder(p, "end_crystal", EntityTypes.END_CRYSTAL)
|
||||||
|
.setHologramOffset(0.025)
|
||||||
|
.addProperties("beam_target", "show_base"));
|
||||||
|
|
||||||
register(builder(p, "ender_dragon", EntityTypes.ENDER_DRAGON)
|
register(builder(p, "ender_dragon", EntityTypes.ENDER_DRAGON)
|
||||||
.setHologramOffset(6.0245));
|
.setHologramOffset(6.0245));
|
||||||
|
|
||||||
|
@ -206,8 +210,7 @@ public class NpcTypeRegistryImpl implements NpcTypeRegistry {
|
||||||
.addEquipmentProperties());
|
.addEquipmentProperties());
|
||||||
|
|
||||||
register(builder(p, "evoker", EntityTypes.EVOKER)
|
register(builder(p, "evoker", EntityTypes.EVOKER)
|
||||||
.setHologramOffset(-0.025)
|
.setHologramOffset(-0.025));
|
||||||
.addProperties("evoker_spell"));
|
|
||||||
|
|
||||||
register(builder(p, "llama", EntityTypes.LLAMA)
|
register(builder(p, "llama", EntityTypes.LLAMA)
|
||||||
.setHologramOffset(-0.105)
|
.setHologramOffset(-0.105)
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
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 lol.pyr.znpcsplus.util.Vector3i;
|
||||||
|
|
||||||
|
import java.util.Deque;
|
||||||
|
|
||||||
|
public class Vector3iParser extends ParserType<Vector3i> {
|
||||||
|
public Vector3iParser(Message<CommandContext> message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vector3i parse(Deque<String> deque) throws CommandExecutionException {
|
||||||
|
if (deque.size() == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return new Vector3i(
|
||||||
|
Integer.parseInt(deque.pop()),
|
||||||
|
Integer.parseInt(deque.pop()),
|
||||||
|
Integer.parseInt(deque.pop()));
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new CommandExecutionException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue