mirror of
https://github.com/Freezy-Studios/BlazeSMP.git
synced 2025-04-22 13:44:06 +02:00
Add JSON storage support for clans, homes, and protected blocks
- Implemented the **Clan** class to load, reload, and save clan data (including chunk locations and ownership) using Gson and the Paper API. - Added the **Homes** class to manage player home locations, converting JSON-stored coordinates into Bukkit `Location` objects. - Created **ProtectedBlocks** and **ProtectedBlock** classes to handle protected block data (owner, key, and block location) from JSON.
This commit is contained in:
parent
e7fc7f199f
commit
d724d64334
12 changed files with 500 additions and 6 deletions
|
@ -4,6 +4,10 @@ import org.bukkit.plugin.java.JavaPlugin;
|
|||
|
||||
public final class BlazeSMP extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
// Plugin startup logic
|
||||
|
|
|
@ -1,5 +1,212 @@
|
|||
package me.freezy.plugins.papermc.blazesmp.module;
|
||||
|
||||
public class Clan {
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Getter
|
||||
public class Clan {
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||
private static final String STORAGE_PATH = "plugins/BlazeSMP/storage/clans/";
|
||||
private static final Logger LOGGER = Logger.getLogger("Clan");
|
||||
|
||||
private final UUID uuid;
|
||||
@Setter private String name;
|
||||
@Setter private Component tag;
|
||||
@Setter private UUID leaderUUID;
|
||||
@Setter private UUID viceUUID;
|
||||
private final LinkedList<UUID> members;
|
||||
private final LinkedList<Chunk> chunks;
|
||||
private final LinkedHashMap<Chunk, UUID> chunkOwnerMap;
|
||||
private int chunkAmount;
|
||||
|
||||
public Clan(String name, Component tag, UUID leaderUUID) {
|
||||
this.uuid = UUID.randomUUID();
|
||||
this.name = name;
|
||||
this.tag = tag;
|
||||
this.leaderUUID = leaderUUID;
|
||||
this.viceUUID = null;
|
||||
this.members = new LinkedList<>();
|
||||
this.chunks = new LinkedList<>();
|
||||
this.chunkOwnerMap = new LinkedHashMap<>();
|
||||
this.chunkAmount = 0;
|
||||
}
|
||||
|
||||
public Clan(UUID clanUUID, String name, Component tag, UUID leaderUUID, UUID viceUUID,
|
||||
LinkedList<UUID> members, LinkedList<Chunk> chunks, LinkedHashMap<Chunk, UUID> chunkOwnerMap) {
|
||||
this.uuid = clanUUID;
|
||||
this.name = name;
|
||||
this.tag = tag;
|
||||
this.leaderUUID = leaderUUID;
|
||||
this.viceUUID = viceUUID;
|
||||
this.members = members;
|
||||
this.chunks = chunks;
|
||||
this.chunkOwnerMap = chunkOwnerMap;
|
||||
this.chunkAmount = chunks.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a Clan from the JSON file corresponding to the given UUID.
|
||||
*
|
||||
* @param uuid The UUID of the clan.
|
||||
* @return The loaded Clan or null if the file does not exist.
|
||||
*/
|
||||
public static Clan load(UUID uuid) {
|
||||
File file = new File(STORAGE_PATH + uuid + ".json");
|
||||
if (!file.exists()) {
|
||||
LOGGER.warning("Clan file " + file.getAbsolutePath() + " does not exist.");
|
||||
return null;
|
||||
}
|
||||
try (FileReader reader = new FileReader(file)) {
|
||||
ClanJson jsonClan = GSON.fromJson(reader, ClanJson.class);
|
||||
if (jsonClan == null) {
|
||||
LOGGER.warning("Failed to parse clan JSON for UUID " + uuid);
|
||||
return null;
|
||||
}
|
||||
Component tagComponent = MiniMessage.miniMessage().deserialize(jsonClan.tag);
|
||||
UUID leader = (jsonClan.leader == null || jsonClan.leader.isEmpty()) ? null : UUID.fromString(jsonClan.leader);
|
||||
UUID vice = (jsonClan.vize == null || jsonClan.vize.isEmpty()) ? null : UUID.fromString(jsonClan.vize);
|
||||
|
||||
// Convert members
|
||||
LinkedList<UUID> memberUUIDs = new LinkedList<>();
|
||||
if (jsonClan.members != null) {
|
||||
for (String s : jsonClan.members) {
|
||||
if (s != null && !s.isEmpty()) {
|
||||
memberUUIDs.add(UUID.fromString(s));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process chunks with world information
|
||||
LinkedList<Chunk> chunkList = new LinkedList<>();
|
||||
LinkedHashMap<Chunk, UUID> chunkOwnerMap = new LinkedHashMap<>();
|
||||
if (jsonClan.chunks != null && jsonClan.chunks.locations != null) {
|
||||
for (LocationJson loc : jsonClan.chunks.locations) {
|
||||
World world = Bukkit.getWorld(loc.world);
|
||||
if (world == null) {
|
||||
LOGGER.warning("World '" + loc.world + "' not found. Skipping chunk at " + loc.x + ", " + loc.z);
|
||||
continue;
|
||||
}
|
||||
int x = Integer.parseInt(loc.x);
|
||||
int z = Integer.parseInt(loc.z);
|
||||
Chunk chunk = world.getChunkAt(x, z);
|
||||
chunkList.add(chunk);
|
||||
UUID ownerUUID = (loc.owner == null || loc.owner.isEmpty()) ? null : UUID.fromString(loc.owner);
|
||||
chunkOwnerMap.put(chunk, ownerUUID);
|
||||
}
|
||||
}
|
||||
|
||||
Clan clan = new Clan(uuid, jsonClan.name, tagComponent, leader, vice, memberUUIDs, chunkList, chunkOwnerMap);
|
||||
clan.chunkAmount = (jsonClan.chunks != null) ? jsonClan.chunks.amount : chunkList.size();
|
||||
return clan;
|
||||
} catch (IOException e) {
|
||||
LOGGER.severe("Error loading clan: " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads the clan from its corresponding JSON file.
|
||||
*/
|
||||
public void reload() {
|
||||
Clan loaded = load(this.uuid);
|
||||
if (loaded == null) {
|
||||
LOGGER.warning("Failed to reload clan with UUID: " + this.uuid);
|
||||
return;
|
||||
}
|
||||
this.name = loaded.name;
|
||||
this.tag = loaded.tag;
|
||||
this.leaderUUID = loaded.leaderUUID;
|
||||
this.viceUUID = loaded.viceUUID;
|
||||
this.members.clear();
|
||||
this.members.addAll(loaded.members);
|
||||
this.chunks.clear();
|
||||
this.chunks.addAll(loaded.chunks);
|
||||
this.chunkOwnerMap.clear();
|
||||
this.chunkOwnerMap.putAll(loaded.chunkOwnerMap);
|
||||
this.chunkAmount = loaded.chunkAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the clan data to its corresponding JSON file.
|
||||
*/
|
||||
public void save() {
|
||||
ClanJson jsonClan = new ClanJson();
|
||||
jsonClan.name = this.name;
|
||||
jsonClan.tag = MiniMessage.miniMessage().serialize(this.tag);
|
||||
jsonClan.leader = (this.leaderUUID == null) ? "" : this.leaderUUID.toString();
|
||||
jsonClan.vize = (this.viceUUID == null) ? "" : this.viceUUID.toString();
|
||||
jsonClan.members = this.members.stream().map(UUID::toString).toList();
|
||||
|
||||
// Prepare chunks JSON
|
||||
jsonClan.chunks = new ChunksJson();
|
||||
jsonClan.chunks.amount = this.chunkAmount;
|
||||
jsonClan.chunks.locations = new LinkedList<>();
|
||||
for (Chunk chunk : this.chunks) {
|
||||
LocationJson loc = new LocationJson();
|
||||
// Assuming the owner mapping may be null
|
||||
UUID owner = this.chunkOwnerMap.getOrDefault(chunk, null);
|
||||
loc.owner = (owner == null) ? "" : owner.toString();
|
||||
// Store world name along with chunk coordinates
|
||||
loc.world = chunk.getWorld().getName();
|
||||
loc.x = String.valueOf(chunk.getX());
|
||||
loc.z = String.valueOf(chunk.getZ());
|
||||
jsonClan.chunks.locations.add(loc);
|
||||
}
|
||||
|
||||
// Ensure directory exists
|
||||
File dir = new File(STORAGE_PATH);
|
||||
if (!dir.exists()) {
|
||||
if (dir.mkdirs()) {
|
||||
LOGGER.info("Successfully created folder structure!");
|
||||
} else {
|
||||
LOGGER.severe("Failed to create folder structure!");
|
||||
}
|
||||
}
|
||||
File file = new File(dir, this.uuid + ".json");
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
GSON.toJson(jsonClan, writer);
|
||||
} catch (IOException e) {
|
||||
LOGGER.severe("Error saving clan: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Helper classes to represent the JSON structure
|
||||
|
||||
private static class ClanJson {
|
||||
String name;
|
||||
String tag;
|
||||
String leader;
|
||||
String vize;
|
||||
List<String> members;
|
||||
ChunksJson chunks;
|
||||
}
|
||||
|
||||
private static class ChunksJson {
|
||||
int amount;
|
||||
List<LocationJson> locations;
|
||||
}
|
||||
|
||||
private static class LocationJson {
|
||||
String owner;
|
||||
String world;
|
||||
String x;
|
||||
String z;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package me.freezy.plugins.papermc.blazesmp.module;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Represents a protected block with an owner, a key, and a location.
|
||||
*/
|
||||
public record ProtectedBlock(UUID owner, UUID key, Location location) {}
|
|
@ -0,0 +1,124 @@
|
|||
package me.freezy.plugins.papermc.blazesmp.module.manager;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class Homes {
|
||||
private static final String FILE_PATH = "plugins/BlazeSMP/storage/homes.json";
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||
private static final Logger LOGGER = Logger.getLogger("Homes");
|
||||
|
||||
// Mapping of player UUID to their home location
|
||||
@Getter private final LinkedHashMap<UUID, Location> homes;
|
||||
|
||||
public Homes() {
|
||||
this.homes = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads homes from the JSON file.
|
||||
*/
|
||||
public void load() {
|
||||
File file = new File(FILE_PATH);
|
||||
if (!file.exists()) {
|
||||
LOGGER.info("Homes file does not exist, a new one will be created upon saving.");
|
||||
return;
|
||||
}
|
||||
try (FileReader reader = new FileReader(file)) {
|
||||
// Use a TypeToken to handle the Map<String, LocationJson> structure
|
||||
Type type = new TypeToken<Map<String, LocationJson>>() {}.getType();
|
||||
Map<String, LocationJson> jsonMap = GSON.fromJson(reader, type);
|
||||
if (jsonMap == null) {
|
||||
return;
|
||||
}
|
||||
for (Map.Entry<String, LocationJson> entry : jsonMap.entrySet()) {
|
||||
UUID uuid;
|
||||
try {
|
||||
uuid = UUID.fromString(entry.getKey());
|
||||
} catch (IllegalArgumentException ex) {
|
||||
LOGGER.warning("Invalid UUID key in homes file: " + entry.getKey());
|
||||
continue;
|
||||
}
|
||||
LocationJson locJson = entry.getValue();
|
||||
// Assume the default world "world" for homes
|
||||
World world = Bukkit.getWorld("world");
|
||||
if (world == null) {
|
||||
LOGGER.warning("Default world 'world' not found. Skipping home for " + uuid);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
double x = Double.parseDouble(locJson.x);
|
||||
double y = Double.parseDouble(locJson.y);
|
||||
double z = Double.parseDouble(locJson.z);
|
||||
float yaw = Float.parseFloat(locJson.yaw);
|
||||
float pitch = Float.parseFloat(locJson.pitch);
|
||||
Location location = new Location(world, x, y, z, yaw, pitch);
|
||||
homes.put(uuid, location);
|
||||
} catch (NumberFormatException ex) {
|
||||
LOGGER.warning("Invalid number format for home of " + uuid + ": " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOGGER.severe("Error loading homes: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the homes mapping to the JSON file.
|
||||
*/
|
||||
public void save() {
|
||||
// Convert the homes map to a map of String keys (UUIDs) to LocationJson objects.
|
||||
Map<String, LocationJson> jsonMap = new LinkedHashMap<>();
|
||||
for (Map.Entry<UUID, Location> entry : homes.entrySet()) {
|
||||
Location location = entry.getValue();
|
||||
LocationJson locJson = new LocationJson();
|
||||
locJson.x = String.valueOf(location.getX());
|
||||
locJson.y = String.valueOf(location.getY());
|
||||
locJson.z = String.valueOf(location.getZ());
|
||||
locJson.yaw = String.valueOf(location.getYaw());
|
||||
locJson.pitch = String.valueOf(location.getPitch());
|
||||
jsonMap.put(entry.getKey().toString(), locJson);
|
||||
}
|
||||
File file = new File(FILE_PATH);
|
||||
// Ensure the parent directory exists
|
||||
File parent = file.getParentFile();
|
||||
if (parent != null && !parent.exists()) {
|
||||
if (parent.mkdirs()) {
|
||||
LOGGER.info("Successfully created folder structure!");
|
||||
} else {
|
||||
LOGGER.severe("Failed to create folder structure!");
|
||||
}
|
||||
}
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
GSON.toJson(jsonMap, writer);
|
||||
} catch (IOException e) {
|
||||
LOGGER.severe("Error saving homes: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inner class representing the JSON structure for a location.
|
||||
*/
|
||||
private static class LocationJson {
|
||||
String x;
|
||||
String y;
|
||||
String z;
|
||||
String yaw;
|
||||
String pitch;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
package me.freezy.plugins.papermc.blazesmp.module.manager;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import me.freezy.plugins.papermc.blazesmp.module.ProtectedBlock;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Manager class for loading and saving protected blocks.
|
||||
*/
|
||||
public class ProtectedBlocks {
|
||||
private static final String FILE_PATH = "plugins/BlazeSMP/storage/protected_blocks.json";
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||
private static final Logger LOGGER = Logger.getLogger("ProtectedBlocks");
|
||||
|
||||
// List of protected blocks
|
||||
private final List<ProtectedBlock> blocks;
|
||||
|
||||
public ProtectedBlocks() {
|
||||
this.blocks = new ArrayList<>();
|
||||
}
|
||||
|
||||
public List<ProtectedBlock> getBlocks() {
|
||||
return blocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads protected blocks from the JSON file.
|
||||
*/
|
||||
public void load() {
|
||||
File file = new File(FILE_PATH);
|
||||
if (!file.exists()) {
|
||||
LOGGER.info("Protected blocks file does not exist, a new one will be created upon saving.");
|
||||
return;
|
||||
}
|
||||
try (FileReader reader = new FileReader(file)) {
|
||||
// Deserialize the JSON into a ProtectedBlocksJson object
|
||||
ProtectedBlocksJson jsonData = GSON.fromJson(reader, ProtectedBlocksJson.class);
|
||||
if (jsonData == null || jsonData.blocks == null) {
|
||||
return;
|
||||
}
|
||||
blocks.clear();
|
||||
for (BlockJson blockJson : jsonData.blocks) {
|
||||
try {
|
||||
UUID owner = (blockJson.owner == null || blockJson.owner.isEmpty())
|
||||
? null : UUID.fromString(blockJson.owner);
|
||||
UUID key = (blockJson.key == null || blockJson.key.isEmpty())
|
||||
? null : UUID.fromString(blockJson.key);
|
||||
|
||||
// Use default world "world" since no world field is provided
|
||||
World world = Bukkit.getWorld("world");
|
||||
if (world == null) {
|
||||
LOGGER.warning("Default world 'world' not found. Skipping block for owner: " + blockJson.owner);
|
||||
continue;
|
||||
}
|
||||
double x = Double.parseDouble(blockJson.location.x);
|
||||
double y = Double.parseDouble(blockJson.location.y);
|
||||
double z = Double.parseDouble(blockJson.location.z);
|
||||
Location location = new Location(world, x, y, z);
|
||||
blocks.add(new ProtectedBlock(owner, key, location));
|
||||
} catch (Exception e) {
|
||||
LOGGER.warning("Error loading a protected block: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOGGER.severe("Error loading protected blocks: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the protected blocks to the JSON file.
|
||||
*/
|
||||
public void save() {
|
||||
ProtectedBlocksJson jsonData = new ProtectedBlocksJson();
|
||||
jsonData.blocks = new ArrayList<>();
|
||||
for (ProtectedBlock block : blocks) {
|
||||
BlockJson blockJson = new BlockJson();
|
||||
blockJson.owner = (block.owner() == null) ? "" : block.owner().toString();
|
||||
blockJson.key = (block.key() == null) ? "" : block.key().toString();
|
||||
blockJson.location = new LocationJson();
|
||||
blockJson.location.x = String.valueOf(block.location().getX());
|
||||
blockJson.location.y = String.valueOf(block.location().getY());
|
||||
blockJson.location.z = String.valueOf(block.location().getZ());
|
||||
jsonData.blocks.add(blockJson);
|
||||
}
|
||||
File file = new File(FILE_PATH);
|
||||
File parent = file.getParentFile();
|
||||
if (parent != null && !parent.exists()) {
|
||||
if (parent.mkdirs()) {
|
||||
LOGGER.info("Successfully created folder structure!");
|
||||
} else {
|
||||
LOGGER.severe("Failed to create folder structure!");
|
||||
} }
|
||||
try (FileWriter writer = new FileWriter(file)) {
|
||||
GSON.toJson(jsonData, writer);
|
||||
} catch (IOException e) {
|
||||
LOGGER.severe("Error saving protected blocks: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Inner classes to match the JSON structure
|
||||
|
||||
private static class ProtectedBlocksJson {
|
||||
List<BlockJson> blocks;
|
||||
}
|
||||
|
||||
private static class BlockJson {
|
||||
String owner;
|
||||
String key;
|
||||
LocationJson location;
|
||||
}
|
||||
|
||||
private static class LocationJson {
|
||||
String x;
|
||||
String y;
|
||||
String z;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue