10 Commits

11 changed files with 274 additions and 25 deletions

View File

@@ -16,19 +16,13 @@
local S=minetest.get_translator("industrialtest") local S=minetest.get_translator("industrialtest")
-- \brief Prepares itemstack containing fluid storage local function createItemFluidStorageText(itemstack)
-- \param itemstack ItemStack
-- \returns bool
function industrialtest.api.prepareFluidStorageItem(itemstack)
local meta=itemstack:get_meta() local meta=itemstack:get_meta()
local def=itemstack:get_definition() local fluidCapacity=meta:get_int("industrialtest.fluidCapacity")
if industrialtest.api.itemHasFluidStorage(itemstack) or not def.groups or not def.groups._industrialtest_fluidStorage or not def._industrialtest_fluidCapacity then local fluidAmount=meta:get_int("industrialtest.fluidAmount")
return false local lowerLimit=math.floor(fluidCapacity*0.25)
end local color=(fluidAmount>lowerLimit and "#0000FF" or "#FF0000")
meta:set_int("industrialtest.fluidAmount",0) return minetest.colorize(color,S("@1 / @2 mB",fluidAmount,fluidCapacity))
meta:set_int("industrialtest.fluidCapacity",def._industrialtest_fluidCapacity)
industrialtest.api.updateItemFluidText(itemstack)
return true
end end
-- \brief Check if itemstack contains fluid storage -- \brief Check if itemstack contains fluid storage
@@ -80,8 +74,13 @@ end
-- \returns nil -- \returns nil
function industrialtest.api.updateItemFluidText(itemstack) function industrialtest.api.updateItemFluidText(itemstack)
local meta=itemstack:get_meta() local meta=itemstack:get_meta()
local def=itemstack:get_definition() if industrialtest.mtgAvailable then
meta:set_string("description",S("@1\n@2 / @3 mB",def.description,meta:get_int("industrialtest.fluidAmount"),meta:get_int("industrialtest.fluidCapacity"))) local def=itemstack:get_definition()
local fluidStorageText=createItemFluidStorageText(itemstack)
meta:set_string("description",string.format("%s\n%s",def.description,fluidStorageText))
elseif industrialtest.mclAvailable then
tt.reload_itemstack_description(itemstack)
end
itemstack:set_wear(65535-meta:get_int("industrialtest.fluidAmount")/meta:get_int("industrialtest.fluidCapacity")*65534) itemstack:set_wear(65535-meta:get_int("industrialtest.fluidAmount")/meta:get_int("industrialtest.fluidCapacity")*65534)
end end
@@ -119,3 +118,15 @@ function industrialtest.api.transferFluidToItem(srcItemstack,itemstack,amount)
industrialtest.api.updateItemFluidText(srcItemstack) industrialtest.api.updateItemFluidText(srcItemstack)
return actualFlow return actualFlow
end end
if industrialtest.mclAvailable then
tt.register_snippet(function(itemstring,toolCapabilities,itemstack)
if not itemstack then
return nil
end
if not industrialtest.api.itemHasFluidStorage(itemstack) then
return nil
end
return createItemFluidStorageText(itemstack),false
end)
end

View File

@@ -41,6 +41,102 @@ local function clampFlow(pos,flow)
return math.min(flow,newFlow) return math.min(flow,newFlow)
end end
-- \brief Finds path from pos to dest in network. Function finished if either dest is found or every node was visited
-- \param pos Vector
-- \param dest Vector
-- \returns table or nil
function industrialtest.api.findPathInNetwork(pos,dest)
local connections=industrialtest.api.getConnections(pos,"i")
if #connections==0 then
return nil
end
local workers={}
local serializedSourcePos=pos.x..","..pos.y..","..pos.z
local visitedNodes={[serializedSourcePos]=true}
for _,conn in ipairs(connections) do
local sideVector=vector.subtract(conn,pos)
table.insert(workers,{
position=conn,
direction=sideVector,
path={[1]=conn}
})
end
while #workers>0 do
for i=1,#workers do
local worker=workers[i]
local serializedPos=worker.position.x..","..worker.position.y..","..worker.position.z
if visitedNodes[serializedPos] then
table.remove(workers,i)
break
end
visitedNodes[serializedPos]=true
if worker.position.x==dest.x and worker.position.y==dest.y and worker.position.z==dest.z then
return worker.path
end
local def=minetest.registered_nodes[minetest.get_node(worker.position).name]
if def and def.groups and def.groups._industrialtest_cable then
connections=industrialtest.api.getConnections(worker.position,"i")
for j=1,#connections do
local direction=vector.subtract(connections[j],worker.position)
local oppositeDirection=vector.multiply(worker.direction,vector.new(-1,-1,-1))
if direction.x~=oppositeDirection.x or direction.y~=oppositeDirection.y or direction.z~=oppositeDirection.z then
if worker.direction.x~=direction.x or worker.direction.y~=direction.y or worker.direction.z~=direction.z then
table.insert(worker.path,worker.position)
end
for c=1,#connections do
local nextDirection=vector.subtract(connections[c],worker.position)
if c~=j and (nextDirection.x~=oppositeDirection.x or nextDirection.y~=oppositeDirection.y or nextDirection.z~=oppositeDirection.z) then
local newWorker={
position=connections[c],
direction=nextDirection,
path=table.copy(worker.path)
}
table.insert(newWorker.path,worker.position)
table.insert(workers,newWorker)
end
end
worker.direction=direction
worker.position=connections[j]
break
end
end
if #connections>2 then
break
end
else
table.remove(workers,i)
break
end
end
end
return nil
end
-- \brief Goes through path vertices specified by path running callback on each node.
-- Function finishes if either callback returns false or entire path is went over.
-- \param path table
-- \param callback function
-- \returns nil
function industrialtest.api.walkPath(path,callback)
local pos=path[1]
for i=2,#path do
local pathNode=path[i]
local direction=vector.normalize(vector.subtract(pathNode,pos))
while pos.x~=pathNode.x or pos.y~=pathNode.y or pos.z~=pathNode.z do
if not callback(pos) then
return
end
pos=vector.add(pos,direction)
end
end
end
-- \brief Transfers power from source node to it's network, if sides is set then power will be only transfered to network connected to that sides -- \brief Transfers power from source node to it's network, if sides is set then power will be only transfered to network connected to that sides
-- \param pos Vector with position of source node -- \param pos Vector with position of source node
-- \param (optional) sides table with Vectors -- \param (optional) sides table with Vectors
@@ -100,8 +196,36 @@ function industrialtest.api.powerFlow(pos,sides,flowOverride)
roomAvailable=true roomAvailable=true
end end
else else
minetest.remove_node(endpoint.position) local path=industrialtest.api.findPathInNetwork(pos,endpoint.position)
industrialtest.internal.explode(endpoint.position,2) if path and #path>0 then
table.insert(path,endpoint.position)
local removed=false
industrialtest.api.walkPath(path,function(pathPos)
local def=minetest.registered_nodes[minetest.get_node(pathPos).name]
if not def or not def.groups or not def.groups._industrialtest_cable then
return false
end
if powerDistribution>def._industrialtest_cableFlow then
removed=true
minetest.swap_node(pathPos,{
name="air"
})
minetest.remove_node(pathPos)
minetest.check_for_falling(pathPos)
minetest.sound_play("default_cool_lava",{
pos=pathPos,
max_hear_distance=5,
gain=0.7
})
end
return true
end)
if not removed and powerDistribution>endpoint.originalFlow then
minetest.remove_node(endpoint.position)
industrialtest.internal.explode(endpoint.position,2)
end
industrialtest.api.createNetworkMapForNode(pos)
end
end end
end end
end end
@@ -199,6 +323,7 @@ function industrialtest.api.createNetworkMap(pos,addCables,omit)
position=worker.position, position=worker.position,
distance=worker.distance, distance=worker.distance,
flow=math.min(worker.flow,flow), flow=math.min(worker.flow,flow),
originalFlow=flow,
side=connectionSide, side=connectionSide,
sourceSide=worker.sourceSide sourceSide=worker.sourceSide
}) })
@@ -271,6 +396,34 @@ function industrialtest.api.getNetwork(meta)
return minetest.deserialize(meta:get_string("industrialtest.network")) return minetest.deserialize(meta:get_string("industrialtest.network"))
end end
-- \brief Returns amount of power that will flow from specified network master
-- \param pos Vector
-- \returns number
function industrialtest.api.getFlowingCurrent(pos)
local meta=minetest.get_meta(pos)
if not industrialtest.api.hasPowerStorage(meta) or meta:get_int("industrialtest.powerAmount")==0 then
return 0
end
local network=industrialtest.api.getNetwork(meta)
if not network then
return 0
end
local amount=meta:get_int("industrialtest.powerAmount")
if amount==0 then
return 0
end
local demand=0
for _,endpoint in ipairs(network) do
local endpointMeta=minetest.get_meta(endpoint.position)
if industrialtest.api.hasPowerStorage(endpointMeta) then
demand=demand+math.min(endpointMeta:get_int("industrialtest.powerCapacity")-endpointMeta:get_int("industrialtest.powerAmount"),endpoint.flow)
end
end
return math.min(amount,demand)
end
-- \brief Returns connections of node with power storage. If direction is "i" only input connections will be returned, if direction is "o" only output connections -- \brief Returns connections of node with power storage. If direction is "i" only input connections will be returned, if direction is "o" only output connections
-- will be returned, if it's not provided all connections will be returned. -- will be returned, if it's not provided all connections will be returned.
-- \param pos Vector -- \param pos Vector

View File

@@ -16,6 +16,15 @@
local S=minetest.get_translator("industrialtest") local S=minetest.get_translator("industrialtest")
local function createItemPowerText(itemstack)
local meta=itemstack:get_meta()
local powerCapacity=meta:get_int("industrialtest.powerCapacity")
local powerAmount=meta:get_int("industrialtest.powerAmount")
local lowerLimit=math.floor(powerCapacity*0.25)
local color=(powerAmount>lowerLimit and "#00FFFF" or "#FF0000")
return minetest.colorize(color,S("@1 / @2 EU",powerAmount,powerCapacity))
end
-- \brief Adds power storage to metadata -- \brief Adds power storage to metadata
-- \param capacity How much EU item/node can store -- \param capacity How much EU item/node can store
-- \param flow How much EU can flow in or out item/node per industrialtest.updateDelay -- \param flow How much EU can flow in or out item/node per industrialtest.updateDelay
@@ -158,9 +167,14 @@ end
-- \returns nil -- \returns nil
function industrialtest.api.updateItemPowerText(itemstack) function industrialtest.api.updateItemPowerText(itemstack)
local meta=itemstack:get_meta() local meta=itemstack:get_meta()
local def=minetest.registered_tools[itemstack:get_name()] if industrialtest.mtgAvailable then
local desc=meta:contains("industrialtest.descriptionOverride") and meta:get_string("industrialtest.descriptionOverride") or def.description local def=minetest.registered_tools[itemstack:get_name()]
meta:set_string("description",S("@1\n@2 / @3 EU",desc,meta:get_int("industrialtest.powerAmount"),meta:get_int("industrialtest.powerCapacity"))) local desc=meta:contains("industrialtest.descriptionOverride") and meta:get_string("industrialtest.descriptionOverride") or def.description
local powerText=createItemPowerText(itemstack)
meta:set_string("description",string.format("%s\n%s",desc,powerText))
elseif industrialtest.mclAvailable then
tt.reload_itemstack_description(itemstack)
end
itemstack:set_wear(65535-meta:get_int("industrialtest.powerAmount")/meta:get_int("industrialtest.powerCapacity")*65534) itemstack:set_wear(65535-meta:get_int("industrialtest.powerAmount")/meta:get_int("industrialtest.powerCapacity")*65534)
end end
@@ -209,3 +223,15 @@ function industrialtest.api.transferPowerFromItem(srcItemstack,meta,amount)
return actualFlow return actualFlow
end end
if industrialtest.mclAvailable then
tt.register_snippet(function(itemstring,toolCapabilities,itemstack)
if not itemstack then
return nil
end
local meta=itemstack:get_meta()
if not industrialtest.api.hasPowerStorage(meta) then
return nil
end
return createItemPowerText(itemstack),false
end)
end

View File

@@ -162,12 +162,15 @@ function industrialtest.Cable.createDefinitionTable(self,description,inventoryIm
def.sound=mcl_sounds.node_sound_metal_defaults() def.sound=mcl_sounds.node_sound_metal_defaults()
end end
def.groups._industrialtest_cable=1 def.groups._industrialtest_cable=1
if insulated then
def.groups._industrialtest_insulatedCable=1
end
return def return def
end end
function industrialtest.Cable.register(self) function industrialtest.Cable.register(self)
local def=self:createDefinitionTable(self.description,self.inventoryImage,self.tile,false) local def=self:createDefinitionTable(self.description,self.inventoryImage,self.tile,self.safe)
minetest.register_node(self.name,def) minetest.register_node(self.name,def)
if self.insulated then if self.insulated then
@@ -385,6 +388,7 @@ industrialtest.internal.unpackTableInto(industrialtest.GlassFibreCable,{
inventoryImage="industrialtest_glass_fibre_cable_inv.png", inventoryImage="industrialtest_glass_fibre_cable_inv.png",
transparent=true, transparent=true,
tile="industrialtest_glass_fibre_cable.png", tile="industrialtest_glass_fibre_cable.png",
safe=true,
size=0.12, size=0.12,
flow=industrialtest.api.ivPowerFlow flow=industrialtest.api.ivPowerFlow
}) })
@@ -401,3 +405,52 @@ minetest.register_craft({
} }
}) })
-- TODO: Add glass fibre cable craft with silver ingot -- TODO: Add glass fibre cable craft with silver ingot
if industrialtest.config.electrocution then
local electrocutionDelta=0
minetest.register_globalstep(function(dtime)
electrocutionDelta=electrocutionDelta+dtime
if electrocutionDelta<industrialtest.config.updateDelay then
return
end
electrocutionDelta=0
local offsets={
vector.new(0,0,0),
vector.new(-0.7,0,0),
vector.new(-0.7,1,0),
vector.new(0,1,0),
vector.new(0.7,0,0),
vector.new(0.7,1,0),
vector.new(0,0,-0.7),
vector.new(0,1,-0.7),
vector.new(0,0,0.7),
vector.new(0,1,0.7)
}
local players=minetest.get_connected_players()
for _,player in ipairs(players) do
local pos=player:get_pos()
for _,offset in ipairs(offsets) do
local nodePos=vector.add(pos,offset)
local node=minetest.get_node(nodePos)
local def=minetest.registered_nodes[node.name]
if def and def.groups and def.groups._industrialtest_cable and not def.groups._industrialtest_insulatedCable then
local meta=minetest.get_meta(pos)
local networks=industrialtest.api.isAttachedToNetwork(meta)
if networks then
local current=0
for _,network in ipairs(networks) do
current=current+industrialtest.api.getFlowingCurrent(network)
end
if current>0 then
local removed=math.ceil(current/500)
player:set_hp(player:get_hp()-removed,"electrocution")
break
end
end
end
end
end
end)
end

View File

@@ -21,7 +21,8 @@ industrialtest={}
-- Settings -- Settings
industrialtest.config={ industrialtest.config={
updateDelay=minetest.settings:get("industrialtest.updateDelay") or 1, updateDelay=tonumber(minetest.settings:get("industrialtest.updateDelay") or "1"),
electrocution=minetest.settings:get_bool("industrialtest.electrocution",true),
developerMode=minetest.settings:get_bool("industrialtest.developerMode",false) developerMode=minetest.settings:get_bool("industrialtest.developerMode",false)
} }

View File

@@ -29,7 +29,8 @@ industrialtest.internal.unpackTableInto(industrialtest.SolarPanelBase,{
} }
}, },
hasPowerOutput=true, hasPowerOutput=true,
ioConfig="oooooo" ioConfig="oooooo",
multiplier=1
}) })
local solarPanels={} local solarPanels={}
@@ -66,7 +67,7 @@ function industrialtest.SolarPanelBase.action(self,pos)
local amount=minetest.get_natural_light(vector.offset(pos,0,1,0))/15.0 local amount=minetest.get_natural_light(vector.offset(pos,0,1,0))/15.0
local charging=amount>0.5 local charging=amount>0.5
if charging then if charging then
if industrialtest.api.addPower(meta,math.ceil(amount*self.flow))>0 then if industrialtest.api.addPower(meta,math.ceil(amount*self.flow*self.multiplier))>0 then
self:updateFormspec(pos) self:updateFormspec(pos)
end end
self:trigger(pos) self:trigger(pos)
@@ -118,7 +119,8 @@ industrialtest.internal.unpackTableInto(industrialtest.LVSolarArray,{
"industrialtest_machine_block.png" "industrialtest_machine_block.png"
}, },
capacity=industrialtest.api.lvPowerFlow*4, capacity=industrialtest.api.lvPowerFlow*4,
flow=industrialtest.api.lvPowerFlow*2 flow=industrialtest.api.lvPowerFlow,
multiplier=1.5
}) })
industrialtest.LVSolarArray:register() industrialtest.LVSolarArray:register()

View File

@@ -1,5 +1,8 @@
# This determines value how frequently machines update # This determines value how frequently machines update
industrialtest.updateDelay (Update delay) float 1.0 industrialtest.updateDelay (Update delay) float 1.0
# Whether electrocution by uninsulated cables is used
industrialtest.electrocution (Electrocution) bool true
# Enables additional utils useful when developing mod # Enables additional utils useful when developing mod
industrialtest.developerMode (Developer mode) bool false industrialtest.developerMode (Developer mode) bool false

View File

@@ -3,4 +3,4 @@
- `industrialtest_gui_water.png` was taken from Minetest Game (by Cisoun licensed with CC BY-SA 3.0) - `industrialtest_gui_water.png` was taken from Minetest Game (by Cisoun licensed with CC BY-SA 3.0)
- `industrialtest_gui_river_water.png` was taken from Minetest Game (by paramat licensed with CC BY-SA 3.0) - `industrialtest_gui_river_water.png` was taken from Minetest Game (by paramat licensed with CC BY-SA 3.0)
... rest was made either by LuanHawk, mrkubax10 or Migdyn and is licensed with CC BY 4.0 International ... rest was made either by LuanHawk, mrkubax10, HandfulOfFrogs or Migdyn and is licensed with CC BY 4.0 International

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B