Fix skeleton disguises appearing invisible
This commit is contained in:
parent
ebd9986542
commit
c69f67b3e8
@ -228,6 +228,9 @@ public class DisguiseManager extends MiniPlugin implements IPacketHandler
|
||||
if (!spawnedIn)
|
||||
{
|
||||
refreshTrackers(disguise.getEntity().getBukkitEntity());
|
||||
} else
|
||||
{
|
||||
disguise.markSpawnedIn();
|
||||
}
|
||||
|
||||
disguise.onDisguise(true);
|
||||
|
@ -1,7 +1,11 @@
|
||||
package mineplex.core.disguise.disguises;
|
||||
|
||||
import mineplex.core.common.DummyEntity;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import net.minecraft.server.v1_8_R3.*;
|
||||
|
||||
@ -10,12 +14,8 @@ import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import mineplex.core.common.DummyEntity;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
|
||||
public abstract class DisguiseBase
|
||||
{
|
||||
@ -32,6 +32,8 @@ public abstract class DisguiseBase
|
||||
*/
|
||||
private boolean _hideIfNotDisguised = false;
|
||||
|
||||
protected boolean _spawnedIn = false;
|
||||
|
||||
public DisguiseBase(EntityType entityType, org.bukkit.entity.Entity entity)
|
||||
{
|
||||
if (entity == null)
|
||||
@ -67,7 +69,7 @@ public abstract class DisguiseBase
|
||||
DataWatcher.watch(1, getEntity().getDataWatcher().getShort(1), net.minecraft.server.v1_8_R3.Entity.META_AIR, (int) getEntity().getDataWatcher().getShort(1));
|
||||
}
|
||||
|
||||
public void sendToWatchers(Supplier<Packet> supplier)
|
||||
protected void sendToWatchers(Predicate<Integer> protocolPredicate, Supplier<Packet> supplier)
|
||||
{
|
||||
if (getEntity() == null || !getEntity().getBukkitEntity().isValid() || !(getEntity().world instanceof WorldServer))
|
||||
return;
|
||||
@ -83,12 +85,16 @@ public abstract class DisguiseBase
|
||||
|
||||
for (EntityPlayer player : tracker.get(getEntity().getId()).trackedPlayers)
|
||||
{
|
||||
int protocol = player.getProtocol();
|
||||
if (!protocolPredicate.test(protocol))
|
||||
continue;
|
||||
|
||||
if (packet instanceof PacketPlayOutEntityMetadata)
|
||||
{
|
||||
player.playerConnection.sendPacket(modifyMetaPacket(player.getProtocol(), packet));
|
||||
player.playerConnection.sendPacket(modifyMetaPacket(protocol, packet));
|
||||
} else if (packet instanceof PacketPlayOutSpawnEntityLiving)
|
||||
{
|
||||
player.playerConnection.sendPacket(modifySpawnPacket(player.getProtocol(), packet));
|
||||
player.playerConnection.sendPacket(modifySpawnPacket(protocol, packet));
|
||||
} else
|
||||
{
|
||||
player.playerConnection.sendPacket(packet);
|
||||
@ -96,6 +102,11 @@ public abstract class DisguiseBase
|
||||
}
|
||||
}
|
||||
|
||||
protected void sendToWatchers(Supplier<Packet> supplier)
|
||||
{
|
||||
sendToWatchers(x -> true, supplier);
|
||||
}
|
||||
|
||||
public abstract Packet getSpawnPacket();
|
||||
|
||||
public Packet modifySpawnPacket(int protocol, Packet packet)
|
||||
@ -203,6 +214,11 @@ public abstract class DisguiseBase
|
||||
|
||||
}
|
||||
|
||||
public void markSpawnedIn()
|
||||
{
|
||||
_spawnedIn = true;
|
||||
}
|
||||
|
||||
public void setHideIfNotDisguised(boolean hideIfNotDisguised)
|
||||
{
|
||||
this._hideIfNotDisguised = hideIfNotDisguised;
|
||||
|
@ -1,10 +1,10 @@
|
||||
package mineplex.core.disguise.disguises;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.mineplex.MetaWrapper;
|
||||
import com.mineplex.MetadataRewriter;
|
||||
import com.mineplex.ProtocolVersion;
|
||||
|
||||
import net.minecraft.server.v1_8_R3.*;
|
||||
@ -78,45 +78,112 @@ public abstract class DisguiseCreature extends DisguiseInsentient
|
||||
return packet;
|
||||
}
|
||||
|
||||
// ---- Metadata processing
|
||||
|
||||
// This WON'T be post-processed by the Spigot metadata processor
|
||||
|
||||
@Override
|
||||
public Packet modifySpawnPacket(int protocol, Packet packet)
|
||||
{
|
||||
if (protocol >= ProtocolVersion.v1_10_PRE)
|
||||
{
|
||||
PacketPlayOutSpawnEntityLiving newSpawn = (PacketPlayOutSpawnEntityLiving) getSpawnPacket();
|
||||
newSpawn.m = processSpawnMeta(protocol, DataWatcher.c());
|
||||
|
||||
// Allow the entity type to be changed (needed on 1.11+)
|
||||
newSpawn.b = getTypeId(protocol >= ProtocolVersion.v1_11);
|
||||
|
||||
boolean hasArms = false;
|
||||
List<WatchableObject> meta = DataWatcher.b();
|
||||
|
||||
if (meta != null)
|
||||
{
|
||||
// Run the meta through our Spigot rewriter
|
||||
meta = MetadataRewriter.rewrite(getTypeId(false), protocol, meta).objects;
|
||||
|
||||
// Remove indexes >= 12 on 1.11+
|
||||
if (protocol >= ProtocolVersion.v1_11)
|
||||
{
|
||||
Iterator<WatchableObject> iter = meta.iterator();
|
||||
while (iter.hasNext())
|
||||
{
|
||||
WatchableObject next = iter.next();
|
||||
if (next.getIndex().a() == 6)
|
||||
{
|
||||
hasArms = true;
|
||||
} else if (next.getIndex().a() >= 12)
|
||||
{
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
meta = new ArrayList<>();
|
||||
}
|
||||
|
||||
if (!hasArms)
|
||||
{
|
||||
WatchableObject<Byte> arms = new WatchableObject<>(0, 0, null,
|
||||
new DataIndex<>(6, DataType.BYTE), (byte) 0);
|
||||
meta.add(arms);
|
||||
}
|
||||
|
||||
newSpawn.m = meta;
|
||||
return newSpawn;
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
private List<WatchableObject> processSpawnMeta(int protocol, List<WatchableObject> list)
|
||||
protected int getTypeId(boolean separate)
|
||||
{
|
||||
List<MetaWrapper> newMeta = new ArrayList<>();
|
||||
for (WatchableObject meta : list)
|
||||
{
|
||||
MetaWrapper wrapper = new MetaWrapper(meta);
|
||||
if (wrapper.getIndex() >= 5) // 1.10
|
||||
{
|
||||
wrapper.setIndex(wrapper.getIndex() + 1);
|
||||
return getDisguiseType().getTypeId();
|
||||
}
|
||||
|
||||
if (protocol < ProtocolVersion.v1_11)
|
||||
// This WILL be post-processed by Spigot's metadata processor
|
||||
|
||||
@Override
|
||||
public Packet modifyMetaPacket(int protocol, Packet packet)
|
||||
{
|
||||
newMeta.add(wrapper);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (getEntity() instanceof EntityArmorStand && wrapper.getIndex() >= 12)
|
||||
if (protocol >= ProtocolVersion.v1_10_PRE)
|
||||
{
|
||||
// Armor stand meta conflicts with a lot of entities on 1.11+
|
||||
continue;
|
||||
PacketPlayOutEntityMetadata newMeta = new PacketPlayOutEntityMetadata();
|
||||
newMeta.a = getEntityId();
|
||||
|
||||
boolean hasArms = false;
|
||||
List<WatchableObject> meta = DataWatcher.b();
|
||||
List<WatchableObject> adjusted = new ArrayList<>();
|
||||
|
||||
if (meta != null)
|
||||
{
|
||||
// Process the meta while we know the entity id
|
||||
adjusted = MetadataRewriter.rewrite(getTypeId(false), protocol, meta).objects;
|
||||
hasArms = meta.stream().anyMatch(obj -> obj.getIndex().a() == 6);
|
||||
}
|
||||
|
||||
newMeta.add(wrapper);
|
||||
for (int i = 0; i < adjusted.size(); i++)
|
||||
{
|
||||
WatchableObject object = adjusted.get(i);
|
||||
int index = object.getIndex().a();
|
||||
if (index >= 6)
|
||||
{
|
||||
index--;
|
||||
adjusted.set(i, new WatchableObject(0, 0, null,
|
||||
new DataIndex(index, object.getIndex().b()), object.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
return newMeta.stream().map(MetaWrapper::toWatchableObject).collect(Collectors.toList());
|
||||
if (!hasArms)
|
||||
{
|
||||
WatchableObject<Byte> arms = new WatchableObject<>(0, 0, null,
|
||||
new DataIndex<>(5, DataType.BYTE), (byte) 0);
|
||||
adjusted.add(arms);
|
||||
}
|
||||
|
||||
newMeta.b = adjusted;
|
||||
return newMeta;
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,14 @@
|
||||
package mineplex.core.disguise.disguises;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import net.minecraft.server.v1_8_R3.EntityGuardian;
|
||||
|
||||
import com.mineplex.MetaWrapper;
|
||||
import com.mineplex.ProtocolVersion;
|
||||
|
||||
import net.minecraft.server.v1_8_R3.*;
|
||||
import net.minecraft.server.v1_8_R3.DataWatcher.WatchableObject;
|
||||
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
public class DisguiseGuardian extends DisguiseCreature
|
||||
public class DisguiseGuardian extends DisguiseMutable
|
||||
{
|
||||
private static final int GUARDIAN_ID = 68;
|
||||
private static final int ELDER_GUARDIAN_ID = 4;
|
||||
|
||||
private int target = 0;
|
||||
private boolean elder = false;
|
||||
|
||||
@ -41,9 +35,7 @@ public class DisguiseGuardian extends DisguiseCreature
|
||||
|
||||
DataWatcher.watch(16, Integer.valueOf(newValue), EntityGuardian.META_ELDER, (byte) newValue);
|
||||
|
||||
sendToWatchers(() -> new PacketPlayOutEntityDestroy(new int[]{getEntityId()}));
|
||||
sendToWatchers(this::getSpawnPacket);
|
||||
sendToWatchers(this::getMetadataPacket);
|
||||
mutate();
|
||||
}
|
||||
|
||||
public boolean isElder()
|
||||
@ -66,49 +58,9 @@ public class DisguiseGuardian extends DisguiseCreature
|
||||
return "mob.guardian.hit";
|
||||
}
|
||||
|
||||
// ---- Packet modification for 1.11 and up
|
||||
|
||||
@Override
|
||||
public Packet modifySpawnPacket(int protocol, Packet packet)
|
||||
protected int getTypeId(boolean separate)
|
||||
{
|
||||
PacketPlayOutSpawnEntityLiving newSpawn = (PacketPlayOutSpawnEntityLiving) super.modifySpawnPacket(protocol, packet);
|
||||
if (protocol >= ProtocolVersion.v1_11 && isElder())
|
||||
{
|
||||
newSpawn.b = 4;
|
||||
}
|
||||
|
||||
return newSpawn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet modifyMetaPacket(int protocol, Packet packet)
|
||||
{
|
||||
if (protocol >= ProtocolVersion.v1_11)
|
||||
{
|
||||
PacketPlayOutEntityMetadata newPacket = (PacketPlayOutEntityMetadata) getMetadataPacket();
|
||||
newPacket.b = processMeta(newPacket.b);
|
||||
return newPacket;
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
private List<WatchableObject> processMeta(List<WatchableObject> list)
|
||||
{
|
||||
List<MetaWrapper> newMeta = new ArrayList<>();
|
||||
for (WatchableObject meta : list)
|
||||
{
|
||||
MetaWrapper wrapper = new MetaWrapper(meta);
|
||||
if (wrapper.getIndex() == 11)
|
||||
{
|
||||
byte value = (byte) wrapper.getValue();
|
||||
newMeta.add(new MetaWrapper(11, DataType.BOOLEAN, (value & 0x02) != 0));
|
||||
} else
|
||||
{
|
||||
newMeta.add(wrapper);
|
||||
}
|
||||
}
|
||||
|
||||
return newMeta.stream().map(MetaWrapper::toWatchableObject).collect(Collectors.toList());
|
||||
return separate && isElder() ? ELDER_GUARDIAN_ID : GUARDIAN_ID;
|
||||
}
|
||||
}
|
||||
|
@ -2,14 +2,24 @@ package mineplex.core.disguise.disguises;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import net.minecraft.server.v1_8_R3.EntityHorse;
|
||||
|
||||
import org.bukkit.entity.*;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
|
||||
public class DisguiseHorse extends DisguiseAnimal
|
||||
import net.minecraft.server.v1_8_R3.EntityAgeable;
|
||||
import net.minecraft.server.v1_8_R3.EntityHorse;
|
||||
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Horse;
|
||||
|
||||
public class DisguiseHorse extends DisguiseMutable
|
||||
{
|
||||
private static final int HORSE_ID = 100;
|
||||
private static final int DONKEY_ID = 31;
|
||||
private static final int MULE_ID = 32;
|
||||
private static final int ZOMBIE_HORSE_ID = 29;
|
||||
private static final int SKELETON_HORSE_ID = 28;
|
||||
|
||||
private Horse.Variant variant = Horse.Variant.HORSE;
|
||||
|
||||
public DisguiseHorse(org.bukkit.entity.Entity entity)
|
||||
{
|
||||
super(EntityType.HORSE, entity);
|
||||
@ -19,11 +29,25 @@ public class DisguiseHorse extends DisguiseAnimal
|
||||
DataWatcher.a(20, Integer.valueOf(0), EntityHorse.META_VARIANT, 0);
|
||||
DataWatcher.a(21, String.valueOf(""), EntityHorse.META_OWNER, Optional.<UUID> absent());
|
||||
DataWatcher.a(22, Integer.valueOf(0), EntityHorse.META_ARMOR, 0);
|
||||
|
||||
DataWatcher.a(12, new Byte((byte)0), EntityAgeable.META_BABY, false);
|
||||
}
|
||||
|
||||
public boolean isBaby()
|
||||
{
|
||||
return DataWatcher.getByte(12) < 0;
|
||||
}
|
||||
|
||||
public void setBaby()
|
||||
{
|
||||
DataWatcher.watch(12, new Byte((byte) ( -1 )), EntityAgeable.META_BABY, true);
|
||||
}
|
||||
|
||||
public void setType(Horse.Variant horseType)
|
||||
{
|
||||
DataWatcher.watch(19, Byte.valueOf((byte) horseType.ordinal()), EntityHorse.META_TYPE, horseType.ordinal());
|
||||
this.variant = horseType;
|
||||
mutate();
|
||||
}
|
||||
|
||||
public Horse.Variant getType()
|
||||
@ -72,4 +96,23 @@ public class DisguiseHorse extends DisguiseAnimal
|
||||
{
|
||||
DataWatcher.watch(22, Integer.valueOf(i), EntityHorse.META_ARMOR, i);
|
||||
}
|
||||
|
||||
// 1.11 and up require separate entity ids
|
||||
@Override
|
||||
protected int getTypeId(boolean separate)
|
||||
{
|
||||
if (separate && variant != Horse.Variant.HORSE)
|
||||
{
|
||||
switch (variant)
|
||||
{
|
||||
case DONKEY: return DONKEY_ID;
|
||||
case MULE: return MULE_ID;
|
||||
case UNDEAD_HORSE: return ZOMBIE_HORSE_ID;
|
||||
case SKELETON_HORSE: return SKELETON_HORSE_ID;
|
||||
default: return HORSE_ID;
|
||||
}
|
||||
}
|
||||
|
||||
return HORSE_ID;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
package mineplex.core.disguise.disguises;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.mineplex.ProtocolVersion;
|
||||
|
||||
import net.minecraft.server.v1_8_R3.Packet;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
/**
|
||||
* Represents a disguise that can "mutate" from one entity type to another.
|
||||
*/
|
||||
public abstract class DisguiseMutable extends DisguiseCreature
|
||||
{
|
||||
public DisguiseMutable(EntityType disguiseType, Entity entity)
|
||||
{
|
||||
super(disguiseType, entity);
|
||||
}
|
||||
|
||||
protected void mutate()
|
||||
{
|
||||
// if (!_spawnedIn)
|
||||
// return;
|
||||
|
||||
Predicate<Integer> pred = v -> v >= ProtocolVersion.v1_11;
|
||||
sendToWatchers(pred, this::getDestroyPacket);
|
||||
sendToWatchers(pred, this::getSpawnPacket);
|
||||
sendToWatchers(pred, this::getMetadataPacket);
|
||||
}
|
||||
|
||||
private Packet getDestroyPacket()
|
||||
{
|
||||
return new PacketPlayOutEntityDestroy(new int[] { getEntityId() });
|
||||
}
|
||||
|
||||
protected abstract int getTypeId(boolean separate);
|
||||
}
|
@ -2,11 +2,16 @@ package mineplex.core.disguise.disguises;
|
||||
|
||||
import net.minecraft.server.v1_8_R3.EntitySkeleton;
|
||||
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Skeleton.SkeletonType;
|
||||
|
||||
public class DisguiseSkeleton extends DisguiseMonster
|
||||
public class DisguiseSkeleton extends DisguiseMutable
|
||||
{
|
||||
private static final int SKELETON_ID = 51;
|
||||
private static final int WITHER_SKELETON_ID = 5;
|
||||
|
||||
private SkeletonType type = SkeletonType.NORMAL;
|
||||
|
||||
public DisguiseSkeleton(org.bukkit.entity.Entity entity)
|
||||
{
|
||||
super(EntityType.SKELETON, entity);
|
||||
@ -17,15 +22,24 @@ public class DisguiseSkeleton extends DisguiseMonster
|
||||
public void SetSkeletonType(SkeletonType skeletonType)
|
||||
{
|
||||
DataWatcher.watch(13, Byte.valueOf((byte) skeletonType.getId()), EntitySkeleton.META_TYPE, skeletonType.getId());
|
||||
this.type = skeletonType;
|
||||
mutate();
|
||||
}
|
||||
|
||||
public int GetSkeletonType()
|
||||
public SkeletonType getSkeletonType()
|
||||
{
|
||||
return DataWatcher.getByte(13);
|
||||
return type;
|
||||
}
|
||||
|
||||
protected String getHurtSound()
|
||||
{
|
||||
return "mob.skeleton.hurt";
|
||||
}
|
||||
|
||||
// 1.11 and up require separate entity ids
|
||||
@Override
|
||||
protected int getTypeId(boolean separate)
|
||||
{
|
||||
return separate && type == SkeletonType.WITHER ? WITHER_SKELETON_ID : SKELETON_ID;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user