Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for fluid tanks and piping fluids #29

Merged
merged 17 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ export default function App() {
* Handlers for React Flow events
*/
const onConnect: OnConnect = useCallback(
(connection) => GraphUpdateCallbacks.onConnect(connection, setTempEdge, setEdges),
[setEdges, setTempEdge]
(connection) => GraphUpdateCallbacks.onConnect(connection, setTempEdge, setEdges, factory),
[setEdges, setTempEdge, factory]
);

const onEdgesDelete: OnEdgesDelete = useCallback(
Expand Down
45 changes: 40 additions & 5 deletions client/src/CombineHandlers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GroupId, GroupMap, MachineId, MachineMap, Slot } from "@server/types/core-types";
import { Group, GroupId, GroupMap, MachineId, MachineMap, Slot } from "@server/types/core-types";
import { GroupDelReq, GroupEditReq, MachineDelReq, MachineEditReq, Request } from "@server/types/messages";
import { v4 as uuidv4 } from "uuid";

Expand All @@ -7,6 +7,16 @@ import { v4 as uuidv4 } from "uuid";
* combining operation, and the final React Flow node state after combining.
*/

/***
* Determine whether the source Group can combine with the target Group
* @param source Source group
* @param target Target group
* @returns True if they can combine
*/
function canCombine(source: Group, target: Group) {
return Boolean(source.fluid) === Boolean(target.fluid)
}

/**
* Combine 1 or more source machines into a target Machine.
* - Groups from the source machines will be moved into the target machine
Expand All @@ -21,21 +31,35 @@ function combineMachines(sourceMachineIds: MachineId[], targetMachineId: Machine
const messages: Request[] = [];

const namedGroups: {[nick: string]: GroupId[]} = {}; // named groups with the same nickname will be combined into the first group of that name encountered
const namedFluidGroups: {[nick: string]: GroupId[]} = {};
const unnamedGroups: GroupId[] = []; // unnamed groups will just be added to the target without changing its slots
for (let machineId of [targetMachineId].concat(sourceMachineIds)) {
for (let groupId of machines[machineId].groups) {
const group = groups[groupId];

console.log(namedFluidGroups, group)


if (!group.nickname) {
unnamedGroups.push(groupId);
continue;
}

if (!(group.nickname in namedGroups)) {
namedGroups[group.nickname] = [];
if (group.fluid) {
if (!(group.nickname in namedFluidGroups)) {
namedFluidGroups[group.nickname] = [];
}
} else {
if (!(group.nickname in namedGroups)) {
namedGroups[group.nickname] = [];
}
}

namedGroups[group.nickname].push(groupId);
if (group.fluid) {
namedFluidGroups[group.nickname].push(groupId);
} else {
namedGroups[group.nickname].push(groupId);
}
}
}

Expand All @@ -46,13 +70,21 @@ function combineMachines(sourceMachineIds: MachineId[], targetMachineId: Machine
}
finalNamedGroups.push(groupIds[0]);
}

const finalNamedFluidGroups: GroupId[] = []; // named fluid groups that have been combined
for (const groupIds of Object.values(namedFluidGroups)) {
if (groupIds.length > 1) {
messages.push(...combineGroups(groupIds.slice(1), groupIds[0], groups))
}
finalNamedFluidGroups.push(groupIds[0]);
}

messages.push({
type: "MachineEdit",
reqId: uuidv4(),
machineId: targetMachineId,
edits: {
groups: [...finalNamedGroups, ...unnamedGroups],
groups: [...finalNamedGroups, ...finalNamedFluidGroups, ...unnamedGroups],
}
} as MachineEditReq);

Expand Down Expand Up @@ -80,6 +112,9 @@ function combineMachines(sourceMachineIds: MachineId[], targetMachineId: Machine
function combineGroups(sourceGroupIds: GroupId[], targetGroupId: GroupId, groups: GroupMap) {
const messages: Request[] = [];

// only try to combine fluid groups into fluid groups and vice versa
sourceGroupIds = sourceGroupIds.filter(sourceGroupId => canCombine(groups[sourceGroupId], groups[targetGroupId]));

// get the group's slots and tell cc to add them to the target group's slot list
const combinedSlotList: Slot[] = sourceGroupIds.reduce(
(combinedList, sourceGroupId) => [...combinedList, ...groups[sourceGroupId].slots],
Expand Down
6 changes: 5 additions & 1 deletion client/src/GraphUpdateCallbacks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@ function onEdgesDelete(
}
}

function onConnect(connection: Connection, setTempEdge: Dispatch<SetStateAction<Edge|null>>, setEdges: Dispatch<SetStateAction<Edge[]>>) {
function onConnect(connection: Connection, setTempEdge: Dispatch<SetStateAction<Edge|null>>, setEdges: Dispatch<SetStateAction<Edge[]>>, factory: Factory) {
if (!connection.source || !connection.target) return;

if (Boolean(factory.groups[connection.source].fluid) !== Boolean(factory.groups[connection.target].fluid)) {
return;
}

const tempEdge: Edge = {
id: uuidv4(),
Expand Down
3 changes: 3 additions & 0 deletions client/src/SplitHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ export function splitSlotFromGroup(slotData: ItemSlotDragData, intersections: No
const newGroupId = uuidv4();
const newGroup: Group = {
id: newGroupId,
nickname: oldGroup.nickname,
slots: [slot],
x: initialPosition.x,
y: initialPosition.y,
fluid: oldGroup.fluid,
};
const groupAddReq: GroupAddReq = {
type: "GroupAdd",
Expand Down Expand Up @@ -105,6 +107,7 @@ export function splitPeripheralFromMachine(peripheralData: PeripheralBadgeDragDa
id: uuidv4(),
nickname: oldGroup.nickname,
slots: slotsFromPeripheral,
fluid: oldGroup.fluid,
}
};
messages.push(groupAddReq);
Expand Down
5 changes: 3 additions & 2 deletions client/src/nodes/GroupNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function getHeight(numSlots: number) {

export function GroupNode({ id, selected }: NodeProps) {
const dropTarget = useDropTargetStore(state => state.dropTarget);
const { nickname, numSlots, slots } = useFactoryStore(useShallow(state => ({
const { nickname, numSlots, slots, fluid } = useFactoryStore(useShallow(state => ({
...state.factory.groups[id],
numSlots: state.factory.groups[id]?.slots.length,
})));
Expand All @@ -43,8 +43,9 @@ export function GroupNode({ id, selected }: NodeProps) {
return (
<div
className={
"react-flow__node-default w-full h-full bg-mcgui-bg p-0 rounded-sm " +
"react-flow__node-default w-full h-full p-0 rounded-sm " +
"border border-mcgui-group-border " +
(fluid ? " bg-blue-800 text-white " : " bg-mcgui-bg") +
(dropTarget?.id === id ? " !bg-green-200" : "") +
(selected ? " !bg-blue-200" : "")
}
Expand Down
4 changes: 3 additions & 1 deletion computercraft/installer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ local files = {
'sigils/logging.lua',
'sigils/machine.lua',
'sigils/machines/chest.lua',
'sigils/machines/fluidtank.lua',
'sigils/machines/generic.lua',
'sigils/pipe.lua',
'sigils/transfer-calculator.lua',
'sigils/pipeModes/fluid.lua',
'sigils/pipeModes/natural.lua',
'sigils/utils.lua',
'sigils/websocket.lua',
'sigils/sigils-config.dist.json',
Expand Down
14 changes: 10 additions & 4 deletions computercraft/sigils/factory.lua
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,11 @@ local function getPeripheralIds ()
for i, periphId in ipairs(peripheral.getNames()) do
-- add if the peripheral has an inventory and is connected via a modem
local periph = peripheral.wrap(periphId)
if periph['pushItems'] and periph.size() >= 1 and string.match(periphId, ':') then

local isInventory = periph['pushItems'] and periph.size() >= 1
local isFluidTank = periph['tanks']

if (isInventory or isFluidTank) and string.match(periphId, ':') then
table.insert(periphs, periphId)
end
end
Expand Down Expand Up @@ -441,10 +445,12 @@ local function autodetectFactory ()
}
for i, periphId in ipairs(getPeripheralIds()) do
local machine, groups = Machine.fromPeriphId(periphId)
factory.machines[machine.id] = machine
if machine then
factory.machines[machine.id] = machine

for groupId, group in pairs(groups) do
factory.groups[groupId] = group
for groupId, group in pairs(groups) do
factory.groups[groupId] = group
end
end
end

Expand Down
8 changes: 8 additions & 0 deletions computercraft/sigils/filter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ end
---@param filter string Filter to match
---@return boolean match True if match, false otherwise
local function displayNameMatch (itemDetail, filter)
if not itemDetail.displayName then -- HACK: this IF block is for fluids ONLY, which don't have displayName because CC doesn't give it to us
local itemId = string.lower(itemDetail.name)
return string.match(
itemId,
string.sub(filter, 2)
) ~= nil
end

local displayName = string.lower(itemDetail.displayName)
return string.match(displayName, filter) ~= nil
end
Expand Down
31 changes: 30 additions & 1 deletion computercraft/sigils/machine.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,41 @@
local machineTemplates = {
require('sigils.machines.chest'),
require('sigils.machines.generic'),
require('sigils.machines.fluidtank'),
}

local function addFluidTank (machine, periphId, groups)
local groupId = periphId .. ':fluids'
local fluidGroup = {
id = groupId,
slots = {
{
periphId = periphId,
slot = nil,
}
},
nickname = 'Fluid tank',
fluid = true,
}

groups[groupId] = fluidGroup
table.insert(machine.groups, groupId)
end

---Initialize a new Machine from the given peripheral ID
---@param periphId string Peripheral ID to initialize as a Machine
---@return Machine|nil machine Newly initialized Machine
---@return Group[]|nil groups Newly initialized Groups in the Machine
local function fromPeriphId (periphId)
for _, template in pairs(machineTemplates) do
if template.canInitialize(periphId) then
return template.initialize(periphId)
local machine, groups = template.initialize(periphId)

if peripheral.wrap(periphId).tanks then
addFluidTank(machine, periphId, groups)
end

return machine, groups
end
end
end
Expand Down
7 changes: 4 additions & 3 deletions computercraft/sigils/machines/chest.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ local function canInitialize (periphId)
local peripheral = peripheral.wrap(periphId)

return not not (
string.find(periphId, 'minecraft:chest_') or
peripheral.size and
(string.find(periphId, 'minecraft:chest_') or
string.find(periphId, 'minecraft:trapped_chest_') or
string.find(periphId, 'minecraft:barrel_') or
string.find(periphId, 'minecraft:dispenser_') or
string.find(periphId, 'minecraft:dropper_') or
string.find(periphId, 'minecraft:hopper_') or
(string.find(periphId, 'minecraft:') and string.find(periphId, '_shulker_box_')) or
peripheral.size() >= 8
peripheral.size() >= 8)
)
end

Expand All @@ -25,7 +26,7 @@ function initialize (periphId)
local machine = {
id = periphId,
groups = {},
nickname = nickname,
nickname = nil,
}

local groups = {}
Expand Down
32 changes: 32 additions & 0 deletions computercraft/sigils/machines/fluidtank.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---Determine if the peripheral can be initialized as ONLY any fluid tank
---(e.g. it has a fluid tank, and no inventory)
---@param periphId any
---@return boolean
local function canInitialize (periphId)
local periph = peripheral.wrap(periphId)
local isInventory = periph.size and periph.size() > 0
return periph.tanks ~= nil and not isInventory
end

---Create a Machine for the given tank-only peripheral
---This actually initializes an empty machine; machine.lua will add the fluid
---tank after.
---@param periphId any
---@return table
---@return table
local function initialize (periphId)
local machine = {
id = periphId,
groups = {},
nickname = nil,
}

local groups = {}

return machine, groups
end

return {
canInitialize = canInitialize,
initialize = initialize,
}
15 changes: 8 additions & 7 deletions computercraft/sigils/machines/generic.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,32 @@ local AUTO_GROUP_NICKNAMES = {
brewingStand = {'Bottle', 'Bottle', 'Bottle', 'Ingredient', 'Blaze Powder'},
}

---Determine if the peripheral can be initialized as a generic machine.
---Always returns true.
---Determine if the peripheral can be initialized as a generic machine with
---an inventory.
---@param periphId string Peripheral ID to check
---@return true canInitialize Always true
local function canInitialize (periphId)
return true
local periph = peripheral.wrap(periphId)
return periph.size and periph.size() > 0
end

---Create a generic Machine for the given peripheral
---The machine will have one Group for each Slot
---@param periphId any Peripheral ID to initialize as a Machine
---@return Machine machine New chest Machine
---@return Group[] groups List of groups in the Machine
function initialize (periphId)
local function initialize (periphId)
local machine = {
id = periphId,
groups = {},
nickname = nickname,
nickname = nil,
}

local groups = {}

local peripheral = peripheral.wrap(periphId)
local periph = peripheral.wrap(periphId)
-- create 1 group for each slot
for slotNbr=1, peripheral.size() do
for slotNbr=1, periph.size() do
local slot = {
periphId = periphId,
slot = slotNbr,
Expand Down
Loading
Loading