many worldgen mods and gonna try technic now
This commit is contained in:
1 parent
bac6ac94a3
commit
548749cb1a
4811 files changed
+163271
-1
No files matched your search
@@ -0,0 +1,38 @@
|
||||
Technic
|
||||
=======
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Copyright (C) 2012-2014 Maciej Kasatkin (RealBadAngel)
|
||||
|
||||
Technic chests code is licensed under the GNU LGPLv2+.
|
||||
|
||||
Texture licenses:
|
||||
|
||||
BlockMen modified by Zefram (CC BY-SA 3.0):
|
||||
* technic_chernobylite_block.png
|
||||
* technic_corium_flowing_animated.png
|
||||
* technic_corium_source_animated.png
|
||||
|
||||
celeron55 (Perttu Ahola) modified by Zefram (CC BY-SA 3.0):
|
||||
* technic_bucket_corium.png
|
||||
|
||||
sdzen (Elise Staudter) (CC BY-SA 3.0):
|
||||
* most of the older 16x16 textures
|
||||
|
||||
leftshift (CC BY-SA 3.0):
|
||||
* technic_river_water_can.png
|
||||
|
||||
RealBadAngel: (WTFPL)
|
||||
* Everything else.
|
||||
|
||||
CC BY-SA 3.0: <http://creativecommons.org/licenses/by-sa/3.0/>
|
||||
|
||||
Sound licenses:
|
||||
|
||||
veikk0 (Veikko Mäkelä) (CC BY-SA 4.0):
|
||||
* technic_hv_nuclear_reactor_siren_danger_loop.ogg
|
||||
* Derived from "Nuclear alarm.wav" by Freesound.org user rene___ from <https://freesound.org/people/rene___/sounds/56778/>. Originally licensed under CC0 1.0 <https://creativecommons.org/publicdomain/zero/1.0/>
|
||||
|
||||
CC BY-SA 4.0: <https://creativecommons.org/licenses/by-sa/4.0/>
|
||||
@@ -0,0 +1,32 @@
|
||||
technic.config = technic.config or Settings(minetest.get_worldpath().."/technic.conf")
|
||||
|
||||
local conf_table = technic.config:to_table()
|
||||
|
||||
local defaults = {
|
||||
enable_mining_drill = "true",
|
||||
enable_mining_laser = "false",
|
||||
enable_flashlight = "false",
|
||||
enable_wind_mill = "false",
|
||||
enable_frames = "false",
|
||||
enable_corium_griefing = "true",
|
||||
enable_radiation_protection = "true",
|
||||
enable_radiation_throttling = "false",
|
||||
enable_entity_radiation_damage = "true",
|
||||
enable_longterm_radiation_damage = "true",
|
||||
enable_nuclear_reactor_digiline_selfdestruct = "false",
|
||||
switch_max_range = "256",
|
||||
switch_off_delay_seconds = "1800",
|
||||
network_overload_reset_time = "20",
|
||||
admin_priv = "basic_privs",
|
||||
quarry_dig_above_nodes = "3",
|
||||
quarry_max_depth = "100",
|
||||
quarry_time_limit = "5000",
|
||||
max_lag_reduction_multiplier = "0.99",
|
||||
--constant_digit_count = nil,
|
||||
}
|
||||
|
||||
for k, v in pairs(defaults) do
|
||||
if conf_table[k] == nil then
|
||||
technic.config:set(k, v)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,188 @@
|
||||
-- check if we have the necessary dependencies to allow actually using these materials in the crafts
|
||||
local mesecons_materials = minetest.get_modpath("mesecons_materials")
|
||||
|
||||
-- Remove some recipes
|
||||
-- Bronze
|
||||
minetest.clear_craft({
|
||||
type = "shapeless",
|
||||
output = "default:bronze_ingot"
|
||||
})
|
||||
-- Restore recipe for bronze block to ingots
|
||||
minetest.register_craft({
|
||||
output = "default:bronze_ingot 9",
|
||||
recipe = {
|
||||
{"default:bronzeblock"}
|
||||
}
|
||||
})
|
||||
|
||||
-- Accelerator tube
|
||||
if pipeworks.enable_accelerator_tube then
|
||||
minetest.clear_craft({
|
||||
output = "pipeworks:accelerator_tube_1",
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'pipeworks:accelerator_tube_1',
|
||||
recipe = {
|
||||
{'technic:copper_coil', 'pipeworks:tube_1', 'technic:copper_coil'},
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
-- Teleport tube
|
||||
if pipeworks.enable_teleport_tube then
|
||||
minetest.clear_craft({
|
||||
output = "pipeworks:teleport_tube_1",
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'pipeworks:teleport_tube_1',
|
||||
recipe = {
|
||||
{'default:mese_crystal', 'technic:copper_coil', 'default:mese_crystal'},
|
||||
{'pipeworks:tube_1', 'technic:control_logic_unit', 'pipeworks:tube_1'},
|
||||
{'default:mese_crystal', 'technic:copper_coil', 'default:mese_crystal'},
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
-- basic materials' brass ingot
|
||||
|
||||
minetest.clear_craft({
|
||||
output = "basic_materials:brass_ingot",
|
||||
})
|
||||
|
||||
minetest.register_craft( {
|
||||
type = "shapeless",
|
||||
output = "basic_materials:brass_ingot 9",
|
||||
recipe = { "basic_materials:brass_block" },
|
||||
})
|
||||
|
||||
-- tubes crafting recipes
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:diamond_drill_head',
|
||||
recipe = {
|
||||
{'technic:stainless_steel_ingot', 'default:diamond', 'technic:stainless_steel_ingot'},
|
||||
{'default:diamond', '', 'default:diamond'},
|
||||
{'technic:stainless_steel_ingot', 'default:diamond', 'technic:stainless_steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:green_energy_crystal',
|
||||
recipe = {
|
||||
{'default:gold_ingot', 'technic:battery', 'dye:green'},
|
||||
{'technic:battery', 'technic:red_energy_crystal', 'technic:battery'},
|
||||
{'dye:green', 'technic:battery', 'default:gold_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:blue_energy_crystal',
|
||||
recipe = {
|
||||
{'moreores:mithril_ingot', 'technic:battery', 'dye:blue'},
|
||||
{'technic:battery', 'technic:green_energy_crystal', 'technic:battery'},
|
||||
{'dye:blue', 'technic:battery', 'moreores:mithril_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:red_energy_crystal',
|
||||
recipe = {
|
||||
{'moreores:silver_ingot', 'technic:battery', 'dye:red'},
|
||||
{'technic:battery', 'basic_materials:energy_crystal_simple', 'technic:battery'},
|
||||
{'dye:red', 'technic:battery', 'moreores:silver_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:copper_coil 1',
|
||||
recipe = {
|
||||
{'basic_materials:copper_wire', 'technic:wrought_iron_ingot', 'basic_materials:copper_wire'},
|
||||
{'technic:wrought_iron_ingot', '', 'technic:wrought_iron_ingot'},
|
||||
{'basic_materials:copper_wire', 'technic:wrought_iron_ingot', 'basic_materials:copper_wire'},
|
||||
},
|
||||
replacements = {
|
||||
{"basic_materials:copper_wire", "basic_materials:empty_spool"},
|
||||
{"basic_materials:copper_wire", "basic_materials:empty_spool"},
|
||||
{"basic_materials:copper_wire", "basic_materials:empty_spool"},
|
||||
{"basic_materials:copper_wire", "basic_materials:empty_spool"}
|
||||
},
|
||||
})
|
||||
|
||||
local isolation = mesecons_materials and "mesecons_materials:fiber" or "technic:rubber"
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:lv_transformer',
|
||||
recipe = {
|
||||
{isolation, 'technic:wrought_iron_ingot', isolation},
|
||||
{'technic:copper_coil', 'technic:wrought_iron_ingot', 'technic:copper_coil'},
|
||||
{'technic:wrought_iron_ingot', 'technic:wrought_iron_ingot', 'technic:wrought_iron_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:mv_transformer',
|
||||
recipe = {
|
||||
{isolation, 'technic:carbon_steel_ingot', isolation},
|
||||
{'technic:copper_coil', 'technic:carbon_steel_ingot', 'technic:copper_coil'},
|
||||
{'technic:carbon_steel_ingot', 'technic:carbon_steel_ingot', 'technic:carbon_steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:hv_transformer',
|
||||
recipe = {
|
||||
{isolation, 'technic:stainless_steel_ingot', isolation},
|
||||
{'technic:copper_coil', 'technic:stainless_steel_ingot', 'technic:copper_coil'},
|
||||
{'technic:stainless_steel_ingot', 'technic:stainless_steel_ingot', 'technic:stainless_steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:control_logic_unit',
|
||||
recipe = {
|
||||
{'', 'basic_materials:gold_wire', ''},
|
||||
{'default:copper_ingot', 'technic:silicon_wafer', 'default:copper_ingot'},
|
||||
{'', 'technic:chromium_ingot', ''},
|
||||
},
|
||||
replacements = { {"basic_materials:gold_wire", "basic_materials:empty_spool"}, },
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:mixed_metal_ingot 9',
|
||||
recipe = {
|
||||
{'technic:stainless_steel_ingot', 'technic:stainless_steel_ingot', 'technic:stainless_steel_ingot'},
|
||||
{'default:bronze_ingot', 'default:bronze_ingot', 'default:bronze_ingot'},
|
||||
{'default:tin_ingot', 'default:tin_ingot', 'default:tin_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:carbon_cloth',
|
||||
recipe = {
|
||||
{'technic:graphite', 'technic:graphite', 'technic:graphite'}
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "technic:machine_casing",
|
||||
recipe = {
|
||||
{ "technic:cast_iron_ingot", "technic:cast_iron_ingot", "technic:cast_iron_ingot" },
|
||||
{ "technic:cast_iron_ingot", "basic_materials:brass_ingot", "technic:cast_iron_ingot" },
|
||||
{ "technic:cast_iron_ingot", "technic:cast_iron_ingot", "technic:cast_iron_ingot" },
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
minetest.register_craft({
|
||||
output = "default:dirt 2",
|
||||
type = "shapeless",
|
||||
replacements = {{"bucket:bucket_water","bucket:bucket_empty"}},
|
||||
recipe = {
|
||||
"technic:stone_dust",
|
||||
"group:leaves",
|
||||
"bucket:bucket_water",
|
||||
"group:sand",
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,15 @@
|
||||
default
|
||||
pipeworks
|
||||
technic_worldgen
|
||||
basic_materials
|
||||
bucket?
|
||||
screwdriver?
|
||||
mesecons?
|
||||
mesecons_mvps?
|
||||
digilines?
|
||||
digiline_remote?
|
||||
digistuff?
|
||||
intllib?
|
||||
unified_inventory?
|
||||
vector_extras?
|
||||
dye?
|
||||
@@ -0,0 +1,57 @@
|
||||
|
||||
|
||||
administrative world anchor
|
||||
---------------------------
|
||||
|
||||
A world anchor is an object in the Minetest world that causes the server
|
||||
to keep surrounding parts of the world running even when no players
|
||||
are nearby. It is mainly used to allow machines to run unattended:
|
||||
normally machines are suspended when not near a player. The technic
|
||||
mod supplies a form of world anchor, as a placable block, but it is not
|
||||
straightforwardly available to players. There is no recipe for it, so it
|
||||
is only available if explicitly spawned into existence by someone with
|
||||
administrative privileges. In a single-player world, the single player
|
||||
normally has administrative privileges, and can obtain a world anchor
|
||||
by entering the chat command "/give singleplayer technic:admin\_anchor".
|
||||
|
||||
The world anchor tries to force a cubical area, centered upon the anchor,
|
||||
to stay loaded. The distance from the anchor to the most distant map
|
||||
nodes that it will keep loaded is referred to as the "radius", and can be
|
||||
set in the world anchor's interaction form. The radius can be set as low
|
||||
as 0, meaning that the anchor only tries to keep itself loaded, or as high
|
||||
as 255, meaning that it will operate on a 511×511×511 cube.
|
||||
Larger radii are forbidden, to avoid typos causing the server excessive
|
||||
work; to keep a larger area loaded, use multiple anchors. Also use
|
||||
multiple anchors if the area to be kept loaded is not well approximated
|
||||
by a cube.
|
||||
|
||||
The world is always kept loaded in units of 16×16×16 cubes,
|
||||
confusingly known as "map blocks". The anchor's configured radius takes
|
||||
no account of map block boundaries, but the anchor's effect is actually to
|
||||
keep loaded each map block that contains any part of the configured cube.
|
||||
The anchor's interaction form includes a status note showing how many map
|
||||
blocks this is, and how many of those it is successfully keeping loaded.
|
||||
When the anchor is disabled, as it is upon placement, it will always
|
||||
show that it is keeping no map blocks loaded; this does not indicate
|
||||
any kind of failure.
|
||||
|
||||
The world anchor can optionally be locked. When it is locked, only
|
||||
the anchor's owner, the player who placed it, can reconfigure it or
|
||||
remove it. Only the owner can lock it. Locking an anchor is useful
|
||||
if the use of anchors is being tightly controlled by administrators:
|
||||
an administrator can set up a locked anchor and be sure that it will
|
||||
not be set by ordinary players to an unapproved configuration.
|
||||
|
||||
The server limits the ability of world anchors to keep parts of the world
|
||||
loaded, to avoid overloading the server. The total number of map blocks
|
||||
that can be kept loaded in this way is set by the server configuration
|
||||
item "max\_forceloaded\_blocks" (in minetest.conf), which defaults to
|
||||
only 16. For comparison, each player normally keeps 125 map blocks loaded
|
||||
(a radius of 32). If an enabled world anchor shows that it is failing to
|
||||
keep all the map blocks loaded that it would like to, this can be fixed
|
||||
by increasing max\_forceloaded\_blocks by the amount of the shortfall.
|
||||
|
||||
The tight limit on force-loading is the reason why the world anchor is
|
||||
not directly available to players. With the limit so low both by default
|
||||
and in common practice, the only feasible way to determine where world
|
||||
anchors should be used is for administrators to decide it directly.
|
||||
@@ -0,0 +1,144 @@
|
||||
This file is fairly incomplete. Help is welcome.
|
||||
|
||||
Tiers
|
||||
-----
|
||||
The tier is a string, currently `"LV"`, `"MV"` and `"HV"` are supported.
|
||||
|
||||
Network
|
||||
-------
|
||||
The network is the cable with the connected machine nodes. Currently the
|
||||
switching station handles the network activity.
|
||||
|
||||
Helper functions
|
||||
----------------
|
||||
* `technic.EU_string(num)`
|
||||
* Converts num to a human-readable string (see pretty_num)
|
||||
and adds the `EU` unit
|
||||
* Use this function when showing players energy values
|
||||
* `technic.pretty_num(num)`
|
||||
* Converts the number `num` to a human-readable string with SI prefixes
|
||||
* `technic.swap_node(pos, nodename)`
|
||||
* Same as `mintest.swap_node` but it only changes the nodename.
|
||||
* It uses `minetest.get_node` before swapping to ensure the new nodename
|
||||
is not the same as the current one.
|
||||
* `technic.get_or_load_node(pos)`
|
||||
* If the mapblock is loaded, it returns the node at pos,
|
||||
else it loads the chunk and returns `nil`.
|
||||
* `technic.set_RE_wear(itemstack, item_load, max_charge)`
|
||||
* If the `wear_represents` field in the item's nodedef is
|
||||
`"technic_RE_charge"`, this function does nothing.
|
||||
* `technic.refill_RE_charge(itemstack)`
|
||||
* This function fully recharges an RE chargeable item.
|
||||
* If `technic.power_tools[itemstack:get_name()]` is `nil` (or `false`), this
|
||||
function does nothing, else that value is the maximum charge.
|
||||
* The itemstack metadata is changed to contain the charge.
|
||||
* `technic.is_tier_cable(nodename, tier)`
|
||||
* Tells whether the node `nodename` is the cable of the tier `tier`.
|
||||
* `technic.get_cable_tier(nodename)`
|
||||
* Returns the tier of the cable `nodename` or `nil`.
|
||||
* `technic.trace_node_ray(pos, dir, range)`
|
||||
* Returns an iteration function (usable in the for loop) to iterate over the
|
||||
node positions along the specified ray.
|
||||
* The returned positions will not include the starting position `pos`.
|
||||
* `technic.trace_node_ray_fat(pos, dir, range)`
|
||||
* Like `technic.trace_node_ray` but includes extra positions near the ray.
|
||||
* The node ray functions are used for mining lasers.
|
||||
* `technic.config:get(name)`
|
||||
* Some configuration function
|
||||
* `technic.tube_inject_item(pos, start_pos, velocity, item)`
|
||||
* Same as `pipeworks.tube_inject_item`
|
||||
* `technic.get_charge(itemstack)` (alias `technic.get_RE_charge`)
|
||||
* Returns current charge level of tool.
|
||||
* `technic.set_charge(itemstack, charge)` (alias `technic.set_RE_charge`)
|
||||
* Sets tool charge level.
|
||||
* `technic.use_charge(itemstack, charge)` (alias `technic.use_RE_charge`)
|
||||
* Attempt to use charge and return `true`/`false` indicating success.
|
||||
* Always succeeds without checking charge level if creative is enabled.
|
||||
|
||||
Registration functions
|
||||
----------------------
|
||||
* `technic.register_power_tool(itemname, max_charge)`
|
||||
* Same as `technic.power_tools[itemname] = max_charge`
|
||||
* This function makes the craftitem `itemname` chargeable.
|
||||
* `technic.register_machine(tier, nodename, machine_type)`
|
||||
* Same as `technic.machines[tier][nodename] = machine_type`
|
||||
* Currently this is requisite to make technic recognize your node.
|
||||
* See also `Machine types`
|
||||
* `technic.register_tier(tier)`
|
||||
* Same as `technic.machines[tier] = {}`
|
||||
* See also `tiers`
|
||||
|
||||
### Specific machines
|
||||
* `technic.register_solar_array(data)`
|
||||
* data is a table
|
||||
* `technic.can_insert_unique_stack(pos, node, stack, direction)`
|
||||
* `technic.insert_object_unique_stack(pos, node, stack, direction)`
|
||||
* Functions for the parameters `can_insert` and `insert_object` to avoid
|
||||
filling multiple inventory slots with same type of item.
|
||||
|
||||
Used itemdef fields
|
||||
-------------------
|
||||
* groups:
|
||||
* `technic_<ltier> = 1` ltier is a tier in small letters; this group makes
|
||||
the node connect to the cable(s) of the right tier.
|
||||
* `technic_machine = 1` Currently used for
|
||||
* `connect_sides`
|
||||
* In addition to the default use (see lua_api.txt), this tells where the
|
||||
machine can be connected.
|
||||
#
|
||||
#
|
||||
* `technic_run(pos, node)`
|
||||
* This function is currently used to update the node.
|
||||
Modders have to manually change the information about supply etc. in the
|
||||
node metadata.
|
||||
|
||||
Machine types
|
||||
-------------
|
||||
There are currently following types:
|
||||
* `technic.receiver = "RE"` e.g. grinder
|
||||
* `technic.producer = "PR"` e.g. solar panel
|
||||
* `technic.producer_receiver = "PR_RE"` supply converter
|
||||
* `technic.battery = "BA"` e.g. LV batbox
|
||||
|
||||
Switching Station
|
||||
-----------------
|
||||
The switching station is the center of all power distribution on an electric
|
||||
network.
|
||||
|
||||
The station collects power from sources (PR), distributes it to sinks (RE),
|
||||
and uses the excess/shortfall to charge and discharge batteries (BA).
|
||||
|
||||
For now, all supply and demand values are expressed in kW.
|
||||
|
||||
It works like this:
|
||||
All PR,BA,RE nodes are indexed and tagged with the switching station.
|
||||
The tagging is a workaround to allow more stations to be built without allowing
|
||||
a cheat with duplicating power.
|
||||
All the RE nodes are queried for their current EU demand. Those which are off
|
||||
would require no or a small standby EU demand, while those which are on would
|
||||
require more.
|
||||
If the total demand is less than the available power they are all updated with
|
||||
the demand number.
|
||||
If any surplus exists from the PR nodes the batteries will be charged evenly
|
||||
with this.
|
||||
If the total demand requires draw on the batteries they will be discharged
|
||||
evenly.
|
||||
|
||||
If the total demand is more than the available power all RE nodes will be shut
|
||||
down. We have a brown-out situation.
|
||||
|
||||
Hence for now all the power distribution logic resides in this single node.
|
||||
|
||||
### Node meta usage
|
||||
Nodes connected to the network will have one or more of these parameters as meta
|
||||
data:
|
||||
* `<LV|MV|HV>_EU_supply` : Exists for PR and BA node types.
|
||||
This is the EU value supplied by the node. Output
|
||||
* `<LV|MV|HV>_EU_demand` : Exists for RE and BA node types.
|
||||
This is the EU value the node requires to run. Output
|
||||
* `<LV|MV|HV>_EU_input` : Exists for RE and BA node types.
|
||||
This is the actual EU value the network can give the node. Input
|
||||
|
||||
The reason the LV|MV|HV type is prepended to meta data is because some machine
|
||||
could require several supplies to work.
|
||||
This way the supplies are separated per network.
|
||||
@@ -0,0 +1,52 @@
|
||||
|
||||
chests
|
||||
------
|
||||
|
||||
The technic mod replaces the basic Minetest game's single type of
|
||||
chest with a range of chests that have different sizes and features.
|
||||
The chest types are identified by the materials from which they are made;
|
||||
the better chests are made from more exotic materials. The chest types
|
||||
form a linear sequence, each being (with one exception noted below)
|
||||
strictly more powerful than the preceding one. The sequence begins with
|
||||
the wooden chest from the basic game, and each later chest type is built
|
||||
by upgrading a chest of the preceding type. The chest types are:
|
||||
|
||||
1. wooden chest: 8×4 (32) slots
|
||||
2. iron chest: 9×5 (45) slots
|
||||
3. copper chest: 12×5 (60) slots
|
||||
4. silver chest: 12×6 (72) slots
|
||||
5. gold chest: 15×6 (90) slots
|
||||
6. mithril chest: 15×6 (90) slots
|
||||
|
||||
The iron and later chests have the ability to sort their contents,
|
||||
when commanded by a button in their interaction forms. Item types are
|
||||
sorted in the same order used in the unified\_inventory craft guide.
|
||||
The copper and later chests also have an auto-sorting facility that can
|
||||
be enabled from the interaction form. An auto-sorting chest automatically
|
||||
sorts its contents whenever a player closes the chest. The contents will
|
||||
then usually be in a sorted state when the chest is opened, but may not
|
||||
be if pneumatic tubes have operated on the chest while it was closed,
|
||||
or if two players have the chest open simultaneously.
|
||||
|
||||
The silver and gold chests, but not the mithril chest, have a built-in
|
||||
sign-like capability. They can be given a textual label, which will
|
||||
be visible when hovering over the chest. The gold chest, but again not
|
||||
the mithril chest, can be further labelled with a colored patch that is
|
||||
visible from a moderate distance.
|
||||
|
||||
The mithril chest is currently an exception to the upgrading system.
|
||||
It has only as many inventory slots as the preceding (gold) type, and has
|
||||
fewer of the features. It has no feature that other chests don't have:
|
||||
it is strictly weaker than the gold chest. It is planned that in the
|
||||
future it will acquire some unique features, but for now the only reason
|
||||
to use it is aesthetic.
|
||||
|
||||
The size of the largest chests is dictated by the maximum size
|
||||
of interaction form that the game engine can successfully display.
|
||||
If in the future the engine becomes capable of handling larger forms,
|
||||
by scaling them to fit the screen, the sequence of chest sizes will
|
||||
likely be revised.
|
||||
|
||||
As with the chest of the basic Minetest game, each chest type comes
|
||||
in both locked and unlocked flavors. All of the chests work with the
|
||||
pneumatic tubes of the pipeworks mod.
|
||||
@@ -0,0 +1,132 @@
|
||||
|
||||
# Technic digilines compatibility
|
||||
|
||||
This document describes the interaction of
|
||||
technic machines with the `digilines` mod (https://github.com/minetest-mods/digilines)
|
||||
|
||||
## Switching station
|
||||
|
||||
**NOTE**: make sure the channel is set accordingly, "switch" in this case
|
||||
|
||||
There are two ways getting information from the switching station:
|
||||
1. Give it a mesecon signal (eg. with a lever) and it will send always when the supply or demand changes.
|
||||
|
||||
2. Send to the switching station `"get"` or `"GET"` and it will send back.
|
||||
|
||||
The sent message is always a table containing the supply, demand and lag.
|
||||
|
||||
Example luacontroller code:
|
||||
```lua
|
||||
if event.type == "program" then
|
||||
-- start interrupt cycle
|
||||
interrupt(1)
|
||||
end
|
||||
|
||||
if event.type == "interrupt" then
|
||||
-- request stats
|
||||
digiline_send("switch", "GET")
|
||||
end
|
||||
|
||||
if event.type == "digiline" and event.channel == "switch" then
|
||||
--[[
|
||||
event.msg = {
|
||||
demand = 0, -- demand in EU's
|
||||
supply = 0, -- supply in EU's
|
||||
lag = 0 -- generated lag in microseconds
|
||||
}
|
||||
--]]
|
||||
end
|
||||
```
|
||||
|
||||
## Power monitor
|
||||
The commands:
|
||||
- `"get"`: The power monitor sends back information about the attached network
|
||||
- `"supply"`, `"demand"` and `"lag"`: Same as switching station
|
||||
- `"battery_count"`, `"battery_charge"` and `"battery_charge_max"`: Totaled information about the attached batteries.
|
||||
|
||||
|
||||
## Supply Converter
|
||||
You can send the following to it:
|
||||
- `"get"`: It will send back a table containing the fields `"enabled"`, `"power"` and `"mesecon_mode"` which are all integers.
|
||||
- `"off"`: Deactivate the supply converter.
|
||||
- `"on"`: Activate the supply converter.
|
||||
- `"toggle"`: Activate or deactivate the supply converter depending on its current state.
|
||||
- `"power "..power`: Set the amount of the power, it shall convert.
|
||||
- `"mesecon_mode "..<int>`: Set the mesecon mode.
|
||||
|
||||
## Battery Boxes
|
||||
Send to it `"get"` or `"GET"` and it will send a table back containing:
|
||||
- `demand`: A number.
|
||||
- `supply`: A number.
|
||||
- `input`: A number.
|
||||
- `charge`: A number.
|
||||
- `max_charge`: A number.
|
||||
- `src`: Itemstack made to table.
|
||||
- `dst`: Itemstack made to table.
|
||||
- `upgrade1`: Itemstack made to table.
|
||||
- `upgrade2`: Itemstack made to table.
|
||||
|
||||
|
||||
## Forcefield Emitter
|
||||
You should send a table to it containing the `command` and for some commands the `value` field.
|
||||
Some strings will automatically be made to tables:
|
||||
- `"get"` :arrow_right: `{command = "get"}`
|
||||
- `"off"` :arrow_right: `{command = "off"}`
|
||||
- `"on"` :arrow_right: `{command = "on"}`
|
||||
- `"toggle"` :arrow_right: `{command = "toggle"}`
|
||||
- `"range "..range` :arrow_right: `{command = "range", value = range}`
|
||||
- `"shape "..shape` :arrow_right: `{command = "shape", value = shape}`
|
||||
|
||||
The commands:
|
||||
- `"get"`: The forcefield emitter sends back a table containing:
|
||||
- `"enabled"`: `0` is off, `1` is on.
|
||||
- `"range"`
|
||||
- `"shape"`: `0` is spheric, `1` is cubic.
|
||||
- `"off"`: Deactivate the forcefield emitter.
|
||||
- `"on"`: Activate the forcefield emitter.
|
||||
- `"toggle"`: Activate or deactivate the forcefield emitter depending on its current state.
|
||||
- `"range"`: Set the range to `value`.
|
||||
- `"shape"`: `value` can be a number (`0` or `1`) or a string (`"sphere"` or `"cube"`).
|
||||
|
||||
|
||||
## Nuclear Reactor
|
||||
Since the nuclear reactor core can't be accessed by digiline wire because the water layer which mustn't have a hole, you need the HV Digicables to interact with it.
|
||||
|
||||
You should send a table to it containing at least the `command` field and for some commands other fields.
|
||||
|
||||
The commands:
|
||||
- `"get"`: The nuclear reactor sends back a table containing:
|
||||
- `"burn_time"`: The time in seconds how long the reactor already runs. One week after start, when it reaches 7 * 24 * 60 * 60 (=604800), the fuel is completely used.
|
||||
- `"enabled"`: A bool.
|
||||
- `"siren"`: A bool.
|
||||
- `"structure_accumulated_badness"`
|
||||
- `"rods"`: A table with 6 numbers in it, one for each fuel slot.
|
||||
- A positive value is the count of fuel rods in the slot.
|
||||
- `0` means the slot is empty.
|
||||
- A negative value means some other items are in the slot. The absolute value is the count of these items.
|
||||
- `"self_destruct"`: A setting has to be enabled to use this. The reactor will melt down after `timer` seconds or instantly.
|
||||
- `"start"`: Tries to start the reactor, `"Start successful"` is sent back on success, `"Error"` if something is wrong.
|
||||
|
||||
If the automatic start is enabled, it will always send `"fuel used"` when it uses fuel.
|
||||
|
||||
|
||||
## Quarry
|
||||
You should send a table to it containing the `command` and for some commands the `value` field.
|
||||
Some strings will automatically be converted to tables:
|
||||
- `"get"` :arrow_right: `{command = "get"}`
|
||||
- `"on"` :arrow_right: `{command = "on"}`
|
||||
- `"off"` :arrow_right: `{command = "off"}`
|
||||
- `"restart` :arrow_right: `{command = "restart"}`
|
||||
- `"radius "..value` :arrow_right: `{command = "radius", value = value}`
|
||||
|
||||
The commands:
|
||||
- `"get"`: The forcefield emitter sends back a table containing:
|
||||
- `"enabled"`: `0` is off, `1` is on.
|
||||
- `"radius"`
|
||||
- `"finished"`
|
||||
- `"dug_nodes"`
|
||||
- `"dig_level"`: A negative value means above the quarry, a positive value means below.
|
||||
- `"on"`: Activate the quarry.
|
||||
- `"off"`: Deactivate the quarry.
|
||||
- `"restart"`: Restart the quarry.
|
||||
- `"radius"`: Set the radius to `value` and restart the quarry if the radius changed.
|
||||
@@ -0,0 +1,221 @@
|
||||
|
||||
power generators
|
||||
----------------
|
||||
|
||||
### fuel-fired generators ###
|
||||
|
||||
The fuel-fired generators are electrical power generators that generate
|
||||
power by the combustion of fuel. Versions of them are available for
|
||||
all three voltages (LV, MV, and HV). These are all capable of burning
|
||||
any type of combustible fuel, such as coal. They are relatively easy
|
||||
to build, and so tend to be the first kind of generator used to power
|
||||
electrical machines. In this role they form an intermediate step between
|
||||
the directly fuel-fired machines and a more mature electrical network
|
||||
powered by means other than fuel combustion. They are also, by virtue of
|
||||
simplicity and controllability, a useful fallback or peak load generator
|
||||
for electrical networks that normally use more sophisticated generators.
|
||||
|
||||
The MV and HV fuel-fired generators can accept fuel via pneumatic tube,
|
||||
from any direction.
|
||||
|
||||
Keeping a fuel-fired generator fully fuelled is usually wasteful, because
|
||||
it will burn fuel as long as it has any, even if there is no demand for
|
||||
the electrical power that it generates. This is unlike the directly
|
||||
fuel-fired machines, which only burn fuel when they have work to do.
|
||||
To satisfy intermittent demand without waste, a fuel-fired generator must
|
||||
only be given fuel when there is either demand for the energy or at least
|
||||
sufficient battery capacity on the network to soak up the excess energy.
|
||||
|
||||
The higher-tier fuel-fired generators get much more energy out of a
|
||||
fuel item than the lower-tier ones. The difference is much more than
|
||||
is needed to overcome the inefficiency of supply converters, so it is
|
||||
worth operating fuel-fired generators at a higher tier than the machines
|
||||
being powered.
|
||||
|
||||
### solar generators ###
|
||||
|
||||
The solar generators are electrical power generators that generate power
|
||||
from sunlight. Versions of them are available for all three voltages
|
||||
(LV, MV, and HV). There are four types in total, two LV and one each
|
||||
of MV and HV, forming a sequence of four tiers. The higher-tier ones
|
||||
are each built mainly from three solar generators of the next tier down,
|
||||
and their outputs scale in rough accordance, tripling at each tier.
|
||||
|
||||
To operate, an arrayed solar generator must be at elevation +1 or above
|
||||
and have a transparent block (typically air) immediately above it.
|
||||
It will generate power only when the block above is well lit during
|
||||
daylight hours. It will generate more power at higher elevation,
|
||||
reaching maximum output at elevation +36 or higher when sunlit. The small
|
||||
solar generator has similar rules with slightly different thresholds.
|
||||
These rules are an attempt to ensure that the generator will only operate
|
||||
from sunlight, but it is actually possible to fool them to some extent
|
||||
with light sources such as meselamps.
|
||||
|
||||
### hydro generator ###
|
||||
|
||||
The hydro generator is an LV power generator that generates a respectable
|
||||
amount of power from the natural motion of water. To operate, the
|
||||
generator must be horizontally adjacent to flowing water. The power
|
||||
produced is dependent on how much flow there is across any or all four
|
||||
sides, the most flow of course coming from water that's flowing straight
|
||||
down.
|
||||
|
||||
### geothermal generator ###
|
||||
|
||||
The geothermal generator is an LV power generator that generates a small
|
||||
amount of power from the temperature difference between lava and water.
|
||||
To operate, the generator must be horizontally adjacent to both lava
|
||||
and water. It doesn't matter whether the liquids consist of source
|
||||
blocks or flowing blocks.
|
||||
|
||||
Beware that if lava and water blocks are adjacent to each other then the
|
||||
lava will be solidified into stone or obsidian. If the lava adjacent to
|
||||
the generator is thus destroyed, the generator will stop producing power.
|
||||
Currently, in the default Minetest game, lava is destroyed even if
|
||||
it is only diagonally adjacent to water. Under these circumstances,
|
||||
the only way to operate the geothermal generator is with it adjacent
|
||||
to one lava block and one water block, which are on opposite sides of
|
||||
the generator. If diagonal adjacency doesn't destroy lava, such as with
|
||||
the gloopblocks mod, then it is possible to have more than one lava or
|
||||
water block adjacent to the geothermal generator. This increases the
|
||||
generator's output, with the maximum output achieved with two adjacent
|
||||
blocks of each liquid.
|
||||
|
||||
### wind generator ###
|
||||
|
||||
The wind generator is an MV power generator that generates a moderate
|
||||
amount of energy from wind. To operate, the generator must be placed
|
||||
atop a column of at least 20 wind mill frame blocks, and must be at
|
||||
an elevation of +30 or higher. It generates more at higher elevation,
|
||||
reaching maximum output at elevation +50 or higher. Its surroundings
|
||||
don't otherwise matter; it doesn't actually need to be in open air.
|
||||
|
||||
### nuclear generator ###
|
||||
|
||||
The nuclear generator (nuclear reactor) is an HV power generator that
|
||||
generates a large amount of energy from the controlled fission of
|
||||
uranium-235. It must be fuelled, with uranium fuel rods, but consumes
|
||||
the fuel quite slowly in relation to the rate at which it is likely to
|
||||
be mined. The operation of a nuclear reactor poses radiological hazards
|
||||
to which some thought must be given. Economically, the use of nuclear
|
||||
power requires a high capital investment, and a secure infrastructure,
|
||||
but rewards the investment well.
|
||||
|
||||
Nuclear fuel is made from uranium. Natural uranium doesn't have a
|
||||
sufficiently high proportion of U-235, so it must first be enriched
|
||||
via centrifuge. Producing one unit of 3.5%-fissile uranium requires
|
||||
the input of five units of 0.7%-fissile (natural) uranium, and produces
|
||||
four units of 0.0%-fissile (fully depleted) uranium as a byproduct.
|
||||
It takes five ingots of 3.5%-fissile uranium to make each fuel rod, and
|
||||
six rods to fuel a reactor. It thus takes the input of the equivalent
|
||||
of 150 ingots of natural uranium, which can be obtained from the mining
|
||||
of 75 blocks of uranium ore, to make a full set of reactor fuel.
|
||||
|
||||
The nuclear reactor is a large multi-block structure. Only one block in
|
||||
the structure, the reactor core, is of a type that is truly specific to
|
||||
the reactor; the rest of the structure consists of blocks that have mainly
|
||||
non-nuclear uses. The reactor core is where all the generator-specific
|
||||
action happens: it is where the fuel rods are inserted, and where the
|
||||
power cable must connect to draw off the generated power.
|
||||
|
||||
The reactor structure consists of concentric layers, each a cubical
|
||||
shell, around the core. Immediately around the core is a layer of water,
|
||||
representing the reactor coolant; water blocks may be either source blocks
|
||||
or flowing blocks. Around that is a layer of stainless steel blocks,
|
||||
representing the reactor pressure vessel, and around that a layer of
|
||||
blast-resistant concrete blocks, representing a containment structure.
|
||||
It is customary, though no longer mandatory, to surround this with a
|
||||
layer of ordinary concrete blocks. The mandatory reactor structure
|
||||
makes a 7×7×7 cube, and the full customary structure a
|
||||
9×9×9 cube.
|
||||
|
||||
The layers surrounding the core don't have to be absolutely complete.
|
||||
Indeed, if they were complete, it would be impossible to cable the core to
|
||||
a power network. The cable makes it necessary to have at least one block
|
||||
missing from each surrounding layer. The water layer is only permitted
|
||||
to have one water block missing of the 26 possible. The steel layer may
|
||||
have up to two blocks missing of the 98 possible, and the blast-resistant
|
||||
concrete layer may have up to two blocks missing of the 218 possible.
|
||||
Thus it is possible to have not only a cable duct, but also a separate
|
||||
inspection hole through the solid layers. The separate inspection hole
|
||||
is of limited use: the cable duct can serve double duty.
|
||||
|
||||
Once running, the reactor core is significantly radioactive. The layers
|
||||
of reactor structure provide quite a lot of shielding, but not enough
|
||||
to make the reactor safe to be around, in two respects. Firstly, the
|
||||
shortest possible path from the core to a player outside the reactor
|
||||
is sufficiently short, and has sufficiently little shielding material,
|
||||
that it will damage the player. This only affects a player who is
|
||||
extremely close to the reactor, and close to a face rather than a vertex.
|
||||
The customary additional layer of ordinary concrete around the reactor
|
||||
adds sufficient distance and shielding to negate this risk, but it can
|
||||
also be addressed by just keeping extra distance (a little over two
|
||||
meters of air).
|
||||
|
||||
The second radiological hazard of a running reactor arises from shine
|
||||
paths; that is, specific paths from the core that lack sufficient
|
||||
shielding. The necessary cable duct, if straight, forms a perfect
|
||||
shine path, because the cable itself has no radiation shielding effect.
|
||||
Any secondary inspection hole also makes a shine path, along which the
|
||||
only shielding material is the water of the reactor coolant. The shine
|
||||
path aspect of the cable duct can be ameliorated by adding a kink in the
|
||||
cable, but this still yields paths with reduced shielding. Ultimately,
|
||||
shine paths must be managed either with specific shielding outside the
|
||||
mandatory structure, or with additional no-go areas.
|
||||
|
||||
The radioactivity of an operating reactor core makes starting up a reactor
|
||||
hazardous, and can come as a surprise because the non-operating core
|
||||
isn't radioactive at all. The radioactive damage is survivable, but it is
|
||||
normally preferable to avoid it by some care around the startup sequence.
|
||||
To start up, the reactor must have a full set of fuel inserted, have all
|
||||
the mandatory structure around it, and be cabled to a switching station.
|
||||
Only the fuel insertion requires direct access to the core, so irradiation
|
||||
of the player can be avoided by making one of the other two criteria be
|
||||
the last one satisfied. Completing the cabling to a switching station
|
||||
is the easiest to do from a safe distance.
|
||||
|
||||
Once running, the reactor will generate 100 kEU/s for a week (168 hours,
|
||||
604800 seconds), a total of 6.048 GEU from one set of fuel. After the
|
||||
week is up, it will stop generating and no longer be radioactive. It can
|
||||
then be refuelled to run for another week. It is not really intended
|
||||
to be possible to pause a running reactor, but actually disconnecting
|
||||
it from a switching station will have the effect of pausing the week.
|
||||
This will probably change in the future. A paused reactor is still
|
||||
radioactive, just not generating electrical power.
|
||||
|
||||
A running reactor can't be safely dismantled, and not only because
|
||||
dismantling the reactor implies removing the shielding that makes
|
||||
it safe to be close to the core. The mandatory parts of the reactor
|
||||
structure are not just mandatory in order to start the reactor; they're
|
||||
mandatory in order to keep it intact. If the structure around the core
|
||||
gets damaged, and remains damaged, the core will eventually melt down.
|
||||
How long there is before meltdown depends on the extent of the damage;
|
||||
if only one mandatory block is missing, meltdown will follow in 100
|
||||
seconds. While the structure of a running reactor is in a damaged state,
|
||||
heading towards meltdown, a siren built into the reactor core will sound.
|
||||
If the structure is rectified, the siren will signal all-clear. If the
|
||||
siren stops sounding without signalling all-clear, then it was stopped
|
||||
by meltdown.
|
||||
|
||||
If meltdown is imminent because of damaged reactor structure, digging the
|
||||
reactor core is not a way to avert it. Digging the core of a running
|
||||
reactor causes instant meltdown. The only way to dismantle a reactor
|
||||
without causing meltdown is to start by waiting for it to finish the
|
||||
week-long burning of its current set of fuel. Once a reactor is no longer
|
||||
operating, it can be dismantled by ordinary means, with no special risks.
|
||||
|
||||
Meltdown, if it occurs, destroys the reactor and poses a major
|
||||
environmental hazard. The reactor core melts, becoming a hot, highly
|
||||
radioactive liquid known as "corium". A single meltdown yields a single
|
||||
corium source block, where the core used to be. Corium flows, and the
|
||||
flowing corium is very destructive to whatever it comes into contact with.
|
||||
Flowing corium also randomly solidifies into a radioactive solid called
|
||||
"Chernobylite". The random solidification and random destruction of
|
||||
solid blocks means that the flow of corium is constantly changing.
|
||||
This combined with the severe radioactivity makes corium much more
|
||||
challenging to deal with than lava. If a meltdown is left to its own
|
||||
devices, it gets worse over time, as the corium works its way through
|
||||
the reactor structure and starts to flow over a variety of paths.
|
||||
It is best to tackle a meltdown quickly; the priority is to extinguish
|
||||
the corium source block, normally by dropping gravel into it. Only the
|
||||
most motivated should attempt to pick up the corium in a bucket.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 304 KiB |
@@ -0,0 +1,331 @@
|
||||
|
||||
powered machines
|
||||
----------------
|
||||
|
||||
## Overview
|
||||
Many of the important machines in Technic run on electricity, using wires to connect generators with the consuming machines. These electric circuits consist of a generator, a consumer, wiring, and a switching station. Every independent circuit requires all 4 of these elements to function. In general the machines are all connected on the bottom by wire. Machines should be placed first and then the wire placed under and around them. The wiring should automatically adjust itself to connect to each machine and adjacent wires. If the wiring looks incorrect, it's likely that it won't work so be sure to check this!
|
||||
|
||||
Circuits are also grouped into 3 different categories based on how much power they transfer and the corresponding voltage: low voltage (LV), medium voltage (MV), and high voltage (HV). The base level for all electronics is low voltage, so if voltage isn't specified for a electrical component, you may safely assume it's low voltage. Most low-voltage components are upgradable to medium- and high-voltage through further crafting. To get started, you won't need to worry about any MV or HV components, and the basic low-voltage components are fine.
|
||||
|
||||
## Getting started
|
||||
The first step to working with the more advanced machines are to get a basic electrical circuit set up for converting coal into power for other machines. This will rely on the following:
|
||||
|
||||
<img src="./images/LV_Fuel_Fired_Generator_Crafting.png"/>
|
||||
1x LV Fuel Fired Generator
|
||||
|
||||
<img src="./images/Switching_station_crafting.png"/>
|
||||
1x Switching station
|
||||
|
||||
<img src="./images/LV_cable_Crafting.png"/>
|
||||
2x LV Cable
|
||||
|
||||
The generator and switching station should be placed side-by-side with the wire underneath connecting both of them. Once this is done, additional consumers can be added to the network. A grinder or extractor are both good choices to expand the capabilities of the coal-fired smelter and coal-fired alloy furnace that you already have.
|
||||
|
||||
|
||||
### powered machine tiers ###
|
||||
|
||||
Each powered machine takes its power in some specific form, being
|
||||
either fuel-fired (burning fuel directly) or electrically powered at
|
||||
some specific voltage. There is a general progression through the
|
||||
game from using fuel-fired machines to electrical machines, and to
|
||||
higher electrical voltages. The most important kinds of machine come
|
||||
in multiple variants that are powered in different ways, so the earlier
|
||||
ones can be superseded. However, some machines are only available for
|
||||
a specific power tier, so the tier can't be entirely superseded.
|
||||
|
||||
### powered machine upgrades ###
|
||||
|
||||
Some machines have inventory slots that are used to upgrade them in
|
||||
some way. Generally, machines of MV and HV tiers have two upgrade slots,
|
||||
and machines of lower tiers (fuel-fired and LV) do not. Any item can
|
||||
be placed in an upgrade slot, but only specific items will have any
|
||||
upgrading effect. It is possible to have multiple upgrades of the same
|
||||
type, but this can't be achieved by stacking more than one upgrade item
|
||||
in one slot: it is necessary to put the same kind of item in more than one
|
||||
upgrade slot. The ability to upgrade machines is therefore very limited.
|
||||
Two kinds of upgrade are currently possible: an energy upgrade and a
|
||||
tube upgrade.
|
||||
|
||||
An energy upgrade consists of a battery item, the same kind of battery
|
||||
that serves as a mobile energy store. The effect of an energy upgrade
|
||||
is to improve in some way the machine's use of electrical energy, most
|
||||
often by making it use less energy. The upgrade effect has no relation
|
||||
to energy stored in the battery: the battery's charge level is irrelevant
|
||||
and will not be affected.
|
||||
|
||||
A tube upgrade consists of a control logic unit item. The effect of a
|
||||
tube upgrade is to make the machine able, or more able, to eject items
|
||||
it has finished with into pneumatic tubes. The machines that can take
|
||||
this kind of upgrade are in any case capable of accepting inputs from
|
||||
pneumatic tubes. These upgrades are essential in using powered machines
|
||||
as components in larger automated systems.
|
||||
|
||||
### tubes with powered machines ###
|
||||
|
||||
Generally, powered machines of MV and HV tiers can work with pneumatic
|
||||
tubes, and those of lower tiers cannot. (As an exception, the fuel-fired
|
||||
furnace from the basic Minetest game can accept inputs through tubes,
|
||||
but can't output into tubes.)
|
||||
|
||||
If a machine can accept inputs through tubes at all, then this
|
||||
is a capability of the basic machine, not requiring any upgrade.
|
||||
Most item-processing machines take only one kind of input, and in that
|
||||
case they will accept that input from any direction. This doesn't match
|
||||
how tubes visually connect to the machines: generally tubes will visually
|
||||
connect to any face except the front, but an item passing through a tube
|
||||
in front of the machine will actually be accepted into the machine.
|
||||
|
||||
A minority of machines take more than one kind of input, and in that
|
||||
case the input slot into which an arriving item goes is determined by the
|
||||
direction from which it arrives. In this case the machine may be picky
|
||||
about the direction of arriving items, associating each input type with
|
||||
a single face of the machine and not accepting inputs at all through the
|
||||
remaining faces. Again, the visual connection of tubes doesn't match:
|
||||
generally tubes will still visually connect to any face except the front,
|
||||
thus connecting to faces that neither accept inputs nor emit outputs.
|
||||
|
||||
Machines do not accept items from tubes into non-input inventory slots:
|
||||
the output slots or upgrade slots. Output slots are normally filled
|
||||
only by the processing operation of the machine, and upgrade slots must
|
||||
be filled manually.
|
||||
|
||||
Powered machines generally do not eject outputs into tubes without
|
||||
an upgrade. One tube upgrade will make them eject outputs at a slow
|
||||
rate; a second tube upgrade will increase the rate. Whether the slower
|
||||
rate is adequate depends on how it compares to the rate at which the
|
||||
machine produces outputs, and on how the machine is being used as part
|
||||
of a larger construct. The machine always ejects its outputs through a
|
||||
particular face, usually a side. Due to a bug, the side through which
|
||||
outputs are ejected is not consistent: when the machine is rotated one
|
||||
way, the direction of ejection is rotated the other way. This will
|
||||
probably be fixed some day, but because a straightforward fix would
|
||||
break half the machines already in use, the fix may be tied to some
|
||||
larger change such as free selection of the direction of ejection.
|
||||
|
||||
### battery boxes ###
|
||||
|
||||
The primary purpose of battery boxes is to temporarily store electrical
|
||||
energy to let an electrical network cope with mismatched supply and
|
||||
demand. They have a secondary purpose of charging and discharging
|
||||
powered tools. They are thus a mixture of electrical infrastructure,
|
||||
powered machine, and generator. Battery boxes connect to cables only
|
||||
from the bottom.
|
||||
|
||||
MV and HV battery boxes have upgrade slots. Energy upgrades increase
|
||||
the capacity of a battery box, each by 10% of the un-upgraded capacity.
|
||||
This increase is far in excess of the capacity of the battery that forms
|
||||
the upgrade.
|
||||
|
||||
For charging and discharging of power tools, rather than having input and
|
||||
output slots, each battery box has a charging slot and a discharging slot.
|
||||
A fully charged/discharged item stays in its slot. The rates at which a
|
||||
battery box can charge and discharge increase with voltage, so it can
|
||||
be worth building a battery box of higher tier before one has other
|
||||
infrastructure of that tier, just to get access to faster charging.
|
||||
|
||||
MV and HV battery boxes work with pneumatic tubes. An item can be input
|
||||
to the charging slot through the sides or back of the battery box, or
|
||||
to the discharging slot through the top. With a tube upgrade, fully
|
||||
charged/discharged tools (as appropriate for their slot) will be ejected
|
||||
through a side.
|
||||
|
||||
### processing machines ###
|
||||
|
||||
The furnace, alloy furnace, grinder, extractor, compressor, and centrifuge
|
||||
have much in common. Each implements some industrial process that
|
||||
transforms items into other items, and the manner in which they present
|
||||
these processes as powered machines is essentially identical.
|
||||
|
||||
Most of the processing machines operate on inputs of only a single type
|
||||
at a time, and correspondingly have only a single input slot. The alloy
|
||||
furnace is an exception: it operates on inputs of two distinct types at
|
||||
once, and correspondingly has two input slots. It doesn't matter which
|
||||
way round the alloy furnace's inputs are placed in the two slots.
|
||||
|
||||
The processing machines are mostly available in variants for multiple
|
||||
tiers. The furnace and alloy furnace are each available in fuel-fired,
|
||||
LV, and MV forms. The grinder, extractor, and compressor are each
|
||||
available in LV and MV forms. The centrifuge is the only single-tier
|
||||
processing machine, being only available in MV form. The higher-tier
|
||||
machines process items faster than the lower-tier ones, but also have
|
||||
higher power consumption, usually taking more energy overall to perform
|
||||
the same amount of processing. The MV machines have upgrade slots,
|
||||
and energy upgrades reduce their energy consumption.
|
||||
|
||||
The MV machines can work with pneumatic tubes. They accept inputs via
|
||||
tubes from any direction. For most of the machines, having only a single
|
||||
input slot, this is perfectly simple behavior. The alloy furnace is more
|
||||
complex: it will put an arriving item in either input slot, preferring to
|
||||
stack it with existing items of the same type. It doesn't matter which
|
||||
slot each of the alloy furnace's inputs is in, so it doesn't matter that
|
||||
there's no direct control over that, but there is a risk that supplying
|
||||
a lot of one item type through tubes will result in both slots containing
|
||||
the same type of item, leaving no room for the second input.
|
||||
|
||||
The MV machines can be given a tube upgrade to make them automatically
|
||||
eject output items into pneumatic tubes. The items are always ejected
|
||||
through a side, though which side it is depends on the machine's
|
||||
orientation, due to a bug. Output items are always ejected singly.
|
||||
For some machines, such as the grinder, the ejection rate with a
|
||||
single tube upgrade doesn't keep up with the rate at which items can
|
||||
be processed. A second tube upgrade increases the ejection rate.
|
||||
|
||||
The LV and fuel-fired machines do not work with pneumatic tubes, except
|
||||
that the fuel-fired furnace (actually part of the basic Minetest game)
|
||||
can accept inputs from tubes. Items arriving through the bottom of
|
||||
the furnace go into the fuel slot, and items arriving from all other
|
||||
directions go into the input slot.
|
||||
|
||||
### music player ###
|
||||
|
||||
The music player is an LV powered machine that plays audio recordings.
|
||||
It offers a selection of up to nine tracks. The technic modpack doesn't
|
||||
include specific music tracks for this purpose; they have to be installed
|
||||
separately.
|
||||
|
||||
The music player gives the impression that the music is being played in
|
||||
the Minetest world. The music only plays as long as the music player
|
||||
is in place and is receiving electrical power, and the choice of music
|
||||
is controlled by interaction with the machine. The sound also appears
|
||||
to emanate specifically from the music player: the ability to hear it
|
||||
depends on the player's distance from the music player. However, the
|
||||
game engine doesn't currently support any other positional cues for
|
||||
sound, such as attenuation, panning, or HRTF. The impression of the
|
||||
sound being located in the Minetest world is also compromised by the
|
||||
subjective nature of track choice: the specific music that is played to
|
||||
a player depends on what media the player has installed.
|
||||
|
||||
### CNC machine ###
|
||||
|
||||
The CNC machine is an LV powered machine that cuts building blocks into a
|
||||
variety of sub-block shapes that are not covered by the crafting recipes
|
||||
of the stairs mod and its variants. Most of the target shapes are not
|
||||
rectilinear, involving diagonal or curved surfaces.
|
||||
|
||||
Only certain kinds of building material can be processed in the CNC
|
||||
machine.
|
||||
|
||||
### tool workshop ###
|
||||
|
||||
The tool workshop is an MV powered machine that repairs mechanically-worn
|
||||
tools, such as pickaxes and the other ordinary digging tools. It has
|
||||
a single slot for a tool to be repaired, and gradually repairs the
|
||||
tool while it is powered. For any single tool, equal amounts of tool
|
||||
wear, resulting from equal amounts of tool use, take equal amounts of
|
||||
repair effort. Also, all repairable tools currently take equal effort
|
||||
to repair equal percentages of wear. The amount of tool use enabled by
|
||||
equal amounts of repair therefore depends on the tool type.
|
||||
|
||||
The mechanical wear that the tool workshop repairs is always indicated in
|
||||
inventory displays by a colored bar overlaid on the tool image. The bar
|
||||
can be seen to fill and change color as the tool workshop operates,
|
||||
eventually disappearing when the repair is complete. However, not every
|
||||
item that shows such a wear bar is using it to show mechanical wear.
|
||||
A wear bar can also be used to indicate charging of a power tool with
|
||||
stored electrical energy, or filling of a container, or potentially for
|
||||
all sorts of other uses. The tool workshop won't affect items that use
|
||||
wear bars to indicate anything other than mechanical wear.
|
||||
|
||||
The tool workshop has upgrade slots. Energy upgrades reduce its power
|
||||
consumption.
|
||||
|
||||
It can work with pneumatic tubes. Tools to be repaired are accepted
|
||||
via tubes from any direction. With a tube upgrade, the tool workshop
|
||||
will also eject fully-repaired tools via one side, the choice of side
|
||||
depending on the machine's orientation, as for processing machines. It is
|
||||
safe to put into the tool workshop a tool that is already fully repaired:
|
||||
assuming the presence of a tube upgrade, the tool will be quickly ejected.
|
||||
Furthermore, any item of unrepairable type will also be ejected as if
|
||||
fully repaired. (Due to a historical limitation of the basic Minetest
|
||||
game, it is impossible for the tool workshop to distinguish between a
|
||||
fully-repaired tool and any item type that never displays a wear bar.)
|
||||
|
||||
### quarry ###
|
||||
|
||||
The quarry is an HV powered machine that automatically digs out a
|
||||
large area. The region that it digs out is a cuboid with a square
|
||||
horizontal cross section, located immediately behind the quarry machine.
|
||||
The quarry's action is slow and energy-intensive, but requires little
|
||||
player effort.
|
||||
|
||||
The size of the quarry's horizontal cross section is configurable through
|
||||
the machine's interaction form. A setting referred to as "radius"
|
||||
is an integer number of meters which can vary from 2 to 8 inclusive.
|
||||
The horizontal cross section is a square with side length of twice the
|
||||
radius plus one meter, thus varying from 5 to 17 inclusive. Vertically,
|
||||
the quarry always digs from 3 m above the machine to 100 m below it,
|
||||
inclusive, a total vertical height of 104 m.
|
||||
|
||||
Whatever the quarry digs up is ejected through the top of the machine,
|
||||
as if from a pneumatic tube. Normally a tube should be placed there
|
||||
to convey the material into a sorting system, processing machines, or
|
||||
at least chests. A chest may be placed directly above the machine to
|
||||
capture the output without sorting, but is liable to overflow.
|
||||
|
||||
If the quarry encounters something that cannot be dug, such as a liquid,
|
||||
a locked chest, or a protected area, it will skip past that and attempt
|
||||
to continue digging.
|
||||
|
||||
The quarry consumes 10 kEU per block dug, which is quite a lot of energy.
|
||||
With most of what is dug being mere stone, it is usually not economically
|
||||
favorable to power a quarry from anything other than solar power.
|
||||
In particular, one cannot expect to power a quarry by burning the coal
|
||||
that it digs up.
|
||||
|
||||
Given sufficient power, the quarry digs at a rate of one block per second.
|
||||
This is rather tedious to wait for. Unfortunately, leaving the quarry
|
||||
unattended normally means that the Minetest server won't keep the machine
|
||||
running: it needs a player nearby. This can be resolved by using a world
|
||||
anchor. The digging is still quite slow, and independently of whether a
|
||||
world anchor is used the digging can be speeded up by placing multiple
|
||||
quarry machines with overlapping digging areas. Four can be placed to
|
||||
dig identical areas, one on each side of the square cross section.
|
||||
|
||||
The quarry can be toggled on and off with a mesecons signal.
|
||||
|
||||
### forcefield emitter ###
|
||||
|
||||
The forcefield emitter is an HV powered machine that generates a
|
||||
forcefield reminiscent of those seen in many science-fiction stories.
|
||||
|
||||
The emitter can be configured to generate a forcefield of either
|
||||
spherical or cubical shape, in either case centered on the emitter.
|
||||
The size of the forcefield is configured using a radius parameter that
|
||||
is an integer number of meters which can vary from 5 to 20 inclusive.
|
||||
For a spherical forcefield this is simply the radius of the forcefield;
|
||||
for a cubical forcefield it is the distance from the emitter to the
|
||||
center of each square face.
|
||||
|
||||
The power drawn by the emitter is proportional to the surface area of
|
||||
the forcefield being generated. A spherical forcefield is therefore the
|
||||
cheapest way to enclose a specified volume of space with a forcefield,
|
||||
if the shape of the space doesn't matter. A cubical forcefield is less
|
||||
efficient at enclosing volume, but is cheaper than the larger spherical
|
||||
forcefield that would be required if it is necessary to enclose a
|
||||
cubical space.
|
||||
|
||||
The emitter is normally controlled merely through its interaction form,
|
||||
which has an enable/disable toggle. However, it can also (via the form)
|
||||
be placed in a mesecon-controlled mode. If mesecon control is enabled,
|
||||
the emitter must be receiving a mesecon signal in addition to being
|
||||
manually enabled, in order for it to generate the forcefield.
|
||||
|
||||
The forcefield itself behaves largely as if solid, despite being
|
||||
immaterial: it cannot be traversed, and prevents access to blocks behind
|
||||
it. It is transparent, but not totally invisible. It cannot be dug.
|
||||
Some effects can pass through it, however, such as the beam of a mining
|
||||
laser, and explosions. In fact, explosions as currently implemented by
|
||||
the tnt mod actually temporarily destroy the forcefield itself; the tnt
|
||||
mod assumes too much about the regularity of node types.
|
||||
|
||||
The forcefield occupies space that would otherwise have been air, but does
|
||||
not replace or otherwise interfere with materials that are solid, liquid,
|
||||
or otherwise not just air. If such an object blocking the forcefield is
|
||||
removed, the forcefield will quickly extend into the now-available space,
|
||||
but it does not do so instantly: there is a brief moment when the space
|
||||
is air and can be traversed.
|
||||
|
||||
It is possible to have a doorway in a forcefield, by placing in advance,
|
||||
in space that the forcefield would otherwise occupy, some non-air blocks
|
||||
that can be walked through. For example, a door suffices, and can be
|
||||
opened and closed while the forcefield is in place.
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
# Technic mesecons compatibility
|
||||
|
||||
This document describes the interaction of
|
||||
technic machines with the `mesecons` mod (https://github.com/minetest-mods/mesecons)
|
||||
|
||||
## HV Quarry
|
||||
|
||||
* **On-Action**: Enables the quarry
|
||||
* **Off-Action**: Disables the quarry
|
||||
@@ -0,0 +1,67 @@
|
||||
|
||||
electrical power
|
||||
----------------
|
||||
|
||||
Most machines in technic are electrically powered. To operate them it is
|
||||
necessary to construct an electrical power network. The network links
|
||||
together power generators and power-consuming machines, connecting them
|
||||
using power cables.
|
||||
|
||||
There are three tiers of electrical networking: low voltage (LV),
|
||||
medium voltage (MV), and high voltage (HV). Each network must operate
|
||||
at a single voltage, and most electrical items are specific to a single
|
||||
voltage. Generally, the machines of higher tiers are more powerful,
|
||||
but consume more energy and are more expensive to build, than machines
|
||||
of lower tiers. It is normal to build networks of all three tiers,
|
||||
in ascending order as one progresses through the game, but it is not
|
||||
strictly necessary to do this. Building HV equipment requires some parts
|
||||
that can only be manufactured using electrical machines, either LV or MV,
|
||||
so it is not possible to build an HV network first, but it is possible
|
||||
to skip either LV or MV on the way to HV.
|
||||
|
||||
Each voltage has its own cable type, with distinctive insulation. Cable
|
||||
segments connect to each other and to compatible machines automatically.
|
||||
Incompatible electrical items don't connect. All non-cable electrical
|
||||
items must be connected via cable: they don't connect directly to each
|
||||
other. Most electrical items can connect to cables in any direction,
|
||||
but there are a couple of important exceptions noted below.
|
||||
|
||||
To be useful, an electrical network must connect at least one power
|
||||
generator to at least one power-consuming machine. In addition to these
|
||||
items, the network must have a "switching station" in order to operate:
|
||||
no energy will flow without one. Unlike most electrical items, the
|
||||
switching station is not voltage-specific: the same item will manage
|
||||
a network of any tier. However, also unlike most electrical items,
|
||||
it is picky about the direction in which it is connected to the cable:
|
||||
the cable must be directly below the switching station.
|
||||
|
||||
Hovering over a network's switching station will show the aggregate energy
|
||||
supply and demand, which is useful for troubleshooting. Electrical energy
|
||||
is measured in "EU", and power (energy flow) in EU per second (EU/s).
|
||||
Energy is shifted around a network instantaneously once per second.
|
||||
|
||||
In a simple network with only generators and consumers, if total
|
||||
demand exceeds total supply then no energy will flow, the machines
|
||||
will do nothing, and the generators' output will be lost. To handle
|
||||
this situation, it is recommended to add a battery box to the network.
|
||||
A battery box will store generated energy, and when enough has been
|
||||
stored to run the consumers for one second it will deliver it to the
|
||||
consumers, letting them run part-time. It also stores spare energy
|
||||
when supply exceeds demand, to let consumers run full-time when their
|
||||
demand occasionally peaks above the supply. More battery boxes can
|
||||
be added to cope with larger periods of mismatched supply and demand,
|
||||
such as those resulting from using solar generators (which only produce
|
||||
energy in the daytime).
|
||||
|
||||
When there are electrical networks of multiple tiers, it can be appealing
|
||||
to generate energy on one tier and transfer it to another. The most
|
||||
direct way to do this is with the "supply converter", which can be
|
||||
directly wired into two networks. It is another tier-independent item,
|
||||
and also particular about the direction of cable connections: it must
|
||||
have the cable of one network directly above, and the cable of another
|
||||
network directly below. The supply converter demands 10000 EU/s from
|
||||
the network above, and when this network gives it power it supplies 9000
|
||||
EU/s to the network below. Thus it is only 90% efficient, unlike most of
|
||||
the electrical system which is 100% efficient in moving energy around.
|
||||
To transfer more than 10000 EU/s between networks, connect multiple
|
||||
supply converters in parallel.
|
||||
@@ -0,0 +1,105 @@
|
||||
|
||||
industrial processes
|
||||
--------------------
|
||||
|
||||
### alloying ###
|
||||
|
||||
In technic, alloying is a way of combining items to create other items,
|
||||
distinct from standard crafting. Alloying always uses inputs of exactly
|
||||
two distinct types, and produces a single output. Like cooking, which
|
||||
takes a single input, it is performed using a powered machine, known
|
||||
generically as an "alloy furnace". An alloy furnace always has two
|
||||
input slots, and it doesn't matter which way round the two ingredients
|
||||
are placed in the slots. Many alloying recipes require one or both
|
||||
slots to contain a stack of more than one of the ingredient item: the
|
||||
quantity required of each ingredient is part of the recipe.
|
||||
|
||||
As with the furnaces used for cooking, there are multiple kinds of alloy
|
||||
furnace, powered in different ways. The most-used alloy furnaces are
|
||||
electrically powered. There is also an alloy furnace that is powered
|
||||
by directly burning fuel, just like the basic cooking furnace. Building
|
||||
almost any electrical machine, including the electrically-powered alloy
|
||||
furnaces, requires a machine casing component, one ingredient of which
|
||||
is brass, an alloy. It is therefore necessary to use the fuel-fired
|
||||
alloy furnace in the early part of the game, on the way to building
|
||||
electrical machinery.
|
||||
|
||||
Alloying recipes are mainly concerned with metals. These recipes
|
||||
combine a base metal with some other element, most often another metal,
|
||||
to produce a new metal. This is discussed in the section on metal.
|
||||
There are also a few alloying recipes in which the base ingredient is
|
||||
non-metallic, such as the recipe for the silicon wafer.
|
||||
|
||||
### grinding, extracting, and compressing ###
|
||||
|
||||
Grinding, extracting, and compressing are three distinct, but very
|
||||
similar, ways of converting one item into another. They are all quite
|
||||
similar to the cooking found in the basic Minetest game. Each uses
|
||||
an input consisting of a single item type, and produces a single
|
||||
output. They are all performed using powered machines, respectively
|
||||
known generically as a "grinder", "extractor", and "compressor".
|
||||
Some compressing recipes require the input to be a stack of more than
|
||||
one of the input item: the quantity required is part of the recipe.
|
||||
Grinding and extracting recipes never require such a stacked input.
|
||||
|
||||
There are multiple kinds of grinder, extractor, and compressor. Unlike
|
||||
cooking furnaces and alloy furnaces, there are none that directly burn
|
||||
fuel; they are all electrically powered.
|
||||
|
||||
Grinding recipes always produce some kind of dust, loosely speaking,
|
||||
as output. The most important grinding recipes are concerned with metals:
|
||||
every metal lump or ingot can be ground into metal dust. Coal can also
|
||||
be ground into dust, and burning the dust as fuel produces much more
|
||||
energy than burning the original coal lump. There are a few other
|
||||
grinding recipes that make block types from the basic Minetest game
|
||||
more interconvertible: standard stone can be ground to standard sand,
|
||||
desert stone to desert sand, cobblestone to gravel, and gravel to dirt.
|
||||
|
||||
Extracting is a miscellaneous category, used for a small group
|
||||
of processes that just don't fit nicely anywhere else. (Its name is
|
||||
notably vaguer than those of the other kinds of processing.) It is used
|
||||
for recipes that produce dye, mainly from flowers. (However, for those
|
||||
recipes using flowers, the basic Minetest game provides parallel crafting
|
||||
recipes that are easier to use and produce more dye, and those recipes
|
||||
are not suppressed by technic.) Its main use is to generate rubber from
|
||||
raw latex, which it does three times as efficiently as merely cooking
|
||||
the latex. Extracting was also formerly used for uranium enrichment for
|
||||
use as nuclear fuel, but this use has been superseded by a new enrichment
|
||||
system using the centrifuge.
|
||||
|
||||
Compressing recipes are mainly used to produce a few relatively advanced
|
||||
artificial item types, such as the copper and carbon plates used in
|
||||
advanced machine recipes. There are also a couple of compressing recipes
|
||||
making natural block types more interconvertible.
|
||||
|
||||
### centrifuging ###
|
||||
|
||||
Centrifuging is another way of using a machine to convert items.
|
||||
Centrifuging takes an input of a single item type, and produces outputs
|
||||
of two distinct types. The input may be required to be a stack of
|
||||
more than one of the input item: the quantity required is part of
|
||||
the recipe. Centrifuging is only performed by a single machine type,
|
||||
the MV (electrically-powered) centrifuge.
|
||||
|
||||
Currently, centrifuging recipes don't appear in the unified\_inventory
|
||||
craft guide, because unified\_inventory can't yet handle recipes with
|
||||
multiple outputs.
|
||||
|
||||
Generally, centrifuging separates the input item into constituent
|
||||
substances, but it can only work when the input is reasonably fluid,
|
||||
and in marginal cases it is quite destructive to item structure.
|
||||
(In real life, centrifuges require their input to be mainly fluid, that
|
||||
is either liquid or gas. Few items in the game are described as liquid
|
||||
or gas, so the concept of the centrifuge is stretched a bit to apply to
|
||||
finely-divided solids.)
|
||||
|
||||
The main use of centrifuging is in uranium enrichment, where it
|
||||
separates the isotopes of uranium dust that otherwise appears uniform.
|
||||
Enrichment is a necessary process before uranium can be used as nuclear
|
||||
fuel, and the radioactivity of uranium blocks is also affected by its
|
||||
isotopic composition.
|
||||
|
||||
A secondary use of centrifuging is to separate the components of
|
||||
metal alloys. This can only be done using the dust form of the alloy.
|
||||
It recovers both components of binary metal/metal alloys. It can't
|
||||
recover the carbon from steel or cast iron.
|
||||
@@ -0,0 +1,136 @@
|
||||
|
||||
radioactivity
|
||||
-------------
|
||||
|
||||
The technic mod adds radioactivity to the game, as a hazard that can
|
||||
harm player characters. Certain substances in the game are radioactive,
|
||||
and when placed as blocks in the game world will damage nearby players.
|
||||
Conversely, some substances attenuate radiation, and so can be used
|
||||
for shielding. The radioactivity system is based on reality, but is
|
||||
not an attempt at serious simulation: like the rest of the game, it has
|
||||
many simplifications and deliberate deviations from reality in the name
|
||||
of game balance.
|
||||
|
||||
In real life radiological hazards can be roughly divided into three
|
||||
categories based on the time scale over which they act: prompt radiation
|
||||
damage (such as radiation burns) that takes effect immediately; radiation
|
||||
poisoning that becomes visible in hours and lasts weeks; and cumulative
|
||||
effects such as increased cancer risk that operate over decades.
|
||||
The game's version of radioactivity causes only prompt damage, not
|
||||
any delayed effects. Damage comes in the abstracted form of removing
|
||||
the player's hit points, and is immediately visible to the player.
|
||||
As with all other kinds of damage in the game, the player can restore
|
||||
the hit points by eating food items. High-nutrition foods, such as the
|
||||
pie baskets supplied by the bushes\_classic mod, are a useful tool in
|
||||
dealing with radiological hazards.
|
||||
|
||||
Only a small range of items in the game are radioactive. From the technic
|
||||
mod, the only radioactive items are uranium ore, refined uranium blocks,
|
||||
nuclear reactor cores (when operating), and the materials released when
|
||||
a nuclear reactor melts down. Other mods can plug into the technic
|
||||
system to make their own block types radioactive. Radioactive items
|
||||
are harmless when held in inventories. They only cause radiation damage
|
||||
when placed as blocks in the game world.
|
||||
|
||||
The rate at which damage is caused by a radioactive block depends on the
|
||||
distance between the source and the player. Distance matters because the
|
||||
damaging radiation is emitted equally in all directions by the source,
|
||||
so with distance it spreads out, so less of it will strike a target
|
||||
of any specific size. The amount of radiation absorbed by a target
|
||||
thus varies in proportion to the inverse square of the distance from
|
||||
the source. The game imitates this aspect of real-life radioactivity,
|
||||
but with some simplifications. While in real life the inverse square law
|
||||
is only really valid for sources and targets that are small relative to
|
||||
the distance between them, in the game it is applied even when the source
|
||||
and target are large and close together. Specifically, the distance is
|
||||
measured from the center of the radioactive block to the abdomen of the
|
||||
player character. For extremely close encounters, such as where the
|
||||
player swims in a radioactive liquid, there is an enforced lower limit
|
||||
on the effective distance.
|
||||
|
||||
Different types of radioactive block emit different amounts of radiation.
|
||||
The least radioactive of the radioactive block types is uranium ore,
|
||||
which causes 0.25 HP/s damage to a player 1 m away. A block of refined
|
||||
but unenriched uranium, as an example, is nine times as radioactive,
|
||||
and so will cause 2.25 HP/s damage to a player 1 m away. By the inverse
|
||||
square law, the damage caused by that uranium block reduces by a factor
|
||||
of four at twice the distance, that is to 0.5625 HP/s at a distance of 2
|
||||
m, or by a factor of nine at three times the distance, that is to 0.25
|
||||
HP/s at a distance of 3 m. Other radioactive block types are far more
|
||||
radioactive than these: the most radioactive of all, the result of a
|
||||
nuclear reactor melting down, is 1024 times as radioactive as uranium ore.
|
||||
|
||||
Uranium blocks are radioactive to varying degrees depending on their
|
||||
isotopic composition. An isotope being fissile, and thus good as
|
||||
reactor fuel, is essentially uncorrelated with it being radioactive.
|
||||
The fissile U-235 is about six times as radioactive than the non-fissile
|
||||
U-238 that makes up the bulk of natural uranium, so one might expect that
|
||||
enriching from 0.7% fissile to 3.5% fissile (or depleting to 0.0%) would
|
||||
only change the radioactivity of uranium by a few percent. But actually
|
||||
the radioactivity of enriched uranium is dominated by the non-fissile
|
||||
U-234, which makes up only about 50 parts per million of natural uranium
|
||||
but is about 19000 times more radioactive than U-238. The radioactivity
|
||||
of natural uranium comes just about half from U-238 and half from U-234,
|
||||
and the uranium gets enriched in U-234 along with the U-235. This makes
|
||||
3.5%-fissile uranium about three times as radioactive as natural uranium,
|
||||
and 0.0%-fissile uranium about half as radioactive as natural uranium.
|
||||
|
||||
Radiation is attenuated by the shielding effect of material along the
|
||||
path between the radioactive block and the player. In general, only
|
||||
blocks of homogeneous material contribute to the shielding effect: for
|
||||
example, a block of solid metal has a shielding effect, but a machine
|
||||
does not, even though the machine's ingredients include a metal case.
|
||||
The shielding effect of each block type is based on the real-life
|
||||
resistance of the material to ionising radiation, but for game balance
|
||||
the effectiveness of shielding is scaled down from real life, more so
|
||||
for stronger shield materials than for weaker ones. Also, whereas in
|
||||
real life materials have different shielding effects against different
|
||||
types of radiation, the game only has one type of damaging radiation,
|
||||
and so only one set of shielding values.
|
||||
|
||||
Almost any solid or liquid homogeneous material has some shielding value.
|
||||
At the low end of the scale, 5 meters of wooden planks nearly halves
|
||||
radiation, though in that case the planks probably contribute more
|
||||
to safety by forcing the player to stay 5 m further away from the
|
||||
source than by actual attenuation. Dirt halves radiation in 2.4 m,
|
||||
and stone in 1.7 m. When a shield must be deliberately constructed,
|
||||
the preferred materials are metals, the denser the better. Iron and
|
||||
steel halve radiation in 1.1 m, copper in 1.0 m, and silver in 0.95 m.
|
||||
Lead would halve in 0.69 m (its in-game shielding value is 80). Gold halves radiation
|
||||
in 0.53 m (factor of 3.7 per meter), but is a bit scarce to use for
|
||||
this purpose. Uranium halves radiation in 0.31 m (factor of 9.4 per
|
||||
meter), but is itself radioactive. The very best shielding in the game
|
||||
is nyancat material (nyancats and their rainbow blocks), which halves
|
||||
radiation in 0.22 m (factor of 24 per meter), but is extremely scarce. See [technic/technic/radiation.lua](https://github.com/minetest-technic/technic/blob/master/technic/radiation.lua) for the in-game shielding values, which are different from real-life values.
|
||||
|
||||
If the theoretical radiation damage from a particular source is
|
||||
sufficiently small, due to distance and shielding, then no damage at all
|
||||
will actually occur. This means that for any particular radiation source
|
||||
and shielding arrangement there is a safe distance to which a player can
|
||||
approach without harm. The safe distance is where the radiation damage
|
||||
would theoretically be 0.25 HP/s. This damage threshold is applied
|
||||
separately for each radiation source, so to be safe in a multi-source
|
||||
situation it is only necessary to be safe from each source individually.
|
||||
|
||||
The best way to use uranium as shielding is in a two-layer structure,
|
||||
of uranium and some non-radioactive material. The uranium layer should
|
||||
be nearer to the primary radiation source and the non-radioactive layer
|
||||
nearer to the player. The uranium provides a great deal of shielding
|
||||
against the primary source, and the other material shields against
|
||||
the uranium layer. Due to the damage threshold mechanism, a meter of
|
||||
dirt is sufficient to shield fully against a layer of fully-depleted
|
||||
(0.0%-fissile) uranium. Obviously this is only worthwhile when the
|
||||
primary radiation source is more radioactive than a uranium block.
|
||||
|
||||
When constructing permanent radiation shielding, it is necessary to
|
||||
pay attention to the geometry of the structure, and particularly to any
|
||||
holes that have to be made in the shielding, for example to accommodate
|
||||
power cables. Any hole that is aligned with the radiation source makes a
|
||||
"shine path" through which a player may be irradiated when also aligned.
|
||||
Shine paths can be avoided by using bent paths for cables, passing
|
||||
through unaligned holes in multiple shield layers. If the desired
|
||||
shielding effect depends on multiple layers, a hole in one layer still
|
||||
produces a partial shine path, along which the shielding is reduced,
|
||||
so the positioning of holes in each layer must still be considered.
|
||||
Tricky shine paths can also be addressed by just keeping players out of
|
||||
the dangerous area.
|
||||
@@ -0,0 +1,7 @@
|
||||
Technic provides additional resources for building these machines.
|
||||
|
||||
## Latex
|
||||
|
||||
<img src="../textures/technic_raw_latex.png"/>
|
||||
|
||||
Latex is used for manufacturing rubber, which is heavily used for the medium- and high-voltage components within Technic. Latex can be harvested directly from rubber trees (look for the pale green/seafoam leaves) using the tree tap like any other tool. Rubber trees regenerate their latex supplies after about a day.
|
||||
@@ -0,0 +1,490 @@
|
||||
|
||||
substances
|
||||
----------
|
||||
|
||||
### ore ###
|
||||
|
||||
The technic mod makes extensive use of not just the default ores but also
|
||||
some that are added by mods. You will need to mine for all the ore types
|
||||
in the course of the game. Each ore type is found at a specific range of
|
||||
elevations, and while the ranges mostly overlap, some have non-overlapping
|
||||
ranges, so you will ultimately need to mine at more than one elevation
|
||||
to find all the ores. Also, because one of the best elevations to mine
|
||||
at is very deep, you will be unable to mine there early in the game.
|
||||
|
||||
Elevation is measured in meters, relative to a reference plane that
|
||||
is not quite sea level. (The standard sea level is at an elevation
|
||||
of about +1.4.) Positive elevations are above the reference plane and
|
||||
negative elevations below. Because elevations are always described this
|
||||
way round, greater numbers when higher, we avoid the word "depth".
|
||||
|
||||
The ores that matter in technic are coal, iron, copper, tin, zinc,
|
||||
chromium, uranium, silver, gold, mithril, mese, and diamond.
|
||||
|
||||
Coal is part of the basic Minetest game. It is found from elevation
|
||||
+64 downwards, so is available right on the surface at the start of
|
||||
the game, but it is far less abundant above elevation 0 than below.
|
||||
It is initially used as a fuel, driving important machines in the early
|
||||
part of the game. It becomes less important as a fuel once most of your
|
||||
machines are electrically powered, but burning fuel remains a way to
|
||||
generate electrical power. Coal is also used, usually in dust form, as
|
||||
an ingredient in alloying recipes, wherever elemental carbon is required.
|
||||
|
||||
Iron is part of the basic Minetest game. It is found from elevation
|
||||
+2 downwards, and its abundance increases in stages as one descends,
|
||||
reaching its maximum from elevation -64 downwards. It is a common metal,
|
||||
used frequently as a structural component. In technic, unlike the basic
|
||||
game, iron is used in multiple forms, mainly alloys based on iron and
|
||||
including carbon (coal).
|
||||
|
||||
Copper is part of the basic Minetest game (having migrated there from
|
||||
moreores). It is found from elevation -16 downwards, but is more abundant
|
||||
from elevation -64 downwards. It is a common metal, used either on its
|
||||
own for its electrical conductivity, or as the base component of alloys.
|
||||
Although common, it is very heavily used, and most of the time it will
|
||||
be the material that most limits your activity.
|
||||
|
||||
Tin is part of the basic Minetest game (having migrated there from
|
||||
moreores). It is found from elevation +8 downwards, with no
|
||||
elevation-dependent variations in abundance beyond that point.
|
||||
It is a common metal. Its main use in pure form is as a component
|
||||
of electrical batteries. Apart from that its main purpose is
|
||||
as the secondary ingredient in bronze (the base being copper), but bronze
|
||||
is itself little used. Its abundance is well in excess of its usage,
|
||||
so you will usually have a surplus of it.
|
||||
|
||||
Zinc is supplied by technic. It is found from elevation +2 downwards,
|
||||
with no elevation-dependent variations in abundance beyond that point.
|
||||
It is a common metal. Its main use is as the secondary ingredient
|
||||
in brass (the base being copper), but brass is itself little used.
|
||||
Its abundance is well in excess of its usage, so you will usually have
|
||||
a surplus of it.
|
||||
|
||||
Chromium is supplied by technic. It is found from elevation -100
|
||||
downwards, with no elevation-dependent variations in abundance beyond
|
||||
that point. It is a moderately common metal. Its main use is as the
|
||||
secondary ingredient in stainless steel (the base being iron).
|
||||
|
||||
Uranium is supplied by technic. It is found only from elevation -80 down
|
||||
to -300; using it therefore requires one to mine above elevation -300 even
|
||||
though deeper mining is otherwise more productive. It is a moderately
|
||||
common metal, useful only for reasons related to radioactivity: it forms
|
||||
the fuel for nuclear reactors, and is also one of the best radiation
|
||||
shielding materials available. It is not difficult to find enough uranium
|
||||
ore to satisfy these uses. Beware that the ore is slightly radioactive:
|
||||
it will slightly harm you if you stand as close as possible to it.
|
||||
It is safe when more than a meter away or when mined.
|
||||
|
||||
Silver is supplied by the moreores mod. It is found from elevation -2
|
||||
downwards, with no elevation-dependent variations in abundance beyond
|
||||
that point. It is a semi-precious metal. It is little used, being most
|
||||
notably used in electrical items due to its conductivity, being the best
|
||||
conductor of all the pure elements.
|
||||
|
||||
Gold is part of the basic Minetest game (having migrated there from
|
||||
moreores). It is found from elevation -64 downwards, but is more
|
||||
abundant from elevation -256 downwards. It is a precious metal. It is
|
||||
little used, being most notably used in electrical items due to its
|
||||
combination of good conductivity (third best of all the pure elements)
|
||||
and corrosion resistance.
|
||||
|
||||
Mithril is supplied by the moreores mod. It is found from elevation
|
||||
-512 downwards, the deepest ceiling of any minable substance, with
|
||||
no elevation-dependent variations in abundance beyond that point.
|
||||
It is a rare precious metal, and unlike all the other metals described
|
||||
here it is entirely fictional, being derived from J. R. R. Tolkien's
|
||||
Middle-Earth setting. It is little used.
|
||||
|
||||
Mese is part of the basic Minetest game. It is found from elevation
|
||||
-64 downwards. The ore is more abundant from elevation -256 downwards,
|
||||
and from elevation -1024 downwards there are also occasional blocks of
|
||||
solid mese (each yielding as much mese as nine blocks of ore). It is a
|
||||
precious gemstone, and unlike diamond it is entirely fictional. It is
|
||||
used in many recipes, though mainly not in large quantities, wherever
|
||||
some magical quality needs to be imparted.
|
||||
|
||||
Diamond is part of the basic Minetest game (having migrated there from
|
||||
technic). It is found from elevation -128 downwards, but is more abundant
|
||||
from elevation -256 downwards. It is a precious gemstone. It is used
|
||||
moderately, mainly for reasons connected to its extreme hardness.
|
||||
|
||||
### rock ###
|
||||
|
||||
In addition to the ores, there are multiple kinds of rock that need to be
|
||||
mined in their own right, rather than for minerals. The rock types that
|
||||
matter in technic are standard stone, desert stone, marble, and granite.
|
||||
|
||||
Standard stone is part of the basic Minetest game. It is extremely
|
||||
common. As in the basic game, when dug it yields cobblestone, which can
|
||||
be cooked to turn it back into standard stone. Cobblestone is used in
|
||||
recipes only for some relatively primitive machines. Standard stone is
|
||||
used in a couple of machine recipes. These rock types gain additional
|
||||
significance with technic because the grinder can be used to turn them
|
||||
into dirt and sand. This, especially when combined with an automated
|
||||
cobblestone generator, can be an easier way to acquire sand than
|
||||
collecting it where it occurs naturally.
|
||||
|
||||
Desert stone is part of the basic Minetest game. It is found specifically
|
||||
in desert biomes, and only from elevation +2 upwards. Although it is
|
||||
easily accessible, therefore, its quantity is ultimately quite limited.
|
||||
It is used in a few recipes.
|
||||
|
||||
Marble is supplied by technic. It is found in dense clusters from
|
||||
elevation -50 downwards. It has mainly decorative use, but also appears
|
||||
in one machine recipe.
|
||||
|
||||
Granite is supplied by technic. It is found in dense clusters from
|
||||
elevation -150 downwards. It is much harder to dig than standard stone,
|
||||
so impedes mining when it is encountered. It has mainly decorative use,
|
||||
but also appears in a couple of machine recipes.
|
||||
|
||||
### rubber ###
|
||||
|
||||
Rubber is a biologically-derived material that has industrial uses due
|
||||
to its electrical resistivity and its impermeability. In technic, it
|
||||
is used in a few recipes, and it must be acquired by tapping rubber trees.
|
||||
|
||||
If you have the moretrees mod installed, the rubber trees you need
|
||||
are those defined by that mod. If not, technic supplies a copy of the
|
||||
moretrees rubber tree.
|
||||
|
||||
Extracting rubber requires a specific tool, a tree tap. Using the tree
|
||||
tap (by left-clicking) on a rubber tree trunk block extracts a lump of
|
||||
raw latex from the trunk. Each trunk block can be repeatedly tapped for
|
||||
latex, at intervals of several minutes; its appearance changes to show
|
||||
whether it is currently ripe for tapping. Each tree has several trunk
|
||||
blocks, so several latex lumps can be extracted from a tree in one visit.
|
||||
|
||||
Raw latex isn't used directly. It must be vulcanized to produce finished
|
||||
rubber. This can be performed by alloying the latex with coal dust.
|
||||
|
||||
### metal ###
|
||||
|
||||
Many of the substances important in technic are metals, and there is
|
||||
a common pattern in how metals are handled. Generally, each metal can
|
||||
exist in five forms: ore, lump, dust, ingot, and block. With a couple of
|
||||
tricky exceptions in mods outside technic, metals are only *used* in dust,
|
||||
ingot, and block forms. Metals can be readily converted between these
|
||||
three forms, but can't be converted from them back to ore or lump forms.
|
||||
|
||||
As in the basic Minetest game, a "lump" of metal is acquired directly by
|
||||
digging ore, and will then be processed into some other form for use.
|
||||
A lump is thus more akin to ore than to refined metal. (In real life,
|
||||
metal ore rarely yields lumps ("nuggets") of pure metal directly.
|
||||
More often the desired metal is chemically bound into the rock as an
|
||||
oxide or some other compound, and the ore must be chemically processed
|
||||
to yield pure metal.)
|
||||
|
||||
Not all metals occur directly as ore. Generally, elemental metals (those
|
||||
consisting of a single chemical element) occur as ore, and alloys (those
|
||||
consisting of a mixture of multiple elements) do not. In fact, if the
|
||||
fictional mithril is taken to be elemental, this pattern is currently
|
||||
followed perfectly. (It is not clear in the Middle-Earth setting whether
|
||||
mithril is elemental or an alloy.) This might change in the future:
|
||||
in real life some alloys do occur as ore, and some elemental metals
|
||||
rarely occur naturally outside such alloys. Metals that do not occur
|
||||
as ore also lack the "lump" form.
|
||||
|
||||
The basic Minetest game offers a single way to refine metals: cook a lump
|
||||
in a furnace to produce an ingot. With technic this refinement method
|
||||
still exists, but is rarely used outside the early part of the game,
|
||||
because technic offers a more efficient method once some machines have
|
||||
been built. The grinder, available only in electrically-powered forms,
|
||||
can grind a metal lump into two piles of metal dust. Each dust pile
|
||||
can then be cooked into an ingot, yielding two ingots from one lump.
|
||||
This doubling of material value means that you should only cook a lump
|
||||
directly when you have no choice, mainly early in the game when you
|
||||
haven't yet built a grinder.
|
||||
|
||||
An ingot can also be ground back to (one pile of) dust. Thus it is always
|
||||
possible to convert metal between ingot and dust forms, at the expense
|
||||
of some energy consumption. Nine ingots of a metal can be crafted into
|
||||
a block, which can be used for building. The block can also be crafted
|
||||
back to nine ingots. Thus it is possible to freely convert metal between
|
||||
ingot and block forms, which is convenient to store the metal compactly.
|
||||
Every metal has dust, ingot, and block forms.
|
||||
|
||||
Alloying recipes in which a metal is the base ingredient, to produce a
|
||||
metal alloy, always come in two forms, using the metal either as dust
|
||||
or as an ingot. If the secondary ingredient is also a metal, it must
|
||||
be supplied in the same form as the base ingredient. The output alloy
|
||||
is also returned in the same form. For example, brass can be produced
|
||||
by alloying two copper ingots with one zinc ingot to make three brass
|
||||
ingots, or by alloying two piles of copper dust with one pile of zinc
|
||||
dust to make three piles of brass dust. The two ways of alloying produce
|
||||
equivalent results.
|
||||
|
||||
### iron and its alloys ###
|
||||
|
||||
Iron forms several important alloys. In real-life history, iron was the
|
||||
second metal to be used as the base component of deliberately-constructed
|
||||
alloys (the first was copper), and it was the first metal whose working
|
||||
required processes of any metallurgical sophistication. The game
|
||||
mechanics around iron broadly imitate the historical progression of
|
||||
processes around it, rather than the less-varied modern processes.
|
||||
|
||||
The two-component alloying system of iron with carbon is of huge
|
||||
importance, both in the game and in real life. The basic Minetest game
|
||||
doesn't distinguish between these pure iron and these alloys at all,
|
||||
but technic introduces a distinction based on the carbon content, and
|
||||
renames some items of the basic game accordingly.
|
||||
|
||||
The iron/carbon spectrum is represented in the game by three metal
|
||||
substances: wrought iron, carbon steel, and cast iron. Wrought iron
|
||||
has low carbon content (less than 0.25%), resists shattering, and
|
||||
is easily welded, but is relatively soft and susceptible to rusting.
|
||||
In real-life history it was used for rails, gates, chains, wire, pipes,
|
||||
fasteners, and other purposes. Cast iron has high carbon content
|
||||
(2.1% to 4%), is especially hard, and resists corrosion, but is
|
||||
relatively brittle, and difficult to work. Historically it was used
|
||||
to build large structures such as bridges, and for cannons, cookware,
|
||||
and engine cylinders. Carbon steel has medium carbon content (0.25%
|
||||
to 2.1%), and intermediate properties: moderately hard and also tough,
|
||||
somewhat resistant to corrosion. In real life it is now used for most
|
||||
of the purposes previously satisfied by wrought iron and many of those
|
||||
of cast iron, but has historically been especially important for its
|
||||
use in swords, armor, skyscrapers, large bridges, and machines.
|
||||
|
||||
In real-life history, the first form of iron to be refined was
|
||||
wrought iron, which is nearly pure iron, having low carbon content.
|
||||
It was produced from ore by a low-temperature furnace process (the
|
||||
"bloomery") in which the ore/iron remains solid and impurities (slag)
|
||||
are progressively removed by hammering ("working", hence "wrought").
|
||||
This began in the middle East, around 1800 BCE.
|
||||
|
||||
Historically, the next forms of iron to be refined were those of high
|
||||
carbon content. This was the result of the development of a more
|
||||
sophisticated kind of furnace, the blast furnace, capable of reaching
|
||||
higher temperatures. The real advantage of the blast furnace is that it
|
||||
melts the metal, allowing it to be cast straight into a shape supplied by
|
||||
a mould, rather than having to be gradually beaten into the desired shape.
|
||||
A side effect of the blast furnace is that carbon from the furnace's fuel
|
||||
is unavoidably incorporated into the metal. Normally iron is processed
|
||||
twice through the blast furnace: once producing "pig iron", which has
|
||||
very high carbon content and lots of impurities but lower melting point,
|
||||
casting it into rough ingots, then remelting the pig iron and casting it
|
||||
into the final moulds. The result is called "cast iron". Pig iron was
|
||||
first produced in China around 1200 BCE, and cast iron later in the 5th
|
||||
century BCE. Incidentally, the Chinese did not have the bloomery process,
|
||||
so this was their first iron refining process, and, unlike the rest of
|
||||
the world, their first wrought iron was made from pig iron rather than
|
||||
directly from ore.
|
||||
|
||||
Carbon steel, with intermediate carbon content, was developed much later,
|
||||
in Europe in the 17th century CE. It required a more sophisticated
|
||||
process, because the blast furnace made it extremely difficult to achieve
|
||||
a controlled carbon content. Tweaks of the blast furnace would sometimes
|
||||
produce an intermediate carbon content by luck, but the first processes to
|
||||
reliably produce steel were based on removing almost all the carbon from
|
||||
pig iron and then explicitly mixing a controlled amount of carbon back in.
|
||||
|
||||
In the game, the bloomery process is represented by ordinary cooking
|
||||
or grinding of an iron lump. The lump represents unprocessed ore,
|
||||
and is identified only as "iron", not specifically as wrought iron.
|
||||
This standard refining process produces dust or an ingot which is
|
||||
specifically identified as wrought iron. Thus the standard refining
|
||||
process produces the (nearly) pure metal.
|
||||
|
||||
Cast iron is trickier. You might expect from the real-life notes above
|
||||
that cooking an iron lump (representing ore) would produce pig iron that
|
||||
can then be cooked again to produce cast iron. This is kind of the case,
|
||||
but not exactly, because as already noted cooking an iron lump produces
|
||||
wrought iron. The game doesn't distinguish between low-temperature
|
||||
and high-temperature cooking processes: the same furnace is used not
|
||||
just to cast all kinds of metal but also to cook food. So there is no
|
||||
distinction between cooking processes to produce distinct wrought iron
|
||||
and pig iron. But repeated cooking *is* available as a game mechanic,
|
||||
and is indeed used to produce cast iron: re-cooking a wrought iron ingot
|
||||
produces a cast iron ingot. So pig iron isn't represented in the game as
|
||||
a distinct item; instead wrought iron stands in for pig iron in addition
|
||||
to its realistic uses as wrought iron.
|
||||
|
||||
Carbon steel is produced by a more regular in-game process: alloying
|
||||
wrought iron with coal dust (which is essentially carbon). This bears
|
||||
a fair resemblance to the historical development of carbon steel.
|
||||
This alloying recipe is relatively time-consuming for the amount of
|
||||
material processed, when compared against other alloying recipes, and
|
||||
carbon steel is heavily used, so it is wise to alloy it in advance,
|
||||
when you're not waiting for it.
|
||||
|
||||
There are additional recipes that permit all three of these types of iron
|
||||
to be converted into each other. Alloying carbon steel again with coal
|
||||
dust produces cast iron, with its higher carbon content. Cooking carbon
|
||||
steel or cast iron produces wrought iron, in an abbreviated form of the
|
||||
bloomery process.
|
||||
|
||||
There's one more iron alloy in the game: stainless steel. It is managed
|
||||
in a completely regular manner, created by alloying carbon steel with
|
||||
chromium.
|
||||
|
||||
### uranium enrichment ###
|
||||
|
||||
When uranium is to be used to fuel a nuclear reactor, it is not
|
||||
sufficient to merely isolate and refine uranium metal. It is necessary
|
||||
to control its isotopic composition, because the different isotopes
|
||||
behave differently in nuclear processes.
|
||||
|
||||
The main isotopes of interest are U-235 and U-238. U-235 is good at
|
||||
sustaining a nuclear chain reaction, because when a U-235 nucleus is
|
||||
bombarded with a neutron it will usually fission (split) into fragments.
|
||||
It is therefore described as "fissile". U-238, on the other hand,
|
||||
is not fissile: if bombarded with a neutron it will usually capture it,
|
||||
becoming U-239, which is very unstable and quickly decays into semi-stable
|
||||
(and fissile) plutonium-239.
|
||||
|
||||
Inconveniently, the fissile U-235 makes up only about 0.7% of natural
|
||||
uranium, almost all of the other 99.3% being U-238. Natural uranium
|
||||
therefore doesn't make a great nuclear fuel. (In real life there are
|
||||
a small number of reactor types that can use it, but technic doesn't
|
||||
have such a reactor.) Better nuclear fuel needs to contain a higher
|
||||
proportion of U-235.
|
||||
|
||||
Achieving a higher U-235 content isn't as simple as separating the U-235
|
||||
from the U-238 and just using the required amount of U-235. Because
|
||||
U-235 and U-238 are both uranium, and therefore chemically identical,
|
||||
they cannot be chemically separated, in the way that different elements
|
||||
are separated from each other when refining metal. They do differ
|
||||
in atomic mass, so they can be separated by centrifuging, but because
|
||||
their atomic masses are very close, centrifuging doesn't separate them
|
||||
very well. They cannot be separated completely, but it is possible to
|
||||
produce uranium that has the isotopes mixed in different proportions.
|
||||
Uranium with a significantly larger fissile U-235 fraction than natural
|
||||
uranium is called "enriched", and that with a significantly lower fissile
|
||||
fraction is called "depleted".
|
||||
|
||||
A single pass through a centrifuge produces two output streams, one with
|
||||
a fractionally higher fissile proportion than the input, and one with a
|
||||
fractionally lower fissile proportion. To alter the fissile proportion
|
||||
by a significant amount, these output streams must be centrifuged again,
|
||||
repeatedly. The usual arrangement is a "cascade", a linear arrangement
|
||||
of many centrifuges. Each centrifuge takes as input uranium with some
|
||||
specific fissile proportion, and passes its two output streams to the
|
||||
two adjacent centrifuges. Natural uranium is input somewhere in the
|
||||
middle of the cascade, and the two ends of the cascade produce properly
|
||||
enriched and depleted uranium.
|
||||
|
||||
Fuel for technic's nuclear reactor consists of enriched uranium of which
|
||||
3.5% is fissile. (This is a typical value for a real-life light water
|
||||
reactor, a common type for power generation.) To enrich uranium in the
|
||||
game, it must first be in dust form: the centrifuge will not operate
|
||||
on ingots. (In real life uranium enrichment is done with the uranium
|
||||
in the form of a gas.) It is best to grind uranium lumps directly to
|
||||
dust, rather than cook them to ingots first, because this yields twice
|
||||
as much metal dust. When uranium is in refined form (dust, ingot, or
|
||||
block), the name of the inventory item indicates its fissile proportion.
|
||||
Uranium of any available fissile proportion can be put through all the
|
||||
usual processes for metal.
|
||||
|
||||
A single centrifuge operation takes two uranium dust piles, and produces
|
||||
as output one dust pile with a fissile proportion 0.1% higher and one with
|
||||
a fissile proportion 0.1% lower. Uranium can be enriched up to the 3.5%
|
||||
required for nuclear fuel, and depleted down to 0.0%. Thus a cascade
|
||||
covering the full range of fissile fractions requires 34 cascade stages.
|
||||
(In real life, enriching to 3.5% uses thousands of cascade stages.
|
||||
Also, centrifuging is less effective when the input isotope ratio
|
||||
is more skewed, so the steps in fissile proportion are smaller for
|
||||
relatively depleted uranium. Zero fissile content is only asymptotically
|
||||
approachable, and natural uranium relatively cheap, so uranium is normally
|
||||
only depleted to around 0.3%. On the other hand, much higher enrichment
|
||||
than 3.5% isn't much more difficult than enriching that far.)
|
||||
|
||||
Although centrifuges can be used manually, it is not feasible to perform
|
||||
uranium enrichment by hand. It is a practical necessity to set up
|
||||
an automated cascade, using pneumatic tubes to transfer uranium dust
|
||||
piles between centrifuges. Because both outputs from a centrifuge are
|
||||
ejected into the same tube, sorting tubes are needed to send the outputs
|
||||
in different directions along the cascade. It is possible to send items
|
||||
into the centrifuges through the same tubes that take the outputs, so the
|
||||
simplest version of the cascade structure has a line of 34 centrifuges
|
||||
linked by a line of 34 sorting tube segments.
|
||||
|
||||
Assuming that the cascade depletes uranium all the way to 0.0%,
|
||||
producing one unit of 3.5%-fissile uranium requires the input of five
|
||||
units of 0.7%-fissile (natural) uranium, takes 490 centrifuge operations,
|
||||
and produces four units of 0.0%-fissile (fully depleted) uranium as a
|
||||
byproduct. It is possible to reduce the number of required centrifuge
|
||||
operations by using more natural uranium input and outputting only
|
||||
partially depleted uranium, but (unlike in real life) this isn't usually
|
||||
an economical approach. The 490 operations are not spread equally over
|
||||
the cascade stages: the busiest stage is the one taking 0.7%-fissile
|
||||
uranium, which performs 28 of the 490 operations. The least busy is the
|
||||
one taking 3.4%-fissile uranium, which performs 1 of the 490 operations.
|
||||
|
||||
A centrifuge cascade will consume quite a lot of energy. It is
|
||||
worth putting a battery upgrade in each centrifuge. (Only one can be
|
||||
accommodated, because a control logic unit upgrade is also required for
|
||||
tube operation.) An MV centrifuge, the only type presently available,
|
||||
draws 7 kEU/s in this state, and takes 5 s for each uranium centrifuging
|
||||
operation. It thus takes 35 kEU per operation, and the cascade requires
|
||||
17.15 MEU to produce each unit of enriched uranium. It takes five units
|
||||
of enriched uranium to make each fuel rod, and six rods to fuel a reactor,
|
||||
so the enrichment cascade requires 514.5 MEU to process a full set of
|
||||
reactor fuel. This is about 0.85% of the 6.048 GEU that the reactor
|
||||
will generate from that fuel.
|
||||
|
||||
If there is enough power available, and enough natural uranium input,
|
||||
to keep the cascade running continuously, and exactly one centrifuge
|
||||
at each stage, then the overall speed of the cascade is determined by
|
||||
the busiest stage, the 0.7% stage. It can perform its 28 operations
|
||||
towards the enrichment of a single uranium unit in 140 s, so that is
|
||||
the overall cycle time of the cascade. It thus takes 70 min to enrich
|
||||
a full set of reactor fuel. While the cascade is running at this full
|
||||
speed, its average power consumption is 122.5 kEU/s. The instantaneous
|
||||
power consumption varies from second to second over the 140 s cycle,
|
||||
and the maximum possible instantaneous power consumption (with all 34
|
||||
centrifuges active simultaneously) is 238 kEU/s. It is recommended to
|
||||
have some battery boxes to smooth out these variations.
|
||||
|
||||
If the power supplied to the centrifuge cascade averages less than
|
||||
122.5 kEU/s, then the cascade can't run continuously. (Also, if the
|
||||
power supply is intermittent, such as solar, then continuous operation
|
||||
requires more battery boxes to smooth out the supply variations, even if
|
||||
the average power is high enough.) Because it's automated and doesn't
|
||||
require continuous player attention, having the cascade run at less
|
||||
than full speed shouldn't be a major problem. The enrichment work will
|
||||
consume the same energy overall regardless of how quickly it's performed,
|
||||
and the speed will vary in direct proportion to the average power supply
|
||||
(minus any supply lost because battery boxes filled completely).
|
||||
|
||||
If there is insufficient power to run both the centrifuge cascade at
|
||||
full speed and whatever other machines require power, all machines on
|
||||
the same power network as the centrifuge will be forced to run at the
|
||||
same fractional speed. This can be inconvenient, especially if use
|
||||
of the other machines is less automated than the centrifuge cascade.
|
||||
It can be avoided by putting the centrifuge cascade on a separate power
|
||||
network from other machines, and limiting the proportion of the generated
|
||||
power that goes to it.
|
||||
|
||||
If there is sufficient power and it is desired to enrich uranium faster
|
||||
than a single cascade can, the process can be speeded up more economically
|
||||
than by building an entire second cascade. Because the stages of the
|
||||
cascade do different proportions of the work, it is possible to add a
|
||||
second and subsequent centrifuges to only the busiest stages, and have
|
||||
the less busy stages still keep up with only a single centrifuge each.
|
||||
|
||||
Another possible approach to uranium enrichment is to have no fixed
|
||||
assignment of fissile proportions to centrifuges, dynamically putting
|
||||
whatever uranium is available into whichever centrifuges are available.
|
||||
Theoretically all of the centrifuges can be kept almost totally busy all
|
||||
the time, making more efficient use of capital resources, and the number
|
||||
of centrifuges used can be as little (down to one) or as large as desired.
|
||||
The difficult part is that it is not sufficient to put each uranium dust
|
||||
pile individually into whatever centrifuge is available: they must be
|
||||
input in matched pairs. Any odd dust pile in a centrifuge will not be
|
||||
processed and will prevent that centrifuge from accepting any other input.
|
||||
|
||||
### concrete ###
|
||||
|
||||
Concrete is a synthetic building material. The technic modpack implements
|
||||
it in the game.
|
||||
|
||||
Two forms of concrete are available as building blocks: ordinary
|
||||
"concrete" and more advanced "blast-resistant concrete". Despite its
|
||||
name, the latter has no special resistance to explosions or to any other
|
||||
means of destruction.
|
||||
|
||||
Concrete can also be used to make fences. They act just like wooden
|
||||
fences, but aren't flammable. Confusingly, the item that corresponds
|
||||
to a wooden "fence" is called "concrete post". Posts placed adjacently
|
||||
will implicitly create fence between them. Fencing also appears between
|
||||
a post and adjacent concrete block.
|
||||
@@ -0,0 +1,69 @@
|
||||
Tools in Technic fall into two categories: manual and electric. Both sets of tools are unstackable in the inventory. Manual tools work similarly to the manual tools in `minetest`, they have limited durability that is reduced during use (they disappear after they hit 0 durability). Manual tools can be regenerated by using the Tool Workshop, so that valuable tools, such as mese or diamond tools can be preserved. Electric tools require charging in Battery Boxes (of any voltage) and will not be destroyed when they reach 0 charge. Higher levels of electric tools are more powerful and contain more charge so they work longer.
|
||||
|
||||
## Chainsaw
|
||||
|
||||
<img src="../textures/technic_chainsaw.png"/>
|
||||
|
||||
This electric tool speeds up harvesting of wood by allowing the harvesting of an entire tree in a single click. Just click on any part of a tree, and the wood and leaves of that tree at that point and above will be cut and dropped on the ground as blocks. It has enough charge to cut down about 5 trees before running out of power.
|
||||
|
||||
**Note:** If you can't find the drops from using the chainsaw, dig around as they can be buried under neighbouring terrain blocks.
|
||||
|
||||
## Flashlight
|
||||
|
||||
<img src="../textures/technic_flashlight.png"/>
|
||||
|
||||
This electric tool illumates the area in front of the player. While it is electric, and so requires charging, to use it one only needs to equip it. Punching with this tool does nothing.
|
||||
|
||||
## Lava can
|
||||
|
||||
<img src="../textures/technic_lava_can.png"/>
|
||||
|
||||
The lava can works similarly to the bucket tool and the water can, but instead of carrying water, it can carry lava source blocks (the ones that aren't animated), up to 8 at a time. To use, simply equip and click on lava source blocks (they will highlight in black). Then clicking anywhere where there isn't a lava source block will place them again.
|
||||
|
||||
**Warning:** Be careful where you place these source blocks! Since you're placing lava source blocks, lava will flow out of them and may trap or burn you depending on where you are.
|
||||
|
||||
## Mining drill
|
||||
|
||||
<img src="../textures/technic_mining_drill.png"/>
|
||||
<img src="../textures/technic_mining_drill_mk2.png"/>
|
||||
<img src="../textures/technic_mining_drill_mk3.png"/>
|
||||
|
||||
This electric tool operates similarly to a pickaxe, though every block takes exactly one click to drill out. While the Mining Laser allows for faster collection of bulk minerals, it's cutting path can sometimes be undesirable, and the mining drill is useful in these instances.
|
||||
|
||||
The higher levels of the mining drill allow for drilling more blocks at once, substantially reducing mining time. At mark-2, the mining drill can drill 3 blocks at once, either 3-deep, 3-wide, or 3-tall. At mark-3, the mining drill can drill 9-blocks at once in a 3x3 layout around the block selected. Switching between these modes can be done by shift-clicking.
|
||||
|
||||
**Advice:** Since these tools require substantially more diamonds than the mining laser, and yet drills slower, it is suggested that a mining laser be built first.
|
||||
|
||||
## Mining laser
|
||||
|
||||
<img src="../textures/technic_mining_laser_mk1.png"/>
|
||||
<img src="../textures/technic_mining_laser_mk2.png"/>
|
||||
<img src="../textures/technic_mining_laser_mk3.png"/>
|
||||
|
||||
This electric tool is a substantial upgrade above the pickaxe that you start mining with. The laser works by drilling directly forward 7 blocks making a path that's roughly 1-block in diameter. The laser is electric, requiring charging in a battery box (any voltage). As soon as an LV electrical system is set up, this is a great next step.
|
||||
|
||||
## Sonic screwdriver
|
||||
|
||||
<img src="../textures/technic_sonic_screwdriver.png"/>
|
||||
|
||||
This electric tool is used for rotating nodes, much like the default Screwdriver tool, but loses charge instead of durability. This is useful for any nodes which have a "front" direction, like stairs, machines, furniture, etc. Nodes are rotated around the Y-axes (vertical).
|
||||
|
||||
## Tree tap
|
||||
|
||||
<img src="../textures/technic_tree_tap.png"/>
|
||||
|
||||
This manual tool allows for harvesting latex from rubber trees. Extracting latex can be done by hitting rubber trees with it yields for 1 latex. The rubber tree will regenerate its latex supply over the course of a day.
|
||||
|
||||
## Water can
|
||||
|
||||
<img src="../textures/technic_water_can.png"/>
|
||||
|
||||
The water can works similarly to the bucket tool from minetest_game, but it can hold 16 `water_source` (the water blocks that don't look like they're flowing) blocks instead of 1. To use, simply equip the water can and click on water source blocks (they will highlight in black). Then clicking anywhere where there isn't a `water_source` block with the water can equipped will place them.
|
||||
|
||||
**Warning:** Be careful where you place these source blocks! Since you're placing water source blocks, water will flow out of them and may trap or drown you depending on where you are.
|
||||
|
||||
## Wrench
|
||||
|
||||
<img src="../../wrench/textures/technic_wrench.png"/>
|
||||
|
||||
The manual tool allows for moving blocks which contain an inventory, like chests. A shift-right-click on a machine/chest will immediately add it to the inventory.
|
||||
@@ -0,0 +1,25 @@
|
||||
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = {"technic:hv_nuclear_reactor_core_active"},
|
||||
interval = 10,
|
||||
chance = 1,
|
||||
action = function(pos, node)
|
||||
minetest.add_particlespawner({
|
||||
amount = 50,
|
||||
time = 10,
|
||||
minpos = {x=pos.x-0.5, y=pos.y-0.5, z=pos.z-0.5},
|
||||
maxpos = {x=pos.x+0.5, y=pos.y+0.5, z=pos.z+0.5},
|
||||
minvel = {x=-0.8, y=-0.8, z=-0.8},
|
||||
maxvel = {x=0.8, y=0.8, z=0.8},
|
||||
minacc = {x=0,y=0,z=0},
|
||||
maxacc = {x=0,y=0,z=0},
|
||||
minexptime = 0.5,
|
||||
maxexptime = 2,
|
||||
minsize = 1,
|
||||
maxsize = 2,
|
||||
texture = "blueparticle.png",
|
||||
glow = 5
|
||||
})
|
||||
end
|
||||
})
|
||||
@@ -0,0 +1,262 @@
|
||||
local constant_digit_count = technic.config:get("constant_digit_count")
|
||||
|
||||
-- converts a number to a readable string with SI prefix, e.g. 10000 → "10 k",
|
||||
-- 15 → "15 ", 0.1501 → "150.1 m"
|
||||
-- a non-breaking space (U+a0) instead of a usual one is put after number
|
||||
-- The precision is 4 digits
|
||||
local prefixes = {[-8] = "y", [-7] = "z", [-6] = "a", [-5] = "f", [-4] = "p",
|
||||
[-3] = "n", [-2] = "µ", [-1] = "m", [0] = "", [1] = "k", [2] = "M",
|
||||
[3] = "G", [4] = "T", [5] = "P", [6] = "E", [7] = "Z", [8] = "Y"}
|
||||
function technic.pretty_num(num)
|
||||
-- the small number added is due to floating point inaccuracy
|
||||
local b = math.floor(math.log10(math.abs(num)) +0.000001)
|
||||
local pref_i
|
||||
if b ~= 0 then
|
||||
-- b is decremented by 1 to avoid a single digit with many decimals,
|
||||
-- e.g. instead of 1.021 MEU, 1021 kEU is shown
|
||||
pref_i = math.floor((b - 1) / 3)
|
||||
else
|
||||
-- as special case, avoid showing e.g. 1100 mEU instead of 1.1 EU
|
||||
pref_i = 0
|
||||
end
|
||||
if not prefixes[pref_i] then
|
||||
-- This happens for 0, nan, inf, very big values, etc.
|
||||
if num == 0 then
|
||||
-- handle 0 explicilty to avoid showing "-0"
|
||||
if not constant_digit_count then
|
||||
return "0 "
|
||||
end
|
||||
-- gives 0.000
|
||||
return string.format("%.3f ", 0)
|
||||
end
|
||||
return string.format("%.4g ", num)
|
||||
end
|
||||
|
||||
num = num * 10 ^ (-3 * pref_i)
|
||||
if constant_digit_count then
|
||||
local comma_digits_cnt = 3 - (b - 3 * pref_i)
|
||||
return string.format("%." .. comma_digits_cnt .. "f %s",
|
||||
num, prefixes[pref_i])
|
||||
end
|
||||
return string.format("%.4g %s", num, prefixes[pref_i])
|
||||
end
|
||||
|
||||
-- some unittests
|
||||
assert(technic.pretty_num(-0) == "0 ")
|
||||
assert(technic.pretty_num(0) == "0 ")
|
||||
assert(technic.pretty_num(1234) == "1234 ")
|
||||
assert(technic.pretty_num(123456789) == "123.5 M")
|
||||
|
||||
|
||||
-- used to display power values
|
||||
function technic.EU_string(num)
|
||||
return technic.pretty_num(num) .. "EU"
|
||||
end
|
||||
|
||||
|
||||
--- Same as minetest.swap_node, but only changes name
|
||||
-- and doesn't re-set if already set.
|
||||
function technic.swap_node(pos, name)
|
||||
local node = minetest.get_node(pos)
|
||||
if node.name ~= name then
|
||||
node.name = name
|
||||
minetest.swap_node(pos, node)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Fully charge RE chargeable item.
|
||||
-- Must be defined early to reference in item definitions.
|
||||
function technic.refill_RE_charge(stack)
|
||||
local max_charge = technic.power_tools[stack:get_name()]
|
||||
if not max_charge then return stack end
|
||||
technic.set_RE_wear(stack, max_charge, max_charge)
|
||||
local meta = minetest.deserialize(stack:get_metadata()) or {}
|
||||
meta.charge = max_charge
|
||||
stack:set_metadata(minetest.serialize(meta))
|
||||
return stack
|
||||
end
|
||||
|
||||
function technic.set_RE_charge(stack, charge)
|
||||
local max_charge = technic.power_tools[stack:get_name()]
|
||||
if max_charge then
|
||||
technic.set_RE_wear(stack, charge, max_charge)
|
||||
local meta = minetest.deserialize(stack:get_metadata()) or {}
|
||||
meta.charge = math.min(math.max(0, charge), max_charge)
|
||||
stack:set_metadata(minetest.serialize(meta))
|
||||
end
|
||||
end
|
||||
|
||||
technic.set_charge = technic.set_RE_charge
|
||||
|
||||
function technic.get_RE_charge(stack)
|
||||
local max_charge = technic.power_tools[stack:get_name()]
|
||||
if max_charge then
|
||||
local meta = minetest.deserialize(stack:get_metadata()) or {}
|
||||
return meta.charge or 0, max_charge
|
||||
end
|
||||
return 0, 0
|
||||
end
|
||||
|
||||
technic.get_charge = technic.get_RE_charge
|
||||
|
||||
function technic.use_RE_charge(stack, amount)
|
||||
if technic.creative_mode or amount <= 0 then
|
||||
-- Do not check charge in creative mode or when trying to use zero amount
|
||||
return true
|
||||
end
|
||||
local charge = technic.get_RE_charge(stack)
|
||||
if charge < amount then
|
||||
-- Not enough energy available
|
||||
return false
|
||||
end
|
||||
technic.set_RE_charge(stack, charge - amount)
|
||||
-- Charge used successfully
|
||||
return true
|
||||
end
|
||||
|
||||
technic.use_charge = technic.use_RE_charge
|
||||
|
||||
-- If the node is loaded, returns it. If it isn't loaded, load it and return nil.
|
||||
function technic.get_or_load_node(pos)
|
||||
local node = minetest.get_node_or_nil(pos)
|
||||
if node then return node end
|
||||
local vm = VoxelManip()
|
||||
local _, _ = vm:read_from_map(pos, pos)
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
technic.tube_inject_item = pipeworks.tube_inject_item or function(pos, start_pos, velocity, item)
|
||||
local tubed = pipeworks.tube_item(vector.new(pos), item)
|
||||
tubed:get_luaentity().start_pos = vector.new(start_pos)
|
||||
tubed:set_velocity(velocity)
|
||||
tubed:set_acceleration(vector.new(0, 0, 0))
|
||||
end
|
||||
|
||||
|
||||
--- Iterates over the node positions along the specified ray.
|
||||
-- The returned positions will not include the starting position.
|
||||
function technic.trace_node_ray(pos, dir, range)
|
||||
local x_step = dir.x > 0 and 1 or -1
|
||||
local y_step = dir.y > 0 and 1 or -1
|
||||
local z_step = dir.z > 0 and 1 or -1
|
||||
|
||||
local i = 1
|
||||
return function(p)
|
||||
-- Approximation of where we should be if we weren't rounding
|
||||
-- to nodes. This moves forward a bit faster then we do.
|
||||
-- A correction is done below.
|
||||
local real_x = pos.x + (dir.x * i)
|
||||
local real_y = pos.y + (dir.y * i)
|
||||
local real_z = pos.z + (dir.z * i)
|
||||
|
||||
-- How far off we've gotten from where we should be.
|
||||
local dx = math.abs(real_x - p.x)
|
||||
local dy = math.abs(real_y - p.y)
|
||||
local dz = math.abs(real_z - p.z)
|
||||
|
||||
-- If the real position moves ahead too fast, stop it so we
|
||||
-- can catch up. If it gets too far ahead it will smooth
|
||||
-- out our movement too much and we won't turn fast enough.
|
||||
if dx + dy + dz < 2 then
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
-- Step in whichever direction we're most off course in.
|
||||
if dx > dy then
|
||||
if dx > dz then
|
||||
p.x = p.x + x_step
|
||||
else
|
||||
p.z = p.z + z_step
|
||||
end
|
||||
elseif dy > dz then
|
||||
p.y = p.y + y_step
|
||||
else
|
||||
p.z = p.z + z_step
|
||||
end
|
||||
if vector.distance(pos, p) > range then
|
||||
return nil
|
||||
end
|
||||
return p
|
||||
end, vector.round(pos)
|
||||
end
|
||||
|
||||
|
||||
--- Like trace_node_ray, but includes extra positions close to the ray.
|
||||
function technic.trace_node_ray_fat(pos, dir, range)
|
||||
local x_step = dir.x > 0 and 1 or -1
|
||||
local y_step = dir.y > 0 and 1 or -1
|
||||
local z_step = dir.z > 0 and 1 or -1
|
||||
|
||||
local next_poses = {}
|
||||
|
||||
local i = 1
|
||||
return function(p)
|
||||
local ni, np = next(next_poses)
|
||||
if np then
|
||||
next_poses[ni] = nil
|
||||
return np
|
||||
end
|
||||
|
||||
-- Approximation of where we should be if we weren't rounding
|
||||
-- to nodes. This moves forward a bit faster then we do.
|
||||
-- A correction is done below.
|
||||
local real_x = pos.x + (dir.x * i)
|
||||
local real_y = pos.y + (dir.y * i)
|
||||
local real_z = pos.z + (dir.z * i)
|
||||
|
||||
-- How far off we've gotten from where we should be.
|
||||
local dx = math.abs(real_x - p.x)
|
||||
local dy = math.abs(real_y - p.y)
|
||||
local dz = math.abs(real_z - p.z)
|
||||
|
||||
-- If the real position moves ahead too fast, stop it so we
|
||||
-- can catch up. If it gets too far ahead it will smooth
|
||||
-- out our movement too much and we won't turn fast enough.
|
||||
if dx + dy + dz < 2 then
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
-- Step in whichever direction we're most off course in.
|
||||
local sx, sy, sz -- Whether we've already stepped along each axis
|
||||
if dx > dy then
|
||||
if dx > dz then
|
||||
sx = true
|
||||
p.x = p.x + x_step
|
||||
else
|
||||
sz = true
|
||||
p.z = p.z + z_step
|
||||
end
|
||||
elseif dy > dz then
|
||||
sy = true
|
||||
p.y = p.y + y_step
|
||||
else
|
||||
sz = true
|
||||
p.z = p.z + z_step
|
||||
end
|
||||
|
||||
if vector.distance(pos, p) > range then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Add other positions that we're significantly off on.
|
||||
-- We can just use fixed integer keys here because the
|
||||
-- table will be completely cleared before we reach this
|
||||
-- code block again.
|
||||
local dlen = math.sqrt(dx*dx + dy*dy + dz*dz)
|
||||
-- Normalized axis deltas
|
||||
local dxn, dyn, dzn = dx / dlen, dy / dlen, dz / dlen
|
||||
if not sx and dxn > 0.5 then
|
||||
next_poses[1] = vector.new(p.x + x_step, p.y, p.z)
|
||||
end
|
||||
if not sy and dyn > 0.5 then
|
||||
next_poses[2] = vector.new(p.x, p.y + y_step, p.z)
|
||||
end
|
||||
if not sz and dzn > 0.5 then
|
||||
next_poses[3] = vector.new(p.x, p.y, p.z + z_step)
|
||||
end
|
||||
|
||||
return p
|
||||
end, vector.round(pos)
|
||||
end
|
||||
@@ -0,0 +1,76 @@
|
||||
-- Minetest 0.4.7 mod: technic
|
||||
-- namespace: technic
|
||||
-- (c) 2012-2013 by RealBadAngel <mk@realbadangel.pl>
|
||||
|
||||
local load_start = os.clock()
|
||||
|
||||
technic = rawget(_G, "technic") or {}
|
||||
technic.creative_mode = minetest.settings:get_bool("creative_mode")
|
||||
|
||||
local modpath = minetest.get_modpath("technic")
|
||||
technic.modpath = modpath
|
||||
|
||||
|
||||
-- Boilerplate to support intllib
|
||||
if rawget(_G, "intllib") then
|
||||
technic.getter = intllib.Getter()
|
||||
else
|
||||
technic.getter = function(s, a, ...)
|
||||
if a == nil then
|
||||
return s
|
||||
end
|
||||
a = {a, ...}
|
||||
return s:gsub(
|
||||
"(@?)@(%(?)(%d+)(%)?)",
|
||||
function(e, o, n, c)
|
||||
if e == "" then
|
||||
return a[tonumber(n)] .. (o == "" and c or "")
|
||||
else
|
||||
return "@" .. o .. n .. c
|
||||
end
|
||||
end
|
||||
)
|
||||
end
|
||||
end
|
||||
local S = technic.getter
|
||||
|
||||
-- Read configuration file
|
||||
dofile(modpath.."/config.lua")
|
||||
|
||||
-- Lag monitoring
|
||||
dofile(modpath.."/max_lag.lua")
|
||||
|
||||
-- Helper functions
|
||||
dofile(modpath.."/helpers.lua")
|
||||
|
||||
-- Items
|
||||
dofile(modpath.."/items.lua")
|
||||
|
||||
-- Craft recipes for items
|
||||
dofile(modpath.."/crafts.lua")
|
||||
|
||||
-- Register functions
|
||||
dofile(modpath.."/register.lua")
|
||||
|
||||
-- Radiation
|
||||
dofile(modpath.."/radiation.lua")
|
||||
|
||||
-- Machines
|
||||
dofile(modpath.."/machines/init.lua")
|
||||
|
||||
-- Tools
|
||||
dofile(modpath.."/tools/init.lua")
|
||||
|
||||
-- Aliases for legacy node/item names
|
||||
dofile(modpath.."/legacy.lua")
|
||||
|
||||
-- visual effects
|
||||
dofile(modpath.."/effects.lua")
|
||||
|
||||
if minetest.settings:get_bool("log_mods") then
|
||||
print(S("[Technic] Loaded in %f seconds"):format(os.clock() - load_start))
|
||||
end
|
||||
|
||||
if minetest.settings:get_bool("enable_technic_integration_test") then
|
||||
dofile(modpath.."/integration_test.lua")
|
||||
end
|
||||
@@ -0,0 +1,56 @@
|
||||
|
||||
minetest.log("warning", "[technic] integration-test enabled!")
|
||||
|
||||
-- those mods have to be present
|
||||
local assert_mods = {
|
||||
"technic",
|
||||
"pipeworks"
|
||||
}
|
||||
|
||||
-- those nodes have to be present
|
||||
local assert_nodes = {
|
||||
"technic:admin_anchor"
|
||||
}
|
||||
|
||||
-- defered integration test function
|
||||
minetest.register_on_mods_loaded(function()
|
||||
minetest.log("warning", "[technic] all mods loaded, starting delayed test-function")
|
||||
|
||||
minetest.after(1, function()
|
||||
minetest.log("warning", "[technic] starting integration test")
|
||||
|
||||
-- export stats
|
||||
local file = io.open(minetest.get_worldpath().."/registered_nodes.txt", "w" );
|
||||
if file then
|
||||
for name in pairs(minetest.registered_nodes) do
|
||||
file:write(name .. '\n')
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
|
||||
-- check mods
|
||||
for _, modname in ipairs(assert_mods) do
|
||||
if not minetest.get_modpath(modname) then
|
||||
error("Mod not present: " .. modname)
|
||||
end
|
||||
end
|
||||
|
||||
-- check nodes
|
||||
for _, nodename in ipairs(assert_nodes) do
|
||||
if not minetest.registered_nodes[nodename] then
|
||||
error("Node not present: " .. nodename)
|
||||
end
|
||||
end
|
||||
|
||||
-- write success flag
|
||||
local data = minetest.write_json({ success = true }, true);
|
||||
file = io.open(minetest.get_worldpath().."/integration_test.json", "w" );
|
||||
if file then
|
||||
file:write(data)
|
||||
file:close()
|
||||
end
|
||||
|
||||
minetest.log("warning", "[technic] integration tests done!")
|
||||
minetest.request_shutdown("success")
|
||||
end)
|
||||
end)
|
||||
@@ -0,0 +1,203 @@
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
minetest.register_craftitem("technic:silicon_wafer", {
|
||||
description = S("Silicon Wafer"),
|
||||
inventory_image = "technic_silicon_wafer.png",
|
||||
})
|
||||
|
||||
minetest.register_craftitem( "technic:doped_silicon_wafer", {
|
||||
description = S("Doped Silicon Wafer"),
|
||||
inventory_image = "technic_doped_silicon_wafer.png",
|
||||
})
|
||||
|
||||
minetest.register_craftitem("technic:uranium_fuel", {
|
||||
description = S("Uranium Fuel"),
|
||||
inventory_image = "technic_uranium_fuel.png",
|
||||
})
|
||||
|
||||
minetest.register_craftitem( "technic:diamond_drill_head", {
|
||||
description = S("Diamond Drill Head"),
|
||||
inventory_image = "technic_diamond_drill_head.png",
|
||||
})
|
||||
|
||||
minetest.register_tool("technic:blue_energy_crystal", {
|
||||
description = S("Blue Energy Crystal"),
|
||||
inventory_image = minetest.inventorycube(
|
||||
"technic_diamond_block_blue.png",
|
||||
"technic_diamond_block_blue.png",
|
||||
"technic_diamond_block_blue.png"),
|
||||
wear_represents = "technic_RE_charge",
|
||||
on_refill = technic.refill_RE_charge,
|
||||
tool_capabilities = {
|
||||
max_drop_level = 0,
|
||||
groupcaps = {
|
||||
fleshy = {times={}, uses=10000, maxlevel=0}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_tool("technic:green_energy_crystal", {
|
||||
description = S("Green Energy Crystal"),
|
||||
inventory_image = minetest.inventorycube(
|
||||
"technic_diamond_block_green.png",
|
||||
"technic_diamond_block_green.png",
|
||||
"technic_diamond_block_green.png"),
|
||||
wear_represents = "technic_RE_charge",
|
||||
on_refill = technic.refill_RE_charge,
|
||||
tool_capabilities = {
|
||||
max_drop_level = 0,
|
||||
groupcaps = {
|
||||
fleshy = {times={}, uses=10000, maxlevel=0}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_tool("technic:red_energy_crystal", {
|
||||
description = S("Red Energy Crystal"),
|
||||
inventory_image = minetest.inventorycube(
|
||||
"technic_diamond_block_red.png",
|
||||
"technic_diamond_block_red.png",
|
||||
"technic_diamond_block_red.png"),
|
||||
wear_represents = "technic_RE_charge",
|
||||
on_refill = technic.refill_RE_charge,
|
||||
tool_capabilities = {
|
||||
max_drop_level = 0,
|
||||
groupcaps = {
|
||||
fleshy = {times={}, uses=10000, maxlevel=0}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craftitem("technic:copper_coil", {
|
||||
description = S("Copper Coil"),
|
||||
inventory_image = "technic_copper_coil.png",
|
||||
})
|
||||
|
||||
minetest.register_craftitem("technic:lv_transformer", {
|
||||
description = S("Low Voltage Transformer"),
|
||||
inventory_image = "technic_lv_transformer.png",
|
||||
})
|
||||
|
||||
minetest.register_craftitem("technic:mv_transformer", {
|
||||
description = S("Medium Voltage Transformer"),
|
||||
inventory_image = "technic_mv_transformer.png",
|
||||
})
|
||||
|
||||
minetest.register_craftitem( "technic:hv_transformer", {
|
||||
description = S("High Voltage Transformer"),
|
||||
inventory_image = "technic_hv_transformer.png",
|
||||
})
|
||||
|
||||
minetest.register_craftitem( "technic:control_logic_unit", {
|
||||
description = S("Control Logic Unit"),
|
||||
inventory_image = "technic_control_logic_unit.png",
|
||||
})
|
||||
|
||||
minetest.register_craftitem("technic:mixed_metal_ingot", {
|
||||
description = S("Mixed Metal Ingot"),
|
||||
inventory_image = "technic_mixed_metal_ingot.png",
|
||||
})
|
||||
|
||||
minetest.register_craftitem("technic:composite_plate", {
|
||||
description = S("Composite Plate"),
|
||||
inventory_image = "technic_composite_plate.png",
|
||||
})
|
||||
|
||||
minetest.register_craftitem("technic:copper_plate", {
|
||||
description = S("Copper Plate"),
|
||||
inventory_image = "technic_copper_plate.png",
|
||||
})
|
||||
|
||||
minetest.register_craftitem("technic:carbon_plate", {
|
||||
description = S("Carbon Plate"),
|
||||
inventory_image = "technic_carbon_plate.png",
|
||||
})
|
||||
|
||||
minetest.register_craftitem("technic:graphite", {
|
||||
description = S("Graphite"),
|
||||
inventory_image = "technic_graphite.png",
|
||||
})
|
||||
|
||||
minetest.register_craftitem("technic:carbon_cloth", {
|
||||
description = S("Carbon Cloth"),
|
||||
inventory_image = "technic_carbon_cloth.png",
|
||||
})
|
||||
|
||||
minetest.register_node("technic:machine_casing", {
|
||||
description = S("Machine Casing"),
|
||||
groups = {cracky=2},
|
||||
sunlight_propagates = true,
|
||||
paramtype = "light",
|
||||
drawtype = "allfaces",
|
||||
tiles = {"technic_machine_casing.png"},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
})
|
||||
|
||||
for p = 0, 35 do
|
||||
local nici = (p ~= 0 and p ~= 7 and p ~= 35) and 1 or nil
|
||||
local psuffix = p == 7 and "" or p
|
||||
local ingot = "technic:uranium"..psuffix.."_ingot"
|
||||
local block = "technic:uranium"..psuffix.."_block"
|
||||
local ov = p == 7 and minetest.override_item or nil;
|
||||
(ov or minetest.register_craftitem)(ingot, {
|
||||
description = string.format(S("%.1f%%-Fissile Uranium Ingot"), p/10),
|
||||
inventory_image = "technic_uranium_ingot.png",
|
||||
groups = {uranium_ingot=1, not_in_creative_inventory=nici},
|
||||
});
|
||||
-- Note on radioactivity of blocks:
|
||||
-- Source: <http://www.wise-uranium.org/rup.html>
|
||||
-- The baseline radioactivity of an isotope is not especially
|
||||
-- correlated with whether it's fissile (i.e., suitable as
|
||||
-- reactor fuel). Natural uranium consists mainly of fissile
|
||||
-- U-235 and non-fissile U-238, and both U-235 and U-238 are
|
||||
-- significantly radioactive. U-235's massic activity is
|
||||
-- about 80.0 MBq/kg, and U-238's is about 12.4 MBq/kg, which
|
||||
-- superficially suggests that 3.5%-fissile uranium should have
|
||||
-- only 1.19 times the activity of fully-depleted uranium.
|
||||
-- But a third isotope affects the result hugely: U-234 has
|
||||
-- massic activity of 231 GBq/kg. Natural uranium has massic
|
||||
-- composition of 99.2837% U-238, 0.711% U-235, and 0.0053% U-234,
|
||||
-- so its activity comes roughly 49% each from U-234 and U-238
|
||||
-- and only 2% from U-235. During enrichment via centrifuge,
|
||||
-- the U-234 fraction is concentrated along with the U-235, with
|
||||
-- the U-234:U-235 ratio remaining close to its original value.
|
||||
-- (Actually the U-234 gets separated from U-238 slightly more
|
||||
-- than the U-235 is, so the U-234:U-235 ratio is slightly
|
||||
-- higher in enriched uranium.) A typical massic composition
|
||||
-- for 3.5%-fissile uranium is 96.47116% U-238, 3.5% U-235, and
|
||||
-- 0.02884% U-234. This gives 3.5%-fissile uranium about 6.55
|
||||
-- times the activity of fully-depleted uranium. The values we
|
||||
-- compute here for the "radioactive" group value are based on
|
||||
-- linear interpolation of activity along that scale, rooted at
|
||||
-- a natural (0.7%-fissile) uranium block having the activity of
|
||||
-- 9 uranium ore blocks (due to 9 ingots per block). The group
|
||||
-- value is proportional to the square root of the activity, and
|
||||
-- uranium ore has radioactive=1. This yields radioactive=1.0
|
||||
-- for a fully-depleted uranium block and radioactive=2.6 for
|
||||
-- a 3.5%-fissile uranium block.
|
||||
local radioactivity = math.floor(math.sqrt((1+5.55*p/35) * 18 / (1+5.55*7/35)) + 0.5);
|
||||
(ov or minetest.register_node)(block, {
|
||||
description = string.format(S("%.1f%%-Fissile Uranium Block"), p/10),
|
||||
tiles = {"technic_uranium_block.png"},
|
||||
is_ground_content = true,
|
||||
groups = {uranium_block=1, not_in_creative_inventory=nici,
|
||||
cracky=1, level=2, radioactive=radioactivity},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
});
|
||||
if not ov then
|
||||
minetest.register_craft({
|
||||
output = block,
|
||||
recipe = {
|
||||
{ingot, ingot, ingot},
|
||||
{ingot, ingot, ingot},
|
||||
{ingot, ingot, ingot},
|
||||
},
|
||||
})
|
||||
minetest.register_craft({
|
||||
output = ingot.." 9",
|
||||
recipe = {{block}},
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
|
||||
-- Aliases to convert from legacy node/item names
|
||||
|
||||
technic.legacy_nodenames = {
|
||||
["technic:alloy_furnace"] = "technic:lv_alloy_furnace",
|
||||
["technic:alloy_furnace_active"] = "technic:lv_alloy_furnace_active",
|
||||
["technic:battery_box"] = "technic:lv_battery_box0",
|
||||
["technic:battery_box1"] = "technic:lv_battery_box1",
|
||||
["technic:battery_box2"] = "technic:lv_battery_box2",
|
||||
["technic:battery_box3"] = "technic:lv_battery_box3",
|
||||
["technic:battery_box4"] = "technic:lv_battery_box4",
|
||||
["technic:battery_box5"] = "technic:lv_battery_box5",
|
||||
["technic:battery_box6"] = "technic:lv_battery_box6",
|
||||
["technic:battery_box7"] = "technic:lv_battery_box7",
|
||||
["technic:battery_box8"] = "technic:lv_battery_box8",
|
||||
["technic:electric_furnace"] = "technic:lv_electric_furnace",
|
||||
["technic:electric_furnace_active"] = "technic:lv_electric_furnace_active",
|
||||
["technic:grinder"] = "technic:lv_grinder",
|
||||
["technic:grinder_active"] = "technic:lv_grinder_active",
|
||||
["technic:extractor"] = "technic:lv_extractor",
|
||||
["technic:extractor_active"] = "technic:lv_extractor_active",
|
||||
["technic:compressor"] = "technic:lv_compressor",
|
||||
["technic:compressor_active"] = "technic:lv_compressor_active",
|
||||
["technic:hv_battery_box"] = "technic:hv_battery_box0",
|
||||
["technic:mv_battery_box"] = "technic:mv_battery_box0",
|
||||
["technic:generator"] = "technic:lv_generator",
|
||||
["technic:generator_active"] = "technic:lv_generator_active",
|
||||
["technic:iron_dust"] = "technic:wrought_iron_dust",
|
||||
["technic:enriched_uranium"] = "technic:uranium35_ingot",
|
||||
}
|
||||
|
||||
for old, new in pairs(technic.legacy_nodenames) do
|
||||
minetest.register_alias(old, new)
|
||||
end
|
||||
|
||||
for i = 0, 64 do
|
||||
minetest.register_alias("technic:hv_cable"..i, "technic:hv_cable")
|
||||
minetest.register_alias("technic:mv_cable"..i, "technic:mv_cable")
|
||||
minetest.register_alias("technic:lv_cable"..i, "technic:lv_cable")
|
||||
end
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
# German Translation for Technic Mod
|
||||
# Deutsche Uebersetzung des Technic Mods
|
||||
# by Xanthin
|
||||
|
||||
## Misc
|
||||
[Technic] Loaded in %f seconds = [Technic] ist in %f Sekunden geladen
|
||||
|
||||
## Items
|
||||
Silicon Wafer = Siliziumscheibe
|
||||
Doped Silicon Wafer = Dotierte Siliziumscheibe
|
||||
Enriched Uranium = Angereichertes Uran
|
||||
Uranium Fuel = Uranbrennstoff
|
||||
Diamond Drill Head = Diamantbohrkopf
|
||||
Blue Energy Crystal = Blauer Energiekristall
|
||||
Green Energy Crystal = Gruener Energiekristall
|
||||
Red Energy Crystal = Roter Energiekristall
|
||||
Fine Copper Wire = Feinkupferdraht
|
||||
Copper Coil = Kupferspule
|
||||
Electric Motor = Elektromotor
|
||||
Low Voltage Transformer = Niederspannungstransformator
|
||||
Medium Voltage Transformer = Mittelspannungstransformator
|
||||
High Voltage Transformer = Hochspannungstransformator
|
||||
Control Logic Unit = Steuer- und Regelungseinheit
|
||||
Mixed Metal Ingot = Mischmetallbarren
|
||||
Composite Plate = Verbundplatte
|
||||
Copper Plate = Kupferplatte
|
||||
Carbon Plate = Kohlefaserplatte
|
||||
Graphite = Graphit
|
||||
Carbon Cloth = Kohlefasergewebe
|
||||
Raw Latex = Rohlatex
|
||||
Rubber Fiber = Gummifaser
|
||||
%.1f%%-Fissile Uranium Ingot =
|
||||
%.1f%%-Fissile Uranium Block =
|
||||
|
||||
## Machine misc
|
||||
Machine cannot be removed because it is not empty = Die Maschine kann nicht entfernt werden, weil sie noch nicht leer ist.
|
||||
Inventory move disallowed due to protection = Das Inventar ist geschuetzt, Zugriff verweigert.
|
||||
# $1: Machine name (Includes tier)
|
||||
@1 Active (@2 EU) = @1 ist eingeschaltet (@2 EU)
|
||||
%s Active = %s ist eingeschaltet
|
||||
%s Disabled = %s ist ausgeschaltet
|
||||
%s Enabled =
|
||||
%s Idle = %s ist bereit
|
||||
%s Improperly Placed = %s ist falsch plaziert
|
||||
%s Unpowered = %s hat keine Stromversorgung
|
||||
%s Out Of Fuel = %s hat keinen Brennstoff
|
||||
%s Has Bad Cabling = %s ist falsch verkabelt
|
||||
%s Has No Network = %s hat kein Netzwerk
|
||||
%s Finished = %s ist fertig
|
||||
Enable/Disable = Einschalten/Ausschalten
|
||||
Range = Reichweite
|
||||
Upgrade Slots = Verbesserungsfaecher
|
||||
In: = Rein:
|
||||
Out: = Raus:
|
||||
Slot %d = Fach %d
|
||||
Itemwise = Einzelstuecke
|
||||
Stackwise = Ganzer Stapel
|
||||
Owner: =
|
||||
Unlocked =
|
||||
Locked =
|
||||
Radius: =
|
||||
Enabled =
|
||||
Disabled =
|
||||
|
||||
## Machine names
|
||||
# $1: Tier
|
||||
%s Alloy Furnace = %s Legierungsofen
|
||||
%s Battery Box = %s Batteriebox
|
||||
%s Cable = %s Kabel
|
||||
%s Compressor = %s Kompressor
|
||||
%s Extractor = %s Extraktor
|
||||
%s Forcefield Emitter = %s Kraftfeld-Emitter
|
||||
%s Furnace = %s Ofen
|
||||
%s Grinder = %s Schleifmaschine
|
||||
%s Music Player = %s Musikspieler
|
||||
%s Quarry = %s Steinbruch
|
||||
%s Tool Workshop = %s Werkzeugwerkstatt
|
||||
Arrayed Solar %s Generator = %s Solaranlage
|
||||
Fuel-Fired %s Generator = %s Kohle-Generator
|
||||
Geothermal %s Generator = %s Geothermie-Generator
|
||||
Hydro %s Generator = %s Wassermuehle
|
||||
Nuclear %s Generator Core = %s Reaktorkern
|
||||
Small Solar %s Generator = %s Solarmodul
|
||||
Wind %s Generator = %s Windmuehle
|
||||
Self-Contained Injector = Selbstversorger-Injektor
|
||||
Constructor Mk%d = Konstruktor Modell %d
|
||||
Frame = Rahmen
|
||||
Frame Motor = Rahmenmotor
|
||||
Template = Schablone
|
||||
Template (replacing) = Schablone (ersetzend)
|
||||
Template motor = Schablonenmotor
|
||||
Template tool = Schablonenwerkzeug
|
||||
Battery Box = Batteriebox
|
||||
Supply Converter = Stromumwandler
|
||||
Switching Station = Schaltanlage
|
||||
Fuel-Fired Alloy Furnace = Kohle-Legierungsofen
|
||||
Fuel-Fired Furnace = Kohle-Ofen
|
||||
Wind Mill Frame = Windmuehlengeruest
|
||||
Forcefield = Kraftfeld
|
||||
Nuclear Reactor Rod Compartment = Brennstabfaecher
|
||||
Administrative World Anchor =
|
||||
|
||||
## Machine-specific
|
||||
# $1: Pruduced EU
|
||||
Charge = Aufladen
|
||||
Discharge = Entladen
|
||||
Power level = Energiestufe
|
||||
# $1: Tier $2: current_charge $3: max_charge
|
||||
@1 Battery Box: @2/@3 = @1 Batteriebox: @2/@3
|
||||
# $1: Machine name $2: Supply $3: Demand
|
||||
@1. Supply: @2 Demand: @3 = @1. Versorgung: @2 Bedarf: @3
|
||||
Production at %d%% = Produktion bei %d%%
|
||||
Choose Milling Program: = Waehle ein Fraesprogramm:
|
||||
Slim Elements half / normal height: = Schmale Elemente von halber / normaler Hoehe:
|
||||
Current track %s = Aktueller Titel %s
|
||||
Stopped =
|
||||
Keeping %d/%d map blocks loaded =
|
||||
Digging not started =
|
||||
Digging finished =
|
||||
Digging %d m above machine =
|
||||
Digging %d m below machine =
|
||||
|
||||
## Grinder Recipes
|
||||
# $1: Name
|
||||
%s Dust = %sstaub
|
||||
Akalin = Akalin
|
||||
Alatro = Alatro
|
||||
Arol = Arol
|
||||
Brass = Messing
|
||||
Bronze = Bronze
|
||||
Carbon Steel = Kohlenstoffstahl
|
||||
Cast Iron = Gusseisen
|
||||
Chromium = Chrom
|
||||
Coal = Kohle
|
||||
Copper = Kupfer
|
||||
Gold = Gold
|
||||
Mithril = Mithril
|
||||
Silver = Silber
|
||||
Stainless Steel = Edelstahl
|
||||
Talinite = Talinite
|
||||
Tin = Zinn
|
||||
Wrought Iron = Schmiedeeisen
|
||||
Zinc = Zink
|
||||
%.1f%%-Fissile Uranium =
|
||||
|
||||
## Tools
|
||||
RE Battery = Akkubatterie
|
||||
Water Can = Wasserkanister
|
||||
Lava Can = Lavakanister
|
||||
Chainsaw = Kettensaege
|
||||
Flashlight = Taschenlampe
|
||||
3 nodes deep. = 3 Bloecke tief.
|
||||
3 nodes tall. = 3 Bloecke hoch.
|
||||
3 nodes wide. = 3 Bloecke breit.
|
||||
3x3 nodes. = 3x3 Bloecke.
|
||||
Use while sneaking to change Mining Drill Mk%d modes. = Halte die Shift-Taste beim Benutzen gedrueckt, um die Funktion des Bergbaubohrers Modell %d zu aendern.
|
||||
Mining Drill Mk%d Mode %d = Bergbaubohrer Modell %d Funktion %d
|
||||
Mining Drill Mk%d = Bergbaubohrer Modell %d
|
||||
Mining Laser Mk%d = Bergbaulaser Modell %d
|
||||
Single node. = Einzelblock
|
||||
Sonic Screwdriver = Schallschraubendreher
|
||||
Tree Tap = Baumzapfhahn
|
||||
|
||||
## Craft descriptions
|
||||
Alloy cooking =
|
||||
Grinding =
|
||||
Compressing =
|
||||
Extracting =
|
||||
@@ -0,0 +1,162 @@
|
||||
# Spanish Translation for Technic Mod
|
||||
# Traduccion al Español del Mod Technic
|
||||
# Autor: Diego Martínez <kaeza>
|
||||
|
||||
## Misc
|
||||
[Technic] Loaded in %f seconds = [Technic] Cargado en %f segundos
|
||||
|
||||
## Items
|
||||
Silicon Wafer = Oblea de Silicio
|
||||
Doped Silicon Wafer = Oblea de Silicio Dopada
|
||||
Enriched Uranium = Uranio Enriquecido
|
||||
Uranium Fuel = Combustible de Uranio
|
||||
Diamond Drill Head = Mecha de Taladro de Diamante
|
||||
Blue Energy Crystal = Cristal de Energia Azul
|
||||
Green Energy Crystal = Cristal de Energia Verde
|
||||
Red Energy Crystal = Cristal de Energia Rojo
|
||||
Fine Copper Wire = Cable Fino de Cobre
|
||||
Copper Coil = Resorte de Cobre
|
||||
Electric Motor = Motor Electrico
|
||||
Low Voltage Transformer = Transformador de Bajo Voltaje
|
||||
Medium Voltage Transformer = Transformador de Voltaje Medio
|
||||
High Voltage Transformer = Transformador de Alto Voltaje
|
||||
Control Logic Unit = Unidad Logica de Control
|
||||
Mixed Metal Ingot = Lingote de Metal Mezclado
|
||||
Composite Plate = Placa de Compuestos
|
||||
Copper Plate = Placa de Cobre
|
||||
Carbon Plate = Placa de Carbon
|
||||
Graphite = Grafito
|
||||
Carbon Cloth = Tela de Carbon
|
||||
Raw Latex = Latex Crudo
|
||||
Rubber Fiber = Fibra de Hule
|
||||
%.1f%%-Fissile Uranium Ingot =
|
||||
%.1f%%-Fissile Uranium Block =
|
||||
|
||||
## Machine misc
|
||||
Machine cannot be removed because it is not empty = La maquina no puede removerse porque no esta vacia
|
||||
Inventory move disallowed due to protection =
|
||||
# $1: Machine name (Includes tier)
|
||||
@1 Active (@2 EU) = @1 Activo (@2 EU)
|
||||
%s Active = %s Activo
|
||||
%s Enabled =
|
||||
%s Idle = %s Quieto
|
||||
%s Unpowered = %s Sin Energia
|
||||
%s Out Of Fuel = %s Sin Combustible
|
||||
%s Has Bad Cabling = %s Tiene Mal Cableado
|
||||
%s Has No Network = %s No Tiene Una Red
|
||||
%s Finished = %s Terminado
|
||||
%s Disabled = %s Deshabilitado
|
||||
%s Improperly Placed = %s No Colocado Apropiadamente
|
||||
Range = Alcance
|
||||
Enable/Disable = Habilitar/Deshabilitar
|
||||
Itemwise =
|
||||
Stackwise =
|
||||
Owner: =
|
||||
Unlocked =
|
||||
Locked =
|
||||
Radius: =
|
||||
Enabled =
|
||||
Disabled =
|
||||
|
||||
## Machine names
|
||||
# $1: Tier
|
||||
%s Alloy Furnace = Horno de Aleacion %s
|
||||
%s Battery Box = Caja de Bateria %s
|
||||
%s Cable = Cable %s
|
||||
%s Compressor = Compresor %s
|
||||
%s Extractor = Extractor %s
|
||||
%s Forcefield Emitter = Emisor de Campo de Fuerza %s
|
||||
%s Furnace = Horno %s
|
||||
%s Grinder = Amoladora %s
|
||||
%s Music Player = Reproductor de Musica %s
|
||||
%s Quarry = Cantera %s
|
||||
%s Tool Workshop = Taller de Herramientas %s
|
||||
Arrayed Solar %s Generator = Panel Solar %s
|
||||
Fuel-Fired %s Generator = Generador a Carbon %s
|
||||
Geothermal %s Generator = Generador Geotermico %s
|
||||
Hydro %s Generator = Molino de Agua %s
|
||||
Nuclear %s Generator Core = Nucleo de Reactor Nuclear %s
|
||||
Small Solar %s Generator = Panel Solar %s
|
||||
Wind %s Generator = Molino de Viento %s
|
||||
Self-Contained Injector =
|
||||
Constructor Mk%d =
|
||||
Frame =
|
||||
Frame Motor =
|
||||
Template =
|
||||
Template (replacing) =
|
||||
Template Motor =
|
||||
Template Tool =
|
||||
Supply Converter = Convertidor de Alimentacion
|
||||
Switching Station = Estacion de Conmutacion
|
||||
Battery Box = Caja de Baterias
|
||||
Fuel-Fired Alloy Furnace = Horno de Aleacion a Carbon
|
||||
Fuel-Fired Furnace = Horno a Carbon
|
||||
Forcefield = Campo de Fuerza
|
||||
Nuclear Reactor Rod Compartment = Compartimiento para Vara de Reactor Nuclear
|
||||
Wind Mill Frame = Armazon de Molino de Viento
|
||||
Administrative World Anchor =
|
||||
|
||||
## Machine-specific
|
||||
# $1: Pruduced EU
|
||||
Charge = Cargar
|
||||
Discharge = Descargar
|
||||
Power level = Nivel de Poder
|
||||
# $1: Tier $2: current_charge $3: max_charge
|
||||
@1 Battery Box: @2/@3 = Caja de Bateria @1: @2/@3
|
||||
# $1: Machine name $2: Supply $3: Demand
|
||||
@1. Supply: @2 Demand: @3 = @1. Alimentacion: @2 Demanda: @3
|
||||
# $1: Production percent
|
||||
Production at %d%% = Produccion en %d%%
|
||||
Stopped =
|
||||
Keeping %d/%d map blocks loaded =
|
||||
Digging not started =
|
||||
Digging finished =
|
||||
Digging %d m above machine =
|
||||
Digging %d m below machine =
|
||||
|
||||
## Grinder Recipes
|
||||
# $1: Name
|
||||
%s Dust = Polvo de %s
|
||||
Akalin = Akalina
|
||||
Alatro = Alatro
|
||||
Arol = Arol
|
||||
Brass = Laton
|
||||
Bronze = Bronce
|
||||
Carbon Steel = Acero al Carbono
|
||||
Cast Iron = Hierro Fundido
|
||||
Chromium = Cromo
|
||||
Coal = Carbon
|
||||
Copper = Cobre
|
||||
Gold = Oro
|
||||
Mithril = Mitrilo
|
||||
Silver = Plata
|
||||
Stainless Steel = Acero Inoxidable
|
||||
Talinite = Talinita
|
||||
Tin = Estanio
|
||||
Wrought Iron = Hierro Forjado
|
||||
Zinc = Zinc
|
||||
%.1f%%-Fissile Uranium =
|
||||
|
||||
## Tools
|
||||
RE Battery =
|
||||
Water Can = Bidon de Agua
|
||||
Lava Can = Bidon de Lava
|
||||
Chainsaw = Motosierra
|
||||
Flashlight = Linterna
|
||||
3 nodes deep. = 3 nodos de profundo.
|
||||
3 nodes tall. = 3 nodos de alto.
|
||||
3 nodes wide. = 3 nodos de ancho.
|
||||
3x3 nodes. = 3x3 nodos.
|
||||
Use while sneaking to change Mining Drill Mk%d modes. = Manten pulsado Mayus y Usar para cambiar el modo del Taladro de Mineria Mk%d.
|
||||
Mining Drill Mk%d Mode %d = Taladro de Mineria Mk%d Modo %d
|
||||
Mining Drill Mk%d = Taladro de Mineria Mk%d
|
||||
Mining Laser Mk%d = Laser de Mineria Mk%d
|
||||
Single node. = Nodo simple.
|
||||
Sonic Screwdriver = Destonillador Sonico
|
||||
Tree Tap = Grifo de Arbol
|
||||
|
||||
## Craft descriptions
|
||||
Alloy cooking =
|
||||
Grinding =
|
||||
Compressing =
|
||||
Extracting =
|
||||
@@ -0,0 +1,215 @@
|
||||
# template.txt
|
||||
# Template for translations of Technic
|
||||
|
||||
## Misc
|
||||
[Technic] Loaded in %f seconds = [Technic] Chargement en %f secondes
|
||||
|
||||
## Items
|
||||
Silicon Wafer = Tranche de silicium
|
||||
Doped Silicon Wafer = Tranche de silicium doppée
|
||||
Enriched Uranium = Uranium enrichi
|
||||
Uranium Fuel = Uranium 235
|
||||
Diamond Drill Head = Tête de forage en diamant
|
||||
Blue Energy Crystal = Cristal d'énergie bleu
|
||||
Green Energy Crystal = Cristal d'énergie vert
|
||||
Red Energy Crystal = Cristal d'énergie rouge
|
||||
Fine Copper Wire = Fil en cuivre fin
|
||||
Fine Gold Wire = Fil en or fin
|
||||
Fine Silver Wire = Fil en argent fin
|
||||
Copper Coil = Bobine de cuivre
|
||||
Electric Motor = Moteur électrique
|
||||
Low Voltage Transformer = Transformateur basse tension
|
||||
Medium Voltage Transformer = Transformateur moyenne tension
|
||||
High Voltage Transformer = Transformateur haute tension
|
||||
Control Logic Unit = Unité de contrôle logique
|
||||
Mixed Metal Ingot = Lingot de métal allié
|
||||
Composite Plate = Plaque composite
|
||||
Copper Plate = Plaque de cuivre
|
||||
Carbon Plate = Plaque de carbone
|
||||
Graphite = Graphite
|
||||
Carbon Cloth = Fibre de carbone
|
||||
Raw Latex = Latex brut
|
||||
Rubber Fiber = Fibre de caoutchouc
|
||||
%.1f%%-Fissile Uranium Ingot = Lingot d'uranium fissile (%.1f%%)
|
||||
%.1f%%-Fissile Uranium Block = Bloc d'uranium fissile (%.1f%%)
|
||||
|
||||
## Machine misc
|
||||
Machine cannot be removed because it is not empty = La machine ne peut pas être retirée car elle n'est pas vide
|
||||
Inventory move disallowed due to protection = Le mouvement d'inventaire n'est pas autorisé en raison de la protection
|
||||
|
||||
# $1: Machine name (Includes tier)
|
||||
@1 Active (@2 EU) = @1 Active (@2 EU)
|
||||
%s Active = %s actif
|
||||
%s Disabled = %s désactivé
|
||||
%s Enabled = %s activé
|
||||
%s Idle = %s au repos
|
||||
%s Improperly Placed = %s est mal placé
|
||||
%s is empty = %s est vide
|
||||
%s Unpowered = %s non alimenté en énergie
|
||||
%s Out Of Fuel = %s plus de carburant
|
||||
%s Has Bad Cabling = %s est mal cablé
|
||||
%s (Slave) = %s (esclave)
|
||||
%s Has No Network = %s n'a pas de réseau
|
||||
%s Finished = %s a fini
|
||||
Enable/Disable = Activer/Désactiver
|
||||
Range = Plage
|
||||
Upgrade Slots = Emplacement d'amélioration
|
||||
In: = Entrée :
|
||||
Out: = Sortie :
|
||||
Slot %d = Emplacement %d
|
||||
Itemwise = Item par Item
|
||||
Stackwise = Stack par Stack
|
||||
Ignoring Mesecon Signal = Ignorer le signal Mesecon
|
||||
Controlled by Mesecon Signal = Contrôlé par signal Mesecon
|
||||
Owner: = Propriétaire :
|
||||
Unlocked = Déverrouillé
|
||||
Locked = Verrouillé
|
||||
Radius: = Rayon :
|
||||
Enabled = Activé
|
||||
Disabled = Désactivé
|
||||
|
||||
## Machine names
|
||||
# $1: Tier
|
||||
%s Alloy Furnace = Four à alliage %s
|
||||
%s Battery Box = Batterie %s
|
||||
%s Cable = Câble %s
|
||||
%s CNC Machine = Machine-outils %s
|
||||
%s Centrifuge = Centrifugeuse %s
|
||||
%s Compressor = Compresseur %s
|
||||
%s Extractor = Extracteur %s
|
||||
%s Forcefield Emitter = Emetteur de champ de force %s
|
||||
%s Furnace = Four %s
|
||||
%s Grinder = Broyeur %s
|
||||
%s Music Player = Grammophone %s
|
||||
%s Quarry = Carrière %s
|
||||
%s Tool Workshop = Atelier d'outillage %s
|
||||
Arrayed Solar %s Generator = Générateur solaire %s
|
||||
Fuel-Fired %s Generator = Générateur thermique %s
|
||||
Geothermal %s Generator = Géénarteur géothermique %s
|
||||
Hydro %s Generator = Générateur hydroélectrique %s
|
||||
Nuclear %s Generator Core = Générateur nucléaire %
|
||||
Small Solar %s Generator = Petit générateur solaire %s
|
||||
Wind %s Generator = Générateur éolien %s
|
||||
Self-Contained Injector = Injecteur autonome
|
||||
Constructor Mk%d = Constructeur Mk%d
|
||||
Frame = Cadre
|
||||
Frame Motor = Cadre de moteur
|
||||
Template = Modèle
|
||||
Template (replacing) =
|
||||
Template Motor =
|
||||
Template Tool =
|
||||
Battery Box = Compartiment à batterie
|
||||
Supply Converter = Convertisseur de tension
|
||||
Switching Station = Station de commutation
|
||||
Fuel-Fired Alloy Furnace = Four à alliage à carburant
|
||||
Fuel-Fired Furnace = Four à carburant
|
||||
Wind Mill Frame = Cadre d'éolienne
|
||||
Forcefield = Champ de force
|
||||
Nuclear Reactor Rod Compartment = Compartiment à barres du réacteur nucléaire
|
||||
Administrative World Anchor =
|
||||
|
||||
## Machine-specific
|
||||
# $1: Pruduced EU
|
||||
Charge = Charger
|
||||
Discharge = Décharger
|
||||
Power level = Niveau d'énergie
|
||||
|
||||
# $1: Tier $2: current_charge $3: max_charge
|
||||
@1 Battery Box: @2/@3 = @1 batterie : @2/@3
|
||||
|
||||
# $1: Machine name $2: Supply $3: Demand
|
||||
@1. Supply: @2 Demand: @3 = @1. fournit : @2 demande : @3
|
||||
Production at %d%% = Production à %d%%
|
||||
Choose Milling Program: = Choisissez le programme de fraisage :
|
||||
Slim Elements half / normal height: =
|
||||
Current track %s = Morceau actuel %s
|
||||
Stopped = Arrêté
|
||||
Keeping %d/%d map blocks loaded =
|
||||
Digging not started = Creusement non démarré
|
||||
Digging finished = Creusement terminé
|
||||
Digging %d m above machine = Creusement à %dm au dessus de la machine
|
||||
Digging %d m below machine = Creusement à %dm en dessous de la machine
|
||||
@1 (@2 @3 -> @4 @5) = @1 (@2 @3 -> @4 @5)
|
||||
|
||||
## CNC
|
||||
Cylinder =
|
||||
Element Cross = Elément croisé
|
||||
Element Cross Double = Elément croisé (double)
|
||||
Element Edge = Elément de bordure
|
||||
Element Edge Double = Elément de bordure (double)
|
||||
Element End = Elément de fin
|
||||
Element End Double = Elément de fin (double)
|
||||
Element Straight = Elément droit
|
||||
Element Straight Double = Elément droit (double)
|
||||
Element T = Elément en T
|
||||
Element T Double = Elément en T (double)
|
||||
Horizontal Cylinder = Cylindre horizontal
|
||||
One Curved Edge Block = Bloc à un bord incurvé
|
||||
Pyramid = Pyramide
|
||||
Slope = Pente
|
||||
Slope Edge =
|
||||
Slope Inner Edge =
|
||||
Slope Lying =
|
||||
Slope Upside Down =
|
||||
Slope Upside Down Edge =
|
||||
Slope Upside Down Inner Edge =
|
||||
Sphere = Sphère
|
||||
Spike = Pointe
|
||||
Stick = Bâton
|
||||
Two Curved Edge Block = Bloc à deux bords incurvés
|
||||
Brick = Brique
|
||||
Cobble = Pierre taillée
|
||||
Dirt = Terre
|
||||
Leaves = Feuilles
|
||||
Sandstone = Grès
|
||||
Stone = Pierre
|
||||
Tree = Arbre
|
||||
Wooden = Bois
|
||||
|
||||
## Grinder Recipes
|
||||
# $1: Name
|
||||
%s Dust = Poudre de %s
|
||||
Akalin =
|
||||
Alatro =
|
||||
Arol =
|
||||
Brass = Laiton
|
||||
Bronze = Bronze
|
||||
Carbon Steel = Acier au carbone
|
||||
Cast Iron = Fonte
|
||||
Chromium = Chrome
|
||||
Coal = Charbon
|
||||
Copper = Cuivre
|
||||
Gold = Or
|
||||
Mithril = Mithril
|
||||
Silver = Argent
|
||||
Stainless Steel = Acier inoxydable
|
||||
Talinite = Talanite
|
||||
Tin = Etain
|
||||
Wrought Iron = Fer
|
||||
Zinc = Zinc
|
||||
%.1f%%-Fissile Uranium = Uranium fissile (%.1f%%)
|
||||
|
||||
## Tools
|
||||
RE Battery = Batterie RE
|
||||
Water Can = Jerrycan d'eau
|
||||
Lava Can = Jerrycan de lave
|
||||
Chainsaw = Tronçonneuse
|
||||
Flashlight = Lampe-torche
|
||||
3 nodes deep. =
|
||||
3 nodes tall. =
|
||||
3 nodes wide. =
|
||||
3x3 nodes. =
|
||||
Use while sneaking to change Mining Drill Mk%d modes. =
|
||||
Mining Drill Mk%d Mode %d = Foreuse Mk%d Mode %d
|
||||
Mining Drill Mk%d = Foreuse Mk%d
|
||||
Mining Laser Mk%d = Foreuse laser Mk%d
|
||||
Single node. = Mode simple.
|
||||
Sonic Screwdriver = Tournevis supersonique
|
||||
Tree Tap = Robinet à sève
|
||||
|
||||
## Craft descriptions
|
||||
Alloy cooking = Fonderie d'alliage
|
||||
Grinding = Broyage
|
||||
Compressing = Compression
|
||||
Extracting = Extraction
|
||||
Separating = Séparation
|
||||
@@ -0,0 +1,165 @@
|
||||
|
||||
## Misc
|
||||
[Technic] Loaded in %f seconds = [Technic] caricato in %f secondi
|
||||
|
||||
## Items
|
||||
Silicon Wafer = Wafer di silicone
|
||||
Doped Silicon Wafer = Wafer di silicone dopato
|
||||
Enriched Uranium = Uranio arricchito
|
||||
Uranium Fuel = Uranio Combustibile
|
||||
Diamond Drill Head = Trivella diamantata
|
||||
Blue Energy Crystal = Cristallo energetico blu
|
||||
Green Energy Crystal = Cristallo energetico verde
|
||||
Red Energy Crystal = Cristallo energetico rosso
|
||||
Fine Copper Wire = Filo di rame fine
|
||||
Copper Coil = Bobina di rame
|
||||
Electric Motor = Motore elettrico
|
||||
Low Voltage Transformer = Trasformatore in bassa tensione
|
||||
Medium Voltage Transformer = Trasformatore in media tensione
|
||||
High Voltage Transformer = Trasformatore in alta tensione
|
||||
Control Logic Unit = Unità di controllo logica
|
||||
Mixed Metal Ingot = Lingotto in lega ibrida
|
||||
Composite Plate = Lastra composita
|
||||
Copper Plate = Lastra di rame
|
||||
Carbon Plate = Lastra in carbonio
|
||||
Graphite = Lastra in graffite
|
||||
Carbon Cloth = Fibra di carbonio
|
||||
Raw Latex = Latex grezzo
|
||||
Rubber Fiber = Fibra di gomma
|
||||
%.1f%%-Fissile Uranium Ingot = %.1f%%-Lingotto di uranio fissile
|
||||
%.1f%%-Fissile Uranium Block = %.1f%%-Blocco di uranio fissile
|
||||
|
||||
## Machine misc
|
||||
Machine cannot be removed because it is not empty = La macchina non può essere rimossa perchè non è vuota
|
||||
Inventory move disallowed due to protection = Impossibile muovere l'inventario a causa della protezione
|
||||
# $1: Machine name (Includes tier)
|
||||
@1 Active (@2 EU) = @1 Attivo (@2 EU)
|
||||
%s Active = %s Attivo
|
||||
%s Disabled = %s Disabilitato
|
||||
%s Enabled = %s Abilitato
|
||||
%s Idle = %s Inattivo
|
||||
%s Improperly Placed = %s Piazzato impropiamente
|
||||
%s Unpowered = %s Non alimentato
|
||||
%s Out Of Fuel = %s senza carburante
|
||||
%s Has Bad Cabling = %s ha un cablaggio scorretto
|
||||
%s Has No Network = %s non è collegata
|
||||
%s Finished = %s Finito
|
||||
Enable/Disable = Abilita/Disabilita
|
||||
Range = Raggio
|
||||
Upgrade Slots = Alloggi di aggiornamento
|
||||
In: = Ingresso:
|
||||
Out: = Uscita:
|
||||
Slot %d = Alloggio %d
|
||||
Itemwise = Singolo elemento
|
||||
Stackwise = pila completa
|
||||
Owner: = Proprietario:
|
||||
Unlocked = Non chiuso a chiave
|
||||
Locked = Chiuso a chiave
|
||||
Radius: = Raggio:
|
||||
Enabled = Abilitato
|
||||
Disabled = Disabilitato
|
||||
|
||||
## Machine names
|
||||
# $1: Tier
|
||||
%s Alloy Furnace = %s Fornace per leghe
|
||||
%s Battery Box = %s Box batterie
|
||||
%s Cable = Cavo %s
|
||||
%s Compressor = Compressore %s
|
||||
%s Extractor = Estrattore %s
|
||||
%s Forcefield Emitter = Emettitore di campo di forza %s
|
||||
%s Furnace = %s Fornace
|
||||
%s Grinder = %s Tritatutto
|
||||
%s Music Player = Music Player %s
|
||||
%s Quarry = Cava %s
|
||||
%s Tool Workshop = Officina per attrezzi %s
|
||||
Arrayed Solar %s Generator = %s Pannello Solare
|
||||
Fuel-Fired %s Generator = %s Generatore a carbone
|
||||
Geothermal %s Generator = %s Generatore Geotermico
|
||||
Hydro %s Generator = Turbina Elettrica %s
|
||||
Nuclear %s Generator Core = Reattore nucleare %s
|
||||
Small Solar %s Generator = %s Pannello solare
|
||||
Wind %s Generator = %s Generatore eolico
|
||||
Self-Contained Injector = Ignettore
|
||||
Constructor Mk%d = Costruttore Mk%d
|
||||
Frame = Cornice
|
||||
Frame Motor = Cornice del motore
|
||||
Template = Sagoma
|
||||
Template (replacing) = Sagoma (di rimpiazzo)
|
||||
Template Motor = Motore per sagome
|
||||
Template Tool = Strumento per sagome
|
||||
Battery Box = Box batterie
|
||||
Supply Converter = Trasformatore
|
||||
Switching Station = Stazione di controllo
|
||||
Fuel-Fired Alloy Furnace = Fornace per leghe a carbone
|
||||
Fuel-Fired Furnace = Fornace a carbone
|
||||
Wind Mill Frame = Pala eolica
|
||||
Forcefield = Campo di forza
|
||||
Nuclear Reactor Rod Compartment = Compartimento combustibile nucleare
|
||||
Administrative World Anchor = Ancora-mondo amministrativa
|
||||
|
||||
## Machine-specific
|
||||
# $1: Pruduced EU
|
||||
Charge = Carica
|
||||
Discharge = Scarica
|
||||
Power level = Livello di potenza
|
||||
# $1: Tier $2: current_charge $3: max_charge
|
||||
@1 Battery Box: @2/@3 = @1 Box Batterie: @2/@3
|
||||
# $1: Machine name $2: Supply $3: Demand
|
||||
@1. Supply: @2 Demand: @3 = @1. Prodotto: @2 Consumato: @3
|
||||
Production at %d%% = Produzione a %d%%
|
||||
Choose Milling Program: = Scegliere un programma di Fresatura
|
||||
Slim Elements half / normal height: = Metà elementi sottili / altezza normale:
|
||||
Current track %s = Traccia corrente %s
|
||||
Stopped = Fermato
|
||||
Keeping %d/%d map blocks loaded = Mantenimento di %d/%d blocchi mappa caricati
|
||||
Digging not started = Scavo non iniziato
|
||||
Digging finished = Scavo finito
|
||||
Digging %d m above machine = Scavo di %d m sopra la macchina
|
||||
Digging %d m below machine = Scavo di %d m sotto la macchina
|
||||
|
||||
## Grinder Recipes
|
||||
# $1: Name
|
||||
%s Dust = Polvere di %s
|
||||
Akalin = Alcalino
|
||||
Alatro = Alatro
|
||||
Arol = Arol
|
||||
Brass = Ottone
|
||||
Bronze = Bronzo
|
||||
Carbon Steel = Acciaio al Carbonio
|
||||
Cast Iron = Ghisa
|
||||
Chromium = Cromo
|
||||
Coal = Carbone
|
||||
Copper = Rame
|
||||
Gold = Oro
|
||||
Mithril = Mithril
|
||||
Silver = Argento
|
||||
Stainless Steel = Acciaio Inossidabile
|
||||
Talinite = Talinite
|
||||
Tin = Stagno
|
||||
Wrought Iron = Ferro Battuto
|
||||
Zinc = Zinco
|
||||
%.1f%%-Fissile Uranium = %.1f%%-Uranio fissile
|
||||
|
||||
## Tools
|
||||
RE Battery = Batteria RE
|
||||
Water Can = Serbatoio d'acqua
|
||||
Lava Can = Serbatoio di lava
|
||||
Chainsaw = Motosega
|
||||
Flashlight = Torcia
|
||||
3 nodes deep. = 3 nodi in profondità.
|
||||
3 nodes tall. = 3 nodi in altezza.
|
||||
3 nodes wide. = 3 nodi in larghezza.
|
||||
3x3 nodes. = 3x3 nodi.
|
||||
Use while sneaking to change Mining Drill Mk%d modes. = Premi shift (freccia grossa) e usa per cambiare modalità nella trivella da miniera Mk%d.
|
||||
Mining Drill Mk%d Mode %d = Trivella mk%d in modalità %d
|
||||
Mining Drill Mk%d = Trivella da miniera mk%d
|
||||
Mining Laser Mk%d = Laser da miniera mk%d
|
||||
Single node. = Nodo singolo.
|
||||
Sonic Screwdriver = Cacciavite sonico
|
||||
Tree Tap = Batti albero
|
||||
|
||||
## Craft descriptions
|
||||
Alloy cooking = Cottura lege
|
||||
Grinding = Macinazione
|
||||
Compressing = Compressione
|
||||
Extracting = Estrazione
|
||||
@@ -0,0 +1,175 @@
|
||||
# Polish Translation for Technic mod
|
||||
# Polskie tłumaczenie Technic mod
|
||||
# by mat9117
|
||||
|
||||
## Misc
|
||||
[Technic] Loaded in %f seconds = [Technic] Wczytany w %f sekund
|
||||
|
||||
## Items
|
||||
Silicon Wafer = Płytka krzemowa
|
||||
Doped Silicon Wafer = Domieszkowana płytka krzemowa
|
||||
Enriched Uranium = Wzbogacony uran
|
||||
Uranium Fuel = Paliwo uranowe
|
||||
Diamond Drill Head = Diamentowa głowica wiertła
|
||||
Blue Energy Crystal = Niebieski kryształ energii
|
||||
Green Energy Crystal = Zielony kryształ energii
|
||||
Red Energy Crystal = Czerwony kryształ energii
|
||||
Fine Copper Wire = Cienki miedziany drut
|
||||
Copper Coil = Miedziana cewka
|
||||
Electric Motor = Silnik elektryczny
|
||||
Low Voltage Transformer = Transformator niskiego napięcia
|
||||
Medium Voltage Transformer = Transformator średniego napięcia
|
||||
High Voltage Transformer = Transformator wysokiego napięcia
|
||||
Control Logic Unit = Jednostka sterująca
|
||||
Mixed Metal Ingot = Sztabka zmieszanych metali
|
||||
Composite Plate = Płytka kompozytowa
|
||||
Copper Plate = Płytka miedziana
|
||||
Carbon Plate = Płytka węglowa
|
||||
Graphite = Grafit
|
||||
Carbon Cloth = Włókno węglowe
|
||||
Raw Latex = Lateks naturalny
|
||||
Rubber Fiber = Włókno gumowe
|
||||
%.1f%%-Fissile Uranium Ingot = %.1f%% Sztabka uranu
|
||||
%.1f%%-Fissile Uranium Block = %.1f%% Blok uranu
|
||||
|
||||
## Machine misc
|
||||
Machine cannot be removed because it is not empty = Nie można usunąć maszyny, ponieważ nie jest pusta
|
||||
Inventory move disallowed due to protection = Przenoszenie rzeczy z ekwipunku niemożliwe z powodu ochrony
|
||||
# $1: Machine name (Includes tier)
|
||||
@1 Active (@2 EU) = @1 Aktywny (@2 EU)
|
||||
%s Active = %s Aktywny/a
|
||||
%s Disabled = %s Wyłączony/a
|
||||
%s Enabled = %s Włączony/a
|
||||
%s Idle = %s Bezczynny/a
|
||||
%s Improperly Placed = %s Ustawiony/a nieprawidłowo
|
||||
%s is empty = %s jest pusty/a
|
||||
%s Unpowered = %s brak zasilania
|
||||
%s Out Of Fuel = %s brak paliwa
|
||||
%s Has Bad Cabling = %s Źle podłączono kable
|
||||
%s (Slave) =
|
||||
%s Has No Network = %s Nie podłączony/a do sieci
|
||||
%s Finished = %s Ukończony
|
||||
Enable/Disable = Włącz/Wyłącz
|
||||
Range = Zasięg
|
||||
Upgrade Slots = Miejsca na ulepszenia
|
||||
In: = Wejście
|
||||
Out: = Wyjście
|
||||
Slot %d = Otwór %d
|
||||
Itemwise = Jeden przedmiot
|
||||
Stackwise = Cały stack
|
||||
Ignoring Mesecon Signal = Ignoruj sygnał Mesecon
|
||||
Controlled by Mesecon Signal = Sterowany sygnałem Mesecon
|
||||
Owner: = Właściciel:
|
||||
Unlocked = Odblokowany/a
|
||||
Locked = Zablokowany/a
|
||||
Radius: = Promień:
|
||||
Enabled = Włączony/a
|
||||
Disabled = Wyłączony/a
|
||||
|
||||
## Machine names
|
||||
# $1: Tier
|
||||
%s Alloy Furnace = %s Piec stopowy
|
||||
%s Battery Box = %s Skrzynka baterii
|
||||
%s Cable = %s Przewód
|
||||
%s Centrifuge = %s Centryfuga
|
||||
%s Compressor = %s Kompresor
|
||||
%s Extractor = %s Ekstraktor
|
||||
%s Forcefield Emitter = %s Emiter pola siłowego
|
||||
%s Furnace = %s Piec
|
||||
%s Grinder = %s Młynek
|
||||
%s Music Player = %s Odtwarzacz muzyki
|
||||
%s Quarry = %s Kamieniołom
|
||||
%s Tool Workshop = %s Warsztat narzędzi
|
||||
Arrayed Solar %s Generator = %s Szeregowy generator słoneczny
|
||||
Fuel-Fired %s Generator = %s Generator zasilany paliwem
|
||||
Geothermal %s Generator = %s Generator geotermalny
|
||||
Hydro %s Generator = %s Hydrogenerator
|
||||
Nuclear %s Generator Core = %s Reaktor atomowy
|
||||
Small Solar %s Generator = %s Mały generator słoneczny
|
||||
Wind %s Generator = %s Generator wiatrowy
|
||||
Self-Contained Injector = Samowystarczalny wtryskiwacz
|
||||
Constructor Mk%d = Konstruktor Mk%d
|
||||
Frame = Klatka
|
||||
Frame Motor = Silnik klatkowy
|
||||
Template = Szablon
|
||||
Template (replacing) = Szablon (zastępczy)
|
||||
Template Motor =Szablon silnika
|
||||
Template Tool = Szablon narzędzia
|
||||
Battery Box = Skrzynka baterii
|
||||
Supply Converter = Konwerter zasilania
|
||||
Switching Station = Rozdzielnia
|
||||
Fuel-Fired Alloy Furnace = Piec stopowy zasilany paliwem
|
||||
Fuel-Fired Furnace = Piec zasilany paliwem
|
||||
Wind Mill Frame = Klatka wiatraka
|
||||
Forcefield = Pole siłowe
|
||||
Nuclear Reactor Rod Compartment = Komora rdzenia reaktora atomowego
|
||||
Administrative World Anchor = Administracyjna kotwica świata
|
||||
|
||||
## Machine-specific
|
||||
# $1: Pruduced EU
|
||||
Charge = Ładuj
|
||||
Discharge = Rozładuj
|
||||
Power level = Poziom zasilania
|
||||
# $1: Tier $2: current_charge $3: max_charge
|
||||
@1 Battery Box: @2/@3 = @1 Skrzynka baterii: @2/@3
|
||||
# $1: Machine name $2: Supply $3: Demand
|
||||
@1. Supply: @2 Demand: @3 = @1. Zapas: @2 Pobór: @3
|
||||
Production at %d%% = Produkowanie w %d%%
|
||||
Choose Milling Program: = Wybierz program mielenia:
|
||||
Slim Elements half / normal height: = Małe elementy połowa / normalna wysokość:
|
||||
Current track %s =
|
||||
Stopped = Zatrzymany/a
|
||||
Keeping %d/%d map blocks loaded = Ciągle ładuję %d/%d bloki mapy
|
||||
Digging not started = Nie rozpoczęto kopania
|
||||
Digging finished = Kopanie skończone
|
||||
Digging %d m above machine = Kopię %d m nad maszyną
|
||||
Digging %d m below machine = Kopię %d m pod maszyną
|
||||
@1 (@2 @3 -> @4 @5) = @1 (@2 @3 -> @4 @5)
|
||||
|
||||
## Grinder Recipes
|
||||
# $1: Name
|
||||
%s Dust = %s Pył
|
||||
Akalin = Akalinowy
|
||||
Alatro = Alatrowy
|
||||
Arol = Arolowy
|
||||
Brass = Mosiądzu
|
||||
Bronze = Brązu
|
||||
Carbon Steel = Stali węglowej
|
||||
Cast Iron = Żeliwa
|
||||
Chromium = Chromu
|
||||
Coal = Węglowy
|
||||
Copper = Miedzi
|
||||
Gold = Złoty
|
||||
Mithril = Mithrilu
|
||||
Silver = Srebrny
|
||||
Stainless Steel = Stali nierdzewnej
|
||||
Talinite = Talinitu
|
||||
Tin = Cyny
|
||||
Wrought Iron = Kutego żelaza
|
||||
Zinc = Cynku
|
||||
%.1f%%-Fissile Uranium = %.1f%% Uranu
|
||||
|
||||
## Tools
|
||||
RE Battery = Bateria ładowalna
|
||||
Water Can = Kanister wody
|
||||
Lava Can = Kanister lawy
|
||||
Chainsaw = Piła łańcuchowa
|
||||
Flashlight = Latarka
|
||||
3 nodes deep. = Głęboki na 3 bloki.
|
||||
3 nodes tall. = Wysoki na 3 bloki.
|
||||
3 nodes wide. = Szeroki na 3 bloki.
|
||||
3x3 nodes. = 3x3 bloki.
|
||||
Use while sneaking to change Mining Drill Mk%d modes. = Użyj podczas skradania, aby zmienić tryby wiertła górniczego Mk%d
|
||||
Mining Drill Mk%d Mode %d = Tryb wiertła górniczego Mk%d
|
||||
Mining Drill Mk%d = Wiertło górnicze Mk%d
|
||||
Mining Laser Mk%d = Laser górniczy Mk%d
|
||||
Single node. = Pojedynczy blok.
|
||||
Sonic Screwdriver = Dźwiękowy śrubokręt
|
||||
Tree Tap = Nacinak drzewny
|
||||
|
||||
## Craft descriptions
|
||||
Alloy cooking = Stapianie
|
||||
Grinding = Mielenie
|
||||
Compressing = Kompresowanie
|
||||
Extracting = Ekstrakcja
|
||||
Separating = Oddzielanie
|
||||
@@ -0,0 +1,211 @@
|
||||
# Braziliam portuguese translation for technic
|
||||
# Tradução portuguesa brasileira para technic
|
||||
# By Sires
|
||||
|
||||
## Misc
|
||||
[Technic] Loaded in %f seconds = [Technic] Carregado em %f segundos
|
||||
|
||||
## Items
|
||||
Silicon Wafer = Pastilha de Silício
|
||||
Doped Silicon Wafer = Pastilha de Silício Dopada
|
||||
Enriched Uranium = Urânio Enriquecido
|
||||
Uranium Fuel = Combustivel de Urânio
|
||||
Diamond Drill Head = Cabeça de Broca de Diamante
|
||||
Blue Energy Crystal = Cristal de Energia Azul
|
||||
Green Energy Crystal = Cristal de Energia Verde
|
||||
Red Energy Crystal = Cristal de Energia Vermelho
|
||||
Fine Copper Wire = Fio Fino de Cobre
|
||||
Copper Coil = Bobina de Cobre
|
||||
Electric Motor = Motor Elétrico
|
||||
Low Voltage Transformer = Transformador de Baixa Voltagem
|
||||
Medium Voltage Transformer = Transformador de Média Voltagem
|
||||
High Voltage Transformer = Transformador de Alta Voltagem
|
||||
Control Logic Unit = Unidade de Controle Lógico
|
||||
Mixed Metal Ingot = Lingote de Metal Misturado
|
||||
Composite Plate = Placa Composta
|
||||
Copper Plate = Placa de Cobre
|
||||
Carbon Plate = Placa de Carbono
|
||||
Graphite = Grafite
|
||||
Carbon Cloth = Recido de Carbono
|
||||
Raw Latex = Latex bruto
|
||||
Rubber Fiber = Fibra de Borracha
|
||||
%.1f%%-Fissile Uranium Ingot = Lingote de Urânio %.1f%%-Físsil
|
||||
%.1f%%-Fissile Uranium Block = Bloco de Urânio %.1f%%-Físsil
|
||||
|
||||
## Machine Misc
|
||||
Machine cannot be removed because it is not empty = A máquina não pode ser removida porque ela não está vazia
|
||||
Inventory move disallowed due to protection = Movimento de inventário não permitido pela proteção
|
||||
# $1: Machine name (includes tier)
|
||||
@1 Active (@2 EU) = @1 Ativo (@2 EU)
|
||||
%s Active = %s Ativo
|
||||
%s Disabled = %s Ativado
|
||||
%s Enabled = %s Desativado
|
||||
%s Idle = Ócio
|
||||
%s Improperly Placed = %s Colocado Inapropriadamente
|
||||
%s is empty = %s está vazio
|
||||
%s Unpowered = %s Sem energia
|
||||
%s Out Of Fuel = %s Sem Combustível
|
||||
%s Has Bad Cabling = %s Tem Cabeamento Ruim
|
||||
%s (Slave) = %s (Servo)
|
||||
%s Has No Network = %s Não Tem Rede
|
||||
%s Finished = %s Acabou
|
||||
Enable/Disable = Ativar/Desativar
|
||||
Range = Alcance
|
||||
Upgrade Slots = Lugares para Melhoria
|
||||
In: = Entrada:
|
||||
Out: = Saída:
|
||||
Slot %d = Lugar %d
|
||||
Itemwise = Por item
|
||||
Stackwise = Por pilha
|
||||
Ignoring Mesecon Signal = Ignorar Sinaal de Mesecon
|
||||
Controlled by Mesecon Signal = Controlado por Sinal de Mesecon
|
||||
Owner: = Dono:
|
||||
Unlocked = Destravado
|
||||
Locked = Travado
|
||||
Radius: = Raio:
|
||||
Enabled = Ativado
|
||||
Disabled = Desativado
|
||||
|
||||
## Machine names
|
||||
# $1: Tier
|
||||
%s Alloy Furnace = Fornalha de Liga %s
|
||||
%s Battery Box = Caixa de Bateria %s
|
||||
%s Cable = Cabo %s
|
||||
%s CNC Machine = Máquina CNC %s
|
||||
%s Centrifuge = Centrifuga %s
|
||||
%s Compressor = Compresso %s
|
||||
%s Extractor = Extrator %s
|
||||
%s Forcefield Emitter = Emissor de Campo de Força %s
|
||||
%s Furnace = Fornalha %s
|
||||
%s Grinder = Triturador %s
|
||||
%s Music Player = Tocador de Música %s
|
||||
%s Quarry = Pedreira %s
|
||||
%s Tool Workshop = Oficina de Ferramentas %s
|
||||
Arrayed Solar %s Generator = Gerador Solar Equipado %s
|
||||
Fuel-Fired %s Generator = Gerador Alimentado-por-Combustível %s
|
||||
Geothermal %s Generator = Gerador Geotermal %s
|
||||
Hydro %s Generator = Gerador Hidráulico %s
|
||||
Nuclear %s Generator Core = Núcleo de Gerador Nuclear %s
|
||||
Small Solar %s Generator = Gerador Solar Pequeno %s
|
||||
Wind %s Generator = Gerador de Energia Eólica %s
|
||||
Self-Contained Injector = Injetor Auto-Contido
|
||||
Constructor Mk%d = Construtor Nv%d
|
||||
Frame = Armação
|
||||
Frame Motor = Motor de Armação
|
||||
Template = Modelo
|
||||
Template (replacing) = Modelo (recolocando)
|
||||
Template Motor = Modelo de Motor
|
||||
Template Tool = Modelo de Ferramenta
|
||||
Battery Box = Caixa de Bateria
|
||||
Supply Converter = Conversor de Energia
|
||||
Switching Station = Estação de Comutação
|
||||
Fuel-Fired Alloy Furnace = Fornalha de Liga Alimentada-por-Combustível
|
||||
Fuel-Fired Furnace = Fornalha Alimentada-por-Combustível
|
||||
Wind Mill Frame = Armação de Moinho de Vento
|
||||
Forcefield = Campo de Força
|
||||
Nuclear Reactor Rod Compartment = Compartimento de Barra do Reator Nuclear
|
||||
Administrative World Anchor = Âncora de Mundo Administrativa
|
||||
|
||||
## Machine-specific
|
||||
# $1: Pruduced EU
|
||||
Charge = Carregar
|
||||
Discharge = Descarregar
|
||||
Power level = Nível de Energia
|
||||
# $1: Tier $2: current_charge $3: max_charge
|
||||
@1 Battery Box: @2/@3 = Caixa de Baterias @1: @2/@3
|
||||
# $1: Machine name $2: Supply $3: Demand
|
||||
@1. Supply: @2 Demand: @3 = @1. Suprimento: @2 Demanda: @3
|
||||
Production at %d%% = Produção em %d%%
|
||||
Choose Milling Program: = Escolha o Programa de Serragem:
|
||||
Slim Elements half / normal height: = Metade de Elementos Finos / altura normal:
|
||||
Current track %s = Música Atual %s
|
||||
Stopped = Parado
|
||||
Keeping %d/%d map blocks loaded = Mantendo %d/%d blocos de mapa carregados
|
||||
Digging not started = Escavação não começada
|
||||
Digging finished = Escavação terminada
|
||||
Digging %d m above machine = Escavando %d m acima da máquina
|
||||
Digging %d m below machine = Escavando %d m abaixo da máquina
|
||||
@1 (@2 @3 -> @4 @5) = @1 (@2 @3 -> @4 @5)
|
||||
|
||||
## CNC
|
||||
Cylinder = Cilindro
|
||||
Element Cross = Cruz do Elemento
|
||||
Element Cross Double = Cruz Dupla do Elemento
|
||||
Element Edge = Borda do Elemento
|
||||
Element Edge Double = Borda Dupla do Elemento
|
||||
Element End = Final do Elemento
|
||||
Element End Double = Final Duplo do Elemento
|
||||
Element Straight = Elemento Contínuo
|
||||
Element Straight Double = Elemento Contínuo duplo
|
||||
Element T = Elemento em T
|
||||
Element T Double = Elemento em T Duplo
|
||||
Horizontal Cylinder = Cilindro Horizontal
|
||||
One Curved Edge Block = Uma Borda de Bloco Curvada
|
||||
Pyramid = Pirâmide
|
||||
Slope = Ladeira
|
||||
Slope Edge = Canto de Ladeira
|
||||
Slope Inner Edge = Canto de Dentro de Ladeira
|
||||
Slope Lying = Ladeira Deitada
|
||||
Slope Upside Down = Ladeira de Cabeça para Baixo
|
||||
Slope Upside Down Edge = Cande de Ladeira de Cabeça para Baixo
|
||||
Slope Upside Down Inner Edge = Canto de Dentro de Ladeira de Cabeça para Baixo
|
||||
Sphere = Esfera
|
||||
Spike = Espinho
|
||||
Stick = Graveto
|
||||
Two Curved Edge Block = Bloco de Duas Bordas Curvadas
|
||||
Brick = Tijolo
|
||||
Cobble = Pedregulho
|
||||
Dirt = Terra
|
||||
Leaves = Folhas
|
||||
Sandstone = Arenito
|
||||
Stone = Pedra
|
||||
Tree = Árvore
|
||||
Wooden = de Madeira
|
||||
|
||||
## Grinder Recipes
|
||||
# $1: Name
|
||||
%s Dust = Pó de %s
|
||||
Akalin = Akalin
|
||||
Alatro = Alatro
|
||||
Arol = Arol
|
||||
Brass = Latão
|
||||
Bronze = Bronze
|
||||
Carbon Steel = Aço Carbono
|
||||
Cast Iron = Ferro Fundido
|
||||
Chromium = Crômio
|
||||
Coal = Carvão
|
||||
Copper = Cobre
|
||||
Gold = Ouro
|
||||
Mithril = Mithril
|
||||
Silver = Prata
|
||||
Stainless Steel = Aço Inoxidável
|
||||
Talinite = Talinite
|
||||
Tin = Estanho
|
||||
Wrought Iron = Ferro Forjado
|
||||
Zinc = Zinco
|
||||
%.1f%%-Fissile Uranium = Urânio %.1f%%-Físsil
|
||||
|
||||
## Tools
|
||||
RE Battery = Bateria RE
|
||||
Water Can = Lata de Água
|
||||
Lava Can = Lata de Lava
|
||||
Chainsaw = Motosserra
|
||||
Flashlight = Lanterna
|
||||
3 nodes deep. = 3 nodes de profundidade.
|
||||
3 nodes tall. = 3 nodes de altura.
|
||||
3 nodes wide. = 3 nodes de largura.
|
||||
3x3 nodes. = 3x3 nodes.
|
||||
Use while sneaking to change Mining Drill Mk%d modes. = Use enquanto esgueirando para mudar os modos da Broca de Mineração Nv%d.
|
||||
Mining Drill Mk%d Mode %d = Broca de Mineração Nv%d Modo %d
|
||||
Mining Drill Mk%d = Broca de Mineração Nv%d
|
||||
Mining Laser Mk%d = Laser de Mineração Nv%d
|
||||
Single node. = Unico node.
|
||||
Sonic Screwdriver = Chave de Fenda Sônica.
|
||||
Tree Tap = Torneira de Árvore
|
||||
|
||||
## Craft descriptions
|
||||
Alloy cooking = Cozinhando em liga
|
||||
Grinding = Triturando
|
||||
Compressing = Comprimindo
|
||||
Extracting = Extraindo
|
||||
Separating = Separando
|
||||
@@ -0,0 +1,178 @@
|
||||
# template.txt
|
||||
# Template for translations of Technic
|
||||
|
||||
|
||||
## Misc
|
||||
[Technic] Loaded in %f seconds =
|
||||
|
||||
## Items
|
||||
Silicon Wafer =
|
||||
Doped Silicon Wafer =
|
||||
Enriched Uranium =
|
||||
Uranium Fuel =
|
||||
Diamond Drill Head =
|
||||
Blue Energy Crystal =
|
||||
Green Energy Crystal =
|
||||
Red Energy Crystal =
|
||||
Fine Copper Wire =
|
||||
Fine Gold Wire =
|
||||
Fine Silver Wire =
|
||||
Copper Coil =
|
||||
Electric Motor =
|
||||
Low Voltage Transformer =
|
||||
Medium Voltage Transformer =
|
||||
High Voltage Transformer =
|
||||
Control Logic Unit =
|
||||
Mixed Metal Ingot =
|
||||
Composite Plate =
|
||||
Copper Plate =
|
||||
Carbon Plate =
|
||||
Graphite =
|
||||
Carbon Cloth =
|
||||
Raw Latex =
|
||||
Rubber Fiber =
|
||||
%.1f%%-Fissile Uranium Ingot =
|
||||
%.1f%%-Fissile Uranium Block =
|
||||
|
||||
## Machine misc
|
||||
Machine cannot be removed because it is not empty =
|
||||
Inventory move disallowed due to protection =
|
||||
# $1: Machine name (Includes tier)
|
||||
@1 Active (@2 EU) =
|
||||
%s Active =
|
||||
%s Disabled =
|
||||
%s Enabled =
|
||||
%s Idle =
|
||||
%s Improperly Placed =
|
||||
%s is empty =
|
||||
%s Unpowered =
|
||||
%s Out Of Fuel =
|
||||
%s Has Bad Cabling =
|
||||
%s (Slave) =
|
||||
%s Has No Network =
|
||||
%s Finished =
|
||||
Enable/Disable =
|
||||
Range =
|
||||
Upgrade Slots =
|
||||
In: =
|
||||
Out: =
|
||||
Slot %d =
|
||||
Itemwise =
|
||||
Stackwise =
|
||||
Ignoring Mesecon Signal =
|
||||
Controlled by Mesecon Signal =
|
||||
Owner: =
|
||||
Unlocked =
|
||||
Locked =
|
||||
Radius: =
|
||||
Enabled =
|
||||
Disabled =
|
||||
|
||||
## Machine names
|
||||
# $1: Tier
|
||||
%s Alloy Furnace =
|
||||
%s Battery Box =
|
||||
%s Cable =
|
||||
%s Centrifuge =
|
||||
%s Compressor =
|
||||
%s Extractor =
|
||||
%s Forcefield Emitter =
|
||||
%s Furnace =
|
||||
%s Grinder =
|
||||
%s Music Player =
|
||||
%s Quarry =
|
||||
%s Tool Workshop =
|
||||
Arrayed Solar %s Generator =
|
||||
Fuel-Fired %s Generator =
|
||||
Geothermal %s Generator =
|
||||
Hydro %s Generator =
|
||||
Nuclear %s Generator Core =
|
||||
Small Solar %s Generator =
|
||||
Wind %s Generator =
|
||||
Self-Contained Injector =
|
||||
Constructor Mk%d =
|
||||
Frame =
|
||||
Frame Motor =
|
||||
Template =
|
||||
Template (replacing) =
|
||||
Template Motor =
|
||||
Template Tool =
|
||||
Battery Box =
|
||||
Supply Converter =
|
||||
Switching Station =
|
||||
Fuel-Fired Alloy Furnace =
|
||||
Fuel-Fired Furnace =
|
||||
Wind Mill Frame =
|
||||
Forcefield =
|
||||
Nuclear Reactor Rod Compartment =
|
||||
Administrative World Anchor =
|
||||
|
||||
## Machine-specific
|
||||
# $1: Pruduced EU
|
||||
Charge =
|
||||
Discharge =
|
||||
Power level =
|
||||
# $1: Tier $2: current_charge $3: max_charge
|
||||
@1 Battery Box: @2/@3 =
|
||||
# $1: Machine name $2: Supply $3: Demand
|
||||
@1. Supply: @2 Demand: @3 =
|
||||
Production at %d%% =
|
||||
Choose Milling Program: =
|
||||
Slim Elements half / normal height: =
|
||||
Current track %s =
|
||||
Stopped =
|
||||
Keeping %d/%d map blocks loaded =
|
||||
Digging not started =
|
||||
Digging finished =
|
||||
Digging %d m above machine =
|
||||
Digging %d m below machine =
|
||||
@1 (@2 @3 -> @4 @5) =
|
||||
|
||||
|
||||
## Grinder Recipes
|
||||
# $1: Name
|
||||
%s Dust =
|
||||
Akalin =
|
||||
Alatro =
|
||||
Arol =
|
||||
Brass =
|
||||
Bronze =
|
||||
Carbon Steel =
|
||||
Cast Iron =
|
||||
Chromium =
|
||||
Coal =
|
||||
Copper =
|
||||
Gold =
|
||||
Mithril =
|
||||
Silver =
|
||||
Stainless Steel =
|
||||
Talinite =
|
||||
Tin =
|
||||
Wrought Iron =
|
||||
Zinc =
|
||||
%.1f%%-Fissile Uranium =
|
||||
|
||||
## Tools
|
||||
RE Battery =
|
||||
Water Can =
|
||||
Lava Can =
|
||||
Chainsaw =
|
||||
Flashlight =
|
||||
3 nodes deep. =
|
||||
3 nodes tall. =
|
||||
3 nodes wide. =
|
||||
3x3 nodes. =
|
||||
Use while sneaking to change Mining Drill Mk%d modes. =
|
||||
Mining Drill Mk%d Mode %d =
|
||||
Mining Drill Mk%d =
|
||||
Mining Laser Mk%d =
|
||||
Single node. =
|
||||
Sonic Screwdriver =
|
||||
Tree Tap =
|
||||
|
||||
## Craft descriptions
|
||||
Alloy cooking =
|
||||
Grinding =
|
||||
Compressing =
|
||||
Extracting =
|
||||
Separating =
|
||||
@@ -0,0 +1,145 @@
|
||||
# Author: wzy2006 <3450354617@qq.com>
|
||||
# Template for translations of Technic
|
||||
[Technic] Loaded in %f seconds =[Technic]在%f秒内加载完成
|
||||
Silicon Wafer =硅晶片
|
||||
Doped Silicon Wafer =硅芯片
|
||||
Enriched Uranium =浓缩铀
|
||||
Uranium Fuel =铀燃料
|
||||
Diamond Drill Head =金刚石钻头
|
||||
Blue Energy Crystal =蓝色能量水晶
|
||||
Green Energy Crystal =绿色能源水晶
|
||||
Red Energy Crystal =红色能量水晶
|
||||
Fine Copper Wire =细铜线
|
||||
Copper Coil =铜盘管
|
||||
Electric Motor =电动马达
|
||||
Low Voltage Transformer =低压变压器
|
||||
Medium Voltage Transformer =中压变压器
|
||||
High Voltage Transformer =高压变压器
|
||||
Control Logic Unit =控制逻辑单元
|
||||
Mixed Metal Ingot =混合金属锭
|
||||
Composite Plate =复合材料板
|
||||
Copper Plate =铜板
|
||||
Carbon Plate =碳板
|
||||
Graphite =石墨
|
||||
Carbon Cloth =碳布
|
||||
Raw Latex =生乳胶
|
||||
Rubber Fiber =橡胶纤维
|
||||
%.1f%%-Fissile Uranium Ingot = %.1f%%-裂变铀锭
|
||||
%.1f%%-Fissile Uranium Block = %.1f%%-裂变铀块
|
||||
Machine cannot be removed because it is not empty =机器不能被拆除,因为它不是空的
|
||||
Inventory move disallowed due to protection =库存移动不允许由于保护
|
||||
@1 Active (@2 EU) =@1动作(@2 EU)
|
||||
%s Active =%s 活动
|
||||
%s Disabled =%s 禁用
|
||||
%s Enabled =%s 启用
|
||||
%s Idle =%s 闲置
|
||||
%s Improperly Placed =%s 放置不当
|
||||
%s Unpowered =%s 无能量的
|
||||
%s Out Of Fuel =%s 燃料耗尽
|
||||
%s Has Bad Cabling =%s 布线不良
|
||||
%s Has No Network =%s 未并入电网(也许需要"交换站")
|
||||
%s Finished =%s 完成
|
||||
Enable/Disable =启用/禁用
|
||||
Range =范围
|
||||
Upgrade Slots =升级插槽
|
||||
In: =输入:
|
||||
Out: =输出:
|
||||
Slot %d =插槽 %d
|
||||
Itemwise =逐项
|
||||
Stackwise =逐堆
|
||||
Owner: =拥有者:
|
||||
Unlocked =解锁
|
||||
Locked =锁着的
|
||||
Radius: =半径:
|
||||
Enabled =启用
|
||||
Disabled =禁用
|
||||
%s Alloy Furnace =%s 合金炉
|
||||
%s Battery Box =% s电池盒
|
||||
%s Cable =%s 电缆
|
||||
%s Compressor =%s 压缩机
|
||||
%s Extractor =%s 提取机
|
||||
%s Forcefield Emitter =%s 力场发射器
|
||||
%s Furnace =%s 熔炉
|
||||
%s Grinder =%s 研磨机
|
||||
%s Music Player =%s 音乐播放器
|
||||
%s Quarry =% s采石机
|
||||
%s Tool Workshop =% s工具车间
|
||||
Arrayed Solar %s Generator =太阳能%s发电板
|
||||
Fuel-Fired %s Generator =火力%s发电机
|
||||
Geothermal %s Generator =地热%s发电机
|
||||
Hydro %s Generator =水力%s 发电机
|
||||
Nuclear %s Generator Core =核裂变%s发电机核心
|
||||
Small Solar %s Generator =小型太阳能%s发电板
|
||||
Wind %s Generator =风力%s发电机
|
||||
Self-Contained Injector =独立式输入器
|
||||
Constructor Mk%d =建造器%d
|
||||
Frame =框架
|
||||
Frame Motor =框架电机
|
||||
Template =模板
|
||||
Template (replacing) =模板(替换)
|
||||
Template motor =电动机模板
|
||||
Template tool =工具模板
|
||||
Battery Box =电池盒
|
||||
Supply Converter =电源转换器
|
||||
Switching Station =交换站
|
||||
Fuel-Fired Alloy Furnace =火力合金炉
|
||||
Fuel-Fired Furnace =火力熔炉
|
||||
Wind Mill Frame =风力机框架
|
||||
Forcefield =力场
|
||||
Nuclear Reactor Rod Compartment =核反应堆舱
|
||||
Administrative World Anchor =管理员区块锚
|
||||
Charge =Charge
|
||||
Discharge =Discharge
|
||||
Power level =功率级
|
||||
@1 Battery Box: @2/@3 =@1电池盒:@2/@3
|
||||
@1. Supply: @2 Demand: @3 =@1. 供应: @2 需要: @3
|
||||
Production at %d%% =生产 %d%%
|
||||
Choose Milling Program: =选择研磨程序:
|
||||
Slim Elements half / normal height: =苗条的元素一半/正常高度:
|
||||
Current track %s =电流跟踪%s
|
||||
Stopped =停止
|
||||
Keeping %d/%d map blocks loaded =保持%d/%d地图模块加载
|
||||
Digging not started =没有开始挖掘
|
||||
Digging finished =挖完
|
||||
Digging %d m above machine =挖掘 %d m以上的机器
|
||||
Digging %d m below machine =挖掘 %d m以下的机器
|
||||
%s Dust = %s 粉
|
||||
Akalin =Akalin
|
||||
Alatro =Alatro
|
||||
Arol =Arol
|
||||
Brass =黄铜
|
||||
Bronze =青铜
|
||||
Carbon Steel =碳钢
|
||||
Cast Iron =铸铁
|
||||
Chromium =铬
|
||||
Coal =煤炭
|
||||
Copper =铜
|
||||
Gold =黄金
|
||||
Mithril =秘银
|
||||
Silver =银
|
||||
Stainless Steel =不锈钢
|
||||
Talinite = 绿泥石
|
||||
Tin =锡
|
||||
Wrought Iron =锻铁
|
||||
Zinc =锌
|
||||
%.1f%%-Fissile Uranium =%.1f%%-裂变铀
|
||||
RE Battery =RE 电池
|
||||
Water Can =水罐
|
||||
Lava Can =岩浆罐
|
||||
Chainsaw =电锯
|
||||
Flashlight =手电筒
|
||||
3 nodes deep. =3方块深度。
|
||||
3 nodes tall. =3方块高。
|
||||
3 nodes wide. =3方块宽。
|
||||
3x3 nodes. =3x3 方块.。
|
||||
Use while sneaking to change Mining Drill Mk%d modes. = 潜行时使用可更改采矿钻机Mk%d模式
|
||||
Mining Drill Mk%d Mode %d =采矿钻 MK%d模式%d
|
||||
Mining Drill Mk%d =采矿钻 MK%d
|
||||
Mining Laser Mk%d =采矿激光 MK %d
|
||||
Single node. =单方块。
|
||||
Sonic Screwdriver =声波螺丝刀
|
||||
Tree Tap =树形水龙头
|
||||
Alloy cooking =熔炼合金
|
||||
Grinding =研磨中
|
||||
Compressing =压缩
|
||||
Extracting =提取
|
||||
@@ -0,0 +1,22 @@
|
||||
-- HV battery box
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:hv_battery_box0',
|
||||
recipe = {
|
||||
{'technic:mv_battery_box0', 'technic:mv_battery_box0', 'technic:mv_battery_box0'},
|
||||
{'technic:mv_battery_box0', 'technic:hv_transformer', 'technic:mv_battery_box0'},
|
||||
{'', 'technic:hv_cable', ''},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_battery_box({
|
||||
tier = "HV",
|
||||
max_charge = 1000000,
|
||||
charge_rate = 100000,
|
||||
discharge_rate = 400000,
|
||||
charge_step = 10000,
|
||||
discharge_step = 40000,
|
||||
upgrade = 1,
|
||||
tube = 1,
|
||||
})
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
minetest.register_craft({
|
||||
output = 'technic:hv_cable 3',
|
||||
recipe = {
|
||||
{'homedecor:plastic_sheeting', 'homedecor:plastic_sheeting', 'homedecor:plastic_sheeting'},
|
||||
{'technic:mv_cable', 'technic:mv_cable', 'technic:mv_cable'},
|
||||
{'homedecor:plastic_sheeting', 'homedecor:plastic_sheeting', 'homedecor:plastic_sheeting'},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_cable("HV", 3/16)
|
||||
|
||||
if minetest.get_modpath("digilines") then
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
if minetest.get_modpath("digistuff") then
|
||||
minetest.register_craft({
|
||||
output = 'technic:hv_digi_cable 1',
|
||||
type = "shapeless",
|
||||
recipe = {'digistuff:digimese', 'technic:hv_cable'}
|
||||
})
|
||||
else
|
||||
minetest.register_craft({
|
||||
output = 'technic:hv_digi_cable 1',
|
||||
recipe = {
|
||||
{'digilines:wire_std_00000000', 'digilines:wire_std_00000000', 'digilines:wire_std_00000000'},
|
||||
{'digilines:wire_std_00000000', 'technic:hv_cable', 'digilines:wire_std_00000000'},
|
||||
{'digilines:wire_std_00000000', 'digilines:wire_std_00000000', 'digilines:wire_std_00000000'},
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
technic.register_cable("HV", 3/16, S("HV Cable (digiline)"), "_digi", {
|
||||
digiline = {
|
||||
wire = {
|
||||
rules = {
|
||||
{x = 1, y = 0, z = 0},
|
||||
{x =-1, y = 0, z = 0},
|
||||
{x = 0, y = 1, z = 0},
|
||||
{x = 0, y =-1, z = 0},
|
||||
{x = 0, y = 0, z = 1},
|
||||
{x = 0, y = 0, z =-1}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
@@ -0,0 +1,12 @@
|
||||
-- HV compressor
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:hv_compressor',
|
||||
recipe = {
|
||||
{'technic:carbon_plate', 'technic:mv_compressor', 'technic:composite_plate'},
|
||||
{'pipeworks:tube_1', 'technic:hv_transformer', 'pipeworks:tube_1'},
|
||||
{'technic:stainless_steel_ingot', 'technic:hv_cable', 'technic:stainless_steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_compressor({tier = "HV", demand = {1500, 1000, 750}, speed = 5, upgrade = 1, tube = 1})
|
||||
@@ -0,0 +1,18 @@
|
||||
-- MV Electric Furnace
|
||||
-- This is a faster version of the stone furnace which runs on EUs
|
||||
-- In addition to this it can be upgraded with microcontrollers and batteries
|
||||
-- This new version uses the batteries to lower the power consumption of the machine
|
||||
-- Also in addition this furnace can be attached to the pipe system from the pipeworks mod.
|
||||
|
||||
-- FIXME: kpoppel I'd like to introduce an induction heating element here also
|
||||
minetest.register_craft({
|
||||
output = 'technic:hv_electric_furnace',
|
||||
recipe = {
|
||||
{'technic:stainless_steel_ingot', 'technic:mv_electric_furnace', 'technic:stainless_steel_ingot'},
|
||||
{'pipeworks:tube_1', 'technic:hv_transformer', 'pipeworks:tube_1'},
|
||||
{'technic:stainless_steel_ingot', 'technic:hv_cable', 'technic:stainless_steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_electric_furnace({tier="HV", upgrade=1, tube=1, demand={4000, 2500, 1500}, speed=12})
|
||||
|
||||
@@ -0,0 +1,390 @@
|
||||
--- Forcefield generator.
|
||||
-- @author ShadowNinja
|
||||
--
|
||||
-- Forcefields are powerful barriers but they consume huge amounts of power.
|
||||
-- The forcefield Generator is an HV machine.
|
||||
|
||||
-- How expensive is the generator?
|
||||
-- Leaves room for upgrades lowering the power drain?
|
||||
local digilines_path = minetest.get_modpath("digilines")
|
||||
|
||||
local forcefield_power_drain = 10
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
local cable_entry = "^technic_cable_connection_overlay.png"
|
||||
|
||||
minetest.register_craft({
|
||||
output = "technic:forcefield_emitter_off",
|
||||
recipe = {
|
||||
{"default:mese", "basic_materials:motor", "default:mese" },
|
||||
{"technic:deployer_off", "technic:machine_casing", "technic:deployer_off"},
|
||||
{"default:mese", "technic:hv_cable", "default:mese" },
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
local replaceable_cids = {}
|
||||
|
||||
minetest.after(0, function()
|
||||
for name, ndef in pairs(minetest.registered_nodes) do
|
||||
if ndef.buildable_to == true and name ~= "ignore" then
|
||||
replaceable_cids[minetest.get_content_id(name)] = true
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
-- Idea: Let forcefields have different colors by upgrade slot.
|
||||
-- Idea: Let forcefields add up by detecting if one hits another.
|
||||
-- ___ __
|
||||
-- / \/ \
|
||||
-- | |
|
||||
-- \___/\___/
|
||||
|
||||
local function update_forcefield(pos, meta, active)
|
||||
|
||||
if active then
|
||||
-- rate limit by chance
|
||||
if math.floor(math.random()*4) ~= 0 then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local shape = meta:get_int("shape")
|
||||
local range = meta:get_int("range")
|
||||
local vm = VoxelManip()
|
||||
local MinEdge, MaxEdge = vm:read_from_map(vector.subtract(pos, range),
|
||||
vector.add(pos, range))
|
||||
local area = VoxelArea:new({MinEdge = MinEdge, MaxEdge = MaxEdge})
|
||||
local data = vm:get_data()
|
||||
|
||||
local c_air = minetest.get_content_id("air")
|
||||
local c_field = minetest.get_content_id("technic:forcefield")
|
||||
|
||||
for z = -range, range do
|
||||
for y = -range, range do
|
||||
local vi = area:index(pos.x + (-range), pos.y + y, pos.z + z)
|
||||
for x = -range, range do
|
||||
local relevant
|
||||
if shape == 0 then
|
||||
local squared = x * x + y * y + z * z
|
||||
relevant =
|
||||
squared <= range * range + range and
|
||||
squared >= (range - 1) * (range - 1) + (range - 1)
|
||||
else
|
||||
relevant =
|
||||
x == -range or x == range or
|
||||
y == -range or y == range or
|
||||
z == -range or z == range
|
||||
end
|
||||
if relevant then
|
||||
local cid = data[vi]
|
||||
if active and replaceable_cids[cid] then
|
||||
data[vi] = c_field
|
||||
elseif not active and cid == c_field then
|
||||
data[vi] = c_air
|
||||
end
|
||||
end
|
||||
vi = vi + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
vm:set_data(data)
|
||||
vm:update_liquids()
|
||||
vm:write_to_map()
|
||||
end
|
||||
|
||||
local function set_forcefield_formspec(meta)
|
||||
local formspec
|
||||
if digilines_path then
|
||||
formspec = "size[5,3.25]"..
|
||||
"field[0.3,3;5,1;channel;Digiline Channel;"..meta:get_string("channel").."]"
|
||||
else
|
||||
formspec = "size[5,2.25]"
|
||||
end
|
||||
formspec = formspec..
|
||||
"field[0.3,0.5;2,1;range;"..S("Range")..";"..meta:get_int("range").."]"
|
||||
-- The names for these toggle buttons are explicit about which
|
||||
-- state they'll switch to, so that multiple presses (arising
|
||||
-- from the ambiguity between lag and a missed press) only make
|
||||
-- the single change that the user expects.
|
||||
if meta:get_int("shape") == 0 then
|
||||
formspec = formspec.."button[3,0.2;2,1;shape1;"..S("Sphere").."]"
|
||||
else
|
||||
formspec = formspec.."button[3,0.2;2,1;shape0;"..S("Cube").."]"
|
||||
end
|
||||
if meta:get_int("mesecon_mode") == 0 then
|
||||
formspec = formspec.."button[0,1;5,1;mesecon_mode_1;"..S("Ignoring Mesecon Signal").."]"
|
||||
else
|
||||
formspec = formspec.."button[0,1;5,1;mesecon_mode_0;"..S("Controlled by Mesecon Signal").."]"
|
||||
end
|
||||
if meta:get_int("enabled") == 0 then
|
||||
formspec = formspec..
|
||||
"button[0,1.75;5,1;enable;"..S("%s Disabled"):format(S("%s Forcefield Emitter"):format("HV")).."]"
|
||||
else
|
||||
formspec = formspec..
|
||||
"button[0,1.75;5,1;disable;"..S("%s Enabled"):format(S("%s Forcefield Emitter"):format("HV")).."]"
|
||||
end
|
||||
meta:set_string("formspec", formspec)
|
||||
end
|
||||
|
||||
local forcefield_receive_fields = function(pos, formname, fields, sender)
|
||||
local player_name = sender:get_player_name()
|
||||
if minetest.is_protected(pos, player_name) then
|
||||
minetest.chat_send_player(player_name, "You are not allowed to edit this!")
|
||||
minetest.record_protection_violation(pos, player_name)
|
||||
return
|
||||
end
|
||||
local meta = minetest.get_meta(pos)
|
||||
local range = nil
|
||||
if fields.range then
|
||||
range = tonumber(fields.range) or 0
|
||||
-- Smallest field is 5. Anything less is asking for trouble.
|
||||
-- Largest is 20. It is a matter of pratical node handling.
|
||||
-- At the maximim range updating the forcefield takes about 0.2s
|
||||
range = math.max(range, 5)
|
||||
range = math.min(range, 20)
|
||||
if range == meta:get_int("range") then range = nil end
|
||||
end
|
||||
if fields.shape0 or fields.shape1 or range then
|
||||
update_forcefield(pos, meta, false)
|
||||
end
|
||||
if range then meta:set_int("range", range) end
|
||||
if fields.channel then meta:set_string("channel", fields.channel) end
|
||||
if fields.shape0 then meta:set_int("shape", 0) end
|
||||
if fields.shape1 then meta:set_int("shape", 1) end
|
||||
if fields.enable then meta:set_int("enabled", 1) end
|
||||
if fields.disable then meta:set_int("enabled", 0) end
|
||||
if fields.mesecon_mode_0 then meta:set_int("mesecon_mode", 0) end
|
||||
if fields.mesecon_mode_1 then meta:set_int("mesecon_mode", 1) end
|
||||
set_forcefield_formspec(meta)
|
||||
end
|
||||
|
||||
local mesecons = {
|
||||
effector = {
|
||||
action_on = function(pos, node)
|
||||
minetest.get_meta(pos):set_int("mesecon_effect", 1)
|
||||
end,
|
||||
action_off = function(pos, node)
|
||||
minetest.get_meta(pos):set_int("mesecon_effect", 0)
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
local digiline_def = {
|
||||
receptor = {
|
||||
rules = technic.digilines.rules,
|
||||
action = function() end
|
||||
},
|
||||
effector = {
|
||||
rules = technic.digilines.rules,
|
||||
action = function(pos, node, channel, msg)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if channel ~= meta:get_string("channel") then
|
||||
return
|
||||
end
|
||||
local msgt = type(msg)
|
||||
if msgt == "string" then
|
||||
local smsg = msg:lower()
|
||||
msg = {}
|
||||
if smsg == "get" then
|
||||
msg.command = "get"
|
||||
elseif smsg == "off" then
|
||||
msg.command = "off"
|
||||
elseif smsg == "on" then
|
||||
msg.command = "on"
|
||||
elseif smsg == "toggle" then
|
||||
msg.command = "toggle"
|
||||
elseif smsg:sub(1, 5) == "range" then
|
||||
msg.command = "range"
|
||||
msg.value = tonumber(smsg:sub(7))
|
||||
elseif smsg:sub(1, 5) == "shape" then
|
||||
msg.command = "shape"
|
||||
msg.value = smsg:sub(7):lower()
|
||||
msg.value = tonumber(msg.value) or msg.value
|
||||
end
|
||||
elseif msgt ~= "table" then
|
||||
return
|
||||
end
|
||||
if msg.command == "get" then
|
||||
digilines.receptor_send(pos, technic.digilines.rules, channel, {
|
||||
enabled = meta:get_int("enabled"),
|
||||
range = meta:get_int("range"),
|
||||
shape = meta:get_int("shape")
|
||||
})
|
||||
return
|
||||
elseif msg.command == "off" then
|
||||
meta:set_int("enabled", 0)
|
||||
elseif msg.command == "on" then
|
||||
meta:set_int("enabled", 1)
|
||||
elseif msg.command == "toggle" then
|
||||
local onn = meta:get_int("enabled")
|
||||
onn = 1-onn -- Mirror onn with pivot 0.5, so switch between 1 and 0.
|
||||
meta:set_int("enabled", onn)
|
||||
elseif msg.command == "range" then
|
||||
if type(msg.value) ~= "number" then
|
||||
return
|
||||
end
|
||||
msg.value = math.max(msg.value, 5)
|
||||
msg.value = math.min(msg.value, 20)
|
||||
update_forcefield(pos, meta, false)
|
||||
meta:set_int("range", msg.value)
|
||||
elseif msg.command == "shape" then
|
||||
local valuet = type(msg.value)
|
||||
if valuet == "string" then
|
||||
if msg.value == "sphere" then
|
||||
msg.value = 0
|
||||
elseif msg.value == "cube" then
|
||||
msg.value = 1
|
||||
end
|
||||
elseif valuet ~= "number" then
|
||||
return
|
||||
end
|
||||
if not msg.value then
|
||||
return
|
||||
end
|
||||
update_forcefield(pos, meta, false)
|
||||
meta:set_int("shape", msg.value)
|
||||
else
|
||||
return
|
||||
end
|
||||
set_forcefield_formspec(meta)
|
||||
end
|
||||
},
|
||||
}
|
||||
|
||||
local function run(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local eu_input = meta:get_int("HV_EU_input")
|
||||
local enabled = meta:get_int("enabled") ~= 0 and
|
||||
(meta:get_int("mesecon_mode") == 0 or meta:get_int("mesecon_effect") ~= 0)
|
||||
local machine_name = S("%s Forcefield Emitter"):format("HV")
|
||||
|
||||
local range = meta:get_int("range")
|
||||
local power_requirement
|
||||
if meta:get_int("shape") == 0 then
|
||||
power_requirement = math.floor(4 * math.pi * range * range)
|
||||
else
|
||||
power_requirement = 24 * range * range
|
||||
end
|
||||
power_requirement = power_requirement * forcefield_power_drain
|
||||
|
||||
if not enabled then
|
||||
if node.name == "technic:forcefield_emitter_on" then
|
||||
update_forcefield(pos, meta, false)
|
||||
technic.swap_node(pos, "technic:forcefield_emitter_off")
|
||||
meta:set_string("infotext", S("%s Disabled"):format(machine_name))
|
||||
end
|
||||
meta:set_int("HV_EU_demand", 0)
|
||||
return
|
||||
end
|
||||
meta:set_int("HV_EU_demand", power_requirement)
|
||||
if eu_input < power_requirement then
|
||||
meta:set_string("infotext", S("%s Unpowered"):format(machine_name))
|
||||
if node.name == "technic:forcefield_emitter_on" then
|
||||
update_forcefield(pos, meta, false)
|
||||
technic.swap_node(pos, "technic:forcefield_emitter_off")
|
||||
end
|
||||
elseif eu_input >= power_requirement then
|
||||
if node.name == "technic:forcefield_emitter_off" then
|
||||
technic.swap_node(pos, "technic:forcefield_emitter_on")
|
||||
meta:set_string("infotext", S("%s Active"):format(machine_name))
|
||||
end
|
||||
update_forcefield(pos, meta, true)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node("technic:forcefield_emitter_off", {
|
||||
description = S("%s Forcefield Emitter"):format("HV"),
|
||||
tiles = {
|
||||
"technic_forcefield_emitter_off.png",
|
||||
"technic_machine_bottom.png"..cable_entry,
|
||||
"technic_forcefield_emitter_off.png",
|
||||
"technic_forcefield_emitter_off.png",
|
||||
"technic_forcefield_emitter_off.png",
|
||||
"technic_forcefield_emitter_off.png"
|
||||
},
|
||||
groups = {cracky = 1, technic_machine = 1, technic_hv = 1},
|
||||
on_receive_fields = forcefield_receive_fields,
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_int("HV_EU_input", 0)
|
||||
meta:set_int("HV_EU_demand", 0)
|
||||
meta:set_int("range", 10)
|
||||
meta:set_int("enabled", 0)
|
||||
meta:set_int("mesecon_mode", 0)
|
||||
meta:set_int("mesecon_effect", 0)
|
||||
if digilines_path then
|
||||
meta:set_string("channel", "forcefield"..minetest.pos_to_string(pos))
|
||||
end
|
||||
meta:set_string("infotext", S("%s Forcefield Emitter"):format("HV"))
|
||||
set_forcefield_formspec(meta)
|
||||
end,
|
||||
mesecons = mesecons,
|
||||
digiline = digiline_def,
|
||||
technic_run = run,
|
||||
})
|
||||
|
||||
minetest.register_node("technic:forcefield_emitter_on", {
|
||||
description = S("%s Forcefield Emitter"):format("HV"),
|
||||
tiles = {
|
||||
"technic_forcefield_emitter_on.png",
|
||||
"technic_machine_bottom.png"..cable_entry,
|
||||
"technic_forcefield_emitter_on.png",
|
||||
"technic_forcefield_emitter_on.png",
|
||||
"technic_forcefield_emitter_on.png",
|
||||
"technic_forcefield_emitter_on.png"
|
||||
},
|
||||
groups = {cracky = 1, technic_machine = 1, technic_hv = 1,
|
||||
not_in_creative_inventory=1},
|
||||
drop = "technic:forcefield_emitter_off",
|
||||
on_receive_fields = forcefield_receive_fields,
|
||||
on_destruct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
update_forcefield(pos, meta, false)
|
||||
end,
|
||||
mesecons = mesecons,
|
||||
digiline = digiline_def,
|
||||
technic_run = run,
|
||||
technic_on_disable = function (pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
update_forcefield(pos, meta, false)
|
||||
technic.swap_node(pos, "technic:forcefield_emitter_off")
|
||||
end,
|
||||
on_blast = function(pos, intensity)
|
||||
minetest.dig_node(pos)
|
||||
return {"technic:forcefield_emitter_off"}
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_node("technic:forcefield", {
|
||||
description = S("%s Forcefield"):format("HV"),
|
||||
sunlight_propagates = true,
|
||||
drawtype = "glasslike",
|
||||
groups = {not_in_creative_inventory=1},
|
||||
paramtype = "light",
|
||||
light_source = default.LIGHT_MAX,
|
||||
diggable = false,
|
||||
drop = '',
|
||||
tiles = {{
|
||||
name = "technic_forcefield_animated.png",
|
||||
animation = {
|
||||
type = "vertical_frames",
|
||||
aspect_w = 16,
|
||||
aspect_h = 16,
|
||||
length = 1.0,
|
||||
},
|
||||
}},
|
||||
on_blast = function(pos, intensity)
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
if minetest.get_modpath("mesecons_mvps") then
|
||||
mesecon.register_mvps_stopper("technic:forcefield")
|
||||
end
|
||||
|
||||
technic.register_machine("HV", "technic:forcefield_emitter_on", technic.receiver)
|
||||
technic.register_machine("HV", "technic:forcefield_emitter_off", technic.receiver)
|
||||
@@ -0,0 +1,13 @@
|
||||
minetest.register_alias("hv_generator", "technic:hv_generator")
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:hv_generator',
|
||||
recipe = {
|
||||
{'technic:carbon_plate', 'technic:mv_generator', 'technic:composite_plate'},
|
||||
{'pipeworks:tube_1', 'technic:hv_transformer', 'pipeworks:tube_1'},
|
||||
{'technic:stainless_steel_ingot', 'technic:hv_cable', 'technic:stainless_steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_generator({tier="HV", tube=1, supply=1200})
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
-- HV grinder
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:hv_grinder',
|
||||
recipe = {
|
||||
{'technic:carbon_plate', 'technic:mv_grinder', 'technic:composite_plate'},
|
||||
{'pipeworks:tube_1', 'technic:hv_transformer', 'pipeworks:tube_1'},
|
||||
{'technic:stainless_steel_ingot', 'technic:hv_cable', 'technic:stainless_steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_grinder({tier="HV", demand={1200, 900, 600}, speed=5, upgrade=1, tube=1})
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
technic.register_tier("HV", "High Voltage")
|
||||
|
||||
local path = technic.modpath.."/machines/HV"
|
||||
|
||||
-- Wiring stuff
|
||||
dofile(path.."/cables.lua")
|
||||
dofile(path.."/battery_box.lua")
|
||||
|
||||
-- Generators
|
||||
dofile(path.."/solar_array.lua")
|
||||
dofile(path.."/nuclear_reactor.lua")
|
||||
dofile(path.."/generator.lua")
|
||||
|
||||
-- Machines
|
||||
dofile(path.."/quarry.lua")
|
||||
dofile(path.."/forcefield.lua")
|
||||
dofile(path.."/electric_furnace.lua")
|
||||
dofile(path.."/grinder.lua")
|
||||
dofile(path.."/compressor.lua")
|
||||
|
||||
|
||||
@@ -0,0 +1,514 @@
|
||||
--[[
|
||||
The enriched uranium rod driven EU generator.
|
||||
A very large and advanced machine providing vast amounts of power.
|
||||
Very efficient but also expensive to run as it needs uranium.
|
||||
Provides 10000 HV EUs for one week (only counted when loaded).
|
||||
|
||||
The nuclear reactor core requires a casing of water and a protective
|
||||
shield to work. This is checked now and then and if the casing is not
|
||||
intact the reactor will melt down!
|
||||
--]]
|
||||
|
||||
local burn_ticks = 7 * 24 * 60 * 60 -- Seconds
|
||||
local power_supply = 100000 -- EUs
|
||||
local fuel_type = "technic:uranium_fuel" -- The reactor burns this
|
||||
local digiline_meltdown = technic.config:get_bool("enable_nuclear_reactor_digiline_selfdestruct")
|
||||
local has_digilines = minetest.get_modpath("digilines")
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
local reactor_desc = S("@1 Nuclear Reactor Core", S("HV"))
|
||||
local cable_entry = "^technic_cable_connection_overlay.png"
|
||||
|
||||
-- FIXME: Recipe should make more sense like a rod recepticle, steam chamber, HV generator?
|
||||
minetest.register_craft({
|
||||
output = 'technic:hv_nuclear_reactor_core',
|
||||
recipe = {
|
||||
{'technic:carbon_plate', 'default:obsidian_glass', 'technic:carbon_plate'},
|
||||
{'technic:composite_plate', 'technic:machine_casing', 'technic:composite_plate'},
|
||||
{'technic:stainless_steel_ingot', 'technic:hv_cable', 'technic:stainless_steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
local function make_reactor_formspec(meta)
|
||||
local f = "size[8,9]"..
|
||||
"label[0,0;"..S("Nuclear Reactor Rod Compartment").."]"..
|
||||
"list[context;src;2,1;3,2;]"..
|
||||
"list[current_player;main;0,5;8,4;]"..
|
||||
"listring[]"..
|
||||
"button[5.5,1.5;2,1;start;Start]"..
|
||||
"checkbox[5.5,2.5;autostart;automatic Start;"..meta:get_string("autostart").."]"
|
||||
if not has_digilines then
|
||||
return f
|
||||
end
|
||||
local digiline_enabled = meta:get_string("enable_digiline")
|
||||
f = f.."checkbox[0.5,2.8;enable_digiline;Enable Digiline;"..digiline_enabled.."]"
|
||||
if digiline_enabled ~= "true" then
|
||||
return f
|
||||
end
|
||||
return f..
|
||||
"button_exit[4.6,3.69;2,1;save;Save]"..
|
||||
"field[1,4;4,1;remote_channel;Digiline Remote Channel;${remote_channel}]"
|
||||
end
|
||||
|
||||
local SS_OFF = 0
|
||||
local SS_DANGER = 1
|
||||
local SS_CLEAR = 2
|
||||
|
||||
local reactor_siren = {}
|
||||
local function siren_set_state(pos, state)
|
||||
local hpos = minetest.hash_node_position(pos)
|
||||
local siren = reactor_siren[hpos]
|
||||
if not siren then
|
||||
if state == SS_OFF then return end
|
||||
siren = {state=SS_OFF}
|
||||
reactor_siren[hpos] = siren
|
||||
end
|
||||
if state == SS_DANGER and siren.state ~= SS_DANGER then
|
||||
if siren.handle then minetest.sound_stop(siren.handle) end
|
||||
siren.handle = minetest.sound_play("technic_hv_nuclear_reactor_siren_danger_loop",
|
||||
{pos=pos, gain=1.5, loop=true, max_hear_distance=48})
|
||||
siren.state = SS_DANGER
|
||||
elseif state == SS_CLEAR then
|
||||
if siren.handle then minetest.sound_stop(siren.handle) end
|
||||
local clear_handle = minetest.sound_play("technic_hv_nuclear_reactor_siren_clear",
|
||||
{pos=pos, gain=1.5, loop=false, max_hear_distance=48})
|
||||
siren.handle = clear_handle
|
||||
siren.state = SS_CLEAR
|
||||
minetest.after(10, function()
|
||||
if siren.handle ~= clear_handle then return end
|
||||
minetest.sound_stop(clear_handle)
|
||||
if reactor_siren[hpos] == siren then
|
||||
reactor_siren[hpos] = nil
|
||||
end
|
||||
end)
|
||||
elseif state == SS_OFF and siren.state ~= SS_OFF then
|
||||
if siren.handle then minetest.sound_stop(siren.handle) end
|
||||
reactor_siren[hpos] = nil
|
||||
end
|
||||
end
|
||||
|
||||
local function siren_danger(pos, meta)
|
||||
meta:set_int("siren", 1)
|
||||
siren_set_state(pos, SS_DANGER)
|
||||
end
|
||||
|
||||
local function siren_clear(pos, meta)
|
||||
if meta:get_int("siren") ~= 0 then
|
||||
siren_set_state(pos, SS_CLEAR)
|
||||
meta:set_int("siren", 0)
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
The standard reactor structure consists of a 9x9x9 cube. A cross
|
||||
section through the middle:
|
||||
|
||||
CCCC CCCC
|
||||
CBBB BBBC
|
||||
CBLL LLBC
|
||||
CBLWWWLBC
|
||||
CBLW#WLBC
|
||||
CBLW|WLBC
|
||||
CBLL|LLBC
|
||||
CBBB|BBBC
|
||||
CCCC|CCCC
|
||||
C = Concrete, B = Blast-resistant concrete, L = Lead,
|
||||
W = water node, # = reactor core, | = HV cable
|
||||
|
||||
The man-hole is optional (but necessary for refueling).
|
||||
|
||||
For the reactor to operate and not melt down, it insists on the inner
|
||||
7x7x7 portion (from the core out to the blast-resistant concrete)
|
||||
being intact. Intactness only depends on the number of nodes of the
|
||||
right type in each layer. The water layer must have water in all but
|
||||
at most one node; the steel and blast-resistant concrete layers must
|
||||
have the right material in all but at most two nodes. The permitted
|
||||
gaps are meant for the cable and man-hole, but can actually be anywhere
|
||||
and contain anything. For the reactor to be useful, a cable must
|
||||
connect to the core, but it can go in any direction.
|
||||
|
||||
The outer concrete layer of the standard structure is not required
|
||||
for the reactor to operate. It is noted here because it used to
|
||||
be mandatory, and for historical reasons (that it predates the
|
||||
implementation of radiation) it needs to continue being adequate
|
||||
shielding of legacy reactors. If it ever ceases to be adequate
|
||||
shielding for new reactors, legacy ones should be grandfathered.
|
||||
|
||||
For legacy reasons, if the reactor has a stainless steel layer instead
|
||||
of a lead layer it will be converted to a lead layer.
|
||||
--]]
|
||||
local function reactor_structure_badness(pos)
|
||||
local vm = VoxelManip()
|
||||
local pos1 = vector.subtract(pos, 3)
|
||||
local pos2 = vector.add(pos, 3)
|
||||
local MinEdge, MaxEdge = vm:read_from_map(pos1, pos2)
|
||||
local data = vm:get_data()
|
||||
local area = VoxelArea:new({MinEdge=MinEdge, MaxEdge=MaxEdge})
|
||||
|
||||
local c_blast_concrete = minetest.get_content_id("technic:blast_resistant_concrete")
|
||||
local c_lead = minetest.get_content_id("technic:lead_block")
|
||||
local c_steel = minetest.get_content_id("technic:stainless_steel_block")
|
||||
local c_water_source = minetest.get_content_id("default:water_source")
|
||||
local c_water_flowing = minetest.get_content_id("default:water_flowing")
|
||||
|
||||
local blast_layer, steel_layer, lead_layer, water_layer = 0, 0, 0, 0
|
||||
|
||||
for z = pos1.z, pos2.z do
|
||||
for y = pos1.y, pos2.y do
|
||||
for x = pos1.x, pos2.x do
|
||||
local cid = data[area:index(x, y, z)]
|
||||
if x == pos1.x or x == pos2.x or
|
||||
y == pos1.y or y == pos2.y or
|
||||
z == pos1.z or z == pos2.z then
|
||||
if cid == c_blast_concrete then
|
||||
blast_layer = blast_layer + 1
|
||||
end
|
||||
elseif x == pos1.x+1 or x == pos2.x-1 or
|
||||
y == pos1.y+1 or y == pos2.y-1 or
|
||||
z == pos1.z+1 or z == pos2.z-1 then
|
||||
if cid == c_lead then
|
||||
lead_layer = lead_layer + 1
|
||||
elseif cid == c_steel then
|
||||
steel_layer = steel_layer + 1
|
||||
end
|
||||
elseif x == pos1.x+2 or x == pos2.x-2 or
|
||||
y == pos1.y+2 or y == pos2.y-2 or
|
||||
z == pos1.z+2 or z == pos2.z-2 then
|
||||
if cid == c_water_source or cid == c_water_flowing then
|
||||
water_layer = water_layer + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if steel_layer >= 96 then
|
||||
for z = pos1.z+1, pos2.z-1 do
|
||||
for y = pos1.y+1, pos2.y-1 do
|
||||
for x = pos1.x+1, pos2.x-1 do
|
||||
local vi = area:index(x, y, z)
|
||||
if x == pos1.x+1 or x == pos2.x-1 or
|
||||
y == pos1.y+1 or y == pos2.y-1 or
|
||||
z == pos1.z+1 or z == pos2.z-1 then
|
||||
if data[vi] == c_steel then
|
||||
data[vi] = c_lead
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
vm:set_data(data)
|
||||
vm:write_to_map()
|
||||
lead_layer = steel_layer
|
||||
end
|
||||
|
||||
if water_layer > 25 then water_layer = 25 end
|
||||
if lead_layer > 96 then lead_layer = 96 end
|
||||
if blast_layer > 216 then blast_layer = 216 end
|
||||
return (25 - water_layer) + (96 - lead_layer) + (216 - blast_layer)
|
||||
end
|
||||
|
||||
|
||||
local function melt_down_reactor(pos)
|
||||
minetest.log("action", "A reactor melted down at "..minetest.pos_to_string(pos))
|
||||
minetest.set_node(pos, {name = "technic:corium_source"})
|
||||
end
|
||||
|
||||
|
||||
local function start_reactor(pos, meta)
|
||||
if minetest.get_node(pos).name ~= "technic:hv_nuclear_reactor_core" then
|
||||
return false
|
||||
end
|
||||
local inv = meta:get_inventory()
|
||||
if inv:is_empty("src") then
|
||||
return false
|
||||
end
|
||||
local src_list = inv:get_list("src")
|
||||
local correct_fuel_count = 0
|
||||
for _, src_stack in pairs(src_list) do
|
||||
if src_stack and src_stack:get_name() == fuel_type then
|
||||
correct_fuel_count = correct_fuel_count + 1
|
||||
end
|
||||
end
|
||||
-- Check that the reactor is complete and has the correct fuel
|
||||
if correct_fuel_count ~= 6 or reactor_structure_badness(pos) ~= 0 then
|
||||
return false
|
||||
end
|
||||
meta:set_int("burn_time", 1)
|
||||
technic.swap_node(pos, "technic:hv_nuclear_reactor_core_active")
|
||||
meta:set_int("HV_EU_supply", power_supply)
|
||||
for idx, src_stack in pairs(src_list) do
|
||||
src_stack:take_item()
|
||||
inv:set_stack("src", idx, src_stack)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
minetest.register_abm({
|
||||
label = "Machines: reactor melt-down check",
|
||||
nodenames = {"technic:hv_nuclear_reactor_core_active"},
|
||||
interval = 4,
|
||||
chance = 1,
|
||||
action = function (pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local badness = reactor_structure_badness(pos)
|
||||
local accum_badness = meta:get_int("structure_accumulated_badness")
|
||||
if badness == 0 then
|
||||
if accum_badness ~= 0 then
|
||||
meta:set_int("structure_accumulated_badness", math.max(accum_badness - 4, 0))
|
||||
siren_clear(pos, meta)
|
||||
end
|
||||
else
|
||||
siren_danger(pos, meta)
|
||||
accum_badness = accum_badness + badness
|
||||
if accum_badness >= 25 then
|
||||
melt_down_reactor(pos)
|
||||
else
|
||||
meta:set_int("structure_accumulated_badness", accum_badness)
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
local function run(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local burn_time = meta:get_int("burn_time") or 0
|
||||
if burn_time >= burn_ticks or burn_time == 0 then
|
||||
if has_digilines and meta:get_int("HV_EU_supply") == power_supply then
|
||||
digilines.receptor_send(pos, technic.digilines.rules, meta:get_string("remote_channel"), {
|
||||
command = "fuel_used",
|
||||
pos = pos
|
||||
})
|
||||
end
|
||||
if meta:get_string("autostart") == "true" then
|
||||
if start_reactor(pos, meta) then
|
||||
return
|
||||
end
|
||||
end
|
||||
meta:set_int("HV_EU_supply", 0)
|
||||
meta:set_int("burn_time", 0)
|
||||
meta:set_string("infotext", S("%s Idle"):format(reactor_desc))
|
||||
technic.swap_node(pos, "technic:hv_nuclear_reactor_core")
|
||||
meta:set_int("structure_accumulated_badness", 0)
|
||||
siren_clear(pos, meta)
|
||||
elseif burn_time > 0 then
|
||||
burn_time = burn_time + 1
|
||||
meta:set_int("burn_time", burn_time)
|
||||
local percent = math.floor(burn_time / burn_ticks * 100)
|
||||
meta:set_string("infotext", reactor_desc.." ("..percent.."%)")
|
||||
meta:set_int("HV_EU_supply", power_supply)
|
||||
end
|
||||
end
|
||||
|
||||
local nuclear_reactor_receive_fields = function(pos, formname, fields, sender)
|
||||
local player_name = sender:get_player_name()
|
||||
if minetest.is_protected(pos, player_name) then
|
||||
minetest.chat_send_player(player_name, "You are not allowed to edit this!")
|
||||
minetest.record_protection_violation(pos, player_name)
|
||||
return
|
||||
end
|
||||
local meta = minetest.get_meta(pos)
|
||||
local update_formspec = false
|
||||
if fields.remote_channel then
|
||||
meta:set_string("remote_channel", fields.remote_channel)
|
||||
end
|
||||
if fields.start then
|
||||
local b = start_reactor(pos, meta)
|
||||
if b then
|
||||
minetest.chat_send_player(player_name, "Start successful")
|
||||
else
|
||||
minetest.chat_send_player(player_name, "Error")
|
||||
end
|
||||
end
|
||||
if fields.autostart then
|
||||
meta:set_string("autostart", fields.autostart)
|
||||
update_formspec = true
|
||||
end
|
||||
if fields.enable_digiline then
|
||||
meta:set_string("enable_digiline", fields.enable_digiline)
|
||||
update_formspec = true
|
||||
end
|
||||
if update_formspec then
|
||||
meta:set_string("formspec", make_reactor_formspec(meta))
|
||||
end
|
||||
end
|
||||
|
||||
local digiline_def = function(pos, _, channel, msg)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_string("enable_digiline") ~= "true" or
|
||||
channel ~= meta:get_string("remote_channel") then
|
||||
return
|
||||
end
|
||||
-- Convert string messages to tables:
|
||||
local msgt = type(msg)
|
||||
if msgt == "string" then
|
||||
local smsg = msg:lower()
|
||||
msg = {}
|
||||
if smsg == "get" then
|
||||
msg.command = "get"
|
||||
elseif smsg:sub(1, 13) == "self_destruct" then
|
||||
msg.command = "self_destruct"
|
||||
msg.timer = tonumber(smsg:sub(15)) or 0
|
||||
elseif smsg == "start" then
|
||||
msg.command = "start"
|
||||
end
|
||||
elseif msgt ~= "table" then
|
||||
return
|
||||
end
|
||||
|
||||
if msg.command == "get" then
|
||||
local inv = meta:get_inventory()
|
||||
local invtable = {}
|
||||
for i = 1, 6 do
|
||||
local stack = inv:get_stack("src", i)
|
||||
if stack:is_empty() then
|
||||
invtable[i] = 0
|
||||
elseif stack:get_name() == fuel_type then
|
||||
invtable[i] = stack:get_count()
|
||||
else
|
||||
invtable[i] = -stack:get_count()
|
||||
end
|
||||
end
|
||||
digilines.receptor_send(pos, technic.digilines.rules, channel, {
|
||||
burn_time = meta:get_int("burn_time"),
|
||||
enabled = meta:get_int("HV_EU_supply") == power_supply,
|
||||
siren = meta:get_int("siren") == 1,
|
||||
structure_accumulated_badness = meta:get_int("structure_accumulated_badness"),
|
||||
rods = invtable
|
||||
})
|
||||
elseif digiline_meltdown and msg.command == "self_destruct" and
|
||||
minetest.get_node(pos).name == "technic:hv_nuclear_reactor_core_active" then
|
||||
if msg.timer ~= 0 and type(msg.timer) == "number" then
|
||||
siren_danger(pos, meta)
|
||||
minetest.after(msg.timer, melt_down_reactor, pos)
|
||||
else
|
||||
melt_down_reactor(pos)
|
||||
end
|
||||
elseif msg.command == "start" then
|
||||
local b = start_reactor(pos, meta)
|
||||
if b then
|
||||
digilines.receptor_send(pos, technic.digilines.rules, channel, {
|
||||
command = "start_success",
|
||||
pos = pos
|
||||
})
|
||||
else
|
||||
digilines.receptor_send(pos, technic.digilines.rules, channel, {
|
||||
command = "start_error",
|
||||
pos = pos
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node("technic:hv_nuclear_reactor_core", {
|
||||
description = reactor_desc,
|
||||
tiles = {
|
||||
"technic_hv_nuclear_reactor_core.png",
|
||||
"technic_hv_nuclear_reactor_core.png"..cable_entry
|
||||
},
|
||||
drawtype = "mesh",
|
||||
mesh = "technic_reactor.obj",
|
||||
groups = {cracky = 1, technic_machine = 1, technic_hv = 1},
|
||||
legacy_facedir_simple = true,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
stack_max = 1,
|
||||
on_receive_fields = nuclear_reactor_receive_fields,
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", reactor_desc)
|
||||
meta:set_string("formspec", make_reactor_formspec(meta))
|
||||
if has_digilines then
|
||||
meta:set_string("remote_channel",
|
||||
"nuclear_reactor"..minetest.pos_to_string(pos))
|
||||
end
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("src", 6)
|
||||
end,
|
||||
|
||||
-- digiline interface
|
||||
digiline = {
|
||||
receptor = {
|
||||
rules = technic.digilines.rules,
|
||||
action = function() end,
|
||||
},
|
||||
effector = {
|
||||
rules = technic.digilines.rules,
|
||||
action = digiline_def,
|
||||
},
|
||||
},
|
||||
|
||||
can_dig = technic.machine_can_dig,
|
||||
on_destruct = function(pos) siren_set_state(pos, SS_OFF) end,
|
||||
allow_metadata_inventory_put = technic.machine_inventory_put,
|
||||
allow_metadata_inventory_take = technic.machine_inventory_take,
|
||||
allow_metadata_inventory_move = technic.machine_inventory_move,
|
||||
technic_run = run,
|
||||
})
|
||||
|
||||
minetest.register_node("technic:hv_nuclear_reactor_core_active", {
|
||||
tiles = {
|
||||
"technic_hv_nuclear_reactor_core.png",
|
||||
"technic_hv_nuclear_reactor_core.png"..cable_entry
|
||||
},
|
||||
drawtype = "mesh",
|
||||
mesh = "technic_reactor.obj",
|
||||
groups = {cracky = 1, technic_machine = 1, technic_hv = 1, radioactive = 4,
|
||||
not_in_creative_inventory = 1},
|
||||
legacy_facedir_simple = true,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
drop = "technic:hv_nuclear_reactor_core",
|
||||
light_source = 14,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
on_receive_fields = nuclear_reactor_receive_fields,
|
||||
|
||||
-- digiline interface
|
||||
digiline = {
|
||||
receptor = {
|
||||
rules = technic.digilines.rules,
|
||||
action = function() end,
|
||||
},
|
||||
effector = {
|
||||
rules = technic.digilines.rules,
|
||||
action = digiline_def,
|
||||
},
|
||||
},
|
||||
|
||||
can_dig = technic.machine_can_dig,
|
||||
after_dig_node = melt_down_reactor,
|
||||
on_destruct = function(pos) siren_set_state(pos, SS_OFF) end,
|
||||
allow_metadata_inventory_put = technic.machine_inventory_put,
|
||||
allow_metadata_inventory_take = technic.machine_inventory_take,
|
||||
allow_metadata_inventory_move = technic.machine_inventory_move,
|
||||
technic_run = run,
|
||||
technic_on_disable = function(pos, node)
|
||||
local timer = minetest.get_node_timer(pos)
|
||||
timer:start(1)
|
||||
end,
|
||||
on_timer = function(pos, node)
|
||||
-- Connected back?
|
||||
if technic.get_timeout("HV", pos) > 0 then return false end
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
local burn_time = meta:get_int("burn_time") or 0
|
||||
|
||||
if burn_time >= burn_ticks or burn_time == 0 then
|
||||
meta:set_int("HV_EU_supply", 0)
|
||||
meta:set_int("burn_time", 0)
|
||||
technic.swap_node(pos, "technic:hv_nuclear_reactor_core")
|
||||
meta:set_int("structure_accumulated_badness", 0)
|
||||
siren_clear(pos, meta)
|
||||
return false
|
||||
end
|
||||
|
||||
meta:set_int("burn_time", burn_time + 1)
|
||||
return true
|
||||
end,
|
||||
})
|
||||
|
||||
technic.register_machine("HV", "technic:hv_nuclear_reactor_core", technic.producer)
|
||||
technic.register_machine("HV", "technic:hv_nuclear_reactor_core_active", technic.producer)
|
||||
@@ -0,0 +1,421 @@
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
local has_digilines = minetest.get_modpath("digilines")
|
||||
|
||||
local quarry_dig_above_nodes = tonumber(technic.config:get("quarry_dig_above_nodes"))
|
||||
local quarry_max_depth = tonumber(technic.config:get("quarry_max_depth"))
|
||||
local quarry_time_limit = tonumber(technic.config:get("quarry_time_limit"))
|
||||
|
||||
local quarry_demand = 10000
|
||||
local quarry_eject_dir = vector.new(0, 1, 0)
|
||||
local machine_name = S("%s Quarry"):format("HV")
|
||||
local quarry_formspec =
|
||||
"size[8,9]"..
|
||||
"item_image[7,0;1,1;technic:quarry]"..
|
||||
"list[context;cache;0,1;4,3;]"..
|
||||
"listring[context;cache]"..
|
||||
"list[current_player;main;0,5;8,4;]"..
|
||||
"listring[current_player;main]"..
|
||||
"label[0,0;"..machine_name.."]"..
|
||||
"button[6,0.9;2,1;restart;"..S("Restart").."]"
|
||||
|
||||
if has_digilines then
|
||||
quarry_formspec = quarry_formspec
|
||||
.. "field[4.3,3.4;4,1;channel;Channel;${channel}]"
|
||||
end
|
||||
|
||||
-- hard-coded spiral dig pattern for up to 17x17 dig area
|
||||
local quarry_dig_pattern = {
|
||||
0,1,2,2,3,3,0,0,0,1,1,1,2,2,2,2,3,3,3,3,0,0,0,0,0,1,1,1,1,1,2,2,
|
||||
2,2,2,2,3,3,3,3,3,3,0,0,0,0,0,0,0,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,
|
||||
3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,
|
||||
2,2,2,2,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,
|
||||
1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,
|
||||
2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||||
}
|
||||
|
||||
local function is_player_allowed(pos, name)
|
||||
local owner = minetest.get_meta(pos):get_string("owner")
|
||||
if owner == "" or owner == name then
|
||||
return true
|
||||
end
|
||||
if not minetest.is_protected(pos, name) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function reset_quarry(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local node = technic.get_or_load_node(pos) or minetest.get_node(pos)
|
||||
meta:set_int("quarry_dir", node.param2)
|
||||
meta:set_string("quarry_pos", minetest.pos_to_string(pos))
|
||||
meta:set_string("dig_pos", "")
|
||||
meta:set_int("dig_level", pos.y + quarry_dig_above_nodes)
|
||||
local radius = meta:get_int("size")
|
||||
local diameter = (radius*2)+1
|
||||
meta:set_int("dig_steps", diameter*diameter)
|
||||
meta:set_int("dig_index", 0)
|
||||
meta:set_int("purge_on", 1)
|
||||
meta:set_int("finished", 0)
|
||||
meta:set_int("dug", 0)
|
||||
end
|
||||
|
||||
local function set_quarry_status(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local formspec = quarry_formspec.."field[4.3,2.4;2,1;size;"..S("Radius:")..";"..meta:get_int("size").."]"
|
||||
local status = S("Digging not started")
|
||||
if meta:get_int("enabled") == 1 then
|
||||
formspec = formspec.."button[4,0.9;2,1;disable;"..S("Enabled").."]"
|
||||
if meta:get_int("purge_on") == 1 then
|
||||
status = S("Purging cache")
|
||||
meta:set_string("infotext", S("%s purging cache"):format(machine_name))
|
||||
meta:set_int("HV_EU_demand", 0)
|
||||
elseif meta:get_int("finished") == 1 then
|
||||
status = S("Digging finished")
|
||||
meta:set_string("infotext", S("%s Finished"):format(machine_name))
|
||||
meta:set_int("HV_EU_demand", 0)
|
||||
else
|
||||
local rel_y = meta:get_int("dig_level") - pos.y
|
||||
status = S("Digging %d m "..(rel_y > 0 and "above" or "below").." machine"):format(math.abs(rel_y))
|
||||
if meta:get_int("HV_EU_input") >= quarry_demand then
|
||||
meta:set_string("infotext", S("%s Active"):format(machine_name))
|
||||
else
|
||||
meta:set_string("infotext", S("%s Unpowered"):format(machine_name))
|
||||
end
|
||||
meta:set_int("HV_EU_demand", quarry_demand)
|
||||
end
|
||||
else
|
||||
formspec = formspec.."button[4,0.9;2,1;enable;"..S("Disabled").."]"
|
||||
meta:set_string("infotext", S("%s Disabled"):format(machine_name))
|
||||
meta:set_int("HV_EU_demand", 0)
|
||||
end
|
||||
meta:set_string("formspec", formspec.."label[0,4.1;"..minetest.formspec_escape(status).."]")
|
||||
end
|
||||
|
||||
local function quarry_receive_fields(pos, formname, fields, sender)
|
||||
local player_name = sender:get_player_name()
|
||||
if not is_player_allowed(pos, player_name) then
|
||||
minetest.chat_send_player(player_name, "You are not allowed to edit this!")
|
||||
minetest.record_protection_violation(pos, player_name)
|
||||
return
|
||||
end
|
||||
local meta = minetest.get_meta(pos)
|
||||
if fields.size and string.find(fields.size, "^[0-9]+$") then
|
||||
local size = tonumber(fields.size)
|
||||
if size >= 1 and size <= 8 and size ~= meta:get_int("size") then
|
||||
meta:set_int("size", size)
|
||||
reset_quarry(pos)
|
||||
end
|
||||
end
|
||||
if fields.channel then
|
||||
meta:set_string("channel", fields.channel)
|
||||
end
|
||||
if fields.enable then meta:set_int("enabled", 1) end
|
||||
if fields.disable then meta:set_int("enabled", 0) end
|
||||
if fields.restart then reset_quarry(pos) end
|
||||
set_quarry_status(pos)
|
||||
end
|
||||
|
||||
local function quarry_handle_purge(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local cache = inv:get_list("cache")
|
||||
if not cache then
|
||||
inv:set_size("cache", 12)
|
||||
return
|
||||
end
|
||||
local i = 0
|
||||
for _,stack in ipairs(cache) do
|
||||
i = i + 1
|
||||
if stack then
|
||||
local item = stack:to_table()
|
||||
if item then
|
||||
technic.tube_inject_item(pos, pos, quarry_eject_dir, item)
|
||||
stack:clear()
|
||||
inv:set_stack("cache", i, stack)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if inv:is_empty("cache") then
|
||||
meta:set_int("purge_on", 0)
|
||||
end
|
||||
end
|
||||
|
||||
local function can_dig_node(pos, node_name, owner, digger)
|
||||
if node_name == "air" or node_name == "vacuum:vacuum" then
|
||||
return false
|
||||
end
|
||||
local def = minetest.registered_nodes[node_name]
|
||||
if not def or not def.diggable or (def.can_dig and not def.can_dig(pos, digger)) then
|
||||
return false
|
||||
end
|
||||
if minetest.is_protected(pos, owner) then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function find_ground(quarry_pos, quarry_dir, meta)
|
||||
local dir = minetest.facedir_to_dir(quarry_dir % 4)
|
||||
local radius = meta:get_int("size")
|
||||
local dig_level = meta:get_int("dig_level")
|
||||
local middle_pos = vector.add(quarry_pos, vector.multiply(dir, radius + 1))
|
||||
local pos1 = vector.new(middle_pos.x - radius, dig_level, middle_pos.z - radius)
|
||||
local pos2 = vector.new(middle_pos.x + radius, dig_level, middle_pos.z + radius)
|
||||
local nodes = minetest.find_nodes_in_area(pos1, pos2, {"air", "vacuum:vacuum"})
|
||||
if #nodes < meta:get_int("dig_steps") then
|
||||
return vector.new(middle_pos.x, dig_level, middle_pos.z)
|
||||
end
|
||||
meta:set_int("dig_level", dig_level - 1)
|
||||
return nil
|
||||
end
|
||||
|
||||
local function get_dig_pos(quarry_pos, quarry_dir, dig_pos, dig_index, dig_steps, meta)
|
||||
if dig_index > 0 and dig_index < dig_steps then
|
||||
local facedir = (quarry_dir + quarry_dig_pattern[dig_index]) % 4
|
||||
dig_pos = vector.add(dig_pos, minetest.facedir_to_dir(facedir))
|
||||
elseif dig_index >= dig_steps then
|
||||
local dig_level = meta:get_int("dig_level")
|
||||
if (quarry_pos.y - dig_level) >= quarry_max_depth then
|
||||
return nil, dig_index
|
||||
end
|
||||
local dir = minetest.facedir_to_dir(quarry_dir % 4)
|
||||
dig_pos = vector.add(quarry_pos, vector.multiply(dir, meta:get_int("size") + 1))
|
||||
dig_pos.y = dig_level - 1
|
||||
meta:set_int("dig_level", dig_pos.y)
|
||||
dig_index = 0
|
||||
end
|
||||
dig_index = dig_index + 1
|
||||
return dig_pos, dig_index
|
||||
end
|
||||
|
||||
local function execute_dig(pos, node, meta)
|
||||
local dig_pos = minetest.string_to_pos(meta:get_string("dig_pos"))
|
||||
local quarry_dir = meta:get_int("quarry_dir")
|
||||
if not dig_pos then
|
||||
-- quarry has not hit ground yet
|
||||
dig_pos = find_ground(pos, quarry_dir, meta)
|
||||
else
|
||||
local owner = meta:get_string("owner")
|
||||
local digger = pipeworks.create_fake_player({name = owner})
|
||||
local dig_steps = meta:get_int("dig_steps")
|
||||
local dig_index = meta:get_int("dig_index")
|
||||
local t0 = minetest.get_us_time()
|
||||
local us_used = 0
|
||||
-- search for something to dig
|
||||
while us_used < quarry_time_limit do
|
||||
dig_pos, dig_index = get_dig_pos(pos, quarry_dir, dig_pos, dig_index, dig_steps, meta)
|
||||
if not dig_pos then
|
||||
-- finished digging
|
||||
meta:set_int("finished", 1)
|
||||
meta:set_int("purge_on", 1)
|
||||
break
|
||||
end
|
||||
local dig_node = technic.get_or_load_node(dig_pos) or minetest.get_node(dig_pos)
|
||||
if can_dig_node(dig_pos, dig_node.name, owner, digger) then
|
||||
-- found something to dig, dig it and stop searching
|
||||
minetest.remove_node(dig_pos)
|
||||
local inv = meta:get_inventory()
|
||||
local drops = minetest.get_node_drops(dig_node.name, "")
|
||||
for _, dropped_item in ipairs(drops) do
|
||||
local left = inv:add_item("cache", dropped_item)
|
||||
while not left:is_empty() do
|
||||
meta:set_int("purge_on", 1)
|
||||
quarry_handle_purge(pos)
|
||||
left = inv:add_item("cache", left)
|
||||
end
|
||||
end
|
||||
local dug_nodes = meta:get_int("dug") + 1
|
||||
meta:set_int("dug", dug_nodes)
|
||||
if dug_nodes % 100 == 0 then
|
||||
meta:set_int("purge_on", 1)
|
||||
end
|
||||
break
|
||||
end
|
||||
us_used = minetest.get_us_time() - t0
|
||||
end
|
||||
meta:set_int("dig_index", dig_index)
|
||||
end
|
||||
if dig_pos then
|
||||
meta:set_string("dig_pos", minetest.pos_to_string(dig_pos))
|
||||
end
|
||||
end
|
||||
|
||||
local function quarry_run(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if minetest.pos_to_string(pos) ~= meta:get_string("quarry_pos") then
|
||||
-- quarry has been moved since last dig
|
||||
reset_quarry(pos)
|
||||
elseif meta:get_int("purge_on") == 1 then
|
||||
quarry_handle_purge(pos)
|
||||
elseif meta:get_int("enabled") and meta:get_int("HV_EU_input") >= quarry_demand and meta:get_int("finished") == 0 then
|
||||
execute_dig(pos, node, meta)
|
||||
elseif not meta:get_inventory():is_empty("cache") then
|
||||
meta:set_int("purge_on", 1)
|
||||
end
|
||||
set_quarry_status(pos)
|
||||
end
|
||||
|
||||
local digiline_def = function(pos, _, channel, msg)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if channel ~= meta:get_string("channel") then
|
||||
return
|
||||
end
|
||||
-- Convert string messages to tables:
|
||||
if type(msg) == "string" then
|
||||
local smsg = msg:lower()
|
||||
msg = {}
|
||||
if smsg == "get" then
|
||||
msg.command = "get"
|
||||
elseif smsg:sub(1,7) == "radius " then
|
||||
msg.command = "radius"
|
||||
msg.value = smsg:sub(8,-1)
|
||||
elseif smsg == "on" then
|
||||
msg.command = "on"
|
||||
elseif smsg == "off" then
|
||||
msg.command = "off"
|
||||
elseif smsg == "restart" then
|
||||
msg.command = "restart"
|
||||
end
|
||||
end
|
||||
|
||||
if type(msg) ~= "table" then
|
||||
return
|
||||
end
|
||||
|
||||
if msg.command == "get" then
|
||||
digilines.receptor_send(pos, technic.digilines.rules, channel, {
|
||||
enabled = meta:get_int("enabled"),
|
||||
radius = meta:get_int("size"),
|
||||
finished = meta:get_int("finished"),
|
||||
dug_nodes = meta:get_int("dug"),
|
||||
dig_level = meta:get_int("dig_level") - pos.y
|
||||
})
|
||||
elseif msg.command == "radius" then
|
||||
local size = tonumber(msg.value)
|
||||
if not size or size < 1 or size > 8 or size == meta:get_int("size") then
|
||||
return
|
||||
end
|
||||
meta:set_int("size", size)
|
||||
reset_quarry(pos)
|
||||
set_quarry_status(pos)
|
||||
elseif msg.command == "on" then
|
||||
meta:set_int("enabled", 1)
|
||||
set_quarry_status(pos)
|
||||
elseif msg.command == "off" then
|
||||
meta:set_int("enabled", 0)
|
||||
set_quarry_status(pos)
|
||||
elseif msg.command == "restart" then
|
||||
reset_quarry(pos)
|
||||
set_quarry_status(pos)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
minetest.register_node("technic:quarry", {
|
||||
description = S("%s Quarry"):format("HV"),
|
||||
tiles = {
|
||||
"technic_carbon_steel_block.png^pipeworks_tube_connection_metallic.png",
|
||||
"technic_carbon_steel_block.png^technic_cable_connection_overlay.png",
|
||||
"technic_carbon_steel_block.png^technic_cable_connection_overlay.png",
|
||||
"technic_carbon_steel_block.png^technic_cable_connection_overlay.png",
|
||||
"technic_carbon_steel_block.png^default_tool_mesepick.png",
|
||||
"technic_carbon_steel_block.png^technic_cable_connection_overlay.png"
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=2, tubedevice=1, technic_machine=1, technic_hv=1},
|
||||
connect_sides = {"bottom", "front", "left", "right"},
|
||||
tube = {
|
||||
connect_sides = {top = 1},
|
||||
-- lower priority than other tubes, so that quarries will prefer any
|
||||
-- other tube to another quarry, which could lead to server freezes
|
||||
-- in certain quarry placements (2x2 for example would never eject)
|
||||
priority = 10,
|
||||
can_go = function(pos, node, velocity, stack)
|
||||
-- always eject the same, even if items came in another way
|
||||
-- this further mitigates loops and generally avoids random sideway movement
|
||||
-- that can be expected in certain quarry placements
|
||||
return { quarry_eject_dir }
|
||||
end
|
||||
},
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_int("size", 4)
|
||||
meta:get_inventory():set_size("cache", 12)
|
||||
reset_quarry(pos)
|
||||
set_quarry_status(pos)
|
||||
end,
|
||||
on_rotate = function(pos, node, player, click, new_param2)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("enabled") == 1 then
|
||||
return false
|
||||
end
|
||||
|
||||
-- only allow rotation around y-axis
|
||||
node.param2 = new_param2 % 4
|
||||
|
||||
minetest.swap_node(pos, node)
|
||||
reset_quarry(pos)
|
||||
set_quarry_status(pos)
|
||||
return true
|
||||
end,
|
||||
after_place_node = function(pos, placer, itemstack)
|
||||
minetest.get_meta(pos):set_string("owner", placer:get_player_name())
|
||||
pipeworks.scan_for_tube_objects(pos)
|
||||
end,
|
||||
can_dig = function(pos,player)
|
||||
return minetest.get_meta(pos):get_inventory():is_empty("cache")
|
||||
end,
|
||||
after_dig_node = pipeworks.scan_for_tube_objects,
|
||||
on_receive_fields = quarry_receive_fields,
|
||||
technic_run = quarry_run,
|
||||
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
return is_player_allowed(pos, player:get_player_name()) and count or 0
|
||||
end,
|
||||
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
return is_player_allowed(pos, player:get_player_name()) and stack:get_count() or 0
|
||||
end,
|
||||
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
return is_player_allowed(pos, player:get_player_name()) and stack:get_count() or 0
|
||||
end,
|
||||
mesecons = {
|
||||
effector = {
|
||||
action_on = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_int("enabled", 1)
|
||||
set_quarry_status(pos)
|
||||
end,
|
||||
action_off = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_int("enabled", 0)
|
||||
set_quarry_status(pos)
|
||||
end
|
||||
}
|
||||
},
|
||||
digiline = {
|
||||
receptor = {
|
||||
rules = technic.digilines.rules,
|
||||
action = function() end,
|
||||
},
|
||||
effector = {
|
||||
rules = technic.digilines.rules,
|
||||
action = digiline_def,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
recipe = {
|
||||
{"technic:carbon_plate", "pipeworks:filter", "technic:composite_plate"},
|
||||
{"basic_materials:motor", "technic:machine_casing", "technic:diamond_drill_head"},
|
||||
{"technic:carbon_steel_block", "technic:hv_cable", "technic:carbon_steel_block"}},
|
||||
output = "technic:quarry"
|
||||
})
|
||||
|
||||
technic.register_machine("HV", "technic:quarry", technic.receiver)
|
||||
@@ -0,0 +1,14 @@
|
||||
-- The high voltage solar array is an assembly of medium voltage arrays.
|
||||
-- Solar arrays are not able to store large amounts of energy.
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:solar_array_hv 1',
|
||||
recipe = {
|
||||
{'technic:solar_array_mv', 'technic:solar_array_mv', 'technic:solar_array_mv'},
|
||||
{'technic:carbon_plate', 'technic:hv_transformer', 'technic:composite_plate'},
|
||||
{'', 'technic:hv_cable', ''},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_solar_array({tier="HV", power=100})
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
-- LV Alloy furnace
|
||||
|
||||
-- FIXME: kpoppel: I'd like to introduce an induction heating element here...
|
||||
minetest.register_craft({
|
||||
output = 'technic:lv_alloy_furnace',
|
||||
recipe = {
|
||||
{'default:brick', 'default:brick', 'default:brick'},
|
||||
{'default:brick', 'technic:machine_casing', 'default:brick'},
|
||||
{'default:brick', 'technic:lv_cable', 'default:brick'},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_alloy_furnace({tier = "LV", speed = 1, demand = {300}})
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
-- LV Battery box
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:lv_battery_box0',
|
||||
recipe = {
|
||||
{'group:wood', 'group:wood', 'group:wood'},
|
||||
{'technic:battery', 'technic:machine_casing', 'technic:battery'},
|
||||
{'technic:battery', 'technic:lv_cable', 'technic:battery'},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_battery_box({
|
||||
tier = "LV",
|
||||
max_charge = 40000,
|
||||
charge_rate = 1000,
|
||||
discharge_rate = 4000,
|
||||
charge_step = 500,
|
||||
discharge_step = 800,
|
||||
})
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
|
||||
minetest.register_alias("lv_cable", "technic:lv_cable")
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:lv_cable 6',
|
||||
recipe = {
|
||||
{'default:paper', 'default:paper', 'default:paper'},
|
||||
{'default:copper_ingot', 'default:copper_ingot', 'default:copper_ingot'},
|
||||
{'default:paper', 'default:paper', 'default:paper'},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_cable("LV", 2/16)
|
||||
|
||||
if minetest.get_modpath("digilines") then
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
if minetest.get_modpath("digistuff") then
|
||||
minetest.register_craft({
|
||||
output = 'technic:lv_digi_cable 1',
|
||||
type = "shapeless",
|
||||
recipe = {'digistuff:digimese', 'technic:lv_cable'}
|
||||
})
|
||||
else
|
||||
minetest.register_craft({
|
||||
output = 'technic:lv_digi_cable 1',
|
||||
recipe = {
|
||||
{'digilines:wire_std_00000000', 'digilines:wire_std_00000000', 'digilines:wire_std_00000000'},
|
||||
{'digilines:wire_std_00000000', 'technic:lv_cable', 'digilines:wire_std_00000000'},
|
||||
{'digilines:wire_std_00000000', 'digilines:wire_std_00000000', 'digilines:wire_std_00000000'},
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
technic.register_cable("LV", 2/16, S("LV Cable (digiline)"), "_digi", {
|
||||
digiline = {
|
||||
wire = {
|
||||
rules = {
|
||||
{x = 1, y = 0, z = 0},
|
||||
{x =-1, y = 0, z = 0},
|
||||
{x = 0, y = 1, z = 0},
|
||||
{x = 0, y =-1, z = 0},
|
||||
{x = 0, y = 0, z = 1},
|
||||
{x = 0, y = 0, z =-1}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
@@ -0,0 +1,17 @@
|
||||
|
||||
minetest.register_alias("compressor", "technic:lv_compressor")
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:lv_compressor',
|
||||
recipe = {
|
||||
{'default:stone', 'basic_materials:motor', 'default:stone'},
|
||||
{'mesecons:piston', 'technic:machine_casing', 'mesecons:piston'},
|
||||
{'basic_materials:silver_wire', 'technic:lv_cable', 'basic_materials:silver_wire'},
|
||||
},
|
||||
replacements = {
|
||||
{"basic_materials:silver_wire", "basic_materials:empty_spool"},
|
||||
{"basic_materials:silver_wire", "basic_materials:empty_spool"}
|
||||
},
|
||||
})
|
||||
|
||||
technic.register_compressor({tier = "LV", demand = {300}, speed = 1})
|
||||
@@ -0,0 +1,16 @@
|
||||
-- LV Electric Furnace
|
||||
-- This is a faster version of the stone furnace which runs on EUs
|
||||
|
||||
-- FIXME: kpoppel I'd like to introduce an induction heating element here also
|
||||
minetest.register_craft({
|
||||
output = 'technic:electric_furnace',
|
||||
recipe = {
|
||||
{'default:cobble', 'default:cobble', 'default:cobble'},
|
||||
{'default:cobble', 'technic:machine_casing', 'default:cobble'},
|
||||
{'default:cobble', 'technic:lv_cable', 'default:cobble'},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_electric_furnace({tier="LV", demand={300}, speed = 2})
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
minetest.register_alias("extractor", "technic:lv_extractor")
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:lv_extractor',
|
||||
recipe = {
|
||||
{'technic:treetap', 'basic_materials:motor', 'technic:treetap'},
|
||||
{'technic:treetap', 'technic:machine_casing', 'technic:treetap'},
|
||||
{'', 'technic:lv_cable', ''},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_extractor({tier = "LV", demand = {300}, speed = 1})
|
||||
@@ -0,0 +1,18 @@
|
||||
-- The electric generator.
|
||||
-- A simple device to get started on the electric machines.
|
||||
-- Inefficient and expensive in fuel (200EU per tick)
|
||||
-- Also only allows for LV machinery to run.
|
||||
|
||||
minetest.register_alias("lv_generator", "technic:lv_generator")
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:lv_generator',
|
||||
recipe = {
|
||||
{'default:stone', 'default:furnace', 'default:stone'},
|
||||
{'default:stone', 'technic:machine_casing', 'default:stone'},
|
||||
{'default:stone', 'technic:lv_cable', 'default:stone'},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_generator({tier="LV", supply=200})
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
-- A geothermal EU generator
|
||||
-- Using hot lava and water this device can create energy from steam
|
||||
-- The machine is only producing LV EUs and can thus not drive more advanced equipment
|
||||
-- The output is a little more than the coal burning generator (max 300EUs)
|
||||
|
||||
minetest.register_alias("geothermal", "technic:geothermal")
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:geothermal',
|
||||
recipe = {
|
||||
{'technic:granite', 'default:diamond', 'technic:granite'},
|
||||
{'basic_materials:copper_wire', 'technic:machine_casing', 'basic_materials:copper_wire'},
|
||||
{'technic:granite', 'technic:lv_cable', 'technic:granite'},
|
||||
},
|
||||
replacements = {
|
||||
{"basic_materials:copper_wire", "basic_materials:empty_spool"},
|
||||
{"basic_materials:copper_wire", "basic_materials:empty_spool"}
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craftitem("technic:geothermal", {
|
||||
description = S("Geothermal %s Generator"):format("LV"),
|
||||
})
|
||||
|
||||
local check_node_around = function(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
if node.name == "default:water_source" or node.name == "default:water_flowing" then return 1 end
|
||||
if node.name == "default:lava_source" or node.name == "default:lava_flowing" then return 2 end
|
||||
return 0
|
||||
end
|
||||
|
||||
local run = function(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local water_nodes = 0
|
||||
local lava_nodes = 0
|
||||
local production_level = 0
|
||||
local eu_supply = 0
|
||||
|
||||
-- Correct positioning is water on one side and lava on the other.
|
||||
-- The two cannot be adjacent because the lava the turns into obsidian or rock.
|
||||
-- To get to 100% production stack the water and lava one extra block down as well:
|
||||
-- WGL (W=Water, L=Lava, G=the generator, |=an LV cable)
|
||||
-- W|L
|
||||
|
||||
local positions = {
|
||||
{x=pos.x+1, y=pos.y, z=pos.z},
|
||||
{x=pos.x+1, y=pos.y-1, z=pos.z},
|
||||
{x=pos.x-1, y=pos.y, z=pos.z},
|
||||
{x=pos.x-1, y=pos.y-1, z=pos.z},
|
||||
{x=pos.x, y=pos.y, z=pos.z+1},
|
||||
{x=pos.x, y=pos.y-1, z=pos.z+1},
|
||||
{x=pos.x, y=pos.y, z=pos.z-1},
|
||||
{x=pos.x, y=pos.y-1, z=pos.z-1},
|
||||
}
|
||||
for _, p in pairs(positions) do
|
||||
local check = check_node_around(p)
|
||||
if check == 1 then water_nodes = water_nodes + 1 end
|
||||
if check == 2 then lava_nodes = lava_nodes + 1 end
|
||||
end
|
||||
|
||||
if water_nodes == 1 and lava_nodes == 1 then production_level = 25; eu_supply = 50 end
|
||||
if water_nodes == 2 and lava_nodes == 1 then production_level = 50; eu_supply = 100 end
|
||||
if water_nodes == 1 and lava_nodes == 2 then production_level = 75; eu_supply = 200 end
|
||||
if water_nodes == 2 and lava_nodes == 2 then production_level = 100; eu_supply = 300 end
|
||||
|
||||
if production_level > 0 then
|
||||
meta:set_int("LV_EU_supply", eu_supply)
|
||||
end
|
||||
|
||||
meta:set_string("infotext",
|
||||
S("Geothermal %s Generator"):format("LV").." ("..production_level.."%)")
|
||||
|
||||
if production_level > 0 and minetest.get_node(pos).name == "technic:geothermal" then
|
||||
technic.swap_node (pos, "technic:geothermal_active")
|
||||
return
|
||||
end
|
||||
if production_level == 0 then
|
||||
technic.swap_node(pos, "technic:geothermal")
|
||||
meta:set_int("LV_EU_supply", 0)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node("technic:geothermal", {
|
||||
description = S("Geothermal %s Generator"):format("LV"),
|
||||
tiles = {"technic_geothermal_top.png", "technic_machine_bottom.png", "technic_geothermal_side.png",
|
||||
"technic_geothermal_side.png", "technic_geothermal_side.png", "technic_geothermal_side.png"},
|
||||
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
|
||||
technic_machine=1, technic_lv=1},
|
||||
paramtype2 = "facedir",
|
||||
legacy_facedir_simple = true,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", S("Geothermal %s Generator"):format("LV"))
|
||||
meta:set_int("LV_EU_supply", 0)
|
||||
end,
|
||||
technic_run = run,
|
||||
})
|
||||
|
||||
minetest.register_node("technic:geothermal_active", {
|
||||
description = S("Geothermal %s Generator"):format("LV"),
|
||||
tiles = {"technic_geothermal_top_active.png", "technic_machine_bottom.png", "technic_geothermal_side.png",
|
||||
"technic_geothermal_side.png", "technic_geothermal_side.png", "technic_geothermal_side.png"},
|
||||
paramtype2 = "facedir",
|
||||
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
|
||||
technic_machine=1, technic_lv=1, not_in_creative_inventory=1},
|
||||
legacy_facedir_simple = true,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
drop = "technic:geothermal",
|
||||
technic_run = run,
|
||||
})
|
||||
|
||||
technic.register_machine("LV", "technic:geothermal", technic.producer)
|
||||
technic.register_machine("LV", "technic:geothermal_active", technic.producer)
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
minetest.register_alias("grinder", "technic:lv_grinder")
|
||||
minetest.register_craft({
|
||||
output = 'technic:lv_grinder',
|
||||
recipe = {
|
||||
{'default:desert_stone', 'default:diamond', 'default:desert_stone'},
|
||||
{'default:desert_stone', 'technic:machine_casing', 'default:desert_stone'},
|
||||
{'technic:granite', 'technic:lv_cable', 'technic:granite'},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_grinder({tier="LV", demand={200}, speed=1})
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
technic.register_tier("LV", "Low Voltage")
|
||||
|
||||
local path = technic.modpath.."/machines/LV"
|
||||
|
||||
-- Wiring stuff
|
||||
dofile(path.."/cables.lua")
|
||||
dofile(path.."/battery_box.lua")
|
||||
|
||||
-- Generators
|
||||
dofile(path.."/solar_panel.lua")
|
||||
dofile(path.."/solar_array.lua")
|
||||
dofile(path.."/geothermal.lua")
|
||||
dofile(path.."/water_mill.lua")
|
||||
dofile(path.."/generator.lua")
|
||||
|
||||
-- Machines
|
||||
dofile(path.."/alloy_furnace.lua")
|
||||
dofile(path.."/electric_furnace.lua")
|
||||
dofile(path.."/grinder.lua")
|
||||
dofile(path.."/extractor.lua")
|
||||
dofile(path.."/compressor.lua")
|
||||
|
||||
dofile(path.."/music_player.lua")
|
||||
|
||||
dofile(path.."/lamp.lua")
|
||||
@@ -0,0 +1,246 @@
|
||||
-- LV LED and LV LED Lamp
|
||||
-- LED - a weak light source, intended primarily as a core component for LED lamps
|
||||
-- LED Lamp - a powerful light source, illuminating a 7x7x3(H) volume below itself
|
||||
-- with light bright as the sun.
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
|
||||
local illuminate = function(pos, mode)
|
||||
for y=1,3,1 do
|
||||
for x=-3,3,1 do
|
||||
for z = -3,3,1 do
|
||||
local loc = {x = pos.x - x, y = pos.y - y, z = pos.z - z}
|
||||
if mode then
|
||||
if minetest.get_node(loc).name == "air" then
|
||||
minetest.swap_node(loc, {name = "technic:dummy_light_source"})
|
||||
end
|
||||
else
|
||||
if minetest.get_node(loc).name == "technic:dummy_light_source" then
|
||||
minetest.swap_node(loc, {name = "air"})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local led_on = function(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local eu_input = meta:get_int("LV_EU_input")
|
||||
local machine_name = S("%s LED"):format("LV")
|
||||
local machine_node = "technic:lv_led"
|
||||
local demand = 5
|
||||
|
||||
if eu_input < demand then
|
||||
technic.swap_node(pos, machine_node)
|
||||
meta:set_string("infotext", S("%s Unpowered"):format(machine_name))
|
||||
elseif eu_input >= demand then
|
||||
technic.swap_node(pos, machine_node.."_active")
|
||||
meta:set_string("infotext", S("%s Active"):format(machine_name))
|
||||
end
|
||||
meta:set_int("LV_EU_demand", demand)
|
||||
end
|
||||
|
||||
local led_off = function(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local machine_name = S("%s LED"):format("LV")
|
||||
local machine_node = "technic:lv_led"
|
||||
|
||||
technic.swap_node(pos, machine_node)
|
||||
meta:set_string("infotext", S("%s Unpowered"):format(machine_name))
|
||||
|
||||
meta:set_int("LV_EU_demand", 0)
|
||||
end
|
||||
|
||||
|
||||
|
||||
local lamp_on = function(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local eu_input = meta:get_int("LV_EU_input")
|
||||
local machine_name = S("%s Lamp"):format("LV")
|
||||
local machine_node = "technic:lv_lamp"
|
||||
local demand = 50
|
||||
|
||||
if eu_input < demand then
|
||||
technic.swap_node(pos, machine_node)
|
||||
meta:set_string("infotext", S("%s Unpowered"):format(machine_name))
|
||||
illuminate(pos, false)
|
||||
elseif eu_input >= demand then
|
||||
technic.swap_node(pos, machine_node.."_active")
|
||||
meta:set_string("infotext", S("%s Active"):format(machine_name))
|
||||
illuminate(pos, true)
|
||||
end
|
||||
meta:set_int("LV_EU_demand", demand)
|
||||
end
|
||||
|
||||
local lamp_off = function(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local machine_name = S("%s Lamp"):format("LV")
|
||||
local machine_node = "technic:lv_lamp"
|
||||
|
||||
illuminate(pos, false)
|
||||
technic.swap_node(pos, machine_node)
|
||||
meta:set_string("infotext", S("%s Unpowered"):format(machine_name))
|
||||
meta:set_int("LV_EU_demand", 0)
|
||||
end
|
||||
|
||||
|
||||
minetest.register_node("technic:dummy_light_source", {
|
||||
description = S("Dummy light source node"),
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {}
|
||||
},
|
||||
collision_box = {
|
||||
type = "fixed",
|
||||
fixed = {}
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {}
|
||||
},
|
||||
drawtype = "airlike",
|
||||
buildable_to = true,
|
||||
light_source = 14,
|
||||
sunlight_propagates = true,
|
||||
diggable = false,
|
||||
walkable = false,
|
||||
groups = { not_in_creative_inventory = 1 }
|
||||
})
|
||||
|
||||
minetest.register_node("technic:lv_led", {
|
||||
description = S("LV LED"),
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {0.2,0.2,0.2,-0.2,-0.2,-0.2}
|
||||
},
|
||||
collision_box = {
|
||||
type = "fixed",
|
||||
fixed = {0.2,0.2,0.2,-0.2,-0.2,-0.2}
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {0.2,0.2,0.2,-0.2,-0.2,-0.2}
|
||||
},
|
||||
tiles = {"technic_lv_led.png"},
|
||||
inventory_image = "technic_lv_led_inv.png",
|
||||
sunlight_propagates = true,
|
||||
groups = {cracky=2, technic_machine=1, technic_lv=1},
|
||||
connect_sides = {"front", "back", "left", "right", "top", "bottom"},
|
||||
can_dig = technic.machine_can_dig,
|
||||
technic_run = led_on,
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", S("%s LED"):format("LV"))
|
||||
end,
|
||||
drop = "technic:lv_led"
|
||||
})
|
||||
|
||||
minetest.register_node("technic:lv_led_active", {
|
||||
description = S("LV LED Active"),
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {0.2,0.2,0.2,-0.2,-0.2,-0.2}
|
||||
},
|
||||
collision_box = {
|
||||
type = "fixed",
|
||||
fixed = {0.2,0.2,0.2,-0.2,-0.2,-0.2}
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {0.2,0.2,0.2,-0.2,-0.2,-0.2}
|
||||
},
|
||||
tiles = {"technic_lv_led.png"},
|
||||
light_source = 9,
|
||||
sunlight_propagates = true,
|
||||
groups = {cracky=2, technic_machine=1, technic_lv=1, not_in_creative_inventory=1},
|
||||
connect_sides = {"front", "back", "left", "right", "top", "bottom"},
|
||||
can_dig = technic.machine_can_dig,
|
||||
technic_run = led_on,
|
||||
technic_on_disable = led_off,
|
||||
drop = "technic:lv_led"
|
||||
})
|
||||
|
||||
|
||||
minetest.register_node("technic:lv_lamp", {
|
||||
description = S("%s Lamp"):format("LV"),
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {0.5,0.5,0.5,-0.5,-0.2,-0.5}
|
||||
},
|
||||
collision_box = {
|
||||
type = "fixed",
|
||||
fixed = {0.5,0.5,0.5,-0.5,-0.2,-0.5}
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {0.5,0.5,0.5,-0.5,-0.2,-0.5}
|
||||
},
|
||||
tiles = {"technic_lv_lamp_top.png", "technic_lv_lamp_bottom.png", "technic_lv_lamp_side.png",
|
||||
"technic_lv_lamp_side.png", "technic_lv_lamp_side.png", "technic_lv_lamp_side.png"},
|
||||
groups = {cracky=2, technic_machine=1, technic_lv=1},
|
||||
connect_sides = {"front", "back", "left", "right", "top",},
|
||||
can_dig = technic.machine_can_dig,
|
||||
technic_run = lamp_on,
|
||||
on_destruct = lamp_off,
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", S("%s Lamp"):format("LV"))
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
minetest.register_node("technic:lv_lamp_active", {
|
||||
description = S("%s Lamp Active"):format("LV"),
|
||||
drawtype = "nodebox",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {0.5,0.5,0.5,-0.5,-0.2,-0.5}
|
||||
},
|
||||
collision_box = {
|
||||
type = "fixed",
|
||||
fixed = {0.5,0.5,0.5,-0.5,-0.2,-0.5}
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = {0.5,0.5,0.5,-0.5,-0.2,-0.5}
|
||||
},
|
||||
tiles = {"technic_lv_lamp_top.png", "technic_lv_lamp_bottom.png", "technic_lv_lamp_side.png",
|
||||
"technic_lv_lamp_side.png", "technic_lv_lamp_side.png", "technic_lv_lamp_side.png"},
|
||||
groups = {cracky=2, technic_machine=1, technic_lv=1, not_in_creative_inventory=1},
|
||||
connect_sides = {"front", "back", "left", "right", "top"},
|
||||
light_source = 1,
|
||||
can_dig = technic.machine_can_dig,
|
||||
technic_run = lamp_on,
|
||||
on_destruct = lamp_off,
|
||||
technic_on_disable = lamp_off,
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:lv_led 2',
|
||||
recipe = {
|
||||
{'', 'homedecor:plastic_sheeting', ''},
|
||||
{'homedecor:plastic_sheeting', 'technic:doped_silicon_wafer', 'homedecor:plastic_sheeting'},
|
||||
{'', 'technic:fine_silver_wire', ''},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:lv_lamp',
|
||||
recipe = {
|
||||
{'default:glass', 'default:glass', 'default:glass'},
|
||||
{'technic:lv_led', 'technic:lv_led', 'technic:lv_led'},
|
||||
{'mesecons_materials:glue', 'technic:lv_cable', 'mesecons_materials:glue'},
|
||||
},
|
||||
})
|
||||
|
||||
technic.register_machine("LV", "technic:lv_lamp", technic.receiver)
|
||||
technic.register_machine("LV", "technic:lv_lamp_active", technic.receiver)
|
||||
|
||||
technic.register_machine("LV", "technic:lv_led", technic.receiver)
|
||||
technic.register_machine("LV", "technic:lv_led_active", technic.receiver)
|
||||
@@ -0,0 +1,131 @@
|
||||
-- LV Music player.
|
||||
-- The player can play music. But it is high ampage!
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
minetest.register_alias("music_player", "technic:music_player")
|
||||
minetest.register_craft({
|
||||
output = 'technic:music_player',
|
||||
recipe = {
|
||||
{'technic:chromium_ingot', 'default:diamond', 'technic:chromium_ingot'},
|
||||
{'default:diamond', 'technic:machine_casing', 'default:diamond'},
|
||||
{'default:mossycobble', 'technic:lv_cable', 'default:mossycobble'},
|
||||
}
|
||||
})
|
||||
|
||||
local music_handles = {}
|
||||
|
||||
local function play_track(pos, track)
|
||||
return minetest.sound_play("technic_track"..tostring(track),
|
||||
{pos = pos, gain = 1.0, loop = true, max_hear_distance = 72,})
|
||||
end
|
||||
|
||||
local run = function(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local eu_input = meta:get_int("LV_EU_input")
|
||||
local machine_name = S("%s Music Player"):format("LV")
|
||||
local demand = 150
|
||||
|
||||
local current_track = meta:get_int("current_track")
|
||||
local pos_hash = minetest.hash_node_position(pos)
|
||||
local music_handle = music_handles[pos_hash]
|
||||
|
||||
-- Setup meta data if it does not exist.
|
||||
if not eu_input then
|
||||
meta:set_int("LV_EU_demand", demand)
|
||||
meta:set_int("LV_EU_input", 0)
|
||||
return
|
||||
end
|
||||
|
||||
if meta:get_int("active") == 0 then
|
||||
meta:set_string("infotext", S("%s Idle"):format(machine_name))
|
||||
meta:set_int("LV_EU_demand", 0)
|
||||
return
|
||||
end
|
||||
|
||||
if eu_input < demand then
|
||||
meta:set_string("infotext", S("%s Unpowered"):format(machine_name))
|
||||
if music_handle then
|
||||
minetest.sound_stop(music_handle)
|
||||
music_handle = nil
|
||||
end
|
||||
elseif eu_input >= demand then
|
||||
meta:set_string("infotext", S("%s Active"):format(machine_name))
|
||||
if not music_handle then
|
||||
music_handle = play_track(pos, current_track)
|
||||
end
|
||||
end
|
||||
music_handles[pos_hash] = music_handle
|
||||
meta:set_int("LV_EU_demand", demand)
|
||||
end
|
||||
|
||||
local function stop_player(pos, node)
|
||||
local pos_hash = minetest.hash_node_position(pos)
|
||||
local music_handle = music_handles[pos_hash]
|
||||
if music_handle then
|
||||
minetest.sound_stop(music_handle)
|
||||
music_handles[pos_hash] = nil
|
||||
end
|
||||
end
|
||||
|
||||
local function set_display(meta)
|
||||
meta:set_string("formspec",
|
||||
"size[4,4.5]"..
|
||||
"item_image[0,0;1,1;technic:music_player]"..
|
||||
"label[1,0;"..S("%s Music Player"):format("LV").."]"..
|
||||
"button[0,1;1,1;track1;1]"..
|
||||
"button[1,1;1,1;track2;2]"..
|
||||
"button[2,1;1,1;track3;3]"..
|
||||
"button[0,2;1,1;track4;4]"..
|
||||
"button[1,2;1,1;track5;5]"..
|
||||
"button[2,2;1,1;track6;6]"..
|
||||
"button[0,3;1,1;track7;7]"..
|
||||
"button[1,3;1,1;track8;8]"..
|
||||
"button[2,3;1,1;track9;9]"..
|
||||
"button[3,1;1,1;stop;Stop]"..
|
||||
"label[0,4;"..minetest.formspec_escape(
|
||||
meta:get_int("active") == 0 and
|
||||
S("Stopped") or
|
||||
S("Current track %s"):format(meta:get_int("current_track"))).."]")
|
||||
end
|
||||
|
||||
minetest.register_node("technic:music_player", {
|
||||
description = S("%s Music Player"):format("LV"),
|
||||
tiles = {"technic_music_player_top.png", "technic_machine_bottom.png", "technic_music_player_side.png",
|
||||
"technic_music_player_side.png", "technic_music_player_side.png", "technic_music_player_side.png"},
|
||||
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
|
||||
technic_machine=1, technic_lv=1},
|
||||
connect_sides = {"bottom"},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", S("%s Music Player"):format("LV"))
|
||||
set_display(meta)
|
||||
end,
|
||||
on_receive_fields = function(pos, formanme, fields, sender)
|
||||
local new_track = nil
|
||||
if fields.stop then new_track = 0 end
|
||||
if fields.track1 then new_track = 1 end
|
||||
if fields.track2 then new_track = 2 end
|
||||
if fields.track3 then new_track = 3 end
|
||||
if fields.track4 then new_track = 4 end
|
||||
if fields.track5 then new_track = 5 end
|
||||
if fields.track6 then new_track = 6 end
|
||||
if fields.track7 then new_track = 7 end
|
||||
if fields.track8 then new_track = 8 end
|
||||
if fields.track9 then new_track = 9 end
|
||||
if new_track then
|
||||
stop_player(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_int("active", new_track == 0 and 0 or 1)
|
||||
meta:set_int("current_track", new_track)
|
||||
set_display(meta)
|
||||
end
|
||||
end,
|
||||
on_destruct = stop_player,
|
||||
technic_run = run,
|
||||
technic_on_disable = stop_player,
|
||||
})
|
||||
|
||||
technic.register_machine("LV", "technic:music_player", technic.receiver)
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
-- The solar array is an assembly of panels into a powerful array
|
||||
-- The assembly can deliver more energy than the individual panel because
|
||||
-- of the transformer unit which converts the panel output variations into
|
||||
-- a stable supply.
|
||||
-- Solar arrays are not able to store large amounts of energy.
|
||||
-- The LV arrays are used to make medium voltage arrays.
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:solar_array_lv 1',
|
||||
recipe = {
|
||||
{'technic:solar_panel', 'technic:solar_panel', 'technic:solar_panel'},
|
||||
{'technic:carbon_steel_ingot', 'technic:lv_transformer', 'technic:carbon_steel_ingot'},
|
||||
{'', 'technic:lv_cable', ''},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_solar_array({tier="LV", power=10})
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
-- Solar panels are the building blocks of LV solar arrays
|
||||
-- They can however also be used separately but with reduced efficiency due to the missing transformer.
|
||||
-- Individual panels are less efficient than when the panels are combined into full arrays.
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:solar_panel',
|
||||
recipe = {
|
||||
{'technic:doped_silicon_wafer', 'technic:doped_silicon_wafer', 'technic:doped_silicon_wafer'},
|
||||
{'basic_materials:silver_wire', 'technic:lv_cable', 'mesecons_materials:glue'},
|
||||
},
|
||||
replacements = { {"basic_materials:silver_wire", "basic_materials:empty_spool"}, },
|
||||
})
|
||||
|
||||
|
||||
local run = function(pos, node)
|
||||
-- The action here is to make the solar panel prodice power
|
||||
-- Power is dependent on the light level and the height above ground
|
||||
-- There are many ways to cheat by using other light sources like lamps.
|
||||
-- As there is no way to determine if light is sunlight that is just a shame.
|
||||
-- To take care of some of it solar panels do not work outside daylight hours or if
|
||||
-- built below 0m
|
||||
local pos1 = {x=pos.x, y=pos.y+1, z=pos.z}
|
||||
local machine_name = S("Small Solar %s Generator"):format("LV")
|
||||
|
||||
local light = minetest.get_node_light(pos1, nil)
|
||||
local time_of_day = minetest.get_timeofday()
|
||||
local meta = minetest.get_meta(pos)
|
||||
if light == nil then light = 0 end
|
||||
-- turn on panel only during day time and if sufficient light
|
||||
-- I know this is counter intuitive when cheating by using other light sources underground.
|
||||
if light >= 12 and time_of_day >= 0.24 and time_of_day <= 0.76 and pos.y > -10 then
|
||||
local charge_to_give = math.floor((light + pos1.y) * 3)
|
||||
charge_to_give = math.max(charge_to_give, 0)
|
||||
charge_to_give = math.min(charge_to_give, 200)
|
||||
meta:set_string("infotext", S("@1 Active (@2)", machine_name,
|
||||
technic.EU_string(charge_to_give)))
|
||||
meta:set_int("LV_EU_supply", charge_to_give)
|
||||
else
|
||||
meta:set_string("infotext", S("%s Idle"):format(machine_name))
|
||||
meta:set_int("LV_EU_supply", 0)
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node("technic:solar_panel", {
|
||||
tiles = {"technic_solar_panel_top.png", "technic_solar_panel_bottom.png", "technic_solar_panel_side.png",
|
||||
"technic_solar_panel_side.png", "technic_solar_panel_side.png", "technic_solar_panel_side.png"},
|
||||
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
|
||||
technic_machine=1, technic_lv=1},
|
||||
connect_sides = {"bottom"},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
description = S("Small Solar %s Generator"):format("LV"),
|
||||
active = false,
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
is_ground_content = true,
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.5, -0.5, -0.5, 0.5, 0, 0.5},
|
||||
},
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_int("LV_EU_supply", 0)
|
||||
meta:set_string("infotext", S("Small Solar %s Generator"):format("LV"))
|
||||
end,
|
||||
technic_run = run,
|
||||
})
|
||||
|
||||
technic.register_machine("LV", "technic:solar_panel", technic.producer)
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
-- A water mill produces LV EUs by exploiting flowing water across it
|
||||
-- It is a LV EU supplier and fairly low yield (max 180EUs)
|
||||
-- It is a little over half as good as the thermal generator.
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
local cable_entry = "^technic_cable_connection_overlay.png"
|
||||
|
||||
minetest.register_alias("water_mill", "technic:water_mill")
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:water_mill',
|
||||
recipe = {
|
||||
{'technic:marble', 'default:diamond', 'technic:marble'},
|
||||
{'group:wood', 'technic:machine_casing', 'group:wood'},
|
||||
{'technic:marble', 'technic:lv_cable', 'technic:marble'},
|
||||
}
|
||||
})
|
||||
|
||||
local function check_node_around_mill(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
if node.name == "default:water_flowing"
|
||||
or node.name == "default:river_water_flowing" then
|
||||
return node.param2 -- returns approx. water flow, if any
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local run = function(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local water_flow = 0
|
||||
local production_level
|
||||
local eu_supply
|
||||
local max_output = 4 * 45 -- keeping it around 180, little more than previous 150 :)
|
||||
|
||||
local positions = {
|
||||
{x=pos.x+1, y=pos.y, z=pos.z},
|
||||
{x=pos.x-1, y=pos.y, z=pos.z},
|
||||
{x=pos.x, y=pos.y, z=pos.z+1},
|
||||
{x=pos.x, y=pos.y, z=pos.z-1},
|
||||
}
|
||||
|
||||
for _, p in pairs(positions) do
|
||||
local check = check_node_around_mill(p)
|
||||
if check then
|
||||
water_flow = water_flow + check
|
||||
end
|
||||
end
|
||||
|
||||
eu_supply = math.min(4 * water_flow, max_output)
|
||||
production_level = math.floor(100 * eu_supply / max_output)
|
||||
|
||||
meta:set_int("LV_EU_supply", eu_supply)
|
||||
|
||||
meta:set_string("infotext",
|
||||
S("Hydro %s Generator"):format("LV").." ("..production_level.."%)")
|
||||
|
||||
if production_level > 0 and
|
||||
minetest.get_node(pos).name == "technic:water_mill" then
|
||||
technic.swap_node (pos, "technic:water_mill_active")
|
||||
meta:set_int("LV_EU_supply", 0)
|
||||
return
|
||||
end
|
||||
if production_level == 0 then
|
||||
technic.swap_node(pos, "technic:water_mill")
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node("technic:water_mill", {
|
||||
description = S("Hydro %s Generator"):format("LV"),
|
||||
tiles = {
|
||||
"technic_water_mill_top.png",
|
||||
"technic_machine_bottom.png"..cable_entry,
|
||||
"technic_water_mill_side.png",
|
||||
"technic_water_mill_side.png",
|
||||
"technic_water_mill_side.png",
|
||||
"technic_water_mill_side.png"
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
|
||||
technic_machine=1, technic_lv=1},
|
||||
legacy_facedir_simple = true,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", S("Hydro %s Generator"):format("LV"))
|
||||
meta:set_int("LV_EU_supply", 0)
|
||||
end,
|
||||
technic_run = run,
|
||||
})
|
||||
|
||||
minetest.register_node("technic:water_mill_active", {
|
||||
description = S("Hydro %s Generator"):format("LV"),
|
||||
tiles = {"technic_water_mill_top_active.png", "technic_machine_bottom.png",
|
||||
"technic_water_mill_side.png", "technic_water_mill_side.png",
|
||||
"technic_water_mill_side.png", "technic_water_mill_side.png"},
|
||||
paramtype2 = "facedir",
|
||||
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
|
||||
technic_machine=1, technic_lv=1, not_in_creative_inventory=1},
|
||||
legacy_facedir_simple = true,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
drop = "technic:water_mill",
|
||||
technic_run = run,
|
||||
technic_disabled_machine_name = "technic:water_mill",
|
||||
})
|
||||
|
||||
technic.register_machine("LV", "technic:water_mill", technic.producer)
|
||||
technic.register_machine("LV", "technic:water_mill_active", technic.producer)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
-- MV alloy furnace
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:mv_alloy_furnace',
|
||||
recipe = {
|
||||
{'technic:stainless_steel_ingot', 'technic:lv_alloy_furnace', 'technic:stainless_steel_ingot'},
|
||||
{'pipeworks:tube_1', 'technic:mv_transformer', 'pipeworks:tube_1'},
|
||||
{'technic:stainless_steel_ingot', 'technic:mv_cable', 'technic:stainless_steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
technic.register_alloy_furnace({tier = "MV", speed = 1.5, upgrade = 1, tube = 1, demand = {3000, 2000, 1000}})
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
-- MV Battery box
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:mv_battery_box0',
|
||||
recipe = {
|
||||
{'technic:lv_battery_box0', 'technic:lv_battery_box0', 'technic:lv_battery_box0'},
|
||||
{'technic:lv_battery_box0', 'technic:mv_transformer', 'technic:lv_battery_box0'},
|
||||
{'', 'technic:mv_cable', ''},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_battery_box({
|
||||
tier = "MV",
|
||||
max_charge = 200000,
|
||||
charge_rate = 20000,
|
||||
discharge_rate = 80000,
|
||||
charge_step = 2000,
|
||||
discharge_step = 8000,
|
||||
upgrade = 1,
|
||||
tube = 1,
|
||||
})
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
|
||||
minetest.register_alias("mv_cable", "technic:mv_cable")
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:mv_cable 3',
|
||||
recipe ={
|
||||
{'technic:rubber', 'technic:rubber', 'technic:rubber'},
|
||||
{'technic:lv_cable', 'technic:lv_cable', 'technic:lv_cable'},
|
||||
{'technic:rubber', 'technic:rubber', 'technic:rubber'},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_cable("MV", 2.5/16)
|
||||
|
||||
if minetest.get_modpath("digilines") then
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
if minetest.get_modpath("digistuff") then
|
||||
minetest.register_craft({
|
||||
output = 'technic:mv_digi_cable 1',
|
||||
type = "shapeless",
|
||||
recipe = {'digistuff:digimese', 'technic:mv_cable'}
|
||||
})
|
||||
else
|
||||
minetest.register_craft({
|
||||
output = 'technic:mv_digi_cable 1',
|
||||
recipe = {
|
||||
{'digilines:wire_std_00000000', 'digilines:wire_std_00000000', 'digilines:wire_std_00000000'},
|
||||
{'digilines:wire_std_00000000', 'technic:mv_cable', 'digilines:wire_std_00000000'},
|
||||
{'digilines:wire_std_00000000', 'digilines:wire_std_00000000', 'digilines:wire_std_00000000'},
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
technic.register_cable("MV", 2.5/16, S("MV Cable (digiline)"), "_digi", {
|
||||
digiline = {
|
||||
wire = {
|
||||
rules = {
|
||||
{x = 1, y = 0, z = 0},
|
||||
{x =-1, y = 0, z = 0},
|
||||
{x = 0, y = 1, z = 0},
|
||||
{x = 0, y =-1, z = 0},
|
||||
{x = 0, y = 0, z = 1},
|
||||
{x = 0, y = 0, z =-1}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
@@ -0,0 +1,16 @@
|
||||
minetest.register_craft({
|
||||
output = "technic:mv_centrifuge",
|
||||
recipe = {
|
||||
{"basic_materials:motor", "technic:copper_plate", "technic:diamond_drill_head"},
|
||||
{"technic:copper_plate", "technic:machine_casing", "technic:copper_plate" },
|
||||
{"pipeworks:one_way_tube", "technic:mv_cable", "pipeworks:mese_filter" },
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_centrifuge({
|
||||
tier = "MV",
|
||||
demand = { 8000, 7000, 6000 },
|
||||
speed = 2,
|
||||
upgrade = 1,
|
||||
tube = 1,
|
||||
})
|
||||
@@ -0,0 +1,12 @@
|
||||
-- MV compressor
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:mv_compressor',
|
||||
recipe = {
|
||||
{'technic:stainless_steel_ingot', 'technic:lv_compressor', 'technic:stainless_steel_ingot'},
|
||||
{'pipeworks:tube_1', 'technic:mv_transformer', 'pipeworks:tube_1'},
|
||||
{'technic:stainless_steel_ingot', 'technic:mv_cable', 'technic:stainless_steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_compressor({tier = "MV", demand = {800, 600, 400}, speed = 2, upgrade = 1, tube = 1})
|
||||
@@ -0,0 +1,18 @@
|
||||
-- MV Electric Furnace
|
||||
-- This is a faster version of the stone furnace which runs on EUs
|
||||
-- In addition to this it can be upgraded with microcontrollers and batteries
|
||||
-- This new version uses the batteries to lower the power consumption of the machine
|
||||
-- Also in addition this furnace can be attached to the pipe system from the pipeworks mod.
|
||||
|
||||
-- FIXME: kpoppel I'd like to introduce an induction heating element here also
|
||||
minetest.register_craft({
|
||||
output = 'technic:mv_electric_furnace',
|
||||
recipe = {
|
||||
{'technic:stainless_steel_ingot', 'technic:lv_electric_furnace', 'technic:stainless_steel_ingot'},
|
||||
{'pipeworks:tube_1', 'technic:mv_transformer', 'pipeworks:tube_1'},
|
||||
{'technic:stainless_steel_ingot', 'technic:mv_cable', 'technic:stainless_steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_electric_furnace({tier="MV", upgrade=1, tube=1, demand={2000, 1000, 500}, speed=4})
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
-- MV extractor
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:mv_extractor',
|
||||
recipe = {
|
||||
{'technic:stainless_steel_ingot', 'technic:lv_extractor', 'technic:stainless_steel_ingot'},
|
||||
{'pipeworks:tube_1', 'technic:mv_transformer', 'pipeworks:tube_1'},
|
||||
{'technic:stainless_steel_ingot', 'technic:mv_cable', 'technic:stainless_steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_extractor({tier = "MV", demand = {800, 600, 400}, speed = 2, upgrade = 1, tube = 1})
|
||||
@@ -0,0 +1,12 @@
|
||||
-- MV freezer
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:mv_freezer',
|
||||
recipe = {
|
||||
{'technic:stainless_steel_ingot', 'technic:motor', 'technic:stainless_steel_ingot'},
|
||||
{'pipeworks:pipe_1_empty', 'technic:mv_transformer', 'pipeworks:pipe_1_empty'},
|
||||
{'technic:stainless_steel_ingot', 'technic:mv_cable', 'technic:stainless_steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_freezer({tier = "MV", demand = {800, 600, 400}, speed = 0.5, upgrade = 1, tube = 1})
|
||||
@@ -0,0 +1,13 @@
|
||||
minetest.register_alias("generator_mv", "technic:generator_mv")
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:mv_generator',
|
||||
recipe = {
|
||||
{'technic:stainless_steel_ingot', 'technic:lv_generator', 'technic:stainless_steel_ingot'},
|
||||
{'pipeworks:tube_1', 'technic:mv_transformer', 'pipeworks:tube_1'},
|
||||
{'technic:stainless_steel_ingot', 'technic:mv_cable', 'technic:stainless_steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_generator({tier="MV", tube=1, supply=600})
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
-- MV grinder
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:mv_grinder',
|
||||
recipe = {
|
||||
{'technic:stainless_steel_ingot', 'technic:lv_grinder', 'technic:stainless_steel_ingot'},
|
||||
{'pipeworks:tube_1', 'technic:mv_transformer', 'pipeworks:tube_1'},
|
||||
{'technic:stainless_steel_ingot', 'technic:mv_cable', 'technic:stainless_steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_grinder({tier="MV", demand={600, 450, 300}, speed=2, upgrade=1, tube=1})
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
-- A Hydro Turbine produces MV EUs by exploiting flowing water across it
|
||||
-- It is a MV EU supplier and fairly high yield (max 1800EUs)
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
local cable_entry = "^technic_cable_connection_overlay.png"
|
||||
|
||||
minetest.register_alias("hydro_turbine", "technic:hydro_turbine")
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:hydro_turbine',
|
||||
recipe = {
|
||||
{'technic:stainless_steel_ingot', 'technic:water_mill', 'technic:stainless_steel_ingot'},
|
||||
{'technic:water_mill', 'technic:mv_transformer', 'technic:water_mill'},
|
||||
{'technic:stainless_steel_ingot', 'technic:mv_cable', 'technic:stainless_steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
local function get_water_flow(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
if minetest.get_item_group(node.name, "water") == 3 then
|
||||
return node.param2 -- returns approx. water flow, if any
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
---
|
||||
-- 10 times better than LV hydro because of 2 extra water mills and 4 stainless steel, a transformer and whatnot ;P.
|
||||
-- Man hydro turbines are tough and long lasting. So, give it some value :)
|
||||
local run = function(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local water_flow = 0
|
||||
local production_level
|
||||
local eu_supply
|
||||
local max_output = 40 * 45 -- Generates 1800EU/s
|
||||
|
||||
local positions = {
|
||||
{x=pos.x+1, y=pos.y, z=pos.z},
|
||||
{x=pos.x-1, y=pos.y, z=pos.z},
|
||||
{x=pos.x, y=pos.y, z=pos.z+1},
|
||||
{x=pos.x, y=pos.y, z=pos.z-1},
|
||||
}
|
||||
|
||||
for _, p in pairs(positions) do
|
||||
water_flow = water_flow + get_water_flow(p)
|
||||
end
|
||||
|
||||
eu_supply = math.min(40 * water_flow, max_output)
|
||||
production_level = math.floor(100 * eu_supply / max_output)
|
||||
|
||||
meta:set_int("MV_EU_supply", eu_supply)
|
||||
|
||||
meta:set_string("infotext",
|
||||
S("Hydro %s Generator"):format("MV").." ("..production_level.."%)")
|
||||
if production_level > 0 and
|
||||
minetest.get_node(pos).name == "technic:hydro_turbine" then
|
||||
technic.swap_node(pos, "technic:hydro_turbine_active")
|
||||
meta:set_int("MV_EU_supply", 0)
|
||||
return
|
||||
end
|
||||
if production_level == 0 then
|
||||
technic.swap_node(pos, "technic:hydro_turbine")
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node("technic:hydro_turbine", {
|
||||
description = S("Hydro %s Generator"):format("MV"),
|
||||
tiles = {
|
||||
"technic_hydro_turbine_top.png",
|
||||
"technic_machine_bottom.png"..cable_entry,
|
||||
"technic_hydro_turbine_side.png",
|
||||
"technic_hydro_turbine_side.png",
|
||||
"technic_hydro_turbine_side.png",
|
||||
"technic_hydro_turbine_side.png"
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
|
||||
technic_machine=1, technic_mv=1},
|
||||
legacy_facedir_simple = true,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", S("Hydro %s Generator"):format("MV"))
|
||||
meta:set_int("MV_EU_supply", 0)
|
||||
end,
|
||||
technic_run = run,
|
||||
})
|
||||
|
||||
minetest.register_node("technic:hydro_turbine_active", {
|
||||
description = S("Hydro %s Generator"):format("MV"),
|
||||
tiles = {"technic_hydro_turbine_top_active.png", "technic_machine_bottom.png",
|
||||
"technic_hydro_turbine_side.png", "technic_hydro_turbine_side.png",
|
||||
"technic_hydro_turbine_side.png", "technic_hydro_turbine_side.png"},
|
||||
paramtype2 = "facedir",
|
||||
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
|
||||
technic_machine=1, technic_mv=1, not_in_creative_inventory=1},
|
||||
legacy_facedir_simple = true,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
drop = "technic:hydro_turbine",
|
||||
technic_run = run,
|
||||
technic_disabled_machine_name = "technic:hydro_turbine",
|
||||
})
|
||||
|
||||
technic.register_machine("MV", "technic:hydro_turbine", technic.producer)
|
||||
technic.register_machine("MV", "technic:hydro_turbine_active", technic.producer)
|
||||
@@ -0,0 +1,35 @@
|
||||
|
||||
technic.register_tier("MV", "Medium Voltage")
|
||||
|
||||
local path = technic.modpath.."/machines/MV"
|
||||
|
||||
-- Wiring stuff
|
||||
dofile(path.."/cables.lua")
|
||||
dofile(path.."/battery_box.lua")
|
||||
|
||||
-- Generators
|
||||
if technic.config:get_bool("enable_wind_mill") then
|
||||
dofile(path.."/wind_mill.lua")
|
||||
end
|
||||
dofile(path.."/generator.lua")
|
||||
dofile(path.."/solar_array.lua")
|
||||
dofile(path.."/hydro_turbine.lua")
|
||||
|
||||
-- Machines
|
||||
dofile(path.."/alloy_furnace.lua")
|
||||
dofile(path.."/electric_furnace.lua")
|
||||
dofile(path.."/grinder.lua")
|
||||
dofile(path.."/extractor.lua")
|
||||
dofile(path.."/compressor.lua")
|
||||
dofile(path.."/centrifuge.lua")
|
||||
|
||||
dofile(path.."/tool_workshop.lua")
|
||||
|
||||
dofile(path.."/freezer.lua")
|
||||
|
||||
-- The power radiator supplies appliances with inductive coupled power:
|
||||
-- Lighting and associated textures is taken directly from VanessaE's homedecor and made electric.
|
||||
-- This is currently useless, slow, and mostly copied
|
||||
--dofile(path.."/power_radiator.lua")
|
||||
--dofile(path.."/lighting.lua")
|
||||
|
||||
@@ -0,0 +1,575 @@
|
||||
-- NOTE: The code is takes directly from VanessaE's homedecor mod.
|
||||
-- I just made it the lights into indictive appliances for this mod.
|
||||
|
||||
-- This file supplies electric powered glowlights
|
||||
|
||||
-- Boilerplate to support localized strings if intllib mod is installed.
|
||||
local S
|
||||
if (minetest.get_modpath("intllib")) then
|
||||
dofile(minetest.get_modpath("intllib").."/intllib.lua")
|
||||
S = intllib.Getter(minetest.get_current_modname())
|
||||
else
|
||||
S = function (s) return s end
|
||||
end
|
||||
|
||||
local function technic_homedecor_node_is_owned(pos, placer)
|
||||
local ownername = false
|
||||
if type(isprotect) == "function" then -- glomie's protection mod
|
||||
if not isprotect(5, pos, placer) then
|
||||
ownername = S("someone")
|
||||
end
|
||||
elseif type(protector) == "table" and type(protector.can_dig) == "function" then -- Zeg9's protection mod
|
||||
if not protector.can_dig(5, pos, placer) then
|
||||
ownername = S("someone")
|
||||
end
|
||||
end
|
||||
|
||||
if ownername ~= false then
|
||||
minetest.chat_send_player(placer:get_player_name(), S("Sorry, %s owns that spot."):format(ownername) )
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
local dirs2 = {9, 18, 7, 12}
|
||||
|
||||
local technic_homedecor_rotate_and_place = function(itemstack, placer, pointed_thing)
|
||||
if not technic_homedecor_node_is_owned(pointed_thing.under, placer)
|
||||
and not technic_homedecor_node_is_owned(pointed_thing.above, placer) then
|
||||
local node = minetest.get_node(pointed_thing.under)
|
||||
if not minetest.registered_nodes[node.name] or not minetest.registered_nodes[node.name].on_rightclick then
|
||||
|
||||
local above = pointed_thing.above
|
||||
local under = pointed_thing.under
|
||||
local pitch = placer:get_look_pitch()
|
||||
local pname = minetest.get_node(under).name
|
||||
local fdir = minetest.dir_to_facedir(placer:get_look_dir())
|
||||
local wield_name = itemstack:get_name()
|
||||
|
||||
if not minetest.registered_nodes[pname]
|
||||
or not minetest.registered_nodes[pname].on_rightclick then
|
||||
|
||||
local iswall = (above.x ~= under.x) or (above.z ~= under.z)
|
||||
local isceiling = (above.x == under.x) and (above.z == under.z) and (pitch > 0)
|
||||
local pos1 = above
|
||||
|
||||
if minetest.registered_nodes[pname]["buildable_to"] then
|
||||
pos1 = under
|
||||
iswall = false
|
||||
end
|
||||
|
||||
if not minetest.registered_nodes[minetest.get_node(pos1).name]["buildable_to"] then return end
|
||||
|
||||
if iswall then
|
||||
minetest.add_node(pos1, {name = wield_name, param2 = dirs2[fdir+1] }) -- place wall variant
|
||||
elseif isceiling then
|
||||
minetest.add_node(pos1, {name = wield_name, param2 = 20 }) -- place upside down variant
|
||||
else
|
||||
minetest.add_node(pos1, {name = wield_name, param2 = 0 }) -- place right side up
|
||||
end
|
||||
|
||||
if not homedecor_expect_infinite_stacks then
|
||||
itemstack:take_item()
|
||||
return itemstack
|
||||
end
|
||||
end
|
||||
else
|
||||
minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Yellow -- Half node
|
||||
minetest.register_node('technic:homedecor_glowlight_half_yellow', {
|
||||
description = S("Yellow Glowlight (thick)"),
|
||||
drawtype = "nodebox",
|
||||
tiles = {
|
||||
'technic_homedecor_glowlight_yellow_tb.png',
|
||||
'technic_homedecor_glowlight_yellow_tb.png',
|
||||
'technic_homedecor_glowlight_thick_yellow_sides.png',
|
||||
'technic_homedecor_glowlight_thick_yellow_sides.png',
|
||||
'technic_homedecor_glowlight_thick_yellow_sides.png',
|
||||
'technic_homedecor_glowlight_thick_yellow_sides.png'
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.5, -0.5, 0.5, 0, 0.5 }
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.5, -0.5, 0.5, 0, 0.5 }
|
||||
},
|
||||
|
||||
sunlight_propagates = false,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = true,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
|
||||
groups = { snappy = 3 },
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
technic_homedecor_rotate_and_place(itemstack, placer, pointed_thing)
|
||||
return itemstack
|
||||
end,
|
||||
on_construct = function(pos)
|
||||
technic.inductive_on_construct(pos, 100, "Yellow Glowlight (thick)")
|
||||
end,
|
||||
on_punch = function(pos, node, puncher)
|
||||
technic.inductive_on_punch_off(pos, 100, "technic:homedecor_glowlight_half_yellow_active")
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_node('technic:homedecor_glowlight_half_yellow_active', {
|
||||
description = S("Yellow Glowlight (thick)"),
|
||||
drawtype = "nodebox",
|
||||
tiles = {
|
||||
'technic_homedecor_glowlight_yellow_tb.png',
|
||||
'technic_homedecor_glowlight_yellow_tb.png',
|
||||
'technic_homedecor_glowlight_thick_yellow_sides.png',
|
||||
'technic_homedecor_glowlight_thick_yellow_sides.png',
|
||||
'technic_homedecor_glowlight_thick_yellow_sides.png',
|
||||
'technic_homedecor_glowlight_thick_yellow_sides.png'
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.5, -0.5, 0.5, 0, 0.5 }
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.5, -0.5, 0.5, 0, 0.5 }
|
||||
},
|
||||
|
||||
sunlight_propagates = false,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = true,
|
||||
light_source = minetest.LIGHT_MAX,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
|
||||
groups = { snappy = 3, not_in_creative_inventory=1},
|
||||
drop="technic:homedecor_glowlight_half_yellow",
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
technic_homedecor_rotate_and_place(itemstack, placer, pointed_thing)
|
||||
return itemstack
|
||||
end,
|
||||
on_construct = function(pos)
|
||||
technic.inductive_on_construct(pos, 100, "Yellow Glowlight (thick)")
|
||||
end,
|
||||
on_punch = function(pos, node, puncher)
|
||||
technic.inductive_on_punch_on(pos, 0, "technic:homedecor_glowlight_half_yellow")
|
||||
end
|
||||
})
|
||||
|
||||
-- Yellow -- Quarter node
|
||||
minetest.register_node('technic:homedecor_glowlight_quarter_yellow', {
|
||||
description = S("Yellow Glowlight (thin)"),
|
||||
drawtype = "nodebox",
|
||||
tiles = {
|
||||
'technic_homedecor_glowlight_yellow_tb.png',
|
||||
'technic_homedecor_glowlight_yellow_tb.png',
|
||||
'technic_homedecor_glowlight_thin_yellow_sides.png',
|
||||
'technic_homedecor_glowlight_thin_yellow_sides.png',
|
||||
'technic_homedecor_glowlight_thin_yellow_sides.png',
|
||||
'technic_homedecor_glowlight_thin_yellow_sides.png'
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.5, -0.5, 0.5, -0.25, 0.5 }
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.5, -0.5, 0.5, -0.25, 0.5 }
|
||||
},
|
||||
|
||||
sunlight_propagates = false,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = true,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
|
||||
groups = { snappy = 3 },
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
technic_homedecor_rotate_and_place(itemstack, placer, pointed_thing)
|
||||
return itemstack
|
||||
end,
|
||||
on_construct = function(pos)
|
||||
technic.inductive_on_construct(pos, 100, "Yellow Glowlight (thin)")
|
||||
end,
|
||||
on_punch = function(pos, node, puncher)
|
||||
technic.inductive_on_punch_off(pos, 100, "technic:homedecor_glowlight_quarter_yellow_active")
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_node('technic:homedecor_glowlight_quarter_yellow_active', {
|
||||
description = S("Yellow Glowlight (thin)"),
|
||||
drawtype = "nodebox",
|
||||
tiles = {
|
||||
'technic_homedecor_glowlight_yellow_tb.png',
|
||||
'technic_homedecor_glowlight_yellow_tb.png',
|
||||
'technic_homedecor_glowlight_thin_yellow_sides.png',
|
||||
'technic_homedecor_glowlight_thin_yellow_sides.png',
|
||||
'technic_homedecor_glowlight_thin_yellow_sides.png',
|
||||
'technic_homedecor_glowlight_thin_yellow_sides.png'
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.5, -0.5, 0.5, -0.25, 0.5 }
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.5, -0.5, 0.5, -0.25, 0.5 }
|
||||
},
|
||||
|
||||
sunlight_propagates = false,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = true,
|
||||
light_source = minetest.LIGHT_MAX-1,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
|
||||
groups = { snappy = 3, not_in_creative_inventory=1},
|
||||
drop="technic:homedecor_glowlight_quarter_yellow",
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
technic_homedecor_rotate_and_place(itemstack, placer, pointed_thing)
|
||||
return itemstack
|
||||
end,
|
||||
on_construct = function(pos)
|
||||
technic.inductive_on_construct(pos, 100, "Yellow Glowlight (thin)")
|
||||
end,
|
||||
on_punch = function(pos, node, puncher)
|
||||
technic.inductive_on_punch_on(pos, 0, "technic:homedecor_glowlight_quarter_yellow")
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
-- White -- half node
|
||||
minetest.register_node('technic:homedecor_glowlight_half_white', {
|
||||
description = S("White Glowlight (thick)"),
|
||||
drawtype = "nodebox",
|
||||
tiles = {
|
||||
'technic_homedecor_glowlight_white_tb.png',
|
||||
'technic_homedecor_glowlight_white_tb.png',
|
||||
'technic_homedecor_glowlight_thick_white_sides.png',
|
||||
'technic_homedecor_glowlight_thick_white_sides.png',
|
||||
'technic_homedecor_glowlight_thick_white_sides.png',
|
||||
'technic_homedecor_glowlight_thick_white_sides.png'
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.5, -0.5, 0.5, 0, 0.5 }
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.5, -0.5, 0.5, 0, 0.5 }
|
||||
},
|
||||
|
||||
sunlight_propagates = false,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = true,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
|
||||
groups = { snappy = 3 },
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
technic_homedecor_rotate_and_place(itemstack, placer, pointed_thing)
|
||||
return itemstack
|
||||
end,
|
||||
on_construct = function(pos)
|
||||
technic.inductive_on_construct(pos, 100, "White Glowlight (thick)")
|
||||
end,
|
||||
on_punch = function(pos, node, puncher)
|
||||
technic.inductive_on_punch_off(pos, 100, "technic:homedecor_glowlight_half_white_active")
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_node('technic:homedecor_glowlight_half_white_active', {
|
||||
description = S("White Glowlight (thick)"),
|
||||
drawtype = "nodebox",
|
||||
tiles = {
|
||||
'technic_homedecor_glowlight_white_tb.png',
|
||||
'technic_homedecor_glowlight_white_tb.png',
|
||||
'technic_homedecor_glowlight_thick_white_sides.png',
|
||||
'technic_homedecor_glowlight_thick_white_sides.png',
|
||||
'technic_homedecor_glowlight_thick_white_sides.png',
|
||||
'technic_homedecor_glowlight_thick_white_sides.png'
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.5, -0.5, 0.5, 0, 0.5 }
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.5, -0.5, 0.5, 0, 0.5 }
|
||||
},
|
||||
|
||||
sunlight_propagates = false,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = true,
|
||||
light_source = minetest.LIGHT_MAX,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
|
||||
groups = { snappy = 3, not_in_creative_inventory=1},
|
||||
drop="technic:homedecor_glowlight_half_white",
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
technic_homedecor_rotate_and_place(itemstack, placer, pointed_thing)
|
||||
return itemstack
|
||||
end,
|
||||
on_construct = function(pos)
|
||||
technic.inductive_on_construct(pos, 100, "White Glowlight (thick)")
|
||||
end,
|
||||
on_punch = function(pos, node, puncher)
|
||||
technic.inductive_on_punch_on(pos, 0, "technic:homedecor_glowlight_half_white")
|
||||
end
|
||||
})
|
||||
|
||||
-- White -- Quarter node
|
||||
minetest.register_node('technic:homedecor_glowlight_quarter_white', {
|
||||
description = S("White Glowlight (thin)"),
|
||||
drawtype = "nodebox",
|
||||
tiles = {
|
||||
'technic_homedecor_glowlight_white_tb.png',
|
||||
'technic_homedecor_glowlight_white_tb.png',
|
||||
'technic_homedecor_glowlight_thin_white_sides.png',
|
||||
'technic_homedecor_glowlight_thin_white_sides.png',
|
||||
'technic_homedecor_glowlight_thin_white_sides.png',
|
||||
'technic_homedecor_glowlight_thin_white_sides.png'
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.5, -0.5, 0.5, -0.25, 0.5 }
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.5, -0.5, 0.5, -0.25, 0.5 }
|
||||
},
|
||||
|
||||
sunlight_propagates = false,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = true,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
|
||||
groups = { snappy = 3 },
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
technic_homedecor_rotate_and_place(itemstack, placer, pointed_thing)
|
||||
return itemstack
|
||||
end,
|
||||
on_construct = function(pos)
|
||||
technic.inductive_on_construct(pos, 100, "White Glowlight (thin)")
|
||||
end,
|
||||
on_punch = function(pos, node, puncher)
|
||||
technic.inductive_on_punch_off(pos, 100, "technic:homedecor_glowlight_quarter_white_active")
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_node('technic:homedecor_glowlight_quarter_white_active', {
|
||||
description = S("White Glowlight (thin)"),
|
||||
drawtype = "nodebox",
|
||||
tiles = {
|
||||
'technic_homedecor_glowlight_white_tb.png',
|
||||
'technic_homedecor_glowlight_white_tb.png',
|
||||
'technic_homedecor_glowlight_thin_white_sides.png',
|
||||
'technic_homedecor_glowlight_thin_white_sides.png',
|
||||
'technic_homedecor_glowlight_thin_white_sides.png',
|
||||
'technic_homedecor_glowlight_thin_white_sides.png'
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.5, -0.5, 0.5, -0.25, 0.5 }
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.5, -0.5, -0.5, 0.5, -0.25, 0.5 }
|
||||
},
|
||||
|
||||
sunlight_propagates = false,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = true,
|
||||
light_source = minetest.LIGHT_MAX-1,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
|
||||
groups = { snappy = 3, not_in_creative_inventory=1},
|
||||
drop="technic:homedecor_glowlight_quarter_white",
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
technic_homedecor_rotate_and_place(itemstack, placer, pointed_thing)
|
||||
return itemstack
|
||||
end,
|
||||
on_construct = function(pos)
|
||||
technic.inductive_on_construct(pos, 100, "White Glowlight (thin)")
|
||||
end,
|
||||
on_punch = function(pos, node, puncher)
|
||||
technic.inductive_on_punch_on(pos, 0, "technic:homedecor_glowlight_quarter_white")
|
||||
end
|
||||
})
|
||||
|
||||
-- Glowlight "cubes" - yellow
|
||||
minetest.register_node('technic:homedecor_glowlight_small_cube_yellow', {
|
||||
description = S("Yellow Glowlight (small cube)"),
|
||||
drawtype = "nodebox",
|
||||
tiles = {
|
||||
'technic_homedecor_glowlight_cube_yellow_tb.png',
|
||||
'technic_homedecor_glowlight_cube_yellow_tb.png',
|
||||
'technic_homedecor_glowlight_cube_yellow_sides.png',
|
||||
'technic_homedecor_glowlight_cube_yellow_sides.png',
|
||||
'technic_homedecor_glowlight_cube_yellow_sides.png',
|
||||
'technic_homedecor_glowlight_cube_yellow_sides.png'
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.25, -0.5, -0.25, 0.25, 0, 0.25 }
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.25, -0.5, -0.25, 0.25, 0, 0.25 }
|
||||
},
|
||||
|
||||
sunlight_propagates = false,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = true,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
|
||||
groups = { snappy = 3 },
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
technic_homedecor_rotate_and_place(itemstack, placer, pointed_thing)
|
||||
return itemstack
|
||||
end,
|
||||
on_construct = function(pos)
|
||||
technic.inductive_on_construct(pos, 50, "Yellow Glowlight (small cube)")
|
||||
end,
|
||||
on_punch = function(pos, node, puncher)
|
||||
technic.inductive_on_punch_off(pos, 50, "technic:homedecor_glowlight_small_cube_yellow_active")
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_node('technic:homedecor_glowlight_small_cube_yellow_active', {
|
||||
description = S("Yellow Glowlight (small cube)"),
|
||||
drawtype = "nodebox",
|
||||
tiles = {
|
||||
'technic_homedecor_glowlight_cube_yellow_tb.png',
|
||||
'technic_homedecor_glowlight_cube_yellow_tb.png',
|
||||
'technic_homedecor_glowlight_cube_yellow_sides.png',
|
||||
'technic_homedecor_glowlight_cube_yellow_sides.png',
|
||||
'technic_homedecor_glowlight_cube_yellow_sides.png',
|
||||
'technic_homedecor_glowlight_cube_yellow_sides.png'
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.25, -0.5, -0.25, 0.25, 0, 0.25 }
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.25, -0.5, -0.25, 0.25, 0, 0.25 }
|
||||
},
|
||||
|
||||
sunlight_propagates = false,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = true,
|
||||
light_source = minetest.LIGHT_MAX-1,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
|
||||
groups = { snappy = 3, not_in_creative_inventory=1},
|
||||
drop="technic:homedecor_glowlight_small_cube_yellow",
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
technic_homedecor_rotate_and_place(itemstack, placer, pointed_thing)
|
||||
return itemstack
|
||||
end,
|
||||
on_construct = function(pos)
|
||||
technic.inductive_on_construct(pos, 50, "Yellow Glowlight (small cube)")
|
||||
end,
|
||||
on_punch = function(pos, node, puncher)
|
||||
technic.inductive_on_punch_on(pos, 0, "technic:homedecor_glowlight_small_cube_yellow")
|
||||
end
|
||||
})
|
||||
|
||||
-- Glowlight "cubes" - white
|
||||
minetest.register_node('technic:homedecor_glowlight_small_cube_white', {
|
||||
description = S("White Glowlight (small cube)"),
|
||||
drawtype = "nodebox",
|
||||
tiles = {
|
||||
'technic_homedecor_glowlight_cube_white_tb.png',
|
||||
'technic_homedecor_glowlight_cube_white_tb.png',
|
||||
'technic_homedecor_glowlight_cube_white_sides.png',
|
||||
'technic_homedecor_glowlight_cube_white_sides.png',
|
||||
'technic_homedecor_glowlight_cube_white_sides.png',
|
||||
'technic_homedecor_glowlight_cube_white_sides.png'
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.25, -0.5, -0.25, 0.25, 0, 0.25 }
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.25, -0.5, -0.25, 0.25, 0, 0.25 }
|
||||
},
|
||||
|
||||
sunlight_propagates = false,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = true,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
|
||||
groups = { snappy = 3 },
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
technic_homedecor_rotate_and_place(itemstack, placer, pointed_thing)
|
||||
return itemstack
|
||||
end,
|
||||
on_construct = function(pos)
|
||||
technic.inductive_on_construct(pos, 50, "White Glowlight (small cube)")
|
||||
end,
|
||||
on_punch = function(pos, node, puncher)
|
||||
technic.inductive_on_punch_off(pos, 50, "technic:homedecor_glowlight_small_cube_white_active")
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_node('technic:homedecor_glowlight_small_cube_white_active', {
|
||||
description = S("White Glowlight (small cube)"),
|
||||
drawtype = "nodebox",
|
||||
tiles = {
|
||||
'technic_homedecor_glowlight_cube_white_tb.png',
|
||||
'technic_homedecor_glowlight_cube_white_tb.png',
|
||||
'technic_homedecor_glowlight_cube_white_sides.png',
|
||||
'technic_homedecor_glowlight_cube_white_sides.png',
|
||||
'technic_homedecor_glowlight_cube_white_sides.png',
|
||||
'technic_homedecor_glowlight_cube_white_sides.png'
|
||||
},
|
||||
selection_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.25, -0.5, -0.25, 0.25, 0, 0.25 }
|
||||
},
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = { -0.25, -0.5, -0.25, 0.25, 0, 0.25 }
|
||||
},
|
||||
|
||||
sunlight_propagates = false,
|
||||
paramtype = "light",
|
||||
paramtype2 = "facedir",
|
||||
walkable = true,
|
||||
light_source = minetest.LIGHT_MAX-1,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
|
||||
groups = { snappy = 3, not_in_creative_inventory=1},
|
||||
drop="technic:homedecor_glowlight_small_cube_white",
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
technic_homedecor_rotate_and_place(itemstack, placer, pointed_thing)
|
||||
return itemstack
|
||||
end,
|
||||
on_construct = function(pos)
|
||||
technic.inductive_on_construct(pos, 50, "White Glowlight (small cube)")
|
||||
end,
|
||||
on_punch = function(pos, node, puncher)
|
||||
technic.inductive_on_punch_on(pos, 0, "technic:homedecor_glowlight_small_cube_white")
|
||||
end
|
||||
})
|
||||
|
||||
technic.register_inductive_machine("technic:homedecor_glowlight_half_yellow")
|
||||
technic.register_inductive_machine("technic:homedecor_glowlight_half_white")
|
||||
technic.register_inductive_machine("technic:homedecor_glowlight_quarter_yellow")
|
||||
technic.register_inductive_machine("technic:homedecor_glowlight_quarter_white")
|
||||
technic.register_inductive_machine("technic:homedecor_glowlight_small_cube_yellow")
|
||||
technic.register_inductive_machine("technic:homedecor_glowlight_small_cube_white")
|
||||
@@ -0,0 +1,220 @@
|
||||
-- The power radiator fuctions like an inductive charger
|
||||
-- only better in the game setting.
|
||||
-- The purpose is to allow small appliances to receive power
|
||||
-- without the overhead of the wiring needed for larger machines.
|
||||
--
|
||||
-- The power radiator will consume power corresponding to the
|
||||
-- sum(power rating of the attached appliances)/0.06
|
||||
-- Using inductive power transfer is very inefficient so this is
|
||||
-- set to the factor 0.06.
|
||||
--
|
||||
-- Punching the radiator will toggle the power state of all attached appliances.
|
||||
|
||||
local power_radius = 12
|
||||
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:power_radiator 1',
|
||||
recipe = {
|
||||
{'technic:stainless_steel_ingot', 'technic:mv_transformer', 'technic:stainless_steel_ingot'},
|
||||
{'technic:copper_coil', 'technic:machine_casing', 'technic:copper_coil'},
|
||||
{'technic:rubber', 'technic:mv_cable', 'technic:rubber'},
|
||||
}
|
||||
})
|
||||
|
||||
------------------------------------------------------------------
|
||||
-- API for inductive powered nodes:
|
||||
-- Use the functions below to set the corresponding callbacks
|
||||
-- Also two nodes are needed: The inactive and the active one. The active must be called <name>_active .
|
||||
------------------------------------------------------------------
|
||||
-- Register a new appliance using this function
|
||||
|
||||
technic.inductive_nodes = {}
|
||||
technic.register_inductive_machine = function(name)
|
||||
table.insert(technic.inductive_nodes, name)
|
||||
table.insert(technic.inductive_nodes, name.."_active")
|
||||
end
|
||||
|
||||
-- Appliances:
|
||||
-- has_supply: pos of supply node if the appliance has a power radiator near with sufficient power for the demand
|
||||
-- EU_demand: The power demand of the device.
|
||||
-- EU_charge: Actual use. set to EU_demand if active==1
|
||||
-- active: set to 1 if the device is on
|
||||
technic.inductive_on_construct = function(pos, eu_demand, infotext)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", infotext)
|
||||
meta:set_int("technic_inductive_power_machine", 1)
|
||||
meta:set_int("EU_demand", eu_demand) -- The power demand of this appliance
|
||||
meta:set_int("EU_charge", 0) -- The actual power draw of this appliance
|
||||
meta:set_string("has_supply", "") -- Register whether we are powered or not. For use with several radiators.
|
||||
meta:set_int("active", 0) -- If the appliance can be turned on and off by using it use this.
|
||||
end
|
||||
|
||||
technic.inductive_on_punch_off = function(pos, eu_charge, swapnode)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_string("has_supply") ~= "" then
|
||||
technic.swap_node(pos, swapnode)
|
||||
meta:set_int("active", 1)
|
||||
meta:set_int("EU_charge",eu_charge)
|
||||
--print("-----------")
|
||||
--print("Turn on:")
|
||||
--print("EU_charge: "..meta:get_int("EU_charge"))
|
||||
--print("has_supply: "..meta:get_string("has_supply"))
|
||||
--print("<----------->")
|
||||
end
|
||||
end
|
||||
|
||||
technic.inductive_on_punch_on = function(pos, eu_charge, swapnode)
|
||||
local meta = minetest.get_meta(pos)
|
||||
technic.swap_node(pos, swapnode)
|
||||
meta:set_int("active", 0)
|
||||
meta:set_int("EU_charge",eu_charge)
|
||||
--print("-----------")
|
||||
--print("Turn off:")
|
||||
--print("EU_charge: "..meta:get_int("EU_charge"))
|
||||
--print("has_supply: "..meta:get_string("has_supply"))
|
||||
--print("<---------->")
|
||||
end
|
||||
|
||||
local shutdown_inductive_appliances = function(pos)
|
||||
-- The supply radius
|
||||
local rad = power_radius
|
||||
-- If the radiator is removed. turn off all appliances in region
|
||||
-- If another radiator is near it will turn on the appliances again
|
||||
local positions = minetest.find_nodes_in_area(
|
||||
{x=pos.x-rad, y=pos.y-rad, z=pos.z-rad},
|
||||
{x=pos.x+rad, y=pos.y+rad, z=pos.z+rad},
|
||||
technic.inductive_nodes)
|
||||
for _, pos1 in pairs(positions) do
|
||||
local meta1 = minetest.get_meta(pos1)
|
||||
-- If the appliance is belonging to this node
|
||||
if meta1:get_string("has_supply") == pos.x..pos.y..pos.z then
|
||||
local nodename = minetest.get_node(pos1).name
|
||||
-- Swap the node and make sure it is off and unpowered
|
||||
if string.sub(nodename, -7) == "_active" then
|
||||
technic.swap_node(pos1, string.sub(nodename, 1, -8))
|
||||
meta1:set_int("active", 0)
|
||||
meta1:set_int("EU_charge", 0)
|
||||
end
|
||||
meta1:set_string("has_supply", "")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local toggle_on_off_inductive_appliances = function(pos, node, puncher)
|
||||
if pos == nil then return end
|
||||
-- The supply radius
|
||||
local rad = power_radius
|
||||
local positions = minetest.find_nodes_in_area(
|
||||
{x=pos.x-rad, y=pos.y-rad, z=pos.z-rad},
|
||||
{x=pos.x+rad, y=pos.y+rad, z=pos.z+rad},
|
||||
technic.inductive_nodes)
|
||||
for _, pos1 in pairs(positions) do
|
||||
local meta1 = minetest.get_meta(pos1)
|
||||
if meta1:get_string("has_supply") == pos.x..pos.y..pos.z then
|
||||
minetest.punch_node(pos1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_node("technic:power_radiator", {
|
||||
description = "MV Power Radiator",
|
||||
tiles = {"technic_lv_cable.png", "technic_lv_cable.png", "technic_lv_cable.png",
|
||||
"technic_lv_cable.png", "technic_lv_cable.png", "technic_lv_cable.png"},
|
||||
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
is_ground_content = true,
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
|
||||
},
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_int("MV_EU_demand",1) -- Demand on the primary side when idle
|
||||
meta:set_int("connected_EU_demand",0) -- Potential demand of connected appliances
|
||||
meta:set_string("infotext", "MV Power Radiator")
|
||||
end,
|
||||
on_dig = function(pos, node, digger)
|
||||
shutdown_inductive_appliances(pos)
|
||||
return minetest.node_dig(pos, node, digger)
|
||||
end,
|
||||
on_punch = function(pos, node, puncher)
|
||||
toggle_on_off_inductive_appliances(pos, node, puncher)
|
||||
end
|
||||
})
|
||||
|
||||
minetest.register_abm({
|
||||
label = "Machines: run power radiator",
|
||||
nodenames = {"technic:power_radiator"},
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local eu_input = meta:get_int("MV_EU_input")
|
||||
local eu_demand = meta:get_int("MV_EU_demand")
|
||||
|
||||
-- Power off automatically if no longer connected to a switching station
|
||||
technic.switching_station_timeout_count(pos, "MV")
|
||||
|
||||
if eu_input == 0 then
|
||||
-- No power
|
||||
meta:set_string("infotext", "MV Power Radiator is unpowered");
|
||||
-- meta:set_int("active", 1) -- used for setting textures someday maybe
|
||||
shutdown_inductive_appliances(pos)
|
||||
meta:set_int("connected_EU_demand", 0)
|
||||
meta:set_int("MV_EU_demand",1)
|
||||
elseif eu_input == eu_demand then
|
||||
-- Powered and ready
|
||||
|
||||
-- The maximum EU sourcing a single radiator can provide.
|
||||
local max_charge = 30000 -- == the max EU demand of the radiator
|
||||
local connected_EU_demand = meta:get_int("connected_EU_demand")
|
||||
|
||||
-- Efficiency factor
|
||||
local eff_factor = 0.06
|
||||
-- The supply radius
|
||||
local rad = power_radius
|
||||
|
||||
local used_charge = 0
|
||||
|
||||
-- Index all nodes within supply range
|
||||
local positions = minetest.find_nodes_in_area(
|
||||
{x=pos.x-rad, y=pos.y-rad, z=pos.z-rad},
|
||||
{x=pos.x+rad, y=pos.y+rad, z=pos.z+rad},
|
||||
technic.inductive_nodes)
|
||||
for _, pos1 in pairs(positions) do
|
||||
local meta1 = minetest.get_meta(pos1)
|
||||
-- If not supplied see if this node can handle it.
|
||||
if meta1:get_string("has_supply") == "" then
|
||||
-- if demand surpasses the capacity of this node, don't bother adding it.
|
||||
local app_eu_demand = math.floor(meta1:get_int("EU_demand") / eff_factor)
|
||||
if connected_EU_demand + app_eu_demand <= max_charge then
|
||||
-- We can power the appliance. Register, and spend power if it is on.
|
||||
connected_EU_demand = connected_EU_demand + app_eu_demand
|
||||
|
||||
meta1:set_string("has_supply", pos.x..pos.y..pos.z)
|
||||
--Always 0: used_charge = math.floor(used_charge + meta1:get_int("EU_charge") / eff_factor)
|
||||
end
|
||||
elseif meta1:get_string("has_supply") == pos.x..pos.y..pos.z then
|
||||
-- The appliance has power from this node. Spend power if it is on.
|
||||
used_charge = used_charge + math.floor(meta1:get_int("EU_charge") / eff_factor)
|
||||
end
|
||||
meta:set_string("infotext", "MV Power Radiator is powered ("
|
||||
..math.floor(used_charge / max_charge * 100)
|
||||
.."% of maximum power)");
|
||||
if used_charge == 0 then
|
||||
meta:set_int("MV_EU_demand", 1) -- Still idle
|
||||
else
|
||||
meta:set_int("MV_EU_demand", used_charge)
|
||||
end
|
||||
end
|
||||
-- Save state
|
||||
meta:set_int("connected_EU_demand", connected_EU_demand)
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
technic.register_machine("MV", "technic:power_radiator", technic.receiver)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:solar_array_mv 1',
|
||||
recipe = {
|
||||
{'technic:solar_array_lv', 'technic:solar_array_lv', 'technic:solar_array_lv'},
|
||||
{'technic:carbon_steel_ingot', 'technic:mv_transformer', 'technic:carbon_steel_ingot'},
|
||||
{'', 'technic:mv_cable', ''},
|
||||
}
|
||||
})
|
||||
|
||||
technic.register_solar_array({tier="MV", power=30})
|
||||
|
||||
-- compatibility alias for upgrading from old versions of technic
|
||||
minetest.register_alias("technic:solar_panel_mv", "technic:solar_array_mv")
|
||||
@@ -0,0 +1,126 @@
|
||||
-- Tool workshop
|
||||
-- This machine repairs tools.
|
||||
|
||||
minetest.register_alias("tool_workshop", "technic:tool_workshop")
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
local tube_entry = "^pipeworks_tube_connection_wooden.png"
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:tool_workshop',
|
||||
recipe = {
|
||||
{'group:wood', 'default:diamond', 'group:wood'},
|
||||
{'mesecons_pistons:piston_sticky_off', 'technic:machine_casing', 'technic:carbon_cloth'},
|
||||
{'default:obsidian', 'technic:mv_cable', 'default:obsidian'},
|
||||
}
|
||||
})
|
||||
|
||||
local workshop_demand = {5000, 3500, 2000}
|
||||
|
||||
local workshop_formspec =
|
||||
"size[8,9;]"..
|
||||
"list[context;src;3,1;1,1;]"..
|
||||
"label[0,0;"..S("%s Tool Workshop"):format("MV").."]"..
|
||||
"list[context;upgrade1;1,3;1,1;]"..
|
||||
"list[context;upgrade2;2,3;1,1;]"..
|
||||
"label[1,4;"..S("Upgrade Slots").."]"..
|
||||
"list[current_player;main;0,5;8,4;]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;upgrade1]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;upgrade2]"..
|
||||
"listring[current_player;main]"
|
||||
|
||||
local run = function(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local eu_input = meta:get_int("MV_EU_input")
|
||||
local machine_name = S("%s Tool Workshop"):format("MV")
|
||||
|
||||
-- Setup meta data if it does not exist.
|
||||
if not eu_input then
|
||||
meta:set_int("MV_EU_demand", workshop_demand[1])
|
||||
meta:set_int("MV_EU_input", 0)
|
||||
return
|
||||
end
|
||||
|
||||
local EU_upgrade, tube_upgrade = technic.handle_machine_upgrades(meta)
|
||||
|
||||
local repairable = false
|
||||
local srcstack = inv:get_stack("src", 1)
|
||||
if not srcstack:is_empty() then
|
||||
local itemdef = minetest.registered_items[srcstack:get_name()]
|
||||
if itemdef and
|
||||
(not itemdef.wear_represents or
|
||||
itemdef.wear_represents == "mechanical_wear") and
|
||||
srcstack:get_wear() ~= 0 then
|
||||
repairable = true
|
||||
end
|
||||
end
|
||||
technic.handle_machine_pipeworks(pos, tube_upgrade, function(pos2, x_velocity, z_velocity)
|
||||
if not repairable then
|
||||
technic.send_items(pos2, x_velocity, z_velocity, "src")
|
||||
end
|
||||
end)
|
||||
if not repairable then
|
||||
meta:set_string("infotext", S("%s Idle"):format(machine_name))
|
||||
meta:set_int("MV_EU_demand", 0)
|
||||
return
|
||||
end
|
||||
|
||||
if eu_input < workshop_demand[EU_upgrade+1] then
|
||||
meta:set_string("infotext", S("%s Unpowered"):format(machine_name))
|
||||
elseif eu_input >= workshop_demand[EU_upgrade+1] then
|
||||
meta:set_string("infotext", S("%s Active"):format(machine_name))
|
||||
srcstack:add_wear(-1000)
|
||||
inv:set_stack("src", 1, srcstack)
|
||||
end
|
||||
meta:set_int("MV_EU_demand", workshop_demand[EU_upgrade+1])
|
||||
end
|
||||
|
||||
minetest.register_node("technic:tool_workshop", {
|
||||
description = S("%s Tool Workshop"):format("MV"),
|
||||
paramtype2 = "facedir",
|
||||
tiles = {
|
||||
"technic_workshop_top.png"..tube_entry,
|
||||
"technic_machine_bottom.png"..tube_entry,
|
||||
"technic_workshop_side.png"..tube_entry,
|
||||
"technic_workshop_side.png"..tube_entry,
|
||||
"technic_workshop_side.png"..tube_entry,
|
||||
"technic_workshop_side.png"
|
||||
},
|
||||
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
|
||||
technic_machine=1, technic_mv=1, tubedevice=1, tubedevice_receiver=1},
|
||||
connect_sides = {"bottom", "back", "left", "right"},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", S("%s Tool Workshop"):format("MV"))
|
||||
meta:set_string("formspec", workshop_formspec)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("src", 1)
|
||||
inv:set_size("upgrade1", 1)
|
||||
inv:set_size("upgrade2", 1)
|
||||
end,
|
||||
can_dig = technic.machine_can_dig,
|
||||
allow_metadata_inventory_put = technic.machine_inventory_put,
|
||||
allow_metadata_inventory_take = technic.machine_inventory_take,
|
||||
tube = {
|
||||
can_insert = function (pos, node, stack, direction)
|
||||
return minetest.get_meta(pos):get_inventory():room_for_item("src", stack)
|
||||
end,
|
||||
insert_object = function (pos, node, stack, direction)
|
||||
return minetest.get_meta(pos):get_inventory():add_item("src", stack)
|
||||
end,
|
||||
connect_sides = {left = 1, right = 1, back = 1, top = 1, bottom = 1},
|
||||
},
|
||||
technic_run = run,
|
||||
after_place_node = pipeworks.after_place,
|
||||
after_dig_node = technic.machine_after_dig_node
|
||||
})
|
||||
|
||||
technic.register_machine("MV", "technic:tool_workshop", technic.receiver)
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:wind_mill_frame 5',
|
||||
recipe = {
|
||||
{'technic:carbon_steel_ingot', '', 'technic:carbon_steel_ingot'},
|
||||
{'', 'technic:carbon_steel_ingot', ''},
|
||||
{'technic:carbon_steel_ingot', '', 'technic:carbon_steel_ingot'},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:wind_mill',
|
||||
recipe = {
|
||||
{'', 'basic_materials:motor', ''},
|
||||
{'technic:carbon_steel_ingot', 'technic:carbon_steel_block', 'technic:carbon_steel_ingot'},
|
||||
{'', 'technic:mv_cable', ''},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_node("technic:wind_mill_frame", {
|
||||
description = S("Wind Mill Frame"),
|
||||
drawtype = "glasslike_framed",
|
||||
tiles = {"technic_carbon_steel_block.png", "default_glass.png"},
|
||||
sunlight_propagates = true,
|
||||
groups = {cracky=3},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
paramtype = "light",
|
||||
})
|
||||
|
||||
local function check_wind_mill(pos)
|
||||
if pos.y < 30 then
|
||||
return false
|
||||
end
|
||||
pos = {x=pos.x, y=pos.y, z=pos.z}
|
||||
for i = 1, 20 do
|
||||
pos.y = pos.y - 1
|
||||
local node = minetest.get_node_or_nil(pos)
|
||||
if not node then
|
||||
-- we reached CONTENT_IGNORE, we can assume, that nothing changed
|
||||
-- as the user will have to load the block to change it
|
||||
return
|
||||
end
|
||||
if node.name ~= "technic:wind_mill_frame" then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local run = function(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local machine_name = S("Wind %s Generator"):format("MV")
|
||||
|
||||
local check = check_wind_mill(pos)
|
||||
if check == false then
|
||||
meta:set_int("MV_EU_supply", 0)
|
||||
meta:set_string("infotext", S("%s Improperly Placed"):format(machine_name))
|
||||
elseif check == true then
|
||||
local power = math.min(pos.y * 100, 5000)
|
||||
meta:set_int("MV_EU_supply", power)
|
||||
meta:set_string("infotext", S("@1 (@2)", machine_name,
|
||||
technic.EU_string(power)))
|
||||
end
|
||||
-- check == nil: assume nothing has changed
|
||||
end
|
||||
|
||||
minetest.register_node("technic:wind_mill", {
|
||||
description = S("Wind %s Generator"):format("MV"),
|
||||
tiles = {"technic_carbon_steel_block.png"},
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=1, technic_machine=1, technic_mv=1},
|
||||
connect_sides = {"top", "bottom", "back", "left", "right"},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
drawtype = "nodebox",
|
||||
paramtype = "light",
|
||||
node_box = {
|
||||
type = "fixed",
|
||||
fixed = {
|
||||
{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}, -- Main box
|
||||
{-0.1, -0.1, -0.5, 0.1, 0.1, -0.6}, -- Shaft
|
||||
{-0.1, -1, -0.6, 0.1, 1, -0.7}, -- Vertical blades
|
||||
{-1, -0.1, -0.6, 1, 0.1, -0.7}, -- Horizontal blades
|
||||
}
|
||||
},
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", S("Wind %s Generator"):format("MV"))
|
||||
meta:set_int("MV_EU_supply", 0)
|
||||
end,
|
||||
technic_run = run,
|
||||
})
|
||||
|
||||
technic.register_machine("MV", "technic:wind_mill", technic.producer)
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
--
|
||||
-- Compatibility hacks for digtron to work well with technic plus new network system
|
||||
--
|
||||
-- More information:
|
||||
-- https://github.com/mt-mods/technic/issues/100
|
||||
--
|
||||
|
||||
local function power_connector_compat()
|
||||
local digtron_technic_run = minetest.registered_nodes["digtron:power_connector"].technic_run
|
||||
minetest.override_item("digtron:power_connector",{
|
||||
technic_run = function(pos, node)
|
||||
local network_id = technic.pos2network(pos)
|
||||
local sw_pos = network_id and technic.network2sw_pos(network_id)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("HV_network", sw_pos and minetest.pos_to_string(sw_pos) or "")
|
||||
return digtron_technic_run(pos, node)
|
||||
end,
|
||||
technic_on_disable = function(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("HV_network", "")
|
||||
meta:set_string("HV_EU_input", "")
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
minetest.register_on_mods_loaded(function()
|
||||
if minetest.registered_nodes["digtron:power_connector"] then
|
||||
power_connector_compat()
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,180 @@
|
||||
local path = technic.modpath.."/machines"
|
||||
|
||||
technic.digilines = {
|
||||
rules = {
|
||||
-- digilines.rules.default
|
||||
{x= 1,y= 0,z= 0},{x=-1,y= 0,z= 0}, -- along x beside
|
||||
{x= 0,y= 0,z= 1},{x= 0,y= 0,z=-1}, -- along z beside
|
||||
{x= 1,y= 1,z= 0},{x=-1,y= 1,z= 0}, -- 1 node above along x diagonal
|
||||
{x= 0,y= 1,z= 1},{x= 0,y= 1,z=-1}, -- 1 node above along z diagonal
|
||||
{x= 1,y=-1,z= 0},{x=-1,y=-1,z= 0}, -- 1 node below along x diagonal
|
||||
{x= 0,y=-1,z= 1},{x= 0,y=-1,z=-1}, -- 1 node below along z diagonal
|
||||
-- added rules for digi cable
|
||||
{x = 0, y = -1, z = 0}, -- along y below
|
||||
}
|
||||
}
|
||||
|
||||
-- https://github.com/mt-mods/technic/issues/100
|
||||
dofile(path.."/compat/digtron.lua")
|
||||
|
||||
dofile(path.."/network.lua")
|
||||
|
||||
dofile(path.."/register/init.lua")
|
||||
|
||||
-- Tiers
|
||||
dofile(path.."/LV/init.lua")
|
||||
dofile(path.."/MV/init.lua")
|
||||
dofile(path.."/HV/init.lua")
|
||||
|
||||
dofile(path.."/switching_station.lua")
|
||||
dofile(path.."/switching_station_globalstep.lua")
|
||||
|
||||
dofile(path.."/power_monitor.lua")
|
||||
dofile(path.."/supply_converter.lua")
|
||||
|
||||
dofile(path.."/other/init.lua")
|
||||
|
||||
--
|
||||
-- Technic power network administrative functions
|
||||
--
|
||||
|
||||
local active_networks = technic.active_networks
|
||||
local networks = technic.networks
|
||||
local cables = technic.cables
|
||||
--
|
||||
-- Enable / disable technic globalstep
|
||||
--
|
||||
technic.powerctrl_state = true
|
||||
minetest.register_chatcommand("powerctrl", {
|
||||
params = "[on|off]",
|
||||
description = "Enables or disables technic network globalstep handler",
|
||||
privs = { [technic.config:get("admin_priv")] = true },
|
||||
func = function(name, state)
|
||||
if state == "on" then
|
||||
technic.powerctrl_state = true
|
||||
elseif state == "off" then
|
||||
technic.powerctrl_state = false
|
||||
end
|
||||
minetest.chat_send_player(name, ("Technic network globalstep %s."):format(
|
||||
technic.powerctrl_state and "enabled" or "disabled"
|
||||
))
|
||||
end
|
||||
})
|
||||
|
||||
--
|
||||
-- List all active networks with additional data
|
||||
--
|
||||
minetest.register_chatcommand("technic_get_active_networks", {
|
||||
params = "[minlag]",
|
||||
description = "list all active networks with additional network data",
|
||||
privs = { [technic.config:get("admin_priv")] = true },
|
||||
func = function(name, minlag)
|
||||
minlag = tonumber(minlag) or 0
|
||||
local activecount = 0
|
||||
local network_info = {}
|
||||
local netcount = 0
|
||||
local nodecount = 0
|
||||
local function align(s, w)
|
||||
s = tostring(s)
|
||||
return string.rep(' ', w - #s) .. s
|
||||
end
|
||||
local function net2str(id)
|
||||
local p=technic.network2pos(id)
|
||||
return align(("%s,%s,%s"):format(p.x,p.y,p.z),21)
|
||||
end
|
||||
for id,net in pairs(active_networks) do
|
||||
if minlag == 0 or (net.lag and net.lag >= minlag * 1000) then
|
||||
activecount = activecount + 1
|
||||
table.insert(network_info, ("Pos:%s PR:%s RE:%s BA:%s Skip:%s Lag:%sms"):format(
|
||||
net2str(id), align(#net.PR_nodes, 4), align(#net.RE_nodes, 4), align(#net.BA_nodes, 4),
|
||||
align(net.skip, 3), net.lag and align(("%0.2f"):format(net.lag / 1000), 6) or ""
|
||||
))
|
||||
end
|
||||
end
|
||||
for _ in pairs(networks) do netcount = netcount + 1 end
|
||||
for _ in pairs(cables) do nodecount = nodecount + 1 end
|
||||
minetest.chat_send_player(name,
|
||||
("Cached networks: %d active, %d total, %d nodes, %0.2f max lag.\n%s"):format(
|
||||
activecount, netcount, nodecount, technic.get_max_lag(), table.concat(network_info, "\n")
|
||||
))
|
||||
end
|
||||
})
|
||||
|
||||
--
|
||||
-- Clear technic active networks
|
||||
--
|
||||
minetest.register_chatcommand("technic_flush_switch_cache", {
|
||||
description = "removes all active networks from the cache",
|
||||
privs = { [technic.config:get("admin_priv")] = true },
|
||||
func = function(name)
|
||||
local activecount = 0
|
||||
for id in pairs(active_networks) do
|
||||
activecount = activecount + 1
|
||||
active_networks[id] = nil
|
||||
end
|
||||
minetest.chat_send_player(name, ("Network data removed: %d active networks deactivated."):format(activecount))
|
||||
end
|
||||
})
|
||||
|
||||
--
|
||||
-- Completely clear all technic network caches
|
||||
--
|
||||
minetest.register_chatcommand("technic_clear_network_data", {
|
||||
description = "removes all networks and network nodes from the cache",
|
||||
privs = { [technic.config:get("admin_priv")] = true },
|
||||
func = function(name)
|
||||
-- Clear all network data keeping all reference links intact
|
||||
local activecount = 0
|
||||
local netcount = 0
|
||||
local nodecount = 0
|
||||
for id in pairs(active_networks) do
|
||||
activecount = activecount + 1
|
||||
active_networks[id] = nil
|
||||
end
|
||||
for id in pairs(networks) do
|
||||
netcount = netcount + 1
|
||||
networks[id] = nil
|
||||
end
|
||||
for id in pairs(cables) do
|
||||
nodecount = nodecount + 1
|
||||
cables[id] = nil
|
||||
end
|
||||
minetest.chat_send_player(name, string.format(
|
||||
"Network data removed: %d active networks, %d total networks, %d network nodes.",
|
||||
activecount, netcount, nodecount
|
||||
))
|
||||
end
|
||||
})
|
||||
|
||||
--
|
||||
-- Metadata cleanup LBM, removes old metadata values from nodes
|
||||
--
|
||||
--luacheck: ignore 511
|
||||
if false then
|
||||
minetest.register_lbm({
|
||||
name = "technic:metadata-cleanup",
|
||||
nodenames = {
|
||||
"group:technic_machine",
|
||||
"group:technic_all_tiers",
|
||||
"technic:switching_station",
|
||||
"technic:power_monitor",
|
||||
},
|
||||
action = function(pos, node)
|
||||
-- Delete all listed metadata key/value pairs from technic machines
|
||||
local keys = {
|
||||
"LV_EU_timeout", "MV_EU_timeout", "HV_EU_timeout",
|
||||
"LV_network", "MV_network", "HV_network",
|
||||
"active_pos", "supply", "demand",
|
||||
"battery_count", "battery_charge", "battery_charge_max",
|
||||
}
|
||||
local meta = minetest.get_meta(pos)
|
||||
for _,key in ipairs(keys) do
|
||||
-- Value of `""` will delete the key.
|
||||
meta:set_string(key, "")
|
||||
end
|
||||
if node.name == "technic:switching_station" then
|
||||
meta:set_string("active", "")
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
@@ -0,0 +1,586 @@
|
||||
--
|
||||
-- Power network specific functions and data should live here
|
||||
--
|
||||
local S = technic.getter
|
||||
|
||||
local switch_max_range = tonumber(technic.config:get("switch_max_range"))
|
||||
local off_delay_seconds = tonumber(technic.config:get("switch_off_delay_seconds"))
|
||||
|
||||
technic.active_networks = {}
|
||||
local networks = {}
|
||||
technic.networks = networks
|
||||
local cables = {}
|
||||
technic.cables = cables
|
||||
|
||||
local poshash = minetest.hash_node_position
|
||||
local hashpos = minetest.get_position_from_hash
|
||||
|
||||
function technic.create_network(sw_pos)
|
||||
local network_id = poshash({x=sw_pos.x,y=sw_pos.y-1,z=sw_pos.z})
|
||||
technic.build_network(network_id)
|
||||
return network_id
|
||||
end
|
||||
|
||||
function technic.activate_network(network_id, timeout)
|
||||
-- timeout is optional ttl for network in seconds, if not specified use default
|
||||
local network = networks[network_id]
|
||||
if network then
|
||||
-- timeout is absolute time in microseconds
|
||||
network.timeout = minetest.get_us_time() + ((timeout or off_delay_seconds) * 1000 * 1000)
|
||||
technic.active_networks[network_id] = network
|
||||
end
|
||||
end
|
||||
|
||||
function technic.sw_pos2tier(pos, use_vm)
|
||||
-- Get cable tier for switching station or nil if no cable
|
||||
-- use_vm true to use VoxelManip to load node
|
||||
local cable_pos = {x=pos.x,y=pos.y-1,z=pos.z}
|
||||
if use_vm then
|
||||
technic.get_or_load_node(cable_pos)
|
||||
end
|
||||
return technic.get_cable_tier(minetest.get_node(cable_pos).name)
|
||||
end
|
||||
|
||||
-- Destroy network data
|
||||
function technic.remove_network(network_id)
|
||||
for pos_hash,cable_net_id in pairs(cables) do
|
||||
if cable_net_id == network_id then
|
||||
cables[pos_hash] = nil
|
||||
end
|
||||
end
|
||||
networks[network_id] = nil
|
||||
technic.active_networks[network_id] = nil
|
||||
end
|
||||
|
||||
-- Remove machine or cable from network
|
||||
local network_node_arrays = {"PR_nodes","BA_nodes","RE_nodes"}
|
||||
function technic.remove_network_node(network_id, pos)
|
||||
local network = networks[network_id]
|
||||
if not network then return end
|
||||
-- Clear hash tables, cannot use table.remove
|
||||
local node_id = poshash(pos)
|
||||
cables[node_id] = nil
|
||||
network.all_nodes[node_id] = nil
|
||||
-- TODO: All following things can be skipped if node is not machine
|
||||
-- check here if it is or is not cable
|
||||
-- or add separate function to remove cables and move responsibility to caller
|
||||
-- Clear indexed arrays, do NOT leave holes
|
||||
local machine_removed = false
|
||||
for _,tblname in ipairs(network_node_arrays) do
|
||||
local tbl = network[tblname]
|
||||
for i=#tbl,1,-1 do
|
||||
local mpos = tbl[i]
|
||||
if mpos.x == pos.x and mpos.y == pos.y and mpos.z == pos.z then
|
||||
table.remove(tbl, i)
|
||||
machine_removed = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if machine_removed then
|
||||
-- Machine can still be in world, just not connected to any network. If so then disable it.
|
||||
local node = minetest.get_node(pos)
|
||||
technic.disable_machine(pos, node)
|
||||
end
|
||||
end
|
||||
|
||||
function technic.sw_pos2network(pos)
|
||||
return cables[poshash({x=pos.x,y=pos.y-1,z=pos.z})]
|
||||
end
|
||||
|
||||
function technic.sw_pos2network(pos)
|
||||
return cables[poshash({x=pos.x,y=pos.y-1,z=pos.z})]
|
||||
end
|
||||
|
||||
function technic.pos2network(pos)
|
||||
return cables[poshash(pos)]
|
||||
end
|
||||
|
||||
function technic.network2pos(network_id)
|
||||
return hashpos(network_id)
|
||||
end
|
||||
|
||||
function technic.network2sw_pos(network_id)
|
||||
-- Return switching station position for network.
|
||||
-- It is not guaranteed that position actually contains switching station.
|
||||
local sw_pos = hashpos(network_id)
|
||||
sw_pos.y = sw_pos.y + 1
|
||||
return sw_pos
|
||||
end
|
||||
|
||||
function technic.network_infotext(network_id, text)
|
||||
if networks[network_id] == nil then return end
|
||||
if text then
|
||||
networks[network_id].infotext = text
|
||||
else
|
||||
return networks[network_id].infotext
|
||||
end
|
||||
end
|
||||
|
||||
local node_timeout = {}
|
||||
local default_timeout = 2
|
||||
|
||||
function technic.set_default_timeout(timeout)
|
||||
default_timeout = timeout or 2
|
||||
end
|
||||
|
||||
function technic.get_timeout(tier, pos)
|
||||
if node_timeout[tier] == nil then
|
||||
-- it is normal that some multi tier nodes always drop here when checking all LV, MV and HV tiers
|
||||
return 0
|
||||
end
|
||||
return node_timeout[tier][poshash(pos)] or 0
|
||||
end
|
||||
|
||||
local function touch_node(tier, pos, timeout)
|
||||
if node_timeout[tier] == nil then
|
||||
-- this should get built up during registration
|
||||
node_timeout[tier] = {}
|
||||
end
|
||||
node_timeout[tier][poshash(pos)] = timeout or default_timeout
|
||||
end
|
||||
technic.touch_node = touch_node
|
||||
|
||||
function technic.disable_machine(pos, node)
|
||||
local nodedef = minetest.registered_nodes[node.name]
|
||||
if nodedef and nodedef.technic_disabled_machine_name then
|
||||
node.name = nodedef.technic_disabled_machine_name
|
||||
minetest.swap_node(pos, node)
|
||||
elseif nodedef and nodedef.technic_on_disable then
|
||||
nodedef.technic_on_disable(pos, node)
|
||||
end
|
||||
if nodedef then
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", S("%s Has No Network"):format(nodedef.description))
|
||||
end
|
||||
local node_id = poshash(pos)
|
||||
for _,nodes in pairs(node_timeout) do
|
||||
nodes[node_id] = nil
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Network overloading (incomplete cheat mitigation)
|
||||
--
|
||||
local overload_reset_time = tonumber(technic.config:get("network_overload_reset_time"))
|
||||
local overloaded_networks = {}
|
||||
|
||||
local function overload_network(network_id)
|
||||
local network = networks[network_id]
|
||||
if network then
|
||||
network.supply = 0
|
||||
network.battery_charge = 0
|
||||
end
|
||||
overloaded_networks[network_id] = minetest.get_us_time() + (overload_reset_time * 1000 * 1000)
|
||||
end
|
||||
technic.overload_network = overload_network
|
||||
|
||||
local function reset_overloaded(network_id)
|
||||
local remaining = math.max(0, overloaded_networks[network_id] - minetest.get_us_time())
|
||||
if remaining == 0 then
|
||||
-- Clear cache, remove overload and restart network
|
||||
technic.remove_network(network_id)
|
||||
overloaded_networks[network_id] = nil
|
||||
end
|
||||
-- Returns 0 when network reset or remaining time if reset timer has not expired yet
|
||||
return remaining
|
||||
end
|
||||
technic.reset_overloaded = reset_overloaded
|
||||
|
||||
local function is_overloaded(network_id)
|
||||
return overloaded_networks[network_id]
|
||||
end
|
||||
technic.is_overloaded = is_overloaded
|
||||
|
||||
--
|
||||
-- Functions to traverse the electrical network
|
||||
--
|
||||
|
||||
-- Add a machine node to the LV/MV/HV network
|
||||
local function add_network_machine(nodes, pos, network_id, all_nodes, multitier)
|
||||
local node_id = poshash(pos)
|
||||
local net_id_old = cables[node_id]
|
||||
if net_id_old == nil or (multitier and net_id_old ~= network_id and all_nodes[node_id] == nil) then
|
||||
-- Add machine to network only if it is not already added
|
||||
table.insert(nodes, pos)
|
||||
-- FIXME: Machines connecting to multiple networks should have way to store multiple network ids
|
||||
cables[node_id] = network_id
|
||||
all_nodes[node_id] = pos
|
||||
return true
|
||||
elseif not multitier and net_id_old ~= network_id then
|
||||
-- Do not allow running from multiple networks, trigger overload
|
||||
overload_network(network_id)
|
||||
overload_network(net_id_old)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext",S("Network Overloaded"))
|
||||
end
|
||||
end
|
||||
|
||||
-- Add a wire node to the LV/MV/HV network
|
||||
local function add_cable_node(nodes, pos, network_id, queue)
|
||||
local node_id = poshash(pos)
|
||||
if not cables[node_id] then
|
||||
cables[node_id] = network_id
|
||||
nodes[node_id] = pos
|
||||
table.insert(queue, pos)
|
||||
end
|
||||
end
|
||||
|
||||
-- Generic function to add found connected nodes to the right classification array
|
||||
local function add_network_node(PR_nodes, RE_nodes, BA_nodes, all_nodes, pos, machines, tier, network_id, queue)
|
||||
technic.get_or_load_node(pos)
|
||||
local name = minetest.get_node(pos).name
|
||||
|
||||
if technic.is_tier_cable(name, tier) then
|
||||
add_cable_node(all_nodes, pos, network_id, queue)
|
||||
elseif machines[name] then
|
||||
if machines[name] == technic.producer then
|
||||
add_network_machine(PR_nodes, pos, network_id, all_nodes)
|
||||
elseif machines[name] == technic.receiver then
|
||||
add_network_machine(RE_nodes, pos, network_id, all_nodes)
|
||||
elseif machines[name] == technic.producer_receiver then
|
||||
if add_network_machine(PR_nodes, pos, network_id, all_nodes, true) then
|
||||
table.insert(RE_nodes, pos)
|
||||
end
|
||||
elseif machines[name] == technic.battery then
|
||||
add_network_machine(BA_nodes, pos, network_id, all_nodes)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Generic function to add single nodes to the right classification array of existing network
|
||||
function technic.add_network_node(pos, network)
|
||||
add_network_node(
|
||||
network.PR_nodes,
|
||||
network.RE_nodes,
|
||||
network.BA_nodes,
|
||||
network.all_nodes,
|
||||
pos,
|
||||
technic.machines[network.tier],
|
||||
network.tier,
|
||||
network.id,
|
||||
{}
|
||||
)
|
||||
end
|
||||
|
||||
-- Traverse a network given a list of machines and a cable type name
|
||||
local function traverse_network(PR_nodes, RE_nodes, BA_nodes, all_nodes, pos, machines, tier, network_id, queue)
|
||||
local positions = {
|
||||
{x=pos.x+1, y=pos.y, z=pos.z},
|
||||
{x=pos.x-1, y=pos.y, z=pos.z},
|
||||
{x=pos.x, y=pos.y+1, z=pos.z},
|
||||
{x=pos.x, y=pos.y-1, z=pos.z},
|
||||
{x=pos.x, y=pos.y, z=pos.z+1},
|
||||
{x=pos.x, y=pos.y, z=pos.z-1}}
|
||||
for i, cur_pos in pairs(positions) do
|
||||
if not all_nodes[poshash(cur_pos)] then
|
||||
add_network_node(PR_nodes, RE_nodes, BA_nodes, all_nodes, cur_pos, machines, tier, network_id, queue)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function touch_nodes(list, tier)
|
||||
for _, pos in ipairs(list) do
|
||||
touch_node(tier, pos) -- Touch node
|
||||
end
|
||||
end
|
||||
|
||||
local function get_network(network_id, tier)
|
||||
local cached = networks[network_id]
|
||||
if cached and cached.tier == tier then
|
||||
touch_nodes(cached.PR_nodes, tier)
|
||||
touch_nodes(cached.BA_nodes, tier)
|
||||
touch_nodes(cached.RE_nodes, tier)
|
||||
return cached.PR_nodes, cached.BA_nodes, cached.RE_nodes
|
||||
end
|
||||
return technic.build_network(network_id)
|
||||
end
|
||||
|
||||
function technic.add_network_branch(queue, network)
|
||||
-- Adds whole branch to network, queue positions can be used to bypass sub branches
|
||||
local PR_nodes = network.PR_nodes -- Indexed array
|
||||
local BA_nodes = network.BA_nodes -- Indexed array
|
||||
local RE_nodes = network.RE_nodes -- Indexed array
|
||||
local all_nodes = network.all_nodes -- Hash table
|
||||
local network_id = network.id
|
||||
local tier = network.tier
|
||||
local machines = technic.machines[tier]
|
||||
local sw_pos = technic.network2sw_pos(network_id)
|
||||
--print(string.format("technic.add_network_branch(%s, %s, %.17g)",queue,minetest.pos_to_string(sw_pos),network.id))
|
||||
while next(queue) do
|
||||
local to_visit = {}
|
||||
for _, pos in ipairs(queue) do
|
||||
if vector.distance(pos, sw_pos) > switch_max_range then
|
||||
-- max range exceeded
|
||||
return
|
||||
end
|
||||
traverse_network(PR_nodes, RE_nodes, BA_nodes, all_nodes, pos,
|
||||
machines, tier, network_id, to_visit)
|
||||
end
|
||||
queue = to_visit
|
||||
end
|
||||
end
|
||||
|
||||
-- Battery charge status updates for network
|
||||
local function update_battery(self, charge, max_charge, supply, demand)
|
||||
self.battery_charge = self.battery_charge + charge
|
||||
self.battery_charge_max = self.battery_charge_max + max_charge
|
||||
self.battery_supply = self.battery_supply + supply
|
||||
self.battery_demand = self.battery_demand + demand
|
||||
if demand ~= 0 then
|
||||
self.BA_count_active = self.BA_count_active + 1
|
||||
self.BA_charge_active = self.BA_charge_active + charge
|
||||
end
|
||||
end
|
||||
|
||||
-- Moving average function generator
|
||||
local function sma(period)
|
||||
local values = {}
|
||||
local index = 1
|
||||
local sum = 0
|
||||
return function(n)
|
||||
-- Add new value and return average
|
||||
sum = sum - (values[index] or 0) + n
|
||||
values[index] = n
|
||||
index = index ~= period and index + 1 or 1
|
||||
return sum / #values
|
||||
end
|
||||
end
|
||||
|
||||
function technic.build_network(network_id)
|
||||
technic.remove_network(network_id)
|
||||
local sw_pos = technic.network2sw_pos(network_id)
|
||||
local tier = technic.sw_pos2tier(sw_pos)
|
||||
if not tier then
|
||||
return
|
||||
end
|
||||
local network = {
|
||||
-- Basic network data and lookup table for attached nodes (no switching stations)
|
||||
id = network_id, tier = tier, all_nodes = {},
|
||||
-- Indexed arrays for iteration by machine type
|
||||
PR_nodes = {}, RE_nodes = {}, BA_nodes = {},
|
||||
-- Power generation, usage and capacity related variables
|
||||
supply = 0, demand = 0, battery_charge = 0, battery_charge_max = 0,
|
||||
BA_count_active = 0, BA_charge_active = 0, battery_supply = 0, battery_demand = 0,
|
||||
-- Battery status update function
|
||||
update_battery = update_battery,
|
||||
-- Network activation and excution control
|
||||
timeout = 0, skip = 0, lag = 0, average_lag = sma(5)
|
||||
}
|
||||
-- Add first cable (one that is holding network id) and build network
|
||||
local queue = {}
|
||||
add_cable_node(network.all_nodes, technic.network2pos(network_id), network_id, queue)
|
||||
technic.add_network_branch(queue, network)
|
||||
network.battery_count = #network.BA_nodes
|
||||
-- Add newly built network to cache array
|
||||
networks[network_id] = network
|
||||
-- And return producers, batteries and receivers (should this simply return network?)
|
||||
return network.PR_nodes, network.BA_nodes, network.RE_nodes
|
||||
end
|
||||
|
||||
--
|
||||
-- Execute technic power network
|
||||
--
|
||||
local node_technic_run = {}
|
||||
minetest.register_on_mods_loaded(function()
|
||||
for name, _ in pairs(technic.machine_tiers) do
|
||||
if type(minetest.registered_nodes[name].technic_run) == "function" then
|
||||
node_technic_run[name] = minetest.registered_nodes[name].technic_run
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
local function run_nodes(list, vm, run_stage, network)
|
||||
for _, pos in ipairs(list) do
|
||||
local node = minetest.get_node_or_nil(pos)
|
||||
if not node then
|
||||
vm:read_from_map(pos, pos)
|
||||
node = minetest.get_node_or_nil(pos)
|
||||
end
|
||||
if node and node.name and node_technic_run[node.name] then
|
||||
node_technic_run[node.name](pos, node, run_stage, network)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local mesecons_path = minetest.get_modpath("mesecons")
|
||||
local digilines_path = minetest.get_modpath("digilines")
|
||||
|
||||
function technic.network_run(network_id)
|
||||
--
|
||||
-- !!! !!! !!! !!! !!! !!! !!! !!! !!! !!! !!!
|
||||
-- TODO: This function requires a lot of cleanup
|
||||
-- It is moved here from switching_station.lua and still
|
||||
-- contain a lot of switching station specific stuff which
|
||||
-- should be removed and/or refactored.
|
||||
--
|
||||
|
||||
local pos = technic.network2sw_pos(network_id)
|
||||
local t0 = minetest.get_us_time()
|
||||
|
||||
local PR_nodes
|
||||
local BA_nodes
|
||||
local RE_nodes
|
||||
|
||||
local tier = technic.sw_pos2tier(pos)
|
||||
local network
|
||||
if tier then
|
||||
PR_nodes, BA_nodes, RE_nodes = get_network(network_id, tier)
|
||||
if technic.is_overloaded(network_id) then return end
|
||||
network = networks[network_id]
|
||||
else
|
||||
--dprint("Not connected to a network")
|
||||
technic.network_infotext(network_id, S("%s Has No Network"):format(S("Switching Station")))
|
||||
return
|
||||
end
|
||||
|
||||
-- Reset battery data for updates
|
||||
network.battery_charge = 0
|
||||
network.battery_charge_max = 0
|
||||
network.battery_supply = 0
|
||||
network.battery_demand = 0
|
||||
network.BA_count_active = 0
|
||||
network.BA_charge_active = 0
|
||||
|
||||
local vm = VoxelManip()
|
||||
run_nodes(PR_nodes, vm, technic.producer)
|
||||
run_nodes(RE_nodes, vm, technic.receiver)
|
||||
run_nodes(BA_nodes, vm, technic.battery, network)
|
||||
|
||||
-- Strings for the meta data
|
||||
local eu_demand_str = tier.."_EU_demand"
|
||||
local eu_input_str = tier.."_EU_input"
|
||||
local eu_supply_str = tier.."_EU_supply"
|
||||
|
||||
-- Distribute charge equally across multiple batteries.
|
||||
local charge_distributed = math.floor(network.BA_charge_active / network.BA_count_active)
|
||||
for n, pos1 in pairs(BA_nodes) do
|
||||
local meta1 = minetest.get_meta(pos1)
|
||||
if (meta1:get_int(eu_demand_str) ~= 0) then
|
||||
meta1:set_int("internal_EU_charge", charge_distributed)
|
||||
end
|
||||
end
|
||||
|
||||
-- Get all the power from the PR nodes
|
||||
local PR_eu_supply = 0 -- Total power
|
||||
for _, pos1 in pairs(PR_nodes) do
|
||||
local meta1 = minetest.get_meta(pos1)
|
||||
PR_eu_supply = PR_eu_supply + meta1:get_int(eu_supply_str)
|
||||
end
|
||||
--dprint("Total PR supply:"..PR_eu_supply)
|
||||
|
||||
-- Get all the demand from the RE nodes
|
||||
local RE_eu_demand = 0
|
||||
for _, pos1 in pairs(RE_nodes) do
|
||||
local meta1 = minetest.get_meta(pos1)
|
||||
RE_eu_demand = RE_eu_demand + meta1:get_int(eu_demand_str)
|
||||
end
|
||||
--dprint("Total RE demand:"..RE_eu_demand)
|
||||
|
||||
technic.network_infotext(network_id, S("@1. Supply: @2 Demand: @3",
|
||||
S("Switching Station"), technic.EU_string(PR_eu_supply),
|
||||
technic.EU_string(RE_eu_demand)))
|
||||
|
||||
-- If mesecon signal and power supply or demand changed then
|
||||
-- send them via digilines.
|
||||
if mesecons_path and digilines_path and mesecon.is_powered(pos) then
|
||||
if PR_eu_supply ~= network.supply or
|
||||
RE_eu_demand ~= network.demand then
|
||||
local meta = minetest.get_meta(pos)
|
||||
local channel = meta:get_string("channel")
|
||||
digilines.receptor_send(pos, technic.digilines.rules, channel, {
|
||||
supply = PR_eu_supply,
|
||||
demand = RE_eu_demand
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- Data that will be used by the power monitor
|
||||
network.supply = PR_eu_supply
|
||||
network.demand = RE_eu_demand
|
||||
network.battery_count = #BA_nodes
|
||||
|
||||
-- If the PR supply is enough for the RE demand supply them all
|
||||
local BA_eu_demand = network.battery_demand
|
||||
if PR_eu_supply >= RE_eu_demand then
|
||||
--dprint("PR_eu_supply"..PR_eu_supply.." >= RE_eu_demand"..RE_eu_demand)
|
||||
for _, pos1 in pairs(RE_nodes) do
|
||||
local meta1 = minetest.get_meta(pos1)
|
||||
local eu_demand = meta1:get_int(eu_demand_str)
|
||||
meta1:set_int(eu_input_str, eu_demand)
|
||||
end
|
||||
-- We have a surplus, so distribute the rest equally to the BA nodes
|
||||
-- Let's calculate the factor of the demand
|
||||
PR_eu_supply = PR_eu_supply - RE_eu_demand
|
||||
local charge_factor = 0 -- Assume all batteries fully charged
|
||||
if BA_eu_demand > 0 then
|
||||
charge_factor = PR_eu_supply / BA_eu_demand
|
||||
end
|
||||
-- TODO: EU input for all batteries: math.floor(BA_eu_demand * charge_factor * #BA_nodes)
|
||||
for n, pos1 in pairs(BA_nodes) do
|
||||
local meta1 = minetest.get_meta(pos1)
|
||||
local eu_demand = meta1:get_int(eu_demand_str)
|
||||
meta1:set_int(eu_input_str, math.floor(eu_demand * charge_factor))
|
||||
--dprint("Charging battery:"..math.floor(eu_demand*charge_factor))
|
||||
end
|
||||
local t1 = minetest.get_us_time()
|
||||
local diff = t1 - t0
|
||||
if diff > 50000 then
|
||||
minetest.log("warning", "[technic] [+supply] technic_run took " .. diff .. " us at " .. minetest.pos_to_string(pos))
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- If the PR supply is not enough for the RE demand we will discharge the batteries too
|
||||
local BA_eu_supply = network.battery_supply
|
||||
if PR_eu_supply + BA_eu_supply >= RE_eu_demand then
|
||||
--dprint("PR_eu_supply "..PR_eu_supply.."+BA_eu_supply "..BA_eu_supply.." >= RE_eu_demand"..RE_eu_demand)
|
||||
for _, pos1 in pairs(RE_nodes) do
|
||||
local meta1 = minetest.get_meta(pos1)
|
||||
local eu_demand = meta1:get_int(eu_demand_str)
|
||||
meta1:set_int(eu_input_str, eu_demand)
|
||||
end
|
||||
-- We have a deficit, so distribute to the BA nodes
|
||||
-- Let's calculate the factor of the supply
|
||||
local charge_factor = 0 -- Assume all batteries depleted
|
||||
if BA_eu_supply > 0 then
|
||||
charge_factor = (PR_eu_supply - RE_eu_demand) / BA_eu_supply
|
||||
end
|
||||
for n,pos1 in pairs(BA_nodes) do
|
||||
local meta1 = minetest.get_meta(pos1)
|
||||
local eu_supply = meta1:get_int(eu_supply_str)
|
||||
meta1:set_int(eu_input_str, math.floor(eu_supply * charge_factor))
|
||||
--dprint("Discharging battery:"..math.floor(eu_supply*charge_factor))
|
||||
end
|
||||
local t1 = minetest.get_us_time()
|
||||
local diff = t1 - t0
|
||||
if diff > 50000 then
|
||||
minetest.log("warning", "[technic] [-supply] technic_run took " .. diff .. " us at " .. minetest.pos_to_string(pos))
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- If the PR+BA supply is not enough for the RE demand: Power only the batteries
|
||||
local charge_factor = 0 -- Assume all batteries fully charged
|
||||
if BA_eu_demand > 0 then
|
||||
charge_factor = PR_eu_supply / BA_eu_demand
|
||||
end
|
||||
for n, pos1 in pairs(BA_nodes) do
|
||||
local meta1 = minetest.get_meta(pos1)
|
||||
local eu_demand = meta1:get_int(eu_demand_str)
|
||||
meta1:set_int(eu_input_str, math.floor(eu_demand * charge_factor))
|
||||
end
|
||||
for n, pos1 in pairs(RE_nodes) do
|
||||
local meta1 = minetest.get_meta(pos1)
|
||||
meta1:set_int(eu_input_str, 0)
|
||||
end
|
||||
|
||||
local t1 = minetest.get_us_time()
|
||||
local diff = t1 - t0
|
||||
if diff > 50000 then
|
||||
minetest.log("warning", "[technic] technic_run took " .. diff .. " us at " .. minetest.pos_to_string(pos))
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,129 @@
|
||||
local S = technic.getter
|
||||
|
||||
local desc = S("Administrative World Anchor")
|
||||
|
||||
local function compute_forceload_positions(pos, meta)
|
||||
local radius = meta:get_int("radius")
|
||||
local minpos = vector.subtract(pos, vector.new(radius, radius, radius))
|
||||
local maxpos = vector.add(pos, vector.new(radius, radius, radius))
|
||||
local minbpos = {}
|
||||
local maxbpos = {}
|
||||
for _, coord in ipairs({"x","y","z"}) do
|
||||
minbpos[coord] = math.floor(minpos[coord] / 16) * 16
|
||||
maxbpos[coord] = math.floor(maxpos[coord] / 16) * 16
|
||||
end
|
||||
local flposes = {}
|
||||
for x = minbpos.x, maxbpos.x, 16 do
|
||||
for y = minbpos.y, maxbpos.y, 16 do
|
||||
for z = minbpos.z, maxbpos.z, 16 do
|
||||
table.insert(flposes, vector.new(x, y, z))
|
||||
end
|
||||
end
|
||||
end
|
||||
return flposes
|
||||
end
|
||||
|
||||
local function currently_forceloaded_positions(meta)
|
||||
local ser = meta:get_string("forceloaded")
|
||||
return ser == "" and {} or minetest.deserialize(ser)
|
||||
end
|
||||
|
||||
local function forceload_off(meta)
|
||||
local flposes = currently_forceloaded_positions(meta)
|
||||
meta:set_string("forceloaded", "")
|
||||
for _, p in ipairs(flposes) do
|
||||
minetest.forceload_free_block(p)
|
||||
end
|
||||
end
|
||||
|
||||
local function forceload_on(pos, meta)
|
||||
local want_flposes = compute_forceload_positions(pos, meta)
|
||||
local have_flposes = {}
|
||||
for _, p in ipairs(want_flposes) do
|
||||
if minetest.forceload_block(p) then
|
||||
table.insert(have_flposes, p)
|
||||
end
|
||||
end
|
||||
meta:set_string("forceloaded", #have_flposes == 0 and "" or minetest.serialize(have_flposes))
|
||||
end
|
||||
|
||||
local function set_display(pos, meta)
|
||||
meta:set_string("infotext", S(meta:get_int("enabled") ~= 0 and "%s Enabled" or "%s Disabled"):format(desc))
|
||||
meta:set_string("formspec",
|
||||
"size[5,3.5]"..
|
||||
"item_image[0,0;1,1;technic:admin_anchor]"..
|
||||
"label[1,0;"..minetest.formspec_escape(desc).."]"..
|
||||
"label[0,1;"..minetest.formspec_escape(S("Owner:").." "..meta:get_string("owner")).."]"..
|
||||
(meta:get_int("locked") == 0 and
|
||||
"button[3,1;2,1;lock;"..minetest.formspec_escape(S("Unlocked")).."]" or
|
||||
"button[3,1;2,1;unlock;"..minetest.formspec_escape(S("Locked")).."]")..
|
||||
"field[0.25,2.3;1,1;radius;"..minetest.formspec_escape(S("Radius:"))..";"..meta:get_int("radius").."]"..
|
||||
(meta:get_int("enabled") == 0 and
|
||||
"button[3,2;2,1;enable;"..minetest.formspec_escape(S("Disabled")).."]" or
|
||||
"button[3,2;2,1;disable;"..minetest.formspec_escape(S("Enabled")).."]")..
|
||||
"label[0,3;"..minetest.formspec_escape(S("Keeping %d/%d map blocks loaded"):format(
|
||||
#currently_forceloaded_positions(meta), #compute_forceload_positions(pos, meta))).."]")
|
||||
end
|
||||
|
||||
minetest.register_node("technic:admin_anchor", {
|
||||
description = desc,
|
||||
drawtype = "normal",
|
||||
tiles = {"technic_admin_anchor.png"},
|
||||
is_ground_content = true,
|
||||
groups = {cracky=3, not_in_creative_inventory=1},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
after_place_node = function (pos, placer)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if placer and placer:is_player() then
|
||||
meta:set_string("owner", placer:get_player_name())
|
||||
end
|
||||
set_display(pos, meta)
|
||||
end,
|
||||
can_dig = function (pos, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
return meta:get_int("locked") == 0 or (player and player:is_player()
|
||||
and player:get_player_name() == meta:get_string("owner"))
|
||||
end,
|
||||
on_destruct = function (pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
forceload_off(meta)
|
||||
end,
|
||||
on_receive_fields = function (pos, formname, fields, sender)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if (meta:get_int("locked") ~= 0 or fields.lock) and
|
||||
not (sender and sender:is_player() and
|
||||
sender:get_player_name() == meta:get_string("owner")) then
|
||||
return
|
||||
end
|
||||
if fields.unlock then meta:set_int("locked", 0) end
|
||||
if fields.lock then meta:set_int("locked", 1) end
|
||||
if fields.disable or fields.enable or fields.radius then
|
||||
forceload_off(meta)
|
||||
if fields.disable then meta:set_int("enabled", 0) end
|
||||
if fields.enable then meta:set_int("enabled", 1) end
|
||||
if fields.radius and string.find(fields.radius, "^[0-9]+$") and tonumber(fields.radius) < 256 then
|
||||
meta:set_int("radius", fields.radius)
|
||||
end
|
||||
if meta:get_int("enabled") ~= 0 then
|
||||
forceload_on(pos, meta)
|
||||
end
|
||||
end
|
||||
set_display(pos, meta)
|
||||
end,
|
||||
mesecons = {
|
||||
effector = {
|
||||
action_on = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_int("enabled", 1)
|
||||
forceload_on(pos, meta)
|
||||
set_display(pos, meta)
|
||||
end,
|
||||
action_off = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_int("enabled", 0)
|
||||
forceload_off(meta)
|
||||
set_display(pos, meta)
|
||||
end
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,176 @@
|
||||
|
||||
-- Fuel driven alloy furnace. This uses no EUs:
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'technic:coal_alloy_furnace',
|
||||
recipe = {
|
||||
{'default:brick', 'default:brick', 'default:brick'},
|
||||
{'default:brick', '', 'default:brick'},
|
||||
{'default:brick', 'default:brick', 'default:brick'},
|
||||
}
|
||||
})
|
||||
|
||||
local machine_name = S("Fuel-Fired Alloy Furnace")
|
||||
local formspec =
|
||||
"size[8,9]"..
|
||||
"label[0,0;"..machine_name.."]"..
|
||||
"image[2,2;1,1;default_furnace_fire_bg.png]"..
|
||||
"list[context;fuel;2,3;1,1;]"..
|
||||
"list[context;src;2,1;2,1;]"..
|
||||
"list[context;dst;5,1;2,2;]"..
|
||||
"list[current_player;main;0,5;8,4;]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;fuel]"..
|
||||
"listring[current_player;main]"
|
||||
|
||||
minetest.register_node("technic:coal_alloy_furnace", {
|
||||
description = machine_name,
|
||||
tiles = {"technic_coal_alloy_furnace_top.png", "technic_coal_alloy_furnace_bottom.png",
|
||||
"technic_coal_alloy_furnace_side.png", "technic_coal_alloy_furnace_side.png",
|
||||
"technic_coal_alloy_furnace_side.png", "technic_coal_alloy_furnace_front.png"},
|
||||
paramtype2 = "facedir",
|
||||
groups = {cracky=2},
|
||||
legacy_facedir_simple = true,
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("formspec", formspec)
|
||||
meta:set_string("infotext", machine_name)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("fuel", 1)
|
||||
inv:set_size("src", 2)
|
||||
inv:set_size("dst", 4)
|
||||
end,
|
||||
can_dig = technic.machine_can_dig,
|
||||
allow_metadata_inventory_put = technic.machine_inventory_put,
|
||||
allow_metadata_inventory_take = technic.machine_inventory_take,
|
||||
allow_metadata_inventory_move = technic.machine_inventory_move,
|
||||
})
|
||||
|
||||
minetest.register_node("technic:coal_alloy_furnace_active", {
|
||||
description = machine_name,
|
||||
tiles = {"technic_coal_alloy_furnace_top.png", "technic_coal_alloy_furnace_bottom.png",
|
||||
"technic_coal_alloy_furnace_side.png", "technic_coal_alloy_furnace_side.png",
|
||||
"technic_coal_alloy_furnace_side.png", "technic_coal_alloy_furnace_front_active.png"},
|
||||
paramtype2 = "facedir",
|
||||
light_source = 8,
|
||||
drop = "technic:coal_alloy_furnace",
|
||||
groups = {cracky=2, not_in_creative_inventory=1},
|
||||
legacy_facedir_simple = true,
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
can_dig = technic.machine_can_dig,
|
||||
allow_metadata_inventory_put = technic.machine_inventory_put,
|
||||
allow_metadata_inventory_take = technic.machine_inventory_take,
|
||||
allow_metadata_inventory_move = technic.machine_inventory_move,
|
||||
})
|
||||
|
||||
minetest.register_abm({
|
||||
label = "Machines: run coal alloy furnace",
|
||||
nodenames = {"technic:coal_alloy_furnace", "technic:coal_alloy_furnace_active"},
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
|
||||
if inv:get_size("src") == 1 then -- Old furnace -> convert it
|
||||
inv:set_size("src", 2)
|
||||
inv:set_stack("src", 2, inv:get_stack("src2", 1))
|
||||
inv:set_size("src2", 0)
|
||||
end
|
||||
|
||||
for i, name in pairs({
|
||||
"fuel_totaltime",
|
||||
"fuel_time",
|
||||
"src_totaltime",
|
||||
"src_time"}) do
|
||||
if not meta:get_float(name) then
|
||||
meta:set_float(name, 0.0)
|
||||
end
|
||||
end
|
||||
|
||||
-- Get what to cook if anything
|
||||
local result = technic.get_recipe("alloy", inv:get_list("src"))
|
||||
|
||||
local was_active = false
|
||||
|
||||
if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then
|
||||
was_active = true
|
||||
meta:set_int("fuel_time", meta:get_int("fuel_time") + 1)
|
||||
if result then
|
||||
meta:set_int("src_time", meta:get_int("src_time") + 1)
|
||||
if meta:get_int("src_time") >= result.time then
|
||||
meta:set_int("src_time", 0)
|
||||
local result_stack = ItemStack(result.output)
|
||||
if inv:room_for_item("dst", result_stack) then
|
||||
inv:set_list("src", result.new_input)
|
||||
inv:add_item("dst", result_stack)
|
||||
end
|
||||
end
|
||||
else
|
||||
meta:set_int("src_time", 0)
|
||||
end
|
||||
end
|
||||
|
||||
if meta:get_float("fuel_time") < meta:get_float("fuel_totaltime") then
|
||||
local percent = math.floor(meta:get_float("fuel_time") /
|
||||
meta:get_float("fuel_totaltime") * 100)
|
||||
meta:set_string("infotext", S("%s Active"):format(machine_name).." ("..percent.."%)")
|
||||
technic.swap_node(pos, "technic:coal_alloy_furnace_active")
|
||||
meta:set_string("formspec",
|
||||
"size[8,9]"..
|
||||
"label[0,0;"..machine_name.."]"..
|
||||
"image[2,2;1,1;default_furnace_fire_bg.png^[lowpart:"..
|
||||
(100 - percent)..":default_furnace_fire_fg.png]"..
|
||||
"list[context;fuel;2,3;1,1;]"..
|
||||
"list[context;src;2,1;2,1;]"..
|
||||
"list[context;dst;5,1;2,2;]"..
|
||||
"list[current_player;main;0,5;8,4;]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;fuel]"..
|
||||
"listring[current_player;main]")
|
||||
return
|
||||
end
|
||||
|
||||
local recipe = technic.get_recipe("alloy", inv:get_list("src"))
|
||||
|
||||
if not recipe then
|
||||
if was_active then
|
||||
meta:set_string("infotext", S("%s is empty"):format(machine_name))
|
||||
technic.swap_node(pos, "technic:coal_alloy_furnace")
|
||||
meta:set_string("formspec", formspec)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- Next take a hard look at the fuel situation
|
||||
local fuel = nil
|
||||
local afterfuel
|
||||
local fuellist = inv:get_list("fuel")
|
||||
|
||||
if fuellist then
|
||||
fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
|
||||
end
|
||||
|
||||
if fuel.time <= 0 then
|
||||
meta:set_string("infotext", S("%s Out Of Fuel"):format(machine_name))
|
||||
technic.swap_node(pos, "technic:coal_alloy_furnace")
|
||||
meta:set_string("formspec", formspec)
|
||||
return
|
||||
end
|
||||
|
||||
meta:set_string("fuel_totaltime", fuel.time)
|
||||
meta:set_string("fuel_time", 0)
|
||||
|
||||
inv:set_stack("fuel", 1, afterfuel.items[1])
|
||||
end,
|
||||
})
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
local S = technic.getter
|
||||
|
||||
if minetest.registered_nodes["default:furnace"].description == "Furnace" then
|
||||
minetest.override_item("default:furnace", { description = S("Fuel-Fired Furnace") })
|
||||
end
|
||||
@@ -0,0 +1,210 @@
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
local function deploy_node(inv, slot_name, pos, node, machine_node)
|
||||
if node.param2 > 3 then return end
|
||||
if node.name ~= "air" then
|
||||
if node.name == "ignore" or
|
||||
node.name == "default:chest_open" or
|
||||
node.name == "default:chest_locked_open" or
|
||||
node.name == "default:lava_source" or
|
||||
node.name == "default:lava_flowing" or
|
||||
node.name == "default:water_source" or
|
||||
node.name == "default:water_flowing" then
|
||||
return
|
||||
end
|
||||
local drops = minetest.get_node_drops(node.name, "")
|
||||
local remove_to = false
|
||||
for i, item in ipairs(drops) do
|
||||
if not inv:room_for_item(slot_name, item) then
|
||||
remove_to = i - 1
|
||||
break
|
||||
end
|
||||
inv:add_item(slot_name, item)
|
||||
end
|
||||
if remove_to then
|
||||
for i = 1, remove_to do
|
||||
inv:remove_item(slot_name, drops[i])
|
||||
end
|
||||
else
|
||||
minetest.remove_node(pos)
|
||||
end
|
||||
return
|
||||
end
|
||||
if not inv:is_empty(slot_name) then
|
||||
local stack = inv:get_list(slot_name)[1]
|
||||
local def = stack:get_definition()
|
||||
if def.type == "node" then
|
||||
minetest.set_node(pos, {
|
||||
name = stack:get_name(),
|
||||
param2 = machine_node.param2
|
||||
})
|
||||
stack:take_item()
|
||||
inv:set_stack(slot_name, 1, stack)
|
||||
elseif def.type == "craft" then
|
||||
if def.on_place then
|
||||
-- Use pcall to avoid nil placer errors.
|
||||
-- TODO: Do without pcall.
|
||||
local ok, stk = pcall(def.on_place, stack, nil, {
|
||||
-- Fake pointed_thing
|
||||
type = "node",
|
||||
above = pos,
|
||||
under = {x=pos.x, y=pos.y-1, z=pos.z},
|
||||
})
|
||||
if ok then
|
||||
inv:set_stack(slot_name, 1, stk or stack)
|
||||
return
|
||||
end
|
||||
end
|
||||
minetest.item_place_object(stack, nil, {
|
||||
-- Fake pointed_thing
|
||||
type = "node",
|
||||
above = pos,
|
||||
under = pos,
|
||||
})
|
||||
inv:set_stack(slot_name, 1, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = 'technic:constructor_mk1_off 1',
|
||||
recipe = {'technic:nodebreaker_off', 'technic:deployer_off'},
|
||||
|
||||
})
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = 'technic:constructor_mk2_off 1',
|
||||
recipe = {'technic:constructor_mk1_off', 'technic:constructor_mk1_off'},
|
||||
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = 'technic:constructor_mk3_off 1',
|
||||
recipe = {'technic:constructor_mk2_off', 'technic:constructor_mk2_off'},
|
||||
|
||||
})
|
||||
|
||||
local function make_on(mark, length)
|
||||
return function(pos, node)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local owner = meta:get_string("owner")
|
||||
local inv = meta:get_inventory()
|
||||
local dir = vector.new()
|
||||
if node.param2 == 3 then dir.x = 1 end
|
||||
if node.param2 == 2 then dir.z = 1 end
|
||||
if node.param2 == 1 then dir.x = -1 end
|
||||
if node.param2 == 0 then dir.z = -1 end
|
||||
|
||||
local place_pos = vector.new(pos)
|
||||
|
||||
if node.name == "technic:constructor_mk"..mark.."_off" then
|
||||
technic.swap_node(pos, "technic:constructor_mk"..mark.."_on")
|
||||
minetest.check_for_falling(pos)
|
||||
for i = 1, length do
|
||||
place_pos = vector.add(place_pos, dir)
|
||||
if owner ~= "" and minetest.is_protected(place_pos, owner) then
|
||||
return
|
||||
end
|
||||
local place_node = minetest.get_node(place_pos)
|
||||
deploy_node(inv, "slot"..i, place_pos, place_node, node)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function make_off(mark)
|
||||
return function(pos, node)
|
||||
if node.name == "technic:constructor_mk"..mark.."_on" then
|
||||
technic.swap_node(pos,"technic:constructor_mk"..mark.."_off")
|
||||
minetest.check_for_falling(pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function allow_inventory_put(pos, listname, index, stack, player)
|
||||
if stack and minetest.get_item_group(stack:get_name(), "technic_constructor") == 1 then
|
||||
return 0
|
||||
end
|
||||
return technic.machine_inventory_put(pos, listname, index, stack, player)
|
||||
end
|
||||
|
||||
local function make_constructor(mark, length)
|
||||
minetest.register_node("technic:constructor_mk"..mark.."_off", {
|
||||
description = S("Constructor Mk%d"):format(mark),
|
||||
tiles = {"technic_constructor_mk"..mark.."_top_off.png",
|
||||
"technic_constructor_mk"..mark.."_bottom_off.png",
|
||||
"technic_constructor_mk"..mark.."_side2_off.png",
|
||||
"technic_constructor_mk"..mark.."_side1_off.png",
|
||||
"technic_constructor_back.png",
|
||||
"technic_constructor_front_off.png"},
|
||||
paramtype2 = "facedir",
|
||||
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
|
||||
mesecon = 2, technic_constructor = 1},
|
||||
mesecons = {effector = {action_on = make_on(mark, length)}},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local formspec = "size[8,9;]"..
|
||||
"label[0,0;"..S("Constructor Mk%d"):format(mark).."]"..
|
||||
"list[current_player;main;0,5;8,4;]"..
|
||||
"listring[current_player;main]"
|
||||
for i = 1, length do
|
||||
formspec = formspec..
|
||||
"label[5,"..(i - 1)..";"..S("Slot %d"):format(i).."]"..
|
||||
"list[context;slot"..i..";6,"..(i - 1)..";1,1;]"..
|
||||
"listring[context;slot"..i.."]"
|
||||
end
|
||||
meta:set_string("formspec", formspec)
|
||||
meta:set_string("infotext", S("Constructor Mk%d"):format(mark))
|
||||
local inv = meta:get_inventory()
|
||||
for i = 1, length do
|
||||
inv:set_size("slot"..i, 1)
|
||||
end
|
||||
meta:set_string("owner", "?")
|
||||
end,
|
||||
after_place_node = function(pos, placer)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("owner", (placer and placer:get_player_name() or "?"))
|
||||
end,
|
||||
can_dig = function(pos, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
for i = 1, length do
|
||||
if not inv:is_empty("slot"..i) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end,
|
||||
allow_metadata_inventory_put = allow_inventory_put,
|
||||
allow_metadata_inventory_take = technic.machine_inventory_take,
|
||||
allow_metadata_inventory_move = technic.machine_inventory_move,
|
||||
on_rotate = screwdriver.rotate_simple
|
||||
})
|
||||
|
||||
minetest.register_node("technic:constructor_mk"..mark.."_on", {
|
||||
tiles = {"technic_constructor_mk"..mark.."_top_on.png",
|
||||
"technic_constructor_mk"..mark.."_bottom_on.png",
|
||||
"technic_constructor_mk"..mark.."_side2_on.png",
|
||||
"technic_constructor_mk"..mark.."_side1_on.png",
|
||||
"technic_constructor_back.png",
|
||||
"technic_constructor_front_on.png"},
|
||||
paramtype2 = "facedir",
|
||||
drop = "technic:constructor_mk"..mark.."_off",
|
||||
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
|
||||
mesecon=2, not_in_creative_inventory=1, technic_constructor=1},
|
||||
mesecons= {effector = {action_off = make_off(mark)}},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
allow_metadata_inventory_put = allow_inventory_put,
|
||||
allow_metadata_inventory_take = technic.machine_inventory_take,
|
||||
allow_metadata_inventory_move = technic.machine_inventory_move,
|
||||
on_rotate = false
|
||||
})
|
||||
end
|
||||
|
||||
make_constructor(1, 1)
|
||||
make_constructor(2, 2)
|
||||
make_constructor(3, 4)
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,15 @@
|
||||
local path = technic.modpath.."/machines/other"
|
||||
|
||||
-- mesecons and tubes related
|
||||
dofile(path.."/injector.lua")
|
||||
dofile(path.."/constructor.lua")
|
||||
|
||||
if technic.config:get_bool("enable_frames") and minetest.get_modpath("mesecons_mvps") ~= nil then
|
||||
dofile(path.."/frames.lua")
|
||||
end
|
||||
|
||||
-- Coal-powered machines
|
||||
dofile(path.."/coal_alloy_furnace.lua")
|
||||
dofile(path.."/coal_furnace.lua")
|
||||
|
||||
dofile(path.."/anchor.lua")
|
||||
@@ -0,0 +1,157 @@
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
local fs_helpers = pipeworks.fs_helpers
|
||||
|
||||
local tube_entry = "^pipeworks_tube_connection_metallic.png"
|
||||
|
||||
local param2_to_under = {
|
||||
[0] = {x= 0,y=-1,z= 0}, [1] = {x= 0,y= 0,z=-1},
|
||||
[2] = {x= 0,y= 0,z= 1}, [3] = {x=-1,y= 0,z= 0},
|
||||
[4] = {x= 1,y= 0,z= 0}, [5] = {x= 0,y= 1,z= 0}
|
||||
}
|
||||
|
||||
local base_formspec = "size[8,9;]"..
|
||||
"label[0,0;"..S("Self-Contained Injector").."]"..
|
||||
"list[context;main;0,2;8,2;]"..
|
||||
"list[current_player;main;0,5;8,4;]"..
|
||||
"listring[]"
|
||||
|
||||
local function set_injector_formspec(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local formspec = base_formspec..
|
||||
fs_helpers.cycling_button(
|
||||
meta,
|
||||
pipeworks.button_base,
|
||||
"splitstacks",
|
||||
{
|
||||
pipeworks.button_off,
|
||||
pipeworks.button_on
|
||||
}
|
||||
)..pipeworks.button_label
|
||||
if meta:get_string("mode") == "whole stacks" then
|
||||
formspec = formspec.."button[0,1;4,1;mode_item;"..S("Stackwise").."]"
|
||||
else
|
||||
formspec = formspec.."button[0,1;4,1;mode_stack;"..S("Itemwise").."]"
|
||||
end
|
||||
if minetest.get_node_timer(pos):is_started() then
|
||||
formspec = formspec.."button[4,1;4,1;disable;"..S("Enabled").."]"
|
||||
else
|
||||
formspec = formspec.."button[4,1;4,1;enable;"..S("Disabled").."]"
|
||||
end
|
||||
meta:set_string("formspec", formspec)
|
||||
end
|
||||
|
||||
minetest.register_node("technic:injector", {
|
||||
description = S("Self-Contained Injector"),
|
||||
tiles = {
|
||||
"technic_injector_top.png"..tube_entry,
|
||||
"technic_injector_bottom.png",
|
||||
"technic_injector_side.png"..tube_entry,
|
||||
"technic_injector_side.png"..tube_entry,
|
||||
"technic_injector_side.png"..tube_entry,
|
||||
"technic_injector_side.png"
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, tubedevice=1, tubedevice_receiver=1},
|
||||
tube = {
|
||||
can_insert = function(pos, node, stack, direction)
|
||||
local meta = minetest.get_meta(pos)
|
||||
if meta:get_int("splitstacks") == 1 then
|
||||
stack = stack:peek_item(1)
|
||||
end
|
||||
return meta:get_inventory():room_for_item("main", stack)
|
||||
end,
|
||||
insert_object = function(pos, node, stack, direction)
|
||||
return minetest.get_meta(pos):get_inventory():add_item("main", stack)
|
||||
end,
|
||||
connect_sides = {left=1, right=1, back=1, top=1, bottom=1},
|
||||
},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", S("Self-Contained Injector"))
|
||||
meta:set_string("mode", "single items")
|
||||
meta:get_inventory():set_size("main", 16)
|
||||
minetest.get_node_timer(pos):start(1)
|
||||
set_injector_formspec(pos)
|
||||
end,
|
||||
can_dig = function(pos, player)
|
||||
return minetest.get_meta(pos):get_inventory():is_empty("main")
|
||||
end,
|
||||
on_receive_fields = function(pos, formanme, fields, sender)
|
||||
if fields.quit or not pipeworks.may_configure(pos, sender) then
|
||||
return
|
||||
end
|
||||
local meta = minetest.get_meta(pos)
|
||||
if fields.mode_item then
|
||||
meta:set_string("mode", "single items")
|
||||
elseif fields.mode_stack then
|
||||
meta:set_string("mode", "whole stacks")
|
||||
elseif fields.disable then
|
||||
minetest.get_node_timer(pos):stop()
|
||||
elseif fields.enable then
|
||||
minetest.get_node_timer(pos):start(1)
|
||||
end
|
||||
fs_helpers.on_receive_fields(pos, fields)
|
||||
set_injector_formspec(pos)
|
||||
end,
|
||||
on_timer = function(pos, elapsed)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
local dir = param2_to_under[math.floor(node.param2 / 4)]
|
||||
local node_under = minetest.get_node(vector.add(pos, dir))
|
||||
if minetest.get_item_group(node_under.name, "tubedevice") > 0 then
|
||||
local inv = meta:get_inventory()
|
||||
local list = inv:get_list("main")
|
||||
if not list then
|
||||
return true
|
||||
end
|
||||
local stackwise = meta:get_string("mode") == "whole stacks"
|
||||
for i,stack in ipairs(list) do
|
||||
if not stack:is_empty() then
|
||||
if stackwise then
|
||||
technic.tube_inject_item(pos, pos, dir, stack:to_table())
|
||||
stack:clear()
|
||||
else
|
||||
technic.tube_inject_item(pos, pos, dir, stack:take_item(1):to_table())
|
||||
end
|
||||
inv:set_stack("main", i, stack)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
return true
|
||||
end,
|
||||
on_rotate = function(pos, node, user, mode, new_param2)
|
||||
node.param2 = new_param2
|
||||
minetest.swap_node(pos, node)
|
||||
pipeworks.scan_for_tube_objects(pos)
|
||||
return true
|
||||
end,
|
||||
allow_metadata_inventory_put = technic.machine_inventory_put,
|
||||
allow_metadata_inventory_take = technic.machine_inventory_take,
|
||||
allow_metadata_inventory_move = technic.machine_inventory_move,
|
||||
after_place_node = pipeworks.after_place,
|
||||
after_dig_node = pipeworks.after_dig
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = "technic:injector 1",
|
||||
recipe = {
|
||||
{"", "technic:control_logic_unit",""},
|
||||
{"", "default:chest",""},
|
||||
{"", "pipeworks:tube_1",""},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_lbm({
|
||||
label = "Old injector conversion",
|
||||
name = "technic:old_injector_conversion",
|
||||
nodenames = {"technic:injector"},
|
||||
run_at_every_load = false,
|
||||
action = function(pos, node)
|
||||
minetest.get_node_timer(pos):start(1)
|
||||
set_injector_formspec(pos)
|
||||
end
|
||||
})
|
||||
@@ -0,0 +1,130 @@
|
||||
-- POWER MONITOR
|
||||
-- The power monitor can be used to monitor how much power is available on a network,
|
||||
-- similarly to the old "slave" switching stations.
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
local cable_entry = "^technic_cable_connection_overlay.png"
|
||||
|
||||
-- Get registered cable or nil, returns nil if area is not loaded
|
||||
local function get_cable(pos)
|
||||
local node = minetest.get_node_or_nil(pos)
|
||||
return (node and technic.get_cable_tier(node.name)) and node
|
||||
end
|
||||
|
||||
-- return the position of connected cable or nil
|
||||
-- TODO: Make it support every possible orientation
|
||||
local function get_connected_cable_network(pos)
|
||||
local param2 = minetest.get_node(pos).param2
|
||||
-- should probably also work sideways or upside down but for now it wont
|
||||
if param2 > 3 then return end
|
||||
-- Below?
|
||||
local checkpos = {x=pos.x,y=pos.y-1,z=pos.z}
|
||||
local network_id = get_cable(checkpos) and technic.pos2network(checkpos)
|
||||
if network_id then
|
||||
return network_id
|
||||
end
|
||||
-- Behind?
|
||||
checkpos = vector.add(minetest.facedir_to_dir(param2),pos)
|
||||
network_id = get_cable(checkpos) and technic.pos2network(checkpos)
|
||||
return network_id
|
||||
end
|
||||
|
||||
-- return the position of the associated switching station or nil
|
||||
local function get_network(pos)
|
||||
local network_id = get_connected_cable_network(pos)
|
||||
local network = network_id and technic.networks[network_id]
|
||||
local swpos = network and technic.network2sw_pos(network_id)
|
||||
local is_powermonitor = swpos and minetest.get_node(swpos).name == "technic:switching_station"
|
||||
return (is_powermonitor and network.all_nodes[network_id]) and network
|
||||
end
|
||||
|
||||
minetest.register_craft({
|
||||
output = "technic:power_monitor",
|
||||
recipe = {
|
||||
{"", "", ""},
|
||||
{"", "technic:machine_casing", "default:copper_ingot"},
|
||||
{"technic:lv_cable", "technic:lv_cable", "technic:lv_cable"}
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_node("technic:power_monitor",{
|
||||
description = S("Power Monitor"),
|
||||
tiles = {
|
||||
"technic_power_monitor_sides.png",
|
||||
"technic_power_monitor_sides.png"..cable_entry,
|
||||
"technic_power_monitor_sides.png",
|
||||
"technic_power_monitor_sides.png",
|
||||
"technic_power_monitor_sides.png"..cable_entry,
|
||||
"technic_power_monitor_front.png"
|
||||
},
|
||||
paramtype2 = "facedir",
|
||||
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2, technic_all_tiers=1},
|
||||
connect_sides = {"bottom", "back"},
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", S("Power Monitor"))
|
||||
meta:set_string("channel", "power_monitor"..minetest.pos_to_string(pos))
|
||||
meta:set_string("formspec", "field[channel;Channel;${channel}]")
|
||||
end,
|
||||
on_receive_fields = function(pos, formname, fields, sender)
|
||||
if not fields.channel then
|
||||
return
|
||||
end
|
||||
local plname = sender:get_player_name()
|
||||
if minetest.is_protected(pos, plname) and not minetest.check_player_privs(sender, "protection_bypass") then
|
||||
minetest.record_protection_violation(pos, plname)
|
||||
return
|
||||
end
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("channel", fields.channel)
|
||||
end,
|
||||
digiline = {
|
||||
receptor = {
|
||||
rules = technic.digilines.rules,
|
||||
action = function() end
|
||||
},
|
||||
effector = {
|
||||
rules = technic.digilines.rules,
|
||||
action = function(pos, node, channel, msg)
|
||||
if msg ~= "GET" and msg ~= "get" then
|
||||
return
|
||||
end
|
||||
local meta = minetest.get_meta(pos)
|
||||
if channel ~= meta:get_string("channel") then
|
||||
return
|
||||
end
|
||||
|
||||
local network = get_network(pos)
|
||||
if not network then return end
|
||||
|
||||
digilines.receptor_send(pos, technic.digilines.rules, channel, {
|
||||
supply = network.supply,
|
||||
demand = network.demand,
|
||||
lag = network.lag,
|
||||
battery_count = network.battery_count,
|
||||
battery_charge = network.battery_charge,
|
||||
battery_charge_max = network.battery_charge_max,
|
||||
})
|
||||
end
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = {"technic:power_monitor"},
|
||||
label = "Machines: run power monitor",
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local network = get_network(pos)
|
||||
if network then
|
||||
meta:set_string("infotext", S("Power Monitor. Supply: @1 Demand: @2",
|
||||
technic.EU_string(network.supply), technic.EU_string(network.demand)))
|
||||
else
|
||||
meta:set_string("infotext",S("Power Monitor Has No Network"))
|
||||
end
|
||||
end,
|
||||
})
|
||||
@@ -0,0 +1,50 @@
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
function technic.insert_object_unique_stack(pos, node, incoming_stack, direction)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local incoming_name = incoming_stack:get_name()
|
||||
local stack_index = nil
|
||||
for inv_index, inv_stack in pairs(inv:get_list("src")) do
|
||||
if inv_stack:get_name() == incoming_name then
|
||||
stack_index = inv_index
|
||||
break
|
||||
end
|
||||
end
|
||||
if stack_index == nil then
|
||||
return inv:add_item("src", incoming_stack)
|
||||
end
|
||||
local present_stack = inv:get_stack("src", stack_index)
|
||||
local leftover = present_stack:add_item(incoming_stack)
|
||||
inv:set_stack("src", stack_index, present_stack)
|
||||
return leftover
|
||||
end
|
||||
|
||||
function technic.can_insert_unique_stack(pos, node, incoming_stack, direction)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local incoming_name = incoming_stack:get_name()
|
||||
if meta:get_int("splitstacks") == 0 then
|
||||
-- avoid looping second time with inv:contains_item("src", incoming_stack)
|
||||
for _, inv_stack in pairs(inv:get_list("src")) do
|
||||
if inv_stack:get_name() == incoming_name then
|
||||
return inv_stack:item_fits(incoming_stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return technic.default_can_insert(pos, node, incoming_stack, direction)
|
||||
end
|
||||
|
||||
function technic.register_alloy_furnace(data)
|
||||
data.typename = "alloy"
|
||||
data.machine_name = "alloy_furnace"
|
||||
data.machine_desc = S("%s Alloy Furnace")
|
||||
|
||||
data.insert_object = technic.insert_object_unique_stack
|
||||
data.can_insert = technic.can_insert_unique_stack
|
||||
|
||||
technic.register_base_machine(data)
|
||||
end
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
technic.register_recipe_type("alloy", {
|
||||
description = S("Alloying"),
|
||||
input_size = 2,
|
||||
})
|
||||
|
||||
function technic.register_alloy_recipe(data)
|
||||
data.time = data.time or 6
|
||||
technic.register_recipe("alloy", data)
|
||||
end
|
||||
|
||||
local recipes = {
|
||||
{"technic:copper_dust 7", "technic:tin_dust", "technic:bronze_dust 8", 12},
|
||||
{"default:copper_ingot 7", "default:tin_ingot", "default:bronze_ingot 8", 12},
|
||||
{"technic:wrought_iron_dust 2", "technic:coal_dust", "technic:carbon_steel_dust 2", 6},
|
||||
{"technic:wrought_iron_ingot 2", "technic:coal_dust", "technic:carbon_steel_ingot 2", 6},
|
||||
{"technic:carbon_steel_dust 2", "technic:coal_dust", "technic:cast_iron_dust 2", 6},
|
||||
{"technic:carbon_steel_ingot 2", "technic:coal_dust", "technic:cast_iron_ingot 2", 6},
|
||||
{"technic:carbon_steel_dust 4", "technic:chromium_dust", "technic:stainless_steel_dust 5", 7.5},
|
||||
{"technic:carbon_steel_ingot 4", "technic:chromium_ingot", "technic:stainless_steel_ingot 5", 7.5},
|
||||
{"technic:copper_dust 2", "technic:zinc_dust", "technic:brass_dust 3"},
|
||||
{"default:copper_ingot 2", "technic:zinc_ingot", "basic_materials:brass_ingot 3"},
|
||||
{"default:sand 2", "technic:coal_dust 2", "technic:silicon_wafer"},
|
||||
{"technic:silicon_wafer", "technic:gold_dust", "technic:doped_silicon_wafer"},
|
||||
-- from https://en.wikipedia.org/wiki/Carbon_black
|
||||
-- The highest volume use of carbon black is as a reinforcing filler in rubber products, especially tires.
|
||||
-- "[Compounding a] pure gum vulcanizate … with 50% of its weight of carbon black
|
||||
-- improves its tensile strength and wear resistance …"
|
||||
{"technic:raw_latex 4", "technic:coal_dust 2", "technic:rubber 6", 2},
|
||||
{"default:ice", "bucket:bucket_empty", "bucket:bucket_water", 1 },
|
||||
{"default:obsidian", "bucket:bucket_empty", "bucket:bucket_lava", 1 },
|
||||
}
|
||||
|
||||
if minetest.get_modpath("ethereal") then
|
||||
table.insert(recipes, {"default:clay", "dye:red", "bakedclay:red"})
|
||||
table.insert(recipes, {"default:clay", "dye:orange", "bakedclay:orange"})
|
||||
table.insert(recipes, {"default:clay", "dye:grey", "bakedclay:grey"})
|
||||
end
|
||||
|
||||
for _, data in pairs(recipes) do
|
||||
technic.register_alloy_recipe({input = {data[1], data[2]}, output = data[3], time = data[4]})
|
||||
end
|
||||
@@ -0,0 +1,431 @@
|
||||
|
||||
local digilines_path = minetest.get_modpath("digilines")
|
||||
|
||||
local S = technic.getter
|
||||
local tube_entry = "^pipeworks_tube_connection_metallic.png"
|
||||
local cable_entry = "^technic_cable_connection_overlay.png"
|
||||
|
||||
technic.register_power_tool("technic:battery", 10000)
|
||||
technic.register_power_tool("technic:red_energy_crystal", 50000)
|
||||
technic.register_power_tool("technic:green_energy_crystal", 150000)
|
||||
technic.register_power_tool("technic:blue_energy_crystal", 450000)
|
||||
|
||||
-- Battery recipes:
|
||||
-- Tin-copper recipe:
|
||||
minetest.register_craft({
|
||||
output = "technic:battery",
|
||||
recipe = {
|
||||
{"group:wood", "default:copper_ingot", "group:wood"},
|
||||
{"group:wood", "default:tin_ingot", "group:wood"},
|
||||
{"group:wood", "default:copper_ingot", "group:wood"},
|
||||
}
|
||||
})
|
||||
-- Sulfur-lead-water recipes:
|
||||
-- With sulfur lumps:
|
||||
-- With water:
|
||||
minetest.register_craft({
|
||||
output = "technic:battery",
|
||||
recipe = {
|
||||
{"group:wood", "technic:sulfur_lump", "group:wood"},
|
||||
{"technic:lead_ingot", "bucket:bucket_water", "technic:lead_ingot"},
|
||||
{"group:wood", "technic:sulfur_lump", "group:wood"},
|
||||
},
|
||||
replacements = {
|
||||
{"bucket:bucket_water", "bucket:bucket_empty"}
|
||||
}
|
||||
})
|
||||
-- With oil extract:
|
||||
minetest.register_craft({
|
||||
output = "technic:battery",
|
||||
recipe = {
|
||||
{"group:wood", "technic:sulfur_lump", "group:wood"},
|
||||
{"technic:lead_ingot", "homedecor:oil_extract", "technic:lead_ingot"},
|
||||
{"group:wood", "technic:sulfur_lump", "group:wood"},
|
||||
}
|
||||
})
|
||||
-- With sulfur dust:
|
||||
-- With water:
|
||||
minetest.register_craft({
|
||||
output = "technic:battery",
|
||||
recipe = {
|
||||
{"group:wood", "technic:sulfur_dust", "group:wood"},
|
||||
{"technic:lead_ingot", "bucket:bucket_water", "technic:lead_ingot"},
|
||||
{"group:wood", "technic:sulfur_dust", "group:wood"},
|
||||
},
|
||||
replacements = {
|
||||
{"bucket:bucket_water", "bucket:bucket_empty"}
|
||||
}
|
||||
})
|
||||
-- With oil extract:
|
||||
minetest.register_craft({
|
||||
output = "technic:battery",
|
||||
recipe = {
|
||||
{"group:wood", "technic:sulfur_dust", "group:wood"},
|
||||
{"technic:lead_ingot", "homedecor:oil_extract", "technic:lead_ingot"},
|
||||
{"group:wood", "technic:sulfur_dust", "group:wood"},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_tool("technic:battery", {
|
||||
description = S("RE Battery"),
|
||||
inventory_image = "technic_battery.png",
|
||||
wear_represents = "technic_RE_charge",
|
||||
on_refill = technic.refill_RE_charge,
|
||||
tool_capabilities = {
|
||||
charge = 0,
|
||||
max_drop_level = 0,
|
||||
groupcaps = {
|
||||
fleshy = {times={}, uses=10000, maxlevel=0}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
-- x+2 + (z+2)*2
|
||||
local dirtab = {
|
||||
[4] = 2,
|
||||
[5] = 3,
|
||||
[7] = 1,
|
||||
[8] = 0
|
||||
}
|
||||
|
||||
local tube = {
|
||||
insert_object = function(pos, node, stack, direction)
|
||||
if direction.y == 1
|
||||
or (direction.y == 0 and dirtab[direction.x+2+(direction.z+2)*2] == node.param2) then
|
||||
return stack
|
||||
end
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
if direction.y == 0 then
|
||||
return inv:add_item("src", stack)
|
||||
else
|
||||
return inv:add_item("dst", stack)
|
||||
end
|
||||
end,
|
||||
can_insert = function(pos, node, stack, direction)
|
||||
if direction.y == 1
|
||||
or (direction.y == 0 and dirtab[direction.x+2+(direction.z+2)*2] == node.param2) then
|
||||
return false
|
||||
end
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
if direction.y == 0 then
|
||||
return inv:room_for_item("src", stack)
|
||||
else
|
||||
return inv:room_for_item("dst", stack)
|
||||
end
|
||||
end,
|
||||
connect_sides = {left=1, right=1, back=1, top=1},
|
||||
}
|
||||
|
||||
function technic.register_battery_box(data)
|
||||
local tier = data.tier
|
||||
local ltier = string.lower(tier)
|
||||
local formspec =
|
||||
"size[8,9]"..
|
||||
"image[1,1;1,2;technic_power_meter_bg.png]"..
|
||||
"list[context;src;3,1;1,1;]"..
|
||||
"image[4,1;1,1;technic_battery_reload.png]"..
|
||||
"list[context;dst;5,1;1,1;]"..
|
||||
"label[0,0;"..S("%s Battery Box"):format(tier).."]"..
|
||||
"label[3,0;"..S("Charge").."]"..
|
||||
"label[5,0;"..S("Discharge").."]"..
|
||||
"label[1,3;"..S("Power level").."]"..
|
||||
"list[current_player;main;0,5;8,4;]"..
|
||||
"listring[context;dst]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;src]"..
|
||||
"listring[current_player;main]"..
|
||||
(data.upgrade and
|
||||
"list[context;upgrade1;3.5,3;1,1;]"..
|
||||
"list[context;upgrade2;4.5,3;1,1;]"..
|
||||
"label[3.5,4;"..S("Upgrade Slots").."]"..
|
||||
"listring[context;upgrade1]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[context;upgrade2]"..
|
||||
"listring[current_player;main]"
|
||||
or "")
|
||||
|
||||
--
|
||||
-- Generate formspec with power meter
|
||||
--
|
||||
local function get_formspec(charge_ratio, channel)
|
||||
return formspec .. "image[1,1;1,2;technic_power_meter_bg.png^[lowpart:" ..
|
||||
math.floor(charge_ratio * 100) .. ":technic_power_meter_fg.png]" ..
|
||||
(digilines_path and
|
||||
("field[0.3,4;2.2,1;channel;Digiline channel;%s]button[2,3.7;1,1;setchannel;Set]")
|
||||
:format(minetest.formspec_escape(channel))
|
||||
or "")
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Update fields not affecting internal network calculations and behavior in any way
|
||||
--
|
||||
local function update_node(pos, update_formspec)
|
||||
-- Read metadata and calculate actual values based on upgrades
|
||||
local meta = minetest.get_meta(pos)
|
||||
local current_charge = meta:get_int("internal_EU_charge")
|
||||
local EU_upgrade = 0
|
||||
if data.upgrade then
|
||||
EU_upgrade = technic.handle_machine_upgrades(meta)
|
||||
end
|
||||
local max_charge = data.max_charge * (1 + EU_upgrade / 10)
|
||||
-- Select node textures
|
||||
local charge_ratio = current_charge / max_charge
|
||||
local charge_count = math.ceil(charge_ratio * 8)
|
||||
charge_count = math.min(charge_count, 8)
|
||||
charge_count = math.max(charge_count, 0)
|
||||
local last_count = meta:get_float("last_side_shown")
|
||||
if charge_count ~= last_count then
|
||||
technic.swap_node(pos, "technic:" .. ltier .. "_battery_box" .. charge_count)
|
||||
meta:set_float("last_side_shown", charge_count)
|
||||
end
|
||||
-- Update formspec and infotext
|
||||
local eu_input = meta:get_int(tier.."_EU_input")
|
||||
local infotext = S("@1 Battery Box: @2 / @3", tier,
|
||||
technic.EU_string(current_charge), technic.EU_string(max_charge))
|
||||
if eu_input == 0 then
|
||||
infotext = S("%s Idle"):format(infotext)
|
||||
end
|
||||
meta:set_string("infotext", infotext)
|
||||
if update_formspec then
|
||||
local channel = meta:get_string("channel")
|
||||
meta:set_string("formspec", get_formspec(charge_ratio, channel))
|
||||
end
|
||||
end
|
||||
|
||||
local function get_tool(inventory, listname)
|
||||
-- Get itemstack and check if it is registered tool
|
||||
if inventory:is_empty(listname) then
|
||||
return
|
||||
end
|
||||
local toolstack = inventory:get_stack(listname, 1)
|
||||
local toolname = toolstack:get_name()
|
||||
if technic.power_tools[toolname] == nil then
|
||||
return
|
||||
end
|
||||
local tooldef = toolstack:get_definition()
|
||||
if not tooldef then
|
||||
return
|
||||
end
|
||||
return toolstack, tooldef
|
||||
end
|
||||
|
||||
local function charge_tools(meta, batt_charge, charge_step)
|
||||
if batt_charge <= 0 then
|
||||
return batt_charge, false
|
||||
end
|
||||
-- Get tool stack and definition
|
||||
local inv = meta:get_inventory()
|
||||
local toolstack, tooldef = get_tool(inv, "src")
|
||||
if not toolstack then return batt_charge, false end
|
||||
-- Do the charging, get and check
|
||||
local get_charge = tooldef.technic_get_charge or technic.get_charge
|
||||
local tool_charge, max_charge = get_charge(toolstack)
|
||||
if tool_charge >= max_charge then
|
||||
return batt_charge, true
|
||||
end
|
||||
-- Do the charging, set charge and replace stack
|
||||
local set_charge = tooldef.technic_set_charge or technic.set_charge
|
||||
charge_step = math.min(charge_step, batt_charge)
|
||||
charge_step = math.min(charge_step, max_charge - tool_charge)
|
||||
tool_charge = tool_charge + charge_step
|
||||
set_charge(toolstack, tool_charge)
|
||||
inv:set_stack("src", 1, toolstack)
|
||||
return batt_charge - charge_step, (tool_charge == max_charge)
|
||||
end
|
||||
|
||||
local function discharge_tools(meta, batt_charge, charge_step, batt_max_charge)
|
||||
if batt_charge >= batt_max_charge then
|
||||
return batt_charge, false
|
||||
end
|
||||
-- Get tool stack and definition
|
||||
local inv = meta:get_inventory()
|
||||
local toolstack, tooldef = get_tool(inv, "dst")
|
||||
if not toolstack then return batt_charge, false end
|
||||
-- Do the discharging, get and check
|
||||
local get_charge = tooldef.technic_get_charge or technic.get_charge
|
||||
local tool_charge = get_charge(toolstack)
|
||||
if tool_charge <= 0 then
|
||||
return batt_charge, true
|
||||
end
|
||||
-- Do the discharging, set charge and replace stack
|
||||
local set_charge = tooldef.technic_set_charge or technic.set_charge
|
||||
charge_step = math.min(charge_step, batt_max_charge - batt_charge)
|
||||
charge_step = math.min(charge_step, tool_charge)
|
||||
tool_charge = tool_charge - charge_step
|
||||
set_charge(toolstack, tool_charge)
|
||||
inv:set_stack("dst", 1, toolstack)
|
||||
return batt_charge + charge_step, (tool_charge == 0)
|
||||
end
|
||||
|
||||
local function run(pos, node, run_state, network)
|
||||
local meta = minetest.get_meta(pos)
|
||||
|
||||
local eu_input = meta:get_int(tier.."_EU_input")
|
||||
local current_charge = meta:get_int("internal_EU_charge")
|
||||
|
||||
local EU_upgrade, tube_upgrade = 0, 0
|
||||
if data.upgrade then
|
||||
EU_upgrade, tube_upgrade = technic.handle_machine_upgrades(meta)
|
||||
end
|
||||
local max_charge = data.max_charge * (1 + EU_upgrade / 10)
|
||||
|
||||
-- Charge/discharge the battery with the input EUs
|
||||
if eu_input >= 0 then
|
||||
current_charge = math.min(current_charge + eu_input, max_charge)
|
||||
else
|
||||
current_charge = math.max(current_charge + eu_input, 0)
|
||||
end
|
||||
|
||||
-- Charging/discharging tools here
|
||||
local tool_full, tool_empty
|
||||
current_charge, tool_full = charge_tools(meta, current_charge, data.charge_step)
|
||||
current_charge, tool_empty = discharge_tools(meta, current_charge, data.discharge_step, max_charge)
|
||||
|
||||
if data.tube and (tool_full or tool_empty) then
|
||||
technic.handle_machine_pipeworks(pos, tube_upgrade, function(pos2, x_velocity, z_velocity)
|
||||
if tool_full then
|
||||
technic.send_items(pos2, x_velocity, z_velocity, "src")
|
||||
elseif tool_empty then
|
||||
technic.send_items(pos2, x_velocity, z_velocity, "dst")
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- We allow batteries to charge on less than the demand
|
||||
local supply = math.min(data.discharge_rate, current_charge)
|
||||
local demand = math.min(data.charge_rate, max_charge - current_charge)
|
||||
network:update_battery(current_charge, max_charge, supply, demand)
|
||||
|
||||
meta:set_int(tier.."_EU_demand", demand)
|
||||
meta:set_int(tier.."_EU_supply", supply)
|
||||
meta:set_int("internal_EU_charge", current_charge)
|
||||
meta:set_int("internal_EU_charge_max", max_charge)
|
||||
|
||||
local timer = minetest.get_node_timer(pos)
|
||||
if not timer:is_started() then
|
||||
timer:start(2)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_timer(pos, elapsed)
|
||||
if not technic.pos2network(pos) then return end
|
||||
update_node(pos)
|
||||
return true
|
||||
end
|
||||
|
||||
for i = 0, 8 do
|
||||
local groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
|
||||
technic_machine=1, ["technic_"..ltier]=1}
|
||||
if i ~= 0 then
|
||||
groups.not_in_creative_inventory = 1
|
||||
end
|
||||
|
||||
if data.tube then
|
||||
groups.tubedevice = 1
|
||||
groups.tubedevice_receiver = 1
|
||||
end
|
||||
|
||||
local top_tex = "technic_"..ltier.."_battery_box_top.png"..tube_entry
|
||||
local front_tex = "technic_"..ltier.."_battery_box_front.png^technic_power_meter"..i..".png"
|
||||
local side_tex = "technic_"..ltier.."_battery_box_side.png"..tube_entry
|
||||
local bottom_tex = "technic_"..ltier.."_battery_box_bottom.png"..cable_entry
|
||||
|
||||
if ltier == "lv" then
|
||||
top_tex = "technic_"..ltier.."_battery_box_top.png"
|
||||
front_tex = "technic_"..ltier.."_battery_box_side.png^technic_power_meter"..i..".png"
|
||||
side_tex = "technic_"..ltier.."_battery_box_side.png^technic_power_meter"..i..".png"
|
||||
end
|
||||
|
||||
minetest.register_node("technic:"..ltier.."_battery_box"..i, {
|
||||
description = S("%s Battery Box"):format(tier),
|
||||
tiles = {
|
||||
top_tex,
|
||||
bottom_tex,
|
||||
side_tex,
|
||||
side_tex,
|
||||
side_tex,
|
||||
front_tex},
|
||||
groups = groups,
|
||||
connect_sides = {"bottom"},
|
||||
tube = data.tube and tube or nil,
|
||||
paramtype2 = "facedir",
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
drop = "technic:"..ltier.."_battery_box0",
|
||||
on_construct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", S("%s Battery Box"):format(tier))
|
||||
meta:set_int(tier.."_EU_demand", 0)
|
||||
meta:set_int(tier.."_EU_supply", 0)
|
||||
meta:set_int(tier.."_EU_input", 0)
|
||||
meta:set_float("internal_EU_charge", 0)
|
||||
local inv = meta:get_inventory()
|
||||
inv:set_size("src", 1)
|
||||
inv:set_size("dst", 1)
|
||||
inv:set_size("upgrade1", 1)
|
||||
inv:set_size("upgrade2", 1)
|
||||
update_node(pos, true)
|
||||
end,
|
||||
can_dig = technic.machine_can_dig,
|
||||
allow_metadata_inventory_put = technic.machine_inventory_put,
|
||||
allow_metadata_inventory_take = technic.machine_inventory_take,
|
||||
allow_metadata_inventory_move = technic.machine_inventory_move,
|
||||
technic_run = run,
|
||||
on_timer = on_timer,
|
||||
on_rightclick = function(pos) update_node(pos, true) end,
|
||||
on_rotate = screwdriver.rotate_simple,
|
||||
after_place_node = data.tube and pipeworks.after_place,
|
||||
after_dig_node = technic.machine_after_dig_node,
|
||||
on_receive_fields = function(pos, formname, fields, player)
|
||||
local name = player:get_player_name()
|
||||
if minetest.is_protected(pos, name) then
|
||||
minetest.record_protection_violation(pos, name)
|
||||
return
|
||||
elseif fields.setchannel then
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("channel", fields.channel or "")
|
||||
update_node(pos, true)
|
||||
end
|
||||
end,
|
||||
digiline = {
|
||||
receptor = {
|
||||
rules = technic.digilines.rules,
|
||||
action = function() end
|
||||
},
|
||||
effector = {
|
||||
rules = technic.digilines.rules,
|
||||
action = function(pos, node, channel, msg)
|
||||
if msg ~= "GET" and msg ~= "get" then
|
||||
return
|
||||
end
|
||||
local meta = minetest.get_meta(pos)
|
||||
if channel ~= meta:get_string("channel") then
|
||||
return
|
||||
end
|
||||
local inv = meta:get_inventory()
|
||||
digilines.receptor_send(pos, technic.digilines.rules, channel, {
|
||||
demand = meta:get_int(tier.."_EU_demand"),
|
||||
supply = meta:get_int(tier.."_EU_supply"),
|
||||
input = meta:get_int(tier.."_EU_input"),
|
||||
charge = meta:get_int("internal_EU_charge"),
|
||||
max_charge = data.max_charge * (1 + technic.handle_machine_upgrades(meta) / 10),
|
||||
src = inv:get_stack("src", 1):to_table(),
|
||||
dst = inv:get_stack("dst", 1):to_table(),
|
||||
upgrade1 = inv:get_stack("upgrade1", 1):to_table(),
|
||||
upgrade2 = inv:get_stack("upgrade2", 1):to_table()
|
||||
})
|
||||
end
|
||||
},
|
||||
},
|
||||
})
|
||||
end
|
||||
|
||||
-- Register as a battery type
|
||||
-- Battery type machines function as power reservoirs and can both receive and give back power
|
||||
for i = 0, 8 do
|
||||
technic.register_machine(tier, "technic:"..ltier.."_battery_box"..i, technic.battery)
|
||||
end
|
||||
|
||||
end -- End registration
|
||||
@@ -0,0 +1,355 @@
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
local cable_tier = {}
|
||||
|
||||
function technic.is_tier_cable(name, tier)
|
||||
return cable_tier[name] == tier
|
||||
end
|
||||
|
||||
function technic.get_cable_tier(name)
|
||||
return cable_tier[name]
|
||||
end
|
||||
|
||||
local function match_cable_tier_filter(name, tiers)
|
||||
-- Helper to check for set of cable tiers
|
||||
if tiers then
|
||||
for _, tier in ipairs(tiers) do if cable_tier[name] == tier then return true end end
|
||||
return false
|
||||
end
|
||||
return cable_tier[name] ~= nil
|
||||
end
|
||||
|
||||
local function get_neighbors(pos, tiers)
|
||||
-- TODO: Move this to network.lua
|
||||
local tier_machines = tiers and technic.machines[tiers[1]]
|
||||
local is_cable = match_cable_tier_filter(minetest.get_node(pos).name, tiers)
|
||||
local network = is_cable and technic.networks[technic.pos2network(pos)]
|
||||
local cables = {}
|
||||
local machines = {}
|
||||
local positions = {
|
||||
{x=pos.x+1, y=pos.y, z=pos.z},
|
||||
{x=pos.x-1, y=pos.y, z=pos.z},
|
||||
{x=pos.x, y=pos.y+1, z=pos.z},
|
||||
{x=pos.x, y=pos.y-1, z=pos.z},
|
||||
{x=pos.x, y=pos.y, z=pos.z+1},
|
||||
{x=pos.x, y=pos.y, z=pos.z-1},
|
||||
}
|
||||
for _,connected_pos in ipairs(positions) do
|
||||
local name = minetest.get_node(connected_pos).name
|
||||
if tier_machines and tier_machines[name] then
|
||||
table.insert(machines, connected_pos)
|
||||
elseif match_cable_tier_filter(name, tiers) then
|
||||
local cable_network = technic.networks[technic.pos2network(connected_pos)]
|
||||
table.insert(cables,{
|
||||
pos = connected_pos,
|
||||
network = cable_network,
|
||||
})
|
||||
if not network then network = cable_network end
|
||||
end
|
||||
end
|
||||
return network, cables, machines
|
||||
end
|
||||
|
||||
local function place_network_node(pos, tiers, name)
|
||||
-- Get connections and primary network if there's any
|
||||
local network, cables, machines = get_neighbors(pos, tiers)
|
||||
if not network then
|
||||
-- We're evidently not on a network, nothing to add ourselves to
|
||||
return
|
||||
end
|
||||
|
||||
-- Attach to primary network, this must be done before building branches from this position
|
||||
technic.add_network_node(pos, network)
|
||||
if not match_cable_tier_filter(name, tiers) then
|
||||
if technic.machines[tiers[1]][name] == technic.producer_receiver then
|
||||
-- FIXME: Multi tier machine like supply converter should also attach to other networks around pos.
|
||||
-- Preferably also with connection rules defined for machine.
|
||||
-- nodedef.connect_sides could be used to generate these rules.
|
||||
-- For now, assume that all multi network machines belong to technic.producer_receiver group:
|
||||
-- Get cables and networks around PR_RE machine
|
||||
local _, machine_cables, _ = get_neighbors(pos)
|
||||
for _,connection in ipairs(machine_cables) do
|
||||
if connection.network and connection.network.id ~= network.id then
|
||||
-- Attach PR_RE machine to secondary networks (last added is primary until above note is resolved)
|
||||
technic.add_network_node(pos, connection.network)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- Check connected cables for foreign networks, overload if machine was connected to multiple networks
|
||||
for _, connection in ipairs(cables) do
|
||||
if connection.network and connection.network.id ~= network.id then
|
||||
technic.overload_network(connection.network.id)
|
||||
technic.overload_network(network.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Machine added, skip all network building
|
||||
return
|
||||
end
|
||||
|
||||
-- Attach neighbor machines if cable was added
|
||||
for _,machine_pos in ipairs(machines) do
|
||||
technic.add_network_node(machine_pos, network)
|
||||
end
|
||||
|
||||
-- Attach neighbor cables
|
||||
for _,connection in ipairs(cables) do
|
||||
if connection.network then
|
||||
if connection.network.id ~= network.id then
|
||||
-- Remove network if position belongs to another network
|
||||
-- FIXME: Network requires partial rebuild but avoid doing it here if possible.
|
||||
-- This might cause problems when merging two active networks into one
|
||||
technic.remove_network(network.id)
|
||||
technic.remove_network(connection.network.id)
|
||||
connection.network = nil
|
||||
end
|
||||
else
|
||||
-- There's cable that does not belong to any network, attach whole branch
|
||||
technic.add_network_node(connection.pos, network)
|
||||
technic.add_network_branch({connection.pos}, network)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- NOTE: Exported for tests but should probably be moved to network.lua
|
||||
technic.network_node_on_placenode = place_network_node
|
||||
|
||||
local function remove_network_node(pos, tiers, name)
|
||||
-- Get the network and neighbors
|
||||
local network, cables, machines = get_neighbors(pos, tiers)
|
||||
if not network then return end
|
||||
|
||||
if not match_cable_tier_filter(name, tiers) then
|
||||
-- Machine removed, skip cable checks to prevent unnecessary network cleanups
|
||||
for _,connection in ipairs(cables) do
|
||||
if connection.network then
|
||||
-- Remove machine from all networks around it
|
||||
technic.remove_network_node(connection.network.id, pos)
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if #cables == 1 then
|
||||
-- Dead end cable removed, remove it from the network
|
||||
technic.remove_network_node(network.id, pos)
|
||||
-- Remove neighbor machines from network if cable was removed
|
||||
if match_cable_tier_filter(name, tiers) then
|
||||
for _,machine_pos in ipairs(machines) do
|
||||
local net, _, _ = get_neighbors(machine_pos, tiers)
|
||||
if not net then
|
||||
-- Remove machine from network if it does not have other connected cables
|
||||
technic.remove_network_node(network.id, machine_pos)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
-- TODO: Check branches around and switching stations for branches:
|
||||
-- remove branches that do not have switching station. Switching stations not tracked but could be easily tracked.
|
||||
-- remove branches not connected to another branch. Individual branches not tracked, requires simple AI heuristics.
|
||||
-- move branches that have switching station to new networks without checking or loading actual nodes in world.
|
||||
-- To do all this network must be aware of individual branches and switching stations, might not be worth it...
|
||||
-- For now remove whole network and let ABM rebuild it
|
||||
technic.remove_network(network.id)
|
||||
end
|
||||
end
|
||||
-- NOTE: Exported for tests but should probably be moved to network.lua
|
||||
technic.network_node_on_dignode = remove_network_node
|
||||
|
||||
local function item_place_override_node(itemstack, placer, pointed, node)
|
||||
-- Call the default on_place function with a fake itemstack
|
||||
local temp_itemstack = ItemStack(itemstack)
|
||||
temp_itemstack:set_name(node.name)
|
||||
local original_count = temp_itemstack:get_count()
|
||||
temp_itemstack =
|
||||
minetest.item_place(temp_itemstack, placer, pointed, node.param2) or
|
||||
temp_itemstack
|
||||
-- Remove the same number of items from the real itemstack
|
||||
itemstack:take_item(original_count - temp_itemstack:get_count())
|
||||
return itemstack
|
||||
end
|
||||
|
||||
local function override_table(target, source)
|
||||
if target and source then
|
||||
for k,v in pairs(source) do
|
||||
target[k] = v
|
||||
end
|
||||
end
|
||||
return target
|
||||
end
|
||||
|
||||
function technic.register_cable(tier, size, description, prefix, override_cable, override_cable_plate)
|
||||
prefix = prefix or ""
|
||||
override_cable_plate = override_cable_plate or override_cable
|
||||
local ltier = string.lower(tier)
|
||||
local node_name = "technic:"..ltier..prefix.."_cable"
|
||||
cable_tier[node_name] = tier
|
||||
|
||||
local groups = {snappy=2, choppy=2, oddly_breakable_by_hand=2,
|
||||
["technic_"..ltier.."_cable"] = 1}
|
||||
|
||||
local node_box = {
|
||||
type = "connected",
|
||||
fixed = {-size, -size, -size, size, size, size},
|
||||
connect_top = {-size, -size, -size, size, 0.5, size}, -- y+
|
||||
connect_bottom = {-size, -0.5, -size, size, size, size}, -- y-
|
||||
connect_front = {-size, -size, -0.5, size, size, size}, -- z-
|
||||
connect_back = {-size, -size, size, size, size, 0.5 }, -- z+
|
||||
connect_left = {-0.5, -size, -size, size, size, size}, -- x-
|
||||
connect_right = {-size, -size, -size, 0.5, size, size}, -- x+
|
||||
}
|
||||
|
||||
minetest.register_node(node_name, override_table({
|
||||
description = S("%s Cable"):format(tier),
|
||||
tiles = {"technic_"..ltier..prefix.."_cable.png"},
|
||||
inventory_image = "technic_"..ltier..prefix.."_cable_wield.png",
|
||||
wield_image = "technic_"..ltier..prefix.."_cable_wield.png",
|
||||
groups = groups,
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
drop = node_name,
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
drawtype = "nodebox",
|
||||
node_box = node_box,
|
||||
connects_to = {"group:technic_"..ltier.."_cable",
|
||||
"group:technic_"..ltier, "group:technic_all_tiers"},
|
||||
on_construct = function(pos) place_network_node(pos, {tier}, node_name) end,
|
||||
on_destruct = function(pos) remove_network_node(pos, {tier}, node_name) end,
|
||||
}, override_cable))
|
||||
|
||||
local xyz = {
|
||||
["-x"] = 1,
|
||||
["-y"] = 2,
|
||||
["-z"] = 3,
|
||||
["x"] = 4,
|
||||
["y"] = 5,
|
||||
["z"] = 6,
|
||||
}
|
||||
local notconnects = {
|
||||
[1] = "left",
|
||||
[2] = "bottom",
|
||||
[3] = "front",
|
||||
[4] = "right",
|
||||
[5] = "top",
|
||||
[6] = "back",
|
||||
}
|
||||
local function s(p)
|
||||
if p:find("-") then
|
||||
return p:sub(2)
|
||||
else
|
||||
return "-"..p
|
||||
end
|
||||
end
|
||||
-- TODO: Does this really need 6 different nodes? Use single node for cable plate if possible.
|
||||
for p, i in pairs(xyz) do
|
||||
local def = {
|
||||
description = S("%s Cable Plate"):format(tier),
|
||||
tiles = {"technic_"..ltier..prefix.."_cable.png"},
|
||||
groups = table.copy(groups),
|
||||
sounds = default.node_sound_wood_defaults(),
|
||||
drop = node_name .. "_plate_1",
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
drawtype = "nodebox",
|
||||
node_box = table.copy(node_box),
|
||||
connects_to = {"group:technic_"..ltier.."_cable",
|
||||
"group:technic_"..ltier, "group:technic_all_tiers"},
|
||||
on_construct = function(pos) place_network_node(pos, {tier}, node_name.."_plate_"..i) end,
|
||||
on_destruct = function(pos) remove_network_node(pos, {tier}, node_name.."_plate_"..i) end,
|
||||
}
|
||||
def.node_box.fixed = {
|
||||
{-size, -size, -size, size, size, size},
|
||||
{-0.5, -0.5, -0.5, 0.5, 0.5, 0.5}
|
||||
}
|
||||
def.node_box.fixed[1][xyz[p]] = 7/16 * (i-3.5)/math.abs(i-3.5)
|
||||
def.node_box.fixed[2][xyz[s(p)]] = 3/8 * (i-3.5)/math.abs(i-3.5)
|
||||
def.node_box["connect_"..notconnects[i]] = nil
|
||||
if i == 1 then
|
||||
def.on_place = function(itemstack, placer, pointed_thing)
|
||||
local pointed_thing_diff = vector.subtract(pointed_thing.above, pointed_thing.under)
|
||||
local num = 1
|
||||
local changed
|
||||
for k, v in pairs(pointed_thing_diff) do
|
||||
if v ~= 0 then
|
||||
changed = k
|
||||
num = xyz[s(tostring(v):sub(-2, -2)..k)]
|
||||
break
|
||||
end
|
||||
end
|
||||
local crtl = placer:get_player_control()
|
||||
if (crtl.aux1 or crtl.sneak) and not (crtl.aux1 and crtl.sneak) and changed then
|
||||
local fine_pointed = minetest.pointed_thing_to_face_pos(placer, pointed_thing)
|
||||
fine_pointed = vector.subtract(fine_pointed, pointed_thing.above)
|
||||
fine_pointed[changed] = nil
|
||||
local ps = {}
|
||||
for p2, _ in pairs(fine_pointed) do
|
||||
ps[#ps+1] = p2
|
||||
end
|
||||
local bigger = (math.abs(fine_pointed[ps[1]]) > math.abs(fine_pointed[ps[2]]) and ps[1]) or ps[2]
|
||||
if math.abs(fine_pointed[bigger]) < 0.3 then
|
||||
num = num + 3
|
||||
num = (num <= 6 and num) or num - 6
|
||||
else
|
||||
num = xyz[((fine_pointed[bigger] < 0 and "-") or "") .. bigger]
|
||||
end
|
||||
end
|
||||
if num == nil then num = 1 end
|
||||
return item_place_override_node(
|
||||
itemstack, placer, pointed_thing,
|
||||
{name = node_name.."_plate_"..num}
|
||||
)
|
||||
end
|
||||
else
|
||||
def.groups.not_in_creative_inventory = 1
|
||||
end
|
||||
def.on_rotate = function(pos, node, user, mode, new_param2)
|
||||
local dir = 0
|
||||
if mode == screwdriver.ROTATE_FACE then -- left-click
|
||||
dir = 1
|
||||
elseif mode == screwdriver.ROTATE_AXIS then -- right-click
|
||||
dir = -1
|
||||
end
|
||||
local num = tonumber(node.name:sub(-1))
|
||||
num = num + dir
|
||||
num = (num >= 1 and num) or num + 6
|
||||
num = (num <= 6 and num) or num - 6
|
||||
minetest.swap_node(pos, {name = node_name.."_plate_"..num})
|
||||
end
|
||||
minetest.register_node(node_name.."_plate_"..i, override_table(def, override_cable_plate))
|
||||
cable_tier[node_name.."_plate_"..i] = tier
|
||||
end
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name.."_plate_1 5",
|
||||
recipe = {
|
||||
{"" , "" , node_name},
|
||||
{node_name, node_name, node_name},
|
||||
{"" , "" , node_name},
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = node_name,
|
||||
recipe = {
|
||||
{node_name.."_plate_1"},
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
minetest.register_on_mods_loaded(function()
|
||||
-- FIXME: Move this to register.lua or somewhere else where register_on_mods_loaded is not required.
|
||||
-- Possible better option would be to inject these when machine is registered in register.lua.
|
||||
for name, tiers in pairs(technic.machine_tiers) do
|
||||
local nodedef = minetest.registered_nodes[name]
|
||||
local on_construct = type(nodedef.on_construct) == "function" and nodedef.on_construct
|
||||
local on_destruct = type(nodedef.on_destruct) == "function" and nodedef.on_destruct
|
||||
minetest.override_item(name,{
|
||||
on_construct = on_construct
|
||||
and function(pos) on_construct(pos) place_network_node(pos, tiers, name) end
|
||||
or function(pos) place_network_node(pos, tiers, name) end,
|
||||
on_destruct = on_destruct
|
||||
and function(pos) on_destruct(pos) remove_network_node(pos, tiers, name) end
|
||||
or function(pos) remove_network_node(pos, tiers, name) end,
|
||||
})
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,8 @@
|
||||
local S = technic.getter
|
||||
|
||||
function technic.register_centrifuge(data)
|
||||
data.typename = "separating"
|
||||
data.machine_name = "centrifuge"
|
||||
data.machine_desc = S("%s Centrifuge")
|
||||
technic.register_base_machine(data)
|
||||
end
|
||||
@@ -0,0 +1,48 @@
|
||||
local S = technic.getter
|
||||
|
||||
technic.register_recipe_type("separating", {
|
||||
description = S("Separating"),
|
||||
output_size = 2,
|
||||
})
|
||||
|
||||
function technic.register_separating_recipe(data)
|
||||
data.time = data.time or 10
|
||||
technic.register_recipe("separating", data)
|
||||
end
|
||||
|
||||
local recipes = {
|
||||
{ "technic:bronze_dust 8", "technic:copper_dust 7", "technic:tin_dust" },
|
||||
{ "technic:stainless_steel_dust 5", "technic:wrought_iron_dust 4", "technic:chromium_dust" },
|
||||
{ "technic:brass_dust 3", "technic:copper_dust 2", "technic:zinc_dust" },
|
||||
{ "technic:chernobylite_dust", "default:sand", "technic:uranium3_dust" },
|
||||
{ "default:dirt 4", "default:sand", "default:gravel", "default:clay_lump 4" },
|
||||
}
|
||||
|
||||
local function uranium_dust(p)
|
||||
return "technic:uranium"..(p == 7 and "" or p).."_dust"
|
||||
end
|
||||
for p = 1, 34 do
|
||||
table.insert(recipes, { uranium_dust(p).." 2", uranium_dust(p-1), uranium_dust(p+1) })
|
||||
end
|
||||
|
||||
if minetest.get_modpath("bushes_classic") then
|
||||
for _, berry in ipairs({ "blackberry", "blueberry", "gooseberry", "raspberry", "strawberry" }) do
|
||||
table.insert(recipes, { "bushes:"..berry.."_bush", "default:stick 20", "bushes:"..berry.." 4" })
|
||||
end
|
||||
end
|
||||
|
||||
if minetest.get_modpath("farming") then
|
||||
if minetest.get_modpath("cottages") then
|
||||
-- work as a mechanized threshing floor
|
||||
table.insert(recipes, { "farming:wheat", "farming:seed_wheat", "cottages:straw_mat" })
|
||||
table.insert(recipes, { "farming:barley", "farming:seed_barley", "cottages:straw_mat" })
|
||||
else
|
||||
-- work in a less fancy and less efficient manner
|
||||
table.insert(recipes, { "farming:wheat 4", "farming:seed_wheat 3", "default:dry_shrub 1" })
|
||||
table.insert(recipes, { "farming:barley 4", "farming:seed_barley 3", "default:dry_shrub 1" })
|
||||
end
|
||||
end
|
||||
|
||||
for _, data in pairs(recipes) do
|
||||
technic.register_separating_recipe({ input = { data[1] }, output = { data[2], data[3], data[4] } })
|
||||
end
|
||||
@@ -0,0 +1,211 @@
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
-- handles the machine upgrades every tick
|
||||
function technic.handle_machine_upgrades(meta)
|
||||
-- Get the names of the upgrades
|
||||
local inv = meta:get_inventory()
|
||||
|
||||
local srcstack = inv:get_stack("upgrade1", 1)
|
||||
local upg_item1 = srcstack and srcstack:get_name()
|
||||
|
||||
srcstack = inv:get_stack("upgrade2", 1)
|
||||
local upg_item2 = srcstack and srcstack:get_name()
|
||||
|
||||
-- Save some power by installing battery upgrades.
|
||||
-- Tube loading speed can be upgraded using control logic units.
|
||||
local EU_upgrade = 0
|
||||
local tube_upgrade = 0
|
||||
|
||||
if upg_item1 == "technic:control_logic_unit" then
|
||||
tube_upgrade = tube_upgrade + 1
|
||||
elseif upg_item1 == "technic:battery" then
|
||||
EU_upgrade = EU_upgrade + 1
|
||||
end
|
||||
|
||||
if upg_item2 == "technic:control_logic_unit" then
|
||||
tube_upgrade = tube_upgrade + 1
|
||||
elseif upg_item2 == "technic:battery" then
|
||||
EU_upgrade = EU_upgrade + 1
|
||||
end
|
||||
|
||||
return EU_upgrade, tube_upgrade
|
||||
end
|
||||
|
||||
-- handles the machine upgrades when set or removed
|
||||
local function on_machine_upgrade(meta, stack)
|
||||
local stack_name = stack:get_name()
|
||||
if stack_name == "default:chest" then
|
||||
meta:set_int("public", 1)
|
||||
return 1
|
||||
elseif stack_name ~= "technic:control_logic_unit"
|
||||
and stack_name ~= "technic:battery" then
|
||||
return 0
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
-- something is about to be removed
|
||||
local function on_machine_downgrade(meta, stack, list)
|
||||
if stack:get_name() == "default:chest" then
|
||||
local inv = meta:get_inventory()
|
||||
local upg1, upg2 = inv:get_stack("upgrade1", 1), inv:get_stack("upgrade2", 1)
|
||||
|
||||
-- only set 0 if theres not a nother chest in the other list too
|
||||
if (not upg1 or not upg2 or upg1:get_name() ~= upg2:get_name()) then
|
||||
meta:set_int("public", 0)
|
||||
end
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
|
||||
function technic.send_items(pos, x_velocity, z_velocity, output_name)
|
||||
-- Send items on their way in the pipe system.
|
||||
if output_name == nil then
|
||||
output_name = "dst"
|
||||
end
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local i = 0
|
||||
for _, stack in ipairs(inv:get_list(output_name)) do
|
||||
i = i + 1
|
||||
if stack then
|
||||
local item0 = stack:to_table()
|
||||
if item0 then
|
||||
item0["count"] = 1
|
||||
technic.tube_inject_item(pos, pos, vector.new(x_velocity, 0, z_velocity), item0)
|
||||
stack:take_item(1)
|
||||
inv:set_stack(output_name, i, stack)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- FIXME: This funtion is never used anywhere, what is it for?
|
||||
function technic.smelt_item(meta, result, speed)
|
||||
local inv = meta:get_inventory()
|
||||
meta:set_int("cook_time", meta:get_int("cook_time") + 1)
|
||||
if meta:get_int("cook_time") < result.time / speed then
|
||||
return
|
||||
end
|
||||
local afterfuel
|
||||
result, afterfuel = minetest.get_craft_result({method = "cooking", width = 1, items = inv:get_list("src")})
|
||||
|
||||
if result and result.item then
|
||||
meta:set_int("cook_time", 0)
|
||||
-- check if there's room for output in "dst" list
|
||||
if inv:room_for_item("dst", result.item) then
|
||||
inv:set_stack("src", 1, afterfuel.items[1])
|
||||
inv:add_item("dst", result.item)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function technic.handle_machine_pipeworks(pos, tube_upgrade, send_function)
|
||||
if send_function == nil then
|
||||
send_function = technic.send_items
|
||||
end
|
||||
|
||||
local node = minetest.get_node(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local pos1 = vector.new(pos)
|
||||
local x_velocity = 0
|
||||
local z_velocity = 0
|
||||
|
||||
-- Output is on the left side of the furnace
|
||||
if node.param2 == 3 then pos1.z = pos1.z - 1 z_velocity = -1 end
|
||||
if node.param2 == 2 then pos1.x = pos1.x - 1 x_velocity = -1 end
|
||||
if node.param2 == 1 then pos1.z = pos1.z + 1 z_velocity = 1 end
|
||||
if node.param2 == 0 then pos1.x = pos1.x + 1 x_velocity = 1 end
|
||||
|
||||
local output_tube_connected = false
|
||||
local node1 = minetest.get_node(pos1)
|
||||
if minetest.get_item_group(node1.name, "tubedevice") > 0 then
|
||||
output_tube_connected = true
|
||||
end
|
||||
local tube_time = meta:get_int("tube_time") + tube_upgrade
|
||||
if tube_time >= 2 then
|
||||
tube_time = 0
|
||||
if output_tube_connected then
|
||||
send_function(pos, x_velocity, z_velocity)
|
||||
end
|
||||
end
|
||||
meta:set_int("tube_time", tube_time)
|
||||
end
|
||||
|
||||
function technic.machine_can_dig(pos, player)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
if not inv:is_empty("src") or not inv:is_empty("dst") then
|
||||
if player then
|
||||
minetest.chat_send_player(player:get_player_name(),
|
||||
S("Machine cannot be removed because it is not empty"))
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function technic.machine_after_dig_node(pos, oldnode, oldmetadata, player)
|
||||
if oldmetadata.inventory then
|
||||
if oldmetadata.inventory.upgrade1 and oldmetadata.inventory.upgrade1[1] then
|
||||
local stack = ItemStack(oldmetadata.inventory.upgrade1[1])
|
||||
if not stack:is_empty() then
|
||||
minetest.add_item(pos, stack)
|
||||
end
|
||||
end
|
||||
if oldmetadata.inventory.upgrade2 and oldmetadata.inventory.upgrade2[1] then
|
||||
local stack = ItemStack(oldmetadata.inventory.upgrade2[1])
|
||||
if not stack:is_empty() then
|
||||
minetest.add_item(pos, stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if minetest.registered_nodes[oldnode.name].tube then
|
||||
pipeworks.after_dig(pos, oldnode, oldmetadata, player)
|
||||
end
|
||||
end
|
||||
|
||||
local function inv_change(pos, player, count, from_list, to_list, stack)
|
||||
local playername = player:get_player_name()
|
||||
local meta = minetest.get_meta(pos);
|
||||
local public = (meta:get_int("public") == 1)
|
||||
local to_upgrade = to_list == "upgrade1" or to_list == "upgrade2"
|
||||
local from_upgrade = from_list == "upgrade1" or from_list == "upgrade2"
|
||||
|
||||
if (not public or to_upgrade or from_upgrade) and minetest.is_protected(pos, playername) then
|
||||
minetest.chat_send_player(playername, S("Inventory move disallowed due to protection"))
|
||||
return 0
|
||||
end
|
||||
if to_upgrade then
|
||||
-- only place a single item into it, if it's empty
|
||||
local empty = meta:get_inventory():is_empty(to_list)
|
||||
if empty then
|
||||
return on_machine_upgrade(meta, stack)
|
||||
end
|
||||
return 0
|
||||
elseif from_upgrade then
|
||||
-- only called on take (not move)
|
||||
on_machine_downgrade(meta, stack, from_list)
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
function technic.machine_inventory_put(pos, listname, index, stack, player)
|
||||
return inv_change(pos, player, stack:get_count(), nil, listname, stack)
|
||||
end
|
||||
|
||||
function technic.machine_inventory_take(pos, listname, index, stack, player)
|
||||
return inv_change(pos, player, stack:get_count(), listname, nil, stack)
|
||||
end
|
||||
|
||||
function technic.machine_inventory_move(pos, from_list, from_index,
|
||||
to_list, to_index, count, player)
|
||||
local stack = minetest.get_meta(pos):get_inventory():get_stack(from_list, from_index)
|
||||
return inv_change(pos, player, count, from_list, to_list, stack)
|
||||
end
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
function technic.register_compressor(data)
|
||||
data.typename = "compressing"
|
||||
data.machine_name = "compressor"
|
||||
data.machine_desc = S("%s Compressor")
|
||||
technic.register_base_machine(data)
|
||||
end
|
||||
@@ -0,0 +1,54 @@
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
technic.register_recipe_type("compressing", { description = S("Compressing") })
|
||||
|
||||
function technic.register_compressor_recipe(data)
|
||||
data.time = data.time or 4
|
||||
technic.register_recipe("compressing", data)
|
||||
end
|
||||
|
||||
local recipes = {
|
||||
{"default:snowblock", "default:ice"},
|
||||
{"default:sand 2", "default:sandstone"},
|
||||
{"default:desert_sand 2", "default:desert_sandstone"},
|
||||
{"default:silver_sand 2", "default:silver_sandstone"},
|
||||
{"default:desert_sandstone", "default:desert_stone"},
|
||||
{"technic:mixed_metal_ingot", "technic:composite_plate"},
|
||||
{"default:copper_ingot 5", "technic:copper_plate"},
|
||||
{"technic:coal_dust 4", "technic:graphite"},
|
||||
{"technic:carbon_cloth", "technic:carbon_plate"},
|
||||
{"technic:uranium35_ingot 5", "technic:uranium_fuel"},
|
||||
{"technic:graphite 25", "default:diamond"}
|
||||
}
|
||||
|
||||
if minetest.get_modpath("ethereal") then
|
||||
-- the density of charcoal is ~1/10 of coal, otherwise it's pure carbon
|
||||
table.insert(recipes, {"ethereal:charcoal_lump 10", "default:coal_lump 1"})
|
||||
end
|
||||
|
||||
|
||||
-- defuse the default sandstone recipe, since we have the compressor to take over in a more realistic manner
|
||||
minetest.clear_craft({
|
||||
recipe = {
|
||||
{"default:sand", "default:sand"},
|
||||
{"default:sand", "default:sand"},
|
||||
},
|
||||
})
|
||||
minetest.clear_craft({
|
||||
recipe = {
|
||||
{"default:desert_sand", "default:desert_sand"},
|
||||
{"default:desert_sand", "default:desert_sand"},
|
||||
},
|
||||
})
|
||||
minetest.clear_craft({
|
||||
recipe = {
|
||||
{"default:silver_sand", "default:silver_sand"},
|
||||
{"default:silver_sand", "default:silver_sand"},
|
||||
},
|
||||
})
|
||||
|
||||
for _, data in pairs(recipes) do
|
||||
technic.register_compressor_recipe({input = {data[1]}, output = data[2]})
|
||||
end
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
function technic.register_electric_furnace(data)
|
||||
data.typename = "cooking"
|
||||
data.machine_name = "electric_furnace"
|
||||
data.machine_desc = S("%s Furnace")
|
||||
technic.register_base_machine(data)
|
||||
end
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
local S = technic.getter
|
||||
|
||||
function technic.register_extractor(data)
|
||||
data.typename = "extracting"
|
||||
data.machine_name = "extractor"
|
||||
data.machine_desc = S("%s Extractor")
|
||||
technic.register_base_machine(data)
|
||||
end
|
||||
Loaded 100 of 4811 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user