From 22e9cfdd4069f15d04228eae81892205d4d5a7d9 Mon Sep 17 00:00:00 2001 From: Govindas Date: Wed, 25 Nov 2020 17:01:11 +0200 Subject: [PATCH] Add cross-server variable editing (I'll make it use {} instead of strings later) --- .../rediskript/managers/RedisManager.java | 92 ++++++++++++++++--- .../rediskript/skript/SkriptHook.java | 8 +- .../skript/elements/EffSendMessage.java | 36 +------- .../elements/EffSetVariableInChannel.java | 5 - .../elements/ExprVariableInChannel.java | 68 ++++++++++++++ 5 files changed, 153 insertions(+), 56 deletions(-) delete mode 100644 src/main/java/net/limework/rediskript/skript/elements/EffSetVariableInChannel.java create mode 100644 src/main/java/net/limework/rediskript/skript/elements/ExprVariableInChannel.java diff --git a/src/main/java/net/limework/rediskript/managers/RedisManager.java b/src/main/java/net/limework/rediskript/managers/RedisManager.java index 794481a..e1f700c 100644 --- a/src/main/java/net/limework/rediskript/managers/RedisManager.java +++ b/src/main/java/net/limework/rediskript/managers/RedisManager.java @@ -1,5 +1,7 @@ package net.limework.rediskript.managers; +import ch.njol.skript.registrations.Classes; +import ch.njol.skript.variables.Variables; import net.limework.rediskript.RediSkript; import net.limework.rediskript.events.RedisMessageEvent; import net.limework.rediskript.data.Encryption; @@ -13,9 +15,11 @@ import redis.clients.jedis.BinaryJedis; import redis.clients.jedis.BinaryJedisPubSub; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; +import redis.clients.jedis.exceptions.JedisConnectionException; import javax.crypto.IllegalBlockSizeException; import java.nio.charset.StandardCharsets; +import java.util.Base64; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -98,6 +102,9 @@ public class RedisManager extends BinaryJedisPubSub implements Runnable { } catch (Exception e) { + if (isShuttingDown.get() || !plugin.isEnabled()) { + return; + } plugin.getLogger().warning(ChatColor.translateAlternateColorCodes('&', "&cConnection to redis has failed! &cReconnecting...")); if (this.subscribeJedis != null) { this.subscribeJedis.close(); @@ -128,23 +135,40 @@ public class RedisManager extends BinaryJedisPubSub implements Runnable { //encryption is disabled, so let's just get the string receivedMessage = new String(message, StandardCharsets.UTF_8); } - if (receivedMessage != null) { JSONObject j = new JSONObject(receivedMessage); - //System.out.println("Message got from channel: "+channel +" and the Message: " +json.toString()); - JSONArray messages = j.getJSONArray("Messages"); - RedisMessageEvent event; - for (int i = 0 ; i < messages.length(); i++) { + if (j.get("Type").equals("Skript")) { + JSONArray messages = j.getJSONArray("Messages"); + RedisMessageEvent event; + for (int i = 0; i < messages.length(); i++) { + event = new RedisMessageEvent(channelString, messages.get(i).toString(), j.getLong("Date")); + //if plugin is disabling, don't call events anymore + if (plugin.isEnabled()) { + RedisMessageEvent finalEvent = event; + Bukkit.getScheduler().runTask(plugin, () -> plugin.getServer().getPluginManager().callEvent(finalEvent)); + } + } + } else if (j.get("Type").equals("SkriptVariables")) { + JSONArray variableNames = j.getJSONArray("Names"); + boolean delete = false; + Object inputValue = null; + if (j.isNull("Value")) { + delete = true; + } else { + String input = j.getString("Value"); + String [] inputs = input.split("\\^", 2); + inputValue = Classes.deserialize(inputs[0], Base64.getDecoder().decode(inputs[1])); - System.out.println(messages.get(i).toString()); - event = new RedisMessageEvent(channelString, messages.get(i).toString(), j.getLong("Date")); - if (plugin.isEnabled()) { - RedisMessageEvent finalEvent = event; - Bukkit.getScheduler().runTask(plugin, () -> plugin.getServer().getPluginManager().callEvent(finalEvent)); + + } + for (int i = 0; i < variableNames.length(); i++) { + if (delete) { + Variables.setVariable(variableNames.get(i).toString(), null, null, false); + } else { + Variables.setVariable(variableNames.get(i).toString(), inputValue, null, false); + } } } - - //if plugin is disabling, don't call events anymore } } catch (Exception e) { e.printStackTrace(); @@ -153,6 +177,50 @@ public class RedisManager extends BinaryJedisPubSub implements Runnable { } } + public void sendMessage(String[] message, String channel) { + JSONObject json = new JSONObject(); + json.put("Messages", new JSONArray(message)); + json.put("Type", "Skript"); + json.put("Date", System.currentTimeMillis()); //for unique string every time & PING calculations + finishSendMessage(json, channel); + } + public void sendVariables(String[] variableNames, String variableValue, String channel) { + JSONObject json = new JSONObject(); + json.put("Names", new JSONArray(variableNames)); + json.put("Value", variableValue); + json.put("Type", "SkriptVariables"); + json.put("Date", System.currentTimeMillis()); //for unique string every time & PING calculations + finishSendMessage(json, channel); + } + + public void finishSendMessage(JSONObject json, String channel) { + try { + byte[] message; + if (this.getEncryption().isEncryptionEnabled()) { + message = this.getEncryption().encrypt(json.toString()); + } else { + message = json.toString().getBytes(StandardCharsets.UTF_8); + } + //execute sending of redis message on the main thread if plugin is disabling + //so it can still process the sending + + //sending a redis message blocks main thread if there's no more connections available + //so to avoid issues, it's best to do it always on separate thread + if (plugin.isEnabled()) { + this.getRedisService().execute(() -> { + BinaryJedis j = this.getJedisPool().getResource(); + j.publish(channel.getBytes(StandardCharsets.UTF_8), message); + j.close(); + }); + } else { + BinaryJedis j = this.getJedisPool().getResource(); + j.publish(channel.getBytes(StandardCharsets.UTF_8), message); + j.close(); + } + } catch (JedisConnectionException exception) { + exception.printStackTrace(); + } + } public void shutdown() { this.isShuttingDown.set(true); diff --git a/src/main/java/net/limework/rediskript/skript/SkriptHook.java b/src/main/java/net/limework/rediskript/skript/SkriptHook.java index 5f54935..7613bf2 100644 --- a/src/main/java/net/limework/rediskript/skript/SkriptHook.java +++ b/src/main/java/net/limework/rediskript/skript/SkriptHook.java @@ -6,12 +6,10 @@ import ch.njol.skript.lang.ExpressionType; import ch.njol.skript.registrations.EventValues; import ch.njol.skript.util.Date; import ch.njol.skript.util.Getter; +import ch.njol.skript.util.Timespan; import net.limework.rediskript.RediSkript; import net.limework.rediskript.events.RedisMessageEvent; -import net.limework.rediskript.skript.elements.EvtRedis; -import net.limework.rediskript.skript.elements.ExprChannel; -import net.limework.rediskript.skript.elements.ExprMessage; -import net.limework.rediskript.skript.elements.ExprMessageDate; +import net.limework.rediskript.skript.elements.*; import java.io.IOException; @@ -21,6 +19,8 @@ public class SkriptHook { try { addon.loadClasses("net.limework.rediskript.skript", "elements"); Skript.registerEvent("redis message", EvtRedis.class, RedisMessageEvent.class, "redis message"); + Skript.registerExpression(ExprVariableInChannel.class, Object.class, ExpressionType.PROPERTY, "variable %strings% in [redis] channel %string%"); + Skript.registerExpression(ExprChannel.class, String.class, ExpressionType.SIMPLE, "redis channel"); EventValues.registerEventValue(RedisMessageEvent.class, String.class, new Getter() { @Override diff --git a/src/main/java/net/limework/rediskript/skript/elements/EffSendMessage.java b/src/main/java/net/limework/rediskript/skript/elements/EffSendMessage.java index d823052..45a3968 100644 --- a/src/main/java/net/limework/rediskript/skript/elements/EffSendMessage.java +++ b/src/main/java/net/limework/rediskript/skript/elements/EffSendMessage.java @@ -34,7 +34,6 @@ public class EffSendMessage extends Effect { String[] message = this.message.getAll(event); String channel = this.channel.getSingle(event); - if (message[0] == null) { Bukkit.getLogger().warning(ChatColor.translateAlternateColorCodes('&', "&2[&aRediSkript&a] &cRedis message was empty. Please check your code.")); return; @@ -43,40 +42,7 @@ public class EffSendMessage extends Effect { Bukkit.getLogger().warning(ChatColor.translateAlternateColorCodes('&', "&2[&aRediSkript&a] &cChannel was empty. Please check your code.")); return; } - assert plugin != null; - JSONObject json = new JSONObject(); - json.put("Messages", new JSONArray(message)); - json.put("Type", "Skript"); - json.put("Date", System.currentTimeMillis()); //for unique string every time & PING calculations - byte[] msg; - RedisManager manager = plugin.getRm(); - if (manager.getEncryption().isEncryptionEnabled()) { - msg = manager.getEncryption().encrypt(json.toString()); - } else { - msg = json.toString().getBytes(StandardCharsets.UTF_8); - } - try { - - //execute sending of redis message on the main thread if plugin is disabling - //so it can still process the sending - - //sending a redis message blocks main thread if there's no more connections available - //so to avoid issues, it's best to do it always on separate thread - if (plugin.isEnabled()) { - manager.getRedisService().execute(() -> { - BinaryJedis j = manager.getJedisPool().getResource(); - j.publish(channel.getBytes(StandardCharsets.UTF_8), msg); - j.close(); - }); - } else { - BinaryJedis j = manager.getJedisPool().getResource(); - j.publish(channel.getBytes(StandardCharsets.UTF_8), msg); - j.close(); - } - } catch (JedisConnectionException exception) { - exception.printStackTrace(); - } - + plugin.getRm().sendMessage(message, channel); } @Override diff --git a/src/main/java/net/limework/rediskript/skript/elements/EffSetVariableInChannel.java b/src/main/java/net/limework/rediskript/skript/elements/EffSetVariableInChannel.java deleted file mode 100644 index 65a70b5..0000000 --- a/src/main/java/net/limework/rediskript/skript/elements/EffSetVariableInChannel.java +++ /dev/null @@ -1,5 +0,0 @@ -package net.limework.rediskript.skript.elements; - -public class EffSetVariableInChannel { - -} diff --git a/src/main/java/net/limework/rediskript/skript/elements/ExprVariableInChannel.java b/src/main/java/net/limework/rediskript/skript/elements/ExprVariableInChannel.java new file mode 100644 index 0000000..0e9ea02 --- /dev/null +++ b/src/main/java/net/limework/rediskript/skript/elements/ExprVariableInChannel.java @@ -0,0 +1,68 @@ +package net.limework.rediskript.skript.elements; + +import ch.njol.skript.classes.Changer; +import ch.njol.skript.lang.*; +import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.skript.registrations.Classes; +import ch.njol.skript.variables.SerializedVariable; +import ch.njol.skript.variables.Variables; +import ch.njol.util.Kleenean; +import ch.njol.util.coll.CollectionUtils; +import net.limework.rediskript.RediSkript; +import org.bukkit.Bukkit; +import org.bukkit.event.Event; + +import java.util.Base64; + +public class ExprVariableInChannel extends SimpleExpression { + private Expression name; + private Expression channel; + @Override + public boolean init(Expression[] expressions, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parser) { + name = (Expression) expressions[0]; + channel = (Expression) expressions[1]; + return true; + + } + + @Override + protected Object[] get(Event event) { + return null; + } + + @Override + public boolean isSingle() { + return false; + } + + @Override + public Class getReturnType() { + return Object.class; + } + + @Override + public String toString(Event event, boolean b) { + return null; + } + @Override + public void change(Event e, Object[] changer, Changer.ChangeMode mode) { + RediSkript plugin = (RediSkript) Bukkit.getPluginManager().getPlugin("RediSkript"); + switch (mode) { + case SET: + SerializedVariable.Value serialized = Classes.serialize(changer[0]); + String encoded = Base64.getEncoder().encodeToString(serialized.data); + encoded = serialized.type + "^" + encoded; + plugin.getRm().sendVariables(name.getAll(e), encoded, channel.getSingle(e)); + break; + case DELETE: + plugin.getRm().sendVariables(name.getAll(e), null, channel.getSingle(e)); + break; + } + } + @Override + public Class[] acceptChange(Changer.ChangeMode mode) { + if (mode == Changer.ChangeMode.DELETE || mode == Changer.ChangeMode.SET) + return CollectionUtils.array(Object.class); + return null; + } +} \ No newline at end of file