Add mods: technic, moreores, paintings, Nyancat (Pbj_pup). Small fix: sandwiches

This commit is contained in:
N-Nachtigal 2025-06-05 16:15:56 +02:00
parent 15e8e696a2
commit fb09deddc1
1404 changed files with 156555 additions and 211 deletions

View file

@ -0,0 +1,178 @@
Technic
-----------------
A mod for [minetest](http://www.minetest.net)
[![mtt](https://github.com/mt-mods/technic/actions/workflows/mtt.yml/badge.svg)](https://github.com/mt-mods/technic/actions/workflows/mtt.yml?query=branch%3Amaster)
[![luacheck](https://github.com/mt-mods/technic/actions/workflows/luacheck.yml/badge.svg)](https://github.com/mt-mods/technic/actions/workflows/luacheck.yml?query=branch%3Amaster)
[![mineunit](https://github.com/mt-mods/technic/actions/workflows/mineunit.yml/badge.svg)](https://github.com/mt-mods/technic/actions/workflows/mineunit.yml?query=branch%3Amaster)
[![mineunit](https://byob.yarr.is/mt-mods/technic/coverage)](https://github.com/mt-mods/technic/actions/workflows/mineunit.yml?query=branch%3Amaster+is%3Asuccess)
[![License](https://img.shields.io/badge/license-LGPLv2.0%2B-purple.svg)](https://www.gnu.org/licenses/old-licenses/lgpl-2.0.en.html)
[![ContentDB](https://content.minetest.net/packages/mt-mods/technic_plus/shields/downloads/)](https://content.minetest.net/packages/mt-mods/technic_plus/)
# Overview
<img src="./technic/doc/images/Technic Screenshot.png"/>
The technic modpack extends the Minetest game with many new elements,
mainly constructable machines and tools. It is a large modpack, and
tends to dominate gameplay when it is used. This manual describes how
to use the technic modpack, mainly from a player's perspective.
The technic modpack depends on some other modpacks:
* the basic Minetest game
* mesecons, which supports the construction of logic systems based on
signaling elements
* pipeworks, which supports the automation of item transport
* moreores, which provides some additional ore types
* basic_materials, which provides some basic craft items
This manual doesn't explain how to use these other modpacks, which have
their own manuals:
* [Minetest Game Documentation](https://wiki.minetest.net/Main_Page)
* [Mesecons Documentation](http://mesecons.net/items.html)
* [Pipeworks Documentation](https://github.com/mt-mods/pipeworks/-/wikis/home)
* [Moreores Forum Post](https://forum.minetest.net/viewtopic.php?t=549)
* [Basic materials Repository](https://github.com/mt-mods/basic_materials)
Recipes for constructable items in technic are generally not guessable,
and are also not specifically documented here. You should use a
craft guide mod to look up the recipes in-game. For the best possible
guidance, use the unified\_inventory mod, with which technic registers
its specialised recipe types.
# Documentation
In-game:
* [Resources](./technic/doc/resources.md)
* [Substances](./technic/doc/substances.md)
* [Processes](./technic/doc/processes.md)
* [Chests](./technic/doc/chests.md)
* [Radioactivity](./technic/doc/radioactivity.md)
* [Electrical power](./technic/doc/power.md)
* [Powered machines](./technic/doc/machines.md)
* [Generators](./technic/doc/generators.md)
* [Forceload anchor](./technic/doc/anchor.md)
* [Digilines](./technic/doc/digilines.md)
* [Mesecons](./technic/doc/mesecons.md)
* [Tools](./technic/doc/tools.md)
Mod development:
* [Api](./technic/doc/api.md)
subjects missing from this manual:
* frames
* templates
## FAQ
1. My technic circuit doesn't work. No power is distributed.
* A: Make sure you have a switching station connected.
# Notes
This is a maintained fork of https://github.com/minetest-mods/technic with various enhancements.
Suitable for multiplayer environments.
* Chainsaw and HV Quarry re-implementation (@OgelGames)
* Switching station lag/polyfuse and globalstep execution (@BuckarooBanzay)
* No forceload hacks
* Additional HV machines (@h-v-smacker)
* LV, MV, and HV digiline cables (@S-S-X and @SwissalpS)
* Chests with digilines and more complete user interface
* Most of network code rewritten
* Many bugs that allowed cheating fixed
* CNC machine with pipeworks, upgrades and digiline support
* Better performance
* various others...
## Compatibility
This mod is meant as a **drop-in replacement** for the upstream `technic` mod.
It also provides some additional machines and items, notably:
* HV Grinder, Furnace, and Compressor
* LV Lamp
* LV, MV, and HV Digiline cables
Note that the `wrench` mod has been separated from the modpack. It can now be found at [mt-mods/wrench](https://github.com/mt-mods/wrench).
# Recommended mods
Dependencies:
* https://github.com/minetest-mods/mesecons
* https://github.com/minetest-mods/moreores
* https://github.com/mt-mods/pipeworks
* https://github.com/mt-mods/basic_materials
Recommended optional Dependencies:
* https://github.com/minetest-mods/digilines
Recommended mods that build on the `technic mod`:
* https://github.com/mt-mods/jumpdrive
* https://github.com/OgelGames/powerbanks
# Settings (worldpath/technic.conf)
| Configuration key | Description
|----------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| enable_mining_drill | |
| enable_mining_laser | |
| enable_flashlight | |
| enable_wind_mill | |
| enable_corium_griefing | |
| enable_radiation_protection | |
| enable_radiation_throttling | enable lag- and per-second-throttling of radiation damage |
| enable_entity_radiation_damage | |
| enable_longterm_radiation_damage | |
| enable_nuclear_reactor_digiline_selfdestruct | |
| admin_priv | Privileges required to use administrative chat commands like cache flushing and enabling/disabling machines globally. |
| quarry_max_depth | max depth of the quarry. |
| quarry_time_limit | max cpu time in μs allowed per quarry step. |
| quarry_dig_particles | Enables particle effect with the quarry digs a node. |
| network_overload_reset_time | After network conflict wait this many seconds before attempting to activate conflicting networks again. |
| switch_off_delay_seconds | switching station off delay. |
See defaults for settings here: [technic/config.lua](./technic/config.lua)
See configuration for CNC machines here: [technic_cnc/README.md](./technic_cnc/README.md)
# Chat commands
* **/technic_flush_switch_cache** clears the switching station cache (stops all unloaded switches)
* **/powerctrl [on|off]** enable/disable technic power distribution globally
* **/technic_get_active_networks [minlag]** list all active networks with additional network data
* **/technic_clear_network_data** removes all networks and network nodes from the cache
# Contributors
* kpoppel
* Nekogloop
* Nore/Ekdohibs
* ShadowNinja
* VanessaE
* BuckarooBanzay
* OgelGames
* int-ua
* S-S-X
* H-V-Smacker
* groxxda
* SwissalpS
* And many others...
# License
Unless otherwise stated, all components of this modpack are licensed under the
LGPL, V2 or later. See also the individual mod folders for their
secondary/alternate licenses, if any.

View file

@ -0,0 +1,437 @@
-- Minetest 0.4.6 mod: extranodes
-- namespace: technic
local S = minetest.get_translator(minetest.get_current_modname())
if minetest.get_modpath("moreblocks") then
-- register stairsplus/circular_saw nodes
-- we skip blast resistant concrete and uranium intentionally
-- chrome seems to be too hard of a metal to be actually sawable
stairsplus:register_all("technic", "marble", "technic:marble", {
description=S("Marble"),
groups={cracky=3, not_in_creative_inventory=1},
tiles={"technic_marble.png"},
})
stairsplus:register_all("technic", "marble_bricks", "technic:marble_bricks", {
description=S("Marble Bricks"),
groups={cracky=3, not_in_creative_inventory=1},
tiles={"technic_marble_bricks.png"},
})
stairsplus:register_all("technic", "granite", "technic:granite", {
description=S("Granite"),
groups={cracky=1, not_in_creative_inventory=1},
tiles={"technic_granite.png"},
})
stairsplus:register_all("technic", "granite_bricks", "technic:granite_bricks", {
description=S("Granite Bricks"),
groups={cracky=1, not_in_creative_inventory=1},
tiles={"technic_granite_bricks.png"},
})
stairsplus:register_all("technic", "concrete", "basic_materials:concrete_block", {
description=S("Concrete"),
groups={cracky=3, not_in_creative_inventory=1},
tiles={"basic_materials_concrete_block.png"},
})
stairsplus:register_all("technic", "zinc_block", "technic:zinc_block", {
description=S("Zinc Block"),
groups={cracky=1, not_in_creative_inventory=1},
tiles={"technic_zinc_block.png"},
})
stairsplus:register_all("technic", "cast_iron_block", "technic:cast_iron_block", {
description=S("Cast Iron Block"),
groups={cracky=1, not_in_creative_inventory=1},
tiles={"technic_cast_iron_block.png"},
})
stairsplus:register_all("technic", "carbon_steel_block", "technic:carbon_steel_block", {
description=S("Carbon Steel Block"),
groups={cracky=1, not_in_creative_inventory=1},
tiles={"technic_carbon_steel_block.png"},
})
stairsplus:register_all("technic", "stainless_steel_block", "technic:stainless_steel_block", {
description=S("Stainless Steel Block"),
groups={cracky=1, not_in_creative_inventory=1},
tiles={"technic_stainless_steel_block.png"},
})
stairsplus:register_all("technic", "blast_resistant_concrete", "technic:blast_resistant_concrete", {
description = S("Blast-resistant Concrete"),
tiles = {"technic_blast_resistant_concrete_block.png",},
groups = {cracky = 1, level = 3, concrete = 1},
on_blast = function(pos, intensity)
if intensity > 3 then
minetest.remove_node(pos)
minetest.add_item(pos, "technic:blast_resistant_concrete")
end
end
})
-- FIXME: Clean this function up somehow
local function register_technic_stairs_alias(modname, origname, newmod, newname)
minetest.register_alias(modname .. ":slab_" .. origname, newmod..":slab_" .. newname)
minetest.register_alias(modname .. ":slab_" .. origname ..
"_inverted", newmod..":slab_" .. newname .. "_inverted")
minetest.register_alias(modname .. ":slab_" .. origname .. "_wall", newmod..":slab_" .. newname .. "_wall")
minetest.register_alias(modname .. ":slab_" .. origname ..
"_quarter", newmod..":slab_" .. newname .. "_quarter")
minetest.register_alias(modname .. ":slab_" .. origname ..
"_quarter_inverted", newmod..":slab_" .. newname .. "_quarter_inverted")
minetest.register_alias(modname .. ":slab_" .. origname ..
"_quarter_wall", newmod..":slab_" .. newname .. "_quarter_wall")
minetest.register_alias(modname .. ":slab_" .. origname ..
"_three_quarter", newmod..":slab_" .. newname .. "_three_quarter")
minetest.register_alias(modname .. ":slab_" .. origname ..
"_three_quarter_inverted", newmod..":slab_" .. newname .. "_three_quarter_inverted")
minetest.register_alias(modname .. ":slab_" .. origname ..
"_three_quarter_wall", newmod..":slab_" .. newname .. "_three_quarter_wall")
minetest.register_alias(modname .. ":stair_" .. origname, newmod..":stair_" .. newname)
minetest.register_alias(modname .. ":stair_" .. origname ..
"_inverted", newmod..":stair_" .. newname .. "_inverted")
minetest.register_alias(modname .. ":stair_" .. origname .. "_wall", newmod..":stair_" .. newname .. "_wall")
minetest.register_alias(modname .. ":stair_" .. origname ..
"_wall_half", newmod..":stair_" .. newname .. "_wall_half")
minetest.register_alias(modname .. ":stair_" .. origname ..
"_wall_half_inverted", newmod..":stair_" .. newname .. "_wall_half_inverted")
minetest.register_alias(modname .. ":stair_" .. origname .. "_half", newmod..":stair_" .. newname .. "_half")
minetest.register_alias(modname .. ":stair_" .. origname ..
"_half_inverted", newmod..":stair_" .. newname .. "_half_inverted")
minetest.register_alias(modname .. ":stair_" .. origname ..
"_right_half", newmod..":stair_" .. newname .. "_right_half")
minetest.register_alias(modname .. ":stair_" .. origname ..
"_right_half_inverted", newmod..":stair_" .. newname .. "_right_half_inverted")
minetest.register_alias(modname .. ":stair_" .. origname ..
"_wall_half", newmod..":stair_" .. newname .. "_wall_half")
minetest.register_alias(modname .. ":stair_" .. origname ..
"_wall_half_inverted", newmod..":stair_" .. newname .. "_wall_half_inverted")
minetest.register_alias(modname .. ":stair_" .. origname .. "_inner", newmod..":stair_" .. newname .. "_inner")
minetest.register_alias(modname .. ":stair_" .. origname ..
"_inner_inverted", newmod..":stair_" .. newname .. "_inner_inverted")
minetest.register_alias(modname .. ":stair_" .. origname .. "_outer", newmod..":stair_" .. newname .. "_outer")
minetest.register_alias(modname .. ":stair_" .. origname ..
"_outer_inverted", newmod..":stair_" .. newname .. "_outer_inverted")
minetest.register_alias(modname .. ":panel_" .. origname ..
"_bottom", newmod..":panel_" .. newname .. "_bottom")
minetest.register_alias(modname .. ":panel_" .. origname .. "_top", newmod..":panel_" .. newname .. "_top")
minetest.register_alias(modname .. ":panel_" .. origname ..
"_vertical", newmod..":panel_" .. newname .. "_vertical")
minetest.register_alias(modname .. ":micro_" .. origname ..
"_bottom", newmod..":micro_" .. newname .. "_bottom")
minetest.register_alias(modname .. ":micro_" .. origname .. "_top", newmod..":micro_" .. newname .. "_top")
end
register_technic_stairs_alias("stairsplus", "concrete", "technic", "concrete")
register_technic_stairs_alias("stairsplus", "marble", "technic", "marble")
register_technic_stairs_alias("stairsplus", "granite", "technic", "granite")
register_technic_stairs_alias("stairsplus", "marble_bricks", "technic", "marble_bricks")
end
local iclip_def = {
description = S("Insulator/cable clip"),
drawtype = "mesh",
mesh = "technic_insulator_clip.obj",
tiles = {"technic_insulator_clip.png"},
paramtype = "light",
is_ground_content = false,
groups = {choppy=1, snappy=1, oddly_breakable_by_hand=1 },
sounds = default.node_sound_stone_defaults(),
}
local iclipfence_def = {
description = S("Insulator/cable clip"),
tiles = {"technic_insulator_clip.png"},
is_ground_content = false,
paramtype = "light",
drawtype = "nodebox",
node_box = {
type = "connected",
fixed = {
{ -0.25, 0.75, -0.25, 0.25, 1.25, 0.25 }, -- the clip on top
{ -0.125, 0.6875, -0.125, 0.125, 0.75, 0.125 },
{ -0.1875, 0.625, -0.1875, 0.1875, 0.6875, 0.1875 },
{ -0.125, 0.5625, -0.125, 0.125, 0.625, 0.125 },
{ -0.1875, 0.5, -0.1875, 0.1875, 0.5625, 0.1875 },
{ -0.125, 0.4375, -0.125, 0.125, 0.5, 0.125 },
{ -0.1875, 0.375, -0.1875, 0.1875, 0.4375, 0.1875 },
{ -0.125, -0.5, -0.125, 0.125, 0.375, 0.125 }, -- the post, slightly short
},
-- connect_top =
-- connect_bottom =
connect_front = {{-1/16,3/16,-1/2,1/16,5/16,-1/8},
{-1/16,-5/16,-1/2,1/16,-3/16,-1/8}},
connect_left = {{-1/2,3/16,-1/16,-1/8,5/16,1/16},
{-1/2,-5/16,-1/16,-1/8,-3/16,1/16}},
connect_back = {{-1/16,3/16,1/8,1/16,5/16,1/2},
{-1/16,-5/16,1/8,1/16,-3/16,1/2}},
connect_right = {{1/8,3/16,-1/16,1/2,5/16,1/16},
{1/8,-5/16,-1/16,1/2,-3/16,1/16}},
},
connects_to = {"group:fence", "group:wood", "group:tree"},
groups = {fence=1, choppy=1, snappy=1, oddly_breakable_by_hand=1 },
sounds = default.node_sound_stone_defaults(),
}
local sclip_tex = {
"technic_insulator_clip.png",
{ name = "strut.png^technic_steel_strut_overlay.png", color = "white" },
{ name = "strut.png", color = "white" }
}
local streetsmod = minetest.get_modpath("streets") or minetest.get_modpath ("steelsupport")
-- cheapie's fork breaks it into several individual mods, with differernt names for the same content.
if streetsmod then
sclip_tex = {
"technic_insulator_clip.png",
{ name = "streets_support.png^technic_steel_strut_overlay.png", color = "white" },
{ name = "streets_support.png", color = "white" }
}
end
local sclip_def = {
description = S("Steel strut with insulator/cable clip"),
drawtype = "mesh",
mesh = "technic_steel_strut_with_insulator_clip.obj",
tiles = sclip_tex,
paramtype = "light",
paramtype2 = "wallmounted",
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
groups = { choppy=1, cracky=1 },
backface_culling = false
}
if minetest.get_modpath("unifieddyes") then
iclip_def.paramtype2 = "colorwallmounted"
iclip_def.palette = "unifieddyes_palette_colorwallmounted.png"
iclip_def.after_place_node = function(pos, placer, itemstack, pointed_thing)
unifieddyes.fix_rotation(pos, placer, itemstack, pointed_thing)
end
iclip_def.groups = {choppy=1, snappy=1, oddly_breakable_by_hand=1, ud_param2_colorable = 1}
iclip_def.on_dig = unifieddyes.on_dig
iclipfence_def.paramtype2 = "color"
iclipfence_def.palette = "unifieddyes_palette_extended.png"
iclipfence_def.on_construct = unifieddyes.on_construct
iclipfence_def.groups = {fence=1, choppy=1, snappy=1, oddly_breakable_by_hand=1, ud_param2_colorable = 1}
iclipfence_def.on_dig = unifieddyes.on_dig
sclip_def.paramtype2 = "colorwallmounted"
sclip_def.palette = "unifieddyes_palette_colorwallmounted.png"
sclip_def.after_place_node = function(pos, placer, itemstack, pointed_thing)
unifieddyes.fix_rotation(pos, placer, itemstack, pointed_thing)
end
sclip_def.on_dig = unifieddyes.on_dig
sclip_def.groups = {choppy=1, cracky=1, ud_param2_colorable = 1}
end
minetest.register_node(":technic:insulator_clip", iclip_def)
minetest.register_node(":technic:insulator_clip_fencepost", iclipfence_def)
minetest.register_craft({
output = "technic:insulator_clip",
recipe = {
{ "", "dye:white", ""},
{ "", "technic:raw_latex", ""},
{ "technic:raw_latex", "default:stone", "technic:raw_latex"},
}
})
minetest.register_craft({
output = "technic:insulator_clip_fencepost 2",
recipe = {
{ "", "dye:white", ""},
{ "", "technic:raw_latex", ""},
{ "technic:raw_latex", "default:fence_wood", "technic:raw_latex"},
}
})
local steelmod = minetest.get_modpath("steel")
if streetsmod or steelmod then
minetest.register_node(":technic:steel_strut_with_insulator_clip", sclip_def)
if steelmod then
minetest.register_craft({
output = "technic:steel_strut_with_insulator_clip",
recipe = {
{"technic:insulator_clip_fencepost"},
{"steel:strut_mount"}
}
})
minetest.register_craft({
output = "technic:steel_strut_with_insulator_clip",
recipe = {
{"technic:insulator_clip_fencepost", "" },
{"steel:strut", "default:steel_ingot" },
}
})
elseif streetsmod then
minetest.register_craft({
output = "technic:steel_strut_with_insulator_clip",
recipe = {
{"technic:insulator_clip_fencepost", "" },
{"streets:steel_support", "default:steel_ingot" },
}
})
end
end
if minetest.get_modpath("unifieddyes") then
unifieddyes.register_color_craft({
output = "technic:insulator_clip_fencepost",
palette = "extended",
type = "shapeless",
neutral_node = "technic:insulator_clip_fencepost",
recipe = {
"NEUTRAL_NODE",
"MAIN_DYE"
}
})
unifieddyes.register_color_craft({
output = "technic:insulator_clip",
palette = "wallmounted",
type = "shapeless",
neutral_node = "technic:insulator_clip",
recipe = {
"NEUTRAL_NODE",
"MAIN_DYE"
}
})
unifieddyes.register_color_craft({
output = "technic:steel_strut_with_insulator_clip",
palette = "wallmounted",
type = "shapeless",
neutral_node = "",
recipe = {
"technic:steel_strut_with_insulator_clip",
"MAIN_DYE"
}
})
if steelmod then
unifieddyes.register_color_craft({
output = "technic:steel_strut_with_insulator_clip",
palette = "wallmounted",
neutral_node = "",
recipe = {
{ "technic:insulator_clip_fencepost", "MAIN_DYE" },
{ "steel:strut_mount", "" },
}
})
end
if streetsmod then
unifieddyes.register_color_craft({
output = "technic:steel_strut_with_insulator_clip",
palette = "wallmounted",
neutral_node = "technic:steel_strut_with_insulator_clip",
recipe = {
{ "technic:insulator_clip_fencepost", "MAIN_DYE" },
{ "streets:steel_support", "default:steel_ingot" },
}
})
end
end
for i = 0, 31 do
minetest.register_alias("technic:concrete_post"..i,
"technic:concrete_post")
end
for i = 32, 63 do
minetest.register_alias("technic:concrete_post"..i,
"technic:concrete_post_with_platform")
end
minetest.register_craft({
output = 'technic:concrete_post_platform 6',
recipe = {
{'basic_materials:concrete_block','technic:concrete_post','basic_materials:concrete_block'},
}
})
minetest.register_craft({
output = 'technic:concrete_post 12',
recipe = {
{'basic_materials:concrete_block','basic_materials:steel_bar','basic_materials:concrete_block'},
{'basic_materials:concrete_block','basic_materials:steel_bar','basic_materials:concrete_block'},
{'basic_materials:concrete_block','basic_materials:steel_bar','basic_materials:concrete_block'},
}
})
local box_platform = {-0.5, 0.3, -0.5, 0.5, 0.5, 0.5}
local box_post = {-0.15, -0.5, -0.15, 0.15, 0.5, 0.15}
local box_front = {-0.1, -0.3, -0.5, 0.1, 0.3, 0}
local box_back = {-0.1, -0.3, 0, 0.1, 0.3, 0.5}
local box_left = {-0.5, -0.3, -0.1, 0, 0.3, 0.1}
local box_right = {0, -0.3, -0.1, 0.5, 0.3, 0.1}
minetest.register_node(":technic:concrete_post_platform", {
description = S("Concrete Post Platform"),
tiles = {"basic_materials_concrete_block.png",},
groups={cracky=1, level=2},
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
paramtype = "light",
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {box_platform}
},
on_place = function (itemstack, placer, pointed_thing)
local node = minetest.get_node(pointed_thing.under)
if node.name ~= "technic:concrete_post" then
return minetest.item_place_node(itemstack, placer, pointed_thing)
end
minetest.set_node(pointed_thing.under, {name="technic:concrete_post_with_platform"})
itemstack:take_item()
placer:set_wielded_item(itemstack)
return itemstack
end,
})
for platform = 0, 1 do
local after_dig_node = nil
if platform == 1 then
after_dig_node = function(pos, old_node)
old_node.name = "technic:concrete_post"
minetest.set_node(pos, old_node)
end
end
minetest.register_node(":technic:concrete_post"..(platform == 1 and "_with_platform" or ""), {
description = S("Concrete Post"),
tiles = {"basic_materials_concrete_block.png"},
groups = {cracky=1, level=2, concrete_post=1, not_in_creative_inventory=platform},
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
drop = (platform == 1 and "technic:concrete_post_platform" or
"technic:concrete_post"),
paramtype = "light",
sunlight_propagates = true,
drawtype = "nodebox",
connects_to = {"group:concrete", "group:concrete_post"},
node_box = {
type = "connected",
fixed = {box_post, (platform == 1 and box_platform or nil)},
connect_front = box_front,
connect_back = box_back,
connect_left = box_left,
connect_right = box_right,
},
after_dig_node = after_dig_node,
})
end

View file

@ -0,0 +1,20 @@
# textdomain: extranodes
# German Translation for technic_extranodes
# Deutsche Übersetzung von technic_extranodes
# by Xanthin
Marble=Marmor
Marble Bricks=Marmorziegel
Granite=Granit
Concrete=Beton
Blast-resistant Concrete=
Granite Bricks=
Zinc Block=
Cast Iron Block=
Carbon Steel Block=
Stainless Steel Block=
Insulator/cable clip=
Steel strut with insulator/cable clip=
Concrete Post Platform=Betonpfostenplattform
Concrete Post=Betonpfosten

View file

@ -0,0 +1,18 @@
# textdomain: extranodes
# technic_extranodes traducido por Carlos Barraza
Marble=Mármol
Marble Bricks=Ladrillos de mármol
Granite=Granito
Concrete=Concreto
Blast-resistant Concrete=
Granite Bricks=
Zinc Block=
Cast Iron Block=
Carbon Steel Block=
Stainless Steel Block=
Insulator/cable clip=
Steel strut with insulator/cable clip=
Concrete Post Platform=Plataforma de concreto
Concrete Post=Postes de concreto

View file

@ -0,0 +1,18 @@
# textdomain: extranodes
# technic_extranodes translation template
Marble=Marbre
Marble Bricks=Briques en marbre
Granite=Granite
Concrete=Béton
Blast-resistant Concrete=
Granite Bricks=Briques en granite
Zinc Block=Bloc de zinc
Cast Iron Block=Bloc de fonte
Carbon Steel Block=Bloc d'acier
Stainless Steel Block=Bloc en acier inoxydable
Insulator/cable clip=Isolateur
Steel strut with insulator/cable clip=Isolateur avec support en acier
Concrete Post Platform=Plateforme en béton
Concrete Post=Pilier en béton

View file

@ -0,0 +1,20 @@
# textdomain: extranodes
# technic_extranodes japanese translation
# technic_extranodesの日本語への翻訳
# by damiemk
Marble=大理石
Marble Bricks=大理石のレンガ
Granite=花崗岩
Concrete=コンクリート
Blast-resistant Concrete=
Granite Bricks=
Zinc Block=
Cast Iron Block=
Carbon Steel Block=
Stainless Steel Block=
Insulator/cable clip=
Steel strut with insulator/cable clip=
Concrete Post Platform=コンクリートのプラットフォーム
Concrete Post=コンクリートポスト

View file

@ -0,0 +1,20 @@
# textdomain: extranodes
# Polish Translation for technic_extranodes
# Polskie tłumaczenie technic_extranodes
# by mat9117
Marble=Marmur
Marble Bricks=Marmurowe cegły
Granite=Granit
Concrete=Beton
Blast-resistant Concrete=
Granite Bricks=
Zinc Block=
Cast Iron Block=
Carbon Steel Block=
Stainless Steel Block=
Insulator/cable clip=
Steel strut with insulator/cable clip=
Concrete Post Platform=Betonowa platforma
Concrete Post=Betonowy słup

View file

@ -0,0 +1,20 @@
# textdomain: extranodes
# Braziliam portuguese translation for technic_extranodes
# Tradução portuguesa brasileira para technic_extranodes
# By Sires
Marble=Mármore
Marble Bricks=Tijolos de Mármore
Granite=Granito
Concrete=Concreto
Blast-resistant Concrete=
Granite Bricks=
Zinc Block=
Cast Iron Block=
Carbon Steel Block=
Stainless Steel Block=
Insulator/cable clip=
Steel strut with insulator/cable clip=
Concrete Post Platform=Plataforma para Poste de Concreto
Concrete Post=Poste de Concreto

View file

@ -0,0 +1,18 @@
# textdomain: extranodes
# turkish translation by mahmutelmas06
Marble=Mermer
Marble Bricks=Mermer tuğla
Granite=Granit
Concrete=Beton
Blast-resistant Concrete=
Granite Bricks=
Zinc Block=
Cast Iron Block=
Carbon Steel Block=
Stainless Steel Block=
Insulator/cable clip=
Steel strut with insulator/cable clip=
Concrete Post Platform=Beton direk platformu
Concrete Post=Beton direk

View file

@ -0,0 +1,16 @@
# textdomain: extranodes
Marble=大理石
Marble Bricks=大理石砖
Granite=花岗岩
Concrete=混凝土
Blast-resistant Concrete=
Granite Bricks=
Zinc Block=
Cast Iron Block=
Carbon Steel Block=
Stainless Steel Block=
Insulator/cable clip=
Steel strut with insulator/cable clip=
Concrete Post Platform=混凝土柱平台
Concrete Post=混凝土柱

View file

@ -0,0 +1,18 @@
# textdomain: extranodes
# technic_extranodes translation template
Marble=
Marble Bricks=
Granite=
Concrete=
Blast-resistant Concrete=
Granite Bricks=
Zinc Block=
Cast Iron Block=
Carbon Steel Block=
Stainless Steel Block=
Insulator/cable clip=
Steel strut with insulator/cable clip=
Concrete Post Platform=
Concrete Post=

View file

@ -0,0 +1,3 @@
name = extranodes
depends = default, technic_worldgen, basic_materials
optional_depends = unifieddyes, moreblocks, steel, streetsmod

View file

@ -0,0 +1,173 @@
# Blender v2.72 (sub 0) OBJ File: ''
# www.blender.org
o Cube
v -0.500000 -0.500000 0.500000
v -0.500000 -0.500000 -0.500000
v 0.500000 -0.500000 -0.500000
v 0.500000 -0.500000 0.500000
v -0.249997 0.500000 0.249997
v -0.249997 0.500000 -0.249997
v 0.249997 0.500000 -0.249997
v 0.249997 0.500000 0.249997
v -0.187500 0.500000 0.187500
v -0.187500 0.500000 -0.187500
v 0.187500 0.500000 -0.187500
v 0.187500 0.500000 0.187500
v -0.187500 0.750000 0.187500
v -0.187500 0.750000 -0.187500
v 0.187500 0.750000 -0.187500
v 0.187500 0.750000 0.187500
v -0.250000 0.750000 0.250000
v -0.250000 0.750000 -0.250000
v 0.250000 0.750000 -0.250000
v 0.250000 0.750000 0.250000
v -0.250000 1.250000 0.250000
v -0.250000 1.250000 -0.250000
v 0.250000 1.250000 -0.250000
v 0.250000 1.250000 0.250000
v -0.500000 0.312500 0.500000
v -0.500000 0.312500 -0.500000
v 0.500000 0.312500 -0.500000
v 0.500000 0.312500 0.500000
v 0.187500 0.625000 0.187500
v 0.187500 0.625000 -0.187500
v -0.187500 0.625000 -0.187500
v -0.187500 0.625000 0.187500
v 0.187500 0.562500 0.187500
v 0.187500 0.687500 -0.187500
v -0.187500 0.687500 -0.187500
v -0.187500 0.562500 0.187500
v 0.187500 0.687500 0.187500
v 0.187500 0.562500 -0.187500
v -0.187500 0.562500 -0.187500
v -0.187500 0.687500 0.187500
v 0.168668 0.531250 0.168668
v 0.168668 0.718750 -0.168668
v -0.168668 0.718750 -0.168668
v -0.168668 0.531250 0.168668
v 0.168668 0.656250 0.168668
v 0.168668 0.593750 -0.168668
v -0.168668 0.593750 -0.168668
v -0.168668 0.656250 0.168668
v 0.168668 0.593750 0.168668
v 0.168668 0.656250 -0.168668
v -0.168668 0.656250 -0.168668
v -0.168668 0.593750 0.168668
v 0.168668 0.718750 0.168668
v 0.168668 0.531250 -0.168668
v -0.168668 0.531250 -0.168668
v -0.168668 0.718750 0.168668
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 0.749997 0.749997
vt 0.749997 0.250003
vt 0.250003 0.250003
vt 0.250003 0.749997
vt 0.000000 0.812500
vt 1.000000 0.812500
vt 0.312500 0.312500
vt 0.312500 0.687500
vt 0.687500 0.312500
vt 0.687500 0.687500
vt 0.331332 1.218750
vt 0.668668 1.218750
vt 0.687500 1.250000
vt 0.312500 1.250000
vt 0.750000 1.250000
vt 0.750000 1.750000
vt 0.250000 1.750000
vt 0.250000 1.250000
vt 0.331332 1.093750
vt 0.668668 1.093750
vt 0.687500 1.125000
vt 0.312500 1.125000
vt 0.331332 1.093750
vt 0.668668 1.093750
vt 0.331332 1.156250
vt 0.668668 1.156250
vt 0.687500 1.187500
vt 0.312500 1.187500
vt 0.331332 1.156250
vt 0.668668 1.156250
vt 0.331332 1.031250
vt 0.668668 1.031250
vt 0.687500 1.062500
vt 0.312500 1.062500
vt 0.312500 1.000000
vt 0.687500 1.000000
vn 0.000000 -1.000000 -0.000000
vn -0.600000 0.800000 -0.000000
vn 0.000000 0.800000 -0.600000
vn 0.600000 0.800000 0.000000
vn -0.000000 0.000000 1.000000
vn 0.000000 1.000000 0.000000
vn 0.856500 -0.516200 0.000000
vn 0.000000 -0.516200 -0.856500
vn -0.000000 -0.516200 0.856500
vn -0.856500 -0.516200 -0.000000
vn -1.000000 0.000000 -0.000000
vn 0.000000 -0.000000 -1.000000
vn 1.000000 -0.000000 0.000000
vn -0.000000 0.800000 0.600000
vn 0.856500 0.516200 0.000000
vn 0.000000 0.516200 -0.856500
vn -0.000000 0.516200 0.856500
vn -0.856500 0.516200 -0.000000
g Cube_Cube_Material
s off
f 1/1/1 2/2/1 3/3/1 4/4/1
f 25/2/2 5/5/2 6/6/2 26/1/2
f 26/1/3 6/6/3 7/7/3 27/4/3
f 27/4/4 7/7/4 8/8/4 28/3/4
f 25/9/5 1/4/5 4/1/5 28/10/5
f 8/8/6 7/7/6 11/11/6 12/12/6
f 7/7/6 6/6/6 10/13/6 11/11/6
f 5/5/6 8/8/6 12/12/6 9/14/6
f 6/6/6 5/5/6 9/14/6 10/13/6
f 53/15/7 42/16/7 15/17/7 16/18/7
f 42/15/8 43/16/8 14/17/8 15/18/8
f 56/15/9 53/16/9 16/17/9 13/18/9
f 43/15/10 56/16/10 13/17/10 14/18/10
f 14/4/1 18/4/1 19/4/1 15/4/1
f 17/19/11 21/20/11 22/21/11 18/22/11
f 18/19/12 22/20/12 23/21/12 19/22/12
f 19/19/13 23/20/13 24/21/13 20/22/13
f 21/21/5 17/22/5 20/19/5 24/20/5
f 21/5/6 24/8/6 23/7/6 22/6/6
f 15/4/1 19/4/1 20/4/1 16/4/1
f 16/4/1 20/4/1 17/4/1 13/4/1
f 13/4/1 17/4/1 18/4/1 14/4/1
f 1/1/11 25/10/11 26/9/11 2/4/11
f 2/1/12 26/10/12 27/9/12 3/4/12
f 3/1/13 27/10/13 28/9/13 4/4/13
f 5/5/14 25/2/14 28/3/14 8/8/14
f 49/23/7 46/24/7 30/25/7 29/26/7
f 46/27/8 47/28/8 31/25/8 30/26/8
f 52/23/9 49/24/9 29/25/9 32/26/9
f 47/23/10 52/24/10 32/25/10 31/26/10
f 45/29/7 50/30/7 34/31/7 37/32/7
f 50/33/8 51/34/8 35/31/8 34/32/8
f 48/33/9 45/34/9 37/31/9 40/32/9
f 51/29/10 48/30/10 40/31/10 35/32/10
f 41/35/7 54/36/7 38/37/7 33/38/7
f 54/35/8 55/36/8 39/37/8 38/38/8
f 44/35/9 41/36/9 33/37/9 36/38/9
f 55/35/10 44/36/10 36/37/10 39/38/10
f 37/32/15 34/31/15 42/16/15 53/15/15
f 34/32/16 35/31/16 43/16/16 42/15/16
f 40/32/17 37/31/17 53/16/17 56/15/17
f 35/32/18 40/31/18 56/16/18 43/15/18
f 33/38/15 38/37/15 46/24/15 49/23/15
f 38/38/16 39/37/16 47/28/16 46/27/16
f 36/38/17 33/37/17 49/24/17 52/23/17
f 39/38/18 36/37/18 52/24/18 47/23/18
f 29/26/15 30/25/15 50/30/15 45/29/15
f 30/26/16 31/25/16 51/34/16 50/33/16
f 32/26/17 29/25/17 45/34/17 48/33/17
f 31/26/18 32/25/18 48/30/18 51/29/18
f 12/39/15 11/40/15 54/36/15 41/35/15
f 11/39/16 10/40/16 55/36/16 54/35/16
f 9/39/17 12/40/17 41/36/17 44/35/17
f 10/39/18 9/40/18 44/36/18 55/35/18

View file

@ -0,0 +1,246 @@
# Blender v2.79 (sub 0) OBJ File: 'technic steel strut with insulator clip.blend'
# www.blender.org
o Cube_Cube_Material.001
v -0.375000 0.500532 -0.250000
v -0.249997 0.562500 -0.249997
v 0.249997 0.562500 -0.249997
v 0.375000 0.500532 -0.250000
v 0.249997 0.562500 0.249997
v 0.375000 0.500532 0.250000
v -0.249997 0.562500 0.249997
v -0.375000 0.500532 0.250000
v 0.187500 0.562500 -0.187500
v -0.168668 0.718750 0.168668
v 0.168668 0.718750 0.168668
v 0.187500 0.750000 0.187500
v -0.187500 0.750000 0.187500
v 0.168668 0.718750 -0.168668
v 0.187500 0.750000 -0.187500
v -0.168668 0.718750 -0.168668
v -0.187500 0.750000 -0.187500
v 0.250000 0.750000 -0.250000
v 0.250000 0.750000 0.250000
v -0.250000 0.750000 -0.250000
v -0.250000 1.250000 -0.250000
v 0.250000 1.250000 -0.250000
v 0.250000 1.250000 0.250000
v -0.250000 1.250000 0.250000
v -0.250000 0.750000 0.250000
v -0.168668 0.593750 0.168668
v 0.168668 0.593750 0.168668
v 0.187500 0.625000 0.187500
v -0.187500 0.625000 0.187500
v 0.168668 0.593750 -0.168668
v 0.187500 0.625000 -0.187500
v -0.168668 0.593750 -0.168668
v -0.187500 0.625000 -0.187500
v -0.168668 0.656250 0.168668
v 0.168668 0.656250 0.168668
v 0.187500 0.687500 0.187500
v -0.187500 0.687500 0.187500
v 0.168668 0.656250 -0.168668
v 0.187500 0.687500 -0.187500
v -0.168668 0.656250 -0.168668
v -0.187500 0.687500 -0.187500
v 0.187500 0.562500 0.187500
v -0.187500 0.562500 0.187500
v -0.187500 0.562500 -0.187500
v -0.499468 -0.499468 -0.499468
v -0.499468 0.500000 -0.499468
v 0.499468 -0.499468 -0.499468
v -0.499468 -0.499468 0.499468
v -0.499468 0.500000 0.499468
v 0.499468 -0.499468 0.499468
v 0.499468 0.500000 -0.499468
v 0.499468 0.500000 0.499468
vt 1.000000 0.875000
vt 0.937500 0.750000
vt 0.937500 0.250000
vt 1.000000 0.125000
vt 0.250000 0.875000
vt 0.250000 0.750000
vt 0.750000 0.750000
vt 0.750000 0.875000
vt 0.000000 0.125000
vt 0.062500 0.250000
vt 0.062500 0.750000
vt 0.000000 0.875000
vt 0.750000 0.250000
vt 0.687500 0.687500
vt 0.687500 0.312500
vt 0.312500 0.687500
vt 0.250000 0.250000
vt 0.312500 0.312500
vt 0.331332 1.218750
vt 0.668668 1.218750
vt 0.687500 1.250000
vt 0.312500 1.250000
vt 0.531250 0.666667
vt 0.531250 0.333333
vt 0.500000 0.312500
vt 0.500000 0.687500
vt 0.531250 0.333333
vt 0.531250 0.666667
vt 0.500000 0.687500
vt 0.500000 0.312500
vt 0.331332 1.218750
vt 0.668668 1.218750
vt 0.687500 1.250000
vt 0.312500 1.250000
vt 0.687500 0.312500
vt 0.750000 0.250000
vt 0.750000 0.750000
vt 0.687500 0.687500
vt 0.500000 0.250000
vt 0.500000 0.750000
vt 0.000000 0.750000
vt 0.000000 0.250000
vt 0.500000 0.250000
vt 0.000000 0.250000
vt 0.000000 0.750000
vt 0.500000 0.750000
vt 0.500000 0.250000
vt 0.500000 0.750000
vt 0.000000 0.750000
vt 0.000000 0.250000
vt 0.000000 0.250000
vt 0.500000 0.750000
vt 0.250000 0.250000
vt 0.750000 0.250000
vt 0.750000 0.750000
vt 0.250000 0.750000
vt 0.250000 0.750000
vt 0.312500 0.687500
vt 0.250000 0.250000
vt 0.312500 0.312500
vt 0.250000 0.125000
vt 0.750000 0.125000
vt 0.331332 1.093750
vt 0.668668 1.093750
vt 0.687500 1.125000
vt 0.312500 1.125000
vt 0.656250 0.666667
vt 0.656250 0.333333
vt 0.625000 0.312500
vt 0.625000 0.687500
vt 0.656250 0.333333
vt 0.656250 0.666667
vt 0.625000 0.687500
vt 0.625000 0.312500
vt 0.331332 1.093750
vt 0.668668 1.093750
vt 0.687500 1.125000
vt 0.312500 1.125000
vt 0.331332 1.156250
vt 0.668668 1.156250
vt 0.687500 1.187500
vt 0.312500 1.187500
vt 0.593750 0.666667
vt 0.593750 0.333333
vt 0.562500 0.312500
vt 0.562500 0.687500
vt 0.593750 0.333333
vt 0.593750 0.666667
vt 0.562500 0.687500
vt 0.562500 0.312500
vt 0.331332 1.156250
vt 0.668668 1.156250
vt 0.687500 1.187500
vt 0.312500 1.187500
vt 0.312500 1.062500
vt 0.687500 1.062500
vt 0.687500 0.312500
vt 0.687500 0.312500
vt 0.687500 0.687500
vt 0.312500 1.062500
vt 0.687500 1.062500
vt 0.000000 0.750000
vt 0.000000 0.250000
vt 1.000000 0.250000
vt 1.000000 0.750000
vt 1.000000 1.000000
vt -0.000000 1.000000
vt 0.000000 -0.000000
vt 1.000000 -0.000000
vt 1.000000 1.000000
vt -0.000000 1.000000
vt 0.000000 -0.000000
vt 1.000000 -0.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 1.000000 -0.000000
vt 1.000000 1.000000
vt 1.000000 1.000000
vt 0.000000 0.000000
vt -0.000000 0.000000
vn 0.0000 0.0000 -1.0000
vn 0.4442 0.8960 -0.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 1.0000 -0.0000
vn 0.0000 -0.5161 0.8565
vn 0.8565 -0.5161 0.0000
vn -0.8565 -0.5161 0.0000
vn 0.0000 -0.5161 -0.8565
vn -0.0000 -1.0000 -0.0000
vn 1.0000 -0.0000 0.0000
vn -1.0000 0.0000 -0.0000
vn -0.4442 0.8960 -0.0000
vn -0.0000 0.5161 0.8565
vn 0.8565 0.5161 -0.0000
vn -0.8565 0.5161 -0.0000
vn 0.0000 0.5161 -0.8565
g Cube_Cube_Material.001_Cube_Cube_Material.001_clip
s 1
f 1/1/1 2/2/1 3/3/1 4/4/1
f 4/5/2 3/6/2 5/7/2 6/8/2
f 6/9/3 5/10/3 7/11/3 8/12/3
f 7/13/4 5/7/4 42/14/4 43/15/4
f 5/7/4 3/6/4 9/16/4 42/14/4
f 2/17/4 7/13/4 43/15/4 44/18/4
f 3/6/4 2/17/4 44/18/4 9/16/4
f 10/19/5 11/20/5 12/21/5 13/22/5
f 11/23/6 14/24/6 15/25/6 12/26/6
f 16/27/7 10/28/7 13/29/7 17/30/7
f 14/31/8 16/32/8 17/33/8 15/34/8
f 15/35/9 18/36/9 19/37/9 12/38/9
f 20/39/1 21/40/1 22/41/1 18/42/1
f 18/43/10 22/44/10 23/45/10 19/46/10
f 19/47/3 23/48/3 24/49/3 25/50/3
f 21/51/11 20/39/11 25/52/11 24/49/11
f 21/53/4 24/54/4 23/55/4 22/56/4
f 12/38/9 19/37/9 25/57/9 13/58/9
f 13/58/9 25/57/9 20/59/9 17/60/9
f 17/60/9 20/59/9 18/36/9 15/35/9
f 2/17/12 1/61/12 8/62/12 7/13/12
f 26/63/5 27/64/5 28/65/5 29/66/5
f 27/67/6 30/68/6 31/69/6 28/70/6
f 32/71/7 26/72/7 29/73/7 33/74/7
f 30/75/8 32/76/8 33/77/8 31/78/8
f 34/79/5 35/80/5 36/81/5 37/82/5
f 35/83/6 38/84/6 39/85/6 36/86/6
f 40/87/7 34/88/7 37/89/7 41/90/7
f 38/91/8 40/92/8 41/93/8 39/94/8
f 37/82/13 36/81/13 11/20/13 10/19/13
f 36/86/14 39/85/14 14/24/14 11/23/14
f 41/90/15 37/89/15 10/28/15 16/27/15
f 39/94/16 41/93/16 16/32/16 14/31/16
f 43/95/13 42/96/13 27/64/13 26/63/13
f 42/14/14 9/97/14 30/68/14 27/67/14
f 44/98/15 43/99/15 26/72/15 32/71/15
f 9/100/16 44/101/16 32/76/16 30/75/16
f 29/66/13 28/65/13 35/80/13 34/79/13
f 28/70/14 31/69/14 38/84/14 35/83/14
f 33/74/15 29/73/15 34/88/15 40/87/15
f 31/78/16 33/77/16 40/92/16 38/91/16
f 8/102/9 1/103/9 4/104/9 6/105/9
g Cube_Cube_Material.001_Cube_Cube_Material.001_sides_with_band
s off
f 47/106/10 51/107/10 52/108/10 50/109/10
f 48/110/11 49/111/11 46/112/11 45/113/11
f 47/114/9 50/115/9 48/116/9 45/117/9
f 51/118/4 46/112/4 49/111/4 52/119/4
g Cube_Cube_Material.001_Cube_Cube_Material.001_sides_without_band
f 45/113/1 46/120/1 51/107/1 47/121/1
f 50/109/3 52/119/3 49/111/3 48/122/3

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 B

View file

@ -0,0 +1,6 @@
name = technic_plus_beta
description = The technic modpack extends the Minetest game with many new elements, mainly constructable machines and tools. It is a large modpack, and tends to dominate gameplay when it is used.
min_minetest_version = 5.5
release = 31092
author = mt-mods
title = Technic Plus Beta

View file

@ -0,0 +1,54 @@
# Technic (main mod)
## License
### Code
Copyright (C) 2012-2014 Maciej Kasatkin (RealBadAngel)
Technic chests code is licensed under the GNU LGPLv2+.
### Textures
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
Neuromancer via Minetest Game (CC BY-SA 3.0)
* `technic_*_electric_furnace_*.png` (derived)
[LB Photo Realism Reload](https://www.curseforge.com/minecraft/texture-packs/lb-photo-realism-reload) (CC 0)
* `technic_geothermal_*.png` (derived)
* `technic_water_mill_*.png` (derived)
* `technic_*_alloy_furnace_*.png` (derived)
* `technic_*_compressor_*.png` (derived)
* `technic_*_grinder_*.png` (derived)
RealBadAngel: (WTFPL)
* Everything else.
### Sounds
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/>
### References
CC BY-SA 3.0: http://creativecommons.org/licenses/by-sa/3.0/
CC BY-SA 4.0: https://creativecommons.org/licenses/by-sa/4.0/

View file

@ -0,0 +1,105 @@
--
-- 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 = "Lists 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
activecount = activecount + 1
if minlag == 0 or (net.lag and net.lag >= minlag * 1000) then
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
})

View file

@ -0,0 +1,73 @@
local config_file = minetest.get_worldpath() .. "/technic.conf"
local defaults = {
-- Power tools enabled
enable_cans = "true",
enable_chainsaw = "true",
enable_flashlight = "false",
enable_mining_drill = "true",
enable_mining_laser = "false",
enable_multimeter = "true",
enable_prospector = "true",
enable_sonic_screwdriver = "true",
enable_tree_tap = "true",
enable_vacuum = "true",
-- Power tool options
multimeter_remote_start_ttl = "300",
-- Machine options
enable_wind_mill = "false",
enable_nuclear_reactor_digiline_selfdestruct = "false",
quarry_max_depth = "100",
quarry_time_limit = "3000",
quarry_dig_particles = "false",
-- Power network and general options
switch_off_delay_seconds = "1800",
network_overload_reset_time = "20",
admin_priv = "basic_privs",
enable_corium_griefing = "true",
enable_radiation_protection = "true",
enable_radiation_throttling = "false",
enable_entity_radiation_damage = "true",
enable_longterm_radiation_damage = "true",
max_lag_reduction_multiplier = "0.99",
--constant_digit_count = nil,
}
--
-- Create technic.config settings object and
-- initialize configuration with default values.
--
local config_obj = Settings(config_file)
technic.config = {}
function technic.config:get_int(key)
local value = tonumber(self:get(key))
if not value then
error("Invalid configuration value for key " .. key .. " in " .. config_file .. ". Number expected.")
end
return value
end
function technic.config:get(...) return config_obj:get(...) end
function technic.config:get_bool(...) return config_obj:get_bool(...) end
function technic.config:get_np_group(...) return config_obj:get_np_group(...) end
function technic.config:get_flags(...) return config_obj:get_flags(...) end
function technic.config:set(...) return config_obj:set(...) end
function technic.config:set_bool(...) return config_obj:set_bool(...) end
function technic.config:set_np_group(...) return config_obj:set_np_group(...) end
function technic.config:remove(...) return config_obj:remove(...) end
function technic.config:get_names(...) return config_obj:get_names(...) end
function technic.config:write(...) return config_obj:write(...) end
function technic.config:to_table(...) return config_obj:to_table(...) end
local conf_table = technic.config:to_table()
for k, v in pairs(defaults) do
if conf_table[k] == nil then
technic.config:set(k, v)
end
end

View file

@ -0,0 +1,190 @@
-- check if we have the necessary dependencies to allow actually using these materials in the crafts
local mat = technic.materials
local has_mcl = minetest.get_modpath("mcl_core")
-- Remove some recipes
-- Bronze
if not has_mcl then
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"}
}
})
end
-- 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 = {
{mat.mese_crystal, 'technic:copper_coil', mat.mese_crystal},
{'pipeworks:tube_1', 'technic:control_logic_unit', 'pipeworks:tube_1'},
{mat.mese_crystal, 'technic:copper_coil', mat.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', mat.diamond, 'technic:stainless_steel_ingot'},
{mat.diamond, '', mat.diamond},
{'technic:stainless_steel_ingot', mat.diamond, 'technic:stainless_steel_ingot'},
}
})
minetest.register_craft({
output = 'technic:green_energy_crystal',
recipe = {
{mat.gold_ingot, 'technic:battery', mat.dye_green},
{'technic:battery', 'technic:red_energy_crystal', 'technic:battery'},
{mat.dye_green, 'technic:battery', mat.gold_ingot},
}
})
minetest.register_craft({
output = 'technic:blue_energy_crystal',
recipe = {
{mat.mithril_ingot, 'technic:battery', mat.dye_blue},
{'technic:battery', 'technic:green_energy_crystal', 'technic:battery'},
{mat.dye_blue, 'technic:battery', mat.mithril_ingot},
}
})
minetest.register_craft({
output = 'technic:red_energy_crystal',
recipe = {
{mat.silver_ingot, 'technic:battery', mat.dye_red},
{'technic:battery', 'basic_materials:energy_crystal_simple', 'technic:battery'},
{mat.dye_red, 'technic:battery', mat.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"}
},
})
minetest.register_craft({
output = 'technic:lv_transformer',
recipe = {
{mat.insulation, 'technic:wrought_iron_ingot', mat.insulation},
{'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 = {
{mat.insulation, 'technic:carbon_steel_ingot', mat.insulation},
{'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 = {
{mat.insulation, 'technic:stainless_steel_ingot', mat.insulation},
{'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', ''},
{mat.bronze_ingot, 'technic:silicon_wafer', mat.bronze_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'},
{mat.bronze_ingot, mat.bronze_ingot, mat.bronze_ingot},
{mat.tin_ingot, mat.tin_ingot, mat.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 = mat.dirt.." 2",
type = "shapeless",
replacements = {{mat.bucket_water,mat.bucket_empty}},
recipe = {
"technic:stone_dust",
"group:leaves",
mat.bucket_water,
"group:sand",
},
})

View file

@ -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&times;511&times;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&times;16&times;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.

View file

@ -0,0 +1,187 @@
This file is fairly incomplete. Read the code if this is not enough. Help is welcome.
Tiers
-----
The tier is a string, currently `"LV"`, `"MV"` and `"HV"` are included with technic.
Network
-------
The network is the cable with the connected machine nodes. The switching station activates network.
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.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.register_cable_tier(nodename, tier)`
* Register user defined cable to list of known tier cables.
* `nodename`: string, name of the node
* `tier`: string, tier name
* `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.tube_inject_item(pos, start_pos, velocity, item)`
* Same as `pipeworks.tube_inject_item`
Configuration API
----------------------
* `technic.config` Settings object that contains Technic configuration.
* Provides all methods that are provided by Minetest Settings object.
* Uses `<world-path>/technic.conf` as configuration file.
* If key is not present in configuration then returns default value for that key.
* `:get_int(key)` Return number value for configuration key.
Power tool API
----------------------
* `technic.register_power_tool(itemname, definition)`
* Registers power tool adding required fields, otherwise same as `minetest.register_tool(itemname, definition)`.
* For regular power tools you only want to change `max_charge` and leave other fields unset (defaults).
* Special fields for `definition`:
* `technic_max_charge` Number, maximum charge for tool. Defaults to `10000` which is same as RE battery.
* `on_refill` Function to refill charge completely. Default is to set maximum charge for tool.
* `wear_represents` Customize wear indicator instead of using charge level. Default is `"technic_RE_charge"`.
* `tool_capabilities` See Minetest documentation. Default is `{ punch_attack_uses = 0 }`.
* `technic_get_charge = function(itemstack) ...`:
* Callback will be used to get itemstack charge and max\_charge.
* Have to return values `charge, max_charge`.
* E.g. `local charge, maxcharge = itemdef.technic_get_charge(itemstack)`.
* Defaults to `technic.get_charge` which handles tool wear and charge values.
* `technic_set_charge = function(itemstack, charge) ...`:
* Callback will be used to set itemstack charge.
* Defaults to `technic.set_charge` which handles tool wear and charge values.
* `technic.get_charge(itemstack)`
* Returns current charge level of tool.
* For tool charger mods it is recommended to use `<tooldef>.technic_get_charge(stack)` instead.
* `technic.set_charge(itemstack, charge)`
* Sets tool charge level.
* For tool charger mods it is recommended to use `<tooldef>.technic_set_charge(stack, charge)` instead.
* `technic.use_charge(itemstack, charge)`
* Attempt to use charge and return `true`/`false` indicating success.
* Always succeeds without checking charge level if creative is enabled.
Machine registration API
----------------------
* `technic.register_machine(tier, nodename, machine_type)`
* Custom machine registration. Not needed when using builtin machine registration functions.
* See also `Machine types`
* `technic.register_tier(tier)`
* Registers network tier.
* See also `tiers`
* `technic.register_base_machine(nodename, def)`
* Register various types of basic factory processing machines.
* `typename = "compressing"`
* `description = S("%s Compressor")`
* `tier = "HV"`
* `demand = {1500, 1000, 750}`
* `speed = 5`
* `upgrade = 1`
* `tube = 1`
* TODO / TBD
* `technic.register_solar_array(nodename, def)`
* Registers solar array generator.
* `tier = "HV"`
* `power = 100`
* TODO / TBD
* `technic.register_battery_box(nodename, def)`
* Registers battery box node used as energy storage.
* TODO / TBD
* `technic.register_cable(nodename, data)`
* Registers technic network cables.
* `tier = "HV"`
* `size = 3/16`
* `description = S("%s Digiline Cable"):format("HV")`
* `digiline = { wire = { rules = technic.digilines.rules_allfaces } }`
* `technic.register_cable_plate(nodename, data)`
* Registers technic network cable plates. Results in multiple nodes registered with `_1` to `_6` appended to name.
* See `technic.register_cable(nodename, data)`
Network control API
----------------------
* TBD, functions exported through technic namespace are currently considered to be internal use only.
### Specific machines
* `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.
* `wear_represents = "string"`
* Specifies how the tool wear level is handled. Available modes:
* `"mechanical_wear"`: represents physical damage
* `"technic_RE_charge"`: represents electrical charge
* `<itemdef>.technic_run = function(pos, node) ...`
* This callback is used to update the node.
* `<itemdef>.technic_disabled_machine_name = "string"`
* Specifies the machine's node name to use when it's not connected connected to a network
* `<itemdef>.technic_on_disable = function(pos, node) ...`
* This callback is run when the machine is no longer connected to a technic-powered network.
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 required to start electric network and keep it running.
Unlike in original mod this node does not handle power distribution logic but instead just resets network timeout. The polyfuse system is activated when there is too much lag, which causes network to skip cycles (it works slower). It is shown in the infotext when activated.
Network logic
-----------------
The network logic 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.
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 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 excess power.
If total demand exceeds generator supply then draw difference from batteries.
If total demand is more than available power all RE nodes will be shut down.
You can only have one network per machine, else the switching station will indicate you that several networks are trying to access the machine.
### 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.

View file

@ -0,0 +1,90 @@
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&times;4 (32) slots
2. iron chest: 9&times;5 (45) slots
3. copper chest: 12&times;5 (60) slots
4. silver chest: 12&times;6 (72) slots
5. gold chest: 15&times;6 (90) slots
6. mithril chest: 15&times;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.
## Sorting
Chests can be sorted with one button with the following sort types : natural sort, by item, by quantity, by type or by wear. The chests can also be sorted automatically when its content changes. On the UI, the three buttons are the following : toggle automatic sorting, toggle sorting type, sort
## Inventory move
Chests have the ability to move all or a certain type of item with a button. All items that fit with that type will move from inventory to chest or the contrary.
## Digilines
Only mithril chests can send digilines logs. They can send messages of following types :
* Player/pipeworks item taking
* Player/pipeworks item putting
* Pipeworks overflow (chest is full)
Example of digiline message :
```lua
{
player = "singleplayer",
items = {
{
meta = {
},
metadata = "",
count = 99,
name = "technic:quarry",
wear = 0
}
},
pos = {
y = 19,
x = 67,
z = 57
},
event = "put"
}
```

View file

@ -0,0 +1,138 @@
# Technic digilines compatibility
This document describes the interaction of
technic machines with the `digilines` mod (https://github.com/minetest-mods/digilines)
## Digicables
Digicables are a type of cable that carry both electric power and digiline messages. Like both original types of cable (electric cable and digiline), you just have to connect cables to each other in order to transmit power/information. They are needed to access nuclear reactor digiline information. The digicables are available in HV, MV and LV.
## 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}`
- `"max_depth "..value` :arrow_right: `{command = "max_depth", value = value}`
The commands:
- `"get"`: The quarry sends back a table containing:
- `"enabled"`: `0` is off, `1` is on.
- `"radius"`
- `"max_depth"`
- `"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.

View file

@ -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&times;7&times;7 cube, and the full customary structure a
9&times;9&times;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

View file

@ -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.

View file

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

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -0,0 +1,87 @@
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.
## Multimeter
<img src="../textures/technic_multimeter.png"/>
This electric tool is used for quick lookup at an electric network. It works by clicking on an electric node (cable, machine, generator, switchting station), and gives values about : the position of the attached switching station, its current status, the lag, the batteries, the supply and the demand, and the total of each type of node.
| Property | Example Value | Unit | Meaning |
|------------------|---------------|------------|---------------------------------------------------------------|
| Ref. point | 61, 19, 62 | Coordinate | The location of the cable below the switching station that initially triggered initialization of this network |
| Activated | yes | active | The current state of the network |
| Timeout | 1800.0 | s | Time remaining, in seconds, before the network will shut down |
| Lag | 0.60 | ms | The lag generated by the network |
| Skip | 0 | cycles | How many cycles are skipped when network lag value is high |
| Supply | 6000 | EU | How much power is supplied by generators |
| Demand | 4000 | EU | How much power is required by consumers |
| Battery charge | 2911956 | EU | The total of energy stored in batteries |
| Battery charge | 97.07 | % | The energy stored per the maximum that can be stored |
| Battery capacity | 3000000 | EU | The maximum amount of energy that can be stored in batteries |
| Nodes | 47 | count | The number of nodes of the network, excluding switch stations |
| Cables | 32 | count | The number of cables |
| Generators | 8 | count | The number of generators (supplying the network) |
| Consumers | 4 | count | The number of consumers (demanding power) |
| Batteries | 3 | count | The number of batteries (storing energy) |
## 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.

View file

@ -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 = "technic_blueparticle.png",
glow = 5
})
end
})

View file

@ -0,0 +1,287 @@
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
function technic.set_charge(stack, charge)
local wear_factor = stack:get_definition().technic_wear_factor
if wear_factor then
local wear = math.floor(charge * wear_factor + 0.5)
stack:set_wear(wear > 0 and 65536 - wear or 0)
end
end
function technic.get_charge(stack)
local def = stack:get_definition()
if def.technic_wear_factor then
local wear = stack:get_wear()
return (wear > 0 and math.floor((65536 - wear) / def.technic_wear_factor + 0.5) or 0), def.technic_max_charge
end
return 0, 0
end
function technic.use_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_charge(stack)
if charge < amount then
-- Not enough energy available
return false
end
-- Ensure that at least single point is always added to wear when using tool
local wear_factor = stack:get_definition().technic_wear_factor
local wear = stack:get_wear()
wear = math.max(math.floor(wear + 1.5), math.floor(amount * wear_factor + wear + 0.5))
stack:set_wear(wear > 65535 and 0 or wear)
-- Charge used successfully
return true
end
-- If the node is loaded, returns it. If it isn't loaded, load it.
function technic.get_or_load_node(pos)
local node = minetest.get_node_or_nil(pos)
if node then return node end
minetest.load_area(pos)
return minetest.get_node(pos)
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
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.process_recipe(recipe, inv)
local dst_copy = inv:get_list("dst")
for _,item in ipairs(recipe.output) do
if not inv:room_for_item("dst", ItemStack(item)) then
inv:set_list("dst", dst_copy)
return false
end
inv:add_item("dst", item)
end
inv:set_list("src", recipe.new_input)
return true
end

View file

@ -0,0 +1,62 @@
technic = rawget(_G, "technic") or {}
technic.plus = true
technic.version = 1.2
if minetest.get_modpath("mcl_sounds") then
technic.sounds = mcl_sounds
else
technic.sounds = assert(default, "No suitable mod found for sounds")
end
technic.creative_mode = minetest.settings:get_bool("creative_mode")
local modpath = minetest.get_modpath("technic")
technic.modpath = modpath
local S = minetest.get_translator("technic")
technic.getter = S
-- Read materials file
dofile(modpath.."/materials.lua")
-- Read configuration file
dofile(modpath.."/config.lua")
-- Lag monitoring
dofile(modpath.."/max_lag.lua")
-- Helper functions
dofile(modpath.."/helpers.lua")
-- Register functions
dofile(modpath.."/register.lua")
-- Compatibility shims for tools
dofile(modpath.."/machines/compat/tools.lua")
-- Items
dofile(modpath.."/items.lua")
-- Craft recipes for items
dofile(modpath.."/crafts.lua")
-- Radiation
dofile(modpath.."/radiation.lua")
-- Machines
dofile(modpath.."/machines/init.lua")
-- Tools
dofile(modpath.."/tools/init.lua")
-- Visual effects
dofile(modpath.."/effects.lua")
-- Chat commands
dofile(modpath.."/chatcommands.lua")
if minetest.get_modpath("mtt") and mtt.enabled then
dofile(modpath.."/mtt.lua")
end

View file

@ -0,0 +1,192 @@
local S = technic.getter
local has_mcl = minetest.get_modpath("mcl_core")
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",
})
technic.register_power_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"),
groups = { disable_repair = 1 },
max_charge = 450000,
})
technic.register_power_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"),
groups = { disable_repair = 1 },
max_charge = 150000,
})
technic.register_power_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"),
groups = { disable_repair = 1 },
max_charge = 50000,
})
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, pickaxey=2},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
sunlight_propagates = true,
paramtype = "light",
drawtype = "allfaces",
tiles = {"technic_machine_casing.png"},
sounds = technic.sounds.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 = S("@1%-Fissile Uranium Ingot", string.format("%.1f", 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 = S("@1%-Fissile Uranium Block", string.format("%.1f", p/10)),
tiles = {"technic_uranium_block.png"},
is_ground_content = false,
groups = {uranium_block=1, not_in_creative_inventory=nici,
cracky=1, level=has_mcl and 0 or 2, radioactive=radioactivity, pickaxey=4},
_mcl_blast_resistance = 1,
_mcl_hardness = 1,
sounds = technic.sounds.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

View file

@ -0,0 +1,211 @@
# textdomain: technic
# German Translation for Technic Mod
# Deutsche Uebersetzung des Technic Mods
# by Xanthin
3 nodes deep.=3 Bloecke tief.
3 nodes tall.=3 Bloecke hoch.
3 nodes wide.=3 Bloecke breit.
3x3 nodes.=3x3 Bloecke.
@1 (@2 @3 -> @4 @5)=@1 (@2 @3 -> @4 @5)
@1 (@2% Efficiency)=@1 (@2% Wirkungsgrad)
@1 (@2% Fuel Used)=@1 (@2% Brennstoffverbrauch)
@1 (@2)=@1 (@2)
@1 Active (@2)=@1 Aktiv (@2)
@1 Active=@1 ist eingeschaltet
@1 Alloy Furnace=@1 Legierungsofen
@1 Battery Box: @2 / @3=@1 Batteriekasten: @2 / @3
@1 Battery Box=@1 Batteriebox
@1 Cable Plate=@1 Kabelplatte
@1 Cable=@1 Kabel
@1 Centrifuge=@1 Zentrifuge
@1 Compressor=@1 Kompressor
@1 Digiline Cable Plate=@1 Digiline Kabelplatte
@1 Digiline Cable=@1 Digiline Kabel
@1 Disabled=@1 ist ausgeschaltet
@1 Dust=@1staub
@1 Enabled=@1 ist eingechaltet
@1 Extractor=@1 Extraktor
@1 Finished=@1 ist fertig
@1 Forcefield Emitter=@1 Kraftfeld-Emitter
@1 Forcefield=@1 Kraftfeld
@1 Freezer=@1 Gefrierschrank
@1 Furnace=@1 Ofen
@1 Grinder=@1 Schleifmaschine
@1 Grinding=@1 Schleifen
@1 Has Bad Cabling=@1 ist falsch verkabelt
@1 Has No Network=@1 hat kein Netzwerk
@1 Idle=@1 ist bereit
@1 Improperly Placed=@1 ist falsch plaziert
@1 LED=@1 LED
@1 Lamp=@1 Lampe
@1 Music Player=@1 Musikspieler
@1 Network Overloaded, Restart in @2ms=@1 Netzwerk überlastet, Neustart in @2ms
@1 Nuclear Reactor Core=@1 Nuklearer Reaktorkern
@1 Off=@1 Aus
@1 Out Of Fuel=@1 hat keinen Brennstoff
@1 Purging Cache=@1 Cache leeren
@1 Quarry=@1 Steinbruch
@1 Restarting Network=@1 Neustart des Netzwerks
@1 Tool Workshop=@1 Werkzeugwerkstatt
@1 Unpowered=@1 hat keine Stromversorgung
@1 is absent in @2 region=@1 ist in der Region @2 abwesend
@1 is empty=@1 ist leer
@1 is present in @2 region=@1 ist in der Region @2 vorhanden
@1%-Fissile Uranium Block=@1%-Spaltbarer Uranblock
@1%-Fissile Uranium Dust=@1%-Spaltbarer Uranstaub
@1%-Fissile Uranium Ingot=@1%-Spaltbarer Uranbarren
@1. Supply: @2 Demand: @3=@1. Versorgung: @2 Bedarf: @3
Acacia=Akazie
Accuracy:=Akkuratesse:
Administrative World Anchor=Administrativer Welt-Anker
Akalin=Akalin
Alatro=Alatro
Alloying=Legieren
Arol=Arol
Arrayed Solar @1 Generator=@1 Solaranlage
Automatic Start=Automatischer Start
Blue Energy Crystal=Blauer Energiekristall
Brass=Messing
Bronze=Bronze
Building Network: @1 Nodes=Gebäude-Netzwerk: @1 Knoten
Carbon Cloth=Kohlefasergewebe
Carbon Plate=Kohlefaserplatte
Carbon Steel=Kohlenstoffstahl
Cast Iron=Gusseisen
Chainsaw=Kettensaege
Charge=Aufladen
Chernobylite Block=Tschernobylit-Block
Chernobylite=Tschernobylit
Chromium=Chrom
Coal=Kohle
Common Tree=Gewöhnlicher Baum
Composite Plate=Verbundplatte
Compressing=Komprimieren
Constructor Mk@1=Konstruktor Modell @1
Control Logic Unit=Steuer- und Regelungseinheit
Controlled by Mesecon Signal=Gesteuert durch Mesecon-Signal
Copper Coil=Kupferspule
Copper Plate=Kupferplatte
Copper=Kupfer
Corium Bucket=Corium-Eimer
Corium Source=Corium-Quelle
Cube=Würfel
Current target:=Aktuelles Ziel:
Current track: @1=Aktueller Kurs: @1
Demand: @1=Bedarf: @1
Diamond Drill Head=Diamantbohrkopf
Digging @1 m below machine=Graben @1 m unterhalb der Maschine
Digging finished=Graben beendet
Digging not started=Graben nicht begonnen
Digiline Channel=Digiline-Kanal
Disabled=Deaktiviert
Discharge=Entladen
Doped Silicon Wafer=Dotierte Siliziumscheibe
Dummy light source node=Dummy-Lichtquellenknoten
Enable Mesecons Control=Mesecons-Steuerung einschalten
Enabled=Aktiviert
Error=Fehler
Extracting=Extrahieren
Flashlight=Taschenlampe
Flowing Corium=Fließendes Corium
Freezing=Einfrieren
Fuel-Fired @1 Generator=Brennstoffbefeuerter @1-Generator
Fuel-Fired Alloy Furnace=Brennstoffbefeuerter Legierungsofen
Fuel-Fired Furnace=Brennstoffbefeuerter Ofen
Geothermal @1 Generator=@1 Geothermie-Generator
Gold=Gold
Graphite=Graphit
Green Energy Crystal=Gruener Energiekristall
Grinding=Schleifen
HV=HV
High Voltage Transformer=Hochspannungstransformator
Hydro @1 Generator=@1 Wassermuehle
Ignoring Mesecon Signal=Ignorieren des Mesecon-Signals
Input Power=Eingangsleistung
Inventory move disallowed due to protection=Das Inventar ist geschuetzt, Zugriff verweigert.
Itemwise=Einzelstuecke
Kalite=Kalit
Keeping @1/@2 map blocks loaded=Beibehaltung der @1/@2 Kartenblöcke geladen
LV=LV
Lava Can=Lavakanister
Lead=Blei
Locked=Gesperrt
Low Voltage Transformer=Niederspannungstransformator
MV=MV
Machine Casing=Gehäuse der Maschine
Machine cannot be removed because it is not empty=Die Maschine kann nicht entfernt werden, weil sie noch nicht leer ist.
Max Depth=Maximale Tiefe
May set new target:=Kann neues Ziel setzen:
Medium Voltage Transformer=Mittelspannungstransformator
Mining Drill Mk@1 Mode @2=Bergbaubohrer Modell @1 Funktion @2
Mining Drill Mk@1=Bergbaubohrer Modell @1
Mining Laser Mk@1=Bergbaulaser Modell @1
Mithril=Mithril
Mixed Metal Ingot=Mischmetallbarren
Multimeter=Multimeter
Network Overloaded=Netzwerk überlastet
No new target available=Kein neues Ziel verfügbar
No target set=Kein Ziel gesetzt
Nuclear Reactor Rod Compartment=Brennstabfaecher
Offset X=Versatz X
Offset Z=Versatz Z
Owner: @1=Besitzer: @1
Polyfuse triggered, current efficiency: @1%, generated lag: @2 ms=Polyfuse ausgelöst, aktueller Wirkungsgrad: @1%, erzeugte Verzögerung: @2 ms
Power Monitor Has No Network=Leistungsmonitor hat kein Netzwerk
Power Monitor. Supply: @1 Demand: @2=Leistungsmonitor. Versorgung: @1 Bedarf: @2
Power Monitor=Leistungsmonitor
Power level=Energiestufe
Prospector=Prospektor
Purging cache=Cache leeren
RE Battery=Akkubatterie
Radius=Radius
Range=Reichweite
Raw Latex=Rohlatex
Red Energy Crystal=Roter Energiekristall
Region cross section:=Region Querschnitt:
Region depth:=Tiefe der Region:
Restart=Neustart
Right-click to set target block type=Rechtsklick zum Einstellen des Zielblocktyps
River Water Can=Fluss Wasser Dose
Rubber Fiber=Gummifaser
Rubber Tree=Gummibaum
Save=Speichern
Sawdust=Sägespäne
Self-Contained Injector=Selbständiger Injektor
Separating=Trennen
Set region cross section:=Querschnitt der Region einstellen:
Set region depth:=Tiefe des Bereichs festlegen:
Set target=Ziel einstellen
Silicon Wafer=Siliziumscheibe
Silver=Silber
Single node.=Einzelblock
Slot @1=Fach @1
Small Solar @1 Generator=@1 Solarmodul
Sonic Screwdriver (left-click rotates face, right-click rotates axis)=Schallschraubendreher (Linksklick dreht die Fläche, Rechtsklick dreht die Achse)
Sphere=Kugel
Stackwise=Ganzer Stapel
Stainless Steel=Edelstahl
Start successful=Start erfolgreich
Start=Start
Stone=Stein
Stop=Stopp
Stopped=Gestoppt
Sulfur=Schwefel
Supply Converter=Stromumwandler
Switching Station=Schaltanlage
Talinite=Talinite
Tin=Zinn
Tree Tap=Baumzapfhahn
Unlocked=Freigegeben
Upgrade Slots=Verbesserungsfaecher
Uranium Fuel=Uranbrennstoff
Use while sneaking to change Mining Drill Mk@1 modes.=Halte die Shift-Taste beim Benutzen gedrueckt, um die Funktion des Bergbaubohrers Modell @1 zu aendern.
Vacuum Cleaner=Staubsauger
Water Can=Wasserkanister
Wind @1 Generator=@1 Windmuehle
Wind Mill Frame=Windmuehlengeruest
Wrought Iron=Schmiedeeisen
You are not allowed to edit this!=Es ist nicht erlaubt, dies zu bearbeiten!
Zinc=Zink

View file

@ -0,0 +1,211 @@
# textdomain: technic
# Spanish Translation for Technic Mod
# Traduccion al Español del Mod Technic
# by Diego Martínez <kaeza>
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.
@1 (@2 @3 -> @4 @5)=@1 (@2 @3 -> @4 @5)
@1 (@2% Efficiency)=@1 (@2% Eficiencia)
@1 (@2% Fuel Used)=@1 (@2% Combustible utilizado)
@1 (@2)=@1 (@2)
@1 Active (@2)=@1 Activo (@2)
@1 Active=@1 Activo
@1 Alloy Furnace=Horno de Aleacion @1
@1 Battery Box: @2 / @3=@1 Caja de baterías: @2 / @3
@1 Battery Box=Caja de Bateria @1
@1 Cable Plate=@1 Placa de cable
@1 Cable=Cable @1
@1 Centrifuge=@1 Centrífuga
@1 Compressor=Compresor @1
@1 Digiline Cable Plate=@1 Placa de cable Digiline
@1 Digiline Cable=@1 Cable Digiline
@1 Disabled=@1 Deshabilitado
@1 Dust=Polvo de @1
@1 Enabled=@1 Habilitado
@1 Extractor=Extractor @1
@1 Finished=@1 Terminado
@1 Forcefield Emitter=Emisor de Campo de Fuerza @1
@1 Forcefield=@1 Campo de fuerza
@1 Freezer=@1 Congelador
@1 Furnace=Horno @1
@1 Grinder=Amoladora @1
@1 Grinding=@1 Amoladora
@1 Has Bad Cabling=@1 Tiene Mal Cableado
@1 Has No Network=@1 No Tiene Una Red
@1 Idle=@1 Quieto
@1 Improperly Placed=@1 No Colocado Apropiadamente
@1 LED=@1 LED
@1 Lamp=@1 Lámpara
@1 Music Player=Reproductor de Musica @1
@1 Network Overloaded, Restart in @2ms=@1 Red sobrecargada, reinicio en @2ms
@1 Nuclear Reactor Core=@1 Núcleo del reactor nuclear
@1 Off=@1 Apagado
@1 Out Of Fuel=@1 Sin Combustible
@1 Purging Cache=@1 Purga de caché
@1 Quarry=Cantera @1
@1 Restarting Network=@1 Reinicio de la red
@1 Tool Workshop=Taller de Herramientas @1
@1 Unpowered=@1 Sin Energia
@1 is absent in @2 region=@1 está ausente en la región @2
@1 is empty=@1 está vacío
@1 is present in @2 region=@1 está presente en la región @2
@1%-Fissile Uranium Block=@1%-Bloque de Uranio Fisible
@1%-Fissile Uranium Dust=@1%-Polvo de uranio fisible
@1%-Fissile Uranium Ingot=@1%-Lingote de uranio fisible
@1. Supply: @2 Demand: @3=@1. Suministro: @2 Demanda: @3
Acacia=Acacia
Accuracy:=Precisión:
Administrative World Anchor=Ancla Administrativa Mundial
Akalin=Akalina
Alatro=Alatro
Alloying=Aleación
Arol=Arol
Arrayed Solar @1 Generator=Panel Solar @1
Automatic Start=Arranque automático
Blue Energy Crystal=Cristal de Energia Azul
Brass=Laton
Bronze=Bronce
Building Network: @1 Nodes=Red de edificios: @1 Nodos
Carbon Cloth=Tela de Carbon
Carbon Plate=Placa de Carbon
Carbon Steel=Acero al Carbono
Cast Iron=Hierro Fundido
Chainsaw=Motosierra
Charge=Cargar
Chernobylite Block=Bloque de Chernóbilita
Chernobylite=Chernobylita
Chromium=Cromo
Coal=Carbon
Common Tree=Árbol común
Composite Plate=Placa de Compuestos
Compressing=Compresor
Constructor Mk@1=Constructor Mk@1
Control Logic Unit=Unidad Logica de Control
Controlled by Mesecon Signal=Controlado por la señal de Mesecon
Copper Coil=Resorte de Cobre
Copper Plate=Placa de Cobre
Copper=Cobre
Corium Bucket=Cubo de corio
Corium Source=Fuente de corio
Cube=Cubo
Current target:=Objetivo actual:
Current track: @1=Pista actual: @1
Demand: @1=Demanda: @1
Diamond Drill Head=Mecha de Taladro de Diamante
Digging @1 m below machine=Excavación @1 m por debajo de la máquina
Digging finished=Excavación terminada
Digging not started=Excavación no iniciada
Digiline Channel=Canal Digiline
Disabled=Desactivado
Discharge=Descargar
Doped Silicon Wafer=Oblea de Silicio Dopada
Dummy light source node=Nodo de fuente de luz ficticia
Enable Mesecons Control=Habilitar control de mesecons
Enabled=Habilitado
Error=Error
Extracting=Extrayendo
Flashlight=Linterna
Flowing Corium=Corio fluyendo
Freezing=Congelando
Fuel-Fired @1 Generator=Generador @1 alimentado por combustible
Fuel-Fired Alloy Furnace=Horno de aleación alimentado por combustible
Fuel-Fired Furnace=Horno de combustible
Geothermal @1 Generator=Generador Geotermico @1
Gold=Oro
Graphite=Grafito
Green Energy Crystal=Cristal de Energia Verde
Grinding=Molienda
HV=HV
High Voltage Transformer=Transformador de Alto Voltaje
Hydro @1 Generator=Molino de Agua @1
Ignoring Mesecon Signal=Ignorar la señal de Mesecon
Input Power=Potencia de entrada
Inventory move disallowed due to protection=Movimiento de inventario desestimado debido a la protección
Itemwise=Itemwise
Kalite=Kalite
Keeping @1/@2 map blocks loaded=Mantener cargados los bloques del mapa @1/@2
LV=LV
Lava Can=Bidon de Lava
Lead=Plomo
Locked=Bloqueado
Low Voltage Transformer=Transformador de Bajo Voltaje
MV=MV
Machine Casing=Carcasa de la máquina
Machine cannot be removed because it is not empty=La maquina no puede removerse porque no esta vacia
Max Depth=Profundidad máxima
May set new target:=Puede establecer un nuevo objetivo:
Medium Voltage Transformer=Transformador de Voltaje Medio
Mining Drill Mk@1 Mode @2=Taladro de Mineria Mk@1 Modo @2
Mining Drill Mk@1=Taladro de Mineria Mk@1
Mining Laser Mk@1=Laser de Mineria Mk@1
Mithril=Mitrilo
Mixed Metal Ingot=Lingote de Metal Mezclado
Multimeter=Multímetro
Network Overloaded=Red sobrecargada
No new target available=No hay ningún objetivo nuevo disponible
No target set=No se ha fijado ningún objetivo
Nuclear Reactor Rod Compartment=Compartimiento para Vara de Reactor Nuclear
Offset X=Desplazamiento X
Offset Z=Desplazamiento Z
Owner: @1=Propietario: @1
Polyfuse triggered, current efficiency: @1%, generated lag: @2 ms=Polifusible disparado, eficiencia de la corriente: @1%, retardo generado: @2 ms
Power Monitor Has No Network=El monitor de potencia no tiene red
Power Monitor. Supply: @1 Demand: @2=Monitor de energía. Suministro: @1 Demanda: @2
Power Monitor=Monitor de potencia
Power level=Nivel de Poder
Prospector=Prospector
Purging cache=Purga de caché
RE Battery=Batería RE
Radius=Radio
Range=Alcance
Raw Latex=Latex Crudo
Red Energy Crystal=Cristal de Energia Rojo
Region cross section:=Sección transversal de la región:
Region depth:=Profundidad de la región:
Restart=Reiniciar
Right-click to set target block type=Haga clic con el botón derecho para establecer el tipo de bloque objetivo
River Water Can=Lata de agua de río
Rubber Fiber=Fibra de Hule
Rubber Tree=Árbol de caucho
Save=Guardar
Sawdust=Aserrín
Self-Contained Injector=Inyector autónomo
Separating=Separación
Set region cross section:=Ajustar la sección transversal de la región:
Set region depth:=Establecer la profundidad de la región:
Set target=Fijar objetivo
Silicon Wafer=Oblea de Silicio
Silver=Plata
Single node.=Nodo simple.
Slot @1=Ranura @1
Small Solar @1 Generator=Panel Solar @1
Sonic Screwdriver (left-click rotates face, right-click rotates axis)=Destornillador sónico (clic izquierdo gira la cara, clic derecho gira el eje)
Sphere=Esfera
Stackwise=Stackwise
Stainless Steel=Acero Inoxidable
Start successful=Comienza con éxito
Start=Inicio
Stone=Piedra
Stop=Parada
Stopped=Detenido
Sulfur=Azufre
Supply Converter=Convertidor de Alimentacion
Switching Station=Estacion de Conmutacion
Talinite=Talinita
Tin=Estanio
Tree Tap=Grifo de Arbol
Unlocked=Desbloqueado
Upgrade Slots=Ranuras de mejora
Uranium Fuel=Combustible de Uranio
Use while sneaking to change Mining Drill Mk@1 modes.=Manten pulsado Mayus y Usar para cambiar el modo del Taladro de Mineria Mk@1.
Vacuum Cleaner=Aspirador
Water Can=Bidon de Agua
Wind @1 Generator=Molino de Viento @1
Wind Mill Frame=Armazon de Molino de Viento
Wrought Iron=Hierro Forjado
You are not allowed to edit this!=¡No está permitido editar esto!
Zinc=Zinc

View file

@ -0,0 +1,211 @@
# textdomain: technic
# French Translation for Technic Mod
# Traduction française pour Technic Mod
# by d-stephane
3 nodes deep.=3 noeuds de profondeur.
3 nodes tall.=3 noeuds de hauteur.
3 nodes wide.=3 noeuds de large.
3x3 nodes.=3x3 noeuds.
@1 (@2 @3 -> @4 @5)=@1 (@2 @3 -> @4 @5)
@1 (@2% Efficiency)=@1 (@2% Efficacité)
@1 (@2% Fuel Used)=@1 (@2% de carburant utilisé)
@1 (@2)=@1 (@2)
@1 Active (@2)=@1 actif (@2)
@1 Active=@1 actif
@1 Alloy Furnace=Four à alliage @1
@1 Battery Box: @2 / @3=1 Boîtier de batterie @2 / @3
@1 Battery Box=Batterie @1
@1 Cable Plate=1 plaque de câble
@1 Cable=Câble @1
@1 Centrifuge=Centrifugeuse @1
@1 Compressor=Compresseur @1
@1 Digiline Cable Plate=1 plaque de câble Digiline
@1 Digiline Cable=1 câble Digiline
@1 Disabled=@1 désactivé
@1 Dust=Poudre de @1
@1 Enabled=@1 activé
@1 Extractor=Extracteur @1
@1 Finished=@1 a fini
@1 Forcefield Emitter=Emetteur de champ de force @1
@1 Forcefield=1 champ de force
@1 Freezer=1 congélateur
@1 Furnace=Four @1
@1 Grinder=Broyeur @1
@1 Grinding=1 Meuleuse
@1 Has Bad Cabling=@1 est mal cablé
@1 Has No Network=@1 n'a pas de réseau
@1 Idle=@1 au repos
@1 Improperly Placed=@1 est mal placé
@1 LED=LED @1
@1 Lamp=1 lampe
@1 Music Player=Grammophone @1
@1 Network Overloaded, Restart in @2ms=1 réseau surchargé, redémarrage dans 2 ms
@1 Nuclear Reactor Core=Noyau de réacteur nucléaire @1
@1 Off=1 éteint
@1 Out Of Fuel=@1 plus de carburant
@1 Purging Cache=1 Cache de purge
@1 Quarry=Carrière @1
@1 Restarting Network=1 Redémarrage du réseau
@1 Tool Workshop=Atelier d'outillage @1
@1 Unpowered=@1 non alimenté en énergie
@1 is absent in @2 region=@1 est absent dans la région @2
@1 is empty=@1 est vide
@1 is present in @2 region=Le bloc @1 est présent dans la région @2
@1%-Fissile Uranium Block=Bloc d'uranium fissile à @1%.
@1%-Fissile Uranium Dust=Poussière d'uranium fissile à @1%.
@1%-Fissile Uranium Ingot=Lingot d'uranium fissile à @1%.
@1. Supply: @2 Demand: @3=Offre @1 : @2 Demande : @3
Acacia=Acacia
Accuracy:=Précision :
Administrative World Anchor=Ancre administrative du monde
Akalin=Akalin
Alatro=Alatro
Alloying=Alloying
Arol=Arol
Arrayed Solar @1 Generator=Générateur solaire @1
Automatic Start=Démarrage automatique
Blue Energy Crystal=Cristal d'énergie bleu
Brass=Laiton
Bronze=Bronze
Building Network: @1 Nodes=Réseau de construction : @1 Nœuds
Carbon Cloth=Fibre de carbone
Carbon Plate=Plaque de carbone
Carbon Steel=Acier au carbone
Cast Iron=Fonte
Chainsaw=Tronçonneuse
Charge=Charger
Chernobylite Block=Bloc de Tchernobylite
Chernobylite=Tchernobylite
Chromium=Chrome
Coal=Charbon
Common Tree=Arbre commun
Composite Plate=Plaque composite
Compressing=Compression
Constructor Mk@1=Constructeur Mk@1
Control Logic Unit=Unité de contrôle logique
Controlled by Mesecon Signal=Contrôlé par signal Mesecon
Copper Coil=Bobine de cuivre
Copper Plate=Plaque de cuivre
Copper=Cuivre
Corium Bucket=Seau de corium
Corium Source=Source de corium
Cube=Cube
Current target:=Cible actuelle :
Current track: @1=Piste actuelle : @1
Demand: @1=Demande : @1
Diamond Drill Head=Tête de forage en diamant
Digging @1 m below machine=Creusement à @1m en dessous de la machine
Digging finished=Creusement terminé
Digging not started=Creusement non démarré
Digiline Channel=Canal Digiline
Disabled=Désactivé
Discharge=Décharger
Doped Silicon Wafer=Tranche de silicium doppée
Dummy light source node=Nœud de source lumineuse factice
Enable Mesecons Control=Enable Mesecons Control
Enabled=Activé
Error=Erreur
Extracting=Extraction
Flashlight=Lampe-torche
Flowing Corium=Corium coulant
Freezing=Geler
Fuel-Fired @1 Generator=Générateur @1 alimenté au carburant
Fuel-Fired Alloy Furnace=Four à alliage alimenté au carburant
Fuel-Fired Furnace=Fourneau à combustible
Geothermal @1 Generator=Géénarteur géothermique @1
Gold=Or
Graphite=Graphite
Green Energy Crystal=Cristal d'énergie vert
Grinding=Broyage
HV=HV
High Voltage Transformer=Transformateur haute tension
Hydro @1 Generator=Générateur hydroélectrique @1
Ignoring Mesecon Signal=Ignorer le signal Mesecon
Input Power=Puissance d'entrée
Inventory move disallowed due to protection=Le mouvement d'inventaire n'est pas autorisé en raison de la protection
Itemwise=Item par Item
Kalite=Kalite
Keeping @1/@2 map blocks loaded=Garder @1/@2 blocs de carte chargés
LV=LV
Lava Can=Jerrycan de lave
Lead=Plomb
Locked=Verrouillé
Low Voltage Transformer=Transformateur basse tension
MV=MV
Machine Casing=Boîtier de la machine
Machine cannot be removed because it is not empty=La machine ne peut pas être retirée car elle n'est pas vide
Max Depth=Profondeur maximale
May set new target:=Peut fixer une nouvelle cible :
Medium Voltage Transformer=Transformateur moyenne tension
Mining Drill Mk@1 Mode @2=Foreuse Mk@1 Mode @2
Mining Drill Mk@1=Foreuse Mk@1
Mining Laser Mk@1=Foreuse laser Mk@1
Mithril=Mithril
Mixed Metal Ingot=Lingot de métal allié
Multimeter=Multimètre
Network Overloaded=Réseau surchargé
No new target available=Aucune nouvelle cible disponible
No target set=Aucune cible définie
Nuclear Reactor Rod Compartment=Compartiment à barres du réacteur nucléaire
Offset X=Décalage X
Offset Z=Décalage Z
Owner: @1=Propriétaire : @1
Polyfuse triggered, current efficiency: @1%, generated lag: @2 ms=Polyfuse déclenché, efficacité du courant : @1%, retard généré : @2 ms
Power Monitor Has No Network=Power Monitor n'a pas de réseau
Power Monitor. Supply: @1 Demand: @2=Power Monitor. Alimentation : @1 Demande : @2
Power Monitor=Moniteur de puissance
Power level=Niveau d'énergie
Prospector=Prospecteur
Purging cache=Purge du cache
RE Battery=Batterie RE
Radius=Rayon
Range=Plage
Raw Latex=Latex brut
Red Energy Crystal=Cristal d'énergie rouge
Region cross section:=Section transversale de la région :
Region depth:=Profondeur de la région :
Restart=Redémarrer
Right-click to set target block type=Cliquez avec le bouton droit de la souris pour définir le type de bloc cible
River Water Can=Bidon d'eau de rivière
Rubber Fiber=Fibre de caoutchouc
Rubber Tree=Arbre en caoutchouc
Save=Sauver
Sawdust=Sciure de bois
Self-Contained Injector=Injecteur autonome
Separating=Séparation
Set region cross section:=Définir la section transversale de la région :
Set region depth:=Définir la profondeur de la région :
Set target=Définir la cible
Silicon Wafer=Tranche de silicium
Silver=Argent
Single node.=Mode simple.
Slot @1=Emplacement @1
Small Solar @1 Generator=Petit générateur solaire @1
Sonic Screwdriver (left-click rotates face, right-click rotates axis)=Tournevis sonique (le clic gauche fait tourner la face, le clic droit fait tourner l'axe)
Sphere=Sphère
Stackwise=Stack par Stack
Stainless Steel=Acier inoxydable
Start successful=Démarrage réussi
Start=Démarrage
Stone=Pierre
Stop=Stop
Stopped=Arrêté
Sulfur=Soufre
Supply Converter=Convertisseur de tension
Switching Station=Station de commutation
Talinite=Talanite
Tin=Etain
Tree Tap=Robinet à sève
Unlocked=Déverrouillé
Upgrade Slots=Emplacement d'amélioration
Uranium Fuel=Uranium 235
Use while sneaking to change Mining Drill Mk@1 modes.=A utiliser en se faufilant pour changer les modes de la foreuse Mk@1.
Vacuum Cleaner=Aspirateur
Water Can=Jerrycan d'eau
Wind @1 Generator=Générateur éolien @1
Wind Mill Frame=Cadre d'éolienne
Wrought Iron=Fer
You are not allowed to edit this!=Vous n'êtes pas autorisé à modifier ceci !
Zinc=Zinc

View file

@ -0,0 +1,211 @@
# textdomain: technic
# Italian Translation for Technic Mod
# Traduzione italiana per Technic Mod
# by pagliaccio
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.
@1 (@2 @3 -> @4 @5)=@1 (@2 @3 -> @4 @5)
@1 (@2% Efficiency)=@1 (@2% Efficienza)
@1 (@2% Fuel Used)=@1 (@2% Carburante usato)
@1 (@2)=@1 (@2)
@1 Active (@2)=@1 Attivo (@2)
@1 Active=@1 Attivo
@1 Alloy Furnace=@1 Fornace per leghe
@1 Battery Box: @2 / @3=@1 Box batterie: @2 / @3
@1 Battery Box=@1 Box batterie
@1 Cable Plate=@1 Piastra per cavi
@1 Cable=Cavo @1
@1 Centrifuge=@1 Centrifuga
@1 Compressor=Compressore @1
@1 Digiline Cable Plate=@1 Piastra per cavi Digiline
@1 Digiline Cable=@1 Cavo Digiline
@1 Disabled=@1 Disabilitato
@1 Dust=Polvere di @1
@1 Enabled=@1 Abilitato
@1 Extractor=Estrattore @1
@1 Finished=@1 Finito
@1 Forcefield Emitter=Emettitore di campo di forza @1
@1 Forcefield=@1 Campo di forza
@1 Freezer=@1 Congelatore
@1 Furnace=@1 Fornace
@1 Grinder=@1 Tritatutto
@1 Grinding=@1 Rettifica
@1 Has Bad Cabling=@1 ha un cablaggio scorretto
@1 Has No Network=@1 non è collegata
@1 Idle=@1 Inattivo
@1 Improperly Placed=@1 Piazzato impropiamente
@1 LED=@1 LED
@1 Lamp=@1 Lampada
@1 Music Player=Music Player @1
@1 Network Overloaded, Restart in @2ms=@1 Rete sovraccarica, riavvio in @2ms
@1 Nuclear Reactor Core=@1 Nucleo del reattore nucleare
@1 Off=@1 Spento
@1 Out Of Fuel=@1 senza carburante
@1 Purging Cache=@1 Spurgo della cache
@1 Quarry=Cava @1
@1 Restarting Network=@1 Riavvio della rete
@1 Tool Workshop=Officina per attrezzi @1
@1 Unpowered=@1 Non alimentato
@1 is absent in @2 region=@1 è assente nella regione @2
@1 is empty=@1 è vuoto
@1 is present in @2 region=@1 è presente nella regione @2
@1%-Fissile Uranium Block=@1%-Blocco di uranio fissile
@1%-Fissile Uranium Dust=@1%-Polvere di Uranio Fissile
@1%-Fissile Uranium Ingot=@1%-Fissile Lingotto di Uranio
@1. Supply: @2 Demand: @3=@1. Fornitura: @2 Domanda: @3
Acacia=Acacia
Accuracy:=Precisione:
Administrative World Anchor=Ancora-mondo amministrativa
Akalin=Alcalino
Alatro=Alatro
Alloying=Lega
Arol=Arol
Arrayed Solar @1 Generator=@1 Pannello Solare
Automatic Start=Avvio automatico
Blue Energy Crystal=Cristallo energetico blu
Brass=Ottone
Bronze=Bronzo
Building Network: @1 Nodes=Rete di edifici: @1 Nodi
Carbon Cloth=Fibra di carbonio
Carbon Plate=Lastra in carbonio
Carbon Steel=Acciaio al Carbonio
Cast Iron=Ghisa
Chainsaw=Motosega
Charge=Carica
Chernobylite Block=Blocco di Chernobylite
Chernobylite=Cernobilite
Chromium=Cromo
Coal=Carbone
Common Tree=Albero comune
Composite Plate=Lastra composita
Compressing=Compressione
Constructor Mk@1=Costruttore Mk@1
Control Logic Unit=Unità di controllo logica
Controlled by Mesecon Signal=Controllato dal segnale Mesecon
Copper Coil=Bobina di rame
Copper Plate=Lastra di rame
Copper=Rame
Corium Bucket=Secchio di corium
Corium Source=Sorgente di corium
Cube=Cubo
Current target:=Obiettivo attuale:
Current track: @1=Traccia attuale: @1
Demand: @1=Domanda: @1
Diamond Drill Head=Trivella diamantata
Digging @1 m below machine=Scavo di @1 m sotto la macchina
Digging finished=Scavo finito
Digging not started=Scavo non iniziato
Digiline Channel=Canale Digiline
Disabled=Disabilitato
Discharge=Scarica
Doped Silicon Wafer=Wafer di silicone dopato
Dummy light source node=Nodo sorgente luminosa fittizio
Enable Mesecons Control=Abilita controllo Mesecons
Enabled=Abilitato
Error=Errore
Extracting=Estrazione
Flashlight=Torcia
Flowing Corium=Corium fluente
Freezing=Congelamento
Fuel-Fired @1 Generator=Generatore @1 alimentato a combustibile
Fuel-Fired Alloy Furnace=Forno a combustibile per leghe
Fuel-Fired Furnace=Forno a combustibile
Geothermal @1 Generator=@1 Generatore Geotermico
Gold=Oro
Graphite=Lastra in graffite
Green Energy Crystal=Cristallo energetico verde
Grinding=Macinazione
HV=HV
High Voltage Transformer=Trasformatore in alta tensione
Hydro @1 Generator=Turbina Elettrica @1
Ignoring Mesecon Signal=Ignorare il segnale Mesecon
Input Power=Potenza in ingresso
Inventory move disallowed due to protection=Impossibile muovere l'inventario a causa della protezione
Itemwise=Singolo elemento
Kalite=Kalite
Keeping @1/@2 map blocks loaded=Mantenimento di @1/@2 blocchi mappa caricati
LV=LV
Lava Can=Serbatoio di lava
Lead=Piombo
Locked=Chiuso a chiave
Low Voltage Transformer=Trasformatore in bassa tensione
MV=MV
Machine Casing=Involucro della macchina
Machine cannot be removed because it is not empty=La macchina non può essere rimossa perchè non è vuota
Max Depth=Profondità massima
May set new target:=Può impostare un nuovo obiettivo:
Medium Voltage Transformer=Trasformatore in media tensione
Mining Drill Mk@1 Mode @2=Trivella mk@1 in modalità @2
Mining Drill Mk@1=Trivella da miniera mk@1
Mining Laser Mk@1=Laser da miniera mk@1
Mithril=Mithril
Mixed Metal Ingot=Lingotto in lega ibrida
Multimeter=Multimetro
Network Overloaded=Rete sovraccarica
No new target available=Nessun nuovo obiettivo disponibile
No target set=Nessun obiettivo impostato
Nuclear Reactor Rod Compartment=Compartimento combustibile nucleare
Offset X=Offset X
Offset Z=Offset Z
Owner: @1=Proprietario: @1
Polyfuse triggered, current efficiency: @1%, generated lag: @2 ms=Polifusore attivato, efficienza di corrente: @1%, ritardo generato: @2 ms
Power Monitor Has No Network=Il Power Monitor non ha rete
Power Monitor. Supply: @1 Demand: @2=Monitoraggio dell'alimentazione. Alimentazione: @1 Domanda: @2
Power Monitor=Monitoraggio della potenza
Power level=Livello di potenza
Prospector=Prospettore
Purging cache=Spurgo della cache
RE Battery=Batteria RE
Radius=Raggio
Range=Raggio
Raw Latex=Latex grezzo
Red Energy Crystal=Cristallo energetico rosso
Region cross section:=Sezione trasversale della regione:
Region depth:=Profondità della regione:
Restart=Riavvio
Right-click to set target block type=Fare clic con il tasto destro del mouse per impostare il tipo di blocco di destinazione
River Water Can=Fiume Acqua Lattina
Rubber Fiber=Fibra di gomma
Rubber Tree=Albero di gomma
Save=Salva
Sawdust=Segatura
Self-Contained Injector=Iniettore autonomo
Separating=Separazione
Set region cross section:=Impostare la sezione trasversale della regione:
Set region depth:=Impostare la profondità della regione:
Set target=Impostare il target
Silicon Wafer=Wafer di silicone
Silver=Argento
Single node.=Nodo singolo.
Slot @1=Alloggio @1
Small Solar @1 Generator=@1 Pannello solare
Sonic Screwdriver (left-click rotates face, right-click rotates axis)=Cacciavite sonico (cliccando a sinistra si ruota la faccia, cliccando a destra si ruota l'asse)
Sphere=Sfera
Stackwise=pila completa
Stainless Steel=Acciaio Inossidabile
Start successful=Avvio riuscito
Start=Avvio
Stone=Pietra
Stop=Fermata
Stopped=Fermato
Sulfur=Zolfo
Supply Converter=Trasformatore
Switching Station=Stazione di controllo
Talinite=Talinite
Tin=Stagno
Tree Tap=Batti albero
Unlocked=Non chiuso a chiave
Upgrade Slots=Alloggi di aggiornamento
Uranium Fuel=Uranio Combustibile
Use while sneaking to change Mining Drill Mk@1 modes.=Premi shift (freccia grossa) e usa per cambiare modalità nella trivella da miniera Mk@1.
Vacuum Cleaner=Aspirapolvere
Water Can=Serbatoio d'acqua
Wind @1 Generator=@1 Generatore eolico
Wind Mill Frame=Pala eolica
Wrought Iron=Ferro Battuto
You are not allowed to edit this!=Non ti è permesso di modificarlo!
Zinc=Zinco

View file

@ -0,0 +1,211 @@
# textdomain: technic
# Polish Translation for Technic mod
# Polskie tłumaczenie Technic mod
# by mat9117
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.
@1 (@2 @3 -> @4 @5)=@1 (@2 @3 -> @4 @5)
@1 (@2% Efficiency)=@1 (@2% Wydajność)
@1 (@2% Fuel Used)=@1 (@2% Zużycie paliwa)
@1 (@2)=@1 (@2)
@1 Active (@2)=@1 Aktywny (@2)
@1 Active=@1 Aktywny/a
@1 Alloy Furnace=@1 Piec stopowy
@1 Battery Box: @2 / @3=@1 Pojemnik na baterie: @2 / @3
@1 Battery Box=@1 Skrzynka baterii
@1 Cable Plate=@1 Płytka kablowa
@1 Cable=@1 Przewód
@1 Centrifuge=@1 Centryfuga
@1 Compressor=@1 Kompresor
@1 Digiline Cable Plate=@1 Płytka kablowa Digiline
@1 Digiline Cable=@1 Kabel Digiline
@1 Disabled=@1 Wyłączony/a
@1 Dust=@1 Pył
@1 Enabled=@1 Włączony/a
@1 Extractor=@1 Ekstraktor
@1 Finished=@1 Ukończony
@1 Forcefield Emitter=@1 Emiter pola siłowego
@1 Forcefield=@1 Pole siłowe
@1 Freezer=@1 Zamrażarka
@1 Furnace=@1 Piec
@1 Grinder=@1 Młynek
@1 Grinding=@1 Szlifierka
@1 Has Bad Cabling=@1 Źle podłączono kable
@1 Has No Network=@1 Nie podłączony/a do sieci
@1 Idle=@1 Bezczynny/a
@1 Improperly Placed=@1 Ustawiony/a nieprawidłowo
@1 LED=@1 DIODA LED
@1 Lamp=@1 Lampa
@1 Music Player=@1 Odtwarzacz muzyki
@1 Network Overloaded, Restart in @2ms=@1 Sieć przeciążona, restart za @2ms
@1 Nuclear Reactor Core=@1 Rdzeń reaktora jądrowego
@1 Off=@1 Wyłączony
@1 Out Of Fuel=@1 brak paliwa
@1 Purging Cache=@1 Purging Cache
@1 Quarry=@1 Kamieniołom
@1 Restarting Network=@1 Restartowanie sieci
@1 Tool Workshop=@1 Warsztat narzędzi
@1 Unpowered=@1 brak zasilania
@1 is absent in @2 region=@1 jest nieobecny w regionie @2
@1 is empty=@1 jest pusty/a
@1 is present in @2 region=@1 jest obecny w regionie @2
@1%-Fissile Uranium Block=@1%-rozszczepialny blok uranu
@1%-Fissile Uranium Dust=@1%-Fissile Pył uranowy
@1%-Fissile Uranium Ingot=@1%-Fissile Uranium Ingot
@1. Supply: @2 Demand: @3=@1 Podaż: @2 Popyt: @3
Acacia=Acacia
Accuracy:=Dokładność:
Administrative World Anchor=Administracyjna kotwica świata
Akalin=Akalinowy
Alatro=Alatrowy
Alloying=Alatro
Arol=Arolowy
Arrayed Solar @1 Generator=@1 Szeregowy generator słoneczny
Automatic Start=Automatyczny start
Blue Energy Crystal=Niebieski kryształ energii
Brass=Mosiądzu
Bronze=Brązu
Building Network: @1 Nodes=Sieć budynków: @1 Węzły
Carbon Cloth=Włókno węglowe
Carbon Plate=Płytka węglowa
Carbon Steel=Stali węglowej
Cast Iron=Żeliwa
Chainsaw=Piła łańcuchowa
Charge=Ładuj
Chernobylite Block=Blok Czarnobylitowy
Chernobylite=Czarnobylit
Chromium=Chromu
Coal=Węglowy
Common Tree=Drzewo zwyczajne
Composite Plate=Płytka kompozytowa
Compressing=Kompresowanie
Constructor Mk@1=Konstruktor Mk@1
Control Logic Unit=Jednostka sterująca
Controlled by Mesecon Signal=Sterowany sygnałem Mesecon
Copper Coil=Miedziana cewka
Copper Plate=Płytka miedziana
Copper=Miedzi
Corium Bucket=Wiadro Korium
Corium Source=Źródło Korium
Cube=Cube
Current target:=Aktualny cel:
Current track: @1=Aktualna ścieżka: @1
Demand: @1=Popyt: @1
Diamond Drill Head=Diamentowa głowica wiertła
Digging @1 m below machine=Kopię @1 m pod maszyną
Digging finished=Kopanie skończone
Digging not started=Nie rozpoczęto kopania
Digiline Channel=Kanał Digiline
Disabled=Wyłączony/a
Discharge=Rozładuj
Doped Silicon Wafer=Domieszkowana płytka krzemowa
Dummy light source node=Sztuczny węzeł źródła światła
Enable Mesecons Control=Włączenie kontroli mezekonów
Enabled=Włączony/a
Error=Błąd
Extracting=Ekstrakcja
Flashlight=Latarka
Flowing Corium=Płynące Corium
Freezing=Zamrażanie
Fuel-Fired @1 Generator=Generator @1 zasilany paliwem
Fuel-Fired Alloy Furnace=Opalany paliwem piec stopowy
Fuel-Fired Furnace=Piec opalany paliwem
Geothermal @1 Generator=@1 Generator geotermalny
Gold=Złoty
Graphite=Grafit
Green Energy Crystal=Zielony kryształ energii
Grinding=Mielenie
HV=HV
High Voltage Transformer=Transformator wysokiego napięcia
Hydro @1 Generator=@1 Hydrogenerator
Ignoring Mesecon Signal=Ignoruj sygnał Mesecon
Input Power=Moc wejściowa
Inventory move disallowed due to protection=Przenoszenie rzeczy z ekwipunku niemożliwe z powodu ochrony
Itemwise=Jeden przedmiot
Kalite=Kalite
Keeping @1/@2 map blocks loaded=Ciągle ładuję @1/@2 bloki mapy
LV=LV
Lava Can=Kanister lawy
Lead=Ołów
Locked=Zablokowany/a
Low Voltage Transformer=Transformator niskiego napięcia
MV=MV
Machine Casing=Obudowa maszyny
Machine cannot be removed because it is not empty=Nie można usunąć maszyny, ponieważ nie jest pusta
Max Depth=Maksymalna głębokość
May set new target:=Może ustawić nowy cel:
Medium Voltage Transformer=Transformator średniego napięcia
Mining Drill Mk@1 Mode @2=Tryb wiertła górniczego Mk@1
Mining Drill Mk@1=Wiertło górnicze Mk@1
Mining Laser Mk@1=Laser górniczy Mk@1
Mithril=Mithrilu
Mixed Metal Ingot=Sztabka zmieszanych metali
Multimeter=Multimetr
Network Overloaded=Sieć przeciążona
No new target available=Brak nowego celu.
No target set=Nie ustawiono celu
Nuclear Reactor Rod Compartment=Komora rdzenia reaktora atomowego
Offset X=Przesunięcie X
Offset Z=Przesunięcie Z
Owner: @1=Właściciel: @1
Polyfuse triggered, current efficiency: @1%, generated lag: @2 ms=Polyfuse wyzwolony, wydajność prądowa: @1%, generowane opóźnienie: @2 ms
Power Monitor Has No Network=Power Monitor nie ma sieci
Power Monitor. Supply: @1 Demand: @2=Power Monitor. Zasilanie: @1 Zapotrzebowanie: @2
Power Monitor=Monitor mocy
Power level=Poziom zasilania
Prospector=Prospector
Purging cache=Oczyszczanie pamięci podręcznej
RE Battery=Bateria ładowalna
Radius=Promień
Range=Zasięg
Raw Latex=Lateks naturalny
Red Energy Crystal=Czerwony kryształ energii
Region cross section:=Przekrój regionu:
Region depth:=Głębokość regionu:
Restart=Uruchom ponownie
Right-click to set target block type=Kliknij prawym przyciskiem myszy, aby ustawić typ bloku docelowego
River Water Can=Rzeka Woda Puszka
Rubber Fiber=Włókno gumowe
Rubber Tree=Gumowe drzewo
Save=Zapisz
Sawdust=Trociny
Self-Contained Injector=Samodzielny iniektor
Separating=Oddzielanie
Set region cross section:=Ustaw przekrój regionu:
Set region depth:=Ustaw głębokość regionu:
Set target=Ustawić cel
Silicon Wafer=Płytka krzemowa
Silver=Srebrny
Single node.=Pojedynczy blok.
Slot @1=Otwór @1
Small Solar @1 Generator=@1 Mały generator słoneczny
Sonic Screwdriver (left-click rotates face, right-click rotates axis)=Śrubokręt dźwiękowy (lewe kliknięcie powoduje obrót twarzy, prawe kliknięcie powoduje obrót osi)
Sphere=Sfera
Stackwise=Cały stack
Stainless Steel=Stali nierdzewnej
Start successful=Początek udany
Start=Start
Stone=Kamień
Stop=Stop
Stopped=Zatrzymany/a
Sulfur=Siarka
Supply Converter=Konwerter zasilania
Switching Station=Rozdzielnia
Talinite=Talinitu
Tin=Cyny
Tree Tap=Nacinak drzewny
Unlocked=Odblokowany/a
Upgrade Slots=Miejsca na ulepszenia
Uranium Fuel=Paliwo uranowe
Use while sneaking to change Mining Drill Mk@1 modes.=Użyj podczas skradania, aby zmienić tryby wiertła górniczego Mk@1
Vacuum Cleaner=Vacuum Cleaner
Water Can=Kanister wody
Wind @1 Generator=@1 Generator wiatrowy
Wind Mill Frame=Klatka wiatraka
Wrought Iron=Kutego żelaza
You are not allowed to edit this!=Nie możesz tego edytować!
Zinc=Cynku

View file

@ -0,0 +1,211 @@
# textdomain: technic
# Braziliam portuguese translation for technic
# Tradução portuguesa brasileira para technic
# By Sires
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.
@1 (@2 @3 -> @4 @5)=@1 (@2 @3 -> @4 @5)
@1 (@2% Efficiency)=@1 (@2% Eficiência)
@1 (@2% Fuel Used)=@1 (@2% Combustível utilizado)
@1 (@2)=@1 (@2)
@1 Active (@2)=@1 Ativo (@2)
@1 Active=@1 Ativo
@1 Alloy Furnace=Fornalha de Liga @1
@1 Battery Box: @2 / @3=@1 Caixa de bateria: @2 / @3
@1 Battery Box=Caixa de Bateria @1
@1 Cable Plate=@1 Placa de cabo
@1 Cable=Cabo @1
@1 Centrifuge=Centrifuga @1
@1 Compressor=Compresso @1
@1 Digiline Cable Plate=@1 Placa de cabo Digiline
@1 Digiline Cable=@1 Cabo Digilino
@1 Disabled=@1 Ativado
@1 Dust=Pó de @1
@1 Enabled=@1 Desativado
@1 Extractor=Extrator @1
@1 Finished=@1 Acabou
@1 Forcefield Emitter=Emissor de Campo de Força @1
@1 Forcefield=@1 Campo de Força
@1 Freezer=@1 Freezer
@1 Furnace=Fornalha @1
@1 Grinder=Triturador @1
@1 Grinding=@1 Moagem
@1 Has Bad Cabling=@1 Tem Cabeamento Ruim
@1 Has No Network=@1 Não Tem Rede
@1 Idle=Ócio
@1 Improperly Placed=@1 Colocado Inapropriadamente
@1 LED=@1 LED
@1 Lamp=@1 Lâmpada
@1 Music Player=Tocador de Música @1
@1 Network Overloaded, Restart in @2ms=@1 Sobrecarga da Rede, Reiniciar em @2ms
@1 Nuclear Reactor Core=@1 Núcleo do Reator Nuclear
@1 Off=@1 Off
@1 Out Of Fuel=@1 Sem Combustível
@1 Purging Cache=@1 Cache de Purgar
@1 Quarry=Pedreira @1
@1 Restarting Network=@1 Rede de Reinício
@1 Tool Workshop=Oficina de Ferramentas @1
@1 Unpowered=@1 Sem energia
@1 is absent in @2 region=@1 está ausente em @2 região
@1 is empty=@1 está vazio
@1 is present in @2 region=@1 está presente em @2 região
@1%-Fissile Uranium Block=@1%-Fissile Uranium Block
@1%-Fissile Uranium Dust=@1%-Pó de Urânio Físsil
@1%-Fissile Uranium Ingot=@1%-Uranio Fissile Ingot
@1. Supply: @2 Demand: @3=1. fornecimento: @2 Demanda: @3
Acacia=Acacia
Accuracy:=Precisão:
Administrative World Anchor=Âncora de Mundo Administrativa
Akalin=Akalin
Alatro=Alatro
Alloying=Ligas
Arol=Arol
Arrayed Solar @1 Generator=Gerador Solar Equipado @1
Automatic Start=Início automático
Blue Energy Crystal=Cristal de Energia Azul
Brass=Latão
Bronze=Bronze
Building Network: @1 Nodes=Rede de Construção Civil: @1 Nodos
Carbon Cloth=Recido de Carbono
Carbon Plate=Placa de Carbono
Carbon Steel=Aço Carbono
Cast Iron=Ferro Fundido
Chainsaw=Motosserra
Charge=Carregar
Chernobylite Block=Bloco de Chernobylite
Chernobylite=Chernobylite
Chromium=Crômio
Coal=Carvão
Common Tree=Árvore comum
Composite Plate=Placa Composta
Compressing=Comprimindo
Constructor Mk@1=Construtor Nv@1
Control Logic Unit=Unidade de Controle Lógico
Controlled by Mesecon Signal=Controlado por Sinal de Mesecon
Copper Coil=Bobina de Cobre
Copper Plate=Placa de Cobre
Copper=Cobre
Corium Bucket=Balde de Cório
Corium Source=Fonte de Cório
Cube=Cube
Current target:=Meta atual:
Current track: @1=Pista atual: @1
Demand: @1=Demanda: @1
Diamond Drill Head=Cabeça de Broca de Diamante
Digging @1 m below machine=Escavando @1 m abaixo da máquina
Digging finished=Escavação terminada
Digging not started=Escavação não começada
Digiline Channel=Canal Digiline
Disabled=Desativado
Discharge=Descarregar
Doped Silicon Wafer=Pastilha de Silício Dopada
Dummy light source node=Nó de fonte de luz idiota
Enable Mesecons Control=Habilitar o Controle de Mesecons
Enabled=Ativado
Error=Erro
Extracting=Extraindo
Flashlight=Lanterna
Flowing Corium=Cório Fluente
Freezing=Congelamento
Fuel-Fired @1 Generator=Gerador de combustível @1
Fuel-Fired Alloy Furnace=Forno de Liga Combustível
Fuel-Fired Furnace=Forno a combustível
Geothermal @1 Generator=Gerador Geotermal @1
Gold=Ouro
Graphite=Grafite
Green Energy Crystal=Cristal de Energia Verde
Grinding=Triturando
HV=HV
High Voltage Transformer=Transformador de Alta Voltagem
Hydro @1 Generator=Gerador Hidráulico @1
Ignoring Mesecon Signal=Ignorar Sinaal de Mesecon
Input Power=Potência de entrada
Inventory move disallowed due to protection=Movimento de inventário não permitido pela proteção
Itemwise=Por item
Kalite=Kalite
Keeping @1/@2 map blocks loaded=Mantendo @1/@2 blocos de mapa carregados
LV=LV
Lava Can=Lata de Lava
Lead=Chumbo
Locked=Travado
Low Voltage Transformer=Transformador de Baixa Voltagem
MV=MV
Machine Casing=Caixa da máquina
Machine cannot be removed because it is not empty=A máquina não pode ser removida porque ela não está vazia
Max Depth=Profundidade máxima
May set new target:=Pode estabelecer uma nova meta:
Medium Voltage Transformer=Transformador de Média Voltagem
Mining Drill Mk@1 Mode @2=Broca de Mineração Nv@1 Modo @2
Mining Drill Mk@1=Broca de Mineração Nv@1
Mining Laser Mk@1=Laser de Mineração Nv@1
Mithril=Mithril
Mixed Metal Ingot=Lingote de Metal Misturado
Multimeter=Multímetro
Network Overloaded=Sobrecarga da rede
No new target available=Nenhuma nova meta disponível
No target set=Nenhuma meta estabelecida
Nuclear Reactor Rod Compartment=Compartimento de Barra do Reator Nuclear
Offset X=Offset X
Offset Z=Offset Z
Owner: @1=Proprietário: @1
Polyfuse triggered, current efficiency: @1%, generated lag: @2 ms=Polifusível acionado, eficiência atual: @1%, gerou atraso: @2 ms
Power Monitor Has No Network=O Power Monitor não possui rede
Power Monitor. Supply: @1 Demand: @2=Monitor de energia. Fornecimento: Demanda @1: @2
Power Monitor=Monitor de energia
Power level=Nível de Energia
Prospector=Prospector
Purging cache=Cache de purga
RE Battery=Bateria RE
Radius=Radius
Range=Alcance
Raw Latex=Latex bruto
Red Energy Crystal=Cristal de Energia Vermelho
Region cross section:=Seção transversal da região:
Region depth:=Profundidade da região:
Restart=Reiniciar
Right-click to set target block type=Clique com o botão direito do mouse para definir o tipo de bloco alvo
River Water Can=Lata de água do rio
Rubber Fiber=Fibra de Borracha
Rubber Tree=Seringueira
Save=Salvar
Sawdust=Serradura
Self-Contained Injector=Injetor autônomo
Separating=Separando
Set region cross section:=Definir a seção transversal da região:
Set region depth:=Profundidade da região definida:
Set target=Objetivo definido
Silicon Wafer=Pastilha de Silício
Silver=Prata
Single node.=Unico node.
Slot @1=Lugar @1
Small Solar @1 Generator=Gerador Solar Pequeno @1
Sonic Screwdriver (left-click rotates face, right-click rotates axis)=Chave de fenda sônica (clique esquerdo gira face, clique direito gira eixo)
Sphere=Esfera
Stackwise=Por pilha
Stainless Steel=Aço Inoxidável
Start successful=Comece com sucesso
Start=Início
Stone=Pedra
Stop=Parada
Stopped=Parado
Sulfur=Enxofre
Supply Converter=Conversor de Energia
Switching Station=Estação de Comutação
Talinite=Talinite
Tin=Estanho
Tree Tap=Torneira de Árvore
Unlocked=Destravado
Upgrade Slots=Lugares para Melhoria
Uranium Fuel=Combustivel de Urânio
Use while sneaking to change Mining Drill Mk@1 modes.=Use enquanto esgueirando para mudar os modos da Broca de Mineração Nv@1.
Vacuum Cleaner=Aspirador de pó
Water Can=Lata de Água
Wind @1 Generator=Gerador de Energia Eólica @1
Wind Mill Frame=Armação de Moinho de Vento
Wrought Iron=Ferro Forjado
You are not allowed to edit this!=Você não está autorizado a editar isto!
Zinc=Zinco

View file

@ -0,0 +1,211 @@
# textdomain: technic
# Chinese Translation for Technic Mod
# 技术模型的中文翻译
# by wzy2006 <3450354617@qq.com>
3 nodes deep.=3方块深度。
3 nodes tall.=3方块高。
3 nodes wide.=3方块宽。
3x3 nodes.=3x3 方块.。
@1 (@2 @3 -> @4 @5)=@1 (@2 @3 -> @4 @5)
@1 (@2% Efficiency)=@1 (@2% 效率)
@1 (@2% Fuel Used)=@1 (@2% 燃料使用)
@1 (@2)=@1 (@2)
@1 Active (@2)=@1 活跃 (@2)
@1 Active=@1 活动
@1 Alloy Furnace=@1 合金炉
@1 Battery Box: @2 / @3=@1 电池盒。@2 / @3
@1 Battery Box=% s电池盒
@1 Cable Plate=@1个电缆板
@1 Cable=@1 电缆
@1 Centrifuge=@1个离心机
@1 Compressor=@1 压缩机
@1 Digiline Cable Plate=@1台Digiline电缆板
@1 Digiline Cable=@1个数字线电缆
@1 Disabled=@1 禁用
@1 Dust=@1 粉
@1 Enabled=@1 启用
@1 Extractor=@1 提取机
@1 Finished=@1 完成
@1 Forcefield Emitter=@1 力场发射器
@1 Forcefield=@1 力场
@1 Freezer=@1 冷藏室
@1 Furnace=@1 熔炉
@1 Grinder=@1 研磨机
@1 Grinding=@1 研磨
@1 Has Bad Cabling=@1 布线不良
@1 Has No Network=@1 未并入电网(也许需要"交换站")
@1 Idle=@1 闲置
@1 Improperly Placed=@1 放置不当
@1 LED=@1 LED
@1 Lamp=@1 灯
@1 Music Player=@1 音乐播放器
@1 Network Overloaded, Restart in @2ms=@1 网络过载,在@2ms内重新启动
@1 Nuclear Reactor Core=@1 核反应堆核心
@1 Off=@1 关闭
@1 Out Of Fuel=@1 燃料耗尽
@1 Purging Cache=@1 清理缓存
@1 Quarry=% s采石机
@1 Restarting Network=@1 重新启动网络
@1 Tool Workshop=% s工具车间
@1 Unpowered=@1 无能量的
@1 is absent in @2 region=@1在@2地区不存在
@1 is empty=@1是空的
@1 is present in @2 region=@1在@2地区存在
@1%-Fissile Uranium Block=@1%-裂变铀块
@1%-Fissile Uranium Dust=@1%-裂变铀粉
@1%-Fissile Uranium Ingot=@1%-裂变铀锭
@1. Supply: @2 Demand: @3=@1.供应。 @2需求。 @3
Acacia=金合欢
Accuracy:=准确度。
Administrative World Anchor=管理员区块锚
Akalin=Akalin
Alatro=Alatro
Alloying=合金化
Arol=Arol
Arrayed Solar @1 Generator=太阳能@1发电板
Automatic Start=自动启动
Blue Energy Crystal=蓝色能量水晶
Brass=黄铜
Bronze=青铜
Building Network: @1 Nodes=建筑网络。@1个节点
Carbon Cloth=碳布
Carbon Plate=碳板
Carbon Steel=碳钢
Cast Iron=铸铁
Chainsaw=电锯
Charge=Charge
Chernobylite Block=切尔诺贝利石块
Chernobylite=切尔诺贝利特
Chromium=铬
Coal=煤炭
Common Tree=普通树木
Composite Plate=复合材料板
Compressing=压缩
Constructor Mk@1=建造器@1
Control Logic Unit=控制逻辑单元
Controlled by Mesecon Signal=由Mesecon信号控制
Copper Coil=铜盘管
Copper Plate=铜板
Copper=铜
Corium Bucket=镭射桶
Corium Source=镭射源
Cube=立方体
Current target:=目前的目标。
Current track: @1=目前的轨道。@1
Demand: @1=需求。 @1
Diamond Drill Head=金刚石钻头
Digging @1 m below machine=挖掘 @1 m以下的机器
Digging finished=挖完
Digging not started=没有开始挖掘
Digiline Channel=数字通道
Disabled=禁用
Discharge=Discharge
Doped Silicon Wafer=硅芯片
Dummy light source node=虚拟光源节点
Enable Mesecons Control=启用中子控制
Enabled=启用
Error=误差
Extracting=提取
Flashlight=手电筒
Flowing Corium=流动珊瑚
Freezing=冷冻
Fuel-Fired @1 Generator=燃料加热的@1发电机
Fuel-Fired Alloy Furnace=燃料燃烧的合金炉
Fuel-Fired Furnace=燃料加热炉
Geothermal @1 Generator=地热@1发电机
Gold=黄金
Graphite=石墨
Green Energy Crystal=绿色能源水晶
Grinding=研磨中
HV=晶体
High Voltage Transformer=高压变压器
Hydro @1 Generator=水力@1 发电机
Ignoring Mesecon Signal=忽略Mesecon信号
Input Power=输入功率
Inventory move disallowed due to protection=库存移动不允许由于保护
Itemwise=逐项
Kalite=卡利特
Keeping @1/@2 map blocks loaded=保持@1/@2地图模块加载
LV=消耗品
Lava Can=岩浆罐
Lead=铅
Locked=锁着的
Low Voltage Transformer=低压变压器
MV=中压
Machine Casing=机器外壳
Machine cannot be removed because it is not empty=机器不能被拆除,因为它不是空的
Max Depth=最大深度
May set new target:=可以设置新的目标。
Medium Voltage Transformer=中压变压器
Mining Drill Mk@1 Mode @2=采矿钻 MK@1模式@2
Mining Drill Mk@1=采矿钻 MK@1
Mining Laser Mk@1=采矿激光 MK @1
Mithril=秘银
Mixed Metal Ingot=混合金属锭
Multimeter=万用表
Network Overloaded=网络过载
No new target available=没有新目标可用
No target set=没有设定目标
Nuclear Reactor Rod Compartment=核反应堆舱
Offset X=偏移 X
Offset Z=偏移量Z
Owner: @1=所有者。@1
Polyfuse triggered, current efficiency: @1%, generated lag: @2 ms=多重熔断器被触发,电流效率。@1%,产生滞后。@2毫秒
Power Monitor Has No Network=电源监控器没有网络
Power Monitor. Supply: @1 Demand: @2=电源监控器。供应。@1 需求。@2
Power Monitor=功率监控器
Power level=功率级
Prospector=探测仪
Purging cache=净化缓存
RE Battery=RE 电池
Radius=半径
Range=范围
Raw Latex=生乳胶
Red Energy Crystal=红色能量水晶
Region cross section:=区域横截面。
Region depth:=区域深度。
Restart=重新启动
Right-click to set target block type=右键设置目标块类型
River Water Can=河水罐
Rubber Fiber=橡胶纤维
Rubber Tree=橡胶树
Save=保存
Sawdust=锯末
Self-Contained Injector=自带的注射器
Separating=分离式
Set region cross section:=设置区域横截面。
Set region depth:=设置区域深度。
Set target=设置目标
Silicon Wafer=硅晶片
Silver=银
Single node.=单方块。
Slot @1=插槽 @1
Small Solar @1 Generator=小型太阳能@1发电板
Sonic Screwdriver (left-click rotates face, right-click rotates axis)=音速螺丝刀(左键旋转面,右键旋转轴)
Sphere=球体
Stackwise=逐堆
Stainless Steel=不锈钢
Start successful=启动成功
Start=启动
Stone=石头
Stop=停止
Stopped=停止
Sulfur=硫磺
Supply Converter=电源转换器
Switching Station=交换站
Talinite=绿泥石
Tin=锡
Tree Tap=树形水龙头
Unlocked=解锁
Upgrade Slots=升级插槽
Uranium Fuel=铀燃料
Use while sneaking to change Mining Drill Mk@1 modes.=潜行时使用可更改采矿钻机Mk@1模式
Vacuum Cleaner=真空清洁器
Water Can=水罐
Wind @1 Generator=风力@1发电机
Wind Mill Frame=风力机框架
Wrought Iron=锻铁
You are not allowed to edit this!=你不允许编辑这个!
Zinc=锌

View file

@ -0,0 +1,208 @@
# textdomain: technic
3 nodes deep.=
3 nodes tall.=
3 nodes wide.=
3x3 nodes.=
@1 (@2 @3 -> @4 @5)=
@1 (@2% Efficiency)=
@1 (@2% Fuel Used)=
@1 (@2)=
@1 Active (@2)=
@1 Active=
@1 Alloy Furnace=
@1 Battery Box: @2 / @3=
@1 Battery Box=
@1 Cable Plate=
@1 Cable=
@1 Centrifuge=
@1 Compressor=
@1 Digiline Cable Plate=
@1 Digiline Cable=
@1 Disabled=
@1 Dust=
@1 Enabled=
@1 Extractor=
@1 Finished=
@1 Forcefield Emitter=
@1 Forcefield=
@1 Freezer=
@1 Furnace=
@1 Grinder=
@1 Grinding=
@1 Has Bad Cabling=
@1 Has No Network=
@1 Idle=
@1 Improperly Placed=
@1 LED=
@1 Lamp=
@1 Music Player=
@1 Network Overloaded, Restart in @2ms=
@1 Nuclear Reactor Core=
@1 Off=
@1 Out Of Fuel=
@1 Purging Cache=
@1 Quarry=
@1 Restarting Network=
@1 Tool Workshop=
@1 Unpowered=
@1 is absent in @2 region=
@1 is empty=
@1 is present in @2 region=
@1%-Fissile Uranium Block=
@1%-Fissile Uranium Dust=
@1%-Fissile Uranium Ingot=
@1. Supply: @2 Demand: @3=
Acacia=
Accuracy:=
Administrative World Anchor=
Akalin=
Alatro=
Alloying=
Arol=
Arrayed Solar @1 Generator=
Automatic Start=
Blue Energy Crystal=
Brass=
Bronze=
Building Network: @1 Nodes=
Carbon Cloth=
Carbon Plate=
Carbon Steel=
Cast Iron=
Chainsaw=
Charge=
Chernobylite Block=
Chernobylite=
Chromium=
Coal=
Common Tree=
Composite Plate=
Compressing=
Constructor Mk@1=
Control Logic Unit=
Controlled by Mesecon Signal=
Copper Coil=
Copper Plate=
Copper=
Corium Bucket=
Corium Source=
Cube=
Current target:=
Current track: @1=
Demand: @1=
Diamond Drill Head=
Digging @1 m below machine=
Digging finished=
Digging not started=
Digiline Channel=
Disabled=
Discharge=
Doped Silicon Wafer=
Dummy light source node=
Enable Mesecons Control=
Enabled=
Error=
Extracting=
Flashlight=
Flowing Corium=
Freezing=
Fuel-Fired @1 Generator=
Fuel-Fired Alloy Furnace=
Fuel-Fired Furnace=
Geothermal @1 Generator=
Gold=
Graphite=
Green Energy Crystal=
Grinding=
HV=
High Voltage Transformer=
Hydro @1 Generator=
Ignoring Mesecon Signal=
Input Power=
Inventory move disallowed due to protection=
Itemwise=
Kalite=
Keeping @1/@2 map blocks loaded=
LV=
Lava Can=
Lead=
Locked=
Low Voltage Transformer=
MV=
Machine Casing=
Machine cannot be removed because it is not empty=
Max Depth=
May set new target:=
Medium Voltage Transformer=
Mining Drill Mk@1 Mode @2=
Mining Drill Mk@1=
Mining Laser Mk@1=
Mithril=
Mixed Metal Ingot=
Multimeter=
Network Overloaded=
No new target available=
No target set=
Nuclear Reactor Rod Compartment=
Offset X=
Offset Z=
Owner: @1=
Polyfuse triggered, current efficiency: @1%, generated lag: @2 ms=
Power Monitor Has No Network=
Power Monitor. Supply: @1 Demand: @2=
Power Monitor=
Power level=
Prospector=
Purging cache=
RE Battery=
Radius=
Range=
Raw Latex=
Red Energy Crystal=
Region cross section:=
Region depth:=
Restart=
Right-click to set target block type=
River Water Can=
Rubber Fiber=
Rubber Tree=
Save=
Sawdust=
Self-Contained Injector=
Separating=
Set region cross section:=
Set region depth:=
Set target=
Silicon Wafer=
Silver=
Single node.=
Slot @1=
Small Solar @1 Generator=
Sonic Screwdriver (left-click rotates face, right-click rotates axis)=
Sphere=
Stackwise=
Stainless Steel=
Start successful=
Start=
Stone=
Stop=
Stopped=
Sulfur=
Supply Converter=
Switching Station=
Talinite=
Tin=
Tree Tap=
Unlocked=
Upgrade Slots=
Uranium Fuel=
Use while sneaking to change Mining Drill Mk@1 modes.=
Vacuum Cleaner=
Water Can=
Wind @1 Generator=
Wind Mill Frame=
Wrought Iron=
You are not allowed to edit this!=
Zinc=

View file

@ -0,0 +1,21 @@
-- 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("technic:hv_battery_box", {
tier = "HV",
max_charge = 1000000,
charge_rate = 100000,
discharge_rate = 400000,
charge_step = 10000,
discharge_step = 40000,
upgrade = 1,
tube = 1,
})

View file

@ -0,0 +1,54 @@
local S = technic.getter
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'},
}
})
minetest.register_craft({
output = "technic:hv_cable_plate_1 5",
recipe = {
{"" , "" , "technic:hv_cable"},
{"technic:hv_cable", "technic:hv_cable", "technic:hv_cable"},
{"" , "" , "technic:hv_cable"},
}
})
minetest.register_craft({
output = "technic:hv_cable",
recipe = {{"technic:hv_cable_plate_1"}}
})
-- Register cables
technic.register_cable("technic:hv_cable", {
tier = "HV",
size = 3/16,
description = S("@1 Cable", S("HV"))
})
technic.register_cable_plate("technic:hv_cable_plate", {
tier = "HV",
size = 3/16,
description = S("@1 Cable Plate", S("HV")),
tiles = {"technic_hv_cable.png"},
})
if minetest.get_modpath("digilines") then
technic.register_cable("technic:hv_digi_cable", {
tier = "HV",
size = 3/16,
description = S("@1 Digiline Cable", S("HV")),
digiline = { wire = { rules = technic.digilines.rules_allfaces } }
})
technic.register_cable_plate("technic:hv_digi_cable_plate", {
tier = "HV",
size = 3/16,
description = S("@1 Digiline Cable Plate", S("HV")),
digiline = { wire = { rules = technic.digilines.rules_allfaces } },
tiles = {"technic_hv_digi_cable.png"}
})
end

View file

@ -0,0 +1,21 @@
-- HV compressor
local S = technic.getter
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_base_machine("technic:hv_compressor", {
typename = "compressing",
description = S("@1 Compressor", S("HV")),
tier = "HV",
demand = {1500, 1000, 750},
speed = 5,
upgrade = 1,
tube = 1
})

View file

@ -0,0 +1,26 @@
-- 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.
local S = technic.getter
-- 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_base_machine("technic:hv_electric_furnace", {
typename = "cooking",
description = S("@1 Furnace", S("HV")),
tier="HV",
upgrade=1,
tube=1,
demand={4000, 2500, 1500},
speed=12
})

View file

@ -0,0 +1,400 @@
--- 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"
local mat = technic.materials
minetest.register_craft({
output = "technic:forcefield_emitter_off",
recipe = {
{mat.mese, "basic_materials:motor", mat.mese },
{"technic:deployer_off", "technic:machine_casing", "technic:deployer_off"},
{mat.mese, "technic:hv_cable", mat.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;"..S("Digiline Channel")..";${channel}]"
else
formspec = "size[5,2.25]"
end
formspec = formspec..
"field[0.3,0.5;2,1;range;"..S("Range")..";${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("@1 Disabled", S("@1 Forcefield Emitter", S("HV"))).."]"
else
formspec = formspec..
"button[0,1.75;5,1;disable;"..S("@1 Enabled", S("@1 Forcefield Emitter", S("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, S("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("@1 Forcefield Emitter", S("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("@1 Disabled", 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("@1 Unpowered", 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("@1 Active", machine_name) .. "\n" ..
S("Demand: @1", technic.EU_string(power_requirement)))
end
update_forcefield(pos, meta, true)
end
end
minetest.register_node("technic:forcefield_emitter_off", {
description = S("@1 Forcefield Emitter", S("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, pickaxey = 3},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
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("@1 Forcefield Emitter", S("HV")))
set_forcefield_formspec(meta)
end,
mesecons = mesecons,
digiline = digiline_def,
technic_run = run,
})
minetest.register_node("technic:forcefield_emitter_on", {
description = S("@1 Forcefield Emitter", S("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, pickaxey = 3},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
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("@1 Forcefield", S("HV")),
sunlight_propagates = true,
drawtype = "glasslike",
groups = {not_in_creative_inventory=1},
is_ground_content = false,
paramtype = "light",
light_source = minetest.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)

View file

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

View file

@ -0,0 +1,21 @@
-- HV grinder
local S = technic.getter
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_base_machine("technic:hv_grinder", {
typename = "grinding",
description = S("@1 Grinder", S("HV")),
tier="HV",
demand={1200, 900, 600},
speed=5,
upgrade=1,
tube=1
})

View file

@ -0,0 +1,20 @@
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")

View file

@ -0,0 +1,557 @@
--[[
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 100000 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 has_mcl = minetest.get_modpath("mcl_core")
local mat = technic.materials
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', mat.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 size = minetest.get_modpath("mcl_formspec") and "size[9,9]" or "size[8,9]"
local function make_reactor_formspec(meta)
local f = size..
"label[0,0;"..S("Nuclear Reactor Rod Compartment").."]"..
"list[context;src;2,1;3,2;]"..
"listring[context;src]"..
"button[5.5,1.5;2,1;start;"..S("Start").."]"..
"checkbox[5.5,2.5;autostart;"..S("Automatic Start")..";"..meta:get_string("autostart").."]"
if has_mcl then
f = f..
mcl_formspec.get_itemslot_bg(2,1,3,2)..
-- player inventory
"list[current_player;main;0,4.5;9,3;9]"..
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
"list[current_player;main;0,7.74;9,1;]"..
mcl_formspec.get_itemslot_bg(0,7.74,9,1)..
"listring[current_player;main]"
else
f = f..
"list[current_player;main;0,5;8,4;]"..
"listring[current_player;main]"
end
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;"..S("Save").."]"..
"field[1,4;4,1;channel;"..S("Digiline Channel")..";${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(mat.water_source)
local c_water_flowing = minetest.get_content_id(mat.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 mcl_expl_info = {
drop_chance = 1.0,
max_blast_resistance = 10,
sound = true,
particles = true,
fire = true,
griefing = true,
grief_protected = true,
}
local function melt_down_reactor(pos)
minetest.log("action", "A reactor melted down at "..minetest.pos_to_string(pos))
if minetest.get_modpath("mcl_explosions") then
mcl_explosions.explode(pos, 30, mcl_expl_info)
end
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_allfaces,
-- TODO: Remove "remote_channel" and use de facto standard "channel"
meta:get("channel") or 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("@1 Idle", 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", S("@1 (@2% Fuel Used)", 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, S("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.channel or fields.remote_channel then
-- TODO: Remove "remote_channel" and use de facto standard "channel"
meta:set_string("remote_channel", fields.channel or fields.remote_channel)
meta:set_string("channel", fields.channel or fields.remote_channel)
end
if fields.start then
local b = start_reactor(pos, meta)
if b then
minetest.chat_send_player(player_name, S("Start successful"))
else
minetest.chat_send_player(player_name, S("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
-- TODO: Remove "remote_channel" and use de facto standard "channel"
channel ~= (meta:get("channel") or 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_allfaces, 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_allfaces, channel, {
command = "start_success",
pos = pos
})
else
digilines.receptor_send(pos, technic.digilines.rules_allfaces, 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, pickaxey = 3},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
legacy_facedir_simple = true,
sounds = technic.sounds.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))
local inv = meta:get_inventory()
inv:set_size("src", 6)
end,
-- digiline interface
digiline = {
receptor = {
rules = technic.digilines.rules_allfaces,
action = function() end,
},
effector = {
rules = technic.digilines.rules_allfaces,
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,
on_metadata_inventory_move = technic.machine_on_inventory_move,
on_metadata_inventory_put = technic.machine_on_inventory_put,
on_metadata_inventory_take = technic.machine_on_inventory_take,
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, pickaxey = 3},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
legacy_facedir_simple = true,
sounds = technic.sounds.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_allfaces,
action = function() end,
},
effector = {
rules = technic.digilines.rules_allfaces,
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,
on_metadata_inventory_move = technic.machine_on_inventory_move,
on_metadata_inventory_put = technic.machine_on_inventory_put,
on_metadata_inventory_take = technic.machine_on_inventory_take,
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)

View file

@ -0,0 +1,640 @@
local S = technic.getter
local has_digilines = minetest.get_modpath("digilines")
local has_mesecons = minetest.get_modpath("mesecons")
local has_vizlib = minetest.get_modpath("vizlib")
local has_jumpdrive = minetest.get_modpath("jumpdrive")
local has_mcl = minetest.get_modpath("mcl_formspec")
local quarry_max_depth = technic.config:get_int("quarry_max_depth")
local quarry_dig_particles = technic.config:get_bool("quarry_dig_particles")
local quarry_time_limit = technic.config:get_int("quarry_time_limit")
local quarry_demand = 10000
local network_time_limit = 30000
local infotext
do
local name = S("@1 Quarry", S("HV"))
local demand = S("Demand: @1", technic.EU_string(quarry_demand))
infotext = {
active = S("@1 Active", name).."\n"..demand,
disabled = S("@1 Disabled", name),
finished = S("@1 Finished", name),
purge = S("@1 Purging Cache", name),
unpowered = S("@1 Unpowered", name),
}
end
-- Hard-coded outward-spiral dig pattern for up to 17x17 dig area
local 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
}
-- Convert the dig pattern values to x/z offset vectors
do
local head = vector.new()
dig_pattern[0] = head
for i = 1, #dig_pattern do
head = vector.add(head, minetest.facedir_to_dir(dig_pattern[i]))
dig_pattern[i] = {x = head.x, z = head.z}
end
end
-- Cache of pipeworks fake players
local fake_players = {}
minetest.register_on_leaveplayer(function(player)
fake_players[player:get_player_name()] = nil
end)
local function get_fake_player(name)
if not fake_players[name] then
fake_players[name] = pipeworks.create_fake_player({name = name})
end
return fake_players[name]
end
local function player_allowed(pos, name)
local owner = minetest.get_meta(pos):get_string("owner")
if owner == "" or owner == name then
return true
end
return not minetest.is_protected(pos, name)
end
local function can_dig_node(pos, dig_pos, node_name, owner, digger)
if node_name == "air" or node_name == "vacuum:vacuum" then
return false
end
if vector.equals(pos, dig_pos) then
return false -- Don't dig self
end
local def = minetest.registered_nodes[node_name]
if not def or not def.diggable or (def.can_dig and not def.can_dig(dig_pos, digger)) then
return false
end
if def._mcl_hardness == -1 then
return false
end
return not minetest.is_protected(dig_pos, owner)
end
local function do_purge(pos, meta)
local inv = meta:get_inventory()
for i, stack in ipairs(inv:get_list("cache")) do
if not stack:is_empty() then
technic.tube_inject_item(pos, pos, vector.new(0, 1, 0), stack:to_table())
inv:set_stack("cache", i, "")
break
end
end
if inv:is_empty("cache") then
meta:set_int("purge_on", 0)
end
end
local function spawn_dig_particles(pos, dig_pos, node)
local end_pos = vector.new(pos.x, pos.y - 0.5, pos.z)
local dist = vector.distance(dig_pos, end_pos)
local t = math.sqrt((2 * dist) / 20)
local acc = vector.multiply(vector.subtract(end_pos, dig_pos), (1 / dist) * 20)
minetest.add_particlespawner({
amount = 50,
time = 0.5,
minpos = vector.subtract(dig_pos, 0.4),
maxpos = vector.add(dig_pos, 0.4),
minacc = acc,
maxacc = acc,
minsize = 0.5,
maxsize = 1.5,
minexptime = t,
maxexptime = t,
node = node,
})
end
local function do_digging(pos, meta, net_time)
local us_start = minetest.get_us_time()
local step = tonumber(meta:get("step") or "")
if not step then
-- Missing metadata or not yet updated by conversion LBM, abort digging
return
end
local radius = meta:get_int("size")
local diameter = radius * 2 + 1
local num_steps = diameter * diameter
local dug = meta:get_int("dug")
local max_depth = meta:get_int("max_depth")
local offset = {
x = meta:get_int("offset_x"),
y = math.floor(step / num_steps) + 1 - meta:get_int("offset_y"),
z = meta:get_int("offset_z")
}
if dug == -1 then
-- Find ground before digging
if offset.y > max_depth then
meta:set_int("finished", 1)
return
end
local pos1 = {
x = pos.x + offset.x - radius,
y = pos.y - offset.y,
z = pos.z + offset.z - radius
}
local pos2 = {
x = pos.x + offset.x + radius,
y = pos.y - offset.y,
z = pos.z + offset.z + radius
}
minetest.load_area(pos1, pos2)
local nodes = minetest.find_nodes_in_area(pos1, pos2, {"air", "vacuum:vacuum"})
if #nodes < num_steps then
-- There are nodes to dig, start digging at this layer
meta:set_int("dug", 0)
else
-- Move down to next layer
meta:set_int("step", step + num_steps)
end
return
end
local owner = meta:get_string("owner")
local digger = get_fake_player(owner)
while true do
-- Search for something to dig
if offset.y > max_depth then
-- Finished digging
meta:set_int("finished", 1)
meta:set_int("purge_on", 1)
break
end
local dig_offset = dig_pattern[step % num_steps]
local dig_pos = {
x = pos.x + offset.x + dig_offset.x,
y = pos.y - offset.y,
z = pos.z + offset.z + dig_offset.z,
}
step = step + 1
if step % num_steps == 0 then
-- Finished this layer, move down
offset.y = offset.y + 1
end
local node = technic.get_or_load_node(dig_pos)
if can_dig_node(pos, dig_pos, node.name, owner, digger) then
-- Found something to dig, dig it and stop
minetest.remove_node(dig_pos)
if quarry_dig_particles then
spawn_dig_particles(pos, dig_pos, node)
end
local inv = meta:get_inventory()
local drops = minetest.get_node_drops(node.name, "")
local full = false
for _, item in ipairs(drops) do
local left = inv:add_item("cache", item)
while not left:is_empty() do
-- Cache is full, forcibly purge until the item fits
full = true
do_purge(pos, meta)
left = inv:add_item("cache", left)
end
end
dug = dug + 1
if full or dug % 99 == 0 then
-- Time to purge the cache
meta:set_int("purge_on", 1)
end
break
end
local us_used = minetest.get_us_time() - us_start
if us_used > quarry_time_limit or net_time + us_used > network_time_limit then
break
end
end
meta:set_int("dug", dug)
meta:set_int("step", step)
end
local function quarry_run(pos, _, _, network)
local meta = minetest.get_meta(pos)
if meta:get_int("purge_on") == 1 then
-- Purging
meta:set_string("infotext", infotext.purge)
meta:set_int("HV_EU_demand", 0)
do_purge(pos, meta)
elseif meta:get_int("finished") == 1 then
-- Finished
meta:set_string("infotext", infotext.finished)
meta:set_int("HV_EU_demand", 0)
elseif meta:get_int("enabled") == 1 then
-- Active
if meta:get_int("HV_EU_input") >= quarry_demand then
meta:set_string("infotext", infotext.active)
do_digging(pos, meta, network.lag)
else
meta:set_string("infotext", infotext.unpowered)
end
meta:set_int("HV_EU_demand", quarry_demand)
else
-- Disabled
meta:set_int("HV_EU_demand", 0)
meta:set_string("infotext", infotext.disabled)
if not meta:get_inventory():is_empty("cache") then
meta:set_int("purge_on", 1)
end
end
end
local function reset_quarry(meta)
meta:set_int("step", 0)
meta:set_int("dug", -1)
meta:set_int("purge_on", 1)
meta:set_int("finished", 0)
end
local size = minetest.get_modpath("mcl_formspec") and "size[9,10]" or "size[8,9]"
local base_formspec = size..
"label[0,0;"..S("@1 Quarry", S("HV")).."]"..
"list[context;cache;0,0.7;4,3;]"..
"listring[context;cache]"..
"button[6,0.6;2,1;restart;"..S("Restart").."]"..
"field[4.3,2.1;2,1;size;"..S("Radius")..";${size}]"..
"field[6.3,2.1;2,1;max_depth;"..S("Max Depth")..";${max_depth}]"..
"field[4.3,3.1;1.333,1;offset_x;"..S("Offset X")..";${offset_x}]"..
"field[5.633,3.1;1.333,1;offset_y;"..S("Offset Y")..";${offset_y}]"..
"field[6.966,3.1;1.333,1;offset_z;"..S("Offset Z")..";${offset_z}]"
if has_digilines then
base_formspec = base_formspec..
"field[4.3,4.2;4,1;channel;"..S("Digiline Channel")..";${channel}]"
end
if has_mcl then
base_formspec = base_formspec..
mcl_formspec.get_itemslot_bg(0,0.7,4,3)..
-- player inventory
"list[current_player;main;0,5.5;9,3;9]"..
mcl_formspec.get_itemslot_bg(0,5.5,9,3)..
"list[current_player;main;0,8.74;9,1;]"..
mcl_formspec.get_itemslot_bg(0,8.74,9,1)..
"listring[current_player;main]"
else
base_formspec = base_formspec..
"list[current_player;main;0,5;8,4;]"..
"listring[current_player;main]"
end
local function update_formspec(meta)
local fs = base_formspec
local status = S("Digging not started")
if meta:get_int("purge_on") == 1 then
status = S("Purging cache")
elseif meta:get_int("finished") == 1 then
status = S("Digging finished")
elseif meta:get_int("enabled") == 1 then
local diameter = meta:get_int("size") * 2 + 1
local num_steps = diameter * diameter
local y_level = math.floor(meta:get_int("step") / num_steps) + 1 - meta:get_int("offset_y")
if y_level < 0 then
status = S("Digging @1 m above machine", math.abs(y_level))
else
status = S("Digging @1 m below machine", y_level)
end
end
if meta:get_int("enabled") == 1 then
fs = fs.."button[4,0.6;2,1;disable;"..S("Enabled").."]"
else
fs = fs.."button[4,0.6;2,1;enable;"..S("Disabled").."]"
end
if has_mesecons then
local selected = meta:get("mesecons") or "true"
if has_jumpdrive then
fs = fs.."checkbox[0,3.6;mesecons;"..S("Enable Mesecons Control")..";"..selected.."]"
else
fs = fs.."checkbox[0,3.8;mesecons;"..S("Enable Mesecons Control")..";"..selected.."]"
end
end
if has_jumpdrive then
local selected = meta:get("reset_on_move") or "true"
if has_mesecons then
fs = fs.."checkbox[0,4.1;reset_on_move;"..S("Restart When Moved")..";"..selected.."]"
else
fs = fs.."checkbox[0,3.8;reset_on_move;"..S("Restart When Moved")..";"..selected.."]"
end
end
meta:set_string("formspec", fs.."label[4,0;"..status.."]")
end
local function clamp(value, min, max, default)
value = tonumber(value) or default or max
return math.min(math.max(value, min), max)
end
local function quarry_receive_fields(pos, _, fields, sender)
local player_name = sender:get_player_name()
if not player_allowed(pos, player_name) then
minetest.chat_send_player(player_name, S("You are not allowed to edit this!"))
return
end
local meta = minetest.get_meta(pos)
if fields.size then
meta:set_int("size", clamp(fields.size, 0, 8, 4))
end
if fields.max_depth then
local depth = clamp(fields.max_depth, 1, quarry_max_depth)
meta:set_int("max_depth", depth)
local ymin = -math.min(10, depth - 1)
meta:set_int("offset_y", clamp(meta:get_int("offset_y"), ymin, 10, 0))
end
if fields.offset_x then
meta:set_int("offset_x", clamp(fields.offset_x, -10, 10, 0))
end
if fields.offset_y then
local ymin = -math.min(10, meta:get_int("max_depth") - 1)
meta:set_int("offset_y", clamp(fields.offset_y, ymin, 10, 0))
end
if fields.offset_z then
meta:set_int("offset_z", clamp(fields.offset_z, -10, 10, 0))
end
if fields.mesecons then
meta:set_string("mesecons", fields.mesecons)
end
if fields.reset_on_move then
meta:set_string("reset_on_move", fields.reset_on_move)
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(meta) end
update_formspec(meta)
end
local function show_working_area(pos, _, player)
if not player or player:get_wielded_item():get_name() ~= "" then
-- Only spawn particles when using an empty hand
return
end
local meta = minetest.get_meta(pos)
local radius = meta:get_int("size") + 0.5
local offset = vector.new(meta:get_int("offset_x"), meta:get_int("offset_y"), meta:get_int("offset_z"))
local depth = meta:get_int("max_depth") + 0.5
-- Draw area from top corner to bottom corner
local pos1 = vector.add(pos, vector.new(offset.x - radius, offset.y - 0.5, offset.z - radius))
local pos2 = vector.add(pos, vector.new(offset.x + radius, -depth, offset.z + radius))
vizlib.draw_area(pos1, pos2, {player = player})
end
local function digiline_action(pos, _, channel, msg)
local meta = minetest.get_meta(pos)
if channel ~= meta:get_string("channel") then
return
end
-- Convert string message to table
if type(msg) == "string" then
msg = msg:lower()
if msg == "get" or msg == "on" or msg == "off" or msg == "restart" then
msg = {command = msg}
elseif msg:sub(1, 7) == "radius " then
msg = {command = "radius", value = msg:sub(8,-1)}
elseif msg:sub(1,10) == "max_depth " then
msg = {command = "max_depth", value = msg:sub(11,-1)}
elseif msg:sub(1,9) == "offset_x " then
msg = {command = "offset_x", value = msg:sub(10,-1)}
elseif msg:sub(1,9) == "offset_y " then
msg = {command = "offset_y", value = msg:sub(10,-1)}
elseif msg:sub(1,9) == "offset_z " then
msg = {command = "offset_z", value = msg:sub(10,-1)}
elseif msg:sub(1,7) == "offset " then
local s = string.split(msg:sub(8,-1), ",")
msg = {command = "offset", value = {x = s[1], y = s[2], z = s[3]}}
end
end
if type(msg) ~= "table" then return end
-- Convert old message format to new format
if msg.command ~= "set" and msg.command ~= "get" then
local cmd = msg.command
if cmd == "restart" then
msg = {command = "set", restart = true}
elseif cmd == "on" or cmd == "off" then
msg = {command = "set", enabled = msg.command == "on"}
elseif cmd == "radius" or cmd == "max_depth" or cmd == "offset"
or cmd == "offset_x" or cmd == "offset_y" or cmd == "offset_z" then
msg = {command = "set", [cmd] = msg.value}
end
end
-- Process message
if msg.command == "get" then
local diameter = meta:get_int("size") * 2 + 1
local num_steps = diameter * diameter
local offset = {
x = meta:get_int("offset_x"),
y = meta:get_int("offset_y"),
z = meta:get_int("offset_z")
}
digilines.receptor_send(pos, technic.digilines.rules, channel, {
enabled = meta:get_int("enabled") == 1,
finished = meta:get_int("finished") == 1,
radius = meta:get_int("size"),
max_depth = meta:get_int("max_depth"),
offset_x = offset.x,
offset_y = offset.y,
offset_z = offset.z,
offset = offset,
dug_nodes = meta:get_int("dug"),
dig_level = -(math.floor(meta:get_int("step") / num_steps) + 1 - offset.y),
})
elseif msg.command == "set" then
if msg.enabled ~= nil then
meta:set_int("enabled", msg.enabled == true and 1 or 0)
end
if msg.restart == true then
reset_quarry(meta)
end
if msg.radius then
meta:set_int("size", clamp(msg.radius, 0, 8, 4))
end
if msg.max_depth then
local depth = clamp(msg.max_depth, 1, quarry_max_depth)
meta:set_int("max_depth", depth)
local ymin = -math.min(10, depth - 1)
meta:set_int("offset_y", clamp(meta:get_int("offset_y"), ymin, 10, 0))
end
if msg.offset_x then
meta:set_int("offset_x", clamp(msg.offset_x, -10, 10, 0))
end
if msg.offset_y then
local ymin = -math.min(10, meta:get_int("max_depth") - 1)
meta:set_int("offset_y", clamp(msg.offset_y, ymin, 10, 0))
end
if msg.offset_z then
meta:set_int("offset_z", clamp(msg.offset_z, -10, 10, 0))
end
if msg.offset and type(msg.offset) == "table" then
local ymin = -math.min(10, meta:get_int("max_depth") - 1)
meta:set_int("offset_x", clamp(msg.offset.x, -10, 10, 0))
meta:set_int("offset_y", clamp(msg.offset.y, ymin, 10, 0))
meta:set_int("offset_z", clamp(msg.offset.z, -10, 10, 0))
end
end
end
minetest.register_node("technic:quarry", {
description = S("@1 Quarry", S("HV")),
tiles = {
"technic_carbon_steel_block.png^pipeworks_tube_connection_metallic.png",
"technic_carbon_steel_block.png^technic_quarry_bottom.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^technic_cable_connection_overlay.png"
},
groups = {cracky = 2, tubedevice = 1, technic_machine = 1, technic_hv = 1, pickaxey = 2},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
connect_sides = {"front", "back", "left", "right"},
tube = {
connect_sides = {top = 1},
-- Lower priority than tubes, so items will prefer any tube to another quarry
priority = 10,
can_go = function(pos, node, velocity, stack)
-- Always eject up, even if items came in another way
return { vector.new(0, 1, 0) }
end
},
on_punch = has_vizlib and show_working_area or nil,
on_rightclick = function(pos)
local meta = minetest.get_meta(pos)
update_formspec(meta)
end,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_int("size", 4)
meta:set_int("offset_x", 0)
meta:set_int("offset_y", 0)
meta:set_int("offset_z", 0)
meta:set_int("max_depth", quarry_max_depth)
meta:set_string("mesecons", "false")
meta:set_string("reset_on_move", "false")
meta:get_inventory():set_size("cache", 12)
reset_quarry(meta)
update_formspec(meta)
end,
on_movenode = has_jumpdrive and function(_, pos)
local meta = minetest.get_meta(pos)
if meta:get("reset_on_move") ~= "false" then
reset_quarry(meta)
end
end or nil,
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 player_allowed(pos, player:get_player_name()) and count or 0
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
return 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 player_allowed(pos, player:get_player_name()) and stack:get_count() or 0
end,
on_metadata_inventory_move = technic.machine_on_inventory_move,
on_metadata_inventory_put = technic.machine_on_inventory_put,
on_metadata_inventory_take = technic.machine_on_inventory_take,
mesecons = {
effector = {
action_on = function(pos)
local meta = minetest.get_meta(pos)
if meta:get("mesecons") ~= "false" then
meta:set_int("enabled", 1)
end
end,
action_off = function(pos)
local meta = minetest.get_meta(pos)
if meta:get("mesecons") ~= "false" then
meta:set_int("enabled", 0)
end
end
}
},
digiline = {
receptor = {
rules = technic.digilines.rules,
},
effector = {
rules = technic.digilines.rules,
action = digiline_action,
}
},
})
minetest.register_craft({
output = "technic:quarry",
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"}
}
})
technic.register_machine("HV", "technic:quarry", technic.receiver)
minetest.register_lbm({
label = "Old quarry conversion",
name = "technic:old_quarry_conversion",
nodenames = {"technic:quarry"},
run_at_every_load = false,
action = function(pos, node)
local meta = minetest.get_meta(pos)
if meta:get("step") then
-- Quarry v3, don't do anything
-- This can happen when a quarry is moved with a jumpdrive
return
elseif meta:get("quarry_pos") then
-- Quarry v2, calculate step if quarry is digging below
local level = meta:get_int("dig_level") - pos.y
if level < 0 then
local diameter = meta:get_int("size") * 2 + 1
local num_steps = diameter * diameter
-- Convert the negative value to positive, and go back up one level
level = math.abs(level + 1)
meta:set_int("step", level * num_steps)
end
-- Delete unused meta values
meta:set_string("quarry_dir", "")
meta:set_string("quarry_pos", "")
meta:set_string("dig_pos", "")
meta:set_string("dig_level", "")
meta:set_string("dig_index", "")
meta:set_string("dig_steps", "")
else
-- Quarry v1, reset quarry
reset_quarry(meta)
end
local dir = minetest.facedir_to_dir(node.param2)
local offset = vector.multiply(dir, meta:get_int("size") + 1)
meta:set_int("offset_x", offset.x)
meta:set_int("offset_y", 4)
meta:set_int("offset_z", offset.z)
if not meta:get("max_depth") then
meta:set_int("max_depth", quarry_max_depth)
end
update_formspec(meta)
end
})

View file

@ -0,0 +1,18 @@
-- 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:hv_solar_array 1',
recipe = {
{'technic:mv_solar_array', 'technic:mv_solar_array', 'technic:mv_solar_array'},
{'technic:carbon_plate', 'technic:hv_transformer', 'technic:composite_plate'},
{'', 'technic:hv_cable', ''},
}
})
technic.register_solar_array("technic:hv_solar_array", {
tier="HV",
power=100
})
minetest.register_alias("technic:solar_array_hv", "technic:hv_solar_array")

View file

@ -0,0 +1,23 @@
-- LV Alloy furnace
local S = technic.getter
local mat = technic.materials
-- FIXME: kpoppel: I'd like to introduce an induction heating element here...
minetest.register_craft({
output = 'technic:lv_alloy_furnace',
recipe = {
{mat.brick, mat.brick, mat.brick},
{mat.brick, 'technic:machine_casing', mat.brick},
{mat.brick, 'technic:lv_cable', mat.brick},
}
})
technic.register_base_machine("technic:lv_alloy_furnace", {
typename = "alloy",
description = S("@1 Alloy Furnace", S("LV")),
insert_object = technic.insert_object_unique_stack,
can_insert = technic.can_insert_unique_stack,
tier = "LV",
speed = 1,
demand = {300}
})

View file

@ -0,0 +1,19 @@
-- 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("technic:lv_battery_box", {
tier = "LV",
max_charge = 40000,
charge_rate = 1000,
discharge_rate = 4000,
charge_step = 500,
discharge_step = 800,
})

View file

@ -0,0 +1,57 @@
local S = technic.getter
local mat = technic.materials
minetest.register_alias("lv_cable", "technic:lv_cable")
minetest.register_craft({
output = 'technic:lv_cable 6',
recipe = {
{mat.paper, mat.paper, mat.paper},
{mat.copper_ingot, mat.copper_ingot, mat.copper_ingot},
{mat.paper, mat.paper, mat.paper},
}
})
minetest.register_craft({
output = "technic:lv_cable_plate_1 5",
recipe = {
{"" , "" , "technic:lv_cable"},
{"technic:lv_cable", "technic:lv_cable", "technic:lv_cable"},
{"" , "" , "technic:lv_cable"},
}
})
minetest.register_craft({
output = "technic:lv_cable",
recipe = {{"technic:lv_cable_plate_1"}}
})
-- Register cables
technic.register_cable("technic:lv_cable", {
tier = "LV",
size = 2/16,
description = S("@1 Cable", S("LV"))
})
technic.register_cable_plate("technic:lv_cable_plate", {
tier = "LV",
size = 2/16,
description = S("@1 Cable Plate", S("LV")),
tiles = {"technic_lv_cable.png"},
})
if minetest.get_modpath("digilines") then
technic.register_cable("technic:lv_digi_cable", {
tier = "LV",
size = 2/16,
description = S("@1 Digiline Cable", S("LV")),
digiline = { wire = { rules = technic.digilines.rules_allfaces } }
})
technic.register_cable_plate("technic:lv_digi_cable_plate", {
tier = "LV",
size = 2/16,
description = S("@1 Digiline Cable Plate", S("LV")),
digiline = { wire = { rules = technic.digilines.rules_allfaces } },
tiles = {"technic_lv_digi_cable.png"}
})
end

View file

@ -0,0 +1,26 @@
local S = technic.getter
local mat = technic.materials
minetest.register_alias("compressor", "technic:lv_compressor")
minetest.register_craft({
output = 'technic:lv_compressor',
recipe = {
{mat.stone, 'basic_materials:motor', mat.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_base_machine("technic:lv_compressor", {
typename = "compressing",
description = S("@1 Compressor", S("LV")),
tier = "LV",
demand = {300},
speed = 1
})

View file

@ -0,0 +1,22 @@
-- LV Electric Furnace
-- This is a faster version of the stone furnace which runs on EUs
local S = technic.getter
local mat = technic.materials
-- FIXME: kpoppel I'd like to introduce an induction heating element here also
minetest.register_craft({
output = 'technic:lv_electric_furnace',
recipe = {
{mat.cobble, mat.cobble, mat.cobble},
{mat.cobble, 'technic:machine_casing', mat.cobble},
{mat.cobble, 'technic:lv_cable', mat.cobble},
}
})
technic.register_base_machine("technic:lv_electric_furnace", {
typename = "cooking",
description = S("@1 Furnace", S("LV")),
tier="LV",
demand={300},
speed = 2
})

View file

@ -0,0 +1,35 @@
local S = technic.getter
minetest.register_alias("extractor", "technic:lv_extractor")
if technic.config:get_bool("enable_tree_tap") then
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', ''},
}
})
else
minetest.register_craft({
output = 'technic:lv_extractor',
recipe = {
{'basic_materials:motor', 'pipeworks:tube_1', 'basic_materials:motor'},
{'technic:carbon_steel_ingot', 'technic:machine_casing', 'technic:carbon_steel_ingot'},
{'', 'technic:lv_cable', ''},
}
})
end
technic.register_base_machine("technic:lv_extractor", {
typename = "extracting",
description = S("@1 Extractor", S("LV")),
tier = "LV",
demand = {300},
speed = 1
})

View file

@ -0,0 +1,20 @@
-- 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.
local mat = technic.materials
minetest.register_alias("lv_generator", "technic:lv_generator")
minetest.register_craft({
output = 'technic:lv_generator',
recipe = {
{mat.stone, mat.furnace, mat.stone},
{mat.stone, 'technic:machine_casing', mat.stone},
{mat.stone, 'technic:lv_cable', mat.stone},
}
})
technic.register_generator({tier="LV", supply=200})

View file

@ -0,0 +1,124 @@
-- 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
local mat = technic.materials
minetest.register_craft({
output = 'technic:geothermal',
recipe = {
{'technic:granite', mat.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 @1 Generator", S("LV")),
})
local check_node_around = function(pos)
local node = minetest.get_node(pos)
if node.name == mat.water_source or node.name == mat.water_flowing then return 1 end
if node.name == mat.lava_source or node.name == mat.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("@1 (@2% Efficiency)",
S("Geothermal @1 Generator", S("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 @1 Generator", S("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, axey=2, handy=1},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
paramtype2 = "facedir",
legacy_facedir_simple = true,
sounds = technic.sounds.node_sound_wood_defaults(),
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("infotext", S("Geothermal @1 Generator", S("LV")))
meta:set_int("LV_EU_supply", 0)
end,
technic_run = run,
})
minetest.register_node("technic:geothermal_active", {
description = S("Geothermal @1 Generator", S("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, axey=2, handy=1},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
legacy_facedir_simple = true,
sounds = technic.sounds.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)

View file

@ -0,0 +1,20 @@
local S = technic.getter
local mat = technic.materials
minetest.register_alias("grinder", "technic:lv_grinder")
minetest.register_craft({
output = 'technic:lv_grinder',
recipe = {
{mat.desert_stone, mat.diamond, mat.desert_stone},
{mat.desert_stone, 'technic:machine_casing', mat.desert_stone},
{'technic:granite', 'technic:lv_cable', 'technic:granite'},
}
})
technic.register_base_machine("technic:lv_grinder", {
typename = "grinding",
description = S("@1 Grinder", S("LV")),
tier="LV",
demand={200},
speed=1
})

View file

@ -0,0 +1,27 @@
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.."/led.lua")
dofile(path.."/lamp.lua")

View file

@ -0,0 +1,204 @@
-- LV Lamp - a powerful light source.
-- Illuminates a 7x7x3(H) volume below itself with light bright as the sun.
local S = technic.getter
local mat = technic.materials
local demand = 50
local desc = S("@1 Lamp", S("LV"))
local active_desc = S("@1 Active", desc).."\n"..S("Demand: @1", technic.EU_string(demand))
local unpowered_desc = S("@1 Unpowered", desc)
local off_desc = S("@1 Off", desc)
-- Invisible light source node used for illumination
minetest.register_node("technic:dummy_light_source", {
description = S("Dummy light source node"),
inventory_image = "technic_dummy_light_source.png",
wield_image = "technic_dummy_light_source.png",
paramtype = "light",
drawtype = "airlike",
light_source = 14,
sunlight_propagates = true,
walkable = false,
buildable_to = true,
diggable = false,
pointable = false,
--drop = "", -- Intentionally allowed to drop itself
groups = {not_in_creative_inventory = 1}
})
local cid_light = minetest.get_content_id("technic:dummy_light_source")
local cid_air = minetest.CONTENT_AIR
local function illuminate(pos, active)
local pos1 = {x = pos.x - 3, y = pos.y - 3, z = pos.z - 3}
local pos2 = {x = pos.x + 3, y = pos.y - 1, z = pos.z + 3}
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map(pos1, pos2)
local va = VoxelArea:new({MinEdge = emin, MaxEdge = emax})
local node_data = vm:get_data()
local find_node = active and cid_air or cid_light
local set_node = active and cid_light or cid_air
local dirty = false
for i in va:iterp(pos1, pos2) do
if node_data[i] == find_node then
node_data[i] = set_node
dirty = true
end
end
if dirty then
vm:set_data(node_data)
vm:write_to_map()
end
end
local function set_random_timer(pos, mint, maxt)
local t = math.random(mint * 10, maxt * 10) * 0.1
minetest.get_node_timer(pos):start(t)
end
local function lamp_run(pos, node)
local meta = minetest.get_meta(pos)
if meta:get_int("LV_EU_demand") == 0 then
return -- Lamp is turned off
end
local eu_input = meta:get_int("LV_EU_input")
if node.name == "technic:lv_lamp_active" then
if eu_input < demand then
technic.swap_node(pos, "technic:lv_lamp")
meta:set_string("infotext", unpowered_desc)
set_random_timer(pos, 0.2, 1)
end
elseif node.name == "technic:lv_lamp" then
if eu_input >= demand then
technic.swap_node(pos, "technic:lv_lamp_active")
meta:set_string("infotext", active_desc)
set_random_timer(pos, 0.2, 2)
end
end
end
local function lamp_toggle(pos, node, player)
if not player or minetest.is_protected(pos, player:get_player_name()) then
return
end
local meta = minetest.get_meta(pos)
if meta:get_int("LV_EU_demand") == 0 then
meta:set_string("infotext", active_desc)
meta:set_int("LV_EU_demand", demand)
else
technic.swap_node(pos, "technic:lv_lamp")
meta:set_string("infotext", off_desc)
meta:set_int("LV_EU_demand", 0)
set_random_timer(pos, 0.2, 1)
end
end
minetest.register_node("technic:lv_lamp", {
description = desc,
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, pickaxey = 2},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
connect_sides = {"front", "back", "left", "right", "top"},
can_dig = technic.machine_can_dig,
technic_run = lamp_run,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("infotext", desc)
meta:set_int("LV_EU_demand", demand)
end,
on_destruct = illuminate,
on_rightclick = lamp_toggle,
on_timer = function(pos)
illuminate(pos, false)
-- Don't start the timer again, otherwise lights will fight each other
end,
})
minetest.register_node("technic:lv_lamp_active", {
description = active_desc,
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"
},
paramtype = "light",
light_source = 14,
drop = "technic:lv_lamp",
groups = {cracky = 2, technic_machine = 1, technic_lv = 1, not_in_creative_inventory = 1, pickaxey = 2},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
connect_sides = {"front", "back", "left", "right", "top"},
can_dig = technic.machine_can_dig,
technic_run = lamp_run,
technic_on_disable = function(pos)
technic.swap_node(pos, "technic:lv_lamp")
set_random_timer(pos, 0.2, 1)
end,
on_destruct = illuminate,
on_rightclick = lamp_toggle,
on_timer = function(pos, elapsed)
if elapsed < 60 then -- Don't check immediately after being unloaded
illuminate(pos, true)
end
set_random_timer(pos, 30, 60) -- Check every 30-60 seconds
end,
})
technic.register_machine("LV", "technic:lv_lamp", technic.receiver)
technic.register_machine("LV", "technic:lv_lamp_active", technic.receiver)
minetest.register_craft({
output = "technic:lv_lamp",
recipe = {
{mat.glass, mat.glass, mat.glass},
{"technic:lv_led", "technic:lv_led", "technic:lv_led"},
{"mesecons_materials:glue", "technic:lv_cable", "mesecons_materials:glue"},
}
})

View file

@ -0,0 +1,102 @@
-- LED - a weak light source.
-- Intended primarily as a core component for LED lamps.
local S = technic.getter
local demand = 5
local desc = S("@1 LED", S("LV"))
local active_desc = S("@1 Active", desc).."\n"..S("Demand: @1", technic.EU_string(demand))
local unpowered_desc = S("@1 Unpowered", desc)
local function led_run(pos, node)
local meta = minetest.get_meta(pos)
local eu_input = meta:get_int("LV_EU_input")
if eu_input < demand and node.name == "technic:lv_led_active" then
technic.swap_node(pos, "technic:lv_led")
meta:set_string("infotext", unpowered_desc)
elseif eu_input >= demand and node.name == "technic:lv_led" then
technic.swap_node(pos, "technic:lv_led_active")
meta:set_string("infotext", active_desc)
end
end
minetest.register_node("technic:lv_led", {
description = desc,
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, pickaxey = 2},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
connect_sides = {"front", "back", "left", "right", "top", "bottom"},
can_dig = technic.machine_can_dig,
technic_run = led_run,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("infotext", desc)
meta:set_int("LV_EU_demand", demand)
end,
})
minetest.register_node("technic:lv_led_active", {
description = active_desc,
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",
paramtype = "light",
light_source = 9,
drop = "technic:lv_led",
sunlight_propagates = true,
groups = {cracky = 2, technic_machine = 1, technic_lv = 1, not_in_creative_inventory = 1, pickaxey = 2},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
connect_sides = {"front", "back", "left", "right", "top", "bottom"},
can_dig = technic.machine_can_dig,
technic_run = led_run,
technic_on_disable = function(pos)
technic.swap_node(pos, "technic:lv_led")
end,
})
technic.register_machine("LV", "technic:lv_led", technic.receiver)
technic.register_machine("LV", "technic:lv_led_active", technic.receiver)
minetest.register_craft({
output = "technic:lv_led 2",
recipe = {
{"", "basic_materials:plastic_sheet", ""},
{"basic_materials:plastic_sheet", "technic:doped_silicon_wafer", "basic_materials:plastic_sheet"},
{"", "basic_materials:silver_wire", ""},
},
replacements = {{"basic_materials:silver_wire", "basic_materials:empty_spool"}},
})

View file

@ -0,0 +1,134 @@
-- LV Music player.
-- The player can play music. But it is high ampage!
local S = technic.getter
local mat = technic.materials
minetest.register_alias("music_player", "technic:music_player")
minetest.register_craft({
output = 'technic:music_player',
recipe = {
{'technic:chromium_ingot', mat.diamond, 'technic:chromium_ingot'},
{mat.diamond, 'technic:machine_casing', mat.diamond},
{mat.mossycobble, 'technic:lv_cable', mat.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("@1 Music Player", S("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("@1 Idle", machine_name))
meta:set_int("LV_EU_demand", 0)
return
end
if eu_input < demand then
meta:set_string("infotext", S("@1 Unpowered", 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("@1 Active", machine_name) .. "\n" ..
S("Demand: @1", technic.EU_string(demand)))
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("@1 Music Player", S("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;"..S("Stop").."]"..
"label[0,4;"..(meta:get_int("active") == 0 and S("Stopped") or
S("Current track: @1", meta:get_int("current_track"))).."]")
end
minetest.register_node("technic:music_player", {
description = S("@1 Music Player", S("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, axey = 2, handy=1},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
connect_sides = {"bottom"},
sounds = technic.sounds.node_sound_wood_defaults(),
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("infotext", S("@1 Music Player", S("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)

View file

@ -0,0 +1,22 @@
-- 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:lv_solar_array 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("technic:lv_solar_array", {
tier="LV",
power=10
})
minetest.register_alias("technic:solar_array_lv", "technic:lv_solar_array")

View file

@ -0,0 +1,74 @@
-- 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 @1 Generator", S("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("@1 Idle", 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, axey=2, handy=1},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
connect_sides = {"bottom"},
sounds = technic.sounds.node_sound_wood_defaults(),
description = S("Small Solar @1 Generator", S("LV")),
active = false,
drawtype = "nodebox",
paramtype = "light",
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 @1 Generator", S("LV")))
end,
technic_run = run,
})
technic.register_machine("LV", "technic:solar_panel", technic.producer)

View file

@ -0,0 +1,115 @@
-- 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 mat = technic.materials
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', mat.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 == mat.water_flowing or node.name == mat.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("@1 (@2% Efficiency)",
S("Hydro @1 Generator", S("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 @1 Generator", S("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, axey=2, handy=1},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
legacy_facedir_simple = true,
sounds = technic.sounds.node_sound_wood_defaults(),
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("infotext", S("Hydro @1 Generator", S("LV")))
meta:set_int("LV_EU_supply", 0)
end,
technic_run = run,
})
minetest.register_node("technic:water_mill_active", {
description = S("Hydro @1 Generator", S("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, axey=2, handy=1},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
legacy_facedir_simple = true,
sounds = technic.sounds.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)

View file

@ -0,0 +1,23 @@
-- MV alloy furnace
local S = technic.getter
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_base_machine("technic:mv_alloy_furnace", {
typename = "alloy",
description = S("@1 Alloy Furnace", S("MV")),
insert_object = technic.insert_object_unique_stack,
can_insert = technic.can_insert_unique_stack,
tier = "MV",
speed = 1.5,
upgrade = 1,
tube = 1,
demand = {3000, 2000, 1000}
})

View file

@ -0,0 +1,21 @@
-- 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("technic:mv_battery_box", {
tier = "MV",
max_charge = 200000,
charge_rate = 20000,
discharge_rate = 80000,
charge_step = 2000,
discharge_step = 8000,
upgrade = 1,
tube = 1,
})

View file

@ -0,0 +1,56 @@
local S = technic.getter
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'},
}
})
minetest.register_craft({
output = "technic:mv_cable_plate_1 5",
recipe = {
{"" , "" , "technic:mv_cable"},
{"technic:mv_cable", "technic:mv_cable", "technic:mv_cable"},
{"" , "" , "technic:mv_cable"},
}
})
minetest.register_craft({
output = "technic:mv_cable",
recipe = {{"technic:mv_cable_plate_1"}}
})
-- Register cables
technic.register_cable("technic:mv_cable", {
tier = "MV",
size = 2.5/16,
description = S("@1 Cable", S("MV"))
})
technic.register_cable_plate("technic:mv_cable_plate", {
tier = "MV",
size = 2.5/16,
description = S("@1 Cable Plate", S("MV")),
tiles = {"technic_mv_cable.png"},
})
if minetest.get_modpath("digilines") then
technic.register_cable("technic:mv_digi_cable", {
tier = "MV",
size = 2.5/16,
description = S("@1 Digiline Cable", S("MV")),
digiline = { wire = { rules = technic.digilines.rules_allfaces } }
})
technic.register_cable_plate("technic:mv_digi_cable_plate", {
tier = "MV",
size = 2.5/16,
description = S("@1 Digiline Cable Plate", S("MV")),
digiline = { wire = { rules = technic.digilines.rules_allfaces } },
tiles = {"technic_mv_digi_cable.png"}
})
end

View file

@ -0,0 +1,20 @@
local S = technic.getter
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_base_machine("technic:mv_centrifuge", {
typename = "separating",
description = S("@1 Centrifuge", S("MV")),
tier = "MV",
demand = { 8000, 7000, 6000 },
speed = 2,
upgrade = 1,
tube = 1,
})

View file

@ -0,0 +1,21 @@
-- MV compressor
local S = technic.getter
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_base_machine("technic:mv_compressor", {
typename = "compressing",
description = S("@1 Compressor", S("MV")),
tier = "MV",
demand = {800, 600, 400},
speed = 2,
upgrade = 1,
tube = 1
})

View file

@ -0,0 +1,26 @@
-- 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.
local S = technic.getter
-- 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_base_machine("technic:mv_electric_furnace", {
typename = "cooking",
description = S("@1 Furnace", S("MV")),
tier="MV",
upgrade=1,
tube=1,
demand={2000, 1000, 500},
speed=4
})

View file

@ -0,0 +1,21 @@
-- MV extractor
local S = technic.getter
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_base_machine("technic:mv_extractor", {
typename = "extracting",
description = S("@1 Extractor", S("MV")),
tier = "MV",
demand = {800, 600, 400},
speed = 2,
upgrade = 1,
tube = 1
})

View file

@ -0,0 +1,21 @@
-- MV freezer
local S = technic.getter
minetest.register_craft({
output = 'technic:mv_freezer',
recipe = {
{'technic:stainless_steel_ingot', 'basic_materials: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_base_machine("technic:mv_freezer", {
typename = "freezing",
description = S("@1 Freezer", S("MV")),
tier = "MV",
demand = {800, 600, 400},
speed = 0.5,
upgrade = 1,
tube = 1
})

View file

@ -0,0 +1,11 @@
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})

View file

@ -0,0 +1,21 @@
-- MV grinder
local S = technic.getter
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_base_machine("technic:mv_grinder", {
typename = "grinding",
description = S("@1 Grinder", S("MV")),
tier="MV",
demand={600, 450, 300},
speed=2,
upgrade=1,
tube=1
})

View file

@ -0,0 +1,111 @@
-- 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("@1 (@2% Efficiency)",
S("Hydro @1 Generator", S("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 @1 Generator", S("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, axey=2, handy=1},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
legacy_facedir_simple = true,
sounds = technic.sounds.node_sound_wood_defaults(),
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("infotext", S("Hydro @1 Generator", S("MV")))
meta:set_int("MV_EU_supply", 0)
end,
technic_run = run,
})
minetest.register_node("technic:hydro_turbine_active", {
description = S("Hydro @1 Generator", S("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, axey=2, handy=1,
technic_machine=1, technic_mv=1, not_in_creative_inventory=1},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
legacy_facedir_simple = true,
sounds = technic.sounds.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)

View file

@ -0,0 +1,28 @@
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")

View file

@ -0,0 +1,18 @@
minetest.register_craft({
output = 'technic:mv_solar_array 1',
recipe = {
{'technic:lv_solar_array', 'technic:lv_solar_array', 'technic:lv_solar_array'},
{'technic:carbon_steel_ingot', 'technic:mv_transformer', 'technic:carbon_steel_ingot'},
{'', 'technic:mv_cable', ''},
}
})
technic.register_solar_array("technic:mv_solar_array", {
tier="MV",
power=30
})
-- compatibility alias for upgrading from old versions of technic
minetest.register_alias("technic:solar_panel_mv", "technic:mv_solar_array")
minetest.register_alias("technic:solar_array_mv", "technic:mv_solar_array")

View file

@ -0,0 +1,152 @@
-- Tool workshop
-- This machine repairs tools.
minetest.register_alias("tool_workshop", "technic:tool_workshop")
local S = technic.getter
local mat = technic.materials
local tube_entry = "^pipeworks_tube_connection_wooden.png"
minetest.register_craft({
output = 'technic:tool_workshop',
recipe = {
{'group:wood', mat.diamond, 'group:wood'},
{'mesecons_pistons:piston_sticky_off', 'technic:machine_casing', 'technic:carbon_cloth'},
{mat.obsidian, 'technic:mv_cable', mat.obsidian},
}
})
local workshop_demand = {5000, 3500, 2000}
local size = minetest.get_modpath("mcl_formspec") and "size[9,9;]" or "size[8,9;]"
local workshop_formspec =
size..
"list[context;src;3,1;1,1;]"..
"label[0,0;"..S("@1 Tool Workshop", S("MV")).."]"..
"list[context;upgrade1;1,3;1,1;]"..
"list[context;upgrade2;2,3;1,1;]"..
"label[1,4;"..S("Upgrade Slots").."]"
if minetest.get_modpath("mcl_formspec") then
workshop_formspec = workshop_formspec..
mcl_formspec.get_itemslot_bg(3,1,1,1)..
mcl_formspec.get_itemslot_bg(1,3,1,1)..
mcl_formspec.get_itemslot_bg(2,3,1,1)..
-- player inventory
"list[current_player;main;0,4.5;9,3;9]"..
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
"list[current_player;main;0,7.74;9,1;]"..
mcl_formspec.get_itemslot_bg(0,7.74,9,1)
else
workshop_formspec = workshop_formspec..
"list[current_player;main;0,5;8,4;]"
end
-- listrings
workshop_formspec = workshop_formspec..
"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("@1 Tool Workshop", S("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("@1 Idle", 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("@1 Unpowered", machine_name))
elseif eu_input >= workshop_demand[EU_upgrade+1] then
meta:set_string("infotext", S("@1 Active", machine_name) .. "\n" ..
S("Demand: @1", technic.EU_string(workshop_demand[EU_upgrade+1])))
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("@1 Tool Workshop", S("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, axey=2, handy=1},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
connect_sides = {"bottom", "back", "left", "right"},
sounds = technic.sounds.node_sound_wood_defaults(),
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("infotext", S("@1 Tool Workshop", S("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,
on_metadata_inventory_move = technic.machine_on_inventory_move,
on_metadata_inventory_put = technic.machine_on_inventory_put,
on_metadata_inventory_take = technic.machine_on_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)

View file

@ -0,0 +1,102 @@
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, pickaxey=1},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
sounds = technic.sounds.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 @1 Generator", S("MV"))
local check = check_wind_mill(pos)
if check == false then
meta:set_int("MV_EU_supply", 0)
meta:set_string("infotext", S("@1 Improperly Placed", 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 @1 Generator", S("MV")),
tiles = {"technic_carbon_steel_block.png"},
paramtype2 = "facedir",
groups = {cracky=1, technic_machine=1, technic_mv=1, pickaxey=2},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
connect_sides = {"top", "bottom", "back", "left", "right"},
sounds = technic.sounds.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 @1 Generator", S("MV")))
meta:set_int("MV_EU_supply", 0)
end,
technic_run = run,
})
technic.register_machine("MV", "technic:wind_mill", technic.producer)

View file

@ -0,0 +1,87 @@
local S = technic.getter
-- Registration compatibility shim to transform Technic 1.x arguments to 2.x
-- This could be made stricter for new style API by utilizing `assert`
local function shallow_copy(t)
local result = {}
for k, v in pairs(t) do
result[k] = v
end
return setmetatable(result, getmetatable(t))
end
function technic.register_compat_v1_to_v2(name, data, default_name)
local modname = minetest.get_current_modname()
local colon, def
if type(name) == "table" then
-- Log old API usage, swap name to def and set name from def table
local msg = "Deprecated Technic registration API call: %s (%s)"
def = shallow_copy(name)
name = def.machine_name or default_name
def.machine_name = nil
def.description = def.machine_desc
def.machine_desc = nil
minetest.log("warning", msg:format(tostring(name), tostring(modname)))
else
def = shallow_copy(data)
end
-- Input name can be "modname:nodename", ":modname:nodename" or "nodename".
-- If name is presented as "nodename" then check for old def.modname field.
if name:find(":") then
colon, modname, name = name:match("(:?)(.+):(.+)")
-- Make sure that all fields are set, can be empty but pattern matcher must succeed.
assert(colon and modname and name)
elseif def.modname then
minetest.log("warning", ("Definition contains modname for %s"):format(name))
colon = ":"
modname = def.modname
end
return (colon or ""), modname, name, def
end
-- Registration functions in Technic 1.x version
function technic.register_alloy_furnace(def)
def.typename = "alloy"
def.description = S("@1 Alloy Furnace", S(def.tier))
def.insert_object = technic.insert_object_unique_stack
def.can_insert = technic.can_insert_unique_stack
technic.register_base_machine(def)
end
function technic.register_centrifuge(def)
def.typename = "separating"
def.description = S("@1 Centrifuge", S(def.tier))
technic.register_base_machine(def)
end
function technic.register_compressor(def)
def.typename = "compressing"
def.description = S("@1 Compressor", S(def.tier))
technic.register_base_machine(def)
end
function technic.register_extractor(def)
def.typename = "extracting"
def.description = S("@1 Extractor", S(def.tier))
technic.register_base_machine(def)
end
function technic.register_freezer(def)
def.typename = "freezing"
def.description = S("@1 Freezer", S(def.tier))
technic.register_base_machine(def)
end
function technic.register_grinder(def)
def.typename = "grinding"
def.description = S("@1 Grinder", S(def.tier))
technic.register_base_machine(def)
end
function technic.register_electric_furnace(def)
def.typename = "cooking"
def.description = S("@1 Furnace", S(def.tier))
technic.register_base_machine(def)
end

View file

@ -0,0 +1,109 @@
--
-- Compatibility hacks for digtron to work well with new Technic Plus network and power tools
--
-- More information:
-- https://github.com/mt-mods/technic/issues/100
-- https://github.com/mt-mods/technic/issues/233
--
-- Disable some luacheck warnings to allow having original formatting here
-- luacheck: no max line length
-- luacheck: globals digtron
-- Only relevant sections modified, you can directly compare this with upstream function defined in util.lua
local node_inventory_table = {type="node"}
local function tap_batteries(battery_positions, target, test)
if (battery_positions == nil) then
return 0
end
local current_burned = 0
-- 1 coal block is 370 PU
-- 1 coal lump is 40 PU
-- An RE battery holds 10000 EU of charge
-- local power_ratio = 100 -- How much charge equals 1 unit of PU from coal
-- setting Moved to digtron.config.power_ratio
for k, location in pairs(battery_positions) do
if current_burned > target then
break
end
node_inventory_table.pos = location.pos
local inv = minetest.get_inventory(node_inventory_table)
local invlist = inv:get_list("batteries")
if (invlist == nil) then -- This check shouldn't be needed, it's yet another guard against https://github.com/minetest/minetest/issues/8067
break
end
for i, itemstack in pairs(invlist) do
local charge = technic.get_charge(itemstack)
local power_available = math.floor(charge / digtron.config.power_ratio)
if power_available ~= 0 then
local actual_burned = power_available -- we just take all we have from the battery, since they aren't stackable
-- don't bother recording the items if we're just testing, nothing is actually being removed.
if test ~= true then
-- since we are taking everything, the wear and charge can both be set to 0
technic.set_charge(itemstack, 0)
end
current_burned = current_burned + actual_burned
end
if current_burned > target then
break
end
end
if test ~= true then
-- only update the list if we're doing this for real.
inv:set_list("batteries", invlist)
end
end
return current_burned
end
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
local function battery_holder_compat()
-- Override battery holder
local tube = minetest.registered_nodes["digtron:battery_holder"].tube
tube.can_insert = function(pos, node, stack, direction)
if technic.get_charge(stack) > 0 then
local inv = minetest.get_meta(pos):get_inventory()
return inv:room_for_item("batteries", stack)
end
return false
end
minetest.override_item("digtron:battery_holder",{
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
return (listname == "batteries" and technic.get_charge(stack) > 0) and stack:get_count() or 0
end,
tube = tube,
})
-- Override digtron.tap_batteries
digtron.tap_batteries = tap_batteries
end
minetest.register_on_mods_loaded(function()
if minetest.registered_nodes["digtron:power_connector"] then
power_connector_compat()
end
if minetest.registered_nodes["digtron:battery_holder"] then
battery_holder_compat()
end
end)

View file

@ -0,0 +1,139 @@
--
-- This allows using old style technic.register_power_tool tool registration function.
--
-- To make tool fully compatible replace `minetest.register_tool` with `technic.register_power_tool`
-- and add `technic_max_charge` field for tool definition.
-- Fields `wear_represents` and `on_refill` can be removed if using defaults.
--
-- Does not offer compatibility for charger mods: mods that charge or discharge registered power tools.
-- Compatibility for those can be achieved by using `<tooldef>.technic_get_charge` / `<tooldef>.technic_set_charge`.
--
local function compat_set_RE_wear(stack, charge)
local def = stack:get_definition()
if def.technic_wear_factor then
local wear = math.floor(charge * def.technic_wear_factor + 0.5)
stack:set_wear(wear > 0 and 65536 - wear or 0)
end
end
local function compat_technic_get_charge(stack)
local def = stack:get_definition()
if def.technic_max_charge then
local legacy_fields = minetest.deserialize(stack:get_meta():get_string("")) or {}
return legacy_fields.charge or 0, def.technic_max_charge
end
return 0, 0
end
local function compat_technic_set_charge(stack, charge)
compat_set_RE_wear(stack, charge)
local meta = stack:get_meta()
local legacy_fields = minetest.deserialize(meta:get_string("")) or {}
legacy_fields.charge = charge
meta:set_string("", minetest.serialize(legacy_fields))
end
-- This attempts to find out if mod is aware of technic.plus version property and marks mod as `plus_aware` if
-- it tries to read `technic.plus` value. Marked tools wont receive automatic metadata compatibility functions.
local plus_aware = {}
do
local original_mt = getmetatable(technic)
local mt = original_mt and table.copy(original_mt) or {}
local mt_index = mt.__index or rawget
local plus = technic.plus
rawset(technic, "plus", nil)
-- Extend `__index` lookup function for `technic` to collect mod names that are reading `technic.plus` property
function mt:__index(key)
if key == "plus" then
local modname = minetest.get_current_modname()
if modname then
plus_aware[modname] = true
end
return plus
end
return mt_index(self, key)
end
setmetatable(technic, mt)
-- Restore version and metatable, this must happen after handling register_on_mods_loaded callbacks
minetest.after(0, function()
rawset(technic, "plus", plus)
setmetatable(technic, original_mt)
end)
end
-- Override `technic.register_power_tool` to handle old style registration that was only setting max charge value.
local register_power_tool = technic.register_power_tool
function technic.register_power_tool(itemname, def_or_max_charge)
if type(def_or_max_charge) == "number" then
minetest.log("warning", "Deprecated technic.register_power_tool use. Setting max_charge for "..itemname)
technic.power_tools[itemname] = def_or_max_charge
minetest.register_on_mods_loaded(function()
minetest.log("warning", "Deprecated technic.register_power_tool use. Ensuring fields for "..itemname)
local redef = minetest.registered_items[itemname]
if redef and redef.wear_represents == "technic_RE_charge" then
-- Override power tools that called register_power_tool but do not have on_refill function defined
local overrides = {
technic_max_charge = def_or_max_charge,
technic_wear_factor = 65535 / def_or_max_charge,
on_refill = function(stack)
local tooldef = stack:get_definition()
tooldef.technic_set_charge(stack, def_or_max_charge)
return stack
end,
}
-- Add legacy meta handlers if mod did not attempt to read technic.plus value
local modname = itemname:match(":?(.+):")
if plus_aware[modname] then
overrides.technic_get_charge = redef.technic_get_charge or technic.get_charge
overrides.technic_set_charge = redef.technic_set_charge or technic.set_charge
minetest.log("warning", "Mod "..modname.." seems to be aware of technic.plus but "..
itemname.." is still using deprecated registration, skipping meta charge compatibility.")
elseif not redef.technic_get_charge and not redef.technic_set_charge then
overrides.technic_get_charge = compat_technic_get_charge
overrides.technic_set_charge = compat_technic_set_charge
minetest.log("warning", "Using metadata charge values for "..itemname)
end
-- Override tool definition with added / new values
minetest.override_item(itemname, overrides)
minetest.log("warning", "Updated legacy Technic power tool definition for "..itemname)
else
minetest.log("error", "Technic compatibility overrides skipped for "..itemname..", charging might "..
'cause crash. Upgrading to technic.register_power_tool("'..itemname..'", {itemdef}) recommended.')
end
end)
else
return register_power_tool(itemname, def_or_max_charge)
end
end
technic.set_RE_charge = assert(technic.set_charge)
technic.get_RE_charge = assert(technic.get_charge)
technic.use_RE_charge = assert(technic.use_charge)
-- Same as `technic.set_charge` but without calling through `itemdef.technic_set_charge`.
function technic.set_RE_wear(stack, charge)
minetest.log("warning", "Use of deprecated function technic.set_RE_wear with stack: "..stack:get_name())
compat_set_RE_wear(stack, charge)
end
-- Old utility function to recharge tools
local function charge_tools(meta, batt_charge, charge_step)
local src_stack = meta:get_inventory():get_stack("src", 1)
local def = src_stack:get_definition()
if not def or not def.technic_max_charge or src_stack:is_empty() then
return batt_charge, false
end
local new_charge = math.min(def.technic_max_charge, def.technic_get_charge(src_stack) + charge_step)
def.technic_set_charge(src_stack, new_charge)
meta:get_inventory():set_stack("src", 1, src_stack)
return batt_charge, (def.technic_max_charge == new_charge)
end
function technic.charge_tools(...)
minetest.log("warning", "Use of deprecated function technic.charge_tools")
technic.charge_tools = charge_tools
return charge_tools(...)
end

View file

@ -0,0 +1,80 @@
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
},
rules_allfaces = {
{x= 1, y= 0, z= 0}, {x=-1, y= 0, z= 0}, -- along x beside
{x= 0, y= 1, z= 0}, {x= 0, y=-1, z= 0}, -- along y above and below
{x= 0, y= 0, z= 1}, {x= 0, y= 0, z=-1}, -- along z beside
}
}
-- Compatibility shim to allow old API usage
dofile(path.."/compat/api.lua")
-- https://github.com/mt-mods/technic/issues/100
dofile(path.."/compat/digtron.lua")
dofile(path.."/network.lua")
dofile(path.."/overload.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")
-- Metadata cleanup LBM, removes old metadata values from nodes
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", "")
-- start nodetimer if not already started
local timer = minetest.get_node_timer(pos)
if not timer:is_started() then
timer:start(1.0)
end
end
end,
})

View file

@ -0,0 +1,767 @@
--
-- Power network specific functions and data should live here
--
local S = technic.getter
local off_delay_seconds = tonumber(technic.config:get("switch_off_delay_seconds"))
local network_node_arrays = {"PR_nodes","BA_nodes","RE_nodes"}
technic.active_networks = {}
local networks = {}
technic.networks = networks
local technic_cables = {}
technic.cables = technic_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
local function pos_in_array(pos, array)
for _,pos2 in ipairs(array) do
if pos.x == pos2.x and pos.y == pos2.y and pos.z == pos2.z then
return true
end
end
return false
end
function technic.merge_networks(net1, net2)
-- TODO: Optimize for merging small network into larger by first checking network
-- node counts for both networks and keep network id with most nodes.
assert(type(net1) == "table", "Invalid net1 for technic.merge_networks")
assert(type(net2) == "table", "Invalid net2 for technic.merge_networks")
assert(net1 ~= net2, "Deadlock recipe: net1 & net2 equals for technic.merge_networks")
-- Move data in cables table
for node_id,cable_net_id in pairs(technic_cables) do
if cable_net_id == net2.id then
technic_cables[node_id] = net1.id
end
end
-- Move data in machine tables
for _,tablename in ipairs(network_node_arrays) do
for _,pos in ipairs(net2[tablename]) do
table.insert(net1[tablename], pos)
end
end
-- Move data in all_nodes table
for node_id,pos in pairs(net2.all_nodes) do
net1.all_nodes[node_id] = pos
end
-- Merge queues for incomplete networks
if net1.queue and net2.queue then
for _,pos in ipairs(net2.queue) do
if not pos_in_array(pos, net1.queue) then
table.insert(net1.queue, pos)
end
end
else
net1.queue = net1.queue or net2.queue
end
-- Remove links to net2
networks[net2.id] = nil
technic.active_networks[net2.id] = nil
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, load_node)
-- Get cable tier for switching station or nil if no cable
-- load_node true to use minetest.load_area to load node
local cable_pos = {x=pos.x,y=pos.y-1,z=pos.z}
if load_node then
minetest.load_area(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(technic_cables) do
if cable_net_id == network_id then
technic_cables[pos_hash] = nil
end
end
networks[network_id] = nil
technic.active_networks[network_id] = nil
end
local function switch_index(pos, net)
for index, spos in ipairs(net.swpos) do
if pos.x == spos.x and pos.y == spos.y and pos.z == spos.z then
return index
end
end
end
function technic.switch_insert(pos, net)
if not switch_index(pos, net) then
table.insert(net.swpos, table.copy(pos))
end
return #net.swpos
end
function technic.switch_remove(pos, net)
local swindex = switch_index(pos, net)
if swindex then
table.remove(net.swpos, swindex)
end
return #net.swpos
end
function technic.sw_pos2network(pos)
return technic_cables[poshash({x=pos.x,y=pos.y-1,z=pos.z})]
end
function technic.pos2network(pos)
return technic_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)
local network = networks[network_id]
if network then
if text then
network.infotext = text
elseif network.queue then
local count = 0
for _ in pairs(network.all_nodes) do count = count + 1 end
return S("Building Network: @1 Nodes", count)
else
return network.infotext
end
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 then
local meta = minetest.get_meta(pos)
meta:set_string("infotext", S("@1 Has No Network", nodedef.description))
end
if nodedef and nodedef.technic_disabled_machine_name then
node.name = nodedef.technic_disabled_machine_name
minetest.swap_node(pos, node)
end
if nodedef and nodedef.technic_on_disable then
nodedef.technic_on_disable(pos, node)
end
local node_id = poshash(pos)
for _,nodes in pairs(node_timeout) do
nodes[node_id] = nil
end
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 technic.is_tier_cable(name, tier) then return true end end
return false
end
return technic.get_cable_tier(name) ~= nil
end
local function get_neighbors(pos, tiers)
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
function technic.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
-- Remove machine or cable from network
local function 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)
technic_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.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
remove_network_node(connection.network.id, pos)
end
end
return
end
if #cables == 1 then
-- Dead end cable removed, remove it from the network
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
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
--
-- 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 = technic_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
technic_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
technic.overload_network(network_id)
technic.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(pos, network)
local node_id = poshash(pos)
if not technic_cables[node_id] then
technic_cables[node_id] = network.id
network.all_nodes[node_id] = pos
if network.queue then
table.insert(network.queue, pos)
end
elseif technic_cables[node_id] ~= network.id then
-- Conflicting network connected, merge networks if both are still in building stage
local net2 = networks[technic_cables[node_id]]
if net2 and net2.queue then
technic.merge_networks(network, net2)
end
end
end
-- Generic function to add found connected nodes to the right classification array
local function add_network_node(network, pos, machines)
local name = technic.get_or_load_node(pos).name
if technic.get_cable_tier(name) == network.tier then
add_cable_node(pos, network)
elseif machines[name] then
if machines[name] == technic.producer then
add_network_machine(network.PR_nodes, pos, network.id, network.all_nodes)
elseif machines[name] == technic.receiver then
add_network_machine(network.RE_nodes, pos, network.id, network.all_nodes)
elseif machines[name] == technic.producer_receiver then
if add_network_machine(network.PR_nodes, pos, network.id, network.all_nodes, true) then
table.insert(network.RE_nodes, pos)
end
elseif machines[name] == technic.battery then
add_network_machine(network.BA_nodes, pos, network.id, network.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, pos, technic.machines[network.tier])
end
-- Traverse a network given a list of machines and a cable type name
local function traverse_network(network, pos, 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 i, cur_pos in pairs(positions) do
if not network.all_nodes[poshash(cur_pos)] then
add_network_node(network, cur_pos, machines)
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 not cached.queue 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 machines = technic.machines[network.tier]
--print(string.format("technic.add_network_branch(%s, %s, %.17g)",queue,minetest.pos_to_string(sw_pos),network.id))
local t1 = minetest.get_us_time()
while next(queue) do
local to_visit = {}
for _, pos in ipairs(queue) do
network.queue = to_visit
traverse_network(network, pos, machines)
end
queue = to_visit
if minetest.get_us_time() - t1 > 10000 then
-- time limit exceeded
break
end
end
-- Set build queue for network if network build was not finished within time limits
network.queue = #queue > 0 and queue
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)
local network = networks[network_id]
if network and not network.queue then
-- Network exists complete and cached
return network.PR_nodes, network.BA_nodes, network.RE_nodes
elseif not network then
-- Build new network if network does not exist
technic.remove_network(network_id)
local sw_pos = technic.network2sw_pos(network_id)
local tier = sw_pos and technic.sw_pos2tier(sw_pos)
if not tier then
-- Failed to get initial cable node for network
return
end
network = {
-- Build queue
queue = {},
-- Basic network data and lookup table for attached nodes
id = network_id, tier = tier, all_nodes = {}, swpos = {},
-- 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
add_cable_node(technic.network2pos(network_id), network)
end
-- Continue building incomplete network
technic.add_network_branch(network.queue, network)
network.battery_count = #network.BA_nodes
-- Add newly built network to cache array
networks[network_id] = network
if not network.queue then
-- And return producers, batteries and receivers (should this simply return network?)
return network.PR_nodes, network.BA_nodes, network.RE_nodes
end
end
--
-- Execute technic power network
--
local node_technic_run = {}
minetest.register_on_mods_loaded(function()
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
local place_node = technic.place_network_node
local remove_node = technic.remove_network_node
minetest.override_item(name, {
on_construct = on_construct
and function(pos) on_construct(pos) place_node(pos, tiers, name) end
or function(pos) place_node(pos, tiers, name) end,
on_destruct = on_destruct
and function(pos) on_destruct(pos) remove_node(pos, tiers, name) end
or function(pos) remove_node(pos, tiers, name) end,
})
end
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, run_stage, network)
for _, pos in ipairs(list) do
local node = minetest.get_node_or_nil(pos)
if not node then
minetest.load_area(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
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 t0 = minetest.get_us_time()
local PR_nodes
local BA_nodes
local RE_nodes
local network = networks[network_id]
if network then
PR_nodes, BA_nodes, RE_nodes = get_network(network_id, network.tier)
if not PR_nodes or technic.is_overloaded(network_id) then return end
else
--dprint("Not connected to a network")
technic.network_infotext(network_id, S("@1 Has No Network", 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
run_nodes(PR_nodes, technic.producer, network)
run_nodes(RE_nodes, technic.receiver, network)
run_nodes(BA_nodes, technic.battery, network)
-- Strings for the meta data
local eu_demand_str = network.tier.."_EU_demand"
local eu_input_str = network.tier.."_EU_input"
local eu_supply_str = network.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)))
-- 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(hashpos(network_id)))
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(hashpos(network_id)))
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(hashpos(network_id)))
end
end

View file

@ -0,0 +1,131 @@
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 "@1 Enabled" or "@1 Disabled", desc))
meta:set_string("formspec",
"size[5,3.5]"..
"item_image[0,0;1,1;technic:admin_anchor]"..
"label[1,0;"..desc.."]"..
"label[0,1;"..S("Owner: @1", meta:get_string("owner")).."]"..
(meta:get_int("locked") == 0 and
"button[3,1;2,1;lock;"..S("Unlocked").."]" or
"button[3,1;2,1;unlock;"..S("Locked").."]")..
"field[0.25,2.3;1,1;radius;"..S("Radius")..";${radius}]"..
(meta:get_int("enabled") == 0 and
"button[3,2;2,1;enable;"..S("Disabled").."]" or
"button[3,2;2,1;disable;"..S("Enabled").."]")..
"label[0,3;"..S("Keeping @1/@2 map blocks loaded",
#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 = false,
groups = {cracky=3, not_in_creative_inventory=1, pickaxey=1},
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
sounds = technic.sounds.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
}
}
})

View file

@ -0,0 +1,206 @@
-- Fuel driven alloy furnace. This uses no EUs:
local S = technic.getter
local mat = technic.materials
minetest.register_craft({
output = 'technic:coal_alloy_furnace',
recipe = {
{mat.brick, mat.brick, mat.brick},
{mat.brick, '', mat.brick},
{mat.brick, mat.brick, mat.brick},
}
})
local machine_name = S("Fuel-Fired Alloy Furnace")
local size = minetest.get_modpath("mcl_formspec") and "size[9,9]" or "size[8,9]"
local formspec =
size..
"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;]"
if minetest.get_modpath("mcl_formspec") then
formspec = formspec..
mcl_formspec.get_itemslot_bg(2,3,1,1)..
mcl_formspec.get_itemslot_bg(2,1,2,1)..
mcl_formspec.get_itemslot_bg(5,1,2,2)..
-- player inventory
"list[current_player;main;0,4.5;9,3;9]"..
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
"list[current_player;main;0,7.74;9,1;]"..
mcl_formspec.get_itemslot_bg(0,7.74,9,1)
else
formspec = formspec..
"list[current_player;main;0,5;8,4;]"
end
-- listrings
formspec = formspec..
"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, pickaxey=2},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
legacy_facedir_simple = true,
sounds = technic.sounds.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,
on_metadata_inventory_move = technic.machine_on_inventory_move,
on_metadata_inventory_put = technic.machine_on_inventory_put,
on_metadata_inventory_take = technic.machine_on_inventory_take,
})
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, pickaxey=2},
is_ground_content = false,
_mcl_blast_resistance = 1,
_mcl_hardness = 0.8,
legacy_facedir_simple = true,
sounds = technic.sounds.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,
on_metadata_inventory_move = technic.machine_on_inventory_move,
on_metadata_inventory_put = technic.machine_on_inventory_put,
on_metadata_inventory_take = technic.machine_on_inventory_take,
})
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()
local src_list = inv:get_list("src")
if not src_list then
return
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 recipe = technic.get_recipe("alloy", src_list)
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 recipe then
meta:set_int("src_time", meta:get_int("src_time") + 1)
if meta:get_int("src_time") >= recipe.time then
meta:set_int("src_time", 0)
technic.process_recipe(recipe, inv)
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("@1 Active", machine_name).." ("..percent.."%)")
technic.swap_node(pos, "technic:coal_alloy_furnace_active")
meta:set_string("formspec",
size..
"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;]"..
(minetest.get_modpath("mcl_formspec") and
mcl_formspec.get_itemslot_bg(2,3,1,1)..
mcl_formspec.get_itemslot_bg(2,1,2,1)..
mcl_formspec.get_itemslot_bg(5,1,2,2)..
-- player inventory
"list[current_player;main;0,4.5;9,3;9]"..
mcl_formspec.get_itemslot_bg(0,4.5,9,3)..
"list[current_player;main;0,7.74;9,1;]"..
mcl_formspec.get_itemslot_bg(0,7.74,9,1)
or "list[current_player;main;0,5;8,4;]")..
-- listrings
"listring[context;dst]"..
"listring[current_player;main]"..
"listring[context;src]"..
"listring[current_player;main]"..
"listring[context;fuel]"..
"listring[current_player;main]")
return
end
if not technic.get_recipe("alloy", inv:get_list("src")) then
if was_active then
meta:set_string("infotext", S("@1 is empty", 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 fuellist = inv:get_list("fuel")
local fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
if fuel.time <= 0 then
meta:set_string("infotext", S("@1 Out Of Fuel", 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,
})

View file

@ -0,0 +1,7 @@
local S = technic.getter
local default_furnace = minetest.registered_nodes["default:furnace"]
if default_furnace and default_furnace.description == "Furnace" then
minetest.override_item("default:furnace", { description = S("Fuel-Fired Furnace") })
end

Some files were not shown because too many files have changed in this diff Show more