tweaks724/src/main/java/eu/m724/tweaks/module/redstone/RedstoneModule.java
2025-01-24 10:05:49 +01:00

99 lines
3.6 KiB
Java

/*
* Copyright (C) 2025 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.module.redstone;
import eu.m724.tweaks.DebugLogger;
import eu.m724.tweaks.TweaksConfig;
import eu.m724.tweaks.module.TweaksModule;
import java.io.IOException;
import java.net.*;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
public class RedstoneModule extends TweaksModule {
private final RedstoneGateways redstoneGateways = new RedstoneGateways(getPlugin());
private DatagramSocket socket;
private RedstoneStateUpdateRunnable runnable;
@Override
protected void onInit() {
RedstoneStore.init(getPlugin());
var gatewayItem = new GatewayItem(getPlugin());
registerEvents(new RedstoneListener(redstoneGateways, gatewayItem));
registerCommand("retstone", new RedstoneCommands(gatewayItem));
this.runnable = new RedstoneStateUpdateRunnable(redstoneGateways);
this.runnable.runTaskTimer(getPlugin(), 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.finer("Update enqueued " + gatewayId + " " + power);
runnable.enqueueUpdate(gatewayId, power);
}
private void enqueueRetrieve(int gatewayId, Consumer<Byte> consumer) {
DebugLogger.finer("Retrieve enqueued " + gatewayId);
runnable.enqueueRetrieve(gatewayId, consumer);
}
}