mirror of
https://github.com/Shiewk/SModeration.git
synced 2026-04-28 05:54:16 +02:00
Add gzip-compressed saving and loading system
This commit is contained in:
@@ -8,24 +8,31 @@ import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static org.bukkit.Bukkit.getPluginManager;
|
||||
|
||||
public final class SModeration extends JavaPlugin {
|
||||
|
||||
public static final PunishmentContainer container = new PunishmentContainer();
|
||||
public static ComponentLogger LOGGER = null;
|
||||
public static SModeration PLUGIN = null;
|
||||
public static File SAVE_FILE = null;
|
||||
|
||||
public static final TextColor PRIMARY_COLOR = TextColor.color(212, 0, 255);
|
||||
public static final TextColor SECONDARY_COLOR = TextColor.color(52, 143, 255);
|
||||
public static final TextColor INACTIVE_COLOR = NamedTextColor.GRAY;
|
||||
public static final TextComponent CHAT_PREFIX = Component.text("SM \u00BB ").color(SECONDARY_COLOR);
|
||||
public static final TextComponent CHAT_PREFIX = Component.text("SM \u00BB ").color(PRIMARY_COLOR);
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
LOGGER = getComponentLogger();
|
||||
PLUGIN = this;
|
||||
SAVE_FILE = new File(this.getDataFolder().getAbsolutePath() + "/container.gz");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -67,5 +74,12 @@ public final class SModeration extends JavaPlugin {
|
||||
assert unban != null;
|
||||
unban.setExecutor(new UnbanCommand());
|
||||
unban.setTabCompleter(new UnbanCommand());
|
||||
|
||||
container.load(SAVE_FILE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
SModeration.container.save(SModeration.SAVE_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.world.WorldSaveEvent;
|
||||
|
||||
import static de.shiewk.smoderation.SModeration.CHAT_PREFIX;
|
||||
|
||||
@@ -59,4 +60,11 @@ public class PunishmentListener implements Listener {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onWorldSave(WorldSaveEvent event){
|
||||
if (event.getWorld().equals(Bukkit.getServer().getWorlds().get(0))){
|
||||
SModeration.container.save(SModeration.SAVE_FILE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,10 @@ import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.UUID;
|
||||
|
||||
import static de.shiewk.smoderation.SModeration.*;
|
||||
@@ -25,12 +28,41 @@ public class Punishment {
|
||||
private UUID undoneBy;
|
||||
|
||||
public Punishment(PunishmentType type, long time, long until, UUID by, UUID to, String reason) {
|
||||
this(type, time, until, by, to, reason, null);
|
||||
}
|
||||
|
||||
private Punishment(PunishmentType type, long time, long until, UUID by, UUID to, String reason, UUID undoneBy) {
|
||||
this.type = type;
|
||||
this.time = time;
|
||||
this.until = until;
|
||||
this.by = by;
|
||||
this.to = to;
|
||||
this.reason = reason;
|
||||
this.undoneBy = undoneBy;
|
||||
}
|
||||
|
||||
private static byte[] readStreamInternal(InputStream stream, int len) throws IOException {
|
||||
final byte[] bytes = stream.readNBytes(len);
|
||||
if (bytes.length != len){
|
||||
throw new EOFException("Stream has ended before enough bytes were read");
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static Punishment load(InputStream in) throws IOException {
|
||||
PunishmentType type = PunishmentType.values()[ByteUtil.bytesToInt(readStreamInternal(in, 4))];
|
||||
long time = ByteUtil.bytesToLong(readStreamInternal(in, 8));
|
||||
long until = ByteUtil.bytesToLong(readStreamInternal(in, 8));
|
||||
UUID by = ByteUtil.bytesToUuid(readStreamInternal(in, 16));
|
||||
UUID to = ByteUtil.bytesToUuid(readStreamInternal(in, 16));
|
||||
int reasonLen = ByteUtil.bytesToInt(readStreamInternal(in, 4));
|
||||
String reason = new String(readStreamInternal(in, reasonLen));
|
||||
UUID undoneBy = null;
|
||||
boolean undone = in.read() == 1;
|
||||
if (undone){
|
||||
undoneBy = ByteUtil.bytesToUuid(readStreamInternal(in, 16));
|
||||
}
|
||||
return new Punishment(type, time, until, by, to, reason, undoneBy);
|
||||
}
|
||||
|
||||
public boolean wasUndone(){
|
||||
@@ -66,21 +98,19 @@ public class Punishment {
|
||||
|
||||
private static final int BUFFER_LENGTH = 56;
|
||||
|
||||
public byte[] toBytes(){
|
||||
public void writeBytes(OutputStream stream) throws IOException {
|
||||
stream.write(ByteUtil.intToBytes(type.ordinal()));
|
||||
stream.write(ByteUtil.longToBytes(time));
|
||||
stream.write(ByteUtil.longToBytes(until));
|
||||
stream.write(ByteUtil.uuidToBytes(by));
|
||||
stream.write(ByteUtil.uuidToBytes(to));
|
||||
final byte[] reasonBytes = reason.getBytes();
|
||||
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_LENGTH + reasonBytes.length + (undoneBy != null ? 17 : 1));
|
||||
buffer.putInt(0, type.ordinal());
|
||||
buffer.putLong(4, time);
|
||||
buffer.putLong(12, until);
|
||||
buffer.put(20, ByteUtil.uuidToBytes(by));
|
||||
buffer.put(36, ByteUtil.uuidToBytes(to));
|
||||
buffer.putInt(40, reason.length());
|
||||
buffer.put(44, reasonBytes);
|
||||
buffer.put(44+reasonBytes.length, undoneBy != null ? (byte) 1 : (byte) 0);
|
||||
if (undoneBy != null){
|
||||
buffer.put(44+reasonBytes.length+1, ByteUtil.uuidToBytes(undoneBy));
|
||||
stream.write(ByteUtil.intToBytes(reasonBytes.length));
|
||||
stream.write(reasonBytes);
|
||||
stream.write(wasUndone() ? 1 : 0);
|
||||
if (wasUndone()){
|
||||
stream.write(ByteUtil.uuidToBytes(undoneBy));
|
||||
}
|
||||
return buffer.array();
|
||||
}
|
||||
|
||||
private Component undoMessage(){
|
||||
|
||||
@@ -1,17 +1,22 @@
|
||||
package de.shiewk.smoderation.storage;
|
||||
|
||||
import de.shiewk.smoderation.SModeration;
|
||||
import de.shiewk.smoderation.punishments.Punishment;
|
||||
import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
public class PunishmentContainer {
|
||||
|
||||
@@ -68,4 +73,54 @@ public class PunishmentContainer {
|
||||
public ArrayList<Punishment> copy() {
|
||||
return new ArrayList<>(punishments);
|
||||
}
|
||||
|
||||
public void load(File file){
|
||||
final ComponentLogger logger = SModeration.LOGGER;
|
||||
try {
|
||||
logger.info("Loading from {}", file.getPath());
|
||||
if (!file.isFile()){
|
||||
logger.warn("The file does not exist.");
|
||||
} else {
|
||||
try (FileInputStream fin = new FileInputStream(file)){
|
||||
GZIPInputStream gzin = new GZIPInputStream(fin);
|
||||
while (gzin.available() > 0){
|
||||
add(Punishment.load(gzin));
|
||||
}
|
||||
}
|
||||
logger.info("Successfully loaded {} items.", punishments.size());
|
||||
}
|
||||
} catch (EOFException e) {
|
||||
logger.error("The file was not correctly saved, {} items could be recovered!", this.punishments.size());
|
||||
} catch (IOException e){
|
||||
logger.error("An error occurred while loading: {}", e.toString());
|
||||
for (StackTraceElement stackTraceElement : e.getStackTrace()) {
|
||||
logger.error(stackTraceElement.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void save(File file) {
|
||||
final ComponentLogger logger = SModeration.LOGGER;
|
||||
try {
|
||||
logger.info("Saving to {}", file.getPath());
|
||||
if (!file.isFile()){
|
||||
file.mkdirs();
|
||||
file.delete();
|
||||
file.createNewFile();
|
||||
}
|
||||
try (FileOutputStream outputStream = new FileOutputStream(file)) {
|
||||
GZIPOutputStream gzout = new GZIPOutputStream(outputStream);
|
||||
for (Punishment punishment : copy()) {
|
||||
punishment.writeBytes(gzout);
|
||||
}
|
||||
gzout.close();
|
||||
}
|
||||
logger.info("Successfully saved.");
|
||||
} catch (IOException e){
|
||||
logger.error("An error occurred while saving: {}", e.toString());
|
||||
for (StackTraceElement stackTraceElement : e.getStackTrace()) {
|
||||
logger.error(stackTraceElement.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,4 +42,19 @@ public abstract class ByteUtil {
|
||||
long m = bytesToLong(new byte[]{ i[0], i[1], i[2], i[3], i[4], i[5], i[6], i[7] });
|
||||
return new UUID(m, l);
|
||||
}
|
||||
|
||||
public static int bytesToInt(byte[] bytes) {
|
||||
if (bytes.length != 4){
|
||||
throw new IllegalArgumentException("length must be 4");
|
||||
}
|
||||
ByteBuffer buffer = ByteBuffer.allocate(4);
|
||||
buffer.put(0, bytes);
|
||||
return buffer.getInt(0);
|
||||
}
|
||||
|
||||
public static byte[] intToBytes(int value) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(4);
|
||||
buffer.putInt(value);
|
||||
return buffer.array();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user