wip: cinematic system
This commit is contained in:
parent
41ae6a2572
commit
05d32c63f5
9 changed files with 289 additions and 8 deletions
|
@ -1,5 +1,8 @@
|
||||||
package me.unurled.sacredrealms.sr.components.cutscene;
|
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.SR;
|
||||||
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recording;
|
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recording;
|
||||||
import me.unurled.sacredrealms.sr.components.cutscene.tasks.ReplayTask;
|
import me.unurled.sacredrealms.sr.components.cutscene.tasks.ReplayTask;
|
||||||
|
@ -12,10 +15,12 @@ public class Replay {
|
||||||
private final Player viewer;
|
private final Player viewer;
|
||||||
private final Recording recording;
|
private final Recording recording;
|
||||||
private final BukkitTask replayTask;
|
private final BukkitTask replayTask;
|
||||||
|
private final Map<UUID, Integer> spawnedEntities;
|
||||||
|
|
||||||
public Replay(Recording recording, @NotNull Player viewer) {
|
public Replay(Recording recording, @NotNull Player viewer) {
|
||||||
this.recording = recording;
|
this.recording = recording;
|
||||||
this.viewer = viewer;
|
this.viewer = viewer;
|
||||||
|
spawnedEntities = new HashMap<>();
|
||||||
|
|
||||||
viewer.getInventory().clear();
|
viewer.getInventory().clear();
|
||||||
// TODO: control cutscene replay
|
// TODO: control cutscene replay
|
||||||
|
@ -42,4 +47,8 @@ public class Replay {
|
||||||
replayTask.cancel();
|
replayTask.cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<UUID, Integer> spawnedEntities() {
|
||||||
|
return spawnedEntities;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
package me.unurled.sacredrealms.sr.components.cutscene.recording;
|
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 {
|
public abstract class Recordable {
|
||||||
private long tick;
|
private long tick;
|
||||||
|
|
||||||
public abstract void replay();
|
public abstract void replay(Replay replay, User user) throws Exception;
|
||||||
|
|
||||||
public long tick() {
|
public long tick() {
|
||||||
return tick;
|
return tick;
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
package me.unurled.sacredrealms.sr.components.cutscene.recording.recordables;
|
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 java.util.UUID;
|
||||||
|
import me.unurled.sacredrealms.sr.components.cutscene.Replay;
|
||||||
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable;
|
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class DespawnEntityRecordable extends Recordable {
|
public class DespawnEntityRecordable extends Recordable {
|
||||||
|
|
||||||
|
@ -14,8 +18,11 @@ public class DespawnEntityRecordable extends Recordable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void replay() {
|
public void replay(@NotNull Replay replay, @NotNull User user) throws Exception {
|
||||||
// TODO: fake spawn entity
|
WrapperPlayServerDestroyEntities destroyEntities =
|
||||||
|
new WrapperPlayServerDestroyEntities(replay.spawnedEntities().get(entityId));
|
||||||
|
user.sendPacket(destroyEntities);
|
||||||
|
replay.spawnedEntities().remove(entityId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID entityId() {
|
public UUID entityId() {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package me.unurled.sacredrealms.sr.components.cutscene.recording.recordables;
|
package me.unurled.sacredrealms.sr.components.cutscene.recording.recordables;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.protocol.player.User;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import me.unurled.sacredrealms.sr.components.cutscene.Replay;
|
||||||
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable;
|
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
|
||||||
|
@ -17,7 +19,7 @@ public class LocationChangeRecordable extends Recordable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void replay() {}
|
public void replay(Replay replay, User user) throws Exception {}
|
||||||
|
|
||||||
public UUID entityId() {
|
public UUID entityId() {
|
||||||
return entityId;
|
return entityId;
|
||||||
|
|
|
@ -1,8 +1,20 @@
|
||||||
package me.unurled.sacredrealms.sr.components.cutscene.recording.recordables;
|
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.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 me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.EntityType;
|
import org.bukkit.entity.EntityType;
|
||||||
|
@ -33,8 +45,49 @@ public class SpawnEntityRecordable extends Recordable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void replay() {
|
public void replay(Replay replay, User user) throws Exception { // TODO: check everything
|
||||||
// TODO: fake spawn entity
|
|
||||||
|
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() {
|
public EntityType entityType() {
|
||||||
|
|
|
@ -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.sacredrealms.sr.utils.Logger.error;
|
||||||
import static me.unurled.srcore.utils.Component.textComp;
|
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.Replay;
|
||||||
import me.unurled.sacredrealms.sr.components.cutscene.ReplayManager;
|
import me.unurled.sacredrealms.sr.components.cutscene.ReplayManager;
|
||||||
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable;
|
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable;
|
||||||
import me.unurled.srcore.api.Manager;
|
import me.unurled.srcore.api.Manager;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class ReplayTask implements Runnable {
|
public class ReplayTask implements Runnable {
|
||||||
|
|
||||||
private final Replay replay;
|
private final Replay replay;
|
||||||
private final ReplayManager rm;
|
private final ReplayManager rm;
|
||||||
|
private final User user;
|
||||||
private long currentTick = 0;
|
private long currentTick = 0;
|
||||||
|
|
||||||
public ReplayTask(Replay replay) {
|
public ReplayTask(@NotNull Replay replay) {
|
||||||
this.replay = replay;
|
this.replay = replay;
|
||||||
rm = Manager.getInstance(ReplayManager.class);
|
rm = Manager.getInstance(ReplayManager.class);
|
||||||
|
this.user = PacketEvents.getAPI().getPlayerManager().getUser(replay.viewer());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -38,7 +43,7 @@ public class ReplayTask implements Runnable {
|
||||||
|
|
||||||
for (Recordable r : recordables) {
|
for (Recordable r : recordables) {
|
||||||
// figure out how to replay a recordable
|
// figure out how to replay a recordable
|
||||||
r.replay();
|
r.replay(replay, user);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
error("Tick: " + currentTick);
|
error("Tick: " + currentTick);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue