107 lines
3.8 KiB
Java
107 lines
3.8 KiB
Java
/*
|
|
* Copyright (C) 2024 Minecon724
|
|
* Tweaks724 is licensed under the GNU General Public License. See the LICENSE.md file
|
|
* in the project root for the full license text.
|
|
*/
|
|
|
|
package eu.m724.tweaks.redstone;
|
|
|
|
import eu.m724.tweaks.DebugLogger;
|
|
import eu.m724.tweaks.TweaksConfig;
|
|
import org.bukkit.command.PluginCommand;
|
|
import org.bukkit.plugin.Plugin;
|
|
|
|
import java.io.IOException;
|
|
import java.net.*;
|
|
import java.util.concurrent.Executors;
|
|
import java.util.function.Consumer;
|
|
|
|
public class RedstoneManager {
|
|
private final Plugin plugin;
|
|
private final RedstoneGateways redstoneGateways;
|
|
|
|
private DatagramSocket socket;
|
|
private RedstoneStateUpdateRunnable runnable;
|
|
|
|
|
|
public RedstoneManager(Plugin plugin) {
|
|
this.plugin = plugin;
|
|
this.redstoneGateways = new RedstoneGateways(plugin);
|
|
}
|
|
|
|
public void init(PluginCommand command) {
|
|
RedstoneStore.init(plugin);
|
|
var gatewayItem = new GatewayItem(plugin);
|
|
|
|
plugin.getServer().getPluginManager().registerEvents(new RedstoneListener(redstoneGateways, gatewayItem), plugin);
|
|
command.setExecutor(new RedstoneCommands(gatewayItem));
|
|
|
|
this.runnable = new RedstoneStateUpdateRunnable(redstoneGateways);
|
|
this.runnable.runTaskTimer(plugin, 0, 20); // TODO configurable
|
|
|
|
var listenAddress = TweaksConfig.getConfig().redstoneListen().split(":");
|
|
InetSocketAddress bindAddress;
|
|
if (listenAddress.length == 1) {
|
|
bindAddress = new InetSocketAddress(Integer.parseInt(listenAddress[0]));
|
|
} else {
|
|
bindAddress = new InetSocketAddress(listenAddress[0], Integer.parseInt(listenAddress[1]));
|
|
}
|
|
|
|
try {
|
|
initSocket(bindAddress);
|
|
} catch (SocketException e) {
|
|
throw new RuntimeException("Starting socket", e);
|
|
}
|
|
|
|
}
|
|
|
|
private void initSocket(SocketAddress bindAddress) throws SocketException {
|
|
socket = new DatagramSocket(bindAddress);
|
|
|
|
Executors.newSingleThreadExecutor().execute(() -> {
|
|
byte[] buf = new byte[4];
|
|
|
|
while (!socket.isClosed()) {
|
|
DatagramPacket packet
|
|
= new DatagramPacket(buf, buf.length);
|
|
try {
|
|
socket.receive(packet);
|
|
} catch (IOException e) {
|
|
DebugLogger.severe("Error reading packet: " + e.getMessage());
|
|
continue;
|
|
}
|
|
|
|
boolean write = (buf[0] >> 7 & 1) == 1;
|
|
byte data = (byte) (buf[3] & 0xF);
|
|
int gatewayId = ((buf[0] & 0x7F) << 24) | ((buf[1] & 0xFF) << 16) | ((buf[2] & 0xFF) << 8) | (buf[3] & 0xF0);
|
|
|
|
if (write) {
|
|
enqueueUpdate(gatewayId, data);
|
|
} else {
|
|
var newPacket = new DatagramPacket(new byte[1], 1, packet.getSocketAddress());
|
|
|
|
enqueueRetrieve(gatewayId, value -> {
|
|
DebugLogger.fine("Retrieved for " + gatewayId + " power " + value);
|
|
newPacket.setData(new byte[] { (byte) Math.max(value, 0) });
|
|
|
|
try {
|
|
socket.send(newPacket);
|
|
} catch (IOException e) {
|
|
throw new RuntimeException("Sending response to get repeater value", e);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
private void enqueueUpdate(int gatewayId, byte power) {
|
|
DebugLogger.fine("Update enqueued " + gatewayId + " " + power);
|
|
runnable.enqueueUpdate(gatewayId, power);
|
|
}
|
|
|
|
private void enqueueRetrieve(int gatewayId, Consumer<Byte> consumer) {
|
|
DebugLogger.fine("Retrieve enqueued " + gatewayId);
|
|
runnable.enqueueRetrieve(gatewayId, consumer);
|
|
}
|
|
}
|