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:
Lead Developer Web 2026-04-30 21:38:44 +02:00
parent ff8dfd3668
commit ba84350a01
25 changed files with 693 additions and 39 deletions

View file

@ -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
View file

@ -0,0 +1 @@
java=25.0.3-tem

View file

@ -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");
}
}

View file

@ -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;
}
}

View file

@ -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");
}
}

View 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;
}
}
}

View 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;
}
}

View 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;
}
}

View 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;
}
}

View 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
}
}

View file

@ -3,7 +3,6 @@
"Name": "items.rs_autocrafter.name",
"Description": "items.rs_autocrafter.description"
},
"Id": "Autocrafter",
"MaxStack": 100,
"Icon": "Icons/ItemsGenerated/autocrafter.png",
"Categories": [

View file

@ -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": [

View file

@ -3,7 +3,6 @@
"Name": "items.rs_cable.name",
"Description": "items.rs_cable.description"
},
"Id": "Cable",
"MaxStack": 100,
"Icon": "Icons/ItemsGenerated/cable.png",
"Categories": [

View file

@ -3,7 +3,6 @@
"Name": "items.rs_controller.name",
"Description": "items.rs_controller.description"
},
"Id": "Controller",
"MaxStack": 100,
"Icon": "Icons/ItemsGenerated/controller.png",
"Categories": [

View file

@ -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": [

View file

@ -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": [

View file

@ -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": [

View file

@ -3,7 +3,6 @@
"Name": "items.rs_grid.name",
"Description": "items.rs_grid.description"
},
"Id": "Grid",
"MaxStack": 100,
"Icon": "Icons/ItemsGenerated/grid.png",
"Categories": [

View file

@ -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": [

View file

@ -3,7 +3,6 @@
"Name": "items.rs_interface.name",
"Description": "items.rs_interface.description"
},
"Id": "Interface",
"MaxStack": 100,
"Icon": "Icons/ItemsGenerated/interface.png",
"Categories": [

View file

@ -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": [

View file

@ -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": [

View file

@ -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": [

View file

@ -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": [

View file

@ -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": [