add of SR-Core and many more things
Some checks failed
Build / build (push) Failing after 1m19s

This commit is contained in:
unurled 2024-09-06 09:29:26 +02:00
parent d58e3da6ac
commit ced4c0d186
Signed by: unurled
GPG key ID: EFC5F5E709B47DDD
122 changed files with 13914 additions and 524 deletions

View file

@ -1,8 +1,10 @@
import net.minecrell.pluginyml.bukkit.BukkitPluginDescription
plugins { plugins {
`java-library` `java-library`
id("io.papermc.paperweight.userdev") version "1.7.1" id("io.papermc.paperweight.userdev") version "1.7.2"
id("io.github.goooler.shadow") version "8.1.7" id("org.sonarqube") version "5.1.0.4882"
id("org.sonarqube") version "4.4.1.3373" id("net.minecrell.plugin-yml.paper") version "0.6.0"
} }
// from 1.20.5+ upward, spigot is not supported // from 1.20.5+ upward, spigot is not supported
@ -13,23 +15,42 @@ group = "me.unurled.sacredrealms"
version = "0.1.0" version = "0.1.0"
description = "The main SR plugin." description = "The main SR plugin."
val mcVersion = "1.21-R0.1-SNAPSHOT" val mcVersion = "1.21.1-R0.1-SNAPSHOT"
val redisVersion = "5.2.0-beta2" val redisVersion = "5.2.0-beta4"
val invuiVersion = "1.32" val invuiVersion = "1.36"
val gsonVersion = "2.11.0"
val javaVersion = 21 val javaVersion = 21
repositories { repositories {
mavenCentral() mavenCentral()
maven("https://repo.xenondevs.xyz/releases") maven {
name = "invui"
url = uri("https://repo.xenondevs.xyz/releases/")
}
maven {
name = "packetevents"
url = uri("https://repo.codemc.io/repository/maven-releases/")
}
maven {
name = "unurled"
url = uri("https://repo.unurled.me/releases")
}
} }
dependencies { dependencies {
paperweight.paperDevBundle(mcVersion) paperweight.paperDevBundle(mcVersion)
implementation("redis.clients:jedis:${redisVersion}")
compileOnly("xyz.xenondevs.invui:invui:${invuiVersion}") compileOnly("xyz.xenondevs.invui:invui:${invuiVersion}")
paperLibrary("com.google.code.gson", "gson", gsonVersion)
paperLibrary("redis.clients", "jedis", redisVersion)
paperLibrary("com.github.retrooper", "packetevents-spigot", "2.4.0")
paperLibrary("me.unurled", "SR-Core", "0.1.0")
} }
java { java {
@ -45,33 +66,6 @@ tasks {
javadoc { javadoc {
options.encoding = Charsets.UTF_8.name() options.encoding = Charsets.UTF_8.name()
} }
processResources {
filteringCharset = Charsets.UTF_8.name()
val props = mapOf(
"name" to project.name,
"version" to project.version,
"description" to project.description,
"apiVersion" to "1.20"
)
inputs.properties(props)
filesMatching("paper-plugin.yml") {
expand(props)
}
}
build {
dependsOn(shadowJar)
}
shadowJar {
archiveClassifier.set("")
relocate("com.google", "libs.com.google")
relocate("org.apache", "libs.org.apache")
relocate("org.intellij", "libs.org.intellij")
relocate("org.jetbrains", "libs.org.jetbrains")
relocate("org.json", "libs.org.json")
relocate("redis", "libs.redis")
// relocate("xyz.xenondevs", "libs.xyz.xenondevs")
exclude("org.slf4j")
}
sonar { sonar {
properties { properties {
property("sonar.projectKey", "Sacred-Realms") property("sonar.projectKey", "Sacred-Realms")
@ -79,3 +73,85 @@ tasks {
} }
} }
} }
paper {
main = "me.unurled.sacredrealms.sr.SR"
bootstrapper = "me.unurled.sacredrealms.sr.SRBootstrap"
loader = "me.unurled.sacredrealms.sr.SRLoader"
hasOpenClassloader = false
generateLibrariesJson = true
foliaSupported = false
apiVersion = "1.21"
load = BukkitPluginDescription.PluginLoadOrder.STARTUP
author = "unurled"
prefix = "SR"
defaultPermission = BukkitPluginDescription.Permission.Default.OP
permissions {
register("sr.*") {
children = listOf(
"sr.tutorial",
"sr.spawn",
"sr.attributes",
"sr.clientbuild",
"sr.level",
"sr.entitytype",
"sr.spawnentity",
"sr.admin.item",
"sr.resetadventure",
"sr.treasure.manage",
"sr.difficulty.*",
"sr.cutscene"
)
description = "Gives access to all Sacred Realms permissions."
}
register("sr.tutorial") {
description = "Gives access to the tutorial command."
default = BukkitPluginDescription.Permission.Default.NOT_OP
}
register("sr.spawn") {
description = "Gives access to the spawn command."
default = BukkitPluginDescription.Permission.Default.NOT_OP
}
register("sr.attributes") {
description = "Gives access to the attributes command."
}
register("sr.clientbuild") {
description = "Gives access to the clientbuild command."
}
register("sr.level") {
description = "Gives access to the level command."
}
register("sr.entitytype") {
description = "Gives access to the entitytype command."
}
register("sr.spawnentity") {
description = "Gives access to the spawnentity command."
}
register("sr.admin.item") {
description = "Gives access to the admin item command."
}
register("sr.resetadventure") {
description = "Gives access to the resetadventure command."
}
register("sr.treasure.manage") {
description = "Gives access to the treasure manage command."
}
register("sr.difficulty.*") {
description = "Gives access to all difficulty commands."
children = listOf(
"sr.difficulty.self",
"sr.difficulty.manage"
)
}
register("sr.cutscene") {
description = "Gives access to the cutscene command."
}
}
}

View file

@ -1 +1,2 @@
systemProp.sonar.gradle.skipCompile=true systemProp.sonar.gradle.skipCompile=true
org.gradle.jvmargs=-Xmx16384M

View file

@ -1,34 +1,73 @@
package me.unurled.sacredrealms.sr; package me.unurled.sacredrealms.sr;
import me.unurled.sacredrealms.sr.managers.Managers; import com.github.retrooper.packetevents.PacketEvents;
import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder;
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.entity.EntityManager;
import me.unurled.sacredrealms.sr.components.item.ItemManager;
import me.unurled.sacredrealms.sr.components.npc.NPCManager;
import me.unurled.sacredrealms.sr.components.pack.ResourcePackManager;
import me.unurled.sacredrealms.sr.components.pack.animatedjava.AnimatedJavaManager;
import me.unurled.sacredrealms.sr.components.pack.background.BackgroundManager;
import me.unurled.sacredrealms.sr.components.player.PlayerManager;
import me.unurled.sacredrealms.sr.components.treasure.TreasureManager;
import me.unurled.sacredrealms.sr.config.ConfigManager;
import me.unurled.sacredrealms.sr.data.DataManager;
import me.unurled.srcore.SRCore;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import xyz.xenondevs.invui.InvUI; import xyz.xenondevs.invui.InvUI;
public final class SR extends JavaPlugin { public final class SR extends JavaPlugin {
private static SR instance; private static SR plugin;
private Managers managers;
public static SR getInstance() { public static SR getPlugin() {
return instance; return plugin;
}
@Override
public void onLoad() {
PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this));
// On Bukkit, calling this here is essential, hence the name "load"
PacketEvents.getAPI().load();
} }
@Override @Override
public void onEnable() { public void onEnable() {
instance = this; plugin = this;
SRCore.getInstance().setPlugin(this);
PacketEvents.getAPI().init();
SRCore.getInstance()
.getManagers()
.register(
List.of(
ConfigManager.class,
DataManager.class,
AnimatedJavaManager.class,
PlayerManager.class,
CombatManager.class,
ItemManager.class,
EntityManager.class,
NPCManager.class,
BlockManager.class,
ClientBuildManager.class,
TreasureManager.class,
BackgroundManager.class,
ResourcePackManager.class));
InvUI.getInstance().setPlugin(this); InvUI.getInstance().setPlugin(this);
managers = new Managers();
} }
@Override @Override
public void onDisable() { public void onDisable() {
managers.unload(); SRCore.getInstance().unload();
managers = null;
}
public Managers getManagers() { PacketEvents.getAPI().terminate();
return managers;
} }
} }

View file

@ -1,8 +1,15 @@
package me.unurled.sacredrealms.sr; package me.unurled.sacredrealms.sr;
import com.google.gson.Gson;
import io.papermc.paper.plugin.loader.PluginClasspathBuilder; import io.papermc.paper.plugin.loader.PluginClasspathBuilder;
import io.papermc.paper.plugin.loader.PluginLoader; import io.papermc.paper.plugin.loader.PluginLoader;
import io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver; import io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
import org.eclipse.aether.artifact.DefaultArtifact; import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.graph.Dependency; import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.repository.RemoteRepository; import org.eclipse.aether.repository.RemoteRepository;
@ -12,15 +19,37 @@ public class SRLoader implements PluginLoader {
@Override @Override
public void classloader(@NotNull PluginClasspathBuilder classpathBuilder) { public void classloader(@NotNull PluginClasspathBuilder classpathBuilder) {
MavenLibraryResolver resolver = new MavenLibraryResolver(); MavenLibraryResolver resolver = new MavenLibraryResolver();
resolver.addDependency( resolver.addDependency(
new Dependency(new DefaultArtifact("xyz.xenondevs.invui:inventory-access-r20:1.32"), null)); new Dependency(new DefaultArtifact("xyz.xenondevs.invui:invui:pom:1.36"), null));
resolver.addDependency(
new Dependency(new DefaultArtifact("xyz.xenondevs.invui:invui-core:1.32"), null));
resolver.addRepository( resolver.addRepository(
new RemoteRepository.Builder("invui", "default", "https://repo.xenondevs.xyz/releases/") new RemoteRepository.Builder("invui", "default", "https://repo.xenondevs.xyz/releases/")
.build()); .build());
classpathBuilder.addLibrary(resolver); classpathBuilder.addLibrary(resolver);
PluginLibraries pluginLibraries = load();
pluginLibraries.asDependencies().forEach(resolver::addDependency);
pluginLibraries.asRepositories().forEach(resolver::addRepository);
classpathBuilder.addLibrary(resolver);
}
public PluginLibraries load() {
try (var in = getClass().getResourceAsStream("/paper-libraries.json")) {
return new Gson()
.fromJson(new InputStreamReader(in, StandardCharsets.UTF_8), PluginLibraries.class);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private record PluginLibraries(Map<String, String> repositories, List<String> dependencies) {
public Stream<Dependency> asDependencies() {
return dependencies.stream().map(d -> new Dependency(new DefaultArtifact(d), null));
}
public Stream<RemoteRepository> asRepositories() {
return repositories.entrySet().stream()
.map(e -> new RemoteRepository.Builder(e.getKey(), "default", e.getValue()).build());
}
} }
} }

View file

@ -1,15 +1,17 @@
package me.unurled.sacredrealms.sr.commands; package me.unurled.sacredrealms.sr.commands;
import static me.unurled.sacredrealms.sr.utils.Logger.error; import static me.unurled.sacredrealms.sr.utils.Logger.error;
import static me.unurled.sacredrealms.sr.utils.Logger.log;
import io.papermc.paper.command.brigadier.BasicCommand; import io.papermc.paper.command.brigadier.BasicCommand;
import io.papermc.paper.command.brigadier.Commands; import io.papermc.paper.command.brigadier.Commands;
import io.papermc.paper.plugin.bootstrap.BootstrapContext; import io.papermc.paper.plugin.bootstrap.BootstrapContext;
import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager; import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager;
import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents;
import java.util.Collection;
import java.util.List;
import me.unurled.sacredrealms.sr.commands.admin.AttributeCommand; import me.unurled.sacredrealms.sr.commands.admin.AttributeCommand;
import me.unurled.sacredrealms.sr.commands.admin.ClientBuildCommand; 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.EntityTypeCommand;
import me.unurled.sacredrealms.sr.commands.admin.ItemCommand; import me.unurled.sacredrealms.sr.commands.admin.ItemCommand;
import me.unurled.sacredrealms.sr.commands.admin.LevelCommand; import me.unurled.sacredrealms.sr.commands.admin.LevelCommand;
@ -17,12 +19,22 @@ import me.unurled.sacredrealms.sr.commands.admin.SpawnEntityCommand;
import me.unurled.sacredrealms.sr.commands.admin.TreasureCommand; import me.unurled.sacredrealms.sr.commands.admin.TreasureCommand;
import me.unurled.sacredrealms.sr.commands.player.DifficultyCommand; import me.unurled.sacredrealms.sr.commands.player.DifficultyCommand;
import me.unurled.sacredrealms.sr.commands.player.ResetAdventureCommand; import me.unurled.sacredrealms.sr.commands.player.ResetAdventureCommand;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.jetbrains.annotations.NotNull;
public class CommandManager extends Manager { public class CommandManager extends Manager {
private static <T extends BasicCommand> void registerCommand( private static <T extends BasicCommand> void registerCommand(
String command, String description, BootstrapContext ctx, Class<T> clazz) { String command, String description, @NotNull BootstrapContext ctx, Class<T> clazz) {
registerCommand(command, description, List.of(), ctx, clazz);
}
private static <T extends BasicCommand> void registerCommand(
String command,
String description,
@NotNull Collection<String> aliases,
@NotNull BootstrapContext ctx,
Class<T> clazz) {
LifecycleEventManager<BootstrapContext> man = ctx.getLifecycleManager(); LifecycleEventManager<BootstrapContext> man = ctx.getLifecycleManager();
try { try {
@ -31,9 +43,8 @@ public class CommandManager extends Manager {
LifecycleEvents.COMMANDS, LifecycleEvents.COMMANDS,
event -> { event -> {
final Commands commands = event.registrar(); final Commands commands = event.registrar();
commands.register(command, description, instance); commands.register(command, description, aliases, instance);
}); });
log("Registered command: " + command);
} catch (Exception e) { } catch (Exception e) {
error("Failed to register command: " + command + " - " + e.getMessage()); error("Failed to register command: " + command + " - " + e.getMessage());
} }
@ -54,5 +65,7 @@ public class CommandManager extends Manager {
"resetadventure", "Reset the adventure of the player.", ctx, ResetAdventureCommand.class); "resetadventure", "Reset the adventure of the player.", ctx, ResetAdventureCommand.class);
registerCommand( registerCommand(
"difficulty", "Set the difficulty of the player.", ctx, DifficultyCommand.class); "difficulty", "Set the difficulty of the player.", ctx, DifficultyCommand.class);
registerCommand("cutscene", "Cutscene commands.", List.of("cs"), ctx, CutsceneCommand.class);
} }
} }

View file

@ -13,7 +13,7 @@ import me.unurled.sacredrealms.sr.components.attributes.Attribute;
import me.unurled.sacredrealms.sr.components.player.PlayerManager; import me.unurled.sacredrealms.sr.components.player.PlayerManager;
import me.unurled.sacredrealms.sr.components.player.SRPlayer; import me.unurled.sacredrealms.sr.components.player.SRPlayer;
import me.unurled.sacredrealms.sr.gui.attributes.AttributesGUI; import me.unurled.sacredrealms.sr.gui.attributes.AttributesGUI;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -192,7 +192,7 @@ public class AttributeCommand implements BasicCommand {
* Executes the command with the given {@link CommandSourceStack} and arguments. * Executes the command with the given {@link CommandSourceStack} and arguments.
* *
* @param commandSourceStack the commandSourceStack of the command * @param commandSourceStack the commandSourceStack of the command
* @param args the arguments of the command ignoring repeated spaces * @param args the arguments of the command ignoring repeated spaces
*/ */
@Override @Override
public void execute(@NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) { public void execute(@NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) {
@ -252,12 +252,12 @@ public class AttributeCommand implements BasicCommand {
* Suggests possible completions for the given command {@link CommandSourceStack} and arguments. * Suggests possible completions for the given command {@link CommandSourceStack} and arguments.
* *
* @param commandSourceStack the commandSourceStack of the command * @param commandSourceStack the commandSourceStack of the command
* @param args the arguments of the command including repeated spaces * @param args the arguments of the command including repeated spaces
* @return a collection of suggestions * @return a collection of suggestions
*/ */
@Override @Override
public @NotNull Collection<String> suggest(@NotNull CommandSourceStack commandSourceStack, public @NotNull Collection<String> suggest(
@NotNull String[] args) { @NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) {
CommandSender sender = commandSourceStack.getSender(); CommandSender sender = commandSourceStack.getSender();
if (!sender.hasPermission("sr.attributes")) { if (!sender.hasPermission("sr.attributes")) {
return List.of(); return List.of();

View file

@ -16,7 +16,7 @@ import me.unurled.sacredrealms.sr.components.clientbuild.ClientBuild;
import me.unurled.sacredrealms.sr.components.clientbuild.ClientBuildManager; import me.unurled.sacredrealms.sr.components.clientbuild.ClientBuildManager;
import me.unurled.sacredrealms.sr.components.player.PlayerManager; import me.unurled.sacredrealms.sr.components.player.PlayerManager;
import me.unurled.sacredrealms.sr.components.player.SRPlayer; import me.unurled.sacredrealms.sr.components.player.SRPlayer;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
@ -179,6 +179,7 @@ public class ClientBuildCommand implements BasicCommand, Listener {
if (build != null) sender.sendMessage(build.getName()); if (build != null) sender.sendMessage(build.getName());
} }
} }
@EventHandler @EventHandler
public void onBlockPlace(@NotNull BlockPlaceEvent e) { public void onBlockPlace(@NotNull BlockPlaceEvent e) {
Player p = e.getPlayer(); Player p = e.getPlayer();
@ -226,7 +227,7 @@ public class ClientBuildCommand implements BasicCommand, Listener {
* Executes the command with the given {@link CommandSourceStack} and arguments. * Executes the command with the given {@link CommandSourceStack} and arguments.
* *
* @param commandSourceStack the commandSourceStack of the command * @param commandSourceStack the commandSourceStack of the command
* @param args the arguments of the command ignoring repeated spaces * @param args the arguments of the command ignoring repeated spaces
*/ */
@Override @Override
public void execute(@NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) { public void execute(@NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) {
@ -282,18 +283,18 @@ public class ClientBuildCommand implements BasicCommand, Listener {
* Suggests possible completions for the given command {@link CommandSourceStack} and arguments. * Suggests possible completions for the given command {@link CommandSourceStack} and arguments.
* *
* @param commandSourceStack the commandSourceStack of the command * @param commandSourceStack the commandSourceStack of the command
* @param args the arguments of the command including repeated spaces * @param args the arguments of the command including repeated spaces
* @return a collection of suggestions * @return a collection of suggestions
*/ */
@Override @Override
public @NotNull Collection<String> suggest(@NotNull CommandSourceStack commandSourceStack, public @NotNull Collection<String> suggest(
@NotNull String[] args) { @NotNull CommandSourceStack commandSourceStack, @NotNull String @NotNull [] args) {
if (args.length == 1) { if (args.length == 1) {
return List.of("create", DELETE, "list", MODIFY, "save", DISPLAY); return List.of("create", DELETE, "list", MODIFY, "save", DISPLAY);
} else if (args.length == 2 } else if (args.length == 2
&& (args[0].equalsIgnoreCase(DELETE) && (args[0].equalsIgnoreCase(DELETE)
|| args[0].equalsIgnoreCase(MODIFY) || args[0].equalsIgnoreCase(MODIFY)
|| args[0].equalsIgnoreCase(DISPLAY))) { || args[0].equalsIgnoreCase(DISPLAY))) {
ClientBuildManager clientBuildManager = Manager.getInstance(ClientBuildManager.class); ClientBuildManager clientBuildManager = Manager.getInstance(ClientBuildManager.class);
List<String> buildNames = clientBuildManager.getBuildNames(); List<String> buildNames = clientBuildManager.getBuildNames();
if (nameCompletions.isEmpty() || !new HashSet<>(nameCompletions).containsAll(buildNames)) { if (nameCompletions.isEmpty() || !new HashSet<>(nameCompletions).containsAll(buildNames)) {

View file

@ -0,0 +1,166 @@
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();
}
}

View file

@ -12,7 +12,7 @@ import java.util.List;
import me.unurled.sacredrealms.sr.components.entity.EntityManager; import me.unurled.sacredrealms.sr.components.entity.EntityManager;
import me.unurled.sacredrealms.sr.components.entity.SREntityType; import me.unurled.sacredrealms.sr.components.entity.SREntityType;
import me.unurled.sacredrealms.sr.gui.entitytype.EntityTypeGUI; import me.unurled.sacredrealms.sr.gui.entitytype.EntityTypeGUI;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -33,7 +33,7 @@ public class EntityTypeCommand implements BasicCommand {
} }
Window window = Window window =
Window.single().setViewer(p).setTitle(args[1]).setGui(EntityTypeGUI.listGui()).build(); Window.single().setViewer(p).setTitle("List").setGui(EntityTypeGUI.listGui()).build();
window.open(); window.open();
} }
@ -74,8 +74,7 @@ public class EntityTypeCommand implements BasicCommand {
try { try {
EntityType type = EntityType.valueOf(args[4]); EntityType type = EntityType.valueOf(args[4]);
EntityManager em = Manager.getInstance(EntityManager.class); EntityManager em = Manager.getInstance(EntityManager.class);
if (setType(sender, args, em, type)) { if (setType(sender, args, em, type)) {}
}
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
sender.sendMessage("Invalid entity type."); sender.sendMessage("Invalid entity type.");
} }
@ -91,7 +90,7 @@ public class EntityTypeCommand implements BasicCommand {
if (!em.getTypes().stream().map(SREntityType::getId).toList().contains(args[1])) { if (!em.getTypes().stream().map(SREntityType::getId).toList().contains(args[1])) {
sender.sendMessage("Invalid entity type."); sender.sendMessage("Invalid entity type.");
} }
// em.removeEntityType(em.getType(args[1])); // em.removeEntityType(em.getType(args[1]));
} }
private static void create(@NotNull CommandSender sender, @NotNull String @NotNull [] args) { private static void create(@NotNull CommandSender sender, @NotNull String @NotNull [] args) {
@ -109,13 +108,13 @@ public class EntityTypeCommand implements BasicCommand {
sender.sendMessage(textComp("<green>Entity type created successfully.")); sender.sendMessage(textComp("<green>Entity type created successfully."));
if (sender instanceof Player p) { if (sender instanceof Player p) {
// opens gui // opens gui
Window window = Window window =
Window.single() Window.single()
.setViewer(p) .setViewer(p)
.setTitle(args[1]) .setTitle(args[1])
.setGui(EntityTypeGUI.createGui(type)) .setGui(EntityTypeGUI.createGui(type))
.build(); .build();
window.open(); window.open();
} }
} }
@ -137,7 +136,7 @@ public class EntityTypeCommand implements BasicCommand {
* Executes the command with the given {@link CommandSourceStack} and arguments. * Executes the command with the given {@link CommandSourceStack} and arguments.
* *
* @param commandSourceStack the commandSourceStack of the command * @param commandSourceStack the commandSourceStack of the command
* @param args the arguments of the command ignoring repeated spaces * @param args the arguments of the command ignoring repeated spaces
*/ */
@Override @Override
public void execute(@NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) { public void execute(@NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) {
@ -165,12 +164,12 @@ public class EntityTypeCommand implements BasicCommand {
* Suggests possible completions for the given command {@link CommandSourceStack} and arguments. * Suggests possible completions for the given command {@link CommandSourceStack} and arguments.
* *
* @param commandSourceStack the commandSourceStack of the command * @param commandSourceStack the commandSourceStack of the command
* @param args the arguments of the command including repeated spaces * @param args the arguments of the command including repeated spaces
* @return a collection of suggestions * @return a collection of suggestions
*/ */
@Override @Override
public @NotNull Collection<String> suggest(@NotNull CommandSourceStack commandSourceStack, public @NotNull Collection<String> suggest(
@NotNull String[] args) { @NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) {
CommandSender sender = commandSourceStack.getSender(); CommandSender sender = commandSourceStack.getSender();
if (sender.hasPermission("sr.entitytype")) { if (sender.hasPermission("sr.entitytype")) {
if (args.length == 1) { if (args.length == 1) {

View file

@ -15,7 +15,7 @@ import me.unurled.sacredrealms.sr.components.item.ItemType;
import me.unurled.sacredrealms.sr.components.item.Rarity; import me.unurled.sacredrealms.sr.components.item.Rarity;
import me.unurled.sacredrealms.sr.components.item.abilities.Ability; import me.unurled.sacredrealms.sr.components.item.abilities.Ability;
import me.unurled.sacredrealms.sr.components.item.enchantments.Enchantment; import me.unurled.sacredrealms.sr.components.item.enchantments.Enchantment;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@ -380,7 +380,7 @@ public class ItemCommand implements BasicCommand {
.map( .map(
name -> { name -> {
if (name.name().startsWith(args[3].toUpperCase())) return name.name(); if (name.name().startsWith(args[3].toUpperCase())) return name.name();
return null; return "";
}) })
.toList(); .toList();
} }
@ -392,8 +392,8 @@ public class ItemCommand implements BasicCommand {
p.getInventory().setItemInMainHand(newItem.toItemStack()); p.getInventory().setItemInMainHand(newItem.toItemStack());
} }
@Nullable private static @NotNull List<String> modifyCompletion(@NotNull String @NotNull [] args) {
private static List<String> modifyCompletion(@NotNull String @NotNull [] args) { if (args.length < 3) return List.of();
if (args[2].equalsIgnoreCase(RARITY)) { if (args[2].equalsIgnoreCase(RARITY)) {
return Arrays.stream(Rarity.values()).map(Enum::name).toList(); return Arrays.stream(Rarity.values()).map(Enum::name).toList();
} else if (args[2].equalsIgnoreCase("type")) { } else if (args[2].equalsIgnoreCase("type")) {
@ -403,7 +403,7 @@ public class ItemCommand implements BasicCommand {
.map( .map(
name -> { name -> {
if (name.name().startsWith(args[3].toUpperCase())) return name.name(); if (name.name().startsWith(args[3].toUpperCase())) return name.name();
return null; return "";
}) })
.toList(); .toList();
} else if (args[2].equalsIgnoreCase(ENCHANTMENTS)) { } else if (args[2].equalsIgnoreCase(ENCHANTMENTS)) {
@ -414,12 +414,12 @@ public class ItemCommand implements BasicCommand {
return List.of("add", REMOVE); return List.of("add", REMOVE);
} else if (args[2].equalsIgnoreCase(CUSTOMMODELDATA)) { } else if (args[2].equalsIgnoreCase(CUSTOMMODELDATA)) {
try { try {
Integer.parseInt(args[3]); if (args.length == 4) Integer.parseInt(args[3]);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
return List.of("1"); return List.of("1");
} }
} }
return null; return List.of();
} }
@Nullable @Nullable
@ -507,14 +507,14 @@ public class ItemCommand implements BasicCommand {
return List.of(""); return List.of("");
} }
if (args.length == 1) { if (args.length <= 1) {
return List.of("list", "create", DELETE, "give", MODIFY); return List.of("list", "create", DELETE, "give", MODIFY);
} }
if (args.length == 2 if (args.length == 2
&& (args[0].equalsIgnoreCase(DELETE) && (args[0].equalsIgnoreCase(DELETE)
|| args[0].equalsIgnoreCase("give") || args[0].equalsIgnoreCase("give")
|| args[0].equalsIgnoreCase(MODIFY))) { || args[0].equalsIgnoreCase(MODIFY))) {
ItemManager im = Manager.getInstance(ItemManager.class); ItemManager im = Manager.getInstance(ItemManager.class);
return im.getItemIDs(); return im.getItemIDs();
} }

View file

@ -6,7 +6,7 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import me.unurled.sacredrealms.sr.components.player.PlayerManager; import me.unurled.sacredrealms.sr.components.player.PlayerManager;
import me.unurled.sacredrealms.sr.components.player.SRPlayer; import me.unurled.sacredrealms.sr.components.player.SRPlayer;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;

View file

@ -9,7 +9,7 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import me.unurled.sacredrealms.sr.components.entity.EntityManager; import me.unurled.sacredrealms.sr.components.entity.EntityManager;
import me.unurled.sacredrealms.sr.components.entity.SREntityType; import me.unurled.sacredrealms.sr.components.entity.SREntityType;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -28,11 +28,12 @@ public class SpawnEntityCommand implements BasicCommand {
return; return;
} }
SREntityType eType = em.getType(type); SREntityType eType = em.getType(type);
if (type == null) { if (eType == null) {
sender.sendMessage("Invalid entity type."); sender.sendMessage("Invalid entity type.");
return; return;
} }
em.spawnEntity(eType, amount, x, y, z, world); em.spawnEntity(eType, amount, x, y, z, world);
sender.sendMessage("Spawned " + amount + " " + eType.getName() + "s.");
} }
private int getAmount(CommandSender sender, String @NotNull [] args) { private int getAmount(CommandSender sender, String @NotNull [] args) {
@ -50,7 +51,7 @@ public class SpawnEntityCommand implements BasicCommand {
* Executes the command with the given {@link CommandSourceStack} and arguments. * Executes the command with the given {@link CommandSourceStack} and arguments.
* *
* @param commandSourceStack the commandSourceStack of the command * @param commandSourceStack the commandSourceStack of the command
* @param args the arguments of the command ignoring repeated spaces * @param args the arguments of the command ignoring repeated spaces
*/ */
@Override @Override
public void execute(@NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) { public void execute(@NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) {
@ -81,7 +82,7 @@ public class SpawnEntityCommand implements BasicCommand {
} }
} }
if (args[3].equals("~")) { if (args[3].equals("~")) {
y = p.getLocation().getX(); y = p.getLocation().getY();
} else { } else {
try { try {
y = Double.parseDouble(args[3]); y = Double.parseDouble(args[3]);
@ -91,7 +92,7 @@ public class SpawnEntityCommand implements BasicCommand {
} }
} }
if (args[4].equals("~")) { if (args[4].equals("~")) {
z = p.getLocation().getX(); z = p.getLocation().getZ();
} else { } else {
try { try {
z = Double.parseDouble(args[4]); z = Double.parseDouble(args[4]);
@ -138,12 +139,12 @@ public class SpawnEntityCommand implements BasicCommand {
* Suggests possible completions for the given command {@link CommandSourceStack} and arguments. * Suggests possible completions for the given command {@link CommandSourceStack} and arguments.
* *
* @param commandSourceStack the commandSourceStack of the command * @param commandSourceStack the commandSourceStack of the command
* @param args the arguments of the command including repeated spaces * @param args the arguments of the command including repeated spaces
* @return a collection of suggestions * @return a collection of suggestions
*/ */
@Override @Override
public @NotNull Collection<String> suggest(@NotNull CommandSourceStack commandSourceStack, public @NotNull Collection<String> suggest(
@NotNull String[] args) { @NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) {
CommandSender sender = commandSourceStack.getSender(); CommandSender sender = commandSourceStack.getSender();
if (sender.hasPermission("sr.spawn-entity")) { if (sender.hasPermission("sr.spawn-entity")) {
if (args.length == 1) { if (args.length == 1) {

View file

@ -11,7 +11,7 @@ import java.util.Set;
import me.unurled.sacredrealms.sr.components.treasure.Treasure; import me.unurled.sacredrealms.sr.components.treasure.Treasure;
import me.unurled.sacredrealms.sr.components.treasure.TreasureManager; import me.unurled.sacredrealms.sr.components.treasure.TreasureManager;
import me.unurled.sacredrealms.sr.gui.treasure.TreasureGUI; import me.unurled.sacredrealms.sr.gui.treasure.TreasureGUI;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@ -54,11 +54,10 @@ public class TreasureCommand implements BasicCommand {
for (Treasure treasure : instance.getTreasures()) { for (Treasure treasure : instance.getTreasures()) {
String s = String s =
String.format( String.format(
"<click:run_command:tp %s %s %s>%s</click>x: %s, y: %s, z: %s", "<click:run_command:tp %s %s %s>x: %s, y: %s, z: %s</click>",
treasure.getLocation().getBlockX(), treasure.getLocation().getBlockX(),
treasure.getLocation().getBlockY(), treasure.getLocation().getBlockY(),
treasure.getLocation().getBlockZ(), treasure.getLocation().getBlockZ(),
treasure.getLocation().toString(),
treasure.getLocation().getBlockX(), treasure.getLocation().getBlockX(),
treasure.getLocation().getBlockY(), treasure.getLocation().getBlockY(),
treasure.getLocation().getBlockZ()); treasure.getLocation().getBlockZ());
@ -85,10 +84,12 @@ public class TreasureCommand implements BasicCommand {
Window window = Window window =
Window.single() Window.single()
.setViewer(p) .setViewer(p)
.setTitle("Attributes") .setTitle("Modifiy Treasure Chest")
.setGui(TreasureGUI.createGui(treasure)) .setGui(TreasureGUI.createGui(treasure))
.build(); .build();
window.open(); window.open();
} else {
p.sendMessage(textComp("<red>Target block is not a chest."));
} }
} }
@ -112,7 +113,10 @@ public class TreasureCommand implements BasicCommand {
} else { } else {
treasure = new Treasure(instance.getNextId(), block.getLocation()); treasure = new Treasure(instance.getNextId(), block.getLocation());
} }
block.setBlockData(Material.AIR.createBlockData());
instance.addTreasure(treasure); instance.addTreasure(treasure);
} else {
p.sendMessage(textComp("<red>Target block is not a chest."));
} }
} }
@ -120,10 +124,11 @@ public class TreasureCommand implements BasicCommand {
* Executes the command with the given {@link CommandSourceStack} and arguments. * Executes the command with the given {@link CommandSourceStack} and arguments.
* *
* @param commandSourceStack the commandSourceStack of the command * @param commandSourceStack the commandSourceStack of the command
* @param args the arguments of the command ignoring repeated spaces * @param args the arguments of the command ignoring repeated spaces
*/ */
@Override @Override
public void execute(@NotNull CommandSourceStack commandSourceStack, @NotNull String @NotNull [] args) { public void execute(
@NotNull CommandSourceStack commandSourceStack, @NotNull String @NotNull [] args) {
CommandSender sender = commandSourceStack.getSender(); CommandSender sender = commandSourceStack.getSender();
if (args.length == 0) { if (args.length == 0) {
sender.sendMessage("Usage: /treasure <create|modify|list|delete>"); sender.sendMessage("Usage: /treasure <create|modify|list|delete>");
@ -143,12 +148,12 @@ public class TreasureCommand implements BasicCommand {
* Suggests possible completions for the given command {@link CommandSourceStack} and arguments. * Suggests possible completions for the given command {@link CommandSourceStack} and arguments.
* *
* @param commandSourceStack the commandSourceStack of the command * @param commandSourceStack the commandSourceStack of the command
* @param args the arguments of the command including repeated spaces * @param args the arguments of the command including repeated spaces
* @return a collection of suggestions * @return a collection of suggestions
*/ */
@Override @Override
public @NotNull Collection<String> suggest(@NotNull CommandSourceStack commandSourceStack, public @NotNull Collection<String> suggest(
@NotNull String[] args) { @NotNull CommandSourceStack commandSourceStack, @NotNull String @NotNull [] args) {
if (args.length == 0) { if (args.length == 0) {
return List.of(CREATE, MODIFY, LIST, DELETE); return List.of(CREATE, MODIFY, LIST, DELETE);
} }

View file

@ -14,7 +14,7 @@ import me.unurled.sacredrealms.sr.components.difficulty.Difficulty;
import me.unurled.sacredrealms.sr.components.player.PlayerManager; import me.unurled.sacredrealms.sr.components.player.PlayerManager;
import me.unurled.sacredrealms.sr.components.player.SRPlayer; import me.unurled.sacredrealms.sr.components.player.SRPlayer;
import me.unurled.sacredrealms.sr.gui.difficulty.DifficultyGUI; import me.unurled.sacredrealms.sr.gui.difficulty.DifficultyGUI;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import net.kyori.adventure.audience.Audience; import net.kyori.adventure.audience.Audience;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -164,7 +164,7 @@ public class DifficultyCommand implements BasicCommand {
* Executes the command with the given {@link CommandSourceStack} and arguments. * Executes the command with the given {@link CommandSourceStack} and arguments.
* *
* @param commandSourceStack the commandSourceStack of the command * @param commandSourceStack the commandSourceStack of the command
* @param args the arguments of the command ignoring repeated spaces * @param args the arguments of the command ignoring repeated spaces
*/ */
@Override @Override
public void execute(@NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) { public void execute(@NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) {
@ -180,12 +180,12 @@ public class DifficultyCommand implements BasicCommand {
* Suggests possible completions for the given command {@link CommandSourceStack} and arguments. * Suggests possible completions for the given command {@link CommandSourceStack} and arguments.
* *
* @param commandSourceStack the commandSourceStack of the command * @param commandSourceStack the commandSourceStack of the command
* @param args the arguments of the command including repeated spaces * @param args the arguments of the command including repeated spaces
* @return a collection of suggestions * @return a collection of suggestions
*/ */
@Override @Override
public @NotNull Collection<String> suggest(@NotNull CommandSourceStack commandSourceStack, public @NotNull Collection<String> suggest(
@NotNull String[] args) { @NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) {
CommandSender sender = commandSourceStack.getSender(); CommandSender sender = commandSourceStack.getSender();
if (args.length == 0 && sender.hasPermission(DIFFICULTY_MANAGE)) { if (args.length == 0 && sender.hasPermission(DIFFICULTY_MANAGE)) {
return Bukkit.getOnlinePlayers().stream().map(Player::getName).toList(); return Bukkit.getOnlinePlayers().stream().map(Player::getName).toList();

View file

@ -12,7 +12,7 @@ import java.util.Objects;
import me.unurled.sacredrealms.sr.SR; import me.unurled.sacredrealms.sr.SR;
import me.unurled.sacredrealms.sr.components.player.PlayerManager; import me.unurled.sacredrealms.sr.components.player.PlayerManager;
import me.unurled.sacredrealms.sr.data.DataManager; import me.unurled.sacredrealms.sr.data.DataManager;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@ -39,7 +39,7 @@ public class ResetAdventureCommand implements BasicCommand {
} }
return; return;
} }
OfflinePlayer player = SR.getInstance().getServer().getOfflinePlayer(args[0]); OfflinePlayer player = SR.getPlugin().getServer().getOfflinePlayer(args[0]);
boolean status = resetAdventure(player); boolean status = resetAdventure(player);
if (status) { if (status) {
@ -62,12 +62,11 @@ public class ResetAdventureCommand implements BasicCommand {
return false; return false;
} }
/** /**
* Executes the command with the given {@link CommandSourceStack} and arguments. * Executes the command with the given {@link CommandSourceStack} and arguments.
* *
* @param commandSourceStack the commandSourceStack of the command * @param commandSourceStack the commandSourceStack of the command
* @param args the arguments of the command ignoring repeated spaces * @param args the arguments of the command ignoring repeated spaces
*/ */
@Override @Override
public void execute(@NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) { public void execute(@NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) {
@ -107,12 +106,12 @@ public class ResetAdventureCommand implements BasicCommand {
* Suggests possible completions for the given command {@link CommandSourceStack} and arguments. * Suggests possible completions for the given command {@link CommandSourceStack} and arguments.
* *
* @param commandSourceStack the commandSourceStack of the command * @param commandSourceStack the commandSourceStack of the command
* @param args the arguments of the command including repeated spaces * @param args the arguments of the command including repeated spaces
* @return a collection of suggestions * @return a collection of suggestions
*/ */
@Override @Override
public @NotNull Collection<String> suggest(@NotNull CommandSourceStack commandSourceStack, public @NotNull Collection<String> suggest(
@NotNull String[] args) { @NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) {
CommandSender sender = commandSourceStack.getSender(); CommandSender sender = commandSourceStack.getSender();
if (sender.hasPermission("sr.resetadventure")) { if (sender.hasPermission("sr.resetadventure")) {
if (args.length == 1) { if (args.length == 1) {

View file

@ -0,0 +1,64 @@
package me.unurled.sacredrealms.sr.components.block;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.ItemDisplay;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
public class Block {
private final Material BROKEN_MATERIAL = Material.AIR;
private final Material HITBOX_MATERIAL = Material.BARRIER;
private Location location;
private ItemDisplay entity;
private BlockItem item;
public Block(@NotNull Location location, @NotNull BlockItem blockItem) {
this.placeBlock(location, blockItem);
}
private void placeBlock(@NotNull Location location, BlockItem blockItem) {
World world = location.getWorld();
world.setBlockData(location, HITBOX_MATERIAL.createBlockData());
Location entityLocation = getLocationFromBlock(location);
world.spawn(
entityLocation,
ItemDisplay.class,
entity -> {
ItemStack item = blockItem.getItem(1);
entity.setItemStack(item);
entity.setPersistent(true);
entity.setInvulnerable(true);
this.entity = entity;
this.location = location;
this.item = blockItem;
});
}
public void breakBlock() {
this.entity.remove();
World world = this.location.getWorld();
world.setBlockData(this.location, BROKEN_MATERIAL.createBlockData());
}
public BlockItem getBlockItem() {
return this.item;
}
private @NotNull Location getLocationFromBlock(@NotNull Location location) {
Location entityLocation = location.clone();
entityLocation.setX(location.getX() + 0.5);
entityLocation.setY(location.getY() + 0.5);
entityLocation.setZ(location.getZ() + 0.5);
return entityLocation;
}
}

View file

@ -0,0 +1,72 @@
package me.unurled.sacredrealms.sr.components.block;
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
import static me.unurled.sacredrealms.sr.utils.Logger.error;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import me.unurled.sacredrealms.sr.constants.Keys;
import net.kyori.adventure.text.Component;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
public class BlockItem {
private static final Material BLOCK_MATERIAL = Material.STONE;
private final Component displayName;
private final List<Component> lore;
private final int customModelData;
public BlockItem(@NotNull ItemStack itemStack) {
this.displayName = itemStack.getItemMeta().displayName();
this.lore = itemStack.getItemMeta().lore();
this.customModelData = itemStack.getItemMeta().getCustomModelData();
}
public BlockItem(@NotNull Map<?, ?> configObject) {
String rawDisplayName = (String) configObject.get(Keys.BLOCK_DISPLAYNAME);
List<String> rawLore = new ArrayList<>();
if (configObject.get(Keys.BLOCK_LORE) instanceof List) {
try {
rawLore = (List<String>) configObject.get(Keys.BLOCK_LORE);
} catch (ClassCastException e) {
error("Failed to cast lore to List<String> " + e.getMessage());
}
}
this.displayName = textComp(rawDisplayName);
this.customModelData = (int) configObject.get(Keys.BLOCK_CUSTOMMODELDATA);
this.lore = new ArrayList<>();
for (String loreItem : rawLore) {
this.lore.add(textComp(loreItem));
}
}
public BlockItem(Component displayName, List<Component> lore, int customModelData) {
this.displayName = displayName;
this.lore = lore;
this.customModelData = customModelData;
}
public Component getDisplayName() {
return this.displayName;
}
public ItemStack getItem(int amount) {
ItemStack item = new ItemStack(BLOCK_MATERIAL, amount);
ItemMeta itemMeta = item.getItemMeta();
itemMeta.displayName(this.displayName);
itemMeta.lore(this.lore);
itemMeta.setCustomModelData(this.customModelData);
item.setItemMeta(itemMeta);
return item;
}
}

View file

@ -0,0 +1,84 @@
package me.unurled.sacredrealms.sr.components.block;
import static me.unurled.sacredrealms.sr.utils.Items.locationToString;
import java.util.HashMap;
import java.util.Map;
import me.unurled.sacredrealms.sr.SR;
import me.unurled.srcore.api.Manager;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Sound;
import org.bukkit.World;
import org.bukkit.entity.ItemDisplay;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
public class BlockManager extends Manager {
private final Map<String, Block> blocks = new HashMap<>();
public void addBlock(@NotNull Location location, @NotNull BlockItem blockItem) {
Block block = new Block(location, blockItem);
blocks.put(locationToString(location), block);
}
public void removeBlock(@NotNull Location location) {
String blockID = locationToString(location);
if (blocks.containsKey(blockID)) {
Block block = blocks.get(blockID);
block.breakBlock();
blocks.remove(blockID);
}
}
public void breakBlock(Location loc, Player player) {
String blockID = locationToString(loc);
if (blocks.containsKey(blockID)) {
Block block = blocks.get(blockID);
block.breakBlock();
player.playSound(loc, Sound.BLOCK_STONE_BREAK, 1, 1);
if (player.getGameMode() == GameMode.SURVIVAL) {
World world = loc.getWorld();
world.dropItemNaturally(loc, block.getBlockItem().getItem(1));
}
blocks.remove(blockID);
}
}
private @NotNull Location getLocationFromEntity(@NotNull Location location) {
Location entityLocation = location.clone();
entityLocation.setX(location.getX() - 0.5);
entityLocation.setY(location.getY() - 0.5);
entityLocation.setZ(location.getZ() - 0.5);
return entityLocation;
}
@Override
public void load() {
Bukkit.getScheduler()
.runTask(
SR.getPlugin(),
() -> {
for (World world : SR.getPlugin().getServer().getWorlds()) {
if (world == null) {
continue;
}
for (ItemDisplay entity : world.getEntitiesByClass(ItemDisplay.class)) {
Location location = getLocationFromEntity(entity.getLocation());
ItemStack itemStack = entity.getItemStack();
BlockItem blockItem = new BlockItem(itemStack);
entity.remove();
this.addBlock(location, blockItem);
}
}
});
}
}

View file

@ -2,15 +2,17 @@ package me.unurled.sacredrealms.sr.components.clientbuild;
import static me.unurled.sacredrealms.sr.utils.Logger.error; import static me.unurled.sacredrealms.sr.utils.Logger.error;
import com.google.gson.Gson;
import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer; import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonParseException; import com.google.gson.JsonParseException;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import me.unurled.sacredrealms.sr.utils.gson.LocationSerializer;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.jetbrains.annotations.NotNull;
public class ClientBuildDeserializer implements JsonDeserializer<ClientBuild> { public class ClientBuildDeserializer implements JsonDeserializer<ClientBuild> {
@ -31,28 +33,18 @@ public class ClientBuildDeserializer implements JsonDeserializer<ClientBuild> {
* @throws JsonParseException if json is not in the expected format of {@code typeofT} * @throws JsonParseException if json is not in the expected format of {@code typeofT}
*/ */
@Override @Override
public ClientBuild deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) public ClientBuild deserialize(
@NotNull JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException { throws JsonParseException {
String[] data = json.getAsString().split(";"); String[] data = json.getAsString().split(";");
ClientBuild build = new ClientBuild(data[0]); ClientBuild build = new ClientBuild(data[0]);
LocationSerializer locDes = new LocationSerializer();
for (String block : data[1].split(",")) { for (String block : data[1].split(",")) {
String[] spl = block.replace("{", "").replace("}", "").split("\\|"); String[] spl = block.replace("{", "").replace("}", "").split("\\|");
World world = Bukkit.getWorld(spl[0]); Location loc = locDes.deserialize(new Gson().toJsonTree(spl[0]), Location.class, context);
if (world == null) {
error("World " + spl[0] + " does not exist");
return build;
}
Location loc;
BlockData bData; BlockData bData;
try { try {
loc = bData = Bukkit.createBlockData(spl[1]);
new Location(
world,
Integer.parseInt(spl[1]),
Integer.parseInt(spl[2]),
Integer.parseInt(spl[3]));
bData = Bukkit.createBlockData(spl[4]);
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
error("Invalid block data: " + block); error("Invalid block data: " + block);
continue; continue;

View file

@ -15,7 +15,7 @@ import me.unurled.sacredrealms.sr.SR;
import me.unurled.sacredrealms.sr.commands.admin.ClientBuildCommand; import me.unurled.sacredrealms.sr.commands.admin.ClientBuildCommand;
import me.unurled.sacredrealms.sr.data.DataHandler; import me.unurled.sacredrealms.sr.data.DataHandler;
import me.unurled.sacredrealms.sr.data.DataManager; import me.unurled.sacredrealms.sr.data.DataManager;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
@ -41,7 +41,7 @@ public class ClientBuildManager extends Manager {
@Override @Override
public void load() { public void load() {
super.load(); super.load();
Bukkit.getPluginManager().registerEvents(new ClientBuildCommand(), SR.getInstance()); Bukkit.getPluginManager().registerEvents(new ClientBuildCommand(), SR.getPlugin());
} }
public List<ClientBuild> getBuilds() { public List<ClientBuild> getBuilds() {
@ -83,7 +83,7 @@ public class ClientBuildManager extends Manager {
if (dh == null) { if (dh == null) {
error("Failed to get DataHandler instance, can't load client builds."); error("Failed to get DataHandler instance, can't load client builds.");
error("Retrying in 10 seconds."); error("Retrying in 10 seconds.");
Bukkit.getScheduler().runTaskLaterAsynchronously(SR.getInstance(), this::loadData, 200L); Bukkit.getScheduler().runTaskLaterAsynchronously(SR.getPlugin(), this::loadData, 200L);
return; return;
} }
List<String> keys = dh.getKeysAll("sr.clientbuild"); List<String> keys = dh.getKeysAll("sr.clientbuild");
@ -130,7 +130,7 @@ public class ClientBuildManager extends Manager {
} }
Bukkit.getScheduler() Bukkit.getScheduler()
.runTaskAsynchronously( .runTaskAsynchronously(
SR.getInstance(), SR.getPlugin(),
() -> { () -> {
for (String name : names) { for (String name : names) {
ClientBuild build = getBuild(name); ClientBuild build = getBuild(name);

View file

@ -6,8 +6,10 @@ import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer; import com.google.gson.JsonSerializer;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Map.Entry; import java.util.Map.Entry;
import me.unurled.sacredrealms.sr.utils.gson.LocationSerializer;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.jetbrains.annotations.NotNull;
public class ClientBuildSerializer implements JsonSerializer<ClientBuild> { public class ClientBuildSerializer implements JsonSerializer<ClientBuild> {
@ -27,19 +29,16 @@ public class ClientBuildSerializer implements JsonSerializer<ClientBuild> {
* @return a JsonElement corresponding to the specified object. * @return a JsonElement corresponding to the specified object.
*/ */
@Override @Override
public JsonElement serialize(ClientBuild src, Type typeOfSrc, JsonSerializationContext context) { public JsonElement serialize(
@NotNull ClientBuild src, Type typeOfSrc, JsonSerializationContext context) {
StringBuilder s = new StringBuilder(); StringBuilder s = new StringBuilder();
s.append(src.getName()); s.append(src.getName());
s.append(";"); s.append(";");
LocationSerializer locSer = new LocationSerializer();
for (Entry<Location, BlockData> entry : src.getBlocks().entrySet()) { for (Entry<Location, BlockData> entry : src.getBlocks().entrySet()) {
s.append("{"); s.append("{");
s.append(entry.getKey().getWorld().getName()); JsonElement j = locSer.serialize(entry.getKey(), Location.class, context);
s.append("|"); s.append(j);
s.append(entry.getKey().getBlockX());
s.append("|");
s.append(entry.getKey().getBlockY());
s.append("|");
s.append(entry.getKey().getBlockZ());
s.append("|"); s.append("|");
s.append(entry.getValue().getAsString()); s.append(entry.getValue().getAsString());
s.append("},"); s.append("},");

View file

@ -12,10 +12,12 @@ import java.util.UUID;
import me.unurled.sacredrealms.sr.components.attributes.Attribute; import me.unurled.sacredrealms.sr.components.attributes.Attribute;
import me.unurled.sacredrealms.sr.components.entity.EntityManager; import me.unurled.sacredrealms.sr.components.entity.EntityManager;
import me.unurled.sacredrealms.sr.components.entity.SREntity; import me.unurled.sacredrealms.sr.components.entity.SREntity;
import me.unurled.sacredrealms.sr.components.entity.SREntityType;
import me.unurled.sacredrealms.sr.components.player.PlayerManager; import me.unurled.sacredrealms.sr.components.player.PlayerManager;
import me.unurled.sacredrealms.sr.components.player.SRPlayer; import me.unurled.sacredrealms.sr.components.player.SRPlayer;
import me.unurled.sacredrealms.sr.managers.Manager;
import me.unurled.sacredrealms.sr.utils.Items; import me.unurled.sacredrealms.sr.utils.Items;
import me.unurled.srcore.api.Manager;
import org.bukkit.Particle;
import org.bukkit.Sound; import org.bukkit.Sound;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Mob; import org.bukkit.entity.Mob;
@ -23,6 +25,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityDamageByBlockEvent; import org.bukkit.event.entity.EntityDamageByBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.EntityEquipment;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -33,7 +36,10 @@ public class CombatManager extends Manager {
private final Map<UUID, Map<UUID, Double>> historyMobDamage = new HashMap<>(); private final Map<UUID, Map<UUID, Double>> historyMobDamage = new HashMap<>();
private static void playerVictim( private static void playerVictim(
@NotNull EntityDamageByEntityEvent e, Player player, @NotNull Mob mob, PlayerManager pm) { @NotNull EntityDamageByEntityEvent e,
Player player,
@NotNull Mob mob,
@NotNull PlayerManager pm) {
// get equipment of damager // get equipment of damager
EntityEquipment equipment = mob.getEquipment(); EntityEquipment equipment = mob.getEquipment();
Double dStrength = Items.getTotalAttribute(equipment, Attribute.STRENGTH); Double dStrength = Items.getTotalAttribute(equipment, Attribute.STRENGTH);
@ -92,7 +98,7 @@ public class CombatManager extends Manager {
if (player1.getHealth() <= 0) { if (player1.getHealth() <= 0) {
player.damage(player.getHealth()); player.damage(player.getHealth());
} }
updateActionBar(player, player1); updateActionBar(player);
} }
spawnIndicator(player, false, damage); spawnIndicator(player, false, damage);
@ -100,6 +106,14 @@ public class CombatManager extends Manager {
// TODO: check for status effects (apply status effects depending item of damager) // TODO: check for status effects (apply status effects depending item of damager)
} }
@EventHandler
public void onDamage(@NotNull EntityDamageEvent e) {
if (e.getCause() != DamageCause.ENTITY_ATTACK || !(e.getEntity() instanceof Player)) {
e.setDamage(0.0);
e.setCancelled(true);
}
}
@EventHandler @EventHandler
public void onDamage(@NotNull EntityDamageByBlockEvent e) { public void onDamage(@NotNull EntityDamageByBlockEvent e) {
// TODO: Implement // TODO: Implement
@ -190,6 +204,16 @@ public class CombatManager extends Manager {
} else if (luck > 0 && luck < 1000 && RANDOM.nextBoolean()) { } else if (luck > 0 && luck < 1000 && RANDOM.nextBoolean()) {
// chance of critical hit // chance of critical hit
d.playSound(d, Sound.ENTITY_PLAYER_ATTACK_CRIT, 1.0f, 1.0f); d.playSound(d, Sound.ENTITY_PLAYER_ATTACK_CRIT, 1.0f, 1.0f);
for (int i = 0; i < 10; i++) {
d.spawnParticle(
Particle.CRIT,
entity.getLocation(),
10,
0.5 + (double) i / 10,
0.5 + (double) i / 10,
0.5 + (double) i / 10,
0.1);
}
// damage * 2 // damage * 2
damage = damage * 2; damage = damage * 2;
} }
@ -201,17 +225,31 @@ public class CombatManager extends Manager {
EntityManager em = Manager.getInstance(EntityManager.class); EntityManager em = Manager.getInstance(EntityManager.class);
SREntity ent = em.getEntity(entity.getUniqueId()); SREntity ent = em.getEntity(entity.getUniqueId());
if (ent != null) {
ent.setHealth(ent.getHealth() - damage);
}
if (entity.getHealth() <= 0) { if (entity.getHealth() <= 0) {
die(entity, d, pm, ent); die(entity, d, pm, ent);
return; return;
} }
// change entity health in name
if (ent != null) {
SREntityType type = em.getType(ent.getTypeId());
if (type != null) {
ent.applyName(type, entity);
}
}
spawnIndicator(entity, false, damage); spawnIndicator(entity, false, damage);
// TODO: check for status effects (apply status effects depending item of damager) // TODO: check for status effects (apply status effects depending item of damager)
} }
private void die( private void die(
LivingEntity entity, @NotNull Player d, @NotNull PlayerManager pm, SREntity ent) { @NotNull LivingEntity entity, @NotNull Player d, @NotNull PlayerManager pm, SREntity ent) {
entity.setHealth(0.0);
// entity is dead, give experience to player // entity is dead, give experience to player
SRPlayer player1 = pm.getPlayer(d.getUniqueId()); SRPlayer player1 = pm.getPlayer(d.getUniqueId());
if (player1 != null && ent != null) { if (player1 != null && ent != null) {

View file

@ -0,0 +1,26 @@
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);
}
}

View file

@ -0,0 +1,239 @@
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;
public Cutscene(String id, String name) {
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");
}
}
public Cutscene(@NotNull String id, String name, @NotNull ArrayList<Marker> markers) {
this.id = id.toUpperCase();
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");
}
}
public void setMarkers() {
for (Integer i : markerIds) {
markers.add(Marker.getMarker(i));
}
}
public void addMarker(Marker marker) {
this.markers.add(marker);
}
public String getId() {
return this.id.toUpperCase();
}
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);
}
}
}
}

View file

@ -0,0 +1,168 @@
package me.unurled.sacredrealms.sr.components.cutscene;
import static me.unurled.sacredrealms.sr.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.srcore.api.Manager;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
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 List<Cutscene> cutscenes;
// 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();
cutscenes = new ArrayList<>();
currentPlayingCutscenes = new HashMap<>();
playerOrigins = new HashMap<>();
cutsceneIds = new ArrayList<>();
}
/** Unload the manager */
@Override
public void unload() {
super.unload();
cutscenes.clear();
currentPlayingCutscenes.clear();
playerOrigins.clear();
cutsceneIds.clear();
}
public void createCutscene(String id) {
Cutscene cutscene = new Cutscene(id, id);
addCutscene(cutscene);
}
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!"));
return;
}
if (cutscenes.contains(cutscene) && !currentPlayingCutscenes.containsValue(p.getUniqueId())) {
currentPlayingCutscenes.put(cutscene.getId(), p.getUniqueId());
setPlayerOrigins(p);
cutscene.play(p);
}
}
@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()));
}
}

View file

@ -0,0 +1,7 @@
package me.unurled.sacredrealms.sr.components.cutscene;
import org.bukkit.entity.Player;
public class EntityCinematicAction {
private Player p;
}

View file

@ -0,0 +1,113 @@
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);
}
}

View file

@ -0,0 +1,146 @@
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
+ '}';
}
}

View file

@ -0,0 +1,23 @@
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());
}
}

View file

@ -0,0 +1,82 @@
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();
}
}

View file

@ -0,0 +1,63 @@
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());
}
}
}

View file

@ -0,0 +1,64 @@
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;
}
}
}

View file

@ -0,0 +1,37 @@
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;
}
}

View file

@ -0,0 +1,66 @@
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);
}
}

View file

@ -8,18 +8,23 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import me.unurled.sacredrealms.sr.components.attributes.Attribute;
import me.unurled.sacredrealms.sr.components.item.ItemStackDeserializer; import me.unurled.sacredrealms.sr.components.item.ItemStackDeserializer;
import me.unurled.sacredrealms.sr.components.item.ItemStackSerializer; import me.unurled.sacredrealms.sr.components.item.ItemStackSerializer;
import me.unurled.sacredrealms.sr.components.player.PotionEffectDeserializer; import me.unurled.sacredrealms.sr.components.player.PotionEffectDeserializer;
import me.unurled.sacredrealms.sr.data.DataHandler; import me.unurled.sacredrealms.sr.data.DataHandler;
import me.unurled.sacredrealms.sr.data.DataManager; import me.unurled.sacredrealms.sr.data.DataManager;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Mob; import org.bukkit.entity.Mob;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.bukkit.event.entity.EntityCombustEvent;
import org.bukkit.event.entity.EntitySpawnEvent; import org.bukkit.event.entity.EntitySpawnEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffect;
@ -70,6 +75,25 @@ public class EntityManager extends Manager {
}); });
} }
/** Save the data */
@Override
public void saveData() {
// for every entity if not player kill it
killAllEntities();
}
public void killAllEntities() {
entities.forEach(
(uuid, srEntity) -> {
Entity e = Bukkit.getEntity(uuid);
if (e instanceof LivingEntity liv && !(e instanceof Player)) {
liv.setHealth(0.0);
e.remove();
}
});
entities.clear();
}
public void saveType(@NotNull SREntityType type) { public void saveType(@NotNull SREntityType type) {
// save type // save type
DataManager dm = Manager.getInstance(DataManager.class); DataManager dm = Manager.getInstance(DataManager.class);
@ -100,8 +124,11 @@ public class EntityManager extends Manager {
entities.put(entity.getUuid(), entity); entities.put(entity.getUuid(), entity);
} }
public void addEntity(@NotNull Entity e) { public void addEntity(@NotNull SREntityType type, @NotNull Entity e) {
entities.put(e.getUniqueId(), new SREntity(e)); entities.put(
e.getUniqueId(),
new SREntity(
e, type.getAttributes().get(Attribute.HEALTH), type.getExperience(), type.getId()));
} }
public boolean isSREntity(@NotNull UUID uuid) { public boolean isSREntity(@NotNull UUID uuid) {
@ -131,7 +158,8 @@ public class EntityManager extends Manager {
// spawn entity // spawn entity
List<SREntity> srEntities = new ArrayList<>(); List<SREntity> srEntities = new ArrayList<>();
for (int i = 0; i < amount; i++) { for (int i = 0; i < amount; i++) {
Entity e = world.spawnEntity(new Location(world, x, y, z), type.getType()); Entity e =
world.spawnEntity(new Location(world, x, y, z), type.getType(), SpawnReason.CUSTOM);
if (e instanceof Mob mob) { if (e instanceof Mob mob) {
if (type.getHandItem() != null) { if (type.getHandItem() != null) {
mob.getEquipment().setItemInMainHand(type.getHandItem()); mob.getEquipment().setItemInMainHand(type.getHandItem());
@ -143,7 +171,13 @@ public class EntityManager extends Manager {
mob.getEquipment().setItemInOffHand(type.getSecondHandItem()); mob.getEquipment().setItemInOffHand(type.getSecondHandItem());
} }
} }
SREntity srEntity = new SREntity(e); SREntity srEntity =
new SREntity(
e, type.getAttributes().get(Attribute.HEALTH), type.getExperience(), type.getId());
if (type.getName() != null && !type.getName().isEmpty()) {
srEntity.applyName(type, e);
}
addEntity(srEntity); addEntity(srEntity);
srEntities.add(srEntity); srEntities.add(srEntity);
} }
@ -153,12 +187,19 @@ public class EntityManager extends Manager {
@EventHandler @EventHandler
public void onEntitySpawn(@NotNull EntitySpawnEvent e) { public void onEntitySpawn(@NotNull EntitySpawnEvent e) {
if (e.getEntity() instanceof Player) return; if (e.getEntity().getEntitySpawnReason() != SpawnReason.CUSTOM
&& e.getEntity().getEntitySpawnReason() != SpawnReason.COMMAND) {
if (isSREntity(e.getEntity().getUniqueId())) return; e.setCancelled(true);
}
if (!(e.getEntity() instanceof Mob)) return; }
/**
* cancel entity burn
*
* @param e
*/
@EventHandler
public void onEntityBurn(@NotNull EntityCombustEvent e) {
e.setCancelled(true); e.setCancelled(true);
} }
} }

View file

@ -1,16 +1,23 @@
package me.unurled.sacredrealms.sr.components.entity; package me.unurled.sacredrealms.sr.components.entity;
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
import java.util.UUID; import java.util.UUID;
import me.unurled.sacredrealms.sr.components.attributes.Attribute;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
public class SREntity { public class SREntity {
private final UUID uuid; private final UUID uuid;
private double health = 100; private final String typeId;
private Long experience = 0L; private double health;
private Long experience;
public SREntity(@NotNull Entity e) { public SREntity(@NotNull Entity e, double health, Long exp, String typeId) {
uuid = e.getUniqueId(); uuid = e.getUniqueId();
this.health = health;
this.experience = exp;
this.typeId = typeId;
} }
public UUID getUuid() { public UUID getUuid() {
@ -32,4 +39,23 @@ public class SREntity {
public void setHealth(double health) { public void setHealth(double health) {
this.health = health; this.health = health;
} }
public String getTypeId() {
return typeId;
}
public void applyName(@NotNull SREntityType type, @NotNull Entity e) {
e.customName(
textComp(
"<green>Lv."
+ type.getLevel()
+ " <gold>"
+ type.getName()
+ "<red>"
+ health
+ "/"
+ type.getAttributes().get(Attribute.HEALTH)
+ ""));
e.setCustomNameVisible(true);
}
} }

View file

@ -136,7 +136,7 @@ public class SREntityType {
} }
public EntityType getType() { public EntityType getType() {
return type = type == null ? EntityType.ZOMBIE : type; return type == null ? EntityType.ZOMBIE : type;
} }
public void setType(EntityType type) { public void setType(EntityType type) {
@ -144,7 +144,7 @@ public class SREntityType {
} }
public ItemStack getItem() { public ItemStack getItem() {
return item == null ? new ItemStack(Material.BARRIER) : item; return item == null ? new ItemStack(Material.AIR) : item;
} }
public void setItem(ItemStack item) { public void setItem(ItemStack item) {
@ -153,10 +153,10 @@ public class SREntityType {
public List<ItemStack> getArmor() { public List<ItemStack> getArmor() {
if (armor.isEmpty()) { if (armor.isEmpty()) {
armor.add(new ItemStack(Material.BARRIER)); armor.add(new ItemStack(Material.AIR));
armor.add(new ItemStack(Material.BARRIER)); armor.add(new ItemStack(Material.AIR));
armor.add(new ItemStack(Material.BARRIER)); armor.add(new ItemStack(Material.AIR));
armor.add(new ItemStack(Material.BARRIER)); armor.add(new ItemStack(Material.AIR));
} }
return armor; return armor;
} }
@ -167,7 +167,7 @@ public class SREntityType {
} }
public ItemStack getHandItem() { public ItemStack getHandItem() {
return handItem == null ? new ItemStack(Material.BARRIER) : handItem; return handItem == null ? new ItemStack(Material.AIR) : handItem;
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
@ -176,7 +176,7 @@ public class SREntityType {
} }
public ItemStack getSecondHandItem() { public ItemStack getSecondHandItem() {
return secondHandItem == null ? new ItemStack(Material.BARRIER) : secondHandItem; return secondHandItem == null ? new ItemStack(Material.AIR) : secondHandItem;
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")

View file

@ -150,7 +150,7 @@ public class Item {
} }
public Double getAttribute(Attribute attribute) { public Double getAttribute(Attribute attribute) {
return attributes.get(attribute); return attributes.getOrDefault(attribute, 0.0);
} }
public void addAttribute(Attribute attribute, double value) { public void addAttribute(Attribute attribute, double value) {
@ -244,7 +244,7 @@ public class Item {
+ description + description
+ "\", \"customModelData\": " + "\", \"customModelData\": "
+ customModelData + customModelData
+ "\", \"rarity\": \"" + ", \"rarity\": \""
+ rarity + rarity
+ "\", \"type\": \"" + "\", \"type\": \""
+ type + type

View file

@ -1,13 +1,14 @@
package me.unurled.sacredrealms.sr.components.item; package me.unurled.sacredrealms.sr.components.item;
import static me.unurled.sacredrealms.sr.utils.Logger.error;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import me.unurled.sacredrealms.sr.SR;
import me.unurled.sacredrealms.sr.data.DataHandler; import me.unurled.sacredrealms.sr.data.DataHandler;
import me.unurled.sacredrealms.sr.data.DataManager; import me.unurled.sacredrealms.sr.data.DataManager;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.bukkit.NamespacedKey; import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType; import org.bukkit.persistence.PersistentDataType;
@ -42,7 +43,7 @@ public class ItemManager extends Manager {
DataHandler dh = dm.getDataHandler(); DataHandler dh = dm.getDataHandler();
if (dh == null) { if (dh == null) {
SR.getInstance().getLogger().severe("DataHandler is null in ItemManager.loadData()!"); error("DataHandler is null in ItemManager.loadData()!");
return; return;
} }
@ -69,10 +70,12 @@ public class ItemManager extends Manager {
items.put(item.getId(), item); items.put(item.getId(), item);
} }
@Nullable
public Item getItem(String id) { public Item getItem(String id) {
return items.get(id); return items.get(id);
} }
@Nullable
public Item getItem(ItemStack item) { public Item getItem(ItemStack item) {
if (item == null) return null; if (item == null) return null;
if (item.getItemMeta() == null) return null; if (item.getItemMeta() == null) return null;

View file

@ -0,0 +1,10 @@
package me.unurled.sacredrealms.sr.components.npc;
public class NPCEntity {
private final int id;
public NPCEntity(int id) {
this.id = id;
}
}

View file

@ -0,0 +1,64 @@
package me.unurled.sacredrealms.sr.components.npc;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.UUID;
import me.unurled.sacredrealms.sr.SR;
import me.unurled.sacredrealms.sr.utils.ChunkWrapper;
import me.unurled.srcore.api.Manager;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.world.ChunkLoadEvent;
import org.jetbrains.annotations.NotNull;
public class NPCManager extends Manager {
private final Map<ChunkWrapper, HashSet<NPCEntity>> npcPerChunk = new HashMap<>();
public Map<UUID, NPCEntity> npcs = new HashMap<>();
public void register(@NotNull NPCEntity entity) {
// TODO: Register the entity
/*ChunkWrapper cw = new ChunkWrapper(entity.getClonedLocation().getChunk());
if (!npcPerChunk.containsKey(cw)) {
npcPerChunk.put(cw, new HashSet<>());
}
npcPerChunk.get(cw).add(entity);
entity.spawn();*/
}
public void removeEntity(NPCEntity entity) {
/*try {
entity.despawn();
} catch (Exception e) {
error("Failed to despawn entity: " + entity.getId());
}
ChunkWrapper cw = new ChunkWrapper(entity.getClonedLocation().getChunk());
if (npcPerChunk.containsKey(cw)) {
npcPerChunk.get(cw).remove(entity);
}*/
}
public void addEntity(NPCEntity entity) {
// npcs.put(entity.getEntity().getUniqueId(), entity);
}
@EventHandler
public void onChunkLoad(@NotNull ChunkLoadEvent e) {
ChunkWrapper cw = new ChunkWrapper(e.getChunk());
if (!npcPerChunk.containsKey(cw)) {
return;
}
Bukkit.getScheduler()
.scheduleSyncDelayedTask(
SR.getPlugin(),
() -> {
HashSet<NPCEntity> npc = npcPerChunk.get(cw);
for (NPCEntity entity : npc) {
register(entity);
}
},
20L * 2);
}
}

View file

@ -0,0 +1,158 @@
package me.unurled.sacredrealms.sr.components.pack;
import static me.unurled.sacredrealms.sr.utils.File.getFileChecksum;
import static me.unurled.sacredrealms.sr.utils.File.zipDirectory;
import static me.unurled.sacredrealms.sr.utils.File.zipFile;
import static me.unurled.sacredrealms.sr.utils.Logger.error;
import static me.unurled.sacredrealms.sr.utils.Logger.log;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
import java.util.zip.ZipOutputStream;
import me.unurled.sacredrealms.sr.SR;
import me.unurled.sacredrealms.sr.components.pack.hosts.HostingProvider;
import me.unurled.sacredrealms.sr.components.pack.hosts.RustProvider;
import me.unurled.sacredrealms.sr.config.Settings;
import me.unurled.sacredrealms.sr.data.DataHandler;
import me.unurled.sacredrealms.sr.data.DataManager;
import me.unurled.srcore.api.Manager;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
public class ResourcePackManager extends Manager {
private static final String RESOURCE_PACK_ZIP = "resource_pack.zip";
private final HostingProvider hostingProvider;
public ResourcePackManager() {
this.hostingProvider =
new RustProvider(
Settings.RESOURCE_PACK_URL.toString(), Settings.RESOURCE_PACK_API.toString());
}
@NotNull
private static File packFile(String fileName) {
try {
new File(SR.getPlugin().getDataFolder(), "pack").mkdirs();
String[] filesInclude = {"assets", "pack.mcmeta"};
FileOutputStream fos =
new FileOutputStream(new File(SR.getPlugin().getDataFolder(), fileName));
ZipOutputStream zipOut = new ZipOutputStream(fos);
zipOut.setLevel(9);
for (String filePath : filesInclude) {
File fileToZip = new File(SR.getPlugin().getDataFolder() + "/pack", filePath);
if (fileToZip.isDirectory()) {
zipDirectory(fileToZip, fileToZip.getName(), zipOut);
} else {
zipFile(fileToZip, fileToZip.getName(), zipOut);
}
}
zipOut.close();
fos.close();
log("ZIP file created successfully!");
} catch (IOException e) {
error("Failed to create resource pack");
}
return new File(SR.getPlugin().getDataFolder(), fileName);
}
/** Save the data */
@Override
public void saveData() {
super.saveData();
DataManager dm = Manager.getInstance(DataManager.class);
DataHandler dh = dm.getDataHandler();
dh.set("pack.url", hostingProvider.getMinecraftPackURL());
dh.set("pack.uuid", hostingProvider.getPackUUID().toString());
dh.set("pack.sha1", hostingProvider.getPackUUID().toString());
}
/** Load the data */
@Override
public void loadData() {
super.loadData();
DataManager dm = Manager.getInstance(DataManager.class);
DataHandler dh = dm.getDataHandler();
String packUUID = dh.get("pack.uuid");
if (packUUID == null) {
return;
}
hostingProvider.setPackUUID(UUID.fromString(packUUID));
hostingProvider.setPackURL(dh.get("pack.url"));
hostingProvider.setSHA1(dh.get("pack.sha1").getBytes());
}
/**
* upload a file to the hosting provider and return the url
*
* @param file the file to upload
*/
public void uploadAsync(final File file) {
Bukkit.getScheduler()
.runTaskAsynchronously(
SR.getPlugin(),
() -> {
// start the call
boolean success;
try {
success = hostingProvider.uploadPack(file);
} catch (Exception e) {
error("Failed to upload resource pack (exception) " + e.getMessage());
return;
}
if (!success) {
error("Failed to upload resource pack.");
}
});
}
/** Load the manager */
@Override
public void load() {
super.load();
String zipPath = SR.getPlugin().getDataFolder() + "/" + RESOURCE_PACK_ZIP;
Bukkit.getScheduler()
.runTaskAsynchronously(
SR.getPlugin(),
() -> {
if (new File(SR.getPlugin().getDataFolder(), "pack").exists()
&& new File(zipPath).exists()) {
log("Resource pack exists");
// create a new zip with files
File tmpFile = packFile("tmp.zip");
try {
String tmpSHA = getFileChecksum(tmpFile.getAbsolutePath());
String rpSHA = getFileChecksum(zipPath);
if (tmpSHA.equals(rpSHA)) {
log("Resource pack is up to date");
return;
} else {
log("Resource pack is outdated");
log(tmpSHA + " " + rpSHA);
}
} catch (IOException | NoSuchAlgorithmException e) {
error("Failed to check resource pack hash");
}
}
// create the resource pack
File rp = packFile(RESOURCE_PACK_ZIP);
// upload the resource pack
uploadAsync(rp);
});
}
public HostingProvider getHostingProvider() {
return hostingProvider;
}
}

View file

@ -0,0 +1,5 @@
package me.unurled.sacredrealms.sr.components.pack.animatedjava;
import me.unurled.srcore.api.Manager;
public class AnimatedJavaManager extends Manager {}

View file

@ -0,0 +1,223 @@
package me.unurled.sacredrealms.sr.components.pack.background;
import me.unurled.sacredrealms.sr.utils.character.CharRepo;
import me.unurled.sacredrealms.sr.utils.character.ConfiguredChar;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
public class Background {
private ConfiguredChar left,
offset1,
offset2,
offset4,
offset8,
offset16,
offset32,
offset64,
offset128,
right;
private int leftMargin, rightMargin;
private Background() {}
public Background(
ConfiguredChar left,
ConfiguredChar offset1,
ConfiguredChar offset2,
ConfiguredChar offset4,
ConfiguredChar offset8,
ConfiguredChar offset16,
ConfiguredChar offset32,
ConfiguredChar offset64,
ConfiguredChar offset128,
ConfiguredChar right,
int leftMargin,
int rightMargin,
boolean removeShadow) {
this.left = left;
this.offset1 = offset1;
this.offset2 = offset2;
this.offset4 = offset4;
this.offset8 = offset8;
this.offset16 = offset16;
this.offset32 = offset32;
this.offset64 = offset64;
this.offset128 = offset128;
this.right = right;
this.leftMargin = leftMargin;
this.rightMargin = rightMargin;
}
@Contract(value = " -> new", pure = true)
public static @NotNull Builder builder() {
return new Builder();
}
public ConfiguredChar getLeft() {
return left;
}
public ConfiguredChar getOffset1() {
return offset1;
}
public ConfiguredChar getOffset2() {
return offset2;
}
public ConfiguredChar getOffset4() {
return offset4;
}
public ConfiguredChar getOffset8() {
return offset8;
}
public ConfiguredChar getOffset16() {
return offset16;
}
public ConfiguredChar getOffset32() {
return offset32;
}
public ConfiguredChar getOffset64() {
return offset64;
}
public ConfiguredChar getOffset128() {
return offset128;
}
public ConfiguredChar getRight() {
return right;
}
public String getBackGroundImage(int n) {
String offset = CharRepo.getShortestNegChars(n + rightMargin + 2);
n = n + leftMargin + rightMargin + 2;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(left.getCharacter());
while (n >= 128) {
stringBuilder.append(CharRepo.NEG1.getCh());
stringBuilder.append(offset128.getCharacter());
n -= 128;
}
if (n - 64 >= 0) {
stringBuilder.append(CharRepo.NEG1.getCh());
stringBuilder.append(offset64.getCharacter());
n -= 64;
}
if (n - 32 >= 0) {
stringBuilder.append(CharRepo.NEG1.getCh());
stringBuilder.append(offset32.getCharacter());
n -= 32;
}
if (n - 16 >= 0) {
stringBuilder.append(CharRepo.NEG1.getCh());
stringBuilder.append(offset16.getCharacter());
n -= 16;
}
if (n - 8 >= 0) {
stringBuilder.append(CharRepo.NEG1.getCh());
stringBuilder.append(offset8.getCharacter());
n -= 8;
}
if (n - 4 >= 0) {
stringBuilder.append(CharRepo.NEG1.getCh());
stringBuilder.append(offset4.getCharacter());
n -= 4;
}
if (n - 2 >= 0) {
stringBuilder.append(CharRepo.NEG1.getCh());
stringBuilder.append(offset2.getCharacter());
n -= 2;
}
if (n - 1 >= 0) {
stringBuilder.append(CharRepo.NEG1.getCh());
stringBuilder.append(offset1.getCharacter());
}
stringBuilder.append(CharRepo.NEG1.getCh());
stringBuilder.append(right.getCharacter());
stringBuilder.append(offset);
return stringBuilder.toString();
}
public static class Builder {
private final Background background;
public Builder() {
this.background = new Background();
}
@Contract(value = " -> new", pure = true)
public static @NotNull Builder of() {
return new Builder();
}
public Builder left(ConfiguredChar configuredChar) {
background.left = configuredChar;
return this;
}
public Builder right(ConfiguredChar configuredChar) {
background.right = configuredChar;
return this;
}
public Builder offset1(ConfiguredChar configuredChar) {
background.offset1 = configuredChar;
return this;
}
public Builder offset2(ConfiguredChar configuredChar) {
background.offset2 = configuredChar;
return this;
}
public Builder offset4(ConfiguredChar configuredChar) {
background.offset4 = configuredChar;
return this;
}
public Builder offset8(ConfiguredChar configuredChar) {
background.offset8 = configuredChar;
return this;
}
public Builder offset16(ConfiguredChar configuredChar) {
background.offset16 = configuredChar;
return this;
}
public Builder offset32(ConfiguredChar configuredChar) {
background.offset32 = configuredChar;
return this;
}
public Builder offset64(ConfiguredChar configuredChar) {
background.offset64 = configuredChar;
return this;
}
public Builder offset128(ConfiguredChar configuredChar) {
background.offset128 = configuredChar;
return this;
}
public Builder leftMargin(int margin) {
background.leftMargin = margin;
return this;
}
public Builder rightMargin(int margin) {
background.rightMargin = margin;
return this;
}
public Background build() {
return background;
}
}
}

View file

@ -0,0 +1,139 @@
package me.unurled.sacredrealms.sr.components.pack.background;
import static me.unurled.sacredrealms.sr.utils.Logger.warn;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import me.unurled.sacredrealms.sr.SR;
import me.unurled.sacredrealms.sr.utils.character.CharacterArranger;
import me.unurled.sacredrealms.sr.utils.character.ConfiguredChar;
import me.unurled.srcore.api.Manager;
import org.jetbrains.annotations.NotNull;
public class BackgroundManager extends Manager {
private final Map<String, Background> backgroundMap;
public BackgroundManager() {
this.backgroundMap = new HashMap<>();
}
@Override
public void loadData() {
File bgFolder = new File(SR.getPlugin().getDataFolder(), "backgrounds");
if (!bgFolder.exists() && bgFolder.mkdirs()) {
saveDefaultBackgrounds();
}
int height = 14;
int ascent = 8;
String key = "b0";
Background background =
Background.builder()
.leftMargin(1)
.rightMargin(1)
.left(
ConfiguredChar.builder()
.character(CharacterArranger.getAndIncrease())
.png("b0")
.height(14)
.ascent(7)
.width(1)
.build())
.offset1(
ConfiguredChar.builder()
.character(CharacterArranger.getAndIncrease())
.png("b1")
.height(height)
.ascent(ascent)
.width(1)
.build())
.offset2(
ConfiguredChar.builder()
.character(CharacterArranger.getAndIncrease())
.png("b2")
.height(height)
.ascent(ascent)
.width(1)
.build())
.offset4(
ConfiguredChar.builder()
.character(CharacterArranger.getAndIncrease())
.png("b4")
.height(height)
.ascent(ascent)
.width(1)
.build())
.offset8(
ConfiguredChar.builder()
.character(CharacterArranger.getAndIncrease())
.png("b8")
.height(height)
.ascent(ascent)
.width(1)
.build())
.offset16(
ConfiguredChar.builder()
.character(CharacterArranger.getAndIncrease())
.png("b16")
.height(height)
.ascent(ascent)
.width(1)
.build())
.offset32(
ConfiguredChar.builder()
.character(CharacterArranger.getAndIncrease())
.png("b32")
.height(height)
.ascent(ascent)
.width(1)
.build())
.offset64(
ConfiguredChar.builder()
.character(CharacterArranger.getAndIncrease())
.png("b64")
.height(height)
.ascent(ascent)
.width(1)
.build())
.offset128(
ConfiguredChar.builder()
.character(CharacterArranger.getAndIncrease())
.png("b128")
.height(height)
.ascent(ascent)
.width(1)
.build())
.right(
ConfiguredChar.builder()
.character(CharacterArranger.getAndIncrease())
.png("b0")
.height(14)
.ascent(7)
.width(1)
.build())
.build();
if (!registerBackGround(key, background)) {
warn("Found duplicated background: " + key);
}
}
public boolean registerBackGround(@NotNull String key, @NotNull Background backGround) {
if (backgroundMap.containsKey(key)) {
return false;
}
backgroundMap.put(key, backGround);
return true;
}
private void saveDefaultBackgrounds() {
String[] bgList = new String[] {"b0", "b1", "b2", "b4", "b8", "b16", "b32", "b64", "b128"};
for (String bg : bgList) {
SR.getPlugin().saveResource("backgrounds" + File.separator + bg + ".png", false);
}
}
}

View file

@ -0,0 +1,29 @@
package me.unurled.sacredrealms.sr.components.pack.hosts;
import java.io.File;
import java.util.UUID;
public interface HostingProvider {
boolean uploadPack(File resourcePack) throws InterruptedException;
String getPackURL();
void setPackURL(String packURL);
String getMinecraftPackURL();
void setMinecraftPackURL(String minecraftPackURL);
byte[] getSHA1();
void setSHA1(byte[] sha1);
String getOriginalSHA1();
void setOriginalSHA1(String originalSHA1);
UUID getPackUUID();
void setPackUUID(UUID packUUID);
}

View file

@ -0,0 +1,151 @@
package me.unurled.sacredrealms.sr.components.pack.hosts;
import static me.unurled.sacredrealms.sr.utils.Logger.error;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.UUID;
import me.unurled.sacredrealms.sr.utils.HTTPRequestMultipartBody;
import org.jetbrains.annotations.NotNull;
public class RustProvider implements HostingProvider {
public static final String FAILED = "Failed to upload pack to Rust server: ";
public static final String HTTPS = "https://";
private final String address;
private final String APIKEY;
private String packUrl;
private String minecraftPackURL;
private String sha1;
private UUID packUUID;
public RustProvider(@NotNull String address, @NotNull String apiKey) {
String address1;
if (address.startsWith(HTTPS) || address.startsWith("http://")) {
address1 = address;
} else {
address1 = HTTPS + address;
}
address1 += address.endsWith("/") ? "" : "/";
this.address = address1;
this.APIKEY = apiKey;
}
@Override
public boolean uploadPack(File resourcePack) throws InterruptedException {
try (HttpClient httpClient = HttpClient.newHttpClient()) {
HTTPRequestMultipartBody multipartBody =
new HTTPRequestMultipartBody.Builder()
.addPart("file", resourcePack, null, resourcePack.getName())
.build();
HttpRequest httpRequest =
HttpRequest.newBuilder()
.header(
"Content-Type", "multipart/form-data; boundary=" + multipartBody.getBoundary())
.header("API_KEY", APIKEY)
.uri(new URI(this.address + "post"))
.POST(HttpRequest.BodyPublishers.ofByteArray(multipartBody.getBody()))
.build();
HttpResponse<String> response =
httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
error(FAILED + response.body());
return false;
}
String stringRes = response.body();
if (stringRes.startsWith("[") && stringRes.endsWith("]")) {
stringRes = stringRes.substring(1, stringRes.length() - 1);
}
String[] split = stringRes.split(",");
if (split.length != 2) {
error(FAILED + response.body());
return false;
}
String path = split[0].split(":")[1].replace("\"", "").trim();
sha1 = split[1].split(":")[1].replace("\"", "").trim().replace("}", "");
packUrl = this.address + "files/" + path;
minecraftPackURL = packUrl.replace(HTTPS, "http://");
packUUID = UUID.nameUUIDFromBytes(sha1.getBytes());
} catch (IOException | URISyntaxException e) {
error(FAILED + e.getMessage());
return false;
} catch (InterruptedException e) {
error(FAILED + e.getMessage());
throw e;
}
return true;
}
@Override
public String getPackURL() {
return packUrl;
}
@Override
public void setPackURL(String packURL) {
this.packUrl = packURL;
}
@Override
public String getMinecraftPackURL() {
return minecraftPackURL;
}
@Override
public void setMinecraftPackURL(String minecraftPackURL) {
this.minecraftPackURL = minecraftPackURL;
}
@Override
public byte[] getSHA1() {
int len = sha1.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] =
(byte)
((Character.digit(sha1.charAt(i), 16) << 4)
+ Character.digit(sha1.charAt(i + 1), 16));
}
return data;
}
@Override
public void setSHA1(byte[] sha1) {
this.sha1 = new String(sha1);
}
@Override
public String getOriginalSHA1() {
return sha1;
}
@Override
public void setOriginalSHA1(String originalSHA1) {
this.sha1 = originalSHA1;
}
@Override
public UUID getPackUUID() {
return packUUID;
}
@Override
public void setPackUUID(UUID packUUID) {
this.packUUID = packUUID;
}
}

View file

@ -0,0 +1,12 @@
package me.unurled.sacredrealms.sr.components.packet;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import me.unurled.srcore.api.Manager;
import org.bukkit.entity.Player;
public class PacketManager extends Manager {
public static <T extends PacketWrapper> void sendPacketTo(T packet, Player player) {
PacketEvents.getAPI().getPlayerManager().sendPacket(player, packet);
}
}

View file

@ -2,19 +2,24 @@ package me.unurled.sacredrealms.sr.components.player;
import static me.unurled.sacredrealms.sr.utils.Component.textComp; 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.error;
import static me.unurled.sacredrealms.sr.utils.Logger.log;
import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.updateActionBar; import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.updateActionBar;
import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent; import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import java.net.URI;
import java.util.HashMap; import java.util.HashMap;
import java.util.UUID; import java.util.UUID;
import me.unurled.sacredrealms.sr.SR; import me.unurled.sacredrealms.sr.SR;
import me.unurled.sacredrealms.sr.components.pack.ResourcePackManager;
import me.unurled.sacredrealms.sr.data.DataHandler; import me.unurled.sacredrealms.sr.data.DataHandler;
import me.unurled.sacredrealms.sr.data.DataManager; import me.unurled.sacredrealms.sr.data.DataManager;
import me.unurled.sacredrealms.sr.events.player.PlayerLevelUpEvent; import me.unurled.sacredrealms.sr.events.player.PlayerLevelUpEvent;
import me.unurled.sacredrealms.sr.managers.Manager;
import me.unurled.sacredrealms.sr.utils.Items; import me.unurled.sacredrealms.sr.utils.Items;
import me.unurled.srcore.api.Manager;
import net.kyori.adventure.resource.ResourcePackInfo;
import net.kyori.adventure.resource.ResourcePackRequest;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@ -22,6 +27,7 @@ import org.bukkit.event.entity.FoodLevelChangeEvent;
import org.bukkit.event.player.PlayerItemHeldEvent; import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerResourcePackStatusEvent.Status;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffect;
@ -134,10 +140,36 @@ public class PlayerManager extends Manager {
BukkitTask task = BukkitTask task =
Bukkit.getScheduler() Bukkit.getScheduler()
.runTaskTimerAsynchronously( .runTaskTimerAsynchronously(
SR.getInstance(), () -> updateActionBar(e.getPlayer()), 0, 20L); SR.getPlugin(), () -> updateActionBar(e.getPlayer()), 0, 20L);
actionBarTasks.put(e.getPlayer().getUniqueId(), task); actionBarTasks.put(e.getPlayer().getUniqueId(), task);
e.getPlayer().updateInventory(); e.getPlayer().updateInventory();
// player resource pack give
ResourcePackManager rpm = Manager.getInstance(ResourcePackManager.class);
if (rpm == null) {
error("ResourcePackManager is null, Can't give player resource pack.");
return;
}
try {
URI uri = new URI(rpm.getHostingProvider().getMinecraftPackURL());
ResourcePackRequest request =
ResourcePackRequest.addingRequest(
ResourcePackInfo.resourcePackInfo(
rpm.getHostingProvider().getPackUUID(),
uri,
rpm.getHostingProvider().getOriginalSHA1()));
e.getPlayer().sendResourcePacks(request);
if (e.getPlayer().getResourcePackStatus() != null
&& !e.getPlayer().getResourcePackStatus().equals(Status.ACCEPTED)) {
e.getPlayer().kick(textComp("You must accept the resource pack."));
}
} catch (Exception ex) {
error("Failed to send resource pack to player. " + ex.getMessage());
log(rpm.getHostingProvider().getOriginalSHA1());
log(rpm.getHostingProvider().getPackUUID().toString());
log(rpm.getHostingProvider().getMinecraftPackURL());
}
} }
@Nullable @Nullable
@ -225,7 +257,7 @@ public class PlayerManager extends Manager {
public void levelUp(SRPlayer p, int previousLevel) { public void levelUp(SRPlayer p, int previousLevel) {
PlayerLevelUpEvent event = new PlayerLevelUpEvent(p, previousLevel); PlayerLevelUpEvent event = new PlayerLevelUpEvent(p, previousLevel);
event.callEvent(); Bukkit.getScheduler().runTaskAsynchronously(SR.getPlugin(), event::callEvent);
Player player = Bukkit.getPlayer(p.getUuid()); Player player = Bukkit.getPlayer(p.getUuid());
if (player != null) { if (player != null) {
player.sendMessage(event.getMessage()); player.sendMessage(event.getMessage());

View file

@ -14,7 +14,7 @@ import me.unurled.sacredrealms.sr.components.attributes.Attribute;
import me.unurled.sacredrealms.sr.components.difficulty.Difficulty; import me.unurled.sacredrealms.sr.components.difficulty.Difficulty;
import me.unurled.sacredrealms.sr.components.item.Item; import me.unurled.sacredrealms.sr.components.item.Item;
import me.unurled.sacredrealms.sr.events.player.PlayerKillEvent; import me.unurled.sacredrealms.sr.events.player.PlayerKillEvent;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause; import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
@ -31,15 +31,15 @@ public class SRPlayer {
private static final List<Long> levelRequirements = private static final List<Long> levelRequirements =
List.of(100L, 200L, 400L, 800L, 1600L, 3200L, 6400L, 12800L, 25600L, 51200L); List.of(100L, 200L, 400L, 800L, 1600L, 3200L, 6400L, 12800L, 25600L, 51200L);
@Expose private UUID uuid; @Expose private final UUID uuid;
@Expose private final Map<Attribute, Double> attributes = new EnumMap<>(Attribute.class);
@Expose private final List<Integer> treasuresOpened = new ArrayList<>();
@Expose private int level = 1; @Expose private int level = 1;
@Expose private Long experience = 0L; @Expose private Long experience = 0L;
private double health = 100; private double health = -1;
@Expose private Map<Attribute, Double> attributes = new EnumMap<>(Attribute.class);
private Map<Attribute, Map<ItemStack, Double>> itemAttributes = new EnumMap<>(Attribute.class); private Map<Attribute, Map<ItemStack, Double>> itemAttributes = new EnumMap<>(Attribute.class);
@Expose private List<PotionEffect> potionEffects = new ArrayList<>(); @Expose private List<PotionEffect> potionEffects = new ArrayList<>();
@Expose private Inventory inventory; @Expose private Inventory inventory;
@Expose private List<Integer> treasuresOpened = new ArrayList<>();
@Expose private Difficulty difficulty; @Expose private Difficulty difficulty;
private boolean isClientBuilder = false; private boolean isClientBuilder = false;
private boolean firstTime = true; private boolean firstTime = true;
@ -238,6 +238,9 @@ public class SRPlayer {
} }
public double getHealth() { public double getHealth() {
if (health == -1) {
health = getAttribute(Attribute.HEALTH);
}
return health; return health;
} }
@ -257,6 +260,7 @@ public class SRPlayer {
public void setExperience(Long experience) { public void setExperience(Long experience) {
// checks if experience is above next level requirements // checks if experience is above next level requirements
if (difficulty == null) difficulty = Difficulty.NORMAL;
if (experience >= levelRequirements.get(level - 1) * difficulty.getXpMultiplier()) { if (experience >= levelRequirements.get(level - 1) * difficulty.getXpMultiplier()) {
PlayerManager pm = Manager.getInstance(PlayerManager.class); PlayerManager pm = Manager.getInstance(PlayerManager.class);
setLevel(level + 1); setLevel(level + 1);

View file

@ -2,7 +2,7 @@ package me.unurled.sacredrealms.sr.components.player.listener;
import me.unurled.sacredrealms.sr.components.player.PlayerManager; import me.unurled.sacredrealms.sr.components.player.PlayerManager;
import me.unurled.sacredrealms.sr.components.player.SRPlayer; import me.unurled.sacredrealms.sr.components.player.SRPlayer;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;

View file

@ -0,0 +1,60 @@
package me.unurled.sacredrealms.sr.components.treasure;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import me.unurled.sacredrealms.sr.components.item.ItemStackDeserializer;
import me.unurled.sacredrealms.sr.components.item.ItemStackSerializer;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
public class ItemStackMapSerializer
implements JsonSerializer<Map<Integer, ItemStack>>,
JsonDeserializer<Map<Integer, org.bukkit.inventory.ItemStack>> {
@Override
public Map<Integer, ItemStack> deserialize(
@NotNull JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
Map<Integer, ItemStack> map = new HashMap<>();
JsonObject jsonObject = json.getAsJsonObject();
Gson gson =
new GsonBuilder()
.registerTypeAdapter(ItemStack.class, new ItemStackDeserializer())
.create();
for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
Integer key = Integer.parseInt(entry.getKey());
ItemStack itemStack = gson.fromJson(entry.getValue(), ItemStack.class);
map.put(key, itemStack);
}
return map;
}
@Override
public JsonElement serialize(
@NotNull Map<Integer, ItemStack> src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject jsonObject = new JsonObject();
Gson gson =
new GsonBuilder().registerTypeAdapter(ItemStack.class, new ItemStackSerializer()).create();
for (Map.Entry<Integer, ItemStack> entry : src.entrySet()) {
JsonElement itemStackJson = gson.toJsonTree(entry.getValue(), ItemStack.class);
jsonObject.add(entry.getKey().toString(), itemStackJson);
}
return jsonObject;
}
}

View file

@ -12,9 +12,8 @@ import io.leangen.geantyref.TypeToken;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Map; import java.util.Map;
import me.unurled.sacredrealms.sr.components.item.ItemStackDeserializer; import me.unurled.sacredrealms.sr.components.item.ItemStackDeserializer;
import org.bukkit.Bukkit; import me.unurled.sacredrealms.sr.utils.gson.LocationSerializer;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
public class TreasureDeserializer implements JsonDeserializer<Treasure> { public class TreasureDeserializer implements JsonDeserializer<Treasure> {
@ -42,34 +41,31 @@ public class TreasureDeserializer implements JsonDeserializer<Treasure> {
new GsonBuilder() new GsonBuilder()
.registerTypeAdapter(ItemStack.class, new ItemStackDeserializer()) .registerTypeAdapter(ItemStack.class, new ItemStackDeserializer())
.create(); .create();
try { try {
Integer id = gson.fromJson("id", Integer.class); Integer id = json.getAsJsonObject().get("id").getAsInt();
String loc = gson.fromJson("location", String.class); Gson locGson =
String[] parts = loc.split(","); new GsonBuilder()
if (parts.length != 6) { .registerTypeAdapter(Location.class, new LocationSerializer())
return null; .registerTypeAdapter(
} new TypeToken<Map<Integer, ItemStack>>() {}.getType(),
World world = Bukkit.getServer().getWorld(parts[0]); new ItemStackMapSerializer())
double x = Double.parseDouble(parts[1]); .create();
double y = Double.parseDouble(parts[2]); Location location = locGson.fromJson(json.getAsJsonObject().get("location"), Location.class);
double z = Double.parseDouble(parts[3]); String permission = json.getAsJsonObject().get("permission").getAsString();
float pitch = Float.parseFloat(parts[4]); String items = json.getAsJsonObject().get("items").getAsString();
float yaw = Float.parseFloat(parts[5]);
Location location = new Location(world, x, y, z, pitch, yaw);
String permission = gson.fromJson("permission", String.class);
String items = gson.fromJson("items", String.class);
Type hash = new TypeToken<Map<Integer, ItemStack>>() {}.getType(); Type hash = new TypeToken<Map<Integer, ItemStack>>() {}.getType();
Map<Integer, ItemStack> item = gson.fromJson(items, hash); Map<Integer, ItemStack> item = gson.fromJson(items, hash);
if (permission == null || item == null) { if (permission == null || item == null) {
error("Error deserializing treasure: " + id + " is missing required fields");
return null; return null;
} }
return new Treasure(id, location, item, permission); return new Treasure(id, location, item, permission);
} catch (Exception e) { } catch (Exception e) {
error("Error deserializing treasure: " + e.getMessage()); error("Error deserializing treasure: " + e.getMessage());
return null;
} }
return null;
} }
} }

View file

@ -11,7 +11,7 @@ import me.unurled.sacredrealms.sr.components.item.Item;
import me.unurled.sacredrealms.sr.components.item.ItemManager; import me.unurled.sacredrealms.sr.components.item.ItemManager;
import me.unurled.sacredrealms.sr.components.item.Rarity; import me.unurled.sacredrealms.sr.components.item.Rarity;
import me.unurled.sacredrealms.sr.components.player.SRPlayer; import me.unurled.sacredrealms.sr.components.player.SRPlayer;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;

View file

@ -1,6 +1,8 @@
package me.unurled.sacredrealms.sr.components.treasure; package me.unurled.sacredrealms.sr.components.treasure;
import static me.unurled.sacredrealms.sr.utils.Component.textComp; 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 com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
@ -15,7 +17,7 @@ import me.unurled.sacredrealms.sr.components.player.PlayerManager;
import me.unurled.sacredrealms.sr.components.player.SRPlayer; import me.unurled.sacredrealms.sr.components.player.SRPlayer;
import me.unurled.sacredrealms.sr.data.DataHandler; import me.unurled.sacredrealms.sr.data.DataHandler;
import me.unurled.sacredrealms.sr.data.DataManager; import me.unurled.sacredrealms.sr.data.DataManager;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
@ -34,16 +36,20 @@ public class TreasureManager extends Manager {
private int nextId = 0; private int nextId = 0;
private void saveTreasure(@NotNull Treasure treasure) {
DataHandler dh = Manager.getInstance(DataManager.class).getDataHandler();
Gson gson =
new GsonBuilder().registerTypeAdapter(Treasure.class, new TreasureSerializer()).create();
dh.set("treasures." + treasure.getId(), gson.toJson(treasure));
}
/** Save the data */ /** Save the data */
@Override @Override
public void saveData() { public void saveData() {
// save all treasures // save all treasures
for (Treasure treasure : treasures.values()) { for (Treasure treasure : treasures.values()) {
// serialize treasure // serialize treasure
DataHandler dh = Manager.getInstance(DataManager.class).getDataHandler(); saveTreasure(treasure);
Gson gson =
new GsonBuilder().registerTypeAdapter(Treasure.class, new TreasureSerializer()).create();
dh.set("treasures." + treasure.getId(), gson.toJson(treasure));
} }
} }
@ -54,9 +60,15 @@ public class TreasureManager extends Manager {
DataHandler dh = Manager.getInstance(DataManager.class).getDataHandler(); DataHandler dh = Manager.getInstance(DataManager.class).getDataHandler();
Gson gson = Gson gson =
new GsonBuilder().registerTypeAdapter(Treasure.class, new TreasureDeserializer()).create(); new GsonBuilder().registerTypeAdapter(Treasure.class, new TreasureDeserializer()).create();
log("Loading " + dh.getKeysAll("treasures").size() + " treasures");
for (String key : dh.getKeysAll("treasures")) { for (String key : dh.getKeysAll("treasures")) {
// deserialize treasure Treasure treasure = gson.fromJson(dh.get(key), Treasure.class);
addTreasure(gson.fromJson(dh.get("treasures." + key), Treasure.class)); if (treasure == null) {
error("Error loading treasure with id " + key);
continue;
}
addTreasure(treasure);
} }
} }
@ -118,6 +130,15 @@ public class TreasureManager extends Manager {
treasures.remove(treasure.getId()); treasures.remove(treasure.getId());
} }
public void setBlocks(int id, @NotNull Map<Integer, ItemStack> items) {
Treasure treasure = getTreasureById(id);
if (treasure == null) {
return;
}
treasure.setItems(items);
saveTreasure(treasure);
}
public int getNextId() { public int getNextId() {
return nextId++; return nextId++;
} }
@ -159,8 +180,17 @@ public class TreasureManager extends Manager {
if (sr == null) { if (sr == null) {
return; return;
} }
treasure = TreasureGenerator.generateTreasure(treasure, sr); if (sr.hasOpenedTreasure(treasure.getId())) {
p.sendMessage("You have already opened this chest");
p.playSound(p.getLocation(), Sound.BLOCK_ANVIL_BREAK, 1f, 0.5f);
return;
}
if (treasure.getItems().isEmpty()) { // it generates items if not already set
treasure = TreasureGenerator.generateTreasure(treasure, sr);
}
log(treasure.getItems().toString());
p.openInventory(treasure.getInventory()); p.openInventory(treasure.getInventory());
p.playSound(p.getLocation(), Sound.BLOCK_CHEST_OPEN, 1f, 1f);
SRPlayer srPlayer = Manager.getInstance(PlayerManager.class).getPlayer(p.getUniqueId()); SRPlayer srPlayer = Manager.getInstance(PlayerManager.class).getPlayer(p.getUniqueId());
if (srPlayer != null) { if (srPlayer != null) {
srPlayer.addTreasureOpened(treasure.getId()); srPlayer.addTreasureOpened(treasure.getId());

View file

@ -7,9 +7,14 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive; import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer; import com.google.gson.JsonSerializer;
import io.leangen.geantyref.TypeToken;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Map;
import me.unurled.sacredrealms.sr.components.item.ItemStackSerializer; import me.unurled.sacredrealms.sr.components.item.ItemStackSerializer;
import me.unurled.sacredrealms.sr.utils.gson.LocationSerializer;
import org.bukkit.Location;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
public class TreasureSerializer implements JsonSerializer<Treasure> { public class TreasureSerializer implements JsonSerializer<Treasure> {
@ -29,14 +34,21 @@ public class TreasureSerializer implements JsonSerializer<Treasure> {
* @return a JsonElement corresponding to the specified object. * @return a JsonElement corresponding to the specified object.
*/ */
@Override @Override
public JsonElement serialize(Treasure src, Type typeOfSrc, JsonSerializationContext context) { public JsonElement serialize(
@NotNull Treasure src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject obj = new JsonObject(); JsonObject obj = new JsonObject();
obj.add("id", new JsonPrimitive(src.getId())); obj.add("id", new JsonPrimitive(src.getId()));
obj.add("location", new JsonPrimitive(src.getLocation().toString())); LocationSerializer locSer = new LocationSerializer();
obj.add("location", locSer.serialize(src.getLocation(), Location.class, context));
obj.add("permission", new JsonPrimitive(src.getPermission())); obj.add("permission", new JsonPrimitive(src.getPermission()));
Gson gson = Gson gson =
new GsonBuilder().registerTypeAdapter(ItemStack.class, new ItemStackSerializer()).create(); new GsonBuilder()
obj.add("items", new JsonPrimitive(gson.toJson(src.getItems()))); .registerTypeAdapter(ItemStack.class, new ItemStackSerializer())
.registerTypeAdapter(
new TypeToken<Map<Integer, ItemStack>>() {}.getType(), new ItemStackMapSerializer())
.create();
Type hash = new TypeToken<Map<Integer, ItemStack>>() {}.getType();
obj.add("items", gson.toJsonTree(src.getItems(), hash));
return obj; return obj;
} }
} }

View file

@ -0,0 +1,40 @@
package me.unurled.sacredrealms.sr.config;
import java.io.File;
import me.unurled.sacredrealms.sr.SR;
import me.unurled.srcore.api.Manager;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
public class ConfigManager extends Manager {
public static final String CONFIG_YML = "config.yml";
private FileConfiguration config;
/** Load the data */
@Override
public void loadData() {
if (!SR.getPlugin().getDataFolder().exists()) {
SR.getPlugin().getDataFolder().mkdirs();
}
File configFile = new File(SR.getPlugin().getDataFolder(), CONFIG_YML);
if (!configFile.exists()) {
SR.getPlugin().saveResource(CONFIG_YML, false);
config = YamlConfiguration.loadConfiguration(configFile);
}
config = YamlConfiguration.loadConfiguration(configFile);
}
@Override
public void saveData() {
if (!new File(SR.getPlugin().getDataFolder() + CONFIG_YML).exists()) {
SR.getPlugin().saveDefaultConfig();
} else {
SR.getPlugin().saveConfig();
}
}
public FileConfiguration getConfig() {
return config;
}
}

View file

@ -0,0 +1,95 @@
package me.unurled.sacredrealms.sr.config;
import static me.unurled.sacredrealms.sr.utils.Logger.error;
import java.io.File;
import java.util.List;
import me.unurled.sacredrealms.sr.SR;
import me.unurled.srcore.api.Manager;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.configuration.ConfigurationSection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public enum Settings {
REDIS_HOST("redis.host"),
REDIS_PORT("redis.port"),
RESOURCE_PACK_URL("resource_pack"),
RESOURCE_PACK_API("resource_pack_api");
private final String path;
Settings(String path) {
this.path = path;
}
public String getPath() {
return path;
}
public @Nullable Object getValue() {
ConfigManager cm = Manager.getInstance(ConfigManager.class);
if (cm != null) {
return cm.getConfig().get(path);
}
return null;
}
public void setValue(Object value) {
SR.getPlugin().getConfig().set(path, value);
try {
SR.getPlugin().getConfig().save(new File(SR.getPlugin().getDataFolder(), "config.yml"));
} catch (Exception e) {
error("Failed to save config.yml");
}
}
@Override
public String toString() {
try {
return (String) getValue();
} catch (NullPointerException e) {
return "";
}
}
@Nullable
public Integer toInt() {
try {
return (int) getValue();
} catch (NullPointerException e) {
return null;
}
}
public @NotNull Component toComponent() {
Object value = getValue();
if (value != null) {
return MiniMessage.miniMessage().deserialize(value.toString());
} else {
return Component.empty();
}
}
public Boolean toBool() {
return (Boolean) getValue();
}
public List<String> toStringList() {
ConfigManager cm = Manager.getInstance(ConfigManager.class);
if (cm != null) {
return cm.getConfig().getStringList(path);
}
return List.of();
}
public @Nullable ConfigurationSection toConfigSection() {
ConfigManager cm = Manager.getInstance(ConfigManager.class);
if (cm != null) {
return cm.getConfig().getConfigurationSection(path);
}
return null;
}
}

View file

@ -0,0 +1,9 @@
package me.unurled.sacredrealms.sr.constants;
public class Keys {
public static final String BLOCK_KEY = "key";
public static final String BLOCK_DISPLAYNAME = "displayName";
public static final String BLOCK_LORE = "lore";
public static final String BLOCK_CUSTOMMODELDATA = "customModelData";
}

View file

@ -1,18 +1,10 @@
package me.unurled.sacredrealms.sr.data; package me.unurled.sacredrealms.sr.data;
import static me.unurled.sacredrealms.sr.utils.Logger.error; import me.unurled.srcore.api.Manager;
import java.io.File;
import java.io.IOException;
import me.unurled.sacredrealms.sr.SR;
import me.unurled.sacredrealms.sr.managers.Manager;
import org.bukkit.configuration.file.FileConfiguration;
/** The data and config manager */ /** The data and config manager */
public class DataManager extends Manager { public class DataManager extends Manager {
private FileConfiguration config;
private DataHandler dh; private DataHandler dh;
/** Load the manager */ /** Load the manager */
@ -22,33 +14,6 @@ public class DataManager extends Manager {
dh = new Redis(); dh = new Redis();
} }
/** Save the data */
@Override
public void saveData() {
try {
if (config != null) config.save(new File(SR.getInstance().getDataFolder(), "config.yml"));
} catch (IOException e) {
error("Failed to save config.yml");
}
}
/** Load the data */
@Override
public void loadData() {
SR.getInstance().saveConfig();
SR.getInstance().reloadConfig();
config = SR.getInstance().getConfig();
}
/**
* Get the config
*
* @return The config
*/
public FileConfiguration getConfig() {
return config;
}
/** /**
* Get the data handler * Get the data handler
* *

View file

@ -4,7 +4,9 @@ import static me.unurled.sacredrealms.sr.utils.Logger.error;
import java.util.List; import java.util.List;
import me.unurled.sacredrealms.sr.SR; import me.unurled.sacredrealms.sr.SR;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.sacredrealms.sr.config.ConfigManager;
import me.unurled.sacredrealms.sr.config.Settings;
import me.unurled.srcore.api.Manager;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import redis.clients.jedis.JedisPooled; import redis.clients.jedis.JedisPooled;
@ -13,20 +15,25 @@ public class Redis implements DataHandler {
JedisPooled client; JedisPooled client;
public Redis() { public Redis() {
DataManager dm = Manager.getInstance(DataManager.class); ConfigManager cm = Manager.getInstance(ConfigManager.class);
if (dm != null) { if (cm != null) {
String host = dm.getConfig().getString("redis.host", "127.0.0.1"); String host = Settings.REDIS_HOST.toString();
int port = dm.getConfig().getInt("redis.port", 6379); Integer port = Settings.REDIS_PORT.toInt();
if (host == null || port == null) {
error("Failed to get Redis host or port from config, shutting down server.");
SR.getPlugin().getServer().shutdown();
return;
}
try { try {
client = new JedisPooled(host, port); client = new JedisPooled(host, port);
client.get("test"); client.get("test");
} catch (Exception e) { } catch (Exception e) {
error("Failed to connect to Redis, shutting down server."); error("Failed to connect to Redis, shutting down server.");
SR.getInstance().getServer().shutdown(); SR.getPlugin().getServer().shutdown();
} }
} else { } else {
error("Failed to get DataManager instance. Can't connect to Redis, shutting down server."); error("Failed to get DataManager instance. Can't connect to Redis, shutting down server.");
SR.getInstance().getServer().shutdown(); SR.getPlugin().getServer().shutdown();
} }
} }

View file

@ -16,7 +16,7 @@ public class BackItem extends PageItem {
public ItemProvider getItemProvider(PagedGui<?> gui) { public ItemProvider getItemProvider(PagedGui<?> gui) {
ItemBuilder builder = new ItemBuilder(Material.RED_STAINED_GLASS_PANE); ItemBuilder builder = new ItemBuilder(Material.RED_STAINED_GLASS_PANE);
builder builder
.setDisplayName("$7Previous Page") .setDisplayName("§cPrevious Page")
.addLoreLines( .addLoreLines(
gui.hasPreviousPage() gui.hasPreviousPage()
? "§7Go to page §e" + gui.getCurrentPage() + "§7/§e" + gui.getPageAmount() ? "§7Go to page §e" + gui.getCurrentPage() + "§7/§e" + gui.getPageAmount()

View file

@ -6,7 +6,7 @@ import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.syncSRToPlayer;
import me.unurled.sacredrealms.sr.components.attributes.Attribute; import me.unurled.sacredrealms.sr.components.attributes.Attribute;
import me.unurled.sacredrealms.sr.components.player.PlayerManager; import me.unurled.sacredrealms.sr.components.player.PlayerManager;
import me.unurled.sacredrealms.sr.components.player.SRPlayer; import me.unurled.sacredrealms.sr.components.player.SRPlayer;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.ClickType;

View file

@ -3,7 +3,7 @@ package me.unurled.sacredrealms.sr.gui.difficulty;
import me.unurled.sacredrealms.sr.components.difficulty.Difficulty; import me.unurled.sacredrealms.sr.components.difficulty.Difficulty;
import me.unurled.sacredrealms.sr.components.player.PlayerManager; import me.unurled.sacredrealms.sr.components.player.PlayerManager;
import me.unurled.sacredrealms.sr.components.player.SRPlayer; import me.unurled.sacredrealms.sr.components.player.SRPlayer;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.ClickType;
@ -18,7 +18,7 @@ import xyz.xenondevs.invui.window.Window;
public class DifficultyItem extends AbstractItem { public class DifficultyItem extends AbstractItem {
private Difficulty difficulty; private final Difficulty difficulty;
public DifficultyItem(Difficulty difficulty) { public DifficultyItem(Difficulty difficulty) {
this.difficulty = difficulty; this.difficulty = difficulty;
@ -90,6 +90,8 @@ public class DifficultyItem extends AbstractItem {
SRPlayer sr = pm.getPlayer(player.getUniqueId()); SRPlayer sr = pm.getPlayer(player.getUniqueId());
if (sr != null) { if (sr != null) {
sr.setDifficulty(difficulty); sr.setDifficulty(difficulty);
player.closeInventory();
player.sendMessage("Set difficulty to " + difficulty.name() + "!");
} }
} }
} }

View file

@ -1,6 +1,11 @@
package me.unurled.sacredrealms.sr.gui.entitytype; package me.unurled.sacredrealms.sr.gui.entitytype;
import static me.unurled.sacredrealms.sr.utils.Items.name;
import java.util.ArrayList;
import java.util.List;
import me.unurled.sacredrealms.sr.components.entity.SREntityType; import me.unurled.sacredrealms.sr.components.entity.SREntityType;
import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryClickEvent;
@ -14,15 +19,41 @@ import xyz.xenondevs.invui.window.Window;
public class EntityArmorItem extends AbstractItem { public class EntityArmorItem extends AbstractItem {
private static final ItemStack MAINHAND = name(new ItemStack(Material.BARRIER), "Main Hand");
private static final ItemStack SECONDHAND = name(new ItemStack(Material.BARRIER), "Off Hand");
private static final List<ItemStack> ARMOR = new ArrayList<>();
private final ItemStack stack; private final ItemStack stack;
public EntityArmorItem(SREntityType type, int armorSlot) { public EntityArmorItem(@NotNull SREntityType type, int armorSlot) {
if (armorSlot == 4) {
stack = type.getHandItem(); ARMOR.add(name(new ItemStack(Material.BARRIER), "Helmet"));
} else if (armorSlot == 5) { ARMOR.add(name(new ItemStack(Material.BARRIER), "Chestplate"));
stack = type.getSecondHandItem(); ARMOR.add(name(new ItemStack(Material.BARRIER), "Leggings"));
} else { ARMOR.add(name(new ItemStack(Material.BARRIER), "Boots"));
stack = type.getArmor().get(armorSlot);
switch (armorSlot) {
case 4 -> {
if (type.getHandItem().getType().equals(Material.AIR)) {
stack = MAINHAND;
} else {
stack = type.getHandItem();
}
}
case 5 -> {
if (type.getSecondHandItem().getType().equals(Material.AIR)) {
stack = SECONDHAND;
} else {
stack = type.getSecondHandItem();
}
}
default -> {
if (type.getArmor().size() <= armorSlot
|| type.getArmor().get(armorSlot).getType().equals(Material.AIR)) {
stack = ARMOR.get(armorSlot);
} else {
stack = type.getArmor().get(armorSlot);
}
}
} }
} }

View file

@ -6,7 +6,7 @@ import me.unurled.sacredrealms.sr.components.entity.EntityManager;
import me.unurled.sacredrealms.sr.components.entity.SREntityType; import me.unurled.sacredrealms.sr.components.entity.SREntityType;
import me.unurled.sacredrealms.sr.gui.BackItem; import me.unurled.sacredrealms.sr.gui.BackItem;
import me.unurled.sacredrealms.sr.gui.ForwardItem; import me.unurled.sacredrealms.sr.gui.ForwardItem;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.bukkit.Material; import org.bukkit.Material;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import xyz.xenondevs.invui.gui.Gui; import xyz.xenondevs.invui.gui.Gui;
@ -48,13 +48,13 @@ public class EntityTypeGUI {
return Gui.normal() return Gui.normal()
.setStructure( .setStructure(
"# # # # # # # # #", "# # # # # # # # #",
"# T B O I S N L #", // Type, Behavior, lOot, Item display, Stats, Name, Level "# T V O I S N L #", // Type, behaVior, lOot, Item display, Stats, Name, Level
"# X X X P X X X #", // exPerience "# X X X P X X X #", // exPerience
"# H C E B X M A #", // Helmet, Chestplate, lEgging, Boots, Main hand, second hAnd "# H C E B X M A #", // Helmet, Chestplate, lEgging, Boots, Main hand, second hAnd
"# # # # # # # # #") "# # # # # # # # #")
.addIngredient('#', border) .addIngredient('#', border)
.addIngredient('T', new EntityTypeItem(type)) .addIngredient('T', new EntityTypeItem(type))
.addIngredient('B', new EntityBehaviorItem(type)) .addIngredient('V', new EntityBehaviorItem(type))
.addIngredient('O', new EntityLootItem()) .addIngredient('O', new EntityLootItem())
.addIngredient('I', new EntityItemDisplay(type)) .addIngredient('I', new EntityItemDisplay(type))
.addIngredient('S', new EntityStatsItem(type)) .addIngredient('S', new EntityStatsItem(type))

View file

@ -0,0 +1,45 @@
package me.unurled.sacredrealms.sr.gui.treasure;
import static me.unurled.sacredrealms.sr.utils.Items.cancelItem;
import me.unurled.sacredrealms.sr.components.treasure.Treasure;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import xyz.xenondevs.invui.item.Item;
import xyz.xenondevs.invui.item.ItemProvider;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.AbstractItem;
import xyz.xenondevs.invui.window.Window;
public class CancelItem extends AbstractItem {
public CancelItem() {}
/**
* Gets the {@link ItemProvider}. This method gets called every time a {@link Window} is notified
* ({@link #notifyWindows()}).
*
* @return The {@link ItemProvider}
*/
@Override
public ItemProvider getItemProvider() {
return new ItemBuilder(cancelItem());
}
/**
* A method called if the {@link ItemStack} associated to this {@link Item} has been clicked by a
* player.
*
* @param clickType The {@link ClickType} the {@link Player} performed.
* @param player The {@link Player} who clicked on the {@link ItemStack}.
* @param event The {@link InventoryClickEvent} associated with this click.
*/
@Override
public void handleClick(
@NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent event) {
player.closeInventory();
}
}

View file

@ -0,0 +1,80 @@
package me.unurled.sacredrealms.sr.gui.treasure;
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
import static me.unurled.sacredrealms.sr.utils.Logger.log;
import java.util.HashMap;
import java.util.Map;
import me.unurled.sacredrealms.sr.components.treasure.Treasure;
import me.unurled.sacredrealms.sr.components.treasure.TreasureManager;
import me.unurled.srcore.api.Manager;
import org.bukkit.Material;
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.jetbrains.annotations.NotNull;
import xyz.xenondevs.invui.item.Item;
import xyz.xenondevs.invui.item.ItemProvider;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.AbstractItem;
import xyz.xenondevs.invui.window.Window;
public class ConfirmItem extends AbstractItem {
private final Treasure treasure;
public ConfirmItem(Treasure treasure) {
this.treasure = treasure;
}
/**
* Gets the {@link ItemProvider}. This method gets called every time a {@link Window} is notified
* ({@link #notifyWindows()}).
*
* @return The {@link ItemProvider}
*/
@Override
public ItemProvider getItemProvider() {
ItemStack confirm = new ItemStack(Material.GREEN_STAINED_GLASS_PANE);
ItemMeta confirmMeta = confirm.getItemMeta();
confirmMeta.displayName(textComp("<b><green>Confirm</green></b>"));
confirm.setItemMeta(confirmMeta);
return new ItemBuilder(confirm);
}
/**
* A method called if the {@link ItemStack} associated to this {@link Item} has been clicked by a
* player.
*
* @param clickType The {@link ClickType} the {@link Player} performed.
* @param player The {@link Player} who clicked on the {@link ItemStack}.
* @param event The {@link InventoryClickEvent} associated with this click.
*/
@Override
public void handleClick(
@NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent event) {
Map<Integer, ItemStack> items = new HashMap<>();
for (int i = 0; i < player.getInventory().getContents().length; i++) {
if (i < 9 || i > 35) {
log("Skipping slot " + i);
continue;
}
if (event.getClickedInventory() == null) {
log("Clicked inventory is null");
continue;
}
ItemStack content = event.getClickedInventory().getItem(i);
if (content != null && content.getType() != Material.AIR) {
items.put(i, content);
log("Added item to items: " + content + " at slot " + i);
}
}
log("Items: " + items);
TreasureManager tm = Manager.getInstance(TreasureManager.class);
tm.setBlocks(treasure.getId(), items);
player.closeInventory();
}
}

View file

@ -0,0 +1,64 @@
package me.unurled.sacredrealms.sr.gui.treasure;
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
import me.unurled.sacredrealms.sr.components.treasure.Treasure;
import me.unurled.sacredrealms.sr.components.treasure.TreasureManager;
import me.unurled.srcore.api.Manager;
import org.bukkit.Material;
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.jetbrains.annotations.NotNull;
import xyz.xenondevs.invui.item.Item;
import xyz.xenondevs.invui.item.ItemProvider;
import xyz.xenondevs.invui.item.builder.ItemBuilder;
import xyz.xenondevs.invui.item.impl.AbstractItem;
import xyz.xenondevs.invui.window.Window;
public class DeleteItem extends AbstractItem {
private final Treasure treasure;
public DeleteItem(Treasure treasure) {
this.treasure = treasure;
}
/**
* Gets the {@link ItemProvider}. This method gets called every time a {@link Window} is notified
* ({@link #notifyWindows()}).
*
* @return The {@link ItemProvider}
*/
@Override
public ItemProvider getItemProvider() {
ItemStack delete = new ItemStack(Material.RED_STAINED_GLASS_PANE);
ItemMeta deleteMeta = delete.getItemMeta();
deleteMeta.displayName(textComp("<b><red>Delete</red></b>"));
delete.setItemMeta(deleteMeta);
return new ItemBuilder(delete);
}
/**
* A method called if the {@link ItemStack} associated to this {@link Item} has been clicked by a
* player.
*
* @param clickType The {@link ClickType} the {@link Player} performed.
* @param player The {@link Player} who clicked on the {@link ItemStack}.
* @param event The {@link InventoryClickEvent} associated with this click.
*/
@Override
public void handleClick(
@NotNull ClickType clickType, @NotNull Player player, @NotNull InventoryClickEvent event) {
// delete treasure
if (!player.hasPermission("sr.treasure.delete")) {
return;
}
TreasureManager treasureManager = Manager.getInstance(TreasureManager.class);
treasureManager.removeTreasure(treasure);
player.sendMessage(textComp("<red>Treasure deleted!"));
player.closeInventory();
}
}

View file

@ -1,16 +1,15 @@
package me.unurled.sacredrealms.sr.gui.treasure; package me.unurled.sacredrealms.sr.gui.treasure;
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
import static me.unurled.sacredrealms.sr.utils.Items.cancelItem;
import static me.unurled.sacredrealms.sr.utils.Items.glassPane; import static me.unurled.sacredrealms.sr.utils.Items.glassPane;
import java.util.Map;
import me.unurled.sacredrealms.sr.components.treasure.Treasure; import me.unurled.sacredrealms.sr.components.treasure.Treasure;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import xyz.xenondevs.invui.gui.Gui; import xyz.xenondevs.invui.gui.Gui;
import xyz.xenondevs.invui.gui.Gui.Builder.Normal; import xyz.xenondevs.invui.inventory.Inventory;
import xyz.xenondevs.invui.inventory.VirtualInventory;
import xyz.xenondevs.invui.inventory.event.UpdateReason;
import xyz.xenondevs.invui.item.Item; import xyz.xenondevs.invui.item.Item;
import xyz.xenondevs.invui.item.impl.SimpleItem; import xyz.xenondevs.invui.item.impl.SimpleItem;
@ -22,36 +21,31 @@ public class TreasureGUI {
public static Gui createGui(@NotNull Treasure treasure) { public static Gui createGui(@NotNull Treasure treasure) {
ItemStack itemStack = glassPane(); ItemStack itemStack = glassPane();
Item pane = new SimpleItem(itemStack); Item pane = new SimpleItem(itemStack);
Normal gui =
Gui.normal() Inventory inventory = new VirtualInventory(27);
.setStructure(".........", "abcdefghi", "jklmnopqr", "stuvwxyz$", "...123...") inventory.setPreUpdateHandler(
.addIngredient('.', pane); (itemPreUpdateEvent) -> {
if (!treasure.getItems().isEmpty()) { if (itemPreUpdateEvent.isAdd()
for (int i = 0; i < treasure.getItems().size(); i++) { || itemPreUpdateEvent.isRemove()
Item item = new SimpleItem(treasure.getItems().get(i)); || itemPreUpdateEvent.isSwap()) {
if (i == 28) { itemPreUpdateEvent.setCancelled(false);
gui.addIngredient('$', item); }
} else { });
gui.addIngredient((char) (i + 'a'), item);
} Map<Integer, ItemStack> items = treasure.getItems();
if (!items.isEmpty()) {
for (int i = 0; i < items.size(); i++) {
inventory.setItem(UpdateReason.SUPPRESSED, i, items.get(i));
} }
} }
ItemStack cancel = cancelItem(); Gui gui = Gui.empty(9, 5);
gui.fill(pane, true);
gui.fillRectangle(0, 1, 9, inventory, true);
gui.setItem(39, new DeleteItem(treasure));
gui.setItem(40, new CancelItem());
gui.setItem(41, new ConfirmItem(treasure));
ItemStack confirm = new ItemStack(Material.GREEN_STAINED_GLASS_PANE); return gui;
ItemMeta confirmMeta = confirm.getItemMeta();
confirmMeta.displayName(textComp("<b><green>Confirm</green></b>"));
confirm.setItemMeta(confirmMeta);
ItemStack delete = new ItemStack(Material.RED_STAINED_GLASS_PANE);
ItemMeta deleteMeta = delete.getItemMeta();
deleteMeta.displayName(textComp("<b><red>Delete</red></b>"));
delete.setItemMeta(deleteMeta);
gui.addIngredient('1', new SimpleItem(delete));
gui.addIngredient('2', new SimpleItem(cancel));
gui.addIngredient('3', new SimpleItem(confirm));
return gui.build();
} }
} }

View file

@ -1,51 +0,0 @@
package me.unurled.sacredrealms.sr.managers;
import me.unurled.sacredrealms.sr.SR;
import org.bukkit.Bukkit;
import org.bukkit.event.Listener;
public class Manager implements Listener {
/** Constructor for the Manager class */
public Manager() {
SR.getInstance().getManagers().addManager(this);
Bukkit.getScheduler()
.runTaskAsynchronously(
SR.getInstance(),
() -> {
load();
Bukkit.getPluginManager().registerEvents(this, SR.getInstance());
});
}
/**
* Get an instance of a manager
*
* @param clazz The class of the manager
* @return The instance of the manager
* @param <T> The type of the manager
*/
public static <T extends Manager> T getInstance(Class<T> clazz) {
return clazz.cast(SR.getInstance().getManagers().getManager(clazz));
}
/** Load the manager */
public void load() {
loadData();
}
/** Unload the manager */
public void unload() {
saveData();
}
/** Save the data */
public void saveData() {
/* method empty, so it isn't required by the extended child to implement it */
}
/** Load the data */
public void loadData() {
/* method empty, so it isn't required by the extended child to implement it */
}
}

View file

@ -1,79 +0,0 @@
package me.unurled.sacredrealms.sr.managers;
import static me.unurled.sacredrealms.sr.utils.Logger.error;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import me.unurled.sacredrealms.sr.SR;
import me.unurled.sacredrealms.sr.components.clientbuild.ClientBuildManager;
import me.unurled.sacredrealms.sr.components.combat.CombatManager;
import me.unurled.sacredrealms.sr.components.entity.EntityManager;
import me.unurled.sacredrealms.sr.components.item.ItemManager;
import me.unurled.sacredrealms.sr.components.player.PlayerManager;
import me.unurled.sacredrealms.sr.components.treasure.TreasureManager;
import me.unurled.sacredrealms.sr.data.DataManager;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class Managers {
private final List<Manager> managers;
public Managers() {
managers = new ArrayList<>();
// register managers here (like a new instance of them)
register(
List.of(
DataManager.class,
PlayerManager.class,
CombatManager.class,
ItemManager.class,
EntityManager.class,
ClientBuildManager.class,
TreasureManager.class));
}
private void register(@NotNull List<Class<? extends Manager>> clazz) {
int i = 0;
for (Class<? extends Manager> c : clazz) {
Bukkit.getScheduler()
.runTaskLater(
SR.getInstance(),
() -> {
try {
c.getDeclaredConstructor().newInstance();
} catch (InstantiationException
| IllegalAccessException
| InvocationTargetException
| NoSuchMethodException e) {
error("Failed to register manager: " + c.getSimpleName());
}
},
10L * i);
i++;
}
}
public void addManager(Manager manager) {
managers.add(manager);
}
public void unload() {
for (Manager manager : managers) {
manager.unload();
}
}
@Nullable
public Manager getManager(Class<? extends Manager> clazz) {
for (Manager manager : managers) {
if (manager.getClass().equals(clazz)) {
return manager;
}
}
return null;
}
}

View file

@ -0,0 +1,65 @@
package me.unurled.sacredrealms.sr.utils;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.jetbrains.annotations.NotNull;
public class ChunkWrapper {
private int x;
private int z;
private World world;
public ChunkWrapper(@NotNull Chunk chunk) {
this.x = chunk.getX();
this.z = chunk.getZ();
this.world = chunk.getWorld();
}
@Override
public int hashCode() {
int hash = 17;
hash = hash * 31 + x;
hash = hash * 31 + z;
hash = hash * 31 + world.hashCode();
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
if (!(obj instanceof ChunkWrapper)) return false;
return ((ChunkWrapper) obj).x == this.x
&& ((ChunkWrapper) obj).z == this.z
&& ((ChunkWrapper) obj).world.equals(this.world);
}
@Override
public String toString() {
return "(" + x + ", " + z + ") [" + world + "]";
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getZ() {
return z;
}
public void setZ(int z) {
this.z = z;
}
public World getWorld() {
return world;
}
public void setWorld(World world) {
this.world = world;
}
}

View file

@ -1,5 +1,7 @@
package me.unurled.sacredrealms.sr.utils; 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.TextComponent;
import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.MiniMessage;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -29,4 +31,9 @@ public class Component {
} }
return (TextComponent) miniMessage.deserialize(msg); 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());
}
} }

View file

@ -0,0 +1,67 @@
package me.unurled.sacredrealms.sr.utils;
import static me.unurled.sacredrealms.sr.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;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class CutsceneUtil {
private static final String FONT = "custom";
private CutsceneUtil() {}
public static void showBlackScreen(@NotNull Player p, int duration, int fadeIn, int fadeOut) {
// /title @s title {"text":"\uE000","color":"black"}
Title title =
Title.title(
textComp("\uE000").font(Key.key(FONT)),
textComp(""),
Times.times(
Duration.ofSeconds(fadeIn),
Duration.ofSeconds(duration),
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;
}
}

View file

@ -0,0 +1,70 @@
package me.unurled.sacredrealms.sr.utils;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.jetbrains.annotations.NotNull;
public class File {
private File() {}
public static @NotNull String getFileChecksum(String filePath)
throws IOException, NoSuchAlgorithmException {
MessageDigest sha = MessageDigest.getInstance("MD5");
try (FileInputStream fis = new FileInputStream(filePath)) {
DigestInputStream dis = new DigestInputStream(fis, sha);
while (dis.read() != -1)
;
dis.close();
}
// Convert the byte array to a hexadecimal string
byte[] bytes = sha.digest();
StringBuilder sb = new StringBuilder();
for (byte aByte : bytes) {
sb.append(String.format("%02x", aByte));
}
return sb.toString();
}
public static void zipFile(
@NotNull java.io.File fileToZip, String fileName, ZipOutputStream zipOut) throws IOException {
if (fileToZip.isHidden()) {
return;
}
try (FileInputStream fis = new FileInputStream(fileToZip)) {
ZipEntry zipEntry = new ZipEntry(fileName);
zipEntry.setTime(0);
zipOut.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) >= 0) {
zipOut.write(bytes, 0, length);
}
zipOut.closeEntry();
}
}
public static void zipDirectory(
@NotNull java.io.File folderToZip, String folderName, ZipOutputStream zipOut)
throws IOException {
java.io.File[] children = folderToZip.listFiles();
if (children == null) {
return;
}
for (java.io.File childFile : children) {
if (childFile.isDirectory()) {
zipDirectory(childFile, folderName + "/" + childFile.getName(), zipOut);
} else {
zipFile(childFile, folderName + "/" + childFile.getName(), zipOut);
}
}
}
}

View file

@ -0,0 +1,156 @@
package me.unurled.sacredrealms.sr.utils;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
public class HTTPRequestMultipartBody {
private final byte[] bytes;
private String boundary;
private HTTPRequestMultipartBody(byte[] bytes, String boundary) {
this.bytes = bytes;
this.boundary = boundary;
}
public String getBoundary() {
return boundary;
}
public void setBoundary(String boundary) {
this.boundary = boundary;
}
public String getContentType() {
return "multipart/form-data; boundary=" + this.getBoundary();
}
public byte[] getBody() {
return this.bytes;
}
public static class Builder {
public static final String CONTENT_TYPE = "Content-Type: application/octet-stream\r\n\r\n";
List<MultiPartRecord> parts;
public Builder() {
this.parts = new ArrayList<>();
}
public Builder addPart(String fieldName, String fieldValue) {
MultiPartRecord part = new MultiPartRecord();
part.setFieldName(fieldName);
part.setContent(fieldValue);
String defaultMimetype = "text/plain";
part.setContentType(defaultMimetype);
this.parts.add(part);
return this;
}
public Builder addPart(String fieldName, String fieldValue, String contentType) {
MultiPartRecord part = new MultiPartRecord();
part.setFieldName(fieldName);
part.setContent(fieldValue);
part.setContentType(contentType);
this.parts.add(part);
return this;
}
public Builder addPart(
String fieldName, Object fieldValue, String contentType, String fileName) {
MultiPartRecord part = new MultiPartRecord();
part.setFieldName(fieldName);
part.setContent(fieldValue);
part.setContentType(contentType);
part.setFilename(fileName);
this.parts.add(part);
return this;
}
public HTTPRequestMultipartBody build() throws IOException {
String boundary = new BigInteger(256, new SecureRandom()).toString();
ByteArrayOutputStream out = new ByteArrayOutputStream();
for (MultiPartRecord multiPartRecord : parts) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder
.append("--")
.append(boundary)
.append("\r\n")
.append("Content-Disposition: form-data; name=\"")
.append(multiPartRecord.getFieldName());
if (multiPartRecord.getFilename() != null) {
stringBuilder.append("\"; filename=\"").append(multiPartRecord.getFilename());
}
out.write(stringBuilder.toString().getBytes(StandardCharsets.UTF_8));
out.write(("\"\r\n").getBytes(StandardCharsets.UTF_8));
Object content = multiPartRecord.getContent();
if (content instanceof String cont) {
out.write(("\r\n\r\n").getBytes(StandardCharsets.UTF_8));
out.write(cont.getBytes(StandardCharsets.UTF_8));
} else if (content instanceof byte[] cont) {
out.write(CONTENT_TYPE.getBytes(StandardCharsets.UTF_8));
out.write(cont);
} else if (content instanceof File file) {
out.write(CONTENT_TYPE.getBytes(StandardCharsets.UTF_8));
Files.copy(file.toPath(), out);
} else {
out.write(CONTENT_TYPE.getBytes(StandardCharsets.UTF_8));
ObjectOutputStream objectOutputStream = new ObjectOutputStream(out);
objectOutputStream.writeObject(content);
objectOutputStream.flush();
}
out.write("\r\n".getBytes(StandardCharsets.UTF_8));
}
out.write(("--" + boundary + "--\r\n").getBytes(StandardCharsets.UTF_8));
return new HTTPRequestMultipartBody(out.toByteArray(), boundary);
}
public static class MultiPartRecord {
private String fieldName;
private String filename;
private String contentType;
private Object content;
public String getFieldName() {
return fieldName;
}
public void setFieldName(String fieldName) {
this.fieldName = fieldName;
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public Object getContent() {
return content;
}
public void setContent(Object content) {
this.content = content;
}
}
}
}

View file

@ -4,6 +4,7 @@ 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.Component.textComp;
import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.syncSRToPlayer; import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.syncSRToPlayer;
import com.google.gson.JsonElement;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -11,9 +12,12 @@ import java.util.concurrent.atomic.AtomicReference;
import me.unurled.sacredrealms.sr.components.attributes.Attribute; import me.unurled.sacredrealms.sr.components.attributes.Attribute;
import me.unurled.sacredrealms.sr.components.item.Item; import me.unurled.sacredrealms.sr.components.item.Item;
import me.unurled.sacredrealms.sr.components.item.ItemManager; import me.unurled.sacredrealms.sr.components.item.ItemManager;
import me.unurled.sacredrealms.sr.components.item.ItemStackDeserializer;
import me.unurled.sacredrealms.sr.components.item.ItemStackSerializer;
import me.unurled.sacredrealms.sr.components.player.PlayerManager; import me.unurled.sacredrealms.sr.components.player.PlayerManager;
import me.unurled.sacredrealms.sr.components.player.SRPlayer; import me.unurled.sacredrealms.sr.components.player.SRPlayer;
import me.unurled.sacredrealms.sr.managers.Manager; import me.unurled.srcore.api.Manager;
import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.EntityEquipment;
@ -68,21 +72,10 @@ public class Items {
ItemManager im = Manager.getInstance(ItemManager.class); ItemManager im = Manager.getInstance(ItemManager.class);
if (im == null) return 0.0; if (im == null) return 0.0;
if (item == null) return 0.0; if (item == null) return 0.0;
if (item.getType().equals(Material.AIR)) return 0.0;
PersistentDataContainer p = item.getItemMeta().getPersistentDataContainer(); Item it = im.getItem(item);
if (p.has(ItemManager.ID, PersistentDataType.STRING)) { if (it != null) return it.getAttribute(attribute);
Item i = im.getItem(p.get(ItemManager.ID, PersistentDataType.STRING));
if (i != null) {
return i.getAttribute(attribute);
}
}
if (p.has(attribute.getKey(), PersistentDataType.DOUBLE)) {
try {
return p.get(attribute.getKey(), PersistentDataType.DOUBLE);
} catch (Exception e) {
return 0.0;
}
}
return 0.0; return 0.0;
} }
@ -171,4 +164,29 @@ public class Items {
syncSRToPlayer(p, player); syncSRToPlayer(p, player);
} }
public static @NotNull ItemStack name(@NotNull ItemStack stack, String name) {
ItemMeta meta = stack.getItemMeta();
meta.displayName(textComp(name));
stack.setItemMeta(meta);
return stack;
}
public static @NotNull String locationToString(@NotNull Location location) {
return location.getWorld().getName()
+ "_z"
+ location.getBlockX()
+ "y"
+ location.getBlockY()
+ "z"
+ location.getBlockZ();
}
public static JsonElement serialize(ItemStack itemStack) {
return new ItemStackSerializer().serialize(itemStack, ItemStack.class, null);
}
public static @NotNull ItemStack deserialize(@NotNull JsonElement jsonElement) {
return new ItemStackDeserializer().deserialize(jsonElement, ItemStack.class, null);
}
} }

View file

@ -3,9 +3,12 @@ package me.unurled.sacredrealms.sr.utils;
import static me.unurled.sacredrealms.sr.utils.Component.comp; import static me.unurled.sacredrealms.sr.utils.Component.comp;
import java.util.List; import java.util.List;
import java.util.Random;
import me.unurled.sacredrealms.sr.SR; import me.unurled.sacredrealms.sr.SR;
import me.unurled.sacredrealms.sr.components.attributes.Attribute; import me.unurled.sacredrealms.sr.components.attributes.Attribute;
import me.unurled.sacredrealms.sr.components.player.PlayerManager;
import me.unurled.sacredrealms.sr.components.player.SRPlayer; import me.unurled.sacredrealms.sr.components.player.SRPlayer;
import me.unurled.srcore.api.Manager;
import org.bukkit.attribute.AttributeInstance; import org.bukkit.attribute.AttributeInstance;
import org.bukkit.entity.Display; import org.bukkit.entity.Display;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
@ -18,6 +21,8 @@ import org.jetbrains.annotations.NotNull;
public class SRPlayerUtils { public class SRPlayerUtils {
private static final Random RANDOM = new Random();
private SRPlayerUtils() {} private SRPlayerUtils() {}
public static void syncPlayerToSR(@NotNull Player p, @NotNull SRPlayer sr) { public static void syncPlayerToSR(@NotNull Player p, @NotNull SRPlayer sr) {
@ -58,7 +63,11 @@ public class SRPlayerUtils {
p.updateInventory(); p.updateInventory();
} }
public static void updateActionBar(@NotNull Player p, @NotNull SRPlayer sr) { public static void updateActionBar(@NotNull Player p) {
PlayerManager pm = Manager.getInstance(PlayerManager.class);
if (pm == null) return;
SRPlayer sr = pm.getPlayer(p.getUniqueId());
if (sr == null) return;
int maxHealth = (int) sr.getAttribute(Attribute.HEALTH); int maxHealth = (int) sr.getAttribute(Attribute.HEALTH);
int health = (int) sr.getHealth(); int health = (int) sr.getHealth();
int mana = (int) sr.getAttribute(Attribute.MANA); int mana = (int) sr.getAttribute(Attribute.MANA);
@ -80,11 +89,17 @@ public class SRPlayerUtils {
Vector spawnVector = location.add(facingVector.multiply(0.75)); Vector spawnVector = location.add(facingVector.multiply(0.75));
// summon entity // summon entity
double randomX = RANDOM.nextDouble() * 0.5 - 0.25;
double randomZ = RANDOM.nextDouble() * 0.5 - 0.25;
spawnVector.add(new Vector(randomX, 0, randomZ));
TextDisplay indicators = TextDisplay indicators =
eventEntity eventEntity
.getWorld() .getWorld()
.spawn( .spawn(
spawnVector.toLocation(eventEntity.getWorld()).add(0, 0.7, 0), TextDisplay.class); spawnVector.toLocation(eventEntity.getWorld()).add(0.0, 0.5, 0.0),
TextDisplay.class);
String prefix = "<red>-"; String prefix = "<red>-";
if (isHeal) prefix = "<green>+"; if (isHeal) prefix = "<green>+";
@ -114,6 +129,6 @@ public class SRPlayerUtils {
} }
height++; height++;
} }
}.runTaskTimer(SR.getInstance(), 0, 1); }.runTaskTimer(SR.getPlugin(), 0, 1);
} }
} }

View file

@ -0,0 +1,235 @@
package me.unurled.sacredrealms.sr.utils.character;
import org.jetbrains.annotations.NotNull;
public enum CharRepo {
A('A', 5),
a('a', 5),
B('B', 5),
b('b', 5),
C('C', 5),
c('c', 5),
D('D', 5),
d('d', 5),
E('E', 5),
e('e', 5),
F('F', 5),
f('f', 4),
G('G', 5),
g('g', 5),
H('H', 5),
h('h', 5),
I('I', 3),
i('i', 1),
J('J', 5),
j('j', 5),
K('K', 5),
k('k', 4),
L('L', 5),
l('l', 1),
M('M', 5),
m('m', 5),
N('N', 5),
n('n', 5),
O('O', 5),
o('o', 5),
P('P', 5),
p('p', 5),
Q('Q', 5),
q('q', 5),
R('R', 5),
r('r', 5),
S('S', 5),
s('s', 5),
T('T', 5),
t('t', 4),
U('U', 5),
u('u', 5),
V('V', 5),
v('v', 5),
W('W', 5),
w('w', 5),
X('X', 5),
x('x', 5),
Y('Y', 5),
y('y', 5),
Z('Z', 5),
z('z', 5),
NUM_1('1', 5),
NUM_2('2', 5),
NUM_3('3', 5),
NUM_4('4', 5),
NUM_5('5', 5),
NUM_6('6', 5),
NUM_7('7', 5),
NUM_8('8', 5),
NUM_9('9', 5),
NUM_0('0', 5),
EXCLAMATION_POINT('!', 1),
AT_SYMBOL('@', 6),
NUM_SIGN('#', 5),
DOLLAR_SIGN('$', 5),
PERCENT('%', 5),
UP_ARROW('^', 5),
AMPERSAND('&', 5),
ASTERISK('*', 5),
LEFT_PARENTHESIS('(', 4),
RIGHT_PERENTHESIS(')', 4),
MINUS('-', 5),
UNDERSCORE('_', 5),
PLUS_SIGN('+', 5),
EQUALS_SIGN('=', 5),
LEFT_CURL_BRACE('{', 4),
RIGHT_CURL_BRACE('}', 4),
LEFT_BRACKET('[', 3),
RIGHT_BRACKET(']', 3),
COLON(':', 1),
SEMI_COLON(';', 1),
DOUBLE_QUOTE('"', 3),
SINGLE_QUOTE('\'', 1),
LEFT_ARROW('<', 4),
RIGHT_ARROW('>', 4),
QUESTION_MARK('?', 5),
SLASH('/', 5),
BACK_SLASH('\\', 5),
LINE('|', 1),
TILDE('~', 5),
TICK('`', 2),
PERIOD('.', 1),
COMMA(',', 1),
SPACE(' ', 3),
DEFAULT('\u0000', 0),
// spacing
NEG1('\uF801', -1, -3),
NEG2('\uF802', -2, -4),
NEG3('\uF803', -3, -5),
NEG4('\uF804', -4, -5),
NEG5('\uF805', -5, -7),
NEG6('\uF806', -6, -8),
NEG7('\uF807', -7, -9),
NEG8('\uF808', -8, -10),
NEG16('\uF809', -16, -18),
NEG32('\uF80A', -32, -34),
NEG64('\uF80B', -64, -66),
NEG128('\uF80C', -128, -130),
NEG256('\uF80D', -256, -258),
NEG512('\uF80E', -512, -514),
NEG1024('\uF80F', -1024, -1026),
POS1('\uF821', 1, 0),
POS2('\uF822', 2, 1),
POS4('\uF824', 4, 3),
POS8('\uF828', 8, 7),
POS16('\uF829', 16, 15),
POS32('\uF82A', 32, 31),
POS64('\uF82B', 64, 63),
POS128('\uF82C', 128, 127),
POS256('\uF82D', 256, 255),
POS512('\uF82E', 512, 511),
POS1024('\uF82F', 1024, 1023);
private final char ch;
private final int width;
private final int effectiveWidth;
CharRepo(char ch, int width) {
this.ch = ch;
this.width = width;
this.effectiveWidth = width;
}
CharRepo(char ch, int width, int effectiveWidth) {
this.ch = ch;
this.width = width;
this.effectiveWidth = effectiveWidth;
}
public static CharRepo getDefaultFontInfo(char c) {
for (CharRepo dFI : CharRepo.values()) {
if (dFI.getCh() == c) return dFI;
}
return CharRepo.DEFAULT;
}
public static int getPixelWidth(@NotNull String str) {
int val = 0;
for (char ch : str.toCharArray()) {
val += CharRepo.getDefaultFontInfo(ch).getEffectiveWidth();
val += 1; // acount for spacing
}
return val;
}
/**
* get negative characters
*
* @param n n > 0
* @return chars
*/
public static String getShortestNegChars(int n) {
StringBuilder stringBuilder = new StringBuilder();
while (n >= 128) {
stringBuilder.append(CharRepo.NEG128.getCh());
n -= 128;
}
if (n - 64 >= 0) {
stringBuilder.append(CharRepo.NEG64.getCh());
n -= 64;
}
if (n - 32 >= 0) {
stringBuilder.append(CharRepo.NEG32.getCh());
n -= 32;
}
if (n - 16 >= 0) {
stringBuilder.append(CharRepo.NEG16.getCh());
n -= 16;
}
if (n - 8 >= 0) {
stringBuilder.append(CharRepo.NEG8.getCh());
n -= 8;
}
if (n - 7 >= 0) {
stringBuilder.append(CharRepo.NEG7.getCh());
n -= 7;
}
if (n - 6 >= 0) {
stringBuilder.append(CharRepo.NEG6.getCh());
n -= 6;
}
if (n - 5 >= 0) {
stringBuilder.append(CharRepo.NEG5.getCh());
n -= 5;
}
if (n - 4 >= 0) {
stringBuilder.append(CharRepo.NEG4.getCh());
n -= 4;
}
if (n - 3 >= 0) {
stringBuilder.append(CharRepo.NEG3.getCh());
n -= 3;
}
if (n - 2 >= 0) {
stringBuilder.append(CharRepo.NEG2.getCh());
n -= 2;
}
if (n - 1 >= 0) {
stringBuilder.append(CharRepo.NEG1.getCh());
}
return stringBuilder.toString();
}
public char getCh() {
return ch;
}
public int getEffectiveWidth() {
return effectiveWidth;
}
public int getBoldLength() {
if (this == CharRepo.SPACE) return this.width;
return this.width + 1;
}
}

View file

@ -0,0 +1,39 @@
package me.unurled.sacredrealms.sr.utils.character;
public class CharacterArranger {
public static char currentChar;
public static void increase() {
currentChar = (char) (currentChar + '\u0001');
}
/**
* Get and increase the char arranged automatically by the plugin
*
* @return char
*/
public static char getAndIncrease() {
char temp = currentChar;
increase();
return temp;
}
/**
* Increase and get the char arranged automatically by the plugin
*
* @return char
*/
public static char increaseAndGet() {
increase();
return currentChar;
}
/**
* Reset the initial char
*
* @param c char
*/
public static void reset(char c) {
currentChar = c;
}
}

View file

@ -0,0 +1,104 @@
package me.unurled.sacredrealms.sr.utils.character;
import static me.unurled.sacredrealms.sr.utils.Logger.warn;
public class ConfiguredChar {
private char character;
private String pngFile;
private int height;
private int width;
private int ascent;
private ConfiguredChar() {}
public ConfiguredChar(char character, String pngFile, int height, int width, int ascent) {
this.character = character;
this.pngFile = pngFile;
this.height = height;
this.width = width;
this.ascent = ascent;
}
public static Builder builder() {
return new Builder();
}
public char getCharacter() {
return character;
}
public String getPngFile() {
return pngFile;
}
public int getHeight() {
return height;
}
public int getWidth() {
return width;
}
public int getAscent() {
return ascent;
}
public String getFile() {
return pngFile + ".png";
}
public static class Builder {
private final ConfiguredChar configuredChar;
public Builder() {
this.configuredChar = new ConfiguredChar();
}
public static Builder of() {
return new Builder();
}
public Builder character(char character) {
configuredChar.character = character;
return this;
}
public Builder png(String png) {
configuredChar.pngFile = png;
return this;
}
public Builder height(int height) {
configuredChar.height = height;
return this;
}
public Builder ascent(int ascent) {
configuredChar.ascent = ascent;
if (ascent >= configuredChar.height) {
warn("Invalid config for " + configuredChar.pngFile);
warn("Ascent " + ascent + " should be no higher than Height " + configuredChar.height);
}
return this;
}
public Builder descent(int descent) {
if (descent < 0) {
warn("Invalid config for " + configuredChar.pngFile);
warn("Descent " + descent + " should be no lower than 0");
}
configuredChar.ascent = configuredChar.height - descent;
return this;
}
public Builder width(int width) {
configuredChar.width = width;
return this;
}
public ConfiguredChar build() {
return configuredChar;
}
}
}

View file

@ -0,0 +1,97 @@
package me.unurled.sacredrealms.sr.utils.gson;
import static me.unurled.sacredrealms.sr.utils.Logger.error;
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 com.mojang.brigadier.exceptions.CommandSyntaxException;
import java.lang.reflect.Type;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.TagParser;
import org.bukkit.Location;
import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.jetbrains.annotations.NotNull;
public class EntityGson {
public class Deserializer implements JsonDeserializer<Entity> {
/**
* 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 Entity deserialize(
@NotNull JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
// get type from json, get location from json, then create entity and paste nbt data
EntityType type = EntityType.valueOf(json.getAsJsonObject().get("type").getAsString());
Location location =
new LocationSerializer()
.deserialize(json.getAsJsonObject().get("location"), Location.class, context);
Entity e = location.getWorld().spawnEntity(location, type);
net.minecraft.world.entity.Entity nmsEntity = ((CraftEntity) e).getHandle();
try {
nmsEntity.load(TagParser.parseTag(json.getAsJsonObject().get("entity").getAsString()));
} catch (CommandSyntaxException ex) {
error("Failed to parse entity NBT data " + ex.getMessage());
}
e.teleportAsync(location);
return e;
}
}
public class Serializer implements JsonSerializer<Entity> {
/**
* 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(
@NotNull Entity src, Type typeOfSrc, JsonSerializationContext context) {
net.minecraft.world.entity.Entity nmsEntity = ((CraftEntity) src).getHandle();
CompoundTag nbt = new CompoundTag();
nmsEntity.save(nbt);
LocationSerializer locationSerializer = new LocationSerializer();
String s =
"{\"type\":"
+ src.getType().name()
+ ", \"location\":"
+ locationSerializer.serialize(src.getLocation(), Location.class, context)
+ ", \"entity\":"
+ nbt.getAsString()
+ "}";
return new JsonPrimitive(s);
}
}
}

View file

@ -0,0 +1,51 @@
package me.unurled.sacredrealms.sr.utils.gson;
import com.google.gson.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 io.leangen.geantyref.TypeToken;
import java.lang.reflect.Type;
import java.util.Map;
import org.bukkit.Location;
import org.jetbrains.annotations.NotNull;
public class LocationSerializer implements JsonSerializer<Location>, JsonDeserializer<Location> {
/**
* 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(
@NotNull Location src, Type typeOfSrc, JsonSerializationContext context) {
Gson gson = new Gson();
return gson.toJsonTree(src.serialize());
}
@Override
public Location deserialize(
JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext)
throws JsonParseException {
Gson gson = new Gson();
Type typ = new TypeToken<Map<String, Object>>() {}.getType();
return Location.deserialize(gson.fromJson(jsonElement, typ));
}
}

View file

@ -0,0 +1,34 @@
package me.unurled.sacredrealms.sr.utils.gson;
import com.google.gson.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 io.leangen.geantyref.TypeToken;
import java.lang.reflect.Type;
import java.util.Map;
public class MapSerializer
implements JsonSerializer<Map<String, Object>>, JsonDeserializer<Map<String, Object>> {
@Override
public Map<String, Object> deserialize(
JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext)
throws JsonParseException {
Type typ = new TypeToken<Map<String, Object>>() {}.getType();
return new Gson().fromJson(jsonElement, typ);
}
@Override
public JsonElement serialize(
Map<String, Object> stringObjectMap,
Type type,
JsonSerializationContext jsonSerializationContext) {
return new Gson().toJsonTree(stringObjectMap);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -1,3 +1,6 @@
redis: redis:
host: "127.0.0.1" host: "127.0.0.1"
port: 6379 port: 6379
resource_pack: "http://127.0.0.1:8080"
resource_pack_api: "your_api_key_here"

View file

@ -1,59 +0,0 @@
name: $name
version: $version
main: me.unurled.sacredrealms.sr.SR
api-version: "$apiVersion"
description: $description
loader: me.unurled.sacredrealms.sr.SRLoader
bootstrapper: me.unurled.sacredrealms.sr.SRBootstrap
permissions:
sr.*:
description: Gives access to all Sacred Realms permissions
default: op
children:
sr.tutorial: true
sr.spawn: true
sr.attributes: true
sr.clientbuild: true
sr.level: true
sr.entitytype: true
sr.spawn-entity: true
sr.admin.item: true
sr.resetadventure: true
sr.treasure.manage: true
sr.difficulty.*: true
sr.tutorial:
default: not op
description: When the player joins and doesn't have finished the tutorial.
sr.spawn:
default: not op
description: When the player have discovered the spawn.
sr.attributes:
default: op
description: When the player has permission for the command /attributes set
sr.clientbuild:
default: op
description: When the player has permission for the command /clientbuild
sr.level:
default: op
description: When the player has permission for the command /level
sr.entitytype:
default: op
description: When the player has permission for the command /entitytype
sr.spawn-entity:
default: op
description: When the player has permission for the command /spawn
sr.admin.item:
default: op
description: When the player has permission for the command /item
sr.resetadventure:
default: op
description: When the player has permission for the command /resetadventure
sr.treasure.manage:
default: op
description: When the player has permission for the command /treasure create
sr.difficulty.*:
description: gives permission for all difficulty commands
children:
sr.difficulty.manage: true
sr.difficulty.self: true

View file

@ -0,0 +1 @@
{"sr":{"files":["assets/animated_java/models/empty.json","assets/animated_java/models/item/sr/top.json","assets/animated_java/models/item/sr/bottom.json","assets/animated_java/textures/item/sr/treasure_chest_top.png","assets/animated_java/textures/item/sr/treasure_chest_bottom.png","assets/animated_java/textures/item/sr/treasure_chest_metal.png","assets/animated_java/textures/item/transparent.png"]}}

View file

@ -0,0 +1 @@
{}

View file

@ -0,0 +1 @@
{"textures":{"1":"animated_java:item/sr/treasure_chest_bottom"},"elements":[{"from":[2,8,2],"to":[14,16,14],"faces":{"north":{"uv":[6,0,12,4],"texture":"#1"},"east":{"uv":[6,4,12,8],"texture":"#1"},"south":{"uv":[6,8,12,12],"texture":"#1"},"west":{"uv":[0,12,6,16],"texture":"#1"},"up":{"uv":[6,6,0,0],"texture":"#1"},"down":{"uv":[6,6,0,12],"texture":"#1"}}}],"display":{"head":{"rotation":[0,180,0]}}}

View file

@ -0,0 +1 @@
{"textures":{"0":"animated_java:item/sr/treasure_chest_top","2":"animated_java:item/sr/treasure_chest_metal"},"elements":[{"from":[7,6,20],"to":[9,10,22],"rotation":{"angle":0,"axis":"y","origin":[8,6,21]},"faces":{"north":{"uv":[0,0,2,4],"texture":"#2"},"east":{"uv":[2,0,4,4],"texture":"#2"},"south":{"uv":[0,4,2,8],"texture":"#2"},"west":{"uv":[4,0,6,4],"texture":"#2"},"up":{"uv":[4,6,2,4],"texture":"#2"},"down":{"uv":[6,4,4,6],"texture":"#2"}}},{"from":[2,8,8],"to":[14,12,20],"rotation":{"angle":0,"axis":"y","origin":[3,8,9]},"faces":{"north":{"uv":[6,0,12,2],"texture":"#0"},"east":{"uv":[6,2,12,4],"texture":"#0"},"south":{"uv":[6,4,12,6],"texture":"#0"},"west":{"uv":[6,6,12,8],"texture":"#0"},"up":{"uv":[6,6,0,0],"texture":"#0"},"down":{"uv":[6,6,0,12],"texture":"#0"}}}],"display":{"head":{"rotation":[0,180,0]}}}

Some files were not shown because too many files have changed in this diff Show more