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 {
`java-library`
id("io.papermc.paperweight.userdev") version "1.7.1"
id("io.github.goooler.shadow") version "8.1.7"
id("org.sonarqube") version "4.4.1.3373"
id("io.papermc.paperweight.userdev") version "1.7.2"
id("org.sonarqube") version "5.1.0.4882"
id("net.minecrell.plugin-yml.paper") version "0.6.0"
}
// from 1.20.5+ upward, spigot is not supported
@ -13,23 +15,42 @@ group = "me.unurled.sacredrealms"
version = "0.1.0"
description = "The main SR plugin."
val mcVersion = "1.21-R0.1-SNAPSHOT"
val redisVersion = "5.2.0-beta2"
val invuiVersion = "1.32"
val mcVersion = "1.21.1-R0.1-SNAPSHOT"
val redisVersion = "5.2.0-beta4"
val invuiVersion = "1.36"
val gsonVersion = "2.11.0"
val javaVersion = 21
repositories {
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 {
paperweight.paperDevBundle(mcVersion)
implementation("redis.clients:jedis:${redisVersion}")
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 {
@ -45,33 +66,6 @@ tasks {
javadoc {
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 {
properties {
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
org.gradle.jvmargs=-Xmx16384M

View file

@ -1,34 +1,73 @@
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 xyz.xenondevs.invui.InvUI;
public final class SR extends JavaPlugin {
private static SR instance;
private Managers managers;
private static SR plugin;
public static SR getInstance() {
return instance;
public static SR getPlugin() {
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
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);
managers = new Managers();
}
@Override
public void onDisable() {
managers.unload();
managers = null;
}
SRCore.getInstance().unload();
public Managers getManagers() {
return managers;
PacketEvents.getAPI().terminate();
}
}

View file

@ -1,8 +1,15 @@
package me.unurled.sacredrealms.sr;
import com.google.gson.Gson;
import io.papermc.paper.plugin.loader.PluginClasspathBuilder;
import io.papermc.paper.plugin.loader.PluginLoader;
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.graph.Dependency;
import org.eclipse.aether.repository.RemoteRepository;
@ -12,15 +19,37 @@ public class SRLoader implements PluginLoader {
@Override
public void classloader(@NotNull PluginClasspathBuilder classpathBuilder) {
MavenLibraryResolver resolver = new MavenLibraryResolver();
resolver.addDependency(
new Dependency(new DefaultArtifact("xyz.xenondevs.invui:inventory-access-r20:1.32"), null));
resolver.addDependency(
new Dependency(new DefaultArtifact("xyz.xenondevs.invui:invui-core:1.32"), null));
new Dependency(new DefaultArtifact("xyz.xenondevs.invui:invui:pom:1.36"), null));
resolver.addRepository(
new RemoteRepository.Builder("invui", "default", "https://repo.xenondevs.xyz/releases/")
.build());
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;
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.Commands;
import io.papermc.paper.plugin.bootstrap.BootstrapContext;
import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager;
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.ClientBuildCommand;
import me.unurled.sacredrealms.sr.commands.admin.CutsceneCommand;
import me.unurled.sacredrealms.sr.commands.admin.EntityTypeCommand;
import me.unurled.sacredrealms.sr.commands.admin.ItemCommand;
import me.unurled.sacredrealms.sr.commands.admin.LevelCommand;
@ -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.player.DifficultyCommand;
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 {
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();
try {
@ -31,9 +43,8 @@ public class CommandManager extends Manager {
LifecycleEvents.COMMANDS,
event -> {
final Commands commands = event.registrar();
commands.register(command, description, instance);
commands.register(command, description, aliases, instance);
});
log("Registered command: " + command);
} catch (Exception e) {
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);
registerCommand(
"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.SRPlayer;
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.command.CommandSender;
import org.bukkit.entity.Player;
@ -256,8 +256,8 @@ public class AttributeCommand implements BasicCommand {
* @return a collection of suggestions
*/
@Override
public @NotNull Collection<String> suggest(@NotNull CommandSourceStack commandSourceStack,
@NotNull String[] args) {
public @NotNull Collection<String> suggest(
@NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) {
CommandSender sender = commandSourceStack.getSender();
if (!sender.hasPermission("sr.attributes")) {
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.player.PlayerManager;
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.block.Block;
import org.bukkit.block.data.BlockData;
@ -179,6 +179,7 @@ public class ClientBuildCommand implements BasicCommand, Listener {
if (build != null) sender.sendMessage(build.getName());
}
}
@EventHandler
public void onBlockPlace(@NotNull BlockPlaceEvent e) {
Player p = e.getPlayer();
@ -286,8 +287,8 @@ public class ClientBuildCommand implements BasicCommand, Listener {
* @return a collection of suggestions
*/
@Override
public @NotNull Collection<String> suggest(@NotNull CommandSourceStack commandSourceStack,
@NotNull String[] args) {
public @NotNull Collection<String> suggest(
@NotNull CommandSourceStack commandSourceStack, @NotNull String @NotNull [] args) {
if (args.length == 1) {
return List.of("create", DELETE, "list", MODIFY, "save", DISPLAY);
} else if (args.length == 2

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.SREntityType;
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.entity.EntityType;
import org.bukkit.entity.Player;
@ -33,7 +33,7 @@ public class EntityTypeCommand implements BasicCommand {
}
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();
}
@ -74,8 +74,7 @@ public class EntityTypeCommand implements BasicCommand {
try {
EntityType type = EntityType.valueOf(args[4]);
EntityManager em = Manager.getInstance(EntityManager.class);
if (setType(sender, args, em, type)) {
}
if (setType(sender, args, em, type)) {}
} catch (IllegalArgumentException e) {
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])) {
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) {
@ -169,8 +168,8 @@ public class EntityTypeCommand implements BasicCommand {
* @return a collection of suggestions
*/
@Override
public @NotNull Collection<String> suggest(@NotNull CommandSourceStack commandSourceStack,
@NotNull String[] args) {
public @NotNull Collection<String> suggest(
@NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) {
CommandSender sender = commandSourceStack.getSender();
if (sender.hasPermission("sr.entitytype")) {
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.abilities.Ability;
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.Material;
import org.bukkit.command.CommandSender;
@ -380,7 +380,7 @@ public class ItemCommand implements BasicCommand {
.map(
name -> {
if (name.name().startsWith(args[3].toUpperCase())) return name.name();
return null;
return "";
})
.toList();
}
@ -392,8 +392,8 @@ public class ItemCommand implements BasicCommand {
p.getInventory().setItemInMainHand(newItem.toItemStack());
}
@Nullable
private static List<String> modifyCompletion(@NotNull String @NotNull [] args) {
private static @NotNull List<String> modifyCompletion(@NotNull String @NotNull [] args) {
if (args.length < 3) return List.of();
if (args[2].equalsIgnoreCase(RARITY)) {
return Arrays.stream(Rarity.values()).map(Enum::name).toList();
} else if (args[2].equalsIgnoreCase("type")) {
@ -403,7 +403,7 @@ public class ItemCommand implements BasicCommand {
.map(
name -> {
if (name.name().startsWith(args[3].toUpperCase())) return name.name();
return null;
return "";
})
.toList();
} else if (args[2].equalsIgnoreCase(ENCHANTMENTS)) {
@ -414,12 +414,12 @@ public class ItemCommand implements BasicCommand {
return List.of("add", REMOVE);
} else if (args[2].equalsIgnoreCase(CUSTOMMODELDATA)) {
try {
Integer.parseInt(args[3]);
if (args.length == 4) Integer.parseInt(args[3]);
} catch (NumberFormatException e) {
return List.of("1");
}
}
return null;
return List.of();
}
@Nullable
@ -507,7 +507,7 @@ public class ItemCommand implements BasicCommand {
return List.of("");
}
if (args.length == 1) {
if (args.length <= 1) {
return List.of("list", "create", DELETE, "give", MODIFY);
}

View file

@ -6,7 +6,7 @@ import java.util.Collection;
import java.util.List;
import me.unurled.sacredrealms.sr.components.player.PlayerManager;
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.entity.Player;
import org.jetbrains.annotations.NotNull;

View file

@ -9,7 +9,7 @@ import java.util.Collection;
import java.util.List;
import me.unurled.sacredrealms.sr.components.entity.EntityManager;
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.command.CommandSender;
import org.bukkit.entity.Player;
@ -28,11 +28,12 @@ public class SpawnEntityCommand implements BasicCommand {
return;
}
SREntityType eType = em.getType(type);
if (type == null) {
if (eType == null) {
sender.sendMessage("Invalid entity type.");
return;
}
em.spawnEntity(eType, amount, x, y, z, world);
sender.sendMessage("Spawned " + amount + " " + eType.getName() + "s.");
}
private int getAmount(CommandSender sender, String @NotNull [] args) {
@ -81,7 +82,7 @@ public class SpawnEntityCommand implements BasicCommand {
}
}
if (args[3].equals("~")) {
y = p.getLocation().getX();
y = p.getLocation().getY();
} else {
try {
y = Double.parseDouble(args[3]);
@ -91,7 +92,7 @@ public class SpawnEntityCommand implements BasicCommand {
}
}
if (args[4].equals("~")) {
z = p.getLocation().getX();
z = p.getLocation().getZ();
} else {
try {
z = Double.parseDouble(args[4]);
@ -142,8 +143,8 @@ public class SpawnEntityCommand implements BasicCommand {
* @return a collection of suggestions
*/
@Override
public @NotNull Collection<String> suggest(@NotNull CommandSourceStack commandSourceStack,
@NotNull String[] args) {
public @NotNull Collection<String> suggest(
@NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) {
CommandSender sender = commandSourceStack.getSender();
if (sender.hasPermission("sr.spawn-entity")) {
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.TreasureManager;
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 org.bukkit.Material;
import org.bukkit.block.Block;
@ -54,11 +54,10 @@ public class TreasureCommand implements BasicCommand {
for (Treasure treasure : instance.getTreasures()) {
String s =
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().getBlockY(),
treasure.getLocation().getBlockZ(),
treasure.getLocation().toString(),
treasure.getLocation().getBlockX(),
treasure.getLocation().getBlockY(),
treasure.getLocation().getBlockZ());
@ -85,10 +84,12 @@ public class TreasureCommand implements BasicCommand {
Window window =
Window.single()
.setViewer(p)
.setTitle("Attributes")
.setTitle("Modifiy Treasure Chest")
.setGui(TreasureGUI.createGui(treasure))
.build();
window.open();
} else {
p.sendMessage(textComp("<red>Target block is not a chest."));
}
}
@ -112,7 +113,10 @@ public class TreasureCommand implements BasicCommand {
} else {
treasure = new Treasure(instance.getNextId(), block.getLocation());
}
block.setBlockData(Material.AIR.createBlockData());
instance.addTreasure(treasure);
} else {
p.sendMessage(textComp("<red>Target block is not a chest."));
}
}
@ -123,7 +127,8 @@ public class TreasureCommand implements BasicCommand {
* @param args the arguments of the command ignoring repeated spaces
*/
@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();
if (args.length == 0) {
sender.sendMessage("Usage: /treasure <create|modify|list|delete>");
@ -147,8 +152,8 @@ public class TreasureCommand implements BasicCommand {
* @return a collection of suggestions
*/
@Override
public @NotNull Collection<String> suggest(@NotNull CommandSourceStack commandSourceStack,
@NotNull String[] args) {
public @NotNull Collection<String> suggest(
@NotNull CommandSourceStack commandSourceStack, @NotNull String @NotNull [] args) {
if (args.length == 0) {
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.SRPlayer;
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.text.Component;
import org.bukkit.Bukkit;
@ -184,8 +184,8 @@ public class DifficultyCommand implements BasicCommand {
* @return a collection of suggestions
*/
@Override
public @NotNull Collection<String> suggest(@NotNull CommandSourceStack commandSourceStack,
@NotNull String[] args) {
public @NotNull Collection<String> suggest(
@NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) {
CommandSender sender = commandSourceStack.getSender();
if (args.length == 0 && sender.hasPermission(DIFFICULTY_MANAGE)) {
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.components.player.PlayerManager;
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.OfflinePlayer;
import org.bukkit.command.CommandSender;
@ -39,7 +39,7 @@ public class ResetAdventureCommand implements BasicCommand {
}
return;
}
OfflinePlayer player = SR.getInstance().getServer().getOfflinePlayer(args[0]);
OfflinePlayer player = SR.getPlugin().getServer().getOfflinePlayer(args[0]);
boolean status = resetAdventure(player);
if (status) {
@ -62,7 +62,6 @@ public class ResetAdventureCommand implements BasicCommand {
return false;
}
/**
* Executes the command with the given {@link CommandSourceStack} and arguments.
*
@ -111,8 +110,8 @@ public class ResetAdventureCommand implements BasicCommand {
* @return a collection of suggestions
*/
@Override
public @NotNull Collection<String> suggest(@NotNull CommandSourceStack commandSourceStack,
@NotNull String[] args) {
public @NotNull Collection<String> suggest(
@NotNull CommandSourceStack commandSourceStack, @NotNull String[] args) {
CommandSender sender = commandSourceStack.getSender();
if (sender.hasPermission("sr.resetadventure")) {
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 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 java.lang.reflect.Type;
import me.unurled.sacredrealms.sr.utils.gson.LocationSerializer;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.data.BlockData;
import org.jetbrains.annotations.NotNull;
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}
*/
@Override
public ClientBuild deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
public ClientBuild deserialize(
@NotNull JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
String[] data = json.getAsString().split(";");
ClientBuild build = new ClientBuild(data[0]);
LocationSerializer locDes = new LocationSerializer();
for (String block : data[1].split(",")) {
String[] spl = block.replace("{", "").replace("}", "").split("\\|");
World world = Bukkit.getWorld(spl[0]);
if (world == null) {
error("World " + spl[0] + " does not exist");
return build;
}
Location loc;
Location loc = locDes.deserialize(new Gson().toJsonTree(spl[0]), Location.class, context);
BlockData bData;
try {
loc =
new Location(
world,
Integer.parseInt(spl[1]),
Integer.parseInt(spl[2]),
Integer.parseInt(spl[3]));
bData = Bukkit.createBlockData(spl[4]);
bData = Bukkit.createBlockData(spl[1]);
} catch (NumberFormatException e) {
error("Invalid block data: " + block);
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.data.DataHandler;
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.block.data.BlockData;
@ -41,7 +41,7 @@ public class ClientBuildManager extends Manager {
@Override
public void load() {
super.load();
Bukkit.getPluginManager().registerEvents(new ClientBuildCommand(), SR.getInstance());
Bukkit.getPluginManager().registerEvents(new ClientBuildCommand(), SR.getPlugin());
}
public List<ClientBuild> getBuilds() {
@ -83,7 +83,7 @@ public class ClientBuildManager extends Manager {
if (dh == null) {
error("Failed to get DataHandler instance, can't load client builds.");
error("Retrying in 10 seconds.");
Bukkit.getScheduler().runTaskLaterAsynchronously(SR.getInstance(), this::loadData, 200L);
Bukkit.getScheduler().runTaskLaterAsynchronously(SR.getPlugin(), this::loadData, 200L);
return;
}
List<String> keys = dh.getKeysAll("sr.clientbuild");
@ -130,7 +130,7 @@ public class ClientBuildManager extends Manager {
}
Bukkit.getScheduler()
.runTaskAsynchronously(
SR.getInstance(),
SR.getPlugin(),
() -> {
for (String name : names) {
ClientBuild build = getBuild(name);

View file

@ -6,8 +6,10 @@ import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import java.lang.reflect.Type;
import java.util.Map.Entry;
import me.unurled.sacredrealms.sr.utils.gson.LocationSerializer;
import org.bukkit.Location;
import org.bukkit.block.data.BlockData;
import org.jetbrains.annotations.NotNull;
public class ClientBuildSerializer implements JsonSerializer<ClientBuild> {
@ -27,19 +29,16 @@ public class ClientBuildSerializer implements JsonSerializer<ClientBuild> {
* @return a JsonElement corresponding to the specified object.
*/
@Override
public JsonElement serialize(ClientBuild src, Type typeOfSrc, JsonSerializationContext context) {
public JsonElement serialize(
@NotNull ClientBuild src, Type typeOfSrc, JsonSerializationContext context) {
StringBuilder s = new StringBuilder();
s.append(src.getName());
s.append(";");
LocationSerializer locSer = new LocationSerializer();
for (Entry<Location, BlockData> entry : src.getBlocks().entrySet()) {
s.append("{");
s.append(entry.getKey().getWorld().getName());
s.append("|");
s.append(entry.getKey().getBlockX());
s.append("|");
s.append(entry.getKey().getBlockY());
s.append("|");
s.append(entry.getKey().getBlockZ());
JsonElement j = locSer.serialize(entry.getKey(), Location.class, context);
s.append(j);
s.append("|");
s.append(entry.getValue().getAsString());
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.entity.EntityManager;
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.SRPlayer;
import me.unurled.sacredrealms.sr.managers.Manager;
import me.unurled.sacredrealms.sr.utils.Items;
import me.unurled.srcore.api.Manager;
import org.bukkit.Particle;
import org.bukkit.Sound;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Mob;
@ -23,6 +25,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityDamageByBlockEvent;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.inventory.EntityEquipment;
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 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
EntityEquipment equipment = mob.getEquipment();
Double dStrength = Items.getTotalAttribute(equipment, Attribute.STRENGTH);
@ -92,7 +98,7 @@ public class CombatManager extends Manager {
if (player1.getHealth() <= 0) {
player.damage(player.getHealth());
}
updateActionBar(player, player1);
updateActionBar(player);
}
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)
}
@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
public void onDamage(@NotNull EntityDamageByBlockEvent e) {
// TODO: Implement
@ -190,6 +204,16 @@ public class CombatManager extends Manager {
} else if (luck > 0 && luck < 1000 && RANDOM.nextBoolean()) {
// chance of critical hit
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 = damage * 2;
}
@ -201,17 +225,31 @@ public class CombatManager extends Manager {
EntityManager em = Manager.getInstance(EntityManager.class);
SREntity ent = em.getEntity(entity.getUniqueId());
if (ent != null) {
ent.setHealth(ent.getHealth() - damage);
}
if (entity.getHealth() <= 0) {
die(entity, d, pm, ent);
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);
// TODO: check for status effects (apply status effects depending item of damager)
}
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
SRPlayer player1 = pm.getPlayer(d.getUniqueId());
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.List;
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.ItemStackSerializer;
import me.unurled.sacredrealms.sr.components.player.PotionEffectDeserializer;
import me.unurled.sacredrealms.sr.data.DataHandler;
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.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Mob;
import org.bukkit.entity.Player;
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.inventory.ItemStack;
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) {
// save type
DataManager dm = Manager.getInstance(DataManager.class);
@ -100,8 +124,11 @@ public class EntityManager extends Manager {
entities.put(entity.getUuid(), entity);
}
public void addEntity(@NotNull Entity e) {
entities.put(e.getUniqueId(), new SREntity(e));
public void addEntity(@NotNull SREntityType type, @NotNull Entity e) {
entities.put(
e.getUniqueId(),
new SREntity(
e, type.getAttributes().get(Attribute.HEALTH), type.getExperience(), type.getId()));
}
public boolean isSREntity(@NotNull UUID uuid) {
@ -131,7 +158,8 @@ public class EntityManager extends Manager {
// spawn entity
List<SREntity> srEntities = new ArrayList<>();
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 (type.getHandItem() != null) {
mob.getEquipment().setItemInMainHand(type.getHandItem());
@ -143,7 +171,13 @@ public class EntityManager extends Manager {
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);
srEntities.add(srEntity);
}
@ -153,12 +187,19 @@ public class EntityManager extends Manager {
@EventHandler
public void onEntitySpawn(@NotNull EntitySpawnEvent e) {
if (e.getEntity() instanceof Player) return;
if (isSREntity(e.getEntity().getUniqueId())) return;
if (!(e.getEntity() instanceof Mob)) return;
if (e.getEntity().getEntitySpawnReason() != SpawnReason.CUSTOM
&& e.getEntity().getEntitySpawnReason() != SpawnReason.COMMAND) {
e.setCancelled(true);
}
}
/**
* cancel entity burn
*
* @param e
*/
@EventHandler
public void onEntityBurn(@NotNull EntityCombustEvent e) {
e.setCancelled(true);
}
}

View file

@ -1,16 +1,23 @@
package me.unurled.sacredrealms.sr.components.entity;
import static me.unurled.sacredrealms.sr.utils.Component.textComp;
import java.util.UUID;
import me.unurled.sacredrealms.sr.components.attributes.Attribute;
import org.bukkit.entity.Entity;
import org.jetbrains.annotations.NotNull;
public class SREntity {
private final UUID uuid;
private double health = 100;
private Long experience = 0L;
private final String typeId;
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();
this.health = health;
this.experience = exp;
this.typeId = typeId;
}
public UUID getUuid() {
@ -32,4 +39,23 @@ public class SREntity {
public void setHealth(double 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() {
return type = type == null ? EntityType.ZOMBIE : type;
return type == null ? EntityType.ZOMBIE : type;
}
public void setType(EntityType type) {
@ -144,7 +144,7 @@ public class SREntityType {
}
public ItemStack getItem() {
return item == null ? new ItemStack(Material.BARRIER) : item;
return item == null ? new ItemStack(Material.AIR) : item;
}
public void setItem(ItemStack item) {
@ -153,10 +153,10 @@ public class SREntityType {
public List<ItemStack> getArmor() {
if (armor.isEmpty()) {
armor.add(new ItemStack(Material.BARRIER));
armor.add(new ItemStack(Material.BARRIER));
armor.add(new ItemStack(Material.BARRIER));
armor.add(new ItemStack(Material.BARRIER));
armor.add(new ItemStack(Material.AIR));
armor.add(new ItemStack(Material.AIR));
armor.add(new ItemStack(Material.AIR));
armor.add(new ItemStack(Material.AIR));
}
return armor;
}
@ -167,7 +167,7 @@ public class SREntityType {
}
public ItemStack getHandItem() {
return handItem == null ? new ItemStack(Material.BARRIER) : handItem;
return handItem == null ? new ItemStack(Material.AIR) : handItem;
}
@SuppressWarnings("unused")
@ -176,7 +176,7 @@ public class SREntityType {
}
public ItemStack getSecondHandItem() {
return secondHandItem == null ? new ItemStack(Material.BARRIER) : secondHandItem;
return secondHandItem == null ? new ItemStack(Material.AIR) : secondHandItem;
}
@SuppressWarnings("unused")

View file

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

View file

@ -1,13 +1,14 @@
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.GsonBuilder;
import java.util.HashMap;
import java.util.List;
import me.unurled.sacredrealms.sr.SR;
import me.unurled.sacredrealms.sr.data.DataHandler;
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.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType;
@ -42,7 +43,7 @@ public class ItemManager extends Manager {
DataHandler dh = dm.getDataHandler();
if (dh == null) {
SR.getInstance().getLogger().severe("DataHandler is null in ItemManager.loadData()!");
error("DataHandler is null in ItemManager.loadData()!");
return;
}
@ -69,10 +70,12 @@ public class ItemManager extends Manager {
items.put(item.getId(), item);
}
@Nullable
public Item getItem(String id) {
return items.get(id);
}
@Nullable
public Item getItem(ItemStack item) {
if (item == 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.Logger.error;
import static me.unurled.sacredrealms.sr.utils.Logger.log;
import static me.unurled.sacredrealms.sr.utils.SRPlayerUtils.updateActionBar;
import com.destroystokyo.paper.event.player.PlayerArmorChangeEvent;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.net.URI;
import java.util.HashMap;
import java.util.UUID;
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.DataManager;
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.srcore.api.Manager;
import net.kyori.adventure.resource.ResourcePackInfo;
import net.kyori.adventure.resource.ResourcePackRequest;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
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.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerResourcePackStatusEvent.Status;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
@ -134,10 +140,36 @@ public class PlayerManager extends Manager {
BukkitTask task =
Bukkit.getScheduler()
.runTaskTimerAsynchronously(
SR.getInstance(), () -> updateActionBar(e.getPlayer()), 0, 20L);
SR.getPlugin(), () -> updateActionBar(e.getPlayer()), 0, 20L);
actionBarTasks.put(e.getPlayer().getUniqueId(), task);
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
@ -225,7 +257,7 @@ public class PlayerManager extends Manager {
public void levelUp(SRPlayer p, int previousLevel) {
PlayerLevelUpEvent event = new PlayerLevelUpEvent(p, previousLevel);
event.callEvent();
Bukkit.getScheduler().runTaskAsynchronously(SR.getPlugin(), event::callEvent);
Player player = Bukkit.getPlayer(p.getUuid());
if (player != null) {
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.item.Item;
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.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
@ -31,15 +31,15 @@ public class SRPlayer {
private static final List<Long> levelRequirements =
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 Long experience = 0L;
private double health = 100;
@Expose private Map<Attribute, Double> attributes = new EnumMap<>(Attribute.class);
private double health = -1;
private Map<Attribute, Map<ItemStack, Double>> itemAttributes = new EnumMap<>(Attribute.class);
@Expose private List<PotionEffect> potionEffects = new ArrayList<>();
@Expose private Inventory inventory;
@Expose private List<Integer> treasuresOpened = new ArrayList<>();
@Expose private Difficulty difficulty;
private boolean isClientBuilder = false;
private boolean firstTime = true;
@ -238,6 +238,9 @@ public class SRPlayer {
}
public double getHealth() {
if (health == -1) {
health = getAttribute(Attribute.HEALTH);
}
return health;
}
@ -257,6 +260,7 @@ public class SRPlayer {
public void setExperience(Long experience) {
// checks if experience is above next level requirements
if (difficulty == null) difficulty = Difficulty.NORMAL;
if (experience >= levelRequirements.get(level - 1) * difficulty.getXpMultiplier()) {
PlayerManager pm = Manager.getInstance(PlayerManager.class);
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.SRPlayer;
import me.unurled.sacredrealms.sr.managers.Manager;
import me.unurled.srcore.api.Manager;
import org.bukkit.GameMode;
import org.bukkit.Material;
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.util.Map;
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.World;
import org.bukkit.inventory.ItemStack;
public class TreasureDeserializer implements JsonDeserializer<Treasure> {
@ -42,34 +41,31 @@ public class TreasureDeserializer implements JsonDeserializer<Treasure> {
new GsonBuilder()
.registerTypeAdapter(ItemStack.class, new ItemStackDeserializer())
.create();
try {
Integer id = gson.fromJson("id", Integer.class);
String loc = gson.fromJson("location", String.class);
String[] parts = loc.split(",");
if (parts.length != 6) {
return null;
}
World world = Bukkit.getServer().getWorld(parts[0]);
double x = Double.parseDouble(parts[1]);
double y = Double.parseDouble(parts[2]);
double z = Double.parseDouble(parts[3]);
float pitch = Float.parseFloat(parts[4]);
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);
Integer id = json.getAsJsonObject().get("id").getAsInt();
Gson locGson =
new GsonBuilder()
.registerTypeAdapter(Location.class, new LocationSerializer())
.registerTypeAdapter(
new TypeToken<Map<Integer, ItemStack>>() {}.getType(),
new ItemStackMapSerializer())
.create();
Location location = locGson.fromJson(json.getAsJsonObject().get("location"), Location.class);
String permission = json.getAsJsonObject().get("permission").getAsString();
String items = json.getAsJsonObject().get("items").getAsString();
Type hash = new TypeToken<Map<Integer, ItemStack>>() {}.getType();
Map<Integer, ItemStack> item = gson.fromJson(items, hash);
if (permission == null || item == null) {
error("Error deserializing treasure: " + id + " is missing required fields");
return null;
}
return new Treasure(id, location, item, permission);
} catch (Exception e) {
error("Error deserializing treasure: " + e.getMessage());
}
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.Rarity;
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.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;

View file

@ -1,6 +1,8 @@
package me.unurled.sacredrealms.sr.components.treasure;
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.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.data.DataHandler;
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.Location;
import org.bukkit.Material;
@ -34,16 +36,20 @@ public class TreasureManager extends Manager {
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 */
@Override
public void saveData() {
// save all treasures
for (Treasure treasure : treasures.values()) {
// serialize 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));
saveTreasure(treasure);
}
}
@ -54,9 +60,15 @@ public class TreasureManager extends Manager {
DataHandler dh = Manager.getInstance(DataManager.class).getDataHandler();
Gson gson =
new GsonBuilder().registerTypeAdapter(Treasure.class, new TreasureDeserializer()).create();
log("Loading " + dh.getKeysAll("treasures").size() + " treasures");
for (String key : dh.getKeysAll("treasures")) {
// deserialize treasure
addTreasure(gson.fromJson(dh.get("treasures." + key), Treasure.class));
Treasure treasure = gson.fromJson(dh.get(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());
}
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() {
return nextId++;
}
@ -159,8 +180,17 @@ public class TreasureManager extends Manager {
if (sr == null) {
return;
}
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.playSound(p.getLocation(), Sound.BLOCK_CHEST_OPEN, 1f, 1f);
SRPlayer srPlayer = Manager.getInstance(PlayerManager.class).getPlayer(p.getUniqueId());
if (srPlayer != null) {
srPlayer.addTreasureOpened(treasure.getId());

View file

@ -7,9 +7,14 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
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 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.jetbrains.annotations.NotNull;
public class TreasureSerializer implements JsonSerializer<Treasure> {
@ -29,14 +34,21 @@ public class TreasureSerializer implements JsonSerializer<Treasure> {
* @return a JsonElement corresponding to the specified object.
*/
@Override
public JsonElement serialize(Treasure src, Type typeOfSrc, JsonSerializationContext context) {
public JsonElement serialize(
@NotNull Treasure src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject obj = new JsonObject();
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()));
Gson gson =
new GsonBuilder().registerTypeAdapter(ItemStack.class, new ItemStackSerializer()).create();
obj.add("items", new JsonPrimitive(gson.toJson(src.getItems())));
new GsonBuilder()
.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;
}
}

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;
import static me.unurled.sacredrealms.sr.utils.Logger.error;
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;
import me.unurled.srcore.api.Manager;
/** The data and config manager */
public class DataManager extends Manager {
private FileConfiguration config;
private DataHandler dh;
/** Load the manager */
@ -22,33 +14,6 @@ public class DataManager extends Manager {
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
*

View file

@ -4,7 +4,9 @@ import static me.unurled.sacredrealms.sr.utils.Logger.error;
import java.util.List;
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 redis.clients.jedis.JedisPooled;
@ -13,20 +15,25 @@ public class Redis implements DataHandler {
JedisPooled client;
public Redis() {
DataManager dm = Manager.getInstance(DataManager.class);
if (dm != null) {
String host = dm.getConfig().getString("redis.host", "127.0.0.1");
int port = dm.getConfig().getInt("redis.port", 6379);
ConfigManager cm = Manager.getInstance(ConfigManager.class);
if (cm != null) {
String host = Settings.REDIS_HOST.toString();
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 {
client = new JedisPooled(host, port);
client.get("test");
} catch (Exception e) {
error("Failed to connect to Redis, shutting down server.");
SR.getInstance().getServer().shutdown();
SR.getPlugin().getServer().shutdown();
}
} else {
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) {
ItemBuilder builder = new ItemBuilder(Material.RED_STAINED_GLASS_PANE);
builder
.setDisplayName("$7Previous Page")
.setDisplayName("§cPrevious Page")
.addLoreLines(
gui.hasPreviousPage()
? "§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.player.PlayerManager;
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.entity.Player;
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.player.PlayerManager;
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.entity.Player;
import org.bukkit.event.inventory.ClickType;
@ -18,7 +18,7 @@ import xyz.xenondevs.invui.window.Window;
public class DifficultyItem extends AbstractItem {
private Difficulty difficulty;
private final Difficulty difficulty;
public DifficultyItem(Difficulty difficulty) {
this.difficulty = difficulty;
@ -90,6 +90,8 @@ public class DifficultyItem extends AbstractItem {
SRPlayer sr = pm.getPlayer(player.getUniqueId());
if (sr != null) {
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;
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 org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
@ -14,17 +19,43 @@ import xyz.xenondevs.invui.window.Window;
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;
public EntityArmorItem(SREntityType type, int armorSlot) {
if (armorSlot == 4) {
public EntityArmorItem(@NotNull SREntityType type, int armorSlot) {
ARMOR.add(name(new ItemStack(Material.BARRIER), "Helmet"));
ARMOR.add(name(new ItemStack(Material.BARRIER), "Chestplate"));
ARMOR.add(name(new ItemStack(Material.BARRIER), "Leggings"));
ARMOR.add(name(new ItemStack(Material.BARRIER), "Boots"));
switch (armorSlot) {
case 4 -> {
if (type.getHandItem().getType().equals(Material.AIR)) {
stack = MAINHAND;
} else {
stack = type.getHandItem();
} else if (armorSlot == 5) {
}
}
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);
}
}
}
}
/**
* Gets the {@link ItemProvider}. This method gets called every time a {@link Window} is notified

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.gui.BackItem;
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.jetbrains.annotations.NotNull;
import xyz.xenondevs.invui.gui.Gui;
@ -48,13 +48,13 @@ public class EntityTypeGUI {
return Gui.normal()
.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
"# H C E B X M A #", // Helmet, Chestplate, lEgging, Boots, Main hand, second hAnd
"# # # # # # # # #")
.addIngredient('#', border)
.addIngredient('T', new EntityTypeItem(type))
.addIngredient('B', new EntityBehaviorItem(type))
.addIngredient('V', new EntityBehaviorItem(type))
.addIngredient('O', new EntityLootItem())
.addIngredient('I', new EntityItemDisplay(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;
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 java.util.Map;
import me.unurled.sacredrealms.sr.components.treasure.Treasure;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
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.impl.SimpleItem;
@ -22,36 +21,31 @@ public class TreasureGUI {
public static Gui createGui(@NotNull Treasure treasure) {
ItemStack itemStack = glassPane();
Item pane = new SimpleItem(itemStack);
Normal gui =
Gui.normal()
.setStructure(".........", "abcdefghi", "jklmnopqr", "stuvwxyz$", "...123...")
.addIngredient('.', pane);
if (!treasure.getItems().isEmpty()) {
for (int i = 0; i < treasure.getItems().size(); i++) {
Item item = new SimpleItem(treasure.getItems().get(i));
if (i == 28) {
gui.addIngredient('$', item);
} else {
gui.addIngredient((char) (i + 'a'), item);
}
Inventory inventory = new VirtualInventory(27);
inventory.setPreUpdateHandler(
(itemPreUpdateEvent) -> {
if (itemPreUpdateEvent.isAdd()
|| itemPreUpdateEvent.isRemove()
|| itemPreUpdateEvent.isSwap()) {
itemPreUpdateEvent.setCancelled(false);
}
});
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);
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();
return gui;
}
}

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;
import java.util.List;
import java.util.stream.Collectors;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.jetbrains.annotations.NotNull;
@ -29,4 +31,9 @@ public class Component {
}
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.SRPlayerUtils.syncSRToPlayer;
import com.google.gson.JsonElement;
import java.util.ArrayList;
import java.util.Arrays;
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.item.Item;
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.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.entity.Player;
import org.bukkit.inventory.EntityEquipment;
@ -68,21 +72,10 @@ public class Items {
ItemManager im = Manager.getInstance(ItemManager.class);
if (im == null) return 0.0;
if (item == null) return 0.0;
if (item.getType().equals(Material.AIR)) return 0.0;
PersistentDataContainer p = item.getItemMeta().getPersistentDataContainer();
if (p.has(ItemManager.ID, PersistentDataType.STRING)) {
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;
}
}
Item it = im.getItem(item);
if (it != null) return it.getAttribute(attribute);
return 0.0;
}
@ -171,4 +164,29 @@ public class Items {
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 java.util.List;
import java.util.Random;
import me.unurled.sacredrealms.sr.SR;
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.srcore.api.Manager;
import org.bukkit.attribute.AttributeInstance;
import org.bukkit.entity.Display;
import org.bukkit.entity.Entity;
@ -18,6 +21,8 @@ import org.jetbrains.annotations.NotNull;
public class SRPlayerUtils {
private static final Random RANDOM = new Random();
private SRPlayerUtils() {}
public static void syncPlayerToSR(@NotNull Player p, @NotNull SRPlayer sr) {
@ -58,7 +63,11 @@ public class SRPlayerUtils {
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 health = (int) sr.getHealth();
int mana = (int) sr.getAttribute(Attribute.MANA);
@ -80,11 +89,17 @@ public class SRPlayerUtils {
Vector spawnVector = location.add(facingVector.multiply(0.75));
// 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 =
eventEntity
.getWorld()
.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>-";
if (isHeal) prefix = "<green>+";
@ -114,6 +129,6 @@ public class SRPlayerUtils {
}
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:
host: "127.0.0.1"
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