Skip to content

Commit

Permalink
fix inventory updates when reversing
Browse files Browse the repository at this point in the history
  • Loading branch information
Jumper251 committed Nov 18, 2024
1 parent af8779d commit ee4fdb0
Showing 1 changed file with 94 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ public class ReplayingUtils {
private Map<String, SignatureData> signatures;

private Deque<ActionData> lastSpawnActions;

private Map<String, Deque<InvData>> lastInventoryActions;

private HashMap<Integer, Entity> itemEntities;

private HashMap<Integer, Integer> hooks;
Expand All @@ -55,6 +56,8 @@ public ReplayingUtils(Replayer replayer) {
this.tnt = new ArrayList<Integer>();

this.lastSpawnActions = new ArrayDeque<>();
this.lastInventoryActions = new HashMap<>();

this.signatures = new HashMap<>();
}

Expand Down Expand Up @@ -168,100 +171,91 @@ public void handleAction(ActionData action, ReplayData data, ReplayingMode mode)

if (action.getPacketData() instanceof InvData) {
InvData invData = (InvData) action.getPacketData();

if (!VersionUtil.isCompatible(VersionEnum.V1_8)) {

List<WrapperPlayServerEntityEquipment> equipment = VersionUtil.isBelow(VersionEnum.V1_15) ? NPCManager.updateEquipment(npc.getId(), invData) : NPCManager.updateEquipmentv16(npc.getId(), invData);
npc.setLastEquipment(equipment);

for (WrapperPlayServerEntityEquipment packet : equipment) {
packet.sendPacket(replayer.getWatchingPlayer());
}
if (!reversed) {
lastInventoryActions.computeIfAbsent(action.getName(), k -> new ArrayDeque<>()).addLast(invData);
} else {
List<com.comphenix.packetwrapper.old.WrapperPlayServerEntityEquipment> equipment = NPCManager.updateEquipmentOld(npc.getId(), invData);
PacketNPCOld oldNPC = (PacketNPCOld) npc;
oldNPC.setLastEquipmentOld(equipment);

for (com.comphenix.packetwrapper.old.WrapperPlayServerEntityEquipment packet : equipment) {
packet.sendPacket(replayer.getWatchingPlayer());
if (lastInventoryActions.containsKey(action.getName())) {
lastInventoryActions.get(action.getName()).pollLast();
}
}

playInvUpdate(npc, invData);
}

if (action.getPacketData() instanceof MetadataUpdate) {
MetadataUpdate update = (MetadataUpdate) action.getPacketData();

data.getWatcher(action.getName()).setBurning(!reversed ? update.isBurning() : false);
data.getWatcher(action.getName()).setBlocking(!reversed ? update.isBlocking() : false);
data.getWatcher(action.getName()).setElytra(!reversed ? update.isGliding() : false);
data.getWatcher(action.getName()).setSwimming(!reversed ? update.isSwimming() : false);

WrappedDataWatcher dataWatcher = data.getWatcher(action.getName()).getMetadata(new MetadataBuilder(npc.getData()));
npc.setData(dataWatcher);

npc.updateMetadata();


}

if (action.getPacketData() instanceof ProjectileData) {
ProjectileData projectile = (ProjectileData) action.getPacketData();

spawnProjectile(projectile, null, replayer.getWatchingPlayer().getWorld(), 0);
}

if (action.getPacketData() instanceof BlockChangeData) {
BlockChangeData blockChange = (BlockChangeData) action.getPacketData();

if (reversed) {
blockChange = new BlockChangeData(blockChange.getLocation(), blockChange.getAfter(), blockChange.getBefore());
blockChange.setDoBlockChange(true);
}

setBlockChange(blockChange);
}


if (action.getPacketData() instanceof BedEnterData) {
BedEnterData bed = (BedEnterData) action.getPacketData();

if (VersionUtil.isAbove(VersionEnum.V1_14)) {
npc.teleport(LocationData.toLocation(bed.getLocation()), true);

npc.setData(new MetadataBuilder(npc.getData())
.setPoseField("SLEEPING")
.getData());

npc.updateMetadata();
npc.teleport(LocationData.toLocation(bed.getLocation()), true);


} else {
npc.sleep(LocationData.toLocation(bed.getLocation()));
}
}

if (action.getPacketData() instanceof EntityItemData) {
EntityItemData entityData = (EntityItemData) action.getPacketData();

if (entityData.getAction() == 0 && !reversed) {
spawnItemStack(entityData);
} else if (entityData.getAction() == 1) {
despawnItem(entityData);
} else {
if (hooks.containsKey(entityData.getId())) {
despawn(null, new int[]{hooks.get(entityData.getId())});

hooks.remove(entityData.getId());
}

despawnItem(entityData);
}
}

if (action.getPacketData() instanceof EntityData) {
EntityData entityData = (EntityData) action.getPacketData();

if (entityData.getAction() == 0) {
if (!reversed) {
IEntity entity = VersionUtil.isCompatible(VersionEnum.V1_8) ? new PacketEntityOld(EntityType.valueOf(entityData.getType())) : new PacketEntity(EntityType.valueOf(entityData.getType()));
Expand All @@ -270,9 +264,9 @@ public void handleAction(ActionData action, ReplayData data, ReplayingMode mode)
} else if (replayer.getEntityList().containsKey(entityData.getId())) {
IEntity ent = replayer.getEntityList().get(entityData.getId());
ent.remove();

}

} else if (entityData.getAction() == 1) {
if (!reversed && replayer.getEntityList().containsKey(entityData.getId())) {
IEntity ent = replayer.getEntityList().get(entityData.getId());
Expand All @@ -284,94 +278,94 @@ public void handleAction(ActionData action, ReplayData data, ReplayingMode mode)
}
}
}

if (action.getPacketData() instanceof EntityMovingData) {
EntityMovingData entityMoving = (EntityMovingData) action.getPacketData();
if (replayer.getEntityList().containsKey(entityMoving.getId())) {
IEntity ent = replayer.getEntityList().get(entityMoving.getId());

if (VersionUtil.isAbove(VersionEnum.V1_15) || VersionUtil.isCompatible(VersionEnum.V1_8)) {
ent.move(new Location(ent.getOrigin().getWorld(), entityMoving.getX(), entityMoving.getY(), entityMoving.getZ()), true, entityMoving.getYaw(), entityMoving.getPitch());
}

if (VersionUtil.isBetween(VersionEnum.V1_9, VersionEnum.V1_14)) {
ent.teleport(new Location(ent.getOrigin().getWorld(), entityMoving.getX(), entityMoving.getY(), entityMoving.getZ()), true);
ent.look(entityMoving.getYaw(), entityMoving.getPitch());
}

}
}

if (action.getPacketData() instanceof EntityAnimationData) {
EntityAnimationData entityAnimating = (EntityAnimationData) action.getPacketData();
if (replayer.getEntityList().containsKey(entityAnimating.getEntId()) && !reversed) {

IEntity ent = replayer.getEntityList().get(entityAnimating.getEntId());
ent.animate(entityAnimating.getId());
}
}

if (action.getPacketData() instanceof WorldChangeData) {
WorldChangeData worldChange = (WorldChangeData) action.getPacketData();
if (!worldChange.getLocation().isValidWorld()) {
LogUtils.log("Skipping invalid world: " + worldChange.getLocation().getWorld());
return;
}
Location loc = LocationData.toLocation(worldChange.getLocation());

npc.despawn();
npc.setOrigin(loc);
npc.setLocation(loc);

npc.respawn(replayer.getWatchingPlayer());

}

if (action.getPacketData() instanceof FishingData) {
FishingData fishing = (FishingData) action.getPacketData();
int ownerId = replayer.getNPCList().getOrDefault(fishing.getOwner(), npc).getId();

if (mode == ReplayingMode.PLAYING) {
spawnProjectile(null, fishing, replayer.getWatchingPlayer().getWorld(), ownerId);
}

if (reversed && hooks.containsKey(fishing.getId())) {
despawn(null, new int[]{hooks.get(fishing.getId())});
hooks.remove(fishing.getId());

}
}

if (action.getPacketData() instanceof VelocityData) {
VelocityData velocity = (VelocityData) action.getPacketData();
int entID = -1;
if (hooks.containsKey(velocity.getId())) entID = hooks.get(velocity.getId());
else if (tnt.contains(velocity.getId())) entID = velocity.getId();
else if (replayer.getEntityList().containsKey(velocity.getId()))
entID = replayer.getEntityList().get(velocity.getId()).getId();

if (entID != -1) {
WrapperPlayServerEntityVelocity packet = new WrapperPlayServerEntityVelocity();
packet.setEntityID(entID);
packet.setVelocityX(velocity.getX());
packet.setVelocityY(velocity.getY());
packet.setVelocityZ(velocity.getZ());

packet.sendPacket(replayer.getWatchingPlayer());
}

}
}

if (action.getType() == ActionType.DESPAWN || action.getType() == ActionType.DEATH) {
if (!reversed && replayer.getNPCList().containsKey(action.getName())) {
INPC npc = this.replayer.getNPCList().get(action.getName());
npc.remove();
replayer.getNPCList().remove(action.getName());

SpawnData oldSpawnData = new SpawnData(npc.getUuid(), LocationData.fromLocation(npc.getLocation()), signatures.get(action.getName()));
this.lastSpawnActions.addLast(new ActionData(0, ActionType.SPAWN, action.getName(), oldSpawnData));

if (action.getType() == ActionType.DESPAWN) {
replayer.sendMessage(new MessageBuilder(ConfigManager.LEAVE_MESSAGE)
.set("name", action.getName())
Expand All @@ -381,18 +375,20 @@ else if (replayer.getEntityList().containsKey(velocity.getId()))
.set("name", action.getName())
.build());
}

} else {

if (!this.lastSpawnActions.isEmpty()) {
spawnNPC(this.lastSpawnActions.pollLast());
}

}

}
}



private void despawnItem(EntityItemData entityData) {
if (itemEntities.containsKey(entityData.getId())) {
despawn(Arrays.asList(itemEntities.get(entityData.getId())), null);
Expand Down Expand Up @@ -434,6 +430,8 @@ public void backward() {
for (int i = currentTick; i > backwardTicks; i--) {
this.replayer.executeTick(i, ReplayingMode.REVERSED);
}

sendLastInvAction();
this.replayer.setCurrentTicks(backwardTicks);
this.replayer.setPaused(paused);
}
Expand Down Expand Up @@ -539,6 +537,37 @@ private void spawnTNT(TNTSpawnData tntSpawnData) {
tnt.add(tntSpawnData.getId());
}
}

private void playInvUpdate(INPC npc, InvData invData) {
if (!VersionUtil.isCompatible(VersionEnum.V1_8)) {

List<WrapperPlayServerEntityEquipment> equipment = VersionUtil.isBelow(VersionEnum.V1_15) ? NPCManager.updateEquipment(npc.getId(), invData) : NPCManager.updateEquipmentv16(npc.getId(), invData);
npc.setLastEquipment(equipment);

for (WrapperPlayServerEntityEquipment packet : equipment) {
packet.sendPacket(replayer.getWatchingPlayer());
}
} else {
List<com.comphenix.packetwrapper.old.WrapperPlayServerEntityEquipment> equipment = NPCManager.updateEquipmentOld(npc.getId(), invData);
PacketNPCOld oldNPC = (PacketNPCOld) npc;
oldNPC.setLastEquipmentOld(equipment);

for (com.comphenix.packetwrapper.old.WrapperPlayServerEntityEquipment packet : equipment) {
packet.sendPacket(replayer.getWatchingPlayer());
}
}
}

private void sendLastInvAction() {
for (INPC npc : replayer.getNPCList().values()) {
if (lastInventoryActions.containsKey(npc.getName())) {
Deque<InvData> invData = lastInventoryActions.get(npc.getName());
if (!invData.isEmpty()) {
playInvUpdate(npc, invData.peekLast());
}
}
}
}

private void spawnProjectile(ProjectileData projData, FishingData fishing, World world, int id) {
if (projData != null && projData.getType() != EntityBridge.FISHING_BOBBER.toEntityType()) {
Expand Down

0 comments on commit ee4fdb0

Please sign in to comment.