Initial commit: RefinedStorage2 Hytale plugin
- NetworkManager (BFS cable propagation) - BlockInteractionHandler (UseBlock/PlaceBlock/BreakBlock) - NetworkTickHandler (periodic ~1s tick) - UIManager + GridUI/ControllerUI/DiskDriveUI (CustomUIPage stubs) - 24 Items + 14 Blocks with JSON definitions, textures, models - Builds with ScaffoldIt
This commit is contained in:
parent
ff8dfd3668
commit
ba84350a01
25 changed files with 693 additions and 39 deletions
|
|
@ -5,25 +5,23 @@ type: chore
|
|||
phase: 1
|
||||
priority: critical
|
||||
created: 2026-04-30
|
||||
status: open
|
||||
updated: 2026-04-30
|
||||
status: blocked
|
||||
---
|
||||
|
||||
## Beschreibung
|
||||
Build läuft lassen und im Hytale Dev Server testen.
|
||||
|
||||
## Tasks
|
||||
- `./gradlew build` erfolgreich durchführen
|
||||
- Hytale Dev Server mit dem Plugin starten
|
||||
- Blöcke und Items ingame testen
|
||||
- Logs prüfen auf Fehler
|
||||
|
||||
## Voraussetzungen
|
||||
- JDK 25 (in `gradle.properties` definiert)
|
||||
- Hytale Dev Server installiert (`hytale-test-server/`?)
|
||||
|
||||
## Betroffene Dateien
|
||||
- `build.gradle.kts`, `gradle.properties`, `settings.gradle.kts`
|
||||
|
||||
## Abhängigkeiten
|
||||
- Issue #001
|
||||
## Progress
|
||||
- ✅ `./gradlew build` erfolgreich — 655ms, sauber
|
||||
- ✅ Plugin lädt in Dev Server: `RefinedStoragePlugin === RefinedStorage2 loaded successfully ===`
|
||||
- ✅ 28 Items/Blocks aus JSONs registriert
|
||||
- ✅ 82 Common Assets geladen, 56 I18n Einträge
|
||||
- ✅ 16 Warnings "Unused key: Id" gefixt
|
||||
- ⏳ **BLOCKED**: Assets.zip enthält nur Custom-Modelle (55 entries), keine Hytale Game Assets
|
||||
- Server crashed: Missing Environment/DamageCause/Entity Assets
|
||||
- `setupServer` erstellt keine Game-Assets, nur Custom-Modelle
|
||||
- Hytale Game Client/Assets müssen separat beschafft werden
|
||||
|
||||
## Braucht
|
||||
- Hytale Game Client oder Asset-Download für DevServer
|
||||
|
|
|
|||
1
.sdkmanrc
Normal file
1
.sdkmanrc
Normal file
|
|
@ -0,0 +1 @@
|
|||
java=25.0.3-tem
|
||||
|
|
@ -1,21 +1,27 @@
|
|||
package dev.refinedstorage;
|
||||
|
||||
import com.hypixel.hytale.common.plugin.PluginManifest;
|
||||
import com.hypixel.hytale.common.semver.Semver;
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.server.core.plugin.JavaPlugin;
|
||||
import com.hypixel.hytale.server.core.plugin.JavaPluginInit;
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import dev.refinedstorage.handler.BlockInteractionHandler;
|
||||
import dev.refinedstorage.handler.NetworkTickHandler;
|
||||
import dev.refinedstorage.network.NetworkManager;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* RefinedStorage2 — Hytale port of Refined Storage 2.
|
||||
* RefinedStorage2 — networked storage system for Hytale.
|
||||
* <p>
|
||||
* A networked storage system for Hytale.
|
||||
* Blocks and items are defined as JSON assets in resources/Server/Item/Items/
|
||||
* and automatically loaded by the game. This plugin only registers
|
||||
* custom interactions, network logic, and server-side behaviors.
|
||||
* Blocks and items are defined as JSON in resources/Server/Item|Block/.
|
||||
* This plugin adds server-side interaction events, network management (BFS),
|
||||
and periodic tick maintenance.
|
||||
*/
|
||||
public class RefinedStoragePlugin extends JavaPlugin {
|
||||
|
||||
private NetworkTickHandler tickHandler;
|
||||
|
||||
public RefinedStoragePlugin(@Nonnull JavaPluginInit init) {
|
||||
super(init);
|
||||
}
|
||||
|
|
@ -23,7 +29,31 @@ public class RefinedStoragePlugin extends JavaPlugin {
|
|||
@Override
|
||||
protected void setup() {
|
||||
HytaleLogger logger = HytaleLogger.forEnclosingClass();
|
||||
logger.atInfo().log("=== RefinedStorage2 loaded successfully ===");
|
||||
logger.atInfo().log("Assets: 15 blocks + 13 items loaded from resource JSONs");
|
||||
PluginManifest manifest = getManifest();
|
||||
|
||||
logger.atInfo().log("=== RefinedStorage2 loading ===");
|
||||
logger.atInfo().log("Name: {} Group: {}",
|
||||
manifest.getName(), manifest.getGroup());
|
||||
|
||||
// Initialize core systems
|
||||
NetworkManager.getInstance();
|
||||
|
||||
// Register block event handlers
|
||||
new BlockInteractionHandler(this);
|
||||
|
||||
// Start network tick
|
||||
tickHandler = new NetworkTickHandler();
|
||||
tickHandler.start(this);
|
||||
|
||||
logger.atInfo().log("=== RefinedStorage2 loaded ===");
|
||||
logger.atInfo().log("Place Controller to create a network, Cables to extend it");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutdown() {
|
||||
if (tickHandler != null) {
|
||||
tickHandler.stop();
|
||||
}
|
||||
HytaleLogger.forEnclosingClass().atInfo().log("RefinedStorage2 shutdown");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,145 @@
|
|||
package dev.refinedstorage.handler;
|
||||
|
||||
import com.hypixel.hytale.event.EventPriority;
|
||||
import com.hypixel.hytale.event.EventRegistry;
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.math.vector.Vector3i;
|
||||
import com.hypixel.hytale.server.core.event.events.ecs.BreakBlockEvent;
|
||||
import com.hypixel.hytale.server.core.event.events.ecs.PlaceBlockEvent;
|
||||
import com.hypixel.hytale.server.core.event.events.ecs.UseBlockEvent;
|
||||
import com.hypixel.hytale.server.core.plugin.PluginBase;
|
||||
import dev.refinedstorage.network.NetworkManager;
|
||||
|
||||
/**
|
||||
* Handles block interactions for RefinedStorage blocks:
|
||||
* right-click (UseBlockEvent), place (PlaceBlockEvent), break (BreakBlockEvent).
|
||||
*/
|
||||
public final class BlockInteractionHandler {
|
||||
|
||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||
private final NetworkManager networkManager;
|
||||
|
||||
private static final String CONTROLLER = "controller";
|
||||
private static final String CABLE = "cable";
|
||||
private static final String GRID = "grid";
|
||||
private static final String DISK_DRIVE = "diskdrive";
|
||||
private static final String IMPORTER = "importer";
|
||||
private static final String EXPORTER = "exporter";
|
||||
private static final String INTERFACE_BLOCK = "interface";
|
||||
private static final String CRAFTING_GRID = "craftinggrid";
|
||||
private static final String AUTOCRAFTER = "autocrafter";
|
||||
|
||||
private static final java.util.Set<String> RS_BLOCKS = java.util.Set.of(
|
||||
CONTROLLER, CABLE, GRID, DISK_DRIVE, IMPORTER, EXPORTER, INTERFACE_BLOCK,
|
||||
CRAFTING_GRID, AUTOCRAFTER
|
||||
);
|
||||
|
||||
private static final java.util.Set<String> RS_MACHINES = java.util.Set.of(
|
||||
GRID, DISK_DRIVE, IMPORTER, EXPORTER, INTERFACE_BLOCK,
|
||||
CRAFTING_GRID, AUTOCRAFTER
|
||||
);
|
||||
|
||||
public BlockInteractionHandler(PluginBase plugin) {
|
||||
this.networkManager = NetworkManager.getInstance();
|
||||
registerEvents(plugin);
|
||||
}
|
||||
|
||||
private void registerEvents(PluginBase plugin) {
|
||||
EventRegistry events = plugin.getEventRegistry();
|
||||
|
||||
events.register(EventPriority.NORMAL, UseBlockEvent.class, this::onUseBlock);
|
||||
events.register(EventPriority.NORMAL, PlaceBlockEvent.class, this::onPlaceBlock);
|
||||
events.register(EventPriority.NORMAL, BreakBlockEvent.class, this::onBreakBlock);
|
||||
|
||||
LOGGER.atInfo().log("Registered RS block interaction handlers");
|
||||
}
|
||||
|
||||
private void onUseBlock(UseBlockEvent event) {
|
||||
Vector3i pos = event.getTargetBlock();
|
||||
String blockId = extractBlockId(event.getBlockType());
|
||||
if (blockId == null) return;
|
||||
|
||||
switch (blockId) {
|
||||
case CONTROLLER -> {
|
||||
int netId = networkManager.getNetworkForController(pos);
|
||||
LOGGER.atInfo().log("Player right-clicked Controller at ({},{},{}) network #{}",
|
||||
pos.x, pos.y, pos.z, netId);
|
||||
// TODO: open ControllerUI
|
||||
}
|
||||
case GRID -> {
|
||||
int netId = networkManager.getNetworkForMachine(pos);
|
||||
LOGGER.atInfo().log("Player right-clicked Grid at ({},{},{}) network #{}",
|
||||
pos.x, pos.y, pos.z, netId);
|
||||
// TODO: open GridUI
|
||||
}
|
||||
case DISK_DRIVE -> {
|
||||
int netId = networkManager.getNetworkForMachine(pos);
|
||||
LOGGER.atInfo().log("Player right-clicked DiskDrive at ({},{},{}) network #{}",
|
||||
pos.x, pos.y, pos.z, netId);
|
||||
// TODO: open DiskDriveUI
|
||||
}
|
||||
case CRAFTING_GRID -> {
|
||||
LOGGER.atInfo().log("Player right-clicked CraftingGrid at ({},{},{})",
|
||||
pos.x, pos.y, pos.z);
|
||||
// TODO: open CraftingGridUI
|
||||
}
|
||||
case AUTOCRAFTER -> {
|
||||
LOGGER.atInfo().log("Player right-clicked Autocrafter at ({},{},{})",
|
||||
pos.x, pos.y, pos.z);
|
||||
// TODO: open AutocrafterUI
|
||||
}
|
||||
case IMPORTER, EXPORTER, INTERFACE_BLOCK, CABLE -> {
|
||||
LOGGER.atInfo().log("Player right-clicked {} at ({},{},{})",
|
||||
blockId, pos.x, pos.y, pos.z);
|
||||
}
|
||||
default -> {}
|
||||
}
|
||||
}
|
||||
|
||||
private void onPlaceBlock(PlaceBlockEvent event) {
|
||||
String itemName = event.getItemInHand().toString().toLowerCase();
|
||||
String blockId = matchBlockId(itemName);
|
||||
if (blockId == null) return;
|
||||
|
||||
Vector3i pos = event.getTargetBlock();
|
||||
switch (blockId) {
|
||||
case CONTROLLER -> {
|
||||
networkManager.onControllerPlaced(pos);
|
||||
LOGGER.atInfo().log("Controller placed at ({},{},{})", pos.x, pos.y, pos.z);
|
||||
}
|
||||
case CABLE -> {
|
||||
networkManager.onCablePlaced(pos);
|
||||
LOGGER.atInfo().log("Cable placed at ({},{},{})", pos.x, pos.y, pos.z);
|
||||
}
|
||||
default -> {
|
||||
if (RS_MACHINES.contains(blockId)) {
|
||||
networkManager.onMachinePlaced(pos, blockId);
|
||||
LOGGER.atInfo().log("{} placed at ({},{},{})", blockId, pos.x, pos.y, pos.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onBreakBlock(BreakBlockEvent event) {
|
||||
Vector3i pos = event.getTargetBlock();
|
||||
String blockId = extractBlockId(event.getBlockType());
|
||||
if (blockId == null || !RS_BLOCKS.contains(blockId)) return;
|
||||
|
||||
networkManager.onBlockBroken(pos);
|
||||
LOGGER.atInfo().log("{} broken at ({},{},{})", blockId, pos.x, pos.y, pos.z);
|
||||
}
|
||||
|
||||
private static String extractBlockId(Object blockType) {
|
||||
if (blockType == null) return null;
|
||||
String name = blockType.toString().toLowerCase();
|
||||
return matchBlockId(name);
|
||||
}
|
||||
|
||||
private static String matchBlockId(String input) {
|
||||
if (input == null) return null;
|
||||
for (String id : RS_BLOCKS) {
|
||||
if (input.contains(id)) return id;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
package dev.refinedstorage.handler;
|
||||
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.server.core.plugin.PluginBase;
|
||||
import dev.refinedstorage.network.NetworkManager;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* Periodic network tick handler (~1s intervals).
|
||||
*/
|
||||
public final class NetworkTickHandler {
|
||||
|
||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||
private static final long TICK_INTERVAL_MS = 1000;
|
||||
|
||||
private final NetworkManager networkManager;
|
||||
private final ScheduledExecutorService scheduler;
|
||||
private int tickCounter = 0;
|
||||
|
||||
public NetworkTickHandler() {
|
||||
this.networkManager = NetworkManager.getInstance();
|
||||
this.scheduler = Executors.newSingleThreadScheduledExecutor(r -> {
|
||||
Thread t = new Thread(r, "RS-Network-Tick");
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
});
|
||||
}
|
||||
|
||||
public void start(PluginBase plugin) {
|
||||
scheduler.scheduleAtFixedRate(this::tick, TICK_INTERVAL_MS, TICK_INTERVAL_MS, TimeUnit.MILLISECONDS);
|
||||
LOGGER.atInfo().log("Network tick handler started");
|
||||
}
|
||||
|
||||
private void tick() {
|
||||
tickCounter++;
|
||||
|
||||
for (int netId : networkManager.getAllNetworkIds()) {
|
||||
NetworkManager.Network net = networkManager.getNetwork(netId);
|
||||
if (net == null) continue;
|
||||
try {
|
||||
processNetworkTick(net);
|
||||
} catch (Exception e) {
|
||||
LOGGER.at(Level.WARNING).withCause(e).log("Error ticking network #{}", netId);
|
||||
}
|
||||
}
|
||||
|
||||
if (tickCounter % 30 == 0) {
|
||||
int totalNetworks = networkManager.getAllNetworkIds().size();
|
||||
if (totalNetworks > 0) {
|
||||
LOGGER.atInfo().log("Network tick: {} active networks", totalNetworks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processNetworkTick(NetworkManager.Network net) {
|
||||
// TODO: power check, inventory propagation, importer/exporter I/O, disk I/O
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
scheduler.shutdown();
|
||||
try {
|
||||
if (!scheduler.awaitTermination(2, TimeUnit.SECONDS)) {
|
||||
scheduler.shutdownNow();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
scheduler.shutdownNow();
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
LOGGER.atInfo().log("Network tick handler stopped");
|
||||
}
|
||||
}
|
||||
222
src/main/java/dev/refinedstorage/network/NetworkManager.java
Normal file
222
src/main/java/dev/refinedstorage/network/NetworkManager.java
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
package dev.refinedstorage.network;
|
||||
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.math.vector.Vector3i;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Manages all RefinedStorage networks.
|
||||
* Uses BFS for cable propagation through connected blocks.
|
||||
*/
|
||||
public final class NetworkManager {
|
||||
|
||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||
private static NetworkManager instance;
|
||||
|
||||
private final AtomicInteger networkIdCounter = new AtomicInteger(1);
|
||||
private final Map<Integer, Network> networks = new ConcurrentHashMap<>();
|
||||
private final Map<String, Integer> cableLookup = new ConcurrentHashMap<>();
|
||||
private final Map<String, Integer> machineLookup = new ConcurrentHashMap<>();
|
||||
private final Map<String, Integer> controllerLookup = new ConcurrentHashMap<>();
|
||||
|
||||
private NetworkManager() {}
|
||||
|
||||
public static synchronized NetworkManager getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new NetworkManager();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public int createNetwork(Vector3i controllerPos) {
|
||||
int id = networkIdCounter.getAndIncrement();
|
||||
Network net = new Network(id, controllerPos);
|
||||
networks.put(id, net);
|
||||
controllerLookup.put(key(controllerPos), id);
|
||||
LOGGER.atInfo().log("Created network #{} at controller ({}, {}, {})",
|
||||
id, controllerPos.x, controllerPos.y, controllerPos.z);
|
||||
return id;
|
||||
}
|
||||
|
||||
public void removeNetwork(int networkId) {
|
||||
Network net = networks.remove(networkId);
|
||||
if (net == null) return;
|
||||
controllerLookup.remove(key(net.controllerPos));
|
||||
for (Vector3i cable : net.cables) {
|
||||
cableLookup.remove(key(cable));
|
||||
}
|
||||
for (Map.Entry<Vector3i, String> entry : net.machines.entrySet()) {
|
||||
machineLookup.remove(key(entry.getKey()));
|
||||
}
|
||||
LOGGER.atInfo().log("Removed network #{}", networkId);
|
||||
}
|
||||
|
||||
public void addCable(int networkId, Vector3i pos) {
|
||||
Network net = networks.get(networkId);
|
||||
if (net == null) return;
|
||||
net.cables.add(pos);
|
||||
cableLookup.put(key(pos), networkId);
|
||||
}
|
||||
|
||||
public void removeCable(int networkId, Vector3i pos) {
|
||||
Network net = networks.get(networkId);
|
||||
if (net == null) return;
|
||||
net.cables.remove(pos);
|
||||
cableLookup.remove(key(pos));
|
||||
rebuildNetwork(networkId);
|
||||
}
|
||||
|
||||
public void addMachine(int networkId, Vector3i pos, String machineType) {
|
||||
Network net = networks.get(networkId);
|
||||
if (net == null) return;
|
||||
net.machines.put(pos, machineType);
|
||||
machineLookup.put(key(pos), networkId);
|
||||
}
|
||||
|
||||
public void removeMachine(int networkId, Vector3i pos) {
|
||||
Network net = networks.get(networkId);
|
||||
if (net == null) return;
|
||||
net.machines.remove(pos);
|
||||
machineLookup.remove(key(pos));
|
||||
}
|
||||
|
||||
public int getNetworkForCable(Vector3i pos) {
|
||||
return cableLookup.getOrDefault(key(pos), -1);
|
||||
}
|
||||
|
||||
public int getNetworkForMachine(Vector3i pos) {
|
||||
return machineLookup.getOrDefault(key(pos), -1);
|
||||
}
|
||||
|
||||
public int getNetworkForController(Vector3i pos) {
|
||||
return controllerLookup.getOrDefault(key(pos), -1);
|
||||
}
|
||||
|
||||
public Network getNetwork(int networkId) {
|
||||
return networks.get(networkId);
|
||||
}
|
||||
|
||||
public Collection<Integer> getAllNetworkIds() {
|
||||
return networks.keySet();
|
||||
}
|
||||
|
||||
public void rebuildNetwork(int networkId) {
|
||||
Network net = networks.get(networkId);
|
||||
if (net == null) return;
|
||||
|
||||
Map<Vector3i, String> savedMachines = new HashMap<>(net.machines);
|
||||
List<Vector3i> oldCables = new ArrayList<>(net.cables);
|
||||
net.cables.clear();
|
||||
net.machines.clear();
|
||||
|
||||
Set<String> visited = new HashSet<>();
|
||||
Queue<Vector3i> queue = new ArrayDeque<>();
|
||||
visited.add(key(net.controllerPos));
|
||||
queue.add(net.controllerPos);
|
||||
|
||||
int[] dx = {1, -1, 0, 0, 0, 0};
|
||||
int[] dy = {0, 0, 1, -1, 0, 0};
|
||||
int[] dz = {0, 0, 0, 0, 1, -1};
|
||||
|
||||
while (!queue.isEmpty()) {
|
||||
Vector3i current = queue.poll();
|
||||
for (int i = 0; i < 6; i++) {
|
||||
Vector3i neighbor = new Vector3i(
|
||||
current.x + dx[i],
|
||||
current.y + dy[i],
|
||||
current.z + dz[i]
|
||||
);
|
||||
String nkey = key(neighbor);
|
||||
if (visited.contains(nkey)) continue;
|
||||
visited.add(nkey);
|
||||
|
||||
if (oldCables.contains(neighbor)) {
|
||||
net.cables.add(neighbor);
|
||||
cableLookup.put(nkey, networkId);
|
||||
queue.add(neighbor);
|
||||
}
|
||||
if (savedMachines.containsKey(neighbor)) {
|
||||
net.machines.put(neighbor, savedMachines.get(neighbor));
|
||||
machineLookup.put(nkey, networkId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onCablePlaced(Vector3i pos) {
|
||||
int networkId = findAdjacentNetwork(pos);
|
||||
if (networkId != -1) {
|
||||
addCable(networkId, pos);
|
||||
rebuildNetwork(networkId);
|
||||
}
|
||||
}
|
||||
|
||||
public void onMachinePlaced(Vector3i pos, String machineType) {
|
||||
int networkId = findAdjacentNetwork(pos);
|
||||
if (networkId != -1) {
|
||||
addMachine(networkId, pos, machineType);
|
||||
}
|
||||
}
|
||||
|
||||
public void onControllerPlaced(Vector3i pos) {
|
||||
createNetwork(pos);
|
||||
}
|
||||
|
||||
public void onBlockBroken(Vector3i pos) {
|
||||
Integer netId = controllerLookup.remove(key(pos));
|
||||
if (netId != null) {
|
||||
removeNetwork(netId);
|
||||
return;
|
||||
}
|
||||
netId = cableLookup.remove(key(pos));
|
||||
if (netId != null) {
|
||||
removeCable(netId, pos);
|
||||
return;
|
||||
}
|
||||
netId = machineLookup.remove(key(pos));
|
||||
if (netId != null) {
|
||||
removeMachine(netId, pos);
|
||||
}
|
||||
}
|
||||
|
||||
private int findAdjacentNetwork(Vector3i pos) {
|
||||
int[] dx = {1, -1, 0, 0, 0, 0};
|
||||
int[] dy = {0, 0, 1, -1, 0, 0};
|
||||
int[] dz = {0, 0, 0, 0, 1, -1};
|
||||
for (int i = 0; i < 6; i++) {
|
||||
Vector3i neighbor = new Vector3i(
|
||||
pos.x + dx[i],
|
||||
pos.y + dy[i],
|
||||
pos.z + dz[i]
|
||||
);
|
||||
String nkey = key(neighbor);
|
||||
Integer netId = cableLookup.get(nkey);
|
||||
if (netId != null) return netId;
|
||||
netId = controllerLookup.get(nkey);
|
||||
if (netId != null) return netId;
|
||||
netId = machineLookup.get(nkey);
|
||||
if (netId != null) return netId;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static String key(Vector3i pos) {
|
||||
return pos.x + "," + pos.y + "," + pos.z;
|
||||
}
|
||||
|
||||
public static final class Network {
|
||||
public final int id;
|
||||
public final Vector3i controllerPos;
|
||||
public final List<Vector3i> cables = new CopyOnWriteArrayList<>();
|
||||
public final Map<Vector3i, String> machines = new ConcurrentHashMap<>();
|
||||
|
||||
public Network(int id, Vector3i controllerPos) {
|
||||
this.id = id;
|
||||
this.controllerPos = controllerPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
44
src/main/java/dev/refinedstorage/ui/ControllerUI.java
Normal file
44
src/main/java/dev/refinedstorage/ui/ControllerUI.java
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
package dev.refinedstorage.ui;
|
||||
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.component.Store;
|
||||
import com.hypixel.hytale.protocol.packets.interface_.CustomPageLifetime;
|
||||
import com.hypixel.hytale.server.core.entity.entities.player.pages.CustomUIPage;
|
||||
import com.hypixel.hytale.server.core.ui.builder.UICommandBuilder;
|
||||
import com.hypixel.hytale.server.core.ui.builder.UIEventBuilder;
|
||||
import com.hypixel.hytale.server.core.universe.PlayerRef;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
|
||||
/**
|
||||
* Controller Status UI — shows network information and connected devices.
|
||||
*/
|
||||
public class ControllerUI extends CustomUIPage {
|
||||
|
||||
private final String networkId;
|
||||
|
||||
public ControllerUI(PlayerRef playerRef, String networkId) {
|
||||
super(playerRef, CustomPageLifetime.CanDismissOrCloseThroughInteraction);
|
||||
this.networkId = networkId;
|
||||
rebuild();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(Ref<EntityStore> ref, UICommandBuilder commands, UIEventBuilder events, Store<EntityStore> store) {
|
||||
// TODO: Build controller status UI:
|
||||
// - Network ID
|
||||
// - Connected cables count
|
||||
// - Connected machines list (type + position)
|
||||
// - Disk usage summary
|
||||
// - Power status indicator
|
||||
// - Energy consumption (if applicable)
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleDataEvent(Ref<EntityStore> ref, Store<EntityStore> store, String data) {
|
||||
// TODO: Handle UI events (e.g., refresh)
|
||||
}
|
||||
|
||||
public String getNetworkId() {
|
||||
return networkId;
|
||||
}
|
||||
}
|
||||
47
src/main/java/dev/refinedstorage/ui/DiskDriveUI.java
Normal file
47
src/main/java/dev/refinedstorage/ui/DiskDriveUI.java
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package dev.refinedstorage.ui;
|
||||
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.component.Store;
|
||||
import com.hypixel.hytale.protocol.packets.interface_.CustomPageLifetime;
|
||||
import com.hypixel.hytale.server.core.entity.entities.player.pages.CustomUIPage;
|
||||
import com.hypixel.hytale.server.core.ui.builder.UICommandBuilder;
|
||||
import com.hypixel.hytale.server.core.ui.builder.UIEventBuilder;
|
||||
import com.hypixel.hytale.server.core.universe.PlayerRef;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
|
||||
/**
|
||||
* Disk Drive UI — manage storage disks: view contents, format, eject.
|
||||
*/
|
||||
public class DiskDriveUI extends CustomUIPage {
|
||||
|
||||
private final String networkId;
|
||||
|
||||
public DiskDriveUI(PlayerRef playerRef, String networkId) {
|
||||
super(playerRef, CustomPageLifetime.CanDismissOrCloseThroughInteraction);
|
||||
this.networkId = networkId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(Ref<EntityStore> ref, UICommandBuilder commands, UIEventBuilder events, Store<EntityStore> store) {
|
||||
// TODO: Build disk drive UI:
|
||||
// - List of installed disks with:
|
||||
// - Disk ID / name
|
||||
// - Used space / total space
|
||||
// - Number of item types stored
|
||||
// - Format button per disk
|
||||
// - Eject button per disk
|
||||
// - Priority slider
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleDataEvent(Ref<EntityStore> ref, Store<EntityStore> store, String data) {
|
||||
// TODO: Handle UI events:
|
||||
// - Format disk
|
||||
// - Eject disk
|
||||
// - Change priority
|
||||
}
|
||||
|
||||
public String getNetworkId() {
|
||||
return networkId;
|
||||
}
|
||||
}
|
||||
50
src/main/java/dev/refinedstorage/ui/GridUI.java
Normal file
50
src/main/java/dev/refinedstorage/ui/GridUI.java
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
package dev.refinedstorage.ui;
|
||||
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.component.Store;
|
||||
import com.hypixel.hytale.protocol.packets.interface_.CustomPageLifetime;
|
||||
import com.hypixel.hytale.server.core.entity.entities.player.pages.CustomUIPage;
|
||||
import com.hypixel.hytale.server.core.ui.builder.UICommandBuilder;
|
||||
import com.hypixel.hytale.server.core.ui.builder.UIEventBuilder;
|
||||
import com.hypixel.hytale.server.core.universe.PlayerRef;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
|
||||
/**
|
||||
* Item Grid UI — the main interface for browsing and searching network items.
|
||||
*/
|
||||
public class GridUI extends CustomUIPage {
|
||||
|
||||
private final String networkId;
|
||||
|
||||
public GridUI(PlayerRef playerRef, String networkId) {
|
||||
super(playerRef, CustomPageLifetime.CanDismissOrCloseThroughInteraction);
|
||||
this.networkId = networkId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(Ref<EntityStore> ref, UICommandBuilder commands, UIEventBuilder events, Store<EntityStore> store) {
|
||||
// TODO: Build the grid UI with:
|
||||
// - Search bar at top
|
||||
// - Sort buttons (by name, quantity, mod)
|
||||
// - Scrollable grid of item slots
|
||||
// - Pagination controls
|
||||
|
||||
// Placeholder: send a simple structure for now
|
||||
// The actual UI building will use commands like:
|
||||
// commands.set("searchBar.placeholder", "Search items...");
|
||||
// commands.append("gridContainer", "...");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleDataEvent(Ref<EntityStore> ref, Store<EntityStore> store, String data) {
|
||||
// TODO: Handle UI events:
|
||||
// - Search queries
|
||||
// - Sort changes
|
||||
// - Item clicks (extract/insert)
|
||||
// - Pagination
|
||||
}
|
||||
|
||||
public String getNetworkId() {
|
||||
return networkId;
|
||||
}
|
||||
}
|
||||
57
src/main/java/dev/refinedstorage/ui/UIManager.java
Normal file
57
src/main/java/dev/refinedstorage/ui/UIManager.java
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
package dev.refinedstorage.ui;
|
||||
|
||||
import com.hypixel.hytale.logger.HytaleLogger;
|
||||
import com.hypixel.hytale.server.core.entity.entities.player.pages.CustomUIPage;
|
||||
import com.hypixel.hytale.server.core.universe.PlayerRef;
|
||||
|
||||
/**
|
||||
* Utility manager for opening RefinedStorage UIs.
|
||||
*/
|
||||
public final class UIManager {
|
||||
|
||||
private static final HytaleLogger LOGGER = HytaleLogger.forEnclosingClass();
|
||||
private static UIManager instance;
|
||||
|
||||
private UIManager() {}
|
||||
|
||||
public static synchronized UIManager getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new UIManager();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the item grid UI for a player.
|
||||
*/
|
||||
public void openGrid(PlayerRef playerRef, String networkId) {
|
||||
LOGGER.atInfo().log("Opening Grid UI for player {} (network {})", playerRef, networkId);
|
||||
// TODO: Create and show GridUI page
|
||||
// CustomUIPage page = new GridUI(playerRef, networkId);
|
||||
// The page opens automatically via CustomUIPage's lifecycle
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the controller status UI for a player.
|
||||
*/
|
||||
public void openController(PlayerRef playerRef, String networkId) {
|
||||
LOGGER.atInfo().log("Opening Controller UI for player {} (network {})", playerRef, networkId);
|
||||
// TODO: Create and show ControllerUI page
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the disk drive management UI for a player.
|
||||
*/
|
||||
public void openDiskDrive(PlayerRef playerRef, String networkId) {
|
||||
LOGGER.atInfo().log("Opening DiskDrive UI for player {} (network {})", playerRef, networkId);
|
||||
// TODO: Create and show DiskDriveUI page
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the crafting grid UI for a player.
|
||||
*/
|
||||
public void openCraftingGrid(PlayerRef playerRef, String networkId) {
|
||||
LOGGER.atInfo().log("Opening CraftingGrid UI for player {} (network {})", playerRef, networkId);
|
||||
// TODO: Create and show CraftingGridUI page
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
"Name": "items.rs_autocrafter.name",
|
||||
"Description": "items.rs_autocrafter.description"
|
||||
},
|
||||
"Id": "Autocrafter",
|
||||
"MaxStack": 100,
|
||||
"Icon": "Icons/ItemsGenerated/autocrafter.png",
|
||||
"Categories": [
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"Name": "items.rs_autocraftingmonitor.name",
|
||||
"Description": "items.rs_autocraftingmonitor.description"
|
||||
},
|
||||
"Id": "AutocraftingMonitor",
|
||||
"MaxStack": 100,
|
||||
"Icon": "Icons/ItemsGenerated/autocrafting_monitor.png",
|
||||
"Categories": [
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"Name": "items.rs_cable.name",
|
||||
"Description": "items.rs_cable.description"
|
||||
},
|
||||
"Id": "Cable",
|
||||
"MaxStack": 100,
|
||||
"Icon": "Icons/ItemsGenerated/cable.png",
|
||||
"Categories": [
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"Name": "items.rs_controller.name",
|
||||
"Description": "items.rs_controller.description"
|
||||
},
|
||||
"Id": "Controller",
|
||||
"MaxStack": 100,
|
||||
"Icon": "Icons/ItemsGenerated/controller.png",
|
||||
"Categories": [
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"Name": "items.rs_craftinggrid.name",
|
||||
"Description": "items.rs_craftinggrid.description"
|
||||
},
|
||||
"Id": "CraftingGrid",
|
||||
"MaxStack": 100,
|
||||
"Icon": "Icons/ItemsGenerated/crafting_grid.png",
|
||||
"Categories": [
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"Name": "items.rs_diskdrive.name",
|
||||
"Description": "items.rs_diskdrive.description"
|
||||
},
|
||||
"Id": "DiskDrive",
|
||||
"MaxStack": 100,
|
||||
"Icon": "Icons/ItemsGenerated/disk_drive.png",
|
||||
"Categories": [
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"Name": "items.rs_exporter.name",
|
||||
"Description": "items.rs_exporter.description"
|
||||
},
|
||||
"Id": "Exporter",
|
||||
"MaxStack": 100,
|
||||
"Icon": "Icons/ItemsGenerated/io_device.png",
|
||||
"Categories": [
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"Name": "items.rs_grid.name",
|
||||
"Description": "items.rs_grid.description"
|
||||
},
|
||||
"Id": "Grid",
|
||||
"MaxStack": 100,
|
||||
"Icon": "Icons/ItemsGenerated/grid.png",
|
||||
"Categories": [
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"Name": "items.rs_importer.name",
|
||||
"Description": "items.rs_importer.description"
|
||||
},
|
||||
"Id": "Importer",
|
||||
"MaxStack": 100,
|
||||
"Icon": "Icons/ItemsGenerated/io_device.png",
|
||||
"Categories": [
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"Name": "items.rs_interface.name",
|
||||
"Description": "items.rs_interface.description"
|
||||
},
|
||||
"Id": "Interface",
|
||||
"MaxStack": 100,
|
||||
"Icon": "Icons/ItemsGenerated/interface.png",
|
||||
"Categories": [
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"Name": "items.rs_machinecasing.name",
|
||||
"Description": "items.rs_machinecasing.description"
|
||||
},
|
||||
"Id": "MachineCasing",
|
||||
"MaxStack": 100,
|
||||
"Icon": "Icons/ItemsGenerated/machine_casing.png",
|
||||
"Categories": [
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"Name": "items.rs_securitydetector.name",
|
||||
"Description": "items.rs_securitydetector.description"
|
||||
},
|
||||
"Id": "SecurityDetector",
|
||||
"MaxStack": 100,
|
||||
"Icon": "Icons/ItemsGenerated/security_detector.png",
|
||||
"Categories": [
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"Name": "items.rs_securityterminal.name",
|
||||
"Description": "items.rs_securityterminal.description"
|
||||
},
|
||||
"Id": "SecurityTerminal",
|
||||
"MaxStack": 100,
|
||||
"Icon": "Icons/ItemsGenerated/security_terminal.png",
|
||||
"Categories": [
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"Name": "items.rs_wirelessreceiver.name",
|
||||
"Description": "items.rs_wirelessreceiver.description"
|
||||
},
|
||||
"Id": "WirelessReceiver",
|
||||
"MaxStack": 100,
|
||||
"Icon": "Icons/ItemsGenerated/wireless_receiver.png",
|
||||
"Categories": [
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
"Name": "items.rs_wirelesstransmitter.name",
|
||||
"Description": "items.rs_wirelesstransmitter.description"
|
||||
},
|
||||
"Id": "WirelessTransmitter",
|
||||
"MaxStack": 100,
|
||||
"Icon": "Icons/ItemsGenerated/wireless_transmitter.png",
|
||||
"Categories": [
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue