too many things, kinda forgor to push/commit
This commit is contained in:
parent
897edf1d37
commit
bb514f8a63
69 changed files with 1691 additions and 1256 deletions
17
.forgejo/workflows/format.yaml
Normal file
17
.forgejo/workflows/format.yaml
Normal file
|
@ -0,0 +1,17 @@
|
|||
name: Format
|
||||
|
||||
run-name: ${{ github.actor }} is formatting
|
||||
|
||||
on: [ push, pull_request ]
|
||||
|
||||
jobs:
|
||||
formatting:
|
||||
runs-on: docker
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: axel-op/googlejavaformat-action@v3
|
||||
with:
|
||||
args: "--replace"
|
||||
skip-commit: true
|
||||
- name: Print diffs
|
||||
run: git --no-pager diff --exit-code
|
|
@ -19,4 +19,6 @@ see [docs](https://git.unurled.me/SacredRealms/docs) for more information
|
|||
|
||||
- [Java 17](https://adoptium.net/temurin/releases/?version=17)
|
||||
- [PaperMC 1.20.6](https://papermc.io/downloads/paper) or any fork of it (purpur, etc)
|
||||
- a build of the plugin
|
||||
- a build of the plugin
|
||||
|
||||
spigot plugin development 90 replay plugin - 1:43:02
|
|
@ -2,7 +2,7 @@ import net.minecrell.pluginyml.bukkit.BukkitPluginDescription
|
|||
|
||||
plugins {
|
||||
`java-library`
|
||||
id("io.papermc.paperweight.userdev") version "1.7.2"
|
||||
id("io.papermc.paperweight.userdev") version "1.7.3"
|
||||
id("org.sonarqube") version "5.1.0.4882"
|
||||
id("net.minecrell.plugin-yml.paper") version "0.6.0"
|
||||
}
|
||||
|
@ -36,6 +36,10 @@ repositories {
|
|||
name = "unurled"
|
||||
url = uri("https://repo.unurled.me/releases")
|
||||
}
|
||||
maven {
|
||||
name = "cubbossa"
|
||||
url = uri("https://nexus.leonardbausenwein.de/repository/maven-releases/")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
@ -47,9 +51,9 @@ dependencies {
|
|||
|
||||
paperLibrary("redis.clients", "jedis", redisVersion)
|
||||
|
||||
paperLibrary("com.github.retrooper", "packetevents-spigot", "2.4.0")
|
||||
paperLibrary("com.github.retrooper", "packetevents-spigot", "2.5.0")
|
||||
|
||||
paperLibrary("me.unurled", "SR-Core", "0.1.0")
|
||||
compileOnly("me.unurled:SR-Core:0.1.1")
|
||||
}
|
||||
|
||||
java {
|
||||
|
@ -106,7 +110,7 @@ paper {
|
|||
"sr.resetadventure",
|
||||
"sr.treasure.manage",
|
||||
"sr.difficulty.*",
|
||||
"sr.cutscene"
|
||||
"sr.cutscene.*"
|
||||
)
|
||||
description = "Gives access to all Sacred Realms permissions."
|
||||
}
|
||||
|
@ -151,6 +155,10 @@ paper {
|
|||
}
|
||||
register("sr.cutscene") {
|
||||
description = "Gives access to the cutscene command."
|
||||
children = listOf(
|
||||
"sr.cutscene.create",
|
||||
"sr.cutscene.replay"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,6 +6,9 @@ import java.util.List;
|
|||
import me.unurled.sacredrealms.sr.components.block.BlockManager;
|
||||
import me.unurled.sacredrealms.sr.components.clientbuild.ClientBuildManager;
|
||||
import me.unurled.sacredrealms.sr.components.combat.CombatManager;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.CutsceneManager;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.RecordingManager;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.ReplayManager;
|
||||
import me.unurled.sacredrealms.sr.components.entity.EntityManager;
|
||||
import me.unurled.sacredrealms.sr.components.item.ItemManager;
|
||||
import me.unurled.sacredrealms.sr.components.npc.NPCManager;
|
||||
|
@ -31,6 +34,7 @@ public final class SR extends JavaPlugin {
|
|||
@Override
|
||||
public void onLoad() {
|
||||
PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this));
|
||||
PacketEvents.getAPI().getSettings().reEncodeByDefault(false).checkForUpdates(true);
|
||||
// On Bukkit, calling this here is essential, hence the name "load"
|
||||
PacketEvents.getAPI().load();
|
||||
}
|
||||
|
@ -39,10 +43,10 @@ public final class SR extends JavaPlugin {
|
|||
public void onEnable() {
|
||||
plugin = this;
|
||||
|
||||
SRCore.getInstance().setPlugin(this);
|
||||
|
||||
PacketEvents.getAPI().init();
|
||||
|
||||
SRCore.getInstance().setPlugin(this);
|
||||
|
||||
InvUI.getInstance().setPlugin(this);
|
||||
|
||||
SRCore.getInstance()
|
||||
|
@ -61,7 +65,10 @@ public final class SR extends JavaPlugin {
|
|||
ClientBuildManager.class,
|
||||
TreasureManager.class,
|
||||
BackgroundManager.class,
|
||||
ResourcePackManager.class));
|
||||
ResourcePackManager.class,
|
||||
CutsceneManager.class,
|
||||
RecordingManager.class,
|
||||
ReplayManager.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -25,6 +25,11 @@ public class SRLoader implements PluginLoader {
|
|||
resolver.addRepository(
|
||||
new RemoteRepository.Builder("invui", "default", "https://repo.xenondevs.xyz/releases/")
|
||||
.build());
|
||||
|
||||
resolver.addDependency(new Dependency(new DefaultArtifact("me.unurled:SR-Core:0.1.1"), null));
|
||||
resolver.addRepository(
|
||||
new RemoteRepository.Builder("srcore", "default", "https://repo.unurled.me/releases")
|
||||
.build());
|
||||
classpathBuilder.addLibrary(resolver);
|
||||
|
||||
PluginLibraries pluginLibraries = load();
|
||||
|
|
|
@ -11,12 +11,14 @@ import java.util.Collection;
|
|||
import java.util.List;
|
||||
import me.unurled.sacredrealms.sr.commands.admin.AttributeCommand;
|
||||
import me.unurled.sacredrealms.sr.commands.admin.ClientBuildCommand;
|
||||
import me.unurled.sacredrealms.sr.commands.admin.CutsceneCommand;
|
||||
import me.unurled.sacredrealms.sr.commands.admin.EntityTypeCommand;
|
||||
import me.unurled.sacredrealms.sr.commands.admin.ItemCommand;
|
||||
import me.unurled.sacredrealms.sr.commands.admin.LevelCommand;
|
||||
import me.unurled.sacredrealms.sr.commands.admin.SpawnEntityCommand;
|
||||
import me.unurled.sacredrealms.sr.commands.admin.TreasureCommand;
|
||||
import me.unurled.sacredrealms.sr.commands.admin.cutscene.CreateCutsceneCommand;
|
||||
import me.unurled.sacredrealms.sr.commands.admin.cutscene.RecordCutsceneCommand;
|
||||
import me.unurled.sacredrealms.sr.commands.admin.cutscene.StopRecordingCommand;
|
||||
import me.unurled.sacredrealms.sr.commands.player.DifficultyCommand;
|
||||
import me.unurled.sacredrealms.sr.commands.player.ResetAdventureCommand;
|
||||
import me.unurled.srcore.api.Manager;
|
||||
|
@ -51,7 +53,6 @@ public class CommandManager extends Manager {
|
|||
}
|
||||
|
||||
public static void loadCommands(BootstrapContext ctx) {
|
||||
|
||||
registerCommand("attributes", "Set the attributes of the player.", ctx, AttributeCommand.class);
|
||||
registerCommand(
|
||||
"clientbuild", "Set the client build of the player.", ctx, ClientBuildCommand.class);
|
||||
|
@ -66,6 +67,17 @@ public class CommandManager extends Manager {
|
|||
registerCommand(
|
||||
"difficulty", "Set the difficulty of the player.", ctx, DifficultyCommand.class);
|
||||
|
||||
registerCommand("cutscene", "Cutscene commands.", List.of("cs"), ctx, CutsceneCommand.class);
|
||||
registerCommand("createcustcene", "Create a new Cutscene", ctx, CreateCutsceneCommand.class);
|
||||
|
||||
registerCommand(
|
||||
"recordcutscene",
|
||||
"Record a cutscene entity movement and everything",
|
||||
ctx,
|
||||
RecordCutsceneCommand.class);
|
||||
registerCommand(
|
||||
"stopcutscene",
|
||||
"stop a record of a cutscene entity movement and everything",
|
||||
ctx,
|
||||
StopRecordingCommand.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package me.unurled.sacredrealms.sr.commands.admin;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.comp;
|
||||
import static me.unurled.srcore.utils.Component.comp;
|
||||
import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.syncSRToPlayer;
|
||||
|
||||
import io.papermc.paper.command.brigadier.BasicCommand;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package me.unurled.sacredrealms.sr.commands.admin;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.ERROR;
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
import static me.unurled.srcore.utils.Component.ERROR;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
import static me.unurled.sacredrealms.sr.utils.Logger.log;
|
||||
|
||||
import io.papermc.paper.command.brigadier.BasicCommand;
|
||||
|
|
|
@ -1,166 +0,0 @@
|
|||
package me.unurled.sacredrealms.sr.commands.admin;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
|
||||
import io.papermc.paper.command.brigadier.BasicCommand;
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.Cutscene;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.CutsceneManager;
|
||||
import me.unurled.srcore.api.Manager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CutsceneCommand implements BasicCommand {
|
||||
|
||||
private CutsceneManager cutsceneManager;
|
||||
|
||||
/**
|
||||
* Returns the permission for the root command used in {@link #canUse(CommandSender)} by default.
|
||||
*
|
||||
* @return the permission for the root command used in {@link #canUse(CommandSender)}
|
||||
*/
|
||||
@Override
|
||||
public @Nullable String permission() {
|
||||
return "cutscenes.admin";
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the command with the given {@link CommandSourceStack} and arguments.
|
||||
*
|
||||
* @param sender the commandSourceStack of the command
|
||||
* @param args the arguments of the command ignoring repeated spaces
|
||||
*/
|
||||
@Override
|
||||
public void execute(@NotNull CommandSourceStack sender, @NotNull String @NotNull [] args) {
|
||||
if (cutsceneManager == null) {
|
||||
cutsceneManager = Manager.getInstance(CutsceneManager.class);
|
||||
}
|
||||
// /cs stop, list, reload, play, create, remove
|
||||
if (args.length == 1) {
|
||||
if (args[0].equals("stop")) {
|
||||
if (sender.getSender() instanceof Player p) {
|
||||
cutsceneManager.stopCutscene(p);
|
||||
} else {
|
||||
sender
|
||||
.getSender()
|
||||
.sendMessage(
|
||||
textComp("<red>You must be a player to stop a cutscene. Use /cs stop <player>"));
|
||||
}
|
||||
} else if (args[0].equals("list")) {
|
||||
sender
|
||||
.getSender()
|
||||
.sendMessage(
|
||||
textComp("<yellow>Cutscenes: " + cutsceneManager.getCutscenesId().toString()));
|
||||
} else if (args[0].equals("reload")) {
|
||||
|
||||
}
|
||||
} else if (args.length == 2) {
|
||||
if (args[0].equals("play")) {
|
||||
if (sender.getSender() instanceof Player p) {
|
||||
Cutscene cutscene = cutsceneManager.getCutscene(args[1]);
|
||||
cutsceneManager.playCutscene(cutscene, p);
|
||||
} else {
|
||||
sender
|
||||
.getSender()
|
||||
.sendMessage(
|
||||
textComp(
|
||||
"<red>You must be a player to play a cutscene. Use /cs play <cutscene_id> <player>"));
|
||||
}
|
||||
} else if (args[0].equals("stop")) {
|
||||
Player p = Bukkit.getPlayer(args[1]);
|
||||
if (p != null) {
|
||||
cutsceneManager.stopCutscene(p);
|
||||
}
|
||||
} else if (args[0].equals("create")) {
|
||||
String name = args[1];
|
||||
cutsceneManager.createCutscene(name);
|
||||
sender.getSender().sendMessage(textComp("<green>Created cutscene " + name));
|
||||
} else if (args[0].equals("remove")) {
|
||||
String name = args[1];
|
||||
cutsceneManager.removeCutscene(name);
|
||||
sender.getSender().sendMessage(textComp("<red>Removed cutscene " + name));
|
||||
}
|
||||
} else if (args.length == 3) {
|
||||
if (args[0].equals("play")) {
|
||||
Player p = Bukkit.getPlayer(args[2]);
|
||||
if (p != null) {
|
||||
Cutscene cutscene = cutsceneManager.getCutscene(args[1]);
|
||||
cutsceneManager.playCutscene(cutscene, p);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sender
|
||||
.getSender()
|
||||
.sendMessage(
|
||||
textComp(
|
||||
"<yellow>Usage: /cs <play|stop|reload|list> <cutscene_id|player (only play and stop)> <player (only possible if play with an id before)>"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Suggests possible completions for the given command {@link CommandSourceStack} and arguments.
|
||||
*
|
||||
* @param sender the commandSourceStack of the command
|
||||
* @param args the arguments of the command including repeated spaces
|
||||
* @return a collection of suggestions
|
||||
*/
|
||||
@Override
|
||||
public @NotNull Collection<String> suggest(
|
||||
@NotNull CommandSourceStack sender, @NotNull String[] args) {
|
||||
if (cutsceneManager == null) {
|
||||
cutsceneManager = Manager.getInstance(CutsceneManager.class);
|
||||
}
|
||||
List<String> complete = new ArrayList<>();
|
||||
complete.add("stop");
|
||||
if (sender.getSender().hasPermission("cutscenes.admin")) {
|
||||
complete.add("play");
|
||||
complete.add("list");
|
||||
complete.add("reload");
|
||||
complete.add("create");
|
||||
complete.add("remove");
|
||||
}
|
||||
List<String> result = new ArrayList<>();
|
||||
if (args.length == 1) {
|
||||
for (String s : complete) {
|
||||
if (s.toLowerCase().startsWith(args[0].toLowerCase())) {
|
||||
result.add(s);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} else if (args.length == 2) {
|
||||
if (sender.getSender().hasPermission("cutscenes.admin")) {
|
||||
if (args[0].equalsIgnoreCase("stop")) {
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
if (p.getName().toLowerCase().startsWith(args[1].toLowerCase())) {
|
||||
result.add(p.getName());
|
||||
}
|
||||
}
|
||||
} else if (args[0].equalsIgnoreCase("play") || args[0].equalsIgnoreCase("remove")) {
|
||||
for (String s : cutsceneManager.getCutscenesId()) {
|
||||
if (s.toLowerCase().startsWith(args[1].toLowerCase())) {
|
||||
result.add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} else if (args.length == 3) {
|
||||
if (sender.getSender().hasPermission("cutscenes.admin")) {
|
||||
if (args[0].equalsIgnoreCase("play")) {
|
||||
for (Player p : Bukkit.getOnlinePlayers()) {
|
||||
if (p.getName().toLowerCase().startsWith(args[2].toLowerCase())) {
|
||||
result.add(p.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return List.of();
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
package me.unurled.sacredrealms.sr.commands.admin;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.NOT_PLAYER;
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.comp;
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
import static me.unurled.srcore.utils.Component.NOT_PLAYER;
|
||||
import static me.unurled.srcore.utils.Component.comp;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import io.papermc.paper.command.brigadier.BasicCommand;
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package me.unurled.sacredrealms.sr.commands.admin;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.comp;
|
||||
import static me.unurled.srcore.utils.Component.comp;
|
||||
import static me.unurled.sacredrealms.sr.utils.Logger.error;
|
||||
|
||||
import io.papermc.paper.command.brigadier.BasicCommand;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package me.unurled.sacredrealms.sr.commands.admin;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.NO_PERMISSION;
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
import static me.unurled.srcore.utils.Component.NO_PERMISSION;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import io.papermc.paper.command.brigadier.BasicCommand;
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package me.unurled.sacredrealms.sr.commands.admin;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.NOT_PLAYER;
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
import static me.unurled.srcore.utils.Component.NOT_PLAYER;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import io.papermc.paper.command.brigadier.BasicCommand;
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
package me.unurled.sacredrealms.sr.commands.admin.cutscene;
|
||||
|
||||
import static me.unurled.srcore.utils.Component.NOT_PLAYER;
|
||||
import static me.unurled.srcore.utils.Component.NO_PERMISSION;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import io.papermc.paper.command.brigadier.BasicCommand;
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.CutsceneManager;
|
||||
import me.unurled.srcore.api.Manager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class CreateCutsceneCommand implements BasicCommand {
|
||||
|
||||
private CutsceneManager cm;
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull CommandSourceStack sender, String[] args) {
|
||||
if (!(sender.getSender() instanceof Player p)) {
|
||||
sender.getSender().sendMessage(textComp(NOT_PLAYER));
|
||||
return;
|
||||
}
|
||||
if (!p.hasPermission("sr.cutscene.create")) {
|
||||
p.sendMessage(textComp(NO_PERMISSION));
|
||||
return;
|
||||
}
|
||||
// get the name
|
||||
if (args.length < 1) {
|
||||
p.sendMessage("Usage: /cs <name>");
|
||||
return;
|
||||
}
|
||||
String name = args[0];
|
||||
// create the cutscene
|
||||
|
||||
if (cm == null) {
|
||||
cm = Manager.getInstance(CutsceneManager.class);
|
||||
}
|
||||
|
||||
cm.startCreatingCutscene(p, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> suggest(
|
||||
CommandSourceStack commandSourceStack, String @NotNull [] args) {
|
||||
if (args.length == 1) {
|
||||
return List.of("name");
|
||||
}
|
||||
return BasicCommand.super.suggest(commandSourceStack, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package me.unurled.sacredrealms.sr.commands.admin.cutscene;
|
||||
|
||||
import static me.unurled.srcore.utils.Component.NO_PERMISSION;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import io.papermc.paper.command.brigadier.BasicCommand;
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.Cutscene;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.CutsceneManager;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.RecordingManager;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recording;
|
||||
import me.unurled.srcore.api.Manager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class RecordCutsceneCommand implements BasicCommand {
|
||||
|
||||
private RecordingManager rm;
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull CommandSourceStack stack, String[] args) {
|
||||
if (!(stack.getSender() instanceof Player p)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!p.hasPermission("sr.cutscene.create")) {
|
||||
p.sendMessage(textComp(NO_PERMISSION));
|
||||
return;
|
||||
}
|
||||
|
||||
if (rm == null) {
|
||||
rm = Manager.getInstance(RecordingManager.class);
|
||||
}
|
||||
|
||||
Recording activeRecording = rm.getPlayerActiveRecording(p);
|
||||
if (activeRecording != null) {
|
||||
p.sendMessage("You are already recording a cutscene.");
|
||||
return;
|
||||
}
|
||||
|
||||
Cutscene cutscene =
|
||||
Manager.getInstance(CutsceneManager.class).getCutsceneBeingCreated(p.getUniqueId());
|
||||
if (cutscene == null) {
|
||||
p.sendMessage("You are not creating a cutscene.");
|
||||
return;
|
||||
}
|
||||
activeRecording = new Recording(cutscene, p);
|
||||
|
||||
// open menu for selection cutscene
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package me.unurled.sacredrealms.sr.commands.admin.cutscene;
|
||||
|
||||
import static me.unurled.srcore.utils.Component.NOT_PLAYER;
|
||||
import static me.unurled.srcore.utils.Component.NO_PERMISSION;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import io.papermc.paper.command.brigadier.BasicCommand;
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import java.util.Collection;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ReplayCommand implements BasicCommand {
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull CommandSourceStack stack, String[] args) {
|
||||
if (!(stack.getSender() instanceof Player p)) {
|
||||
stack.getSender().sendMessage(textComp(NOT_PLAYER));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!p.hasPermission("sr.cutscene.replay")) {
|
||||
p.sendMessage(textComp(NO_PERMISSION));
|
||||
}
|
||||
|
||||
// aaa
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> suggest(CommandSourceStack stack, String[] args) {
|
||||
return BasicCommand.super.suggest(stack, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package me.unurled.sacredrealms.sr.commands.admin.cutscene;
|
||||
|
||||
import static me.unurled.srcore.utils.Component.NOT_PLAYER;
|
||||
import static me.unurled.srcore.utils.Component.NO_PERMISSION;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import io.papermc.paper.command.brigadier.BasicCommand;
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
import java.util.Collection;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.RecordingManager;
|
||||
import me.unurled.srcore.api.Manager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class StopRecordingCommand implements BasicCommand {
|
||||
|
||||
@Override
|
||||
public void execute(@NotNull CommandSourceStack stack, String[] args) {
|
||||
if (!(stack.getSender() instanceof Player p)) {
|
||||
stack.getSender().sendMessage(textComp(NOT_PLAYER));
|
||||
return;
|
||||
}
|
||||
if (!p.hasPermission("sr.cutscene.create")) {
|
||||
p.sendMessage(textComp(NO_PERMISSION));
|
||||
return;
|
||||
}
|
||||
|
||||
Manager.getInstance(RecordingManager.class).stopRecording(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> suggest(CommandSourceStack commandSourceStack, String[] args) {
|
||||
return BasicCommand.super.suggest(commandSourceStack, args);
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
package me.unurled.sacredrealms.sr.commands.player;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.NOT_PLAYER;
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.NO_PERMISSION;
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.PLAYER_NOT_FOUND;
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
import static me.unurled.srcore.utils.Component.NOT_PLAYER;
|
||||
import static me.unurled.srcore.utils.Component.NO_PERMISSION;
|
||||
import static me.unurled.srcore.utils.Component.PLAYER_NOT_FOUND;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import io.papermc.paper.command.brigadier.BasicCommand;
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package me.unurled.sacredrealms.sr.commands.player;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.comp;
|
||||
import static me.unurled.srcore.utils.Component.comp;
|
||||
|
||||
import io.papermc.paper.command.brigadier.BasicCommand;
|
||||
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package me.unurled.sacredrealms.sr.components.block;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
import static me.unurled.sacredrealms.sr.utils.Logger.error;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package me.unurled.sacredrealms.sr.components.combat;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.comp;
|
||||
import static me.unurled.srcore.utils.Component.comp;
|
||||
import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.spawnIndicator;
|
||||
import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.updateActionBar;
|
||||
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene;
|
||||
|
||||
import java.util.List;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
public enum Action {
|
||||
IDLE(),
|
||||
MOVE(Location.class),
|
||||
TELEPORT(Location.class),
|
||||
SPAWN(Location.class),
|
||||
DESPAWN(),
|
||||
HIT(Entity.class),
|
||||
SNEAK(),
|
||||
JUMP(),
|
||||
PLACE(Location.class, BlockData.class),
|
||||
INTERACT(Location.class, org.bukkit.event.block.Action.class),
|
||||
BREAK(Location.class);
|
||||
|
||||
private final List<Class> types;
|
||||
|
||||
Action(Class... types) {
|
||||
this.types = List.of(types);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene;
|
||||
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
import static org.bukkit.Material.RED_WOOL;
|
||||
|
||||
import me.unurled.sacredrealms.sr.utils.Region;
|
||||
import me.unurled.sacredrealms.sr.utils.RegionUtil;
|
||||
import me.unurled.srcore.api.Manager;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class CreationListener implements Listener {
|
||||
|
||||
private CutsceneManager cm;
|
||||
|
||||
@EventHandler
|
||||
public void onInventoryClick(@NotNull InventoryClickEvent e) {
|
||||
if (e.getWhoClicked() instanceof Player p) {
|
||||
if (cm == null) {
|
||||
cm = Manager.getInstance(CutsceneManager.class);
|
||||
}
|
||||
|
||||
Cutscene cutscene = cm.getCutsceneBeingCreated(p.getUniqueId());
|
||||
if (cutscene == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onRightClick(@NotNull PlayerInteractEvent e) {
|
||||
if (!e.getAction().isRightClick()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player p = e.getPlayer();
|
||||
if (cm == null) {
|
||||
cm = Manager.getInstance(CutsceneManager.class);
|
||||
}
|
||||
|
||||
Cutscene cutscene = cm.getCutsceneBeingCreated(p.getUniqueId());
|
||||
|
||||
if (cutscene == null) {
|
||||
return;
|
||||
}
|
||||
e.setCancelled(true);
|
||||
|
||||
if (e.getItem() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (e.getItem().getType()) {
|
||||
case BARRIER -> {
|
||||
RegionUtil.killSelectorsWithTag(cutscene.name());
|
||||
cm.cancelCreatingCutscene(p);
|
||||
}
|
||||
case EMERALD_BLOCK -> {
|
||||
if (cutscene.pos1() == null) {
|
||||
p.sendMessage(textComp("<red>Pos1 not set. Click on Red Wool."));
|
||||
return;
|
||||
}
|
||||
if (cutscene.pos2() == null) {
|
||||
p.sendMessage(textComp("<red>Pos2 not set. Click on Blue Wool."));
|
||||
return;
|
||||
}
|
||||
cm.finishCreatingCutscene(p);
|
||||
RegionUtil.killSelectorsWithTag(cutscene.name());
|
||||
}
|
||||
case RED_WOOL, BLUE_WOOL -> {
|
||||
Location loc = null;
|
||||
if (e.getAction() == Action.RIGHT_CLICK_BLOCK && e.getClickedBlock() != null) {
|
||||
loc = e.getClickedBlock().getLocation();
|
||||
} else if (e.getAction() == Action.RIGHT_CLICK_AIR) {
|
||||
loc = e.getPlayer().getLocation();
|
||||
}
|
||||
if (e.getItem().getType() == RED_WOOL) {
|
||||
p.sendMessage(textComp("<green>Pos1 set."));
|
||||
cutscene.setPos1(loc);
|
||||
} else {
|
||||
p.sendMessage(textComp("<green>Pos2 set."));
|
||||
cutscene.setPos2(loc);
|
||||
}
|
||||
|
||||
if (cutscene.pos1() != null && cutscene.pos2() != null) {
|
||||
Region region = new Region();
|
||||
region.setCorner1(cutscene.pos1());
|
||||
region.setCorner2(cutscene.pos2());
|
||||
if (loc == null) return;
|
||||
RegionUtil.killSelectorsWithTag(cutscene.name());
|
||||
RegionUtil.drawSelector(region, loc.getWorld(), cutscene.name(), NamedTextColor.GREEN);
|
||||
p.sendMessage(
|
||||
textComp(
|
||||
"<green>You have set both corners! Right click the Emerald block to finish."));
|
||||
} else if (cutscene.pos1() != null && cutscene.pos2() == null) {
|
||||
Region region = new Region();
|
||||
region.setCorner1(cutscene.pos1());
|
||||
region.setCorner2(cutscene.pos1());
|
||||
if (loc == null) return;
|
||||
RegionUtil.killSelectorsWithTag(cutscene.name());
|
||||
RegionUtil.drawSelector(region, loc.getWorld(), cutscene.name(), NamedTextColor.YELLOW);
|
||||
} else if (cutscene.pos1() == null && cutscene.pos2() != null) {
|
||||
Region region = new Region();
|
||||
region.setCorner1(cutscene.pos2());
|
||||
region.setCorner2(cutscene.pos2());
|
||||
if (loc == null) return;
|
||||
RegionUtil.killSelectorsWithTag(cutscene.name());
|
||||
RegionUtil.drawSelector(region, loc.getWorld(), cutscene.name(), NamedTextColor.YELLOW);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,239 +1,80 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
import static me.unurled.sacredrealms.sr.utils.CutsceneUtil.showBlackScreen;
|
||||
import static me.unurled.sacredrealms.sr.utils.Logger.error;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import me.unurled.sacredrealms.sr.SR;
|
||||
import me.unurled.srcore.api.Manager;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Cutscene class
|
||||
*
|
||||
* <p>Represents a cutscene
|
||||
*
|
||||
* <pre>{@code
|
||||
* {
|
||||
* "id": "cutscene1",
|
||||
* "name": "Cutscene 1",
|
||||
* "markers": [1, 2, 3], // Marker IDs
|
||||
* "start": {
|
||||
* "world": "world",
|
||||
* "x": 0,
|
||||
* "y": 0,
|
||||
* "z": 0,
|
||||
* "yaw": 0,
|
||||
* "pitch": 0
|
||||
* },
|
||||
* "end": {
|
||||
* "world": "world",
|
||||
* "x": 0,
|
||||
* "y": 0,
|
||||
* "z": 0,
|
||||
* "yaw": 0,
|
||||
* "pitch": 0
|
||||
* }
|
||||
* "blackBorders": true,
|
||||
* "startFadeToBlack": true,
|
||||
* "endFadeToBlack": true
|
||||
* }
|
||||
* }</pre>
|
||||
*/
|
||||
public class Cutscene {
|
||||
|
||||
private final String id;
|
||||
private final String name;
|
||||
private final List<Marker> markers;
|
||||
private final List<Integer> markerIds;
|
||||
private CutsceneManager cutsceneManager;
|
||||
private Location start;
|
||||
private Location end;
|
||||
private Map<UUID, BukkitTask> tasks;
|
||||
private boolean blackBorders;
|
||||
private boolean startFadeToBlack;
|
||||
private boolean endFadeToBlack;
|
||||
private UUID id = UUID.randomUUID();
|
||||
private String name;
|
||||
private Location pos1;
|
||||
private Location pos2;
|
||||
|
||||
public Cutscene(String id, String name) {
|
||||
public Cutscene() {}
|
||||
|
||||
public Cutscene(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Cutscene(UUID id, String name, Location pos1, Location pos2) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.markers = new ArrayList<>();
|
||||
this.markerIds = new ArrayList<>();
|
||||
this.tasks = new HashMap<>();
|
||||
cutsceneManager = Manager.getInstance(CutsceneManager.class);
|
||||
if (cutsceneManager == null) {
|
||||
error("CutsceneManager is null, could not create a Cutscene");
|
||||
}
|
||||
this.pos1 = pos1;
|
||||
this.pos2 = pos2;
|
||||
}
|
||||
|
||||
public Cutscene(@NotNull String id, String name, @NotNull ArrayList<Marker> markers) {
|
||||
this.id = id.toUpperCase();
|
||||
public boolean isInRegion(@NotNull Location location) {
|
||||
double x1 = pos1.getX();
|
||||
double x2 = pos2.getX();
|
||||
double y1 = pos1.getY();
|
||||
double y2 = pos2.getY();
|
||||
double z1 = pos1.getZ();
|
||||
double z2 = pos2.getZ();
|
||||
double x = location.getX();
|
||||
double y = location.getY();
|
||||
double z = location.getZ();
|
||||
return x >= Math.min(x1, x2)
|
||||
&& x <= Math.max(x1, x2)
|
||||
&& y >= Math.min(y1, y2)
|
||||
&& y <= Math.max(y1, y2)
|
||||
&& z >= Math.min(z1, z2)
|
||||
&& z <= Math.max(z1, z2);
|
||||
}
|
||||
|
||||
public UUID id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Cutscene setId(UUID id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Cutscene setName(String name) {
|
||||
this.name = name;
|
||||
this.markers = markers;
|
||||
markerIds = new ArrayList<>();
|
||||
for (Marker marker : markers) {
|
||||
markerIds.add(marker.getId());
|
||||
}
|
||||
if (markers.isEmpty()) return;
|
||||
if (markers.getFirst().getFrames().isEmpty()) return;
|
||||
start = markers.getFirst().getFrames().getFirst().getLocation();
|
||||
end = markers.getLast().getFrames().getLast().getLocation();
|
||||
this.tasks = new HashMap<>();
|
||||
cutsceneManager = Manager.getInstance(CutsceneManager.class);
|
||||
if (cutsceneManager == null) {
|
||||
error("CutsceneManager is null, could not create a Cutscene");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setMarkers() {
|
||||
for (Integer i : markerIds) {
|
||||
markers.add(Marker.getMarker(i));
|
||||
}
|
||||
public Location pos1() {
|
||||
return pos1;
|
||||
}
|
||||
|
||||
public void addMarker(Marker marker) {
|
||||
this.markers.add(marker);
|
||||
public Cutscene setPos1(Location pos1) {
|
||||
this.pos1 = pos1;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return this.id.toUpperCase();
|
||||
public Location pos2() {
|
||||
return pos2;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public List<Marker> getMarkers() {
|
||||
return this.markers;
|
||||
}
|
||||
|
||||
public Location getStart() {
|
||||
return this.start;
|
||||
}
|
||||
|
||||
public void setStart(Location start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public Location getEnd() {
|
||||
return this.end;
|
||||
}
|
||||
|
||||
public void setEnd(Location end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public void addMarkerId(Integer id) {
|
||||
this.markerIds.add(id);
|
||||
}
|
||||
|
||||
public long time() {
|
||||
long time = 0;
|
||||
for (Marker marker : this.markers) {
|
||||
if (marker.getOverAllTime() != null) time += marker.getOverAllTime();
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
public void play(@NotNull Player p) {
|
||||
if (cutsceneManager.isPlayingCutscene(p)) {
|
||||
p.sendMessage(textComp("You are already playing a cutscene!"));
|
||||
}
|
||||
cutsceneManager.addCurrentPlayingCutscene(this, p);
|
||||
|
||||
// hide toolbar and make it spectate entity
|
||||
p.setGameMode(GameMode.SPECTATOR);
|
||||
|
||||
// set black borders
|
||||
if (blackBorders) {
|
||||
p.getInventory().setHelmet(new ItemStack(Material.PUMPKIN));
|
||||
p.updateInventory();
|
||||
}
|
||||
|
||||
if (startFadeToBlack) {
|
||||
showBlackScreen(p, 2, 1, 1);
|
||||
}
|
||||
|
||||
BukkitTask task =
|
||||
Bukkit.getScheduler()
|
||||
.runTaskAsynchronously(
|
||||
SR.getPlugin(),
|
||||
() -> {
|
||||
int finalI = 0;
|
||||
for (Marker marker : markers) {
|
||||
for (int i = 0; i < marker.getFrames().size(); i++) {
|
||||
int finalI1 = i;
|
||||
Bukkit.getScheduler()
|
||||
.runTaskLater(
|
||||
SR.getPlugin(),
|
||||
() -> {
|
||||
p.teleport(marker.getFrames().get(finalI1).getLocation());
|
||||
marker.getFrames().get(finalI1).play();
|
||||
},
|
||||
(marker.getTimeBetweenFrames() * finalI) / 50);
|
||||
finalI++;
|
||||
}
|
||||
}
|
||||
if (endFadeToBlack) {
|
||||
Bukkit.getScheduler()
|
||||
.runTask(SR.getPlugin(), () -> showBlackScreen(p, 2, 1, 1));
|
||||
}
|
||||
});
|
||||
Bukkit.getScheduler()
|
||||
.runTaskAsynchronously(
|
||||
SR.getPlugin(),
|
||||
() -> {
|
||||
try {
|
||||
Thread.sleep(time());
|
||||
} catch (InterruptedException e) {
|
||||
error("Error while playing cutscene: " + e.getMessage());
|
||||
}
|
||||
Bukkit.getScheduler().runTask(SR.getPlugin(), () -> stop(p));
|
||||
});
|
||||
tasks.put(p.getUniqueId(), task);
|
||||
}
|
||||
|
||||
public void stop(UUID player) {
|
||||
Player p = Bukkit.getPlayer(player);
|
||||
if (p == null) return;
|
||||
stop(p);
|
||||
}
|
||||
|
||||
public void stop(@NotNull Player p) {
|
||||
if (cutsceneManager.isPlayingCutscene(p)) {
|
||||
if (cutsceneManager.getPlayingCutscene(p).equals(this.id)) {
|
||||
cutsceneManager.removeCurrentPlayingCutscene(this, p);
|
||||
tasks.get(p.getUniqueId()).cancel();
|
||||
p.sendMessage(Component.text("You stopped playing the cutscene!"));
|
||||
}
|
||||
} else {
|
||||
p.sendMessage(Component.text("You are not playing a cutscene!"));
|
||||
}
|
||||
}
|
||||
|
||||
public void calculateMarkers() {
|
||||
if (markers.isEmpty()) return;
|
||||
for (int i = 0; i < markers.size(); i++) {
|
||||
if (i < markers.size() - 1) {
|
||||
markers.get(i).calculateFrames(markers.get(i + 1));
|
||||
} else {
|
||||
ArrayList<Frame> frames = new ArrayList<>();
|
||||
frames.add(new Frame(markers.get(i).getStart()));
|
||||
markers.get(i).setFrames(frames);
|
||||
}
|
||||
}
|
||||
public Cutscene setPos2(Location pos2) {
|
||||
this.pos2 = pos2;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,168 +1,138 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
import static me.unurled.sacredrealms.sr.utils.Items.cancelItem;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.UUID;
|
||||
import me.unurled.sacredrealms.sr.SR;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.tasks.TickTracker;
|
||||
import me.unurled.srcore.api.Manager;
|
||||
import org.bukkit.Bukkit;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CutsceneManager extends Manager {
|
||||
// TODO: spectator to hide toolbar (make it ride an invisible entity to prevent movement)
|
||||
// TODO: save modifications if any
|
||||
// TODO: do you set player back to original position ?
|
||||
// TODO: make a system to easily create cutscenesw
|
||||
|
||||
private static final TextComponent ALREADY_STARTED =
|
||||
textComp("<red>You are already creating a cutscene.");
|
||||
|
||||
private List<Cutscene> cutscenes;
|
||||
private Map<UUID, Cutscene> cutsceneBeingCreated;
|
||||
private Map<UUID, PlayerInventory> savedInventories;
|
||||
|
||||
// cutscene id, player uuid
|
||||
private Map<String, UUID> currentPlayingCutscenes;
|
||||
|
||||
private Map<UUID, PlayerOrigin> playerOrigins;
|
||||
|
||||
private List<String> cutsceneIds;
|
||||
|
||||
/** Load the manager */
|
||||
@Override
|
||||
public void load() {
|
||||
super.load();
|
||||
SR.getPlugin()
|
||||
.getServer()
|
||||
.getPluginManager()
|
||||
.registerEvents(new CreationListener(), SR.getPlugin());
|
||||
TickTracker.startTracking();
|
||||
cutscenes = new ArrayList<>();
|
||||
currentPlayingCutscenes = new HashMap<>();
|
||||
playerOrigins = new HashMap<>();
|
||||
cutsceneIds = new ArrayList<>();
|
||||
cutsceneBeingCreated = new HashMap<>();
|
||||
savedInventories = new HashMap<>();
|
||||
}
|
||||
|
||||
/** Unload the manager */
|
||||
@Override
|
||||
public void unload() {
|
||||
super.unload();
|
||||
cutscenes.clear();
|
||||
currentPlayingCutscenes.clear();
|
||||
playerOrigins.clear();
|
||||
cutsceneIds.clear();
|
||||
cutsceneBeingCreated.clear();
|
||||
savedInventories.clear();
|
||||
}
|
||||
|
||||
public void createCutscene(String id) {
|
||||
Cutscene cutscene = new Cutscene(id, id);
|
||||
addCutscene(cutscene);
|
||||
@Nullable
|
||||
public Cutscene getCutsceneBeingCreated(@NotNull UUID uuid) {
|
||||
return cutsceneBeingCreated.get(uuid);
|
||||
}
|
||||
|
||||
public void removeCutscene(String id) {
|
||||
Cutscene cutscene = getCutscene(id);
|
||||
removeCutscene(cutscene);
|
||||
}
|
||||
|
||||
public void addCutscene(Cutscene cutscene) {
|
||||
cutscenes.add(cutscene);
|
||||
cutsceneIds.add(cutscene.getId());
|
||||
}
|
||||
|
||||
public void removeCutscene(Cutscene cutscene) {
|
||||
cutscenes.remove(cutscene);
|
||||
cutsceneIds.remove(cutscene.getId().toUpperCase());
|
||||
}
|
||||
|
||||
public void addCurrentPlayingCutscene(@NotNull Cutscene cutscene, @NotNull Player p) {
|
||||
currentPlayingCutscenes.put(cutscene.getId(), p.getUniqueId());
|
||||
}
|
||||
|
||||
public void removeCurrentPlayingCutscene(@NotNull Cutscene cutscene, @NotNull Player p) {
|
||||
currentPlayingCutscenes.remove(cutscene.getId(), p.getUniqueId());
|
||||
}
|
||||
|
||||
public List<String> getCutscenesId() {
|
||||
return cutsceneIds;
|
||||
}
|
||||
|
||||
public void stopCutscene(Player p) {
|
||||
for (String string : currentPlayingCutscenes.keySet()) {
|
||||
if (currentPlayingCutscenes.get(string).equals(p.getUniqueId())) {
|
||||
currentPlayingCutscenes.remove(string, p.getUniqueId());
|
||||
Cutscene cutscene = getCutscene(string);
|
||||
if (cutscene != null) {
|
||||
cutscene.stop(p);
|
||||
PlayerOrigin.restore(playerOrigins.get(p.getUniqueId()), p);
|
||||
playerOrigins.remove(p.getUniqueId());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stopCutscenesForAllPlayers() {
|
||||
for (String string : currentPlayingCutscenes.keySet()) {
|
||||
Cutscene cutscene = getCutscene(string);
|
||||
if (cutscene != null) {
|
||||
UUID uuid = currentPlayingCutscenes.get(string);
|
||||
cutscene.stop(uuid);
|
||||
currentPlayingCutscenes.remove(cutscene.getId(), uuid);
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
if (player == null) return;
|
||||
PlayerOrigin.restore(playerOrigins.get(uuid), player);
|
||||
playerOrigins.remove(uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void playCutscene(Cutscene cutscene, Player p) {
|
||||
if (cutscene == null) {
|
||||
p.sendMessage(textComp("<red>There was an error with the cutscene!"));
|
||||
public void startCreatingCutscene(@NotNull Player p, String name) {
|
||||
if (cutsceneBeingCreated.containsKey(p.getUniqueId())) {
|
||||
p.sendMessage(ALREADY_STARTED);
|
||||
return;
|
||||
}
|
||||
if (cutscenes.contains(cutscene) && !currentPlayingCutscenes.containsValue(p.getUniqueId())) {
|
||||
currentPlayingCutscenes.put(cutscene.getId(), p.getUniqueId());
|
||||
setPlayerOrigins(p);
|
||||
cutscene.play(p);
|
||||
cutsceneBeingCreated.put(p.getUniqueId(), new Cutscene(name));
|
||||
|
||||
// process to create cutscene
|
||||
savedInventories.put(p.getUniqueId(), p.getInventory());
|
||||
p.getInventory().clear();
|
||||
p.sendMessage(
|
||||
textComp("<green>You are now creating a cutscene. Place the <gold>corner blocks</gold>."));
|
||||
ItemStack cancel = cancelItem();
|
||||
ItemStack finish = new ItemStack(Material.EMERALD_BLOCK);
|
||||
ItemMeta meta = finish.getItemMeta();
|
||||
meta.displayName(textComp("<b><green>Finish</green></b>"));
|
||||
finish.setItemMeta(meta);
|
||||
|
||||
ItemStack pos1 = new ItemStack(Material.RED_WOOL);
|
||||
meta = pos1.getItemMeta();
|
||||
meta.displayName(textComp("<b><red>Pos1</red></b>"));
|
||||
pos1.setItemMeta(meta);
|
||||
|
||||
ItemStack pos2 = new ItemStack(Material.BLUE_WOOL);
|
||||
meta = pos2.getItemMeta();
|
||||
meta.displayName(textComp("<b><blue>Pos2</blue></b>"));
|
||||
pos2.setItemMeta(meta);
|
||||
|
||||
p.getInventory().setItem(8, cancel);
|
||||
p.getInventory().setItem(0, finish);
|
||||
p.getInventory().setItem(3, pos1);
|
||||
p.getInventory().setItem(5, pos2);
|
||||
|
||||
p.updateInventory();
|
||||
}
|
||||
|
||||
public void finishCreatingCutscene(@NotNull Player p) {
|
||||
if (!cutsceneBeingCreated.containsKey(p.getUniqueId())) {
|
||||
p.sendMessage(textComp("<red>You are not creating a cutscene."));
|
||||
return;
|
||||
}
|
||||
Cutscene cutscene = cutsceneBeingCreated.get(p.getUniqueId());
|
||||
|
||||
cutscenes.add(cutscene);
|
||||
p.getInventory().clear();
|
||||
p.sendMessage(textComp("<green>Cutscene created."));
|
||||
cutsceneBeingCreated.remove(p.getUniqueId());
|
||||
PlayerInventory inv = savedInventories.get(p.getUniqueId());
|
||||
for (int i = 0; i < inv.getSize(); i++) {
|
||||
p.getInventory().setItem(i, inv.getItem(i));
|
||||
}
|
||||
p.updateInventory();
|
||||
savedInventories.remove(p.getUniqueId());
|
||||
}
|
||||
|
||||
public void cancelCreatingCutscene(@NotNull Player p) {
|
||||
if (!cutsceneBeingCreated.containsKey(p.getUniqueId())) {
|
||||
p.sendMessage(textComp("<red>You are not creating a cutscene."));
|
||||
return;
|
||||
}
|
||||
|
||||
p.getInventory().clear();
|
||||
p.sendMessage(textComp("<green>Canceled creating cutscene."));
|
||||
cutsceneBeingCreated.remove(p.getUniqueId());
|
||||
PlayerInventory inv = savedInventories.get(p.getUniqueId());
|
||||
for (int i = 0; i < inv.getSize(); i++) {
|
||||
p.getInventory().setItem(i, inv.getItem(i));
|
||||
}
|
||||
p.updateInventory();
|
||||
savedInventories.remove(p.getUniqueId());
|
||||
}
|
||||
|
||||
public List<Cutscene> cutscenes() {
|
||||
return cutscenes;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Cutscene getCutscene(Player p) {
|
||||
for (Entry<String, UUID> entry : currentPlayingCutscenes.entrySet()) {
|
||||
if (entry.getValue().equals(p.getUniqueId())) return getCutscene(entry.getKey());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Cutscene getCutscene(@NotNull String id) {
|
||||
if (!cutsceneIds.contains(id.toUpperCase())) {
|
||||
return null;
|
||||
}
|
||||
for (Cutscene cutscene : cutscenes) {
|
||||
if (cutscene.getId().equalsIgnoreCase(id.toUpperCase())) return cutscene;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isPlayingCutscene(@NotNull Player p) {
|
||||
return currentPlayingCutscenes.containsValue(p.getUniqueId());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getPlayingCutscene(@NotNull Player p) {
|
||||
for (Entry<String, UUID> entry : currentPlayingCutscenes.entrySet()) {
|
||||
if (entry.getValue().equals(p.getUniqueId())) return entry.getKey();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setPlayerOrigins(@NotNull Player p) {
|
||||
playerOrigins.put(
|
||||
p.getUniqueId(),
|
||||
new PlayerOrigin(
|
||||
p.getLocation(),
|
||||
p.getAllowFlight(),
|
||||
p.isFlying(),
|
||||
p.getWalkSpeed(),
|
||||
p.getFlySpeed(),
|
||||
p.getGameMode()));
|
||||
public Cutscene findByUUID(UUID uuid) {
|
||||
return cutscenes.stream().filter(c -> c.id().equals(uuid)).findFirst().orElse(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class EntityCinematicAction {
|
||||
private Player p;
|
||||
}
|
|
@ -1,113 +0,0 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Logger.error;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import java.util.Map;
|
||||
import me.unurled.sacredrealms.sr.utils.gson.LocationSerializer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Frame class
|
||||
*
|
||||
* <p>example of serializable frame:
|
||||
*
|
||||
* <pre>{@code
|
||||
* {
|
||||
* "id": 1,
|
||||
* "entities": "entities serializable",
|
||||
* "blocks": "blocks serializable",
|
||||
* "action": "action", // if type is entity
|
||||
* "location": {
|
||||
* "world": "world",
|
||||
* "x": 0,
|
||||
* "y": 0,
|
||||
* "z": 0,
|
||||
* "yaw": 0,
|
||||
* "pitch": 0
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
*/
|
||||
public class Frame {
|
||||
private static int idCounter = 0;
|
||||
private final Location location;
|
||||
private final int id;
|
||||
@Nullable private Map<Location, BlockData> blocks;
|
||||
|
||||
public Frame(Location location) {
|
||||
this.location = location;
|
||||
id = idCounter;
|
||||
idCounter++;
|
||||
blocks = null;
|
||||
}
|
||||
|
||||
public Frame(Location location, int ID) {
|
||||
this.location = location;
|
||||
this.id = ID;
|
||||
blocks = null;
|
||||
}
|
||||
|
||||
@Contract("_ -> new")
|
||||
public static @NotNull Frame deserialize(@NotNull JsonElement jsonElement) {
|
||||
int id = jsonElement.getAsJsonObject().get("id").getAsInt();
|
||||
Location loc = null;
|
||||
try {
|
||||
LocationSerializer locationDeserializer = new LocationSerializer();
|
||||
loc =
|
||||
locationDeserializer.deserialize(
|
||||
jsonElement.getAsJsonObject().get("location"), Location.class, null);
|
||||
} catch (Exception e) {
|
||||
error("Error deserializing location in Frame with ID: " + id);
|
||||
}
|
||||
|
||||
Frame frame = new Frame(loc, id);
|
||||
|
||||
try {
|
||||
frame.setBlocks((Map<Location, BlockData>) jsonElement.getAsJsonObject().get("blocks"));
|
||||
} catch (Exception e) {
|
||||
error("Error deserializing blocks in Frame with ID: " + id);
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
/** Play the frame aka move stuff around :shrug: */
|
||||
public void play() {}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public @Nullable Map<Location, BlockData> getBlocks() {
|
||||
return blocks;
|
||||
}
|
||||
|
||||
public void setBlocks(@Nullable Map<Location, BlockData> blocks) {
|
||||
this.blocks = blocks;
|
||||
}
|
||||
|
||||
public JsonElement serialize() {
|
||||
String s =
|
||||
"{"
|
||||
+ "\"id\":"
|
||||
+ id
|
||||
+ ","
|
||||
+ ","
|
||||
+ "\"blocks\":"
|
||||
+ blocks
|
||||
+ ","
|
||||
+ "\"location\":"
|
||||
+ location.serialize()
|
||||
+ "}";
|
||||
return new JsonPrimitive(s);
|
||||
}
|
||||
}
|
|
@ -1,146 +0,0 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.CutsceneUtil.interpolateFrames;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.bukkit.Location;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Marker class
|
||||
*
|
||||
* <pre>{@code
|
||||
* {
|
||||
* "id": 1,
|
||||
* "frames": [ 1, 2, 3 ], // Frame IDs
|
||||
* "timeBetweenFrames": 20,
|
||||
* "overAllTime": 60,
|
||||
* "start": {
|
||||
* "world": "world",
|
||||
* "x": 0,
|
||||
* "y": 0,
|
||||
* "z": 0,
|
||||
* "yaw": 0,
|
||||
* "pitch": 0
|
||||
* }
|
||||
* }
|
||||
* }</pre>
|
||||
*/
|
||||
public class Marker {
|
||||
|
||||
private static int idCounter = 0;
|
||||
private static List<Marker> markers = new ArrayList<>();
|
||||
private final int id;
|
||||
private List<Frame> frames;
|
||||
private Long timeBetweenFrames;
|
||||
private Long overAllTime;
|
||||
private Location start;
|
||||
|
||||
public Marker(Integer id) {
|
||||
frames = new ArrayList<>();
|
||||
timeBetweenFrames = 0L;
|
||||
overAllTime = 0L;
|
||||
if (id == null) {
|
||||
this.id = idCounter;
|
||||
idCounter++;
|
||||
} else {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
public Marker(@NotNull List<Frame> frames, long timeBetweenFrames, Location start) {
|
||||
this.frames = frames;
|
||||
this.timeBetweenFrames = timeBetweenFrames;
|
||||
this.overAllTime = timeBetweenFrames * frames.size();
|
||||
this.start = start;
|
||||
id = idCounter;
|
||||
idCounter++;
|
||||
}
|
||||
|
||||
public static List<Marker> getMarkers() {
|
||||
return markers;
|
||||
}
|
||||
|
||||
public static void setMarkers(List<Marker> markers) {
|
||||
Marker.markers = markers;
|
||||
}
|
||||
|
||||
public static @Nullable Marker getMarker(int ID) {
|
||||
for (Marker marker : markers) {
|
||||
if (marker.getId() == ID) {
|
||||
return marker;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<Frame> getFrames() {
|
||||
return frames;
|
||||
}
|
||||
|
||||
public void setFrames(List<Frame> frames) {
|
||||
this.frames = frames;
|
||||
}
|
||||
|
||||
public Long getTimeBetweenFrames() {
|
||||
return timeBetweenFrames;
|
||||
}
|
||||
|
||||
public void setTimeBetweenFrames(Long timeBetweenFrames) {
|
||||
this.timeBetweenFrames = timeBetweenFrames;
|
||||
}
|
||||
|
||||
public Long getOverAllTime() {
|
||||
return overAllTime;
|
||||
}
|
||||
|
||||
public void setOverAllTime(Long overAllTime) {
|
||||
this.overAllTime = overAllTime;
|
||||
}
|
||||
|
||||
public Location getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public void setStart(Location start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public void calculateFrames(Marker endMarker) {
|
||||
frames = interpolateFrames(this, endMarker, timeBetweenFrames);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void addFrame(Frame frame) {
|
||||
frames.add(frame);
|
||||
}
|
||||
|
||||
public void removeFrame(Frame frame) {
|
||||
frames.remove(frame);
|
||||
}
|
||||
|
||||
public void removeFrame(int index) {
|
||||
frames.remove(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Marker{"
|
||||
+ "ID="
|
||||
+ id
|
||||
+ ", frames="
|
||||
+ frames
|
||||
+ ", timeBetweenFrames="
|
||||
+ timeBetweenFrames
|
||||
+ ", overAllTime="
|
||||
+ overAllTime
|
||||
+ ", start="
|
||||
+ start
|
||||
+ '}';
|
||||
}
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene;
|
||||
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public record PlayerOrigin(
|
||||
Location location,
|
||||
boolean allowFlight,
|
||||
boolean flying,
|
||||
float walkSpeed,
|
||||
float flySpeed,
|
||||
GameMode gameMode) {
|
||||
public static void restore(@NotNull PlayerOrigin origin, @NotNull Player p) {
|
||||
p.teleport(origin.location());
|
||||
p.setAllowFlight(origin.allowFlight());
|
||||
p.setFlying(origin.flying());
|
||||
p.setWalkSpeed(origin.walkSpeed());
|
||||
p.setFlySpeed(origin.flySpeed());
|
||||
p.setGameMode(origin.gameMode());
|
||||
}
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose;
|
||||
import io.papermc.paper.event.player.PlayerArmSwingEvent;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.npc.ArmSwing;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.npc.EntityFrame;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Pose;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PlayerRecording {
|
||||
private final Player player;
|
||||
private final EntityFrame entityFrame;
|
||||
private ArmSwing swing;
|
||||
|
||||
public PlayerRecording(Player player, EntityFrame entityFrame) {
|
||||
this.player = player;
|
||||
this.entityFrame = entityFrame;
|
||||
}
|
||||
|
||||
private static EntityPose toEntityPose(Pose pose) {
|
||||
return pose == Pose.SNEAKING ? EntityPose.SITTING : EntityPose.valueOf(pose.name());
|
||||
}
|
||||
|
||||
private static Pose toBukkitPose(EntityPose pose) {
|
||||
return pose == EntityPose.SITTING ? Pose.SNEAKING : Pose.valueOf(pose.name());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onArmSwing(@NotNull PlayerArmSwingEvent e) {
|
||||
if (e.getPlayer().getUniqueId() != player.getUniqueId()) {
|
||||
return;
|
||||
}
|
||||
addSwing(
|
||||
e.getHand() == EquipmentSlot.HAND
|
||||
? ArmSwing.RIGHT
|
||||
: (e.getHand() == EquipmentSlot.OFF_HAND ? ArmSwing.LEFT : ArmSwing.BOTH));
|
||||
}
|
||||
|
||||
private void addSwing(ArmSwing swing) {
|
||||
if (this.swing != null && this.swing != swing) {
|
||||
this.swing = ArmSwing.BOTH;
|
||||
return;
|
||||
}
|
||||
|
||||
this.swing = swing;
|
||||
}
|
||||
|
||||
public EntityFrame captureFrame() {
|
||||
PlayerInventory inv = player.getInventory();
|
||||
Pose pose = player.isInsideVehicle() ? Pose.SITTING : player.getPose();
|
||||
EntityFrame data =
|
||||
new EntityFrame(
|
||||
player.getLocation(),
|
||||
toEntityPose(pose),
|
||||
swing,
|
||||
inv.getItemInMainHand().isEmpty() ? null : inv.getItemInMainHand(),
|
||||
inv.getItemInOffHand().isEmpty() ? null : inv.getItemInOffHand(),
|
||||
inv.getHelmet(),
|
||||
inv.getChestplate(),
|
||||
inv.getLeggings(),
|
||||
inv.getBoots());
|
||||
swing = null;
|
||||
return data;
|
||||
}
|
||||
|
||||
public void applyState(@NotNull EntityFrame value) {
|
||||
player.teleport(value.location());
|
||||
player.setPose(toBukkitPose(value.pose()));
|
||||
PlayerInventory inv = player.getInventory();
|
||||
inv.setItemInMainHand(value.mainHand());
|
||||
inv.setItemInOffHand(value.offHand());
|
||||
inv.setHelmet(value.helmet());
|
||||
inv.setChestplate(value.chestplate());
|
||||
inv.setLeggings(value.leggings());
|
||||
inv.setBoots(value.boots());
|
||||
player.updateInventory();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene;
|
||||
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recording;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.tasks.TickTracker;
|
||||
import me.unurled.srcore.api.Manager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class RecordingManager extends Manager {
|
||||
private List<Recording> recordings; // existing recordings
|
||||
private List<Recording> activeRecordings; // currently recording
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
super.load();
|
||||
recordings = new ArrayList<>();
|
||||
activeRecordings = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload() {
|
||||
super.unload();
|
||||
recordings.clear();
|
||||
activeRecordings.clear();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Recording getPlayerActiveRecording(Player player) {
|
||||
return activeRecordings.stream()
|
||||
.filter(r -> r.recordingPlayer().equals(player))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
public void startRecording(Cutscene cutscene, Player player) {
|
||||
Recording recording = new Recording(cutscene, player);
|
||||
player.sendMessage(textComp("<green>Recording started."));
|
||||
activeRecordings.add(recording);
|
||||
}
|
||||
|
||||
public void stopRecording(Player player) {
|
||||
Recording recording = getPlayerActiveRecording(player);
|
||||
if (recording == null) {
|
||||
player.sendMessage(textComp("<red>You are not recording a cutscene."));
|
||||
return;
|
||||
}
|
||||
activeRecordings.remove(recording);
|
||||
recording.stopRecording();
|
||||
recordings.add(recording);
|
||||
player.sendMessage(textComp("<green>Recording stopped."));
|
||||
}
|
||||
|
||||
public void addRecordable(@NotNull Recording recording, @NotNull Recordable recordable) {
|
||||
long tick = TickTracker.currentTick();
|
||||
|
||||
// normalize tick
|
||||
tick = tick - recording.startTick();
|
||||
|
||||
recordable.setTick(tick);
|
||||
|
||||
if (recording.recordables().containsKey(tick)) {
|
||||
recording.recordables().get(tick).add(recordable);
|
||||
} else {
|
||||
List<Recordable> recordables = new ArrayList<>();
|
||||
recordables.add(recordable);
|
||||
recording.recordables().put(tick, recordables);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene;
|
||||
|
||||
import me.unurled.sacredrealms.sr.SR;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recording;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.tasks.ReplayTask;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class Replay {
|
||||
private final Player viewer;
|
||||
private final Recording recording;
|
||||
private final BukkitTask replayTask;
|
||||
|
||||
public Replay(Recording recording, @NotNull Player viewer) {
|
||||
this.recording = recording;
|
||||
this.viewer = viewer;
|
||||
|
||||
viewer.getInventory().clear();
|
||||
// TODO: control cutscene replay
|
||||
|
||||
replayTask =
|
||||
Bukkit.getScheduler()
|
||||
.runTaskTimerAsynchronously(SR.getPlugin(), new ReplayTask(this), 0L, 1L);
|
||||
}
|
||||
|
||||
public Player viewer() {
|
||||
return viewer;
|
||||
}
|
||||
|
||||
public Recording recording() {
|
||||
return recording;
|
||||
}
|
||||
|
||||
public BukkitTask replayTask() {
|
||||
return replayTask;
|
||||
}
|
||||
|
||||
public void endReplay() {
|
||||
if (replayTask != null) {
|
||||
replayTask.cancel();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recording;
|
||||
import me.unurled.srcore.api.Manager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ReplayManager extends Manager {
|
||||
|
||||
private Set<Replay> replays;
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
super.load();
|
||||
replays = new HashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unload() {
|
||||
super.unload();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Replay getReplayForPlayer(Player player) {
|
||||
return replays.stream()
|
||||
.filter(replay -> replay.viewer().equals(player))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
public void replayRecording(Recording recording, Player player) {
|
||||
if (getReplayForPlayer(player) != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Replay replay = new Replay(recording, player);
|
||||
replays.add(replay);
|
||||
}
|
||||
|
||||
public void stopReplay(@NotNull Replay replay) {
|
||||
// stop replay taskk
|
||||
replay.endReplay();
|
||||
|
||||
replays.remove(replay);
|
||||
}
|
||||
|
||||
public Set<Replay> replays() {
|
||||
return replays;
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene.gson;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import java.lang.reflect.Type;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.Action;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ActionGson {
|
||||
public class Deserializer implements JsonDeserializer<Action> {
|
||||
|
||||
/**
|
||||
* Gson invokes this call-back method during deserialization when it encounters a field of the
|
||||
* specified type.
|
||||
*
|
||||
* <p>In the implementation of this call-back method, you should consider invoking {@link
|
||||
* JsonDeserializationContext#deserialize(JsonElement, Type)} method to create objects for any
|
||||
* non-trivial field of the returned object. However, you should never invoke it on the same
|
||||
* type passing {@code json} since that will cause an infinite loop (Gson will call your
|
||||
* call-back method again).
|
||||
*
|
||||
* @param json The Json data being deserialized
|
||||
* @param typeOfT The type of the Object to deserialize to
|
||||
* @param context
|
||||
* @return a deserialized object of the specified type typeOfT which is a subclass of {@code T}
|
||||
* @throws JsonParseException if json is not in the expected format of {@code typeofT}
|
||||
*/
|
||||
@Override
|
||||
public Action deserialize(
|
||||
@NotNull JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return Action.valueOf(json.getAsString());
|
||||
}
|
||||
}
|
||||
|
||||
public class Serializer implements JsonSerializer<Action> {
|
||||
|
||||
/**
|
||||
* Gson invokes this call-back method during serialization when it encounters a field of the
|
||||
* specified type.
|
||||
*
|
||||
* <p>In the implementation of this call-back method, you should consider invoking {@link
|
||||
* JsonSerializationContext#serialize(Object, Type)} method to create JsonElements for any
|
||||
* non-trivial field of the {@code src} object. However, you should never invoke it on the
|
||||
* {@code src} object itself since that will cause an infinite loop (Gson will call your
|
||||
* call-back method again).
|
||||
*
|
||||
* @param src the object that needs to be converted to Json.
|
||||
* @param typeOfSrc the actual type (fully genericized version) of the source object.
|
||||
* @param context
|
||||
* @return a JsonElement corresponding to the specified object.
|
||||
*/
|
||||
@Override
|
||||
public JsonElement serialize(Action src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src.name());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene.gson;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.Action;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
public class EntityActionGson {
|
||||
public class Deserializer implements JsonDeserializer<Map<Entity, Action>> {
|
||||
|
||||
/**
|
||||
* Gson invokes this call-back method during deserialization when it encounters a field of the
|
||||
* specified type.
|
||||
*
|
||||
* <p>In the implementation of this call-back method, you should consider invoking {@link
|
||||
* JsonDeserializationContext#deserialize(JsonElement, Type)} method to create objects for any
|
||||
* non-trivial field of the returned object. However, you should never invoke it on the same
|
||||
* type passing {@code json} since that will cause an infinite loop (Gson will call your
|
||||
* call-back method again).
|
||||
*
|
||||
* @param json The Json data being deserialized
|
||||
* @param typeOfT The type of the Object to deserialize to
|
||||
* @param context
|
||||
* @return a deserialized object of the specified type typeOfT which is a subclass of {@code T}
|
||||
* @throws JsonParseException if json is not in the expected format of {@code typeofT}
|
||||
*/
|
||||
@Override
|
||||
public Map<Entity, Action> deserialize(
|
||||
JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class Serializer implements JsonSerializer<Map<Entity, Action>> {
|
||||
|
||||
/**
|
||||
* Gson invokes this call-back method during serialization when it encounters a field of the
|
||||
* specified type.
|
||||
*
|
||||
* <p>In the implementation of this call-back method, you should consider invoking {@link
|
||||
* JsonSerializationContext#serialize(Object, Type)} method to create JsonElements for any
|
||||
* non-trivial field of the {@code src} object. However, you should never invoke it on the
|
||||
* {@code src} object itself since that will cause an infinite loop (Gson will call your
|
||||
* call-back method again).
|
||||
*
|
||||
* @param src the object that needs to be converted to Json.
|
||||
* @param typeOfSrc the actual type (fully genericized version) of the source object.
|
||||
* @param context
|
||||
* @return a JsonElement corresponding to the specified object.
|
||||
*/
|
||||
@Override
|
||||
public JsonElement serialize(
|
||||
Map<Entity, Action> src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene.npc;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.components.packet.PacketManager.sendPacketTo;
|
||||
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityAnimation;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityAnimation.EntityAnimationType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public enum ArmSwing {
|
||||
LEFT,
|
||||
RIGHT,
|
||||
BOTH;
|
||||
|
||||
public static void swingArm(@NotNull ArmSwing arm, Player p, int entityId) {
|
||||
// Swing the arm
|
||||
if (arm.isLeft()) {
|
||||
sendPacketTo(
|
||||
new WrapperPlayServerEntityAnimation(entityId, EntityAnimationType.SWING_OFF_HAND), p);
|
||||
}
|
||||
if (arm.isRight()) {
|
||||
sendPacketTo(
|
||||
new WrapperPlayServerEntityAnimation(entityId, EntityAnimationType.SWING_MAIN_ARM), p);
|
||||
}
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public @NotNull Boolean isLeft() {
|
||||
return this == LEFT || this == BOTH;
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public @NotNull Boolean isRight() {
|
||||
return this == RIGHT || this == BOTH;
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene.npc;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import me.unurled.sacredrealms.sr.utils.Items;
|
||||
import me.unurled.sacredrealms.sr.utils.gson.LocationSerializer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public record EntityFrame(
|
||||
Location location,
|
||||
EntityPose pose,
|
||||
ArmSwing swing,
|
||||
ItemStack mainHand,
|
||||
ItemStack offHand,
|
||||
ItemStack helmet,
|
||||
ItemStack chestplate,
|
||||
ItemStack leggings,
|
||||
ItemStack boots) {
|
||||
|
||||
public static @NotNull EntityFrame deserialize(@NotNull JsonElement jsonElement) {
|
||||
Location location =
|
||||
new LocationSerializer()
|
||||
.deserialize(jsonElement.getAsJsonObject().get("location"), Location.class, null);
|
||||
EntityPose pose = EntityPose.valueOf(jsonElement.getAsJsonObject().get("pose").getAsString());
|
||||
ArmSwing swing = ArmSwing.valueOf(jsonElement.getAsJsonObject().get("swing").getAsString());
|
||||
ItemStack mainHand = Items.deserialize(jsonElement.getAsJsonObject().get("mainHand"));
|
||||
ItemStack offHand = Items.deserialize(jsonElement.getAsJsonObject().get("offHand"));
|
||||
ItemStack helmet = Items.deserialize(jsonElement.getAsJsonObject().get("helmet"));
|
||||
ItemStack chestplate = Items.deserialize(jsonElement.getAsJsonObject().get("chestplate"));
|
||||
ItemStack leggings = Items.deserialize(jsonElement.getAsJsonObject().get("leggings"));
|
||||
ItemStack boots = Items.deserialize(jsonElement.getAsJsonObject().get("boots"));
|
||||
return new EntityFrame(
|
||||
location, pose, swing, mainHand, offHand, helmet, chestplate, leggings, boots);
|
||||
}
|
||||
|
||||
public @NotNull JsonElement serialize() {
|
||||
String s =
|
||||
"""
|
||||
{
|
||||
"location": %s,
|
||||
"pose": %s,
|
||||
"swing": %s,
|
||||
"mainHand": %s,
|
||||
"offHand": %s,
|
||||
"helmet": %s,
|
||||
"chestplate": %s,
|
||||
"leggings": %s,
|
||||
"boots": %s
|
||||
}
|
||||
"""
|
||||
.formatted(
|
||||
location.serialize(),
|
||||
pose.name(),
|
||||
swing.name(),
|
||||
mainHand.serialize(),
|
||||
offHand.serialize(),
|
||||
helmet.serialize(),
|
||||
chestplate.serialize(),
|
||||
leggings.serialize(),
|
||||
boots.serialize());
|
||||
return new JsonPrimitive(s);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene.recording;
|
||||
|
||||
public abstract class Recordable {
|
||||
private long tick;
|
||||
|
||||
public abstract void replay();
|
||||
|
||||
public long tick() {
|
||||
return tick;
|
||||
}
|
||||
|
||||
public Recordable setTick(long tick) {
|
||||
this.tick = tick;
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene.recording;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import me.unurled.sacredrealms.sr.SR;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.Cutscene;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.tasks.ScanEntityTracker;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.tasks.TickTracker;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.tasks.TrackLocationTask;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
public class Recording {
|
||||
// recordables
|
||||
private final Map<Long, List<Recordable>> recordables = new HashMap<>();
|
||||
private final Queue<UUID> recordableEntities = new ConcurrentLinkedQueue<>();
|
||||
private final BukkitTask trackLocationTask;
|
||||
private final BukkitTask scanEntitiesTask;
|
||||
private Cutscene cutscene;
|
||||
private Player recordingPlayer;
|
||||
private long startTime;
|
||||
private long endTime;
|
||||
private long startTick;
|
||||
private long endTick;
|
||||
|
||||
public Recording(Cutscene cutscene, Player recordingPlayer) {
|
||||
this.cutscene = cutscene;
|
||||
this.recordingPlayer = recordingPlayer;
|
||||
|
||||
this.startTime = System.currentTimeMillis();
|
||||
this.startTick = 1; // TODO: get tick
|
||||
this.endTick = 1; // TODO: get tick
|
||||
|
||||
this.scanEntitiesTask =
|
||||
Bukkit.getScheduler().runTaskTimer(SR.getPlugin(), new ScanEntityTracker(this), 0L, 20L);
|
||||
this.trackLocationTask =
|
||||
Bukkit.getScheduler().runTaskTimer(SR.getPlugin(), new TrackLocationTask(this), 0L, 1L);
|
||||
}
|
||||
|
||||
public Map<Long, List<Recordable>> recordables() {
|
||||
return recordables;
|
||||
}
|
||||
|
||||
public Cutscene cutscene() {
|
||||
return cutscene;
|
||||
}
|
||||
|
||||
public Queue<UUID> recordableEntities() {
|
||||
return recordableEntities;
|
||||
}
|
||||
|
||||
public Recording setCutscene(Cutscene cutscene) {
|
||||
this.cutscene = cutscene;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Player recordingPlayer() {
|
||||
return recordingPlayer;
|
||||
}
|
||||
|
||||
public Recording setRecordingPlayer(Player recordingPlayer) {
|
||||
this.recordingPlayer = recordingPlayer;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long startTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public Recording setStartTime(long startTime) {
|
||||
this.startTime = startTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long endTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public Recording setEndTime(long endTime) {
|
||||
this.endTime = endTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long startTick() {
|
||||
return startTick;
|
||||
}
|
||||
|
||||
public Recording setStartTick(long startTick) {
|
||||
this.startTick = startTick;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void stopRecording() {
|
||||
this.endTime = System.currentTimeMillis();
|
||||
this.endTick = TickTracker.currentTick();
|
||||
scanEntitiesTask.cancel();
|
||||
trackLocationTask.cancel();
|
||||
}
|
||||
|
||||
public long tickDuration() {
|
||||
return endTick - startTick;
|
||||
}
|
||||
|
||||
public boolean isEntityBeingTracked(UUID uuid) {
|
||||
synchronized (recordableEntities) {
|
||||
return recordableEntities.contains(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean addEntityIfNotBeingTracked(UUID uuid) {
|
||||
synchronized (recordableEntities) {
|
||||
if (recordableEntities.contains(uuid)) {
|
||||
return false;
|
||||
}
|
||||
recordableEntities.add(uuid);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene.recording.recordables;
|
||||
|
||||
import java.util.UUID;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable;
|
||||
|
||||
public class DespawnEntityRecordable extends Recordable {
|
||||
|
||||
private UUID entityId;
|
||||
|
||||
public DespawnEntityRecordable() {}
|
||||
|
||||
public DespawnEntityRecordable(UUID entityId) {
|
||||
this.entityId = entityId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replay() {
|
||||
// TODO: fake spawn entity
|
||||
}
|
||||
|
||||
public UUID entityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
public DespawnEntityRecordable setEntityId(UUID entityId) {
|
||||
this.entityId = entityId;
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene.recording.recordables;
|
||||
|
||||
import java.util.UUID;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable;
|
||||
import org.bukkit.Location;
|
||||
|
||||
public class LocationChangeRecordable extends Recordable {
|
||||
|
||||
private UUID entityId;
|
||||
private Location location;
|
||||
|
||||
public LocationChangeRecordable() {}
|
||||
|
||||
public LocationChangeRecordable(UUID entityId, Location location) {
|
||||
this.entityId = entityId;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replay() {}
|
||||
|
||||
public UUID entityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
public LocationChangeRecordable setEntityId(UUID entityId) {
|
||||
this.entityId = entityId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Location location() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public LocationChangeRecordable setLocation(Location location) {
|
||||
this.location = location;
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene.recording.recordables;
|
||||
|
||||
import java.util.UUID;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recordable;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SpawnEntityRecordable extends Recordable {
|
||||
|
||||
private EntityType entityType;
|
||||
private Location location;
|
||||
private UUID entityId;
|
||||
private Component name;
|
||||
|
||||
public SpawnEntityRecordable() {}
|
||||
|
||||
public SpawnEntityRecordable(@NotNull Entity e) {
|
||||
this.entityType = e.getType();
|
||||
this.location = e.getLocation();
|
||||
this.entityId = e.getUniqueId();
|
||||
this.name = e.name();
|
||||
}
|
||||
|
||||
public SpawnEntityRecordable(
|
||||
EntityType entityType, Location location, UUID entityId, Component name) {
|
||||
this.entityType = entityType;
|
||||
this.location = location;
|
||||
this.entityId = entityId;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replay() {
|
||||
// TODO: fake spawn entity
|
||||
}
|
||||
|
||||
public EntityType entityType() {
|
||||
return entityType;
|
||||
}
|
||||
|
||||
public SpawnEntityRecordable setEntityType(EntityType entityType) {
|
||||
this.entityType = entityType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Location location() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public SpawnEntityRecordable setLocation(Location location) {
|
||||
this.location = location;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UUID entityId() {
|
||||
return entityId;
|
||||
}
|
||||
|
||||
public SpawnEntityRecordable setEntityId(UUID entityId) {
|
||||
this.entityId = entityId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Component name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public SpawnEntityRecordable setName(Component name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
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 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;
|
||||
|
||||
public class ReplayTask implements Runnable {
|
||||
|
||||
private final Replay replay;
|
||||
private final ReplayManager rm;
|
||||
private long currentTick = 0;
|
||||
|
||||
public ReplayTask(Replay replay) {
|
||||
this.replay = replay;
|
||||
rm = Manager.getInstance(ReplayManager.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
if (currentTick >= replay.recording().tickDuration()) {
|
||||
replay.viewer().sendMessage(textComp("<yellow>Replay has ended."));
|
||||
rm.stopReplay(replay);
|
||||
return;
|
||||
}
|
||||
// get all recordables for current tick
|
||||
var recordables = replay.recording().recordables().get(currentTick);
|
||||
|
||||
try {
|
||||
if (recordables == null) {
|
||||
currentTick++;
|
||||
return;
|
||||
}
|
||||
|
||||
for (Recordable r : recordables) {
|
||||
// figure out how to replay a recordable
|
||||
r.replay();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
error("Tick: " + currentTick);
|
||||
error(e.getMessage());
|
||||
|
||||
} finally {
|
||||
currentTick++;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene.tasks;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.Cutscene;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.RecordingManager;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recording;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.recording.recordables.SpawnEntityRecordable;
|
||||
import me.unurled.srcore.api.Manager;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
|
||||
public class ScanEntityTracker implements Runnable {
|
||||
|
||||
private final Recording recording;
|
||||
|
||||
public ScanEntityTracker(Recording recording) {
|
||||
this.recording = recording;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Cutscene cutscene = recording.cutscene();
|
||||
Location pos1 = cutscene.pos1();
|
||||
Location pos2 = cutscene.pos2();
|
||||
int chunkZ = pos1.getBlockZ() >> 4;
|
||||
int chunkX = pos1.getBlockX() >> 4;
|
||||
int chunkX2 = pos2.getBlockX() >> 4;
|
||||
int chunkZ2 = pos2.getBlockZ() >> 4;
|
||||
|
||||
var loadedChunks = pos1.getWorld().getLoadedChunks();
|
||||
List<Chunk> chunksInRegion = new ArrayList<>();
|
||||
for (Chunk chunk : loadedChunks) {
|
||||
if (chunk.getX() >= chunkX
|
||||
&& chunk.getX() <= chunkX2
|
||||
&& chunk.getZ() >= chunkZ
|
||||
&& chunk.getZ() <= chunkZ2) {
|
||||
chunksInRegion.add(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
for (Chunk chunk : chunksInRegion) {
|
||||
var entities = chunk.getEntities();
|
||||
for (var entity : entities) {
|
||||
if (!cutscene.isInRegion(entity.getLocation())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (recording.addEntityIfNotBeingTracked(entity.getUniqueId())) {
|
||||
// TODO: spawn entity
|
||||
SpawnEntityRecordable recordable = new SpawnEntityRecordable(entity);
|
||||
Manager.getInstance(RecordingManager.class).addRecordable(recording, recordable);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene.tasks;
|
||||
|
||||
import me.unurled.sacredrealms.sr.SR;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
public class TickTracker {
|
||||
private static long currentTick = 0;
|
||||
|
||||
public static void startTracking() {
|
||||
Bukkit.getScheduler().scheduleSyncRepeatingTask(SR.getPlugin(), () -> currentTick++, 0L, 1L);
|
||||
}
|
||||
|
||||
public static long currentTick() {
|
||||
return currentTick;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package me.unurled.sacredrealms.sr.components.cutscene.tasks;
|
||||
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.RecordingManager;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.recording.Recording;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.recording.recordables.DespawnEntityRecordable;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.recording.recordables.LocationChangeRecordable;
|
||||
import me.unurled.srcore.api.Manager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
public class TrackLocationTask implements Runnable {
|
||||
|
||||
private final Recording recording;
|
||||
|
||||
public TrackLocationTask(Recording recording) {
|
||||
this.recording = recording;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
var recordebaleEntities = recording.recordableEntities();
|
||||
synchronized (recordebaleEntities) {
|
||||
recordebaleEntities.forEach(
|
||||
uuid -> {
|
||||
Entity entity = Bukkit.getEntity(uuid);
|
||||
if (entity == null) {
|
||||
recording.recordableEntities().remove(uuid);
|
||||
DespawnEntityRecordable recordable = new DespawnEntityRecordable(uuid);
|
||||
Manager.getInstance(RecordingManager.class).addRecordable(recording, recordable);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!recording.cutscene().isInRegion(entity.getLocation())) {
|
||||
recording.recordableEntities().remove(uuid);
|
||||
DespawnEntityRecordable recordable = new DespawnEntityRecordable(uuid);
|
||||
Manager.getInstance(RecordingManager.class).addRecordable(recording, recordable);
|
||||
return;
|
||||
}
|
||||
|
||||
var recordable =
|
||||
new LocationChangeRecordable(entity.getUniqueId(), entity.getLocation());
|
||||
|
||||
Manager.getInstance(RecordingManager.class).addRecordable(recording, recordable);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package me.unurled.sacredrealms.sr.components.difficulty;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package me.unurled.sacredrealms.sr.components.entity;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import java.util.UUID;
|
||||
import me.unurled.sacredrealms.sr.components.attributes.Attribute;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package me.unurled.sacredrealms.sr.components.item;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
import static me.unurled.sacredrealms.sr.utils.Items.lore;
|
||||
import static me.unurled.sacredrealms.sr.utils.Logger.error;
|
||||
|
||||
|
|
|
@ -69,6 +69,9 @@ public class ResourcePackManager extends Manager {
|
|||
super.saveData();
|
||||
DataManager dm = Manager.getInstance(DataManager.class);
|
||||
DataHandler dh = dm.getDataHandler();
|
||||
if (hostingProvider.getMinecraftPackURL() == null) {
|
||||
return;
|
||||
}
|
||||
dh.set("pack.url", hostingProvider.getMinecraftPackURL());
|
||||
dh.set("pack.uuid", hostingProvider.getPackUUID().toString());
|
||||
dh.set("pack.sha1", hostingProvider.getPackUUID().toString());
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package me.unurled.sacredrealms.sr.components.player;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
import static me.unurled.sacredrealms.sr.utils.Logger.error;
|
||||
import static me.unurled.sacredrealms.sr.utils.Logger.log;
|
||||
import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.updateActionBar;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent;
|
||||
import com.google.gson.Gson;
|
||||
|
@ -167,7 +167,9 @@ public class PlayerManager extends Manager {
|
|||
} catch (Exception ex) {
|
||||
error("Failed to send resource pack to player. " + ex.getMessage());
|
||||
log(rpm.getHostingProvider().getOriginalSHA1());
|
||||
log(rpm.getHostingProvider().getPackUUID().toString());
|
||||
if (rpm.getHostingProvider().getPackUUID() != null) {
|
||||
log(rpm.getHostingProvider().getPackUUID().toString());
|
||||
}
|
||||
log(rpm.getHostingProvider().getMinecraftPackURL());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package me.unurled.sacredrealms.sr.components.treasure;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package me.unurled.sacredrealms.sr.components.treasure;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
import static me.unurled.sacredrealms.sr.utils.Logger.error;
|
||||
import static me.unurled.sacredrealms.sr.utils.Logger.log;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package me.unurled.sacredrealms.sr.events.player;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.comp;
|
||||
import static me.unurled.srcore.utils.Component.comp;
|
||||
|
||||
import me.unurled.sacredrealms.sr.components.player.SRPlayer;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package me.unurled.sacredrealms.sr.gui.attributes;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.comp;
|
||||
import static me.unurled.srcore.utils.Component.comp;
|
||||
import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.syncSRToPlayer;
|
||||
|
||||
import me.unurled.sacredrealms.sr.components.attributes.Attribute;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package me.unurled.sacredrealms.sr.gui.attributes;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.comp;
|
||||
import static me.unurled.srcore.utils.Component.comp;
|
||||
|
||||
import me.unurled.sacredrealms.sr.components.attributes.Attribute;
|
||||
import org.bukkit.Material;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package me.unurled.sacredrealms.sr.gui.entitytype;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.comp;
|
||||
import static me.unurled.srcore.utils.Component.comp;
|
||||
|
||||
import me.unurled.sacredrealms.sr.components.entity.SREntityType;
|
||||
import org.bukkit.Material;
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
package me.unurled.sacredrealms.sr.gui.recordings;
|
||||
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import java.util.UUID;
|
||||
import me.unurled.sacredrealms.sr.SR;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.Cutscene;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.CutsceneManager;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.RecordingManager;
|
||||
import me.unurled.srcore.api.Manager;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import xyz.xenondevs.invui.item.ItemProvider;
|
||||
import xyz.xenondevs.invui.item.builder.ItemBuilder;
|
||||
import xyz.xenondevs.invui.item.impl.AbstractItem;
|
||||
|
||||
public class CutsceneItem extends AbstractItem {
|
||||
|
||||
private static NamespacedKey ID = null;
|
||||
private final String name;
|
||||
private final UUID uuid;
|
||||
|
||||
public CutsceneItem(String name, UUID uuid) {
|
||||
this.name = name;
|
||||
this.uuid = uuid;
|
||||
ID = new NamespacedKey(SR.getPlugin(), "cutscene_id");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemProvider getItemProvider() {
|
||||
ItemStack itemStack = new ItemStack(Material.PAPER);
|
||||
ItemMeta itemMeta = itemStack.getItemMeta();
|
||||
itemMeta.displayName(textComp(name));
|
||||
itemMeta.getPersistentDataContainer().set(ID, PersistentDataType.STRING, uuid.toString());
|
||||
itemStack.setItemMeta(itemMeta);
|
||||
|
||||
return new ItemBuilder(itemStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleClick(
|
||||
@NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent event) {
|
||||
// get uuid
|
||||
if (event.getCurrentItem() != null) {
|
||||
String uuid =
|
||||
event
|
||||
.getCurrentItem()
|
||||
.getItemMeta()
|
||||
.getPersistentDataContainer()
|
||||
.get(ID, PersistentDataType.STRING);
|
||||
|
||||
Cutscene cutscene =
|
||||
Manager.getInstance(CutsceneManager.class).findByUUID(UUID.fromString(uuid));
|
||||
|
||||
if (cutscene == null) {
|
||||
player.sendMessage(textComp("<red>Unexpected error."));
|
||||
return;
|
||||
}
|
||||
if (clickType.isLeftClick()) {
|
||||
Manager.getInstance(RecordingManager.class).startRecording(cutscene, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package me.unurled.sacredrealms.sr.gui.recordings;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Items.glassPane;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.Cutscene;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.CutsceneManager;
|
||||
import me.unurled.sacredrealms.sr.gui.BackItem;
|
||||
import me.unurled.sacredrealms.sr.gui.ForwardItem;
|
||||
import me.unurled.srcore.api.Manager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import xyz.xenondevs.invui.gui.Gui;
|
||||
import xyz.xenondevs.invui.gui.PagedGui;
|
||||
import xyz.xenondevs.invui.gui.structure.Markers;
|
||||
import xyz.xenondevs.invui.item.Item;
|
||||
import xyz.xenondevs.invui.item.builder.ItemBuilder;
|
||||
|
||||
public class StartRecordingGui {
|
||||
private StartRecordingGui() {}
|
||||
|
||||
public static @NotNull Gui listGui() {
|
||||
CutsceneManager cm = Manager.getInstance(CutsceneManager.class);
|
||||
|
||||
List<Item> items = new ArrayList<>();
|
||||
for (Cutscene cs : cm.cutscenes()) {
|
||||
CutsceneItem item = new CutsceneItem(cs.name(), cs.id());
|
||||
items.add(item);
|
||||
}
|
||||
|
||||
return PagedGui.items()
|
||||
.setStructure(
|
||||
"# # # # # # # # #",
|
||||
"# X X X X X X X #",
|
||||
"# X X X X X X X #",
|
||||
"# X X X X X X X #",
|
||||
"# # # < # > # # #")
|
||||
.addIngredient('#', new ItemBuilder(glassPane()))
|
||||
.addIngredient('X', Markers.CONTENT_LIST_SLOT_HORIZONTAL)
|
||||
.addIngredient('<', new BackItem())
|
||||
.addIngredient('>', new ForwardItem())
|
||||
.setContent(items)
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package me.unurled.sacredrealms.sr.gui.replay;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Items.glassPane;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.Replay;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.ReplayManager;
|
||||
import me.unurled.sacredrealms.sr.gui.BackItem;
|
||||
import me.unurled.sacredrealms.sr.gui.ForwardItem;
|
||||
import me.unurled.srcore.api.Manager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import xyz.xenondevs.invui.gui.Gui;
|
||||
import xyz.xenondevs.invui.gui.PagedGui;
|
||||
import xyz.xenondevs.invui.gui.structure.Markers;
|
||||
import xyz.xenondevs.invui.item.Item;
|
||||
import xyz.xenondevs.invui.item.builder.ItemBuilder;
|
||||
|
||||
public class ReplayGui {
|
||||
private ReplayGui() {}
|
||||
|
||||
public static @NotNull Gui listGui() {
|
||||
ReplayManager rm = Manager.getInstance(ReplayManager.class);
|
||||
|
||||
List<Item> items = new ArrayList<>();
|
||||
for (Replay r : rm.replays()) {}
|
||||
|
||||
return PagedGui.items()
|
||||
.setStructure(
|
||||
"# # # # # # # # #",
|
||||
"# X X X X X X X #",
|
||||
"# X X X X X X X #",
|
||||
"# X X X X X X X #",
|
||||
"# # # < # > # # #")
|
||||
.addIngredient('#', new ItemBuilder(glassPane()))
|
||||
.addIngredient('X', Markers.CONTENT_LIST_SLOT_HORIZONTAL)
|
||||
.addIngredient('<', new BackItem())
|
||||
.addIngredient('>', new ForwardItem())
|
||||
.setContent(items)
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package me.unurled.sacredrealms.sr.gui.replay;
|
||||
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import java.util.UUID;
|
||||
import me.unurled.sacredrealms.sr.SR;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.Cutscene;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.CutsceneManager;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.RecordingManager;
|
||||
import me.unurled.srcore.api.Manager;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import xyz.xenondevs.invui.item.ItemProvider;
|
||||
import xyz.xenondevs.invui.item.builder.ItemBuilder;
|
||||
import xyz.xenondevs.invui.item.impl.AbstractItem;
|
||||
|
||||
public class ReplayItem extends AbstractItem {
|
||||
private static NamespacedKey ID = null;
|
||||
private final String name;
|
||||
private final UUID uuid;
|
||||
|
||||
public ReplayItem(String name, UUID uuid) {
|
||||
ID = new NamespacedKey(SR.getPlugin(), "cutscene_id");
|
||||
this.name = name;
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemProvider getItemProvider() {
|
||||
ItemStack itemStack = new ItemStack(Material.PAPER);
|
||||
ItemMeta itemMeta = itemStack.getItemMeta();
|
||||
itemMeta.displayName(textComp(name));
|
||||
itemMeta.getPersistentDataContainer().set(ID, PersistentDataType.STRING, uuid.toString());
|
||||
itemStack.setItemMeta(itemMeta);
|
||||
return new ItemBuilder(itemStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleClick(
|
||||
@NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent event) {
|
||||
if (event.getCurrentItem() != null) {
|
||||
String uuid =
|
||||
event
|
||||
.getCurrentItem()
|
||||
.getItemMeta()
|
||||
.getPersistentDataContainer()
|
||||
.get(ID, PersistentDataType.STRING);
|
||||
|
||||
if (uuid == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Cutscene cutscene =
|
||||
Manager.getInstance(CutsceneManager.class).findByUUID(UUID.fromString(uuid));
|
||||
|
||||
if (cutscene == null) {
|
||||
player.sendMessage(textComp("<red>Unexpected error."));
|
||||
return;
|
||||
}
|
||||
if (clickType.isLeftClick()) {
|
||||
Manager.getInstance(RecordingManager.class).startRecording(cutscene, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package me.unurled.sacredrealms.sr.gui.treasure;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
import static me.unurled.sacredrealms.sr.utils.Logger.log;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package me.unurled.sacredrealms.sr.gui.treasure;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import me.unurled.sacredrealms.sr.components.treasure.Treasure;
|
||||
import me.unurled.sacredrealms.sr.components.treasure.TreasureManager;
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
package me.unurled.sacredrealms.sr.utils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class Component {
|
||||
|
||||
public static final String NOT_PLAYER = "<red>You must be a player to use this command.";
|
||||
public static final String NO_PERMISSION = "<red>You do not have permission to use this command.";
|
||||
public static final String ERROR =
|
||||
"<red>An error occurred while executing this command. Please" + " contact an admin.";
|
||||
public static final String PLAYER_NOT_FOUND = "<red>Player not found.";
|
||||
|
||||
private static MiniMessage miniMessage;
|
||||
|
||||
private Component() {}
|
||||
|
||||
public static net.kyori.adventure.text.@NotNull Component comp(String msg) {
|
||||
if (miniMessage == null) {
|
||||
miniMessage = MiniMessage.miniMessage();
|
||||
}
|
||||
return miniMessage.deserialize(msg);
|
||||
}
|
||||
|
||||
public static net.kyori.adventure.text.@NotNull TextComponent textComp(String msg) {
|
||||
if (miniMessage == null) {
|
||||
miniMessage = MiniMessage.miniMessage();
|
||||
}
|
||||
return (TextComponent) miniMessage.deserialize(msg);
|
||||
}
|
||||
|
||||
public static List<net.kyori.adventure.text.Component> fromStringList(
|
||||
@NotNull List<String> list) {
|
||||
return list.stream().map(Component::comp).collect(Collectors.toList());
|
||||
}
|
||||
}
|
|
@ -1,12 +1,10 @@
|
|||
package me.unurled.sacredrealms.sr.utils;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.Frame;
|
||||
import me.unurled.sacredrealms.sr.components.cutscene.Marker;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.title.Title;
|
||||
import net.kyori.adventure.title.Title.Times;
|
||||
|
@ -32,36 +30,4 @@ public class CutsceneUtil {
|
|||
Duration.ofSeconds(fadeOut)));
|
||||
p.showTitle(title);
|
||||
}
|
||||
|
||||
public static @NotNull List<Frame> interpolateFrames(
|
||||
@NotNull Marker startMarker, @NotNull Marker endMarker, long stepMillis) {
|
||||
long duration = startMarker.getOverAllTime();
|
||||
|
||||
int numFrames = (int) (duration / stepMillis);
|
||||
|
||||
double xDiff = (endMarker.getStart().getX() - startMarker.getStart().getX()) / numFrames;
|
||||
double yDiff = (endMarker.getStart().getY() - startMarker.getStart().getY()) / numFrames;
|
||||
double zDiff = (endMarker.getStart().getZ() - startMarker.getStart().getZ()) / numFrames;
|
||||
double yawDiff = (endMarker.getStart().getYaw() - startMarker.getStart().getYaw()) / numFrames;
|
||||
double pitchDiff =
|
||||
(endMarker.getStart().getPitch() - startMarker.getStart().getPitch()) / numFrames;
|
||||
|
||||
ArrayList<Frame> frames = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < numFrames; i++) {
|
||||
|
||||
double x = startMarker.getStart().getX() + xDiff * i;
|
||||
double y = startMarker.getStart().getY() + yDiff * i;
|
||||
double z = startMarker.getStart().getZ() + zDiff * i;
|
||||
double yaw = startMarker.getStart().getYaw() + yawDiff * i;
|
||||
double pitch = startMarker.getStart().getPitch() + pitchDiff * i;
|
||||
|
||||
Frame frame =
|
||||
new Frame(
|
||||
new Location(startMarker.getStart().getWorld(), x, y, z, (float) yaw, (float) pitch));
|
||||
|
||||
frames.add(frame);
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package me.unurled.sacredrealms.sr.utils;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.comp;
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
|
||||
import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.syncSRToPlayer;
|
||||
import static me.unurled.srcore.utils.Component.comp;
|
||||
import static me.unurled.srcore.utils.Component.textComp;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import java.util.ArrayList;
|
||||
|
|
145
src/main/java/me/unurled/sacredrealms/sr/utils/Region.java
Normal file
145
src/main/java/me/unurled/sacredrealms/sr/utils/Region.java
Normal file
|
@ -0,0 +1,145 @@
|
|||
package me.unurled.sacredrealms.sr.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class Region {
|
||||
private Location corner1;
|
||||
private Location corner2;
|
||||
|
||||
public Region() {
|
||||
this.corner1 = null;
|
||||
this.corner2 = null;
|
||||
}
|
||||
|
||||
public boolean isSet() {
|
||||
return corner1 != null && corner2 != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public World getWorld() {
|
||||
if (corner1 == null) return null;
|
||||
return corner1.getWorld();
|
||||
}
|
||||
|
||||
public boolean isIn(final @NotNull Location loc) {
|
||||
if (corner1 == null || corner2 == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double xMin = Math.min(corner1.getX(), corner2.getX());
|
||||
double xMax = Math.max(corner1.getX(), corner2.getX());
|
||||
double yMin = Math.min(corner1.getY(), corner2.getY());
|
||||
double yMax = Math.max(corner1.getY(), corner2.getY());
|
||||
double zMin = Math.min(corner1.getZ(), corner2.getZ());
|
||||
double zMax = Math.max(corner1.getZ(), corner2.getZ());
|
||||
|
||||
// if the location is within the region in the x, y, and z axis
|
||||
return loc.getBlockX() >= xMin
|
||||
&& loc.getBlockX() <= xMax
|
||||
&& loc.getBlockY() >= yMin
|
||||
&& loc.getBlockY() <= yMax
|
||||
&& loc.getBlockZ() >= zMin
|
||||
&& loc.getBlockZ() <= zMax;
|
||||
}
|
||||
|
||||
public int getTotalBlockSize() {
|
||||
return (int) (this.getHeight() * this.getXWidth() * this.getZWidth());
|
||||
}
|
||||
|
||||
public double getHeight() {
|
||||
if (corner1 == null || corner2 == null) {
|
||||
return -1;
|
||||
}
|
||||
double yMin = Math.min(corner1.getY(), corner2.getY());
|
||||
double yMax = Math.max(corner1.getY(), corner2.getY());
|
||||
return yMax - yMin + 1;
|
||||
}
|
||||
|
||||
public double getXWidth() {
|
||||
if (corner1 == null || corner2 == null) {
|
||||
return -1;
|
||||
}
|
||||
double xMin = Math.min(corner1.getX(), corner2.getX());
|
||||
double xMax = Math.max(corner1.getX(), corner2.getX());
|
||||
return xMax - xMin + 1;
|
||||
}
|
||||
|
||||
public double getZWidth() {
|
||||
if (corner1 == null || corner2 == null) {
|
||||
return -1;
|
||||
}
|
||||
double zMin = Math.min(corner1.getZ(), corner2.getZ());
|
||||
double zMax = Math.max(corner1.getZ(), corner2.getZ());
|
||||
return zMax - zMin + 1;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<Block> blockList(World world) {
|
||||
if (corner1 == null || corner2 == null) {
|
||||
return List.of();
|
||||
}
|
||||
double xMin = Math.min(corner1.getX(), corner2.getX());
|
||||
double xMax = Math.max(corner1.getX(), corner2.getX());
|
||||
double yMin = Math.min(corner1.getY(), corner2.getY());
|
||||
double yMax = Math.max(corner1.getY(), corner2.getY());
|
||||
double zMin = Math.min(corner1.getZ(), corner2.getZ());
|
||||
double zMax = Math.max(corner1.getZ(), corner2.getZ());
|
||||
|
||||
final ArrayList<Block> bL = new ArrayList<>(this.getTotalBlockSize());
|
||||
for (double x = xMin; x <= xMax; ++x) {
|
||||
for (double y = yMin; y <= yMax; ++y) {
|
||||
for (double z = zMin; z <= zMax; ++z) {
|
||||
final Block b = world.getBlockAt((int) x, (int) y, (int) z);
|
||||
bL.add(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
return bL;
|
||||
}
|
||||
|
||||
public boolean isPlayerIn(@NotNull Player player) {
|
||||
return this.isIn(player.getLocation());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<Entity> getEntities() {
|
||||
List<Entity> entities = new ArrayList<>();
|
||||
if (corner1 == null || corner1.getWorld() == null) {
|
||||
return entities;
|
||||
}
|
||||
List<Block> blocks = blockList(corner1.getWorld());
|
||||
if (blocks == null) {
|
||||
return entities;
|
||||
}
|
||||
for (Block block : blocks) {
|
||||
entities.addAll(block.getWorld().getNearbyEntities(block.getLocation(), 1, 1, 1));
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
public Location corner1() {
|
||||
return corner1;
|
||||
}
|
||||
|
||||
public Location corner2() {
|
||||
return corner2;
|
||||
}
|
||||
|
||||
public Region setCorner1(Location corner1) {
|
||||
this.corner1 = corner1;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Region setCorner2(Location corner2) {
|
||||
this.corner2 = corner2;
|
||||
return this;
|
||||
}
|
||||
}
|
139
src/main/java/me/unurled/sacredrealms/sr/utils/RegionUtil.java
Normal file
139
src/main/java/me/unurled/sacredrealms/sr/utils/RegionUtil.java
Normal file
|
@ -0,0 +1,139 @@
|
|||
package me.unurled.sacredrealms.sr.utils;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Logger.error;
|
||||
import static me.unurled.sacredrealms.sr.utils.Logger.log;
|
||||
import static org.bukkit.Bukkit.getServer;
|
||||
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Slime;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
||||
import org.bukkit.scoreboard.Scoreboard;
|
||||
import org.bukkit.scoreboard.Team;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class RegionUtil {
|
||||
|
||||
private static final String REGIONSELECTOR = "srselector";
|
||||
|
||||
public static void killSelectorsWithTag(String inputTag) {
|
||||
for (World world : getServer().getWorlds()) {
|
||||
for (Entity entity : world.getEntities()) {
|
||||
for (String tag : entity.getScoreboardTags()) {
|
||||
if (tag.equals(REGIONSELECTOR + "-" + inputTag)) {
|
||||
entity.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void killAllSelectors() {
|
||||
for (World world : getServer().getWorlds()) {
|
||||
for (Entity entity : world.getEntities()) {
|
||||
for (String tag : entity.getScoreboardTags()) {
|
||||
if (tag.startsWith(REGIONSELECTOR + "-")) {
|
||||
entity.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawSelector(
|
||||
@NotNull Region region, World world, String id, NamedTextColor glowColor) {
|
||||
Location loc1 = region.corner1();
|
||||
Location loc2 = region.corner2();
|
||||
if (loc1.getWorld() == null || !loc1.getWorld().equals(loc2.getWorld())) {
|
||||
return;
|
||||
}
|
||||
int minx = Math.min(loc1.getBlockX(), loc2.getBlockX());
|
||||
int miny = Math.min(loc1.getBlockY(), loc2.getBlockY());
|
||||
int minz = Math.min(loc1.getBlockZ(), loc2.getBlockZ());
|
||||
int maxx = Math.max(loc1.getBlockX(), loc2.getBlockX());
|
||||
int maxy = Math.max(loc1.getBlockY(), loc2.getBlockY());
|
||||
int maxz = Math.max(loc1.getBlockZ(), loc2.getBlockZ());
|
||||
|
||||
Scoreboard board = Bukkit.getScoreboardManager().getMainScoreboard();
|
||||
|
||||
int highestNumber = 0;
|
||||
|
||||
for (Team team : board.getTeams()) {
|
||||
if (team.getName().startsWith(REGIONSELECTOR + "+")) {
|
||||
String number = team.getName().substring(11);
|
||||
try {
|
||||
int tempNumber = Integer.parseInt(number);
|
||||
if (tempNumber >= highestNumber) {
|
||||
highestNumber = tempNumber;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log(REGIONSELECTOR + "+" + (highestNumber + 1));
|
||||
|
||||
Team selectorTeam = board.registerNewTeam(REGIONSELECTOR + "+" + (highestNumber + 1));
|
||||
if (glowColor != null) {
|
||||
selectorTeam.color(glowColor);
|
||||
}
|
||||
selectorTeam.setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.NEVER);
|
||||
|
||||
for (double x = minx; x <= maxx; x++) {
|
||||
makeSlime(id, world, selectorTeam, x, miny, minz);
|
||||
makeSlime(id, world, selectorTeam, x, maxy, minz);
|
||||
makeSlime(id, world, selectorTeam, x, miny, maxz);
|
||||
makeSlime(id, world, selectorTeam, x, maxy, maxz);
|
||||
}
|
||||
|
||||
for (double y = miny; y <= maxy; y++) {
|
||||
makeSlime(id, world, selectorTeam, minx, y, minz);
|
||||
makeSlime(id, world, selectorTeam, maxx, y, minz);
|
||||
makeSlime(id, world, selectorTeam, minx, y, maxz);
|
||||
makeSlime(id, world, selectorTeam, maxx, y, maxz);
|
||||
}
|
||||
|
||||
for (double z = minz; z <= maxz; z++) {
|
||||
makeSlime(id, world, selectorTeam, minx, miny, z);
|
||||
makeSlime(id, world, selectorTeam, maxx, miny, z);
|
||||
makeSlime(id, world, selectorTeam, minx, maxy, z);
|
||||
makeSlime(id, world, selectorTeam, maxx, maxy, z);
|
||||
}
|
||||
}
|
||||
|
||||
private static void makeSlime(
|
||||
String id, @NotNull World world, @NotNull Team selectorTeam, double x, double y, double z) {
|
||||
Slime slime =
|
||||
(Slime)
|
||||
world.spawnEntity(
|
||||
new Location(world, x + 0.5, y, z + 0.5), EntityType.SLIME, SpawnReason.CUSTOM);
|
||||
slime.setSize(2);
|
||||
slime.setAI(false);
|
||||
slime.setGravity(false);
|
||||
slime.setCollidable(false);
|
||||
slime.setSilent(true);
|
||||
slime.setCanPickupItems(false);
|
||||
slime.setGlowing(true);
|
||||
slime.setInvulnerable(true);
|
||||
slime.setInvisible(true);
|
||||
slime.addScoreboardTag(REGIONSELECTOR + "-" + id);
|
||||
slime.setPersistent(true);
|
||||
selectorTeam.addEntry(String.valueOf(slime.getUniqueId()));
|
||||
}
|
||||
|
||||
public void removeTempTeams() {
|
||||
Scoreboard board = Bukkit.getScoreboardManager().getMainScoreboard();
|
||||
for (Team team : board.getTeams()) {
|
||||
if (team.getName().startsWith(REGIONSELECTOR + "+")) {
|
||||
team.unregister();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package me.unurled.sacredrealms.sr.utils;
|
||||
|
||||
import static me.unurled.sacredrealms.sr.utils.Component.comp;
|
||||
import static me.unurled.srcore.utils.Component.comp;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue