Shiny new 1.13 particle support
Hopefully this doesn't break 1.8-1.12
Dieser Commit ist enthalten in:
Ursprung
8d9bf7d91f
Commit
4c3a0afd7e
@ -42,6 +42,8 @@ import com.comphenix.protocol.utility.MinecraftReflection;
|
|||||||
import com.comphenix.protocol.utility.StreamSerializer;
|
import com.comphenix.protocol.utility.StreamSerializer;
|
||||||
import com.comphenix.protocol.wrappers.*;
|
import com.comphenix.protocol.wrappers.*;
|
||||||
import com.comphenix.protocol.wrappers.EnumWrappers.*;
|
import com.comphenix.protocol.wrappers.EnumWrappers.*;
|
||||||
|
import com.comphenix.protocol.wrappers.EnumWrappers.Difficulty;
|
||||||
|
import com.comphenix.protocol.wrappers.EnumWrappers.SoundCategory;
|
||||||
import com.comphenix.protocol.wrappers.nbt.NbtBase;
|
import com.comphenix.protocol.wrappers.nbt.NbtBase;
|
||||||
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
|
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
|
||||||
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
|
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
|
||||||
@ -53,10 +55,8 @@ import com.google.common.collect.Sets;
|
|||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||||
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.*;
|
||||||
import org.bukkit.Sound;
|
import org.bukkit.Particle;
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.WorldType;
|
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.potion.PotionEffectType;
|
import org.bukkit.potion.PotionEffectType;
|
||||||
@ -831,16 +831,28 @@ public class PacketContainer implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve a read/write structure for the Particle enum in 1.8.
|
* Retrieve a read/write structure for the Particle enum in 1.8-1.12.
|
||||||
|
* <b>NOTE:</b> This will produce undesirable results in 1.13
|
||||||
* @return A modifier for Particle enum fields.
|
* @return A modifier for Particle enum fields.
|
||||||
*/
|
*/
|
||||||
public StructureModifier<Particle> getParticles() {
|
public StructureModifier<EnumWrappers.Particle> getParticles() {
|
||||||
// Convert to and from the wrapper
|
// Convert to and from the wrapper
|
||||||
return structureModifier.withType(
|
return structureModifier.withType(
|
||||||
EnumWrappers.getParticleClass(),
|
EnumWrappers.getParticleClass(),
|
||||||
EnumWrappers.getParticleConverter());
|
EnumWrappers.getParticleConverter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a read/write structure for ParticleParams in 1.13
|
||||||
|
* @return A modifier for ParticleParam fields.
|
||||||
|
*/
|
||||||
|
public StructureModifier<WrappedParticle> getNewParticles() {
|
||||||
|
return structureModifier.withType(
|
||||||
|
MinecraftReflection.getMinecraftClass("ParticleParam"),
|
||||||
|
BukkitConverters.getParticleConverter()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve a read/write structure for the MobEffectList class in 1.9.
|
* Retrieve a read/write structure for the MobEffectList class in 1.9.
|
||||||
* @return A modifier for MobEffectList fields.
|
* @return A modifier for MobEffectList fields.
|
||||||
|
@ -47,11 +47,12 @@ import com.google.common.collect.ImmutableList;
|
|||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import org.bukkit.Material;
|
import net.minecraft.server.v1_13_R1.ParticleParam;
|
||||||
import org.bukkit.Sound;
|
import net.minecraft.server.v1_13_R1.ParticleParamBlock;
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.WorldType;
|
import org.bukkit.*;
|
||||||
import org.bukkit.advancement.Advancement;
|
import org.bukkit.advancement.Advancement;
|
||||||
|
import org.bukkit.craftbukkit.v1_13_R1.CraftParticle;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.potion.PotionEffect;
|
import org.bukkit.potion.PotionEffect;
|
||||||
@ -929,6 +930,10 @@ public class BukkitConverters {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static EquivalentConverter<WrappedParticle> getParticleConverter() {
|
||||||
|
return ignoreNull(handle(WrappedParticle::getHandle, WrappedParticle::fromHandle));
|
||||||
|
}
|
||||||
|
|
||||||
public static EquivalentConverter<Advancement> getAdvancementConverter() {
|
public static EquivalentConverter<Advancement> getAdvancementConverter() {
|
||||||
return ignoreNull(new EquivalentConverter<Advancement>() {
|
return ignoreNull(new EquivalentConverter<Advancement>() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -12,6 +12,7 @@ import com.comphenix.protocol.reflect.FuzzyReflection;
|
|||||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
import org.bukkit.EntityEffect;
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,151 @@
|
|||||||
|
package com.comphenix.protocol.wrappers;
|
||||||
|
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||||
|
import com.comphenix.protocol.reflect.StructureModifier;
|
||||||
|
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||||
|
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
|
||||||
|
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
|
||||||
|
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||||
|
|
||||||
|
import org.bukkit.Color;
|
||||||
|
import org.bukkit.Particle;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an immutable wrapped ParticleParam in 1.13
|
||||||
|
*/
|
||||||
|
public class WrappedParticle<T> {
|
||||||
|
private static MethodAccessor toBukkit;
|
||||||
|
private static MethodAccessor toNMS;
|
||||||
|
private static MethodAccessor toCraftData;
|
||||||
|
|
||||||
|
private static void ensureMethods() {
|
||||||
|
if (toBukkit != null && toNMS != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FuzzyReflection fuzzy = FuzzyReflection.fromClass(MinecraftReflection.getCraftBukkitClass("CraftParticle"));
|
||||||
|
FuzzyMethodContract contract = FuzzyMethodContract
|
||||||
|
.newBuilder()
|
||||||
|
.requireModifier(Modifier.STATIC)
|
||||||
|
.returnTypeExact(Particle.class)
|
||||||
|
.parameterExactType(MinecraftReflection.getMinecraftClass("ParticleParam"))
|
||||||
|
.build();
|
||||||
|
toBukkit = Accessors.getMethodAccessor(fuzzy.getMethod(contract));
|
||||||
|
|
||||||
|
contract = FuzzyMethodContract
|
||||||
|
.newBuilder()
|
||||||
|
.requireModifier(Modifier.STATIC)
|
||||||
|
.returnTypeExact(MinecraftReflection.getMinecraftClass("ParticleParam"))
|
||||||
|
.parameterCount(2)
|
||||||
|
.build();
|
||||||
|
toNMS = Accessors.getMethodAccessor(fuzzy.getMethod(contract));
|
||||||
|
|
||||||
|
Class<?> cbData = MinecraftReflection.getCraftBukkitClass("block.data.CraftBlockData");
|
||||||
|
fuzzy = FuzzyReflection.fromClass(cbData);
|
||||||
|
contract = FuzzyMethodContract
|
||||||
|
.newBuilder()
|
||||||
|
.requireModifier(Modifier.STATIC)
|
||||||
|
.returnTypeExact(cbData)
|
||||||
|
.parameterExactArray(MinecraftReflection.getIBlockDataClass())
|
||||||
|
.build();
|
||||||
|
toCraftData = Accessors.getMethodAccessor(fuzzy.getMethod(contract));
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Particle particle;
|
||||||
|
private final T data;
|
||||||
|
private final Object handle;
|
||||||
|
|
||||||
|
private WrappedParticle(Object handle, Particle particle, T data) {
|
||||||
|
this.handle = handle;
|
||||||
|
this.particle = particle;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return This particle's Bukkit type
|
||||||
|
*/
|
||||||
|
public Particle getParticle() {
|
||||||
|
return particle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets this Particle's Bukkit/ProtocolLib data. The type of this data depends on the
|
||||||
|
* {@link #getParticle() Particle type}. For Block particles it will be {@link WrappedBlockData},
|
||||||
|
* for Item crack particles, it will be an {@link ItemStack}, and for redstone particles it will
|
||||||
|
* be {@link Particle.DustOptions}
|
||||||
|
*
|
||||||
|
* @return The particle data
|
||||||
|
*/
|
||||||
|
public T getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return NMS handle
|
||||||
|
*/
|
||||||
|
public Object getHandle() {
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WrappedParticle fromHandle(Object handle) {
|
||||||
|
Particle bukkit = (Particle) toBukkit.invoke(null, handle);
|
||||||
|
Object data = null;
|
||||||
|
|
||||||
|
switch (bukkit) {
|
||||||
|
case BLOCK_CRACK:
|
||||||
|
case BLOCK_DUST:
|
||||||
|
case FALLING_DUST:
|
||||||
|
data = getBlockData(handle);
|
||||||
|
break;
|
||||||
|
case ITEM_CRACK:
|
||||||
|
data = getItem(handle);
|
||||||
|
break;
|
||||||
|
case REDSTONE:
|
||||||
|
data = getRedstone(handle);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new WrappedParticle<>(handle, bukkit, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WrappedBlockData getBlockData(Object handle) {
|
||||||
|
return new StructureModifier<>(handle.getClass())
|
||||||
|
.withTarget(handle)
|
||||||
|
.withType(MinecraftReflection.getIBlockDataClass(), BukkitConverters.getWrappedBlockDataConverter())
|
||||||
|
.read(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object getItem(Object handle) {
|
||||||
|
return new StructureModifier<>(handle.getClass())
|
||||||
|
.withTarget(handle)
|
||||||
|
.withType(MinecraftReflection.getItemStackClass(), BukkitConverters.getItemStackConverter())
|
||||||
|
.read(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object getRedstone(Object handle) {
|
||||||
|
StructureModifier<Float> modifier = new StructureModifier<>(handle.getClass()).withTarget(handle).withType(float.class);
|
||||||
|
return new Particle.DustOptions(Color.fromRGB(
|
||||||
|
(int) (modifier.read(0) * 255),
|
||||||
|
(int) (modifier.read(1) * 255),
|
||||||
|
(int) (modifier.read(2) * 255)),
|
||||||
|
modifier.read(3));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> WrappedParticle<T> create(Particle particle, T data) {
|
||||||
|
ensureMethods();
|
||||||
|
|
||||||
|
Object bukkitData = data;
|
||||||
|
if (data instanceof WrappedBlockData) {
|
||||||
|
WrappedBlockData blockData = (WrappedBlockData) data;
|
||||||
|
bukkitData = toCraftData.invoke(null, blockData.getHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
Object handle = toNMS.invoke(null, particle, bukkitData);
|
||||||
|
return new WrappedParticle<>(handle, particle, data);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package com.comphenix.protocol.wrappers;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.BukkitInitialization;
|
||||||
|
import com.comphenix.protocol.PacketType;
|
||||||
|
import com.comphenix.protocol.events.PacketContainer;
|
||||||
|
|
||||||
|
import org.bukkit.Color;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.Particle;
|
||||||
|
import org.bukkit.Particle.DustOptions;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static com.comphenix.protocol.utility.TestUtils.assertItemsEqual;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class WrappedParticleTest {
|
||||||
|
@BeforeClass
|
||||||
|
public static void beforeClass() {
|
||||||
|
BukkitInitialization.initializeItemMeta();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBlockData() {
|
||||||
|
PacketContainer packet = new PacketContainer(PacketType.Play.Server.WORLD_PARTICLES);
|
||||||
|
WrappedParticle before = WrappedParticle.create(Particle.BLOCK_CRACK,
|
||||||
|
WrappedBlockData.createData(Material.LAPIS_BLOCK));
|
||||||
|
packet.getNewParticles().write(0, before);
|
||||||
|
|
||||||
|
WrappedParticle after = packet.getNewParticles().read(0);
|
||||||
|
assertEquals(before.getParticle(), after.getParticle());
|
||||||
|
assertEquals(before.getData(), after.getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testItemStacks() {
|
||||||
|
PacketContainer packet = new PacketContainer(PacketType.Play.Server.WORLD_PARTICLES);
|
||||||
|
WrappedParticle before = WrappedParticle.create(Particle.ITEM_CRACK, new ItemStack(Material.FLINT_AND_STEEL));
|
||||||
|
packet.getNewParticles().write(0, before);
|
||||||
|
|
||||||
|
WrappedParticle after = packet.getNewParticles().read(0);
|
||||||
|
assertEquals(before.getParticle(), after.getParticle());
|
||||||
|
assertItemsEqual((ItemStack) before.getData(), (ItemStack) after.getData());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRedstone() {
|
||||||
|
PacketContainer packet = new PacketContainer(PacketType.Play.Server.WORLD_PARTICLES);
|
||||||
|
WrappedParticle before = WrappedParticle.create(Particle.REDSTONE, new DustOptions(Color.BLUE, 1));
|
||||||
|
packet.getNewParticles().write(0, before);
|
||||||
|
|
||||||
|
WrappedParticle after = packet.getNewParticles().read(0);
|
||||||
|
assertEquals(before.getParticle(), after.getParticle());
|
||||||
|
|
||||||
|
DustOptions beforeDust = (DustOptions) before.getData();
|
||||||
|
DustOptions afterDust = (DustOptions) after.getData();
|
||||||
|
assertEquals(beforeDust.getColor(), afterDust.getColor());
|
||||||
|
assertEquals(beforeDust.getSize(), afterDust.getSize(), 0);
|
||||||
|
}
|
||||||
|
}
|
In neuem Issue referenzieren
Einen Benutzer sperren