Rename to gateway, add crafting, some other changes
Some checks failed
/ build (push) Has been cancelled
Some checks failed
/ build (push) Has been cancelled
This commit is contained in:
parent
225adf0354
commit
c0b85870e0
12 changed files with 152 additions and 95 deletions
|
@ -82,7 +82,11 @@ Issue messages that the player needs to read to keep playing, and that make an a
|
||||||
`/emergencyalerts` (`tweaks724.emergencyalerts`)
|
`/emergencyalerts` (`tweaks724.emergencyalerts`)
|
||||||
|
|
||||||
### Remote redstone
|
### Remote redstone
|
||||||
Control redstone remotely
|
Adds a "gateway" item that are controlled over internet. \
|
||||||
|
[RETSTONE.md for more info](/Minecon724/tweaks724/src/branch/master/RETSTONE.md)
|
||||||
|
|
||||||
|
### Knockback
|
||||||
|
Control knockback dealt by entities
|
||||||
|
|
||||||
### Utility commands
|
### Utility commands
|
||||||
|
|
||||||
|
|
17
RETSTONE.md
17
RETSTONE.md
|
@ -3,8 +3,21 @@
|
||||||
See [retstone.py](retstone.py) for usage example
|
See [retstone.py](retstone.py) for usage example
|
||||||
|
|
||||||
### Glossary
|
### Glossary
|
||||||
repeaters - the blocks which allow to interact with redstone over internet \
|
gateways - the blocks (daylight detector) that read or emit redstone with a specified power, controlled with UDP packets \
|
||||||
packet - a bunch of bytes sent over the internet, that do something with a single repeater
|
packet - a bunch of bytes sent over the internet, that do something with a specified gateway
|
||||||
|
|
||||||
|
### Crafting
|
||||||
|
|
||||||
|
To craft a gateway, combine:
|
||||||
|
- nether star
|
||||||
|
- ender chest
|
||||||
|
- chorus flower
|
||||||
|
- daylight detector
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
Each gateway has an ID assigned. To view it, shift right-click a gateway.
|
||||||
|
|
||||||
|
To destroy a gateway, use silk touch.
|
||||||
|
|
||||||
### How it works
|
### How it works
|
||||||
A packet is int / 4 bytes / 32 bits
|
A packet is int / 4 bytes / 32 bits
|
||||||
|
|
50
src/main/java/eu/m724/tweaks/redstone/GatewayItem.java
Normal file
50
src/main/java/eu/m724/tweaks/redstone/GatewayItem.java
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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.Language;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.ShapelessRecipe;
|
||||||
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
public class GatewayItem {
|
||||||
|
private final NamespacedKey gatewayKey;
|
||||||
|
|
||||||
|
public GatewayItem(Plugin plugin) {
|
||||||
|
this.gatewayKey = new NamespacedKey(plugin, "gateway");
|
||||||
|
|
||||||
|
var recipe = new ShapelessRecipe(gatewayKey, itemStack());
|
||||||
|
recipe.addIngredient(Material.NETHER_STAR);
|
||||||
|
recipe.addIngredient(Material.ENDER_CHEST);
|
||||||
|
recipe.addIngredient(Material.CHORUS_FLOWER);
|
||||||
|
recipe.addIngredient(Material.DAYLIGHT_DETECTOR);
|
||||||
|
plugin.getServer().addRecipe(recipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStack itemStack() {
|
||||||
|
var itemStack = new ItemStack(Material.DAYLIGHT_DETECTOR);
|
||||||
|
var meta = itemStack.getItemMeta();
|
||||||
|
|
||||||
|
meta.setItemName(Language.getString("redstoneGatewayItem"));
|
||||||
|
meta.getPersistentDataContainer().set(gatewayKey, PersistentDataType.BOOLEAN, true);
|
||||||
|
meta.setEnchantmentGlintOverride(true);
|
||||||
|
|
||||||
|
itemStack.setItemMeta(meta);
|
||||||
|
return itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isGateway(ItemStack itemStack) {
|
||||||
|
var meta = itemStack.getItemMeta();
|
||||||
|
if (meta == null) return false;
|
||||||
|
var value = meta.getPersistentDataContainer().get(gatewayKey, PersistentDataType.BOOLEAN);
|
||||||
|
|
||||||
|
return value != null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,10 +14,10 @@ import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class RedstoneCommands implements CommandExecutor {
|
public class RedstoneCommands implements CommandExecutor {
|
||||||
private final RedstoneRepeaters redstoneRepeaters;
|
private final GatewayItem gatewayItem;
|
||||||
|
|
||||||
public RedstoneCommands(RedstoneRepeaters redstoneRepeaters) {
|
public RedstoneCommands(GatewayItem gatewayItem) {
|
||||||
this.redstoneRepeaters = redstoneRepeaters;
|
this.gatewayItem = gatewayItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,8 +41,9 @@ public class RedstoneCommands implements CommandExecutor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var itemStack = redstoneRepeaters.give();
|
var itemStack = gatewayItem.itemStack();
|
||||||
player.getInventory().addItem(itemStack);
|
player.getInventory().addItem(itemStack);
|
||||||
|
sender.sendMessage("Given to " + player.getName());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sender.sendMessage("Argument needed");
|
sender.sendMessage("Argument needed");
|
||||||
|
|
|
@ -9,53 +9,26 @@ package eu.m724.tweaks.redstone;
|
||||||
import com.google.common.collect.BiMap;
|
import com.google.common.collect.BiMap;
|
||||||
import com.google.common.collect.HashBiMap;
|
import com.google.common.collect.HashBiMap;
|
||||||
import eu.m724.tweaks.DebugLogger;
|
import eu.m724.tweaks.DebugLogger;
|
||||||
import eu.m724.tweaks.Language;
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.NamespacedKey;
|
|
||||||
import org.bukkit.Particle;
|
import org.bukkit.Particle;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.data.AnaloguePowerable;
|
import org.bukkit.block.data.AnaloguePowerable;
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.bukkit.metadata.FixedMetadataValue;
|
import org.bukkit.metadata.FixedMetadataValue;
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ThreadLocalRandom;
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
public class RedstoneRepeaters {
|
public class RedstoneGateways {
|
||||||
private final Plugin plugin;
|
private final Plugin plugin;
|
||||||
private final NamespacedKey repeaterKey;
|
|
||||||
|
|
||||||
private final BiMap<Integer, Location> repeatersById = HashBiMap.create();
|
private final BiMap<Integer, Location> gatewaysById = HashBiMap.create();
|
||||||
private final Map<Integer, Byte> repeatersByPower = new HashMap<>();
|
private final Map<Integer, Byte> gatewaysByPower = new HashMap<>();
|
||||||
|
|
||||||
public RedstoneRepeaters(Plugin plugin) {
|
public RedstoneGateways(Plugin plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.repeaterKey = new NamespacedKey(plugin, "repeater");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Item functions */
|
|
||||||
|
|
||||||
public ItemStack give() {
|
|
||||||
var itemStack = new ItemStack(Material.DAYLIGHT_DETECTOR);
|
|
||||||
var meta = itemStack.getItemMeta();
|
|
||||||
|
|
||||||
meta.setItemName(Language.getString("retstoneBlockItem"));
|
|
||||||
meta.getPersistentDataContainer().set(repeaterKey, PersistentDataType.BOOLEAN, true);
|
|
||||||
meta.setEnchantmentGlintOverride(true);
|
|
||||||
|
|
||||||
itemStack.setItemMeta(meta);
|
|
||||||
return itemStack;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRepeater(ItemStack itemStack) {
|
|
||||||
var meta = itemStack.getItemMeta();
|
|
||||||
if (meta == null) return false;
|
|
||||||
var value = meta.getPersistentDataContainer().get(repeaterKey, PersistentDataType.BOOLEAN);
|
|
||||||
return value != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Event */
|
/* Event */
|
||||||
|
@ -63,7 +36,7 @@ public class RedstoneRepeaters {
|
||||||
int onPlace(Block block) {
|
int onPlace(Block block) {
|
||||||
var repeaterId = ThreadLocalRandom.current().nextInt() & 0x7FFFFFF0;
|
var repeaterId = ThreadLocalRandom.current().nextInt() & 0x7FFFFFF0;
|
||||||
|
|
||||||
repeatersById.put(repeaterId, block.getLocation());
|
gatewaysById.put(repeaterId, block.getLocation());
|
||||||
block.setMetadata("rid", new FixedMetadataValue(plugin, repeaterId));
|
block.setMetadata("rid", new FixedMetadataValue(plugin, repeaterId));
|
||||||
|
|
||||||
RedstoneStore.getInstance().saveRepeaterData(block.getLocation(), repeaterId, (byte) 0);
|
RedstoneStore.getInstance().saveRepeaterData(block.getLocation(), repeaterId, (byte) 0);
|
||||||
|
@ -76,9 +49,9 @@ public class RedstoneRepeaters {
|
||||||
}
|
}
|
||||||
|
|
||||||
void delete(int repeaterId) {
|
void delete(int repeaterId) {
|
||||||
var location = repeatersById.remove(repeaterId);
|
var location = gatewaysById.remove(repeaterId);
|
||||||
if (location == null) return;
|
if (location == null) return;
|
||||||
repeatersByPower.remove(repeaterId);
|
gatewaysByPower.remove(repeaterId);
|
||||||
|
|
||||||
RedstoneStore.getInstance().deleteSavedRepeaterData(location);
|
RedstoneStore.getInstance().deleteSavedRepeaterData(location);
|
||||||
}
|
}
|
||||||
|
@ -88,7 +61,7 @@ public class RedstoneRepeaters {
|
||||||
private boolean isValid(int repeaterId) {
|
private boolean isValid(int repeaterId) {
|
||||||
// check if there's a repeater with such ID stored
|
// check if there's a repeater with such ID stored
|
||||||
// if not, we're not loading because it's loaded as the block is
|
// if not, we're not loading because it's loaded as the block is
|
||||||
var loc = repeatersById.get(repeaterId);
|
var loc = gatewaysById.get(repeaterId);
|
||||||
if (loc == null) {
|
if (loc == null) {
|
||||||
DebugLogger.fine("isValid: Delete because no loc");
|
DebugLogger.fine("isValid: Delete because no loc");
|
||||||
delete(repeaterId);
|
delete(repeaterId);
|
||||||
|
@ -124,7 +97,7 @@ public class RedstoneRepeaters {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
var id = repeatersById.inverse().get(block.getLocation());
|
var id = gatewaysById.inverse().get(block.getLocation());
|
||||||
|
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
// not in memory, check if repeater
|
// not in memory, check if repeater
|
||||||
|
@ -138,8 +111,8 @@ public class RedstoneRepeaters {
|
||||||
id = d.getKey();
|
id = d.getKey();
|
||||||
block.setMetadata("rid", new FixedMetadataValue(plugin, id));
|
block.setMetadata("rid", new FixedMetadataValue(plugin, id));
|
||||||
|
|
||||||
repeatersById.put(id, block.getLocation());
|
gatewaysById.put(id, block.getLocation());
|
||||||
repeatersByPower.put(id, d.getValue());
|
gatewaysByPower.put(id, d.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isValid(id)) return Integer.MIN_VALUE;
|
if (!isValid(id)) return Integer.MIN_VALUE;
|
||||||
|
@ -148,7 +121,7 @@ public class RedstoneRepeaters {
|
||||||
}
|
}
|
||||||
|
|
||||||
Block getBlock(int repeaterId) {
|
Block getBlock(int repeaterId) {
|
||||||
var location = repeatersById.get(repeaterId);
|
var location = gatewaysById.get(repeaterId);
|
||||||
if (location == null) return null;
|
if (location == null) return null;
|
||||||
|
|
||||||
if (!isValid(repeaterId)) return null;
|
if (!isValid(repeaterId)) return null;
|
||||||
|
@ -182,7 +155,7 @@ public class RedstoneRepeaters {
|
||||||
var block = getBlock(repeaterId);
|
var block = getBlock(repeaterId);
|
||||||
if (block == null) return -1;
|
if (block == null) return -1;
|
||||||
|
|
||||||
var power = repeatersByPower.getOrDefault(repeaterId, (byte) 0);
|
var power = gatewaysByPower.getOrDefault(repeaterId, (byte) 0);
|
||||||
DebugLogger.fine("Got " + repeaterId + " outputs " + power);
|
DebugLogger.fine("Got " + repeaterId + " outputs " + power);
|
||||||
return power;
|
return power;
|
||||||
}
|
}
|
||||||
|
@ -196,7 +169,7 @@ public class RedstoneRepeaters {
|
||||||
|
|
||||||
var data = (AnaloguePowerable) block.getBlockData();
|
var data = (AnaloguePowerable) block.getBlockData();
|
||||||
|
|
||||||
repeatersByPower.put(repeaterId, power);
|
gatewaysByPower.put(repeaterId, power);
|
||||||
data.setPower(power);
|
data.setPower(power);
|
||||||
|
|
||||||
block.getWorld().spawnParticle(Particle.LAVA, block.getLocation().add(0.5, 0.5, 0.5), 3);
|
block.getWorld().spawnParticle(Particle.LAVA, block.getLocation().add(0.5, 0.5, 0.5), 3);
|
|
@ -13,6 +13,7 @@ import net.md_5.bungee.api.chat.ClickEvent;
|
||||||
import net.md_5.bungee.api.chat.ComponentBuilder;
|
import net.md_5.bungee.api.chat.ComponentBuilder;
|
||||||
import net.md_5.bungee.api.chat.HoverEvent;
|
import net.md_5.bungee.api.chat.HoverEvent;
|
||||||
import net.md_5.bungee.api.chat.hover.content.Text;
|
import net.md_5.bungee.api.chat.hover.content.Text;
|
||||||
|
import org.bukkit.enchantments.Enchantment;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.block.Action;
|
import org.bukkit.event.block.Action;
|
||||||
|
@ -22,30 +23,37 @@ import org.bukkit.event.block.BlockRedstoneEvent;
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
|
||||||
public class RedstoneListener implements Listener {
|
public class RedstoneListener implements Listener {
|
||||||
private final RedstoneRepeaters redstoneRepeaters;
|
private final RedstoneGateways redstoneGateways;
|
||||||
|
private final GatewayItem gatewayItem;
|
||||||
|
|
||||||
public RedstoneListener(RedstoneRepeaters redstoneRepeaters) {
|
public RedstoneListener(RedstoneGateways redstoneGateways, GatewayItem gatewayItem) {
|
||||||
this.redstoneRepeaters = redstoneRepeaters;
|
this.redstoneGateways = redstoneGateways;
|
||||||
|
this.gatewayItem = gatewayItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onBlockPlace(BlockPlaceEvent event) {
|
public void onBlockPlace(BlockPlaceEvent event) {
|
||||||
if (!redstoneRepeaters.isRepeater(event.getItemInHand())) return;
|
if (!gatewayItem.isGateway(event.getItemInHand())) return;
|
||||||
|
|
||||||
var block = event.getBlockPlaced();
|
var block = event.getBlockPlaced();
|
||||||
var id = redstoneRepeaters.onPlace(block);
|
var id = redstoneGateways.onPlace(block);
|
||||||
|
|
||||||
DebugLogger.fine("Repeater placed: " + id);
|
DebugLogger.fine("Gateway placed: " + id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onBlockBreak(BlockBreakEvent event) {
|
public void onBlockBreak(BlockBreakEvent event) {
|
||||||
var id = redstoneRepeaters.getId(event.getBlock());
|
var id = redstoneGateways.getId(event.getBlock());
|
||||||
if (id == Integer.MIN_VALUE) return;
|
if (id == Integer.MIN_VALUE) return;
|
||||||
|
|
||||||
redstoneRepeaters.onBreak(id);
|
redstoneGateways.onBreak(id);
|
||||||
|
|
||||||
DebugLogger.fine("Repeater broken: " + id);
|
if (event.getPlayer().getInventory().getItemInMainHand().containsEnchantment(Enchantment.SILK_TOUCH)) {
|
||||||
|
event.setDropItems(false);
|
||||||
|
event.getBlock().getWorld().dropItemNaturally(event.getBlock().getLocation(), gatewayItem.itemStack());
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugLogger.fine("Gateway broken: " + id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
|
@ -53,28 +61,31 @@ public class RedstoneListener implements Listener {
|
||||||
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
|
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
|
||||||
if (!event.getPlayer().isSneaking()) return;
|
if (!event.getPlayer().isSneaking()) return;
|
||||||
|
|
||||||
var id = redstoneRepeaters.getId(event.getClickedBlock());
|
var id = redstoneGateways.getId(event.getClickedBlock());
|
||||||
if (id == Integer.MIN_VALUE) return;
|
if (id == Integer.MIN_VALUE) return;
|
||||||
|
|
||||||
// TODO find a less lame way of showing ID
|
// TODO find a less lame way of showing ID
|
||||||
var component = new ComponentBuilder("Repeater ID: ").color(ChatColor.GOLD)
|
var component = new ComponentBuilder("Gateway ID: ").color(ChatColor.GOLD)
|
||||||
.append(String.valueOf(id)).color(ChatColor.AQUA)
|
.append(String.valueOf(id)).color(ChatColor.AQUA)
|
||||||
.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(Language.getString("clickToCopy"))))
|
.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(Language.getString("clickToCopy"))))
|
||||||
.event(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, String.valueOf(id)))
|
.event(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, String.valueOf(id)))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
event.getPlayer().spigot().sendMessage(component);
|
event.getPlayer().spigot().sendMessage(component);
|
||||||
|
|
||||||
|
// cancel block place
|
||||||
|
event.setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onBlockRedstone(BlockRedstoneEvent event) {
|
public void onBlockRedstone(BlockRedstoneEvent event) {
|
||||||
var block = event.getBlock();
|
var block = event.getBlock();
|
||||||
|
|
||||||
var id = redstoneRepeaters.getId(block);
|
var id = redstoneGateways.getId(block);
|
||||||
if (id == Integer.MIN_VALUE) return;
|
if (id == Integer.MIN_VALUE) return;
|
||||||
|
|
||||||
event.setNewCurrent(redstoneRepeaters.getOutboundPower(id));
|
event.setNewCurrent(redstoneGateways.getOutboundPower(id));
|
||||||
|
|
||||||
DebugLogger.fine("Repeater redstone event: " + id);
|
DebugLogger.fine("Gateway redstone event: " + id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,23 +18,25 @@ import java.util.function.Consumer;
|
||||||
|
|
||||||
public class RedstoneManager {
|
public class RedstoneManager {
|
||||||
private final Plugin plugin;
|
private final Plugin plugin;
|
||||||
private final RedstoneRepeaters redstoneRepeaters;
|
private final RedstoneGateways redstoneGateways;
|
||||||
|
|
||||||
private DatagramSocket socket;
|
private DatagramSocket socket;
|
||||||
private RedstoneStateUpdateRunnable runnable;
|
private RedstoneStateUpdateRunnable runnable;
|
||||||
|
|
||||||
|
|
||||||
public RedstoneManager(Plugin plugin) {
|
public RedstoneManager(Plugin plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.redstoneRepeaters = new RedstoneRepeaters(plugin);
|
this.redstoneGateways = new RedstoneGateways(plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(PluginCommand command) {
|
public void init(PluginCommand command) {
|
||||||
RedstoneStore.init(plugin);
|
RedstoneStore.init(plugin);
|
||||||
|
var gatewayItem = new GatewayItem(plugin);
|
||||||
|
|
||||||
plugin.getServer().getPluginManager().registerEvents(new RedstoneListener(redstoneRepeaters), plugin);
|
plugin.getServer().getPluginManager().registerEvents(new RedstoneListener(redstoneGateways, gatewayItem), plugin);
|
||||||
command.setExecutor(new RedstoneCommands(redstoneRepeaters));
|
command.setExecutor(new RedstoneCommands(gatewayItem));
|
||||||
|
|
||||||
this.runnable = new RedstoneStateUpdateRunnable(redstoneRepeaters);
|
this.runnable = new RedstoneStateUpdateRunnable(redstoneGateways);
|
||||||
this.runnable.runTaskTimer(plugin, 0, 20); // TODO configurable
|
this.runnable.runTaskTimer(plugin, 0, 20); // TODO configurable
|
||||||
|
|
||||||
var listenAddress = TweaksConfig.getConfig().redstoneListen().split(":");
|
var listenAddress = TweaksConfig.getConfig().redstoneListen().split(":");
|
||||||
|
@ -50,6 +52,7 @@ public class RedstoneManager {
|
||||||
} catch (SocketException e) {
|
} catch (SocketException e) {
|
||||||
throw new RuntimeException("Starting socket", e);
|
throw new RuntimeException("Starting socket", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initSocket(SocketAddress bindAddress) throws SocketException {
|
private void initSocket(SocketAddress bindAddress) throws SocketException {
|
||||||
|
@ -70,15 +73,15 @@ public class RedstoneManager {
|
||||||
|
|
||||||
boolean write = (buf[0] >> 7 & 1) == 1;
|
boolean write = (buf[0] >> 7 & 1) == 1;
|
||||||
byte data = (byte) (buf[3] & 0xF);
|
byte data = (byte) (buf[3] & 0xF);
|
||||||
int repeaterId = ((buf[0] & 0x7F) << 24) | ((buf[1] & 0xFF) << 16) | ((buf[2] & 0xFF) << 8) | (buf[3] & 0xF0);
|
int gatewayId = ((buf[0] & 0x7F) << 24) | ((buf[1] & 0xFF) << 16) | ((buf[2] & 0xFF) << 8) | (buf[3] & 0xF0);
|
||||||
|
|
||||||
if (write) {
|
if (write) {
|
||||||
enqueueUpdate(repeaterId, data);
|
enqueueUpdate(gatewayId, data);
|
||||||
} else {
|
} else {
|
||||||
var newPacket = new DatagramPacket(new byte[1], 1, packet.getSocketAddress());
|
var newPacket = new DatagramPacket(new byte[1], 1, packet.getSocketAddress());
|
||||||
|
|
||||||
enqueueRetrieve(repeaterId, value -> {
|
enqueueRetrieve(gatewayId, value -> {
|
||||||
DebugLogger.fine("Retrieved for " + repeaterId + " power " + value);
|
DebugLogger.fine("Retrieved for " + gatewayId + " power " + value);
|
||||||
newPacket.setData(new byte[] { (byte) Math.max(value, 0) });
|
newPacket.setData(new byte[] { (byte) Math.max(value, 0) });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -92,13 +95,13 @@ public class RedstoneManager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enqueueUpdate(int repeaterId, byte power) {
|
private void enqueueUpdate(int gatewayId, byte power) {
|
||||||
DebugLogger.fine("Update enqueued " + repeaterId + " " + power);
|
DebugLogger.fine("Update enqueued " + gatewayId + " " + power);
|
||||||
runnable.enqueueUpdate(repeaterId, power);
|
runnable.enqueueUpdate(gatewayId, power);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enqueueRetrieve(int repeaterId, Consumer<Byte> consumer) {
|
private void enqueueRetrieve(int gatewayId, Consumer<Byte> consumer) {
|
||||||
DebugLogger.fine("Retrieve enqueued " + repeaterId);
|
DebugLogger.fine("Retrieve enqueued " + gatewayId);
|
||||||
runnable.enqueueRetrieve(repeaterId, consumer);
|
runnable.enqueueRetrieve(gatewayId, consumer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,14 +16,14 @@ public class RedstoneStateUpdateRunnable extends BukkitRunnable {
|
||||||
private Map<Integer, Byte> updateQueue = new HashMap<>();
|
private Map<Integer, Byte> updateQueue = new HashMap<>();
|
||||||
private Map<Integer, Consumer<Byte>> retrieveQueue = new HashMap<>();
|
private Map<Integer, Consumer<Byte>> retrieveQueue = new HashMap<>();
|
||||||
|
|
||||||
private final RedstoneRepeaters redstoneRepeaters;
|
private final RedstoneGateways redstoneGateways;
|
||||||
|
|
||||||
RedstoneStateUpdateRunnable(RedstoneRepeaters redstoneRepeaters) {
|
RedstoneStateUpdateRunnable(RedstoneGateways redstoneGateways) {
|
||||||
this.redstoneRepeaters = redstoneRepeaters;
|
this.redstoneGateways = redstoneGateways;
|
||||||
}
|
}
|
||||||
|
|
||||||
void enqueueUpdate(int repeaterId, byte power) {
|
void enqueueUpdate(int gatewayId, byte power) {
|
||||||
updateQueue.put(repeaterId, power);
|
updateQueue.put(gatewayId, power);
|
||||||
}
|
}
|
||||||
|
|
||||||
void enqueueRetrieve(int repeaterId, Consumer<Byte> consumer) {
|
void enqueueRetrieve(int repeaterId, Consumer<Byte> consumer) {
|
||||||
|
@ -38,7 +38,7 @@ public class RedstoneStateUpdateRunnable extends BukkitRunnable {
|
||||||
var retrieveQueue = this.retrieveQueue;
|
var retrieveQueue = this.retrieveQueue;
|
||||||
this.retrieveQueue = new HashMap<>();
|
this.retrieveQueue = new HashMap<>();
|
||||||
|
|
||||||
updateQueue.forEach((key, value) -> redstoneRepeaters.setPower(key, value));
|
updateQueue.forEach((key, value) -> redstoneGateways.setPower(key, value));
|
||||||
retrieveQueue.forEach((key, value) -> value.accept(redstoneRepeaters.getInboundPower(key)));
|
retrieveQueue.forEach((key, value) -> value.accept(redstoneGateways.getInboundPower(key)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,9 @@ import java.nio.file.Files;
|
||||||
public class RedstoneStore {
|
public class RedstoneStore {
|
||||||
private static RedstoneStore INSTANCE;
|
private static RedstoneStore INSTANCE;
|
||||||
|
|
||||||
private final Plugin plugin;
|
|
||||||
private final File directory;
|
private final File directory;
|
||||||
|
|
||||||
private RedstoneStore(Plugin plugin) {
|
private RedstoneStore(Plugin plugin) {
|
||||||
this.plugin = plugin;
|
|
||||||
this.directory = new File(plugin.getDataFolder(), "storage/redstone");
|
this.directory = new File(plugin.getDataFolder(), "storage/redstone");
|
||||||
directory.mkdirs();
|
directory.mkdirs();
|
||||||
}
|
}
|
||||||
|
@ -46,20 +44,20 @@ public class RedstoneStore {
|
||||||
// TODO read just 4 bytes
|
// TODO read just 4 bytes
|
||||||
bytes = Files.readAllBytes(file.toPath());
|
bytes = Files.readAllBytes(file.toPath());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("Loading saved repeater data", e);
|
throw new RuntimeException("Loading saved gateway data", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
var repeaterId = Ints.fromByteArray(bytes) & ~0xF;
|
var gatewayId = Ints.fromByteArray(bytes) & ~0xF;
|
||||||
var powerLevel = (byte) (bytes[3] & 0xF);
|
var powerLevel = (byte) (bytes[3] & 0xF);
|
||||||
|
|
||||||
DebugLogger.fine("load " + location + " " + repeaterId + " " + powerLevel);
|
DebugLogger.fine("load " + location + " " + gatewayId + " " + powerLevel);
|
||||||
|
|
||||||
return Pair.of(repeaterId, powerLevel);
|
return Pair.of(gatewayId, powerLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveRepeaterData(Location location, int repeaterId, byte powerLevel) {
|
void saveRepeaterData(Location location, int gatewayId, byte powerLevel) {
|
||||||
var file = getFile(location);
|
var file = getFile(location);
|
||||||
byte[] bytes = Ints.toByteArray((repeaterId & ~0xF) | (powerLevel & 0xF));
|
byte[] bytes = Ints.toByteArray((gatewayId & ~0xF) | (powerLevel & 0xF));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Files.write(file.toPath(), bytes);
|
Files.write(file.toPath(), bytes);
|
||||||
|
@ -67,7 +65,7 @@ public class RedstoneStore {
|
||||||
throw new RuntimeException("Saving repeater data", e);
|
throw new RuntimeException("Saving repeater data", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugLogger.fine("save " + location + " " + repeaterId + " " + powerLevel);
|
DebugLogger.fine("save " + location + " " + gatewayId + " " + powerLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void deleteSavedRepeaterData(Location location) {
|
void deleteSavedRepeaterData(Location location) {
|
||||||
|
|
|
@ -103,7 +103,7 @@ auth:
|
||||||
# The domain of the server. Doesn't do anything other than showing in /tauth new
|
# The domain of the server. Doesn't do anything other than showing in /tauth new
|
||||||
domain: "replace.me"
|
domain: "replace.me"
|
||||||
|
|
||||||
# Adds blocks which allow to interact with redstone over internet
|
# Adds gateways emitting redstone, controlled over internet
|
||||||
retstone:
|
retstone:
|
||||||
enabled: true
|
enabled: true
|
||||||
# This takes host:port, listens on UDP
|
# This takes host:port, listens on UDP
|
||||||
|
|
|
@ -35,6 +35,8 @@ commands:
|
||||||
description: Send emergency alert
|
description: Send emergency alert
|
||||||
permission: tweaks724.emergencyalert
|
permission: tweaks724.emergencyalert
|
||||||
retstone:
|
retstone:
|
||||||
|
description: Retstone commands
|
||||||
|
permission: tweaks724.retstone
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
tweaks724:
|
tweaks724:
|
||||||
|
@ -50,4 +52,6 @@ permissions:
|
||||||
default: op
|
default: op
|
||||||
emergencyalert:
|
emergencyalert:
|
||||||
default: op
|
default: op
|
||||||
|
retstone:
|
||||||
|
default: op
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,6 @@ authKickWrongKey = You're connecting to the wrong server address. You must conne
|
||||||
# If force is enabled and player is not registered. Changing this reveals you're using this plugin
|
# If force is enabled and player is not registered. Changing this reveals you're using this plugin
|
||||||
authKickUnregistered = You are not whitelisted on this server!
|
authKickUnregistered = You are not whitelisted on this server!
|
||||||
|
|
||||||
retstoneBlockItem = Online redstone block
|
redstoneGatewayItem = Redstone gateway
|
||||||
|
|
||||||
clickToCopy = Click to copy to clipboard
|
clickToCopy = Click to copy to clipboard
|
Loading…
Reference in a new issue