wip: cinematic system
Some checks failed
Build / build (push) Failing after 11m33s
Format / formatting (push) Failing after 5m6s

This commit is contained in:
unurled 2024-11-10 15:30:51 +01:00
parent 41ae6a2572
commit 05d32c63f5
Signed by: unurled
GPG key ID: EFC5F5E709B47DDD
9 changed files with 289 additions and 8 deletions

View file

@ -1,5 +1,8 @@
package me.unurled.sacredrealms.sr.components.cutscene;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import me.unurled.sacredrealms.sr.SR;
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recording;
import me.unurled.sacredrealms.sr.components.cutscene.tasks.ReplayTask;
@ -12,10 +15,12 @@ public class Replay {
private final Player viewer;
private final Recording recording;
private final BukkitTask replayTask;
private final Map<UUID, Integer> spawnedEntities;
public Replay(Recording recording, @NotNull Player viewer) {
this.recording = recording;
this.viewer = viewer;
spawnedEntities = new HashMap<>();
viewer.getInventory().clear();
// TODO: control cutscene replay
@ -42,4 +47,8 @@ public class Replay {
replayTask.cancel();
}
}
public Map<UUID, Integer> spawnedEntities() {
return spawnedEntities;
}
}

View file

@ -1,9 +1,12 @@
package me.unurled.sacredrealms.sr.components.cutscene.recording;
import com.github.retrooper.packetevents.protocol.player.User;
import me.unurled.sacredrealms.sr.components.cutscene.Replay;
public abstract class Recordable {
private long tick;
public abstract void replay();
public abstract void replay(Replay replay, User user) throws Exception;
public long tick() {
return tick;

View file

@ -1,7 +1,11 @@
package me.unurled.sacredrealms.sr.components.cutscene.recording.recordables;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDestroyEntities;
import java.util.UUID;
import me.unurled.sacredrealms.sr.components.cutscene.Replay;
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable;
import org.jetbrains.annotations.NotNull;
public class DespawnEntityRecordable extends Recordable {
@ -14,8 +18,11 @@ public class DespawnEntityRecordable extends Recordable {
}
@Override
public void replay() {
// TODO: fake spawn entity
public void replay(@NotNull Replay replay, @NotNull User user) throws Exception {
WrapperPlayServerDestroyEntities destroyEntities =
new WrapperPlayServerDestroyEntities(replay.spawnedEntities().get(entityId));
user.sendPacket(destroyEntities);
replay.spawnedEntities().remove(entityId);
}
public UUID entityId() {

View file

@ -1,6 +1,8 @@
package me.unurled.sacredrealms.sr.components.cutscene.recording.recordables;
import com.github.retrooper.packetevents.protocol.player.User;
import java.util.UUID;
import me.unurled.sacredrealms.sr.components.cutscene.Replay;
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable;
import org.bukkit.Location;
@ -17,7 +19,7 @@ public class LocationChangeRecordable extends Recordable {
}
@Override
public void replay() {}
public void replay(Replay replay, User user) throws Exception {}
public UUID entityId() {
return entityId;

View file

@ -1,8 +1,20 @@
package me.unurled.sacredrealms.sr.components.cutscene.recording.recordables;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.protocol.player.UserProfile;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoUpdate;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnPlayer;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import java.lang.reflect.Field;
import java.util.EnumSet;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import me.unurled.sacredrealms.sr.components.cutscene.Replay;
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable;
import net.kyori.adventure.text.Component;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@ -33,8 +45,49 @@ public class SpawnEntityRecordable extends Recordable {
}
@Override
public void replay() {
// TODO: fake spawn entity
public void replay(Replay replay, User user) throws Exception { // TODO: check everything
Class<?> entityClass = Class.forName("net.minecraft.world.entity.Entity");
Field field = entityClass.getDeclaredField("ENTITY_COUNTER");
field.setAccessible(true);
AtomicInteger ENTITY_COUNTER = (AtomicInteger) field.get(null);
int id = ENTITY_COUNTER.incrementAndGet();
if (entityType == EntityType.PLAYER) {
WrapperPlayServerPlayerInfoUpdate.PlayerInfo data =
new WrapperPlayServerPlayerInfoUpdate.PlayerInfo(
new UserProfile(entityId, name.toString()),
false,
0,
SpigotConversionUtil.fromBukkitGameMode(GameMode.SURVIVAL),
name,
null);
user.sendPacket(
new WrapperPlayServerPlayerInfoUpdate(
EnumSet.of(WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER), data));
user.sendPacket(
new WrapperPlayServerSpawnPlayer(
id, entityId, SpigotConversionUtil.fromBukkitLocation(location)));
replay.spawnedEntities().put(entityId, id);
} else {
com.github.retrooper.packetevents.protocol.entity.type.EntityType entityType1 =
EntityTypes.getByName(entityType.getKey().toString());
WrapperPlayServerSpawnEntity spawnEntityPacket =
new WrapperPlayServerSpawnEntity(
id,
UUID.randomUUID(),
entityType1,
SpigotConversionUtil.fromBukkitLocation(location),
0,
0,
null);
user.sendPacket(spawnEntityPacket);
replay.spawnedEntities().put(entityId, id);
}
}
public EntityType entityType() {

View file

@ -3,20 +3,25 @@ package me.unurled.sacredrealms.sr.components.cutscene.tasks;
import static me.unurled.sacredrealms.sr.utils.Logger.error;
import static me.unurled.srcore.utils.Component.textComp;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.protocol.player.User;
import me.unurled.sacredrealms.sr.components.cutscene.Replay;
import me.unurled.sacredrealms.sr.components.cutscene.ReplayManager;
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable;
import me.unurled.srcore.api.Manager;
import org.jetbrains.annotations.NotNull;
public class ReplayTask implements Runnable {
private final Replay replay;
private final ReplayManager rm;
private final User user;
private long currentTick = 0;
public ReplayTask(Replay replay) {
public ReplayTask(@NotNull Replay replay) {
this.replay = replay;
rm = Manager.getInstance(ReplayManager.class);
this.user = PacketEvents.getAPI().getPlayerManager().getUser(replay.viewer());
}
@Override
@ -38,7 +43,7 @@ public class ReplayTask implements Runnable {
for (Recordable r : recordables) {
// figure out how to replay a recordable
r.replay();
r.replay(replay, user);
}
} catch (Exception e) {
error("Tick: " + currentTick);

View file

@ -0,0 +1,107 @@
package me.unurled.sacredrealms.sr.components.pointer;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.BlockState;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.joml.Vector3f;
// TODO: test this
public class DisplayForPlayer implements Runnable {
private static final int RENDER_DISTANCE_BLOCKS = 128;
private final Pointer pointer;
private final Player player;
private final User user;
public DisplayForPlayer(Pointer pointer, Player player) {
this.pointer = pointer;
this.player = player;
this.user = PacketEvents.getAPI().getPlayerManager().getUser(player);
}
public static Location getLocationInRange(@NotNull Player player, Location targetLocation) {
Location playerLocation = player.getLocation();
// Calculate the distance between player and target location
double distance = playerLocation.distance(targetLocation);
// If the location is within the render distance, return the original location
if (distance <= RENDER_DISTANCE_BLOCKS) {
return targetLocation;
}
// If the location is out of range, calculate a new location within the render distance
// Calculate the direction vector from the player to the target
Location direction =
targetLocation
.clone()
.subtract(playerLocation)
.toVector()
.normalize()
.toLocation(player.getWorld());
// Create a new location within the render distance pointing towards the target location
return playerLocation.clone().add(direction.multiply(RENDER_DISTANCE_BLOCKS));
}
@Override
public void run() {
// get difference between player loc and pointer loc, if it is too large then set pointer
// blockdisplay's location to in range of player
Location location = getLocationInRange(player, pointer.location());
WrapperPlayServerSpawnEntity packet =
new WrapperPlayServerSpawnEntity(
pointer.entityId(),
pointer.entityUUID(),
SpigotConversionUtil.fromBukkitEntityType(EntityType.BLOCK_DISPLAY),
SpigotConversionUtil.fromBukkitLocation(location),
0,
0,
null);
user.sendPacket(packet);
List<EntityData> list = new ArrayList<>();
BlockState ironBar =
player
.getWorld()
.getBlockAt(new Location(player.getWorld(), 0, 0, 0))
.getState()
.getBlockData()
.createBlockState();
ironBar.setType(Material.IRON_BARS);
// make it iron bars
EntityData data = new EntityData(23, EntityDataTypes.BLOCK_STATE, ironBar);
list.add(data);
// scale
EntityData data2 = new EntityData(12, EntityDataTypes.VECTOR3F, new Vector3f(2, 150, 2));
list.add(data2);
// glowing
EntityData glowing = new EntityData(0, EntityDataTypes.BYTE, (byte) 0x40);
list.add(glowing);
WrapperPlayServerEntityMetadata packet1 =
new WrapperPlayServerEntityMetadata(pointer.entityId(), list);
user.sendPacket(packet1);
}
}

View file

@ -0,0 +1,54 @@
package me.unurled.sacredrealms.sr.components.pointer;
import java.util.UUID;
import org.bukkit.Location;
import org.bukkit.entity.BlockDisplay;
public class Pointer {
private final Location location;
private final int entityId;
private BlockDisplay display;
private UUID entityUUID;
private Location entityLocation;
public Pointer(int entityId, Location location) {
this.entityId = entityId;
this.location = location;
}
public Location location() {
return location;
}
public int entityId() {
return entityId;
}
public BlockDisplay display() {
return display;
}
public Pointer setDisplay(BlockDisplay display) {
this.display = display;
return this;
}
public UUID entityUUID() {
return entityUUID;
}
public Pointer setEntityUUID(UUID entityUUID) {
this.entityUUID = entityUUID;
return this;
}
public Location entityLocation() {
return entityLocation;
}
public Pointer setEntityLocation(Location entityLocation) {
this.entityLocation = entityLocation;
return this;
}
}

View file

@ -0,0 +1,41 @@
package me.unurled.sacredrealms.sr.components.pointer;
import static me.unurled.sacredrealms.sr.utils.Logger.error;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import me.unurled.sacredrealms.sr.SR;
import me.unurled.srcore.api.Manager;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
public class PointerManager extends Manager {
private final Map<UUID, BukkitTask> tasks = new HashMap<>();
public void startPointing(Player player, Location location) {
int id = -1;
try {
Class<?> entityClass = Class.forName("net.minecraft.world.entity.Entity");
Field field = entityClass.getDeclaredField("ENTITY_COUNTER");
field.setAccessible(true);
AtomicInteger ENTITY_COUNTER = (AtomicInteger) field.get(null);
id = ENTITY_COUNTER.incrementAndGet();
} catch (Exception e) {
error("Failed to find Entity counter field in nms.");
}
if (id == -1) {
return;
}
Pointer pointer = new Pointer(id, location);
DisplayForPlayer task = new DisplayForPlayer(pointer, player);
BukkitTask btask =
Bukkit.getScheduler().runTaskTimerAsynchronously(SR.getPlugin(), task, 0, 5L);
tasks.put(player.getUniqueId(), btask);
}
}