Compare commits
22 Commits
bee8f740c6
...
master
Author | SHA1 | Date | |
---|---|---|---|
b47a8ad4fa | |||
a1bb89a4d2 | |||
53bfc85164 | |||
bcbb419179 | |||
e45b1ea995 | |||
4b4c656af1 | |||
1f593d0542 | |||
ba51252476 | |||
5dd175bb00 | |||
9f2b3a8050 | |||
c8806be02d | |||
bc46c8adef | |||
78be72c4b1 | |||
a72cd8bef5 | |||
164006f4b0 | |||
b5ea97b5d9 | |||
75b9634ea9 | |||
ff5ff86794 | |||
144b2b9ebb | |||
7853e6174e | |||
c19888f597 | |||
1b38039f62 |
1
storage-net/.gitignore
vendored
Normal file
1
storage-net/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.vscode
|
@@ -4,70 +4,10 @@ This is an implementation of a centralized storage network architecture that use
|
||||
|
||||
## Deployment
|
||||
|
||||
A GPS will need to be established and be accurate within range of the entire network to the block.
|
||||
First, consider using [someone else's project](https://github.com/lewark/inv.lua) instead of this one. It's liable to be a lot better than mine.
|
||||
|
||||
## Communication Protocol
|
||||
|
||||
Port 42914 is used for Master => Slave broadcasting
|
||||
|
||||
Port 42915 is used for Slave => Master return broadcasting
|
||||
|
||||
### Packet Format
|
||||
|
||||
Packet format is uniform between master <-> slaves and is structured like so:
|
||||
|
||||
```
|
||||
{
|
||||
// Metadata
|
||||
magic: str("ccstoragenet")
|
||||
networkid: int()
|
||||
sourceid: int()
|
||||
destid: int()
|
||||
|
||||
// Payload
|
||||
type: str()
|
||||
|
||||
// Optional Arguments
|
||||
itemname: str()
|
||||
itemquant: int()
|
||||
destination: int()
|
||||
location: [int(),int(),int()]
|
||||
}
|
||||
```
|
||||
|
||||
| Name | Required? | Type | Description
|
||||
| :-- | :--: | :-- | :--
|
||||
| `magic` | true | string | Must be `ccstoragenet`. If it is not, the packet is immediately discarded |
|
||||
| `networkid` | true | int | The ID of the network |
|
||||
| `sourceid` | true | int | The CC ID of the machine sending the packet |
|
||||
| `destid` | true | int | The CC ID of the intended recipient of the packet |
|
||||
| `type` | true | string | An arbitrary string literal corresponding to the type of the request. Common examplse include `ping`, `query`, etc. |
|
||||
| `itemname` | false | string | The unlocalized name of an item. Used for querying, crafting, movement, etc. |
|
||||
| `itemquant` | false | int | Quantity of the aforementioned item |
|
||||
| `destination` | false | int | The CC ID of the intended recipient of the item |
|
||||
|
||||
### Slave Node Initialization
|
||||
|
||||
* The slave starts up
|
||||
* The slave receives a `ping` packet from a master server. The slave compares it to any stored `/pairednetwork` file in the root of the filesystem:
|
||||
* If the file exists and the ID does not match, processing is halted
|
||||
* The `networkid` of the packet is stored as `/pairednetwork`
|
||||
* The slave responds with a `pong` packet.
|
||||
|
||||
### Master Node Initialization
|
||||
|
||||
* The master node starts up
|
||||
* The master node sends a packet with type `ping` and `networkid` initialized to its CC ID.
|
||||
* The master node listens for `pong` packets for a configurable timeout.
|
||||
* The `sourceid` of all `pong` packets is recorded for statistics displays. This cached data is only used for user display. Node availability is evaluated at request time.
|
||||
|
||||
### Inventory Search (query)
|
||||
|
||||
* A sender node (master or slave) sends out a `ping`
|
||||
* All available slaves respond with `pong`
|
||||
* The sender node sends a packet with type `query`. Field `itemname` is populated with an item to query for.
|
||||
* Each available slave responds with type `query`.
|
||||
* `itemname` is populated with data from the previous packet
|
||||
* `itemquantity` is populated with the quantity of that item attached to storages the slave has access to.
|
||||
* The requester waits for a response from each slave that responded to the `ping` or until a configurable timeout is reached.
|
||||
* Results are consumed
|
||||
1. Deploy a Smart Computer
|
||||
2. Connect the computer to at least 1 chest and 1 hopper via physical modem lines. Chests need to be attached from the bottom and hoppers from their output direction
|
||||
3. Put a chest on top of the Smart Computer
|
||||
4. Install Basalt (`wget run https://basalt.madefor.cc/install.lua release latest.lua`)
|
||||
5. Deploy the script (as `startup`, of course)
|
90
storage-net/common.lua
Normal file
90
storage-net/common.lua
Normal file
@@ -0,0 +1,90 @@
|
||||
-- Salt's ComputerCraft Storage Network Script
|
||||
--
|
||||
-- For information on this script, physical in-world setup, and configuration,
|
||||
-- see: https://git.desu.ltd/salt/mc-scripts/src/branch/master/storage-net
|
||||
|
||||
-- Startup diagnostics
|
||||
print("Salt's CC Storage Net")
|
||||
|
||||
-- Global scope locals
|
||||
local output = peripheral.wrap("top") or error("Put a chest on top of this terminal for output items", 0)
|
||||
|
||||
-- Helper functions
|
||||
function getDepositHoppers()
|
||||
-- Get all connected inventories that push items into the system
|
||||
return {peripheral.find("inventory", function(name,i)
|
||||
return string.find(name, "minecraft:hopper")
|
||||
end)}
|
||||
end
|
||||
function getConnectedChests()
|
||||
-- Get all connected inventories that store items
|
||||
return {peripheral.find("inventory", function(name,i)
|
||||
return string.find(name, "minecraft:chest")
|
||||
end)}
|
||||
end
|
||||
|
||||
-- Common functions
|
||||
function pushDepositsToChests()
|
||||
-- Take all the contents of all connected hoppers and stuff them into any other connected inventory
|
||||
-- These things are wrapped into tables because that's how you take multiple return values and stuff them in a table, apparently
|
||||
local hoppers = getDepositHoppers()
|
||||
local chests = getConnectedChests()
|
||||
-- For each hopper connected to the network...
|
||||
for k,hopper in ipairs(hoppers) do
|
||||
-- For each item in that hopper's inventory...
|
||||
for hslot,hitem in pairs(hopper.list()) do
|
||||
-- For each connected "chest"...
|
||||
for k,chest in ipairs(chests) do
|
||||
-- First, make an attempt to find slots that we can shove the item into
|
||||
for cslot,citem in pairs(chest.list()) do
|
||||
if
|
||||
citem["name"] == hitem["name"] and -- We have the same item
|
||||
citem["count"] < chest.getItemLimit(cslot) -- There's space in this slot
|
||||
then
|
||||
hopper.pushItems(peripheral.getName(chest),hslot,hitem["count"],cslot)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- We've fallen through trying to fill up existing stacks. Fragmentation is not a concern, put it wherever
|
||||
if hopper.getItemDetail(hslot) then
|
||||
for k,chest in ipairs(chests) do
|
||||
hopper.pushItems(peripheral.getName(chest),hslot)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function requestItem(name, count)
|
||||
-- Pull a number of an item into the output chest above the machine
|
||||
remaining = count
|
||||
local chests = getConnectedChests()
|
||||
-- For each chest on the network...
|
||||
for k,chest in ipairs(chests) do
|
||||
-- For each slot in that chest...
|
||||
for cslot,citem in pairs(chest.list()) do
|
||||
if
|
||||
citem["name"] == name and
|
||||
citem["count"] > 0
|
||||
then
|
||||
desired = math.max(remaining, citem["count"])
|
||||
output.pullItems(peripheral.getName(chest),cslot,desired)
|
||||
remaining = remaining - desired
|
||||
end
|
||||
if remaining <= 0 then return true end
|
||||
end
|
||||
end
|
||||
if remaining > 0 then return false end
|
||||
end
|
||||
|
||||
-- Application entrypoint
|
||||
function main()
|
||||
requestItem("minecraft:sandstone", 12)
|
||||
while true do
|
||||
-- Manage inventory cleanup tasks
|
||||
pushDepositsToChests() -- Take all deposit terminals and push them into the inventory network
|
||||
-- Sleep for a tick
|
||||
sleep(0.05) -- This is to stop CC from killing us
|
||||
end
|
||||
end
|
||||
|
||||
main()
|
20
storage-net/deploy.sh
Executable file
20
storage-net/deploy.sh
Executable file
@@ -0,0 +1,20 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# deploy.sh
|
||||
# Copyright (C) 2024 Jacob Babor <jacob@babor.tech>
|
||||
#
|
||||
# Distributed under terms of the MIT license.
|
||||
#
|
||||
|
||||
mcroot="$HOME/.var/app/org.prismlauncher.PrismLauncher/data/PrismLauncher/instances/ComputerCraft Sandbox/"
|
||||
world="New World"
|
||||
|
||||
masterid="0"
|
||||
|
||||
_ccroot="$mcroot/.minecraft/saves/$world/computercraft/computer"
|
||||
echo "Root: $_ccroot"
|
||||
for computer in "$masterid"; do
|
||||
echo "Deploying to: $computer"
|
||||
mkdir -p "$_ccroot/$computer"
|
||||
cp common.lua "$_ccroot/$computer/startup"
|
||||
done
|
Reference in New Issue
Block a user