1
0
mirror of https://github.com/mt-mods/pipeworks.git synced 2025-06-28 22:36:31 +02:00

96 Commits

Author SHA1 Message Date
3a01f3f8ca fix chest duplication bug
closes #118
2024-03-17 20:06:35 +01:00
1577af738f Autocrafter multi group ingredient (#115)
* check for non-zero group value

in theory groups can have negative values too.

* fix #114 multi group recipe items

Fix the bug that prevented crafting with recipes
that had ingredients that need to match multiple
groups.

* comments and whitespace changes

* fix faulty empty table check
2024-03-13 17:31:38 +01:00
8828183bef remove nan values from digiline messages 2024-03-12 14:17:29 +11:00
ce263da6d5 also accept strings of tags in digilines and lua
fixes #116
2024-03-07 14:56:19 +11:00
6c66a2f43c Tags support (#107)
Signed-off-by: Slava Zanko <slavazanko@gmail.com>
Co-authored-by: Slava Zanko <slava.zanko@godel.shellenergy.co.uk>
Co-authored-by: BuckarooBanzay <BuckarooBanzay@users.noreply.github.com>
Co-authored-by: OgelGames <olliverdc28@gmail.com>
2024-03-03 22:48:27 +11:00
8724c28939 switch to using xcompat (#113) 2024-03-03 12:37:46 +01:00
cb2a59131c Make wielder nodes not ground content (#112)
nodebreaker, deployer and dispenser
2024-03-03 14:52:23 +13:00
c7b153f1ef Is ground content (#110)
* trashcan isn't ground content

* pipes aren't ground content

* auto tree tap isn't ground content

* filter-injectors aren't ground content

* devices aren't ground content

also some whitespace indentation fixes

* is_ground_content

* autocrafter isn't ground content

* tubes aren't ground content

* pane_embedded_tube isn't ground content

* embedded_tube isn't ground content

* routing tubes aren't ground content

* whitespace fix indentation
2024-02-26 18:44:40 -05:00
96dca7e540 Fix autocrafter crafting bug (#108) 2024-02-08 21:01:54 +11:00
c87522c526 export pipeworks.tptube.remove_tube (#105)
Co-authored-by: BuckarooBanzay <BuckarooBanzay@users.noreply.github.com>
2024-01-28 16:08:24 -05:00
6d824a318a Tube repair fixes (#102)
* restart vacuum tube node timers after repair

* clear metadata value after repair
2024-01-14 10:10:24 +01:00
04df87a6c2 Delete .editorconfig 2024-01-14 14:29:55 +11:00
360ed9bdde Autocrafter groups support (#74)
* Add support for recipes with groups to autocrafter

* fix autocrafter replacements

* remove unnecessary check and move some code

* reorder and change back var name

* only whitespace changes

* reuse hash that is asigned to variable anyway

* add get_matching_craft

function that looks for the best matching recipe according to what user
put in recipe inventory

some crafts use groups in multiple recipes

* return right away if there is a chached craft

gives us more horizontal space to work with

* indentation adjusting

* use get_matching_craft to get best craft

this line was buggy anyhow

* new craft format: decremented_input

craft.decremented_input now only holds the items. Extra parameters are
dropped

* bugfix: when item has no groups

"" and unknown items have no def and thus no groups

* add function has_room_for_output

moving the output space calculation into its own function
helps keep autocraft() short and overseeable

* use has_room_for_output

* remove double-check of available materials

* add warning to ensure double-check was not needed

* rebuild cache whenever recipe inv changes

no need to check if still current, this only happens when user is
interacting and can only be better to do so.
Otherwise we would have to check groups etc. again just to check, so
might as well reset cache.

* remove unused line

* use minetest.get_item_group()

* whitespace cleanup

make code easier to read and give it a more
"thoughtthrough" look than the "smash it in to make it work" look it has
had.

(I'm holding back, there would be more to do overall through this mod)

* add .editorconfig

this should also help keep consistency throughout this mod

* changelog updated

at least the most recent more important ones

* whitespace changelog (trailing spaces)

---------

Co-authored-by: rubenwardy <rw@rubenwardy.com>
Co-authored-by: OgelGames <olliverdc28@gmail.com>
Co-authored-by: wsor4035 <24964441+wsor4035@users.noreply.github.com>
2024-01-13 20:41:28 -05:00
578e45257b code and registrations cleanup (#101)
* code and registrations cleanup

* don't expose materials to global env

---------

Co-authored-by: BuckarooBanzay <BuckarooBanzay@users.noreply.github.com>
2024-01-13 20:40:01 -05:00
dd6950f7b0 bump min_minetest_version to 5.5.0 for vector.zero()
closes #100
2024-01-05 16:11:23 +11:00
5b0dceb44a add dummy implementations of all current API calls to fake player (#98)
* add dummy implementations of all current API calls to fake player

* fakeplayer: move all stateless API into a metatable

* correctly set metatable
2023-12-29 14:01:08 -05:00
7c74d0bdf3 replace global_exists with get_modpath
related: #97
2023-11-21 14:35:51 +11:00
dc77d1056c fix escaping of ; in teleport tube formspec
closes #93 #94
2023-11-16 14:02:10 +11:00
ab0713d9a5 Fix item duplication bug with broken tubes. (#92)
It was possible to drag items from broken sorting-/mese-tubes.
2023-11-11 23:06:43 +01:00
b6ae50be87 fix MCL craft, chest item id is "mcl_chests:chest" (#89) 2023-10-09 18:22:14 -04:00
e7cba4071b Fix crash if add_entity fails (#88) 2023-09-16 18:19:03 +02:00
d90c17edee MineClone smoker and blast furnace support (#85) 2023-09-06 15:33:41 +02:00
4f55610df5 fix MCL crafts (#86) 2023-09-06 12:01:35 +02:00
500cce8668 MineClone containers support (#81)
* mcl_barrels compat

* open barrel is not in creative inv

* fix barrel drop content after dig

* fix barrel local var

* mcl_furnaces compat

* optional depends mcl_barrels and mcl_furnaces

* fixing luacheck

* .luacheckrc update

* renamed files to use _

* renamed files to init.lua

* format improvement
2023-09-02 15:17:14 -04:00
cb3e7757fc Mineclone dig times balanced (#84)
* mineclone dig times balanced

* fix pickaxey dupe
2023-09-01 15:00:50 +02:00
7f93e8aa0a MineClone formspec compat (#82)
* MineClone list backgrounds compat

* mineclone get inv func
2023-08-24 20:50:49 -04:00
ebe2331619 remove facedir debugging logs (#73)
Co-authored-by: BuckarooBanzay <BuckarooBanzay@users.noreply.github.com>
2023-06-21 21:22:36 +02:00
2f97a367f3 Fix autocrafter destroying replacement items (#72) 2023-06-21 14:49:34 +10:00
9395013cde Support setting teleport tube can_receive by digilines (#68)
* allow setting can_receive flag by digilines

basically also allows sending tables to change
both or either the tp-channel and receive toggle

* apply suggestions

Co-authored-by: OgelGames <olliverdc28@gmail.com>

---------

Co-authored-by: OgelGames <olliverdc28@gmail.com>
2023-05-28 12:54:05 +10:00
2c880a3843 cache teleport tube logging setting
this gets checked every time an item is teleported
2023-05-19 14:17:04 +10:00
56bcc7dbb7 log when items teleport through tubes (#66)
* log when items teleport through tubes

* put teleport tube logging bethind a setting

* narrow scope of some variables
2023-05-18 19:49:12 +02:00
bd5a42356b Use sane default i3 inventory settings when missing (#57)
- i3.settings.hotbar_len and i3.settings.inv_size were removed
   in commit 75fddf7 because they are now per-player settings
 - This just uses sane defaults when the settings are not
   present to avoid a few nils and allow the game to continue
2023-01-26 15:44:41 -05:00
b0b675f715 Fix deprecated call to player:get_look_pitch()
Fixes #53
2023-01-09 13:51:49 +11:00
855937aec3 make all nodes diggable in mcl* survival mode 2022-12-02 15:54:21 -05:00
fc0d4990b0 make minor bugfixes to restore compat with mineclone2 2022-11-20 19:47:14 -05:00
5e9bfa049b Add digilines to teleport tube and refactor code (#49) 2022-11-11 23:20:28 +11:00
5345fe7af3 Prevent vacuum tubes breaking themselves and refactor code (#51)
also bumps `min_minetest_version` to 5.4.0
2022-11-11 23:14:08 +11:00
8c251800db Store teleport tube DB more compactly (#45) 2022-09-21 17:53:42 -04:00
b190d29d21 fix https://github.com/mt-mods/pipeworks/issues/44 2022-09-19 20:21:34 -04:00
e45eca76e1 check if machine is protected before trying to break/place a node (#43)
* check if target is protected before trying to break/place a node, so as not to trigger protection violations

* check whether the machine is protected, not the target
2022-09-17 19:03:55 -04:00
65cea1e33c check if target is protected before trying to break/place a node, so as not to trigger protection violations (#42) 2022-09-16 19:16:58 -04:00
b6c02ac8de typo fix 2022-08-16 00:30:42 +02:00
54243764e0 prevent tubes from connecting to the front of furnaces to match chests 2022-08-13 23:59:46 -04:00
1823690dad Store teleport tube DB in mod storage (#40)
* Store teleport tube DB in mod storage

* Prevent overwriting of tube DB backup file

* Remove backup code

* Slightly improve storage reading code

* Log DB migration to mod storage

* Add migration note in README

* Improve pipeworks.logger
2022-08-13 16:22:53 -04:00
SX
75894355d4 Use on_repair when repairing tube (#37)
* Use on_repair when repairing tube

* Use tube.on_repair

* Verify was_node registration
2022-06-23 18:06:01 +02:00
7b15bdbd1f Add configurable globalstep interval (#32)
* Add configurable globalstep interval

* Add warning for high globalstep interval

* Lower maximum globalstep interval

With no accelerator tubes, 0.8 can handle item movement speeds even
with lag.
2022-05-24 19:13:41 -04:00
90425fde95 fix broken shift-clicking in wielder formspec
fixes #34
2022-05-23 02:28:21 +10:00
1349ff8dd8 Return early from on_step (#33) 2022-05-15 10:58:35 -04:00
3b31b6f9c0 fix https://github.com/mt-mods/pipeworks/issues/31 2022-05-13 22:10:40 -04:00
4fce320d9c Better Hades Revisited support (#30)
* Fix spaces vs tabs in crafts.lua

* Fix recipes, add telepoter device for teleporter tube recipe.

* Override chests and furnaces in Hades as well.
2022-05-12 22:52:17 -04:00
55ded7e569 Make tubes opaque when entities are not used (#29)
* Make tubes opaque when entities are not used
2022-05-11 18:41:28 -04:00
e3d94cb3a8 fix digiline formspec spacing (#27) 2022-05-07 17:04:06 -04:00
97903327a5 Add option to forego real entities (#26) 2022-05-06 11:25:02 -04:00
37eef73695 add I3 support + update to formspecs v2 (#22)
* add fs helper inv function

* add fs helper prepends function

* add trash can, vacuum tube, teleport tube. wielders, autocrafter, mesetube, injectors

* fixed missed texture to make game agnostic

* fix luacheck
2022-04-16 14:51:59 -04:00
3092ce771f Merge pull request #21 from mt-mods/issue_20
override (not replace) minetest_game furnace behaviors. fixes #20
2022-04-01 20:38:39 -07:00
96ccd29dd2 address flux review 2022-04-01 20:20:48 -04:00
8e0b25fb2c fix https://github.com/mt-mods/pipeworks/issues/20 2022-04-01 19:50:21 -04:00
8a29f8844c fix pipeworks:mese_tube_000000 craft 2022-03-20 12:47:45 -04:00
5aa0501872 make pipeworks Game agnostic (#16)
* make it boot in non mtg

* make water flow

* fix water texture warnings

* fix missing steel texture issues

* remove depreciated/unnessary default function calls

* make sounds work

* fix default formspec crashes

* fix wierd tab spacing

* additionally game dig group support

* move crafts to crafts.lua

* make crafts support various games
2022-03-14 21:39:58 -04:00
5618003be3 fix remaining use_texture_alpha warnings
extension of d2954c52, using the same compatibility check for now, though it would be good to bump the minimum minetest version to 5.4 at some point

fixes #11
2022-02-07 15:53:29 +11:00
06fd754216 fix pipeworks_enable_items_per_tube_limit setting
fixes #7
2022-01-07 13:42:08 +11:00
SX
794cae675e Expose set_tube on public API (#6)
* Expose set_tube on public API
* Added update_meta to public tptube API
2022-01-02 15:14:14 +01:00
7d3a61e595 Fix toggling of autocrafter when digilines is not installed (#5)
Co-authored-by: SX <50966843+S-S-X@users.noreply.github.com>
2021-12-26 17:12:15 +11:00
a70115ab8d update wiki link 2021-12-13 20:20:47 -05:00
23fe215721 Fix furnace block fuel (#2)
* Fix blocking of fuel inventory by fuel replacement and losing of fuel replacements.
2021-11-29 17:01:16 +01:00
8f067db7cd github luacheck workflow 2021-11-28 16:13:11 +11:00
e082ea473b fix missing argument when calling on_rightclick 2021-11-28 14:40:40 +11:00
cec6049dd1 Merge branch 'tptube-cache-v2' into 'master'
add caching layer to teleport tube

See merge request VanessaE/pipeworks!46
2021-06-01 17:17:34 +00:00
047718b3c3 add caching layer to teleport tube 2021-06-01 18:57:59 +02:00
01f4ea066c Merge branch 'master' into 'master'
Fix autocrafter to match formspec changes and fix setting of channel

See merge request VanessaE/pipeworks!45
2021-05-29 12:22:42 +00:00
7ba685344c fix autocrafter 2021-05-29 17:37:10 +10:00
c39d40e940 Merge branch 'fix_undeclared' into 'master'
Fix Undeclared Global Variable "unified_inventory"

See merge request VanessaE/pipeworks!44
2021-05-14 04:08:02 +00:00
48b082e014 Fix Undeclared global variable "unified_inventory" 2021-05-13 10:57:58 -07:00
2670fd88a9 Merge branch 'lua-tube-mono' into 'master'
Make the LUA tube editor textarea and error label use monospaced font

See merge request VanessaE/pipeworks!43
2021-05-06 18:21:59 +00:00
3536004667 Merge branch 'fix-protection-check' into 'master'
Skip protection check on formspec close (where not already done)

See merge request VanessaE/pipeworks!42
2021-05-06 18:21:42 +00:00
b53a1ee477 Make LUA editor and error label use mono font 2021-05-06 18:28:47 +02:00
29bac67d3a Skip protection check on formspec close
Prevents protector flip/player being hurt/protection violation if the
player closes the formspec without attempting any changes (sorting tube
and autocrafter).
2021-05-06 18:02:19 +02:00
db6d1bd9c1 Merge branch 'master' into 'master'
Make luacheck happy

See merge request VanessaE/pipeworks!41
2021-04-06 09:12:01 +00:00
79dc5f5c7d Make luacheck happy 2021-04-06 21:10:08 +12:00
01d44056a2 Merge branch 'master' into 'master'
Remove deprecated invsize

See merge request VanessaE/pipeworks!40
2021-04-06 09:09:56 +00:00
c7d44272e6 Remove deprecated invsize 2021-04-06 21:07:35 +12:00
5837d62979 Merge branch 'categories' 2021-04-05 22:16:04 -04:00
fc6efb450c add support for Unified Inventory categories 2021-04-02 15:48:28 -04:00
828c50e85d Merge branch 'formspec-improvements' into 'master'
Improve formspecs for better mobile usability and consistency

See merge request VanessaE/pipeworks!39
2021-04-02 19:47:48 +00:00
4add40705f Improve formspecs for better mobile usability and consistency 2021-04-02 19:47:48 +00:00
a6e4f2dceb Make sure item_exit() exists before calling it inside minetest.after()
When a signal/detector tube breaks, its minetest.after() can be triggered
just after that, perhaps several times, causing it to try to execute the
item_exit() callback of whatever node is present at least once, but a
broken tube has just taken its place and has no such callback.
2021-03-30 08:28:47 -04:00
7ad991ce40 Assorted changes to tube breaking/repair behavior
* Tubes can now be intentionally broken using a hammer
* Log messages have been improved slightly for tube repair
* Punching a broken tube now causes damage due to the sharp edges
2021-03-27 19:51:23 -05:00
d2954c5277 Get rid of most 5.4.0 texture warnings
This commit also shortens the lua_tube.lua code a bit
2021-03-24 19:47:30 +01:00
9ad6e5d07a Merge branch 'master' into 'master'
Add luacheck config and ci job

See merge request VanessaE/pipeworks!37
2021-02-25 16:34:42 +00:00
31e1255245 Add luacheck config and ci job 2021-02-25 16:34:42 +00:00
a735d1a155 Merge branch 'm_small_fixes' into 'master'
Various small fixes

See merge request VanessaE/pipeworks!35
2021-02-07 12:46:16 +00:00
a2c0dd1130 Various small fixes
* Save the fakeplayer's wielded item in set_wielded_item
* pipeworks.luaentity: Return the found objects in get_objects_inside_radius
* Remove the invalid and unused on_blast return values in lua_tube.lua
  This should avoid a crash when a strong explosion happens next to a Lua Tube.
* Do not access a global "nodename" in a BUG message.
  This avoids a potential crash, in case the message actually appears in practice.
* Set the Flow Sensor and Fountain Head mesecons connection rules
* pipeworks.luaentity: Use the same function for move_to and set_pos
* (no functional change) Do not save the object returned by tube_inject_item into the "item1" local variable in filter-injector.lua
2021-02-07 11:58:18 +01:00
f0ef43823c Merge branch 'm_unused_loop_vars' into 'master'
Remove unused loop variables, trailing whitespace and fix mixed-whitespace indentations

See merge request VanessaE/pipeworks!34
2021-02-05 18:03:54 +00:00
17a602a5a1 Remove unused loop variables, trailing whitespace and fix mixed-whitespace indentations 2021-02-05 17:17:50 +01:00
2294a23582 Merge branch 'm_unused_code_removal' into 'master'
Remove or comment unused code and declare some variables local

See merge request VanessaE/pipeworks!33
2021-02-03 18:33:32 +00:00
b2d2ccbcba Remove or comment unused code and declare some variables local 2021-02-03 18:08:50 +01:00
58 changed files with 3362 additions and 1726 deletions

10
.github/workflows/luacheck.yml vendored Normal file
View File

@ -0,0 +1,10 @@
name: luacheck
on: [push, pull_request]
jobs:
luacheck:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@master
- name: Luacheck
uses: lunarmodules/luacheck@master

26
.luacheckrc Normal file
View File

@ -0,0 +1,26 @@
unused_args = false
max_line_length= 240
redefined = false
globals = {
"pipeworks",
"luaentity"
}
read_globals = {
-- Stdlib
string = {fields = {"split"}},
table = {fields = {"copy", "getn"}},
-- Minetest
"vector", "ItemStack",
"dump", "minetest",
"VoxelManip", "VoxelArea",
-- mods
"default", "mesecon", "digiline",
"screwdriver", "unified_inventory",
"i3", "mcl_experience", "awards",
"xcompat",
}

6
README
View File

@ -1,7 +1,7 @@
This mod uses nodeboxes to supply a complete set of 3D pipes and tubes, This mod uses nodeboxes to supply a complete set of 3D pipes and tubes,
along devices that work with them. along devices that work with them.
See https://gitlab.com/VanessaE/pipeworks/wikis/ for detailed information about usage of this mod. See https://github.com/mt-mods/pipeworks/wiki/ for detailed information about usage of this mod.
Unlike the previous version of this mod, these pipes are rounded, and when Unlike the previous version of this mod, these pipes are rounded, and when
placed, they'll automatically join together as needed. Pipes can go vertically placed, they'll automatically join together as needed. Pipes can go vertically
@ -20,3 +20,7 @@ This mod is a work in progress.
Please note that owing to the nature of this mod, I have opted to use 64px Please note that owing to the nature of this mod, I have opted to use 64px
textures. Anything less just looks terrible. textures. Anything less just looks terrible.
The teleport tube database used to be kept in a file named 'teleport_tubes'.
The database is now kept in mod storage. The migration from 'teleport_tubes' is
automatic. The old file is then kept around but is not used at all.

View File

@ -1,11 +1,15 @@
local S = minetest.get_translator("pipeworks") local S = minetest.get_translator("pipeworks")
local autocrafterCache = {} -- caches some recipe data to avoid to call the slow function minetest.get_craft_result() every second -- cache some recipe data to avoid calling the slow function
-- minetest.get_craft_result() every second
local autocrafterCache = {}
local craft_time = 1 local craft_time = 1
local next = next
local function count_index(invlist) local function count_index(invlist)
local index = {} local index = {}
for _, stack in pairs(invlist) do for _, stack in pairs(invlist) do
stack = ItemStack(stack)
if not stack:is_empty() then if not stack:is_empty() then
local stack_name = stack:get_name() local stack_name = stack:get_name()
index[stack_name] = (index[stack_name] or 0) + stack:get_count() index[stack_name] = (index[stack_name] or 0) + stack:get_count()
@ -21,47 +25,232 @@ local function get_item_info(stack)
return description, name return description, name
end end
-- Get best matching recipe for what user has put in crafting grid.
-- This function does not consider crafting method (mix vs craft)
local function get_matching_craft(output_name, example_recipe)
local recipes = minetest.get_all_craft_recipes(output_name)
if not recipes then
return example_recipe
end
if 1 == #recipes then
return recipes[1].items
end
local index_example = count_index(example_recipe)
local best_score = 0
local index_recipe, best_index, score, group
for i = 1, #recipes do
score = 0
index_recipe = count_index(recipes[i].items)
for recipe_item_name, _ in pairs(index_recipe) do
if index_example[recipe_item_name] then
score = score + 1
elseif recipe_item_name:sub(1, 6) == "group:" then
group = recipe_item_name:sub(7)
for example_item_name, _ in pairs(index_example) do
if minetest.get_item_group(
example_item_name, group) ~= 0
then
score = score + 1
break
end
end
end
end
if best_score < score then
best_index = i
best_score = score
end
end
return best_index and recipes[best_index].items or example_recipe
end
local function get_craft(pos, inventory, hash) local function get_craft(pos, inventory, hash)
local hash = hash or minetest.hash_node_position(pos) local hash = hash or minetest.hash_node_position(pos)
local craft = autocrafterCache[hash] local craft = autocrafterCache[hash]
if not craft then if craft then return craft end
local recipe = inventory:get_list("recipe")
local output, decremented_input = minetest.get_craft_result({method = "normal", width = 3, items = recipe}) local example_recipe = inventory:get_list("recipe")
craft = {recipe = recipe, consumption=count_index(recipe), output = output, decremented_input = decremented_input} local output, decremented_input = minetest.get_craft_result({
autocrafterCache[hash] = craft method = "normal", width = 3, items = example_recipe
})
local recipe = example_recipe
if output and not output.item:is_empty() then
recipe = get_matching_craft(output.item:get_name(), example_recipe)
end end
craft = {
recipe = recipe,
consumption = count_index(recipe),
output = output,
decremented_input = decremented_input.items
}
autocrafterCache[hash] = craft
return craft return craft
end end
-- From a consumption table with groups and an inventory index,
-- build a consumption table without groups
local function calculate_consumption(inv_index, consumption_with_groups)
inv_index = table.copy(inv_index)
consumption_with_groups = table.copy(consumption_with_groups)
-- table of items to actually consume
local consumption = {}
-- table of ingredients defined as one or more groups each
local grouped_ingredients = {}
-- First consume all non-group requirements
-- This is done to avoid consuming a non-group item which
-- is also in a group
for key, count in pairs(consumption_with_groups) do
if key:sub(1, 6) == "group:" then
-- build table with group recipe items while looping
grouped_ingredients[key] = key:sub(7):split(',')
else
-- if the item to consume doesn't exist in inventory
-- or not enough of them, abort crafting
if not inv_index[key] or inv_index[key] < count then
return nil
end
consumption[key] = (consumption[key] or 0) + count
consumption_with_groups[key] = consumption_with_groups[key] - count
assert(consumption_with_groups[key] == 0)
consumption_with_groups[key] = nil
inv_index[key] = inv_index[key] - count
assert(inv_index[key] >= 0)
end
end
-- helper function to resolve matching ingredients with multiple group
-- requirements
local function ingredient_groups_match_item(ingredient_groups, name)
local found = 0
local count_ingredient_groups = #ingredient_groups
for i = 1, count_ingredient_groups do
if minetest.get_item_group(name,
ingredient_groups[i]) ~= 0
then
found = found + 1
end
end
return found == count_ingredient_groups
end
-- Next, resolve groups using the remaining items in the inventory
if next(grouped_ingredients) ~= nil then
local take
for itemname, count in pairs(inv_index) do
if count > 0 then
-- groupname is the string as defined by recipe.
-- e.g. group:dye,color_blue
-- groups holds the group names split into a list
-- ready to be passed to core.get_item_group()
for groupname, groups in pairs(grouped_ingredients) do
if consumption_with_groups[groupname] > 0
and ingredient_groups_match_item(groups, itemname)
then
take = math.min(count,
consumption_with_groups[groupname])
consumption_with_groups[groupname] =
consumption_with_groups[groupname] - take
assert(consumption_with_groups[groupname] >= 0)
consumption[itemname] =
(consumption[itemname] or 0) + take
inv_index[itemname] =
inv_index[itemname] - take
assert(inv_index[itemname] >= 0)
end
end
end
end
end
-- Finally, check everything has been consumed
for key, count in pairs(consumption_with_groups) do
if count > 0 then
return nil
end
end
return consumption
end
local function has_room_for_output(list_output, index_output)
local name
local empty_count = 0
for _, item in pairs(list_output) do
if item:is_empty() then
empty_count = empty_count + 1
else
name = item:get_name()
if index_output[name] then
index_output[name] = index_output[name] - item:get_free_space()
end
end
end
for _, count in pairs(index_output) do
if count > 0 then
empty_count = empty_count - 1
end
end
if empty_count < 0 then
return false
end
return true
end
local function autocraft(inventory, craft) local function autocraft(inventory, craft)
if not craft then return false end if not craft then return false end
local output_item = craft.output.item
-- check if we have enough room in dst -- check if output and all replacements fit in dst
if not inventory:room_for_item("dst", output_item) then return false end local output = craft.output.item
local consumption = craft.consumption local out_items = count_index(craft.decremented_input)
local inv_index = count_index(inventory:get_list("src")) out_items[output:get_name()] =
-- check if we have enough material available (out_items[output:get_name()] or 0) + output:get_count()
for itemname, number in pairs(consumption) do
if (not inv_index[itemname]) or inv_index[itemname] < number then return false end if not has_room_for_output(inventory:get_list("dst"), out_items) then
return false
end end
-- check if we have enough material available
local inv_index = count_index(inventory:get_list("src"))
local consumption = calculate_consumption(inv_index, craft.consumption)
if not consumption then
return false
end
-- consume material -- consume material
for itemname, number in pairs(consumption) do for itemname, number in pairs(consumption) do
for i = 1, number do -- We have to do that since remove_item does not work if count > stack_max -- We have to do that since remove_item does not work if count > stack_max
for _ = 1, number do
inventory:remove_item("src", ItemStack(itemname)) inventory:remove_item("src", ItemStack(itemname))
end end
end end
-- craft the result into the dst inventory and add any "replacements" as well -- craft the result into the dst inventory and add any "replacements" as well
inventory:add_item("dst", output_item) inventory:add_item("dst", output)
local leftover
for i = 1, 9 do for i = 1, 9 do
inventory:add_item("dst", craft.decremented_input.items[i]) leftover = inventory:add_item("dst", craft.decremented_input[i])
if leftover and not leftover:is_empty() then
minetest.log("warning", "[pipeworks] autocrafter didn't " ..
"calculate output space correctly.")
end
end end
return true return true
end end
-- returns false to stop the timer, true to continue running -- returns false to stop the timer, true to continue running
-- is started only from start_autocrafter(pos) after sanity checks and cached recipe -- is started only from start_autocrafter(pos) after sanity checks and
-- recipe is cached
local function run_autocrafter(pos, elapsed) local function run_autocrafter(pos, elapsed)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local inventory = meta:get_inventory() local inventory = meta:get_inventory()
@ -73,7 +262,7 @@ local function run_autocrafter(pos, elapsed)
return false return false
end end
for step = 1, math.floor(elapsed/craft_time) do for _ = 1, math.floor(elapsed / craft_time) do
local continue = autocraft(inventory, craft) local continue = autocraft(inventory, craft)
if not continue then return false end if not continue then return false end
end end
@ -97,34 +286,17 @@ end
-- note, that this function assumes allready being updated to virtual items -- note, that this function assumes allready being updated to virtual items
-- and doesn't handle recipes with stacksizes > 1 -- and doesn't handle recipes with stacksizes > 1
local function after_recipe_change(pos, inventory) local function after_recipe_change(pos, inventory)
local hash = minetest.hash_node_position(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
autocrafterCache[hash] = nil
-- if we emptied the grid, there's no point in keeping it running or cached -- if we emptied the grid, there's no point in keeping it running or cached
if inventory:is_empty("recipe") then if inventory:is_empty("recipe") then
minetest.get_node_timer(pos):stop() minetest.get_node_timer(pos):stop()
autocrafterCache[minetest.hash_node_position(pos)] = nil
meta:set_string("infotext", S("unconfigured Autocrafter")) meta:set_string("infotext", S("unconfigured Autocrafter"))
inventory:set_stack("output", 1, "") inventory:set_stack("output", 1, "")
return return
end end
local recipe_changed = false local craft = get_craft(pos, inventory, hash)
local recipe = inventory:get_list("recipe")
local hash = minetest.hash_node_position(pos)
local craft = autocrafterCache[hash]
if craft then
-- check if it changed
local cached_recipe = craft.recipe
for i = 1, 9 do
if recipe[i]:get_name() ~= cached_recipe[i]:get_name() then
autocrafterCache[hash] = nil -- invalidate recipe
craft = nil
break
end
end
end
craft = craft or get_craft(pos, inventory, hash)
local output_item = craft.output.item local output_item = craft.output.item
local description, name = get_item_info(output_item) local description, name = get_item_info(output_item)
meta:set_string("infotext", S("'@1' Autocrafter (@2)", description, name)) meta:set_string("infotext", S("'@1' Autocrafter (@2)", description, name))
@ -133,7 +305,8 @@ local function after_recipe_change(pos, inventory)
after_inventory_change(pos) after_inventory_change(pos)
end end
-- clean out unknown items and groups, which would be handled like unknown items in the crafting grid -- clean out unknown items and groups, which would be handled like unknown
-- items in the crafting grid
-- if minetest supports query by group one day, this might replace them -- if minetest supports query by group one day, this might replace them
-- with a canonical version instead -- with a canonical version instead
local function normalize(item_list) local function normalize(item_list)
@ -164,37 +337,65 @@ local function on_output_change(pos, inventory, stack)
end end
width_idx = (width_idx < 3) and (width_idx + 1) or 1 width_idx = (width_idx < 3) and (width_idx + 1) or 1
end end
-- we'll set the output slot in after_recipe_change to the actual result of the new recipe -- we'll set the output slot in after_recipe_change to the actual
-- result of the new recipe
end end
after_recipe_change(pos, inventory) after_recipe_change(pos, inventory)
end end
-- returns false if we shouldn't bother attempting to start the timer again after this -- returns false if we shouldn't bother attempting to start the timer again
-- after this
local function update_meta(meta, enabled) local function update_meta(meta, enabled)
local state = enabled and "on" or "off" local state = enabled and "on" or "off"
meta:set_int("enabled", enabled and 1 or 0) meta:set_int("enabled", enabled and 1 or 0)
local fs = "size[8,12]".. local list_backgrounds = ""
"list[context;recipe;0,0;3,3;]".. if minetest.get_modpath("i3") or minetest.get_modpath("mcl_formspec") then
"image[3,1;1,1;gui_hb_bg.png^[colorize:#141318:255]".. list_backgrounds = "style_type[box;colors=#666]"
"list[context;output;3,1;1,1;]".. for i = 0, 2 do
"image_button[3,2;1,0.6;pipeworks_button_" .. state .. ".png;" .. state .. ";;;false;pipeworks_button_interm.png]" .. for j = 0, 2 do
"list[context;src;0,4.5;8,3;]".. list_backgrounds = list_backgrounds .. "box[" ..
"list[context;dst;4,0;4,3;]".. 0.22 + (i * 1.25) .. "," .. 0.22 + (j * 1.25) .. ";1,1;]"
default.gui_bg.. end
default.gui_bg_img.. end
default.gui_slots.. for i = 0, 3 do
default.get_hotbar_bg(0,8) .. for j = 0, 2 do
"list[current_player;main;0,8;8,4;]" .. list_backgrounds = list_backgrounds .. "box[" ..
"listring[current_player;main]".. 5.28 + (i * 1.25) .. "," .. 0.22 + (j * 1.25) .. ";1,1;]"
"listring[context;src]" .. end
"listring[current_player;main]".. end
"listring[context;dst]" .. for i = 0, 7 do
"listring[current_player;main]" for j = 0, 2 do
if minetest.get_modpath("digilines") then list_backgrounds = list_backgrounds .. "box[" ..
fs = fs.."field[1,3.5;4,1;channel;"..S("Channel")..";${channel}]" 0.22 + (i * 1.25) .. "," .. 5 + (j * 1.25) .. ";1,1;]"
fs = fs.."button_exit[5,3.2;2,1;save;"..S("Save").."]" end
end
end end
meta:set_string("formspec",fs) local size = "10.2,14"
local fs =
"formspec_version[2]" ..
"size[" .. size .. "]" ..
pipeworks.fs_helpers.get_prepends(size) ..
list_backgrounds ..
"list[context;recipe;0.22,0.22;3,3;]" ..
"image[4,1.45;1,1;[combine:16x16^[noalpha^[colorize:#141318:255]" ..
"list[context;output;4,1.45;1,1;]" ..
"image_button[4,2.6;1,0.6;pipeworks_button_" .. state .. ".png;" ..
state .. ";;;false;pipeworks_button_interm.png]" ..
"list[context;dst;5.28,0.22;4,3;]" ..
"list[context;src;0.22,5;8,3;]" ..
pipeworks.fs_helpers.get_inv(9) ..
"listring[current_player;main]" ..
"listring[context;src]" ..
"listring[current_player;main]" ..
"listring[context;dst]" ..
"listring[current_player;main]"
if minetest.get_modpath("digilines") then
fs = fs .. "field[0.22,4.1;4.5,0.75;channel;" .. S("Channel") ..
";${channel}]" ..
"button[5,4.1;1.5,0.75;set_channel;" .. S("Set") .. "]" ..
"button_exit[6.8,4.1;2,0.75;close;" .. S("Close") .. "]"
end
meta:set_string("formspec", fs)
-- toggling the button doesn't quite call for running a recipe change check -- toggling the button doesn't quite call for running a recipe change check
-- so instead we run a minimal version for infotext setting only -- so instead we run a minimal version for infotext setting only
@ -214,9 +415,12 @@ local function update_meta(meta, enabled)
end end
-- 1st version of the autocrafter had actual items in the crafting grid -- 1st version of the autocrafter had actual items in the crafting grid
-- the 2nd replaced these with virtual items, dropped the content on update and set "virtual_items" to string "1" -- the 2nd replaced these with virtual items, dropped the content on update and
-- the third added an output inventory, changed the formspec and added a button for enabling/disabling -- set "virtual_items" to string "1"
-- so we work out way backwards on this history and update each single case to the newest version -- the third added an output inventory, changed the formspec and added a button
-- for enabling/disabling
-- so we work out way backwards on this history and update each single case
-- to the newest version
local function upgrade_autocrafter(pos, meta) local function upgrade_autocrafter(pos, meta)
local meta = meta or minetest.get_meta(pos) local meta = meta or minetest.get_meta(pos)
local inv = meta:get_inventory() local inv = meta:get_inventory()
@ -227,7 +431,8 @@ local function upgrade_autocrafter(pos, meta)
update_meta(meta, true) update_meta(meta, true)
if meta:get_string("virtual_items") == "1" then -- we are version 2 if meta:get_string("virtual_items") == "1" then -- we are version 2
-- we already dropped stuff, so lets remove the metadatasetting (we are not being called again for this node) -- we already dropped stuff, so lets remove the metadatasetting
-- (we are not being called again for this node)
meta:set_string("virtual_items", "") meta:set_string("virtual_items", "")
else -- we are version 1 else -- we are version 1
local recipe = inv:get_list("recipe") local recipe = inv:get_list("recipe")
@ -252,7 +457,9 @@ minetest.register_node("pipeworks:autocrafter", {
description = S("Autocrafter"), description = S("Autocrafter"),
drawtype = "normal", drawtype = "normal",
tiles = {"pipeworks_autocrafter.png"}, tiles = {"pipeworks_autocrafter.png"},
groups = {snappy = 3, tubedevice = 1, tubedevice_receiver = 1}, groups = {snappy = 3, tubedevice = 1, tubedevice_receiver = 1, dig_generic = 1, axey=1, handy=1, pickaxey=1},
is_ground_content = false,
_mcl_hardness=0.8,
tube = {insert_object = function(pos, node, stack, direction) tube = {insert_object = function(pos, node, stack, direction)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local inv = meta:get_inventory() local inv = meta:get_inventory()
@ -266,18 +473,25 @@ minetest.register_node("pipeworks:autocrafter", {
return inv:room_for_item("src", stack) return inv:room_for_item("src", stack)
end, end,
input_inventory = "dst", input_inventory = "dst",
connect_sides = {left = 1, right = 1, front = 1, back = 1, top = 1, bottom = 1}}, connect_sides = {
left = 1, right = 1, front = 1, back = 1, top = 1, bottom = 1
}
},
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local inv = meta:get_inventory() local inv = meta:get_inventory()
inv:set_size("src", 3*8) inv:set_size("src", 3 * 8)
inv:set_size("recipe", 3*3) inv:set_size("recipe", 3 * 3)
inv:set_size("dst", 4*3) inv:set_size("dst", 4 * 3)
inv:set_size("output", 1) inv:set_size("output", 1)
update_meta(meta, false) update_meta(meta, false)
end, end,
on_receive_fields = function(pos, formname, fields, sender) on_receive_fields = function(pos, formname, fields, sender)
if not pipeworks.may_configure(pos, sender) then return end if (fields.quit and not fields.key_enter_field)
or not pipeworks.may_configure(pos, sender)
then
return
end
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
if fields.on then if fields.on then
update_meta(meta, false) update_meta(meta, false)
@ -286,8 +500,9 @@ minetest.register_node("pipeworks:autocrafter", {
if update_meta(meta, true) then if update_meta(meta, true) then
start_crafter(pos) start_crafter(pos)
end end
elseif fields.save then end
meta:set_string("channel",fields.channel) if fields.channel then
meta:set_string("channel", fields.channel)
end end
end, end,
can_dig = function(pos, player) can_dig = function(pos, player)
@ -321,7 +536,9 @@ minetest.register_node("pipeworks:autocrafter", {
end, end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player) allow_metadata_inventory_take = function(pos, listname, index, stack, player)
if not pipeworks.may_configure(pos, player) then if not pipeworks.may_configure(pos, player) then
minetest.log("action", string.format("%s attempted to take from autocrafter at %s", player:get_player_name(), minetest.pos_to_string(pos))) minetest.log("action", string.format("%s attempted to take from " ..
"autocrafter at %s",
player:get_player_name(), minetest.pos_to_string(pos)))
return 0 return 0
end end
upgrade_autocrafter(pos) upgrade_autocrafter(pos)
@ -337,7 +554,9 @@ minetest.register_node("pipeworks:autocrafter", {
after_inventory_change(pos) after_inventory_change(pos)
return stack:get_count() return stack:get_count()
end, end,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player) allow_metadata_inventory_move = function(
pos, from_list, from_index, to_list, to_index, count, player)
if not pipeworks.may_configure(pos, player) then return 0 end if not pipeworks.may_configure(pos, player) then return 0 end
upgrade_autocrafter(pos) upgrade_autocrafter(pos)
local inv = minetest.get_meta(pos):get_inventory() local inv = minetest.get_meta(pos):get_inventory()
@ -378,13 +597,14 @@ minetest.register_node("pipeworks:autocrafter", {
if type(msg) == "table" then if type(msg) == "table" then
if #msg < 3 then return end if #msg < 3 then return end
local inv = meta:get_inventory() local inv = meta:get_inventory()
for y=0,2,1 do for y = 0, 2, 1 do
for x=1,3,1 do for x = 1, 3, 1 do
local slot = y*3+x local slot = y * 3 + x
if minetest.registered_items[msg[y+1][x]] then if minetest.registered_items[msg[y + 1][x]] then
inv:set_stack("recipe",slot,ItemStack(msg[y+1][x])) inv:set_stack("recipe", slot, ItemStack(
msg[y + 1][x]))
else else
inv:set_stack("recipe",slot,ItemStack("")) inv:set_stack("recipe", slot, ItemStack(""))
end end
end end
end end
@ -393,11 +613,12 @@ minetest.register_node("pipeworks:autocrafter", {
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local inv = meta:get_inventory() local inv = meta:get_inventory()
local recipe = {} local recipe = {}
for y=0,2,1 do for y = 0, 2, 1 do
local row = {} local row = {}
for x=1,3,1 do for x = 1, 3, 1 do
local slot = y*3+x local slot = y * 3 + x
table.insert(row, inv:get_stack("recipe",slot):get_name()) table.insert(row, inv:get_stack(
"recipe", slot):get_name())
end end
table.insert(recipe, row) table.insert(recipe, row)
end end
@ -424,12 +645,4 @@ minetest.register_node("pipeworks:autocrafter", {
}, },
}, },
}) })
pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list + 1] = "pipeworks:autocrafter"
minetest.register_craft( {
output = "pipeworks:autocrafter 2",
recipe = {
{ "default:steel_ingot", "default:mese_crystal", "default:steel_ingot" },
{ "basic_materials:plastic_sheet", "default:steel_ingot", "basic_materials:plastic_sheet" },
{ "default:steel_ingot", "default:mese_crystal", "default:steel_ingot" }
},
})

View File

@ -81,7 +81,7 @@ local function tube_autoroute(pos)
local basename = nodedef.basename local basename = nodedef.basename
if nodedef.style == "old" then if nodedef.style == "old" then
local nsurround = "" local nsurround = ""
for i, n in ipairs(active) do for _, n in ipairs(active) do
nsurround = nsurround..n nsurround = nsurround..n
end end
nctr.name = basename.."_"..nsurround nctr.name = basename.."_"..nsurround

View File

@ -3,6 +3,65 @@ Changelog
2024-02-26 (SwissalpS)
set is_ground_content to false for various nodes.
2023-06-22 (SwissalpS, rubenwardy)
groups support in recipe. Set recipe as usual via recipe formspec or digilines.
Autocrafter now resolves matching recipe using groups so that items in input
inventory are used, that match group and no longer only strictly what user
has in recipe-inventory
2023-06-21 (OgelGames, BuckarooBanzay)
fix autocrafter destroying replacement items (OG)
remove facedir debugging logs (BB)
2023-05-28 (SwissalpS)
support setting 'can_receive' for teleport tubes via digiline
2023-05-19 (fluxionary, OgelGames)
log items going through teleport tubes
2022-12-02 (wsor4035)
bring back compatibility with mineclone2
2022-11-11 (OgelGames)
prevent tp- and sand-tubes from breaking themselves and refactor part of code
2022-09-18 (fluxionary)
protection checks before break-/placeing a node -> less violation logs
2022-08-14 (wsor4035)
prevent tubes from connecting to furnace front
2022-08-13 (TurkeyMcMac)
moved teleport-tube database to mod-storage
2022-06-23 (S-S-X)
on_repair tweak, improved repairing tubes
* many updates not mentioned here *
2017-10-19 (thetaepsilon) 2017-10-19 (thetaepsilon)
Directional flowables are now implemented. Directional flowables are now implemented.
All devices for which it is relevant (valve, flow sensor etc.) have been converted so that they only flow on their connecting sides, so pressure propogation now works as expected for these devices when pressure logic is enabled. All devices for which it is relevant (valve, flow sensor etc.) have been converted so that they only flow on their connecting sides, so pressure propogation now works as expected for these devices when pressure logic is enabled.
@ -50,91 +109,91 @@ What *does not* work:
*seems this hasn't been updated in a while* *seems this hasn't been updated in a while*
2013-01-13: Tubes can transport items now! Namely, I added Novatux/Nore's item 2013-01-13: Tubes can transport items now! Namely, I added Novatux/Nore's item
transport mod as a default part of this mod, to make tubes do something useful! transport mod as a default part of this mod, to make tubes do something useful!
Thanks to Nore and RealBadAngel for the code contributions! Thanks to Nore and RealBadAngel for the code contributions!
2013-01-05: made storage tanks connect from top/bottom, made storage tank and 2013-01-05: made storage tanks connect from top/bottom, made storage tank and
pipe textures use the ^ combine operator so they can show the actual liquid pipe textures use the ^ combine operator so they can show the actual liquid
going through the pipes/tanks. going through the pipes/tanks.
2013-01-04 (a bit later): Made pipes able to carry water! It was just a minor 2013-01-04 (a bit later): Made pipes able to carry water! It was just a minor
logic error resulting from moving the water flowing code into it's own file logic error resulting from moving the water flowing code into it's own file
when I originally imported it. Many thanks to Mauvebic for writing it! when I originally imported it. Many thanks to Mauvebic for writing it!
2013-01-04: First stage of integrating Mauvebic's water flowing code. This is 2013-01-04: First stage of integrating Mauvebic's water flowing code. This is
experimental and doesn't move water yet - but at least it doesn't break experimental and doesn't move water yet - but at least it doesn't break
anything :-) anything :-)
2013-01-01: Various minor tweaks to textures, facedir settings, some other 2013-01-01: Various minor tweaks to textures, facedir settings, some other
stuff. Changed crafting recipes to account for revamped pumps, valves, etc. stuff. Changed crafting recipes to account for revamped pumps, valves, etc.
Now requires the moreores mod and most recent git (for mese crystal fragments) Now requires the moreores mod and most recent git (for mese crystal fragments)
to craft a pump. Added a "sealed" entry/exit panel (really just a horizontal to craft a pump. Added a "sealed" entry/exit panel (really just a horizontal
pipe with a metal panel overlayed into the middle). Also, tweaked pipes to pipe with a metal panel overlayed into the middle). Also, tweaked pipes to
always drop the empty ones. Revamped pumps so that now they should sit in/on always drop the empty ones. Revamped pumps so that now they should sit in/on
liquid and be connected only from the top, relegated grates to decorational- liquid and be connected only from the top, relegated grates to decorational-
only, added outlet spigot. Got rid of a few obsolete textures. Got rid of only, added outlet spigot. Got rid of a few obsolete textures. Got rid of
that whole _x and _z naming thing - now all directional devices (pumps, valves, that whole _x and _z naming thing - now all directional devices (pumps, valves,
spigots, tanks) use facedir. Valves, spigots no longer auto-rotate to find spigots, tanks) use facedir. Valves, spigots no longer auto-rotate to find
nearby pipes. nearby pipes.
2012-09-17: Added test object for pneumatic tube autorouting code, made tubes 2012-09-17: Added test object for pneumatic tube autorouting code, made tubes
connect to it and any object that bears groups={tubedevice=1} (connects to any connect to it and any object that bears groups={tubedevice=1} (connects to any
side) side)
2012-09-05: All recipes doubled except for junglegrass -> plastic sheet (since 2012-09-05: All recipes doubled except for junglegrass -> plastic sheet (since
that is derived from home decor) that is derived from home decor)
2012-09-02: Fixed plastic sheeting recipe. Added crafting recipes for various 2012-09-02: Fixed plastic sheeting recipe. Added crafting recipes for various
objects, with options: If homedecor is installed, use the plastic sheeting objects, with options: If homedecor is installed, use the plastic sheeting
therein. If not, we define it manually. If the Technic mod is installed, therein. If not, we define it manually. If the Technic mod is installed,
don't define any recipes at all. Also removed the extra "loaded!" messages and don't define any recipes at all. Also removed the extra "loaded!" messages and
tweaked the default pipe alias to point to something that is actually visible tweaked the default pipe alias to point to something that is actually visible
:-) :-)
2012-09-01: flattened wielded pipe segment. 2012-09-01: flattened wielded pipe segment.
2012-08-24: Added square-ish pneumatic tubes with their own autoplace code 2012-08-24: Added square-ish pneumatic tubes with their own autoplace code
(does not connect to steel pipes or pipe-oriented devices), then revised their (does not connect to steel pipes or pipe-oriented devices), then revised their
textures shortly after. Fixed a recursion bug that sometimes caused a stack textures shortly after. Fixed a recursion bug that sometimes caused a stack
overflow. Old pipes were overriding the pipeworks:pipe defintion that belongs overflow. Old pipes were overriding the pipeworks:pipe defintion that belongs
with the new pipes. with the new pipes.
2012-08-22: Added outlet grate, made it participate in autoplace algorithm. 2012-08-22: Added outlet grate, made it participate in autoplace algorithm.
Extended storage tank to show fill level in 10% steps (0% to 100%). Added Extended storage tank to show fill level in 10% steps (0% to 100%). Added
"expansion tank" that appears if the user stacks tanks upwards. (Downwards is "expansion tank" that appears if the user stacks tanks upwards. (Downwards is
not checked). not checked).
2012-08-21: Made storage tank participate in autoplace algorithm. Tuned API a 2012-08-21: Made storage tank participate in autoplace algorithm. Tuned API a
little to allow for more flexible placement. Re-organized code a bit to allow little to allow for more flexible placement. Re-organized code a bit to allow
for some upcoming rules changes. Made storage tanks' upper/lower fittins and for some upcoming rules changes. Made storage tanks' upper/lower fittins and
intake grate participate in autoplace algorithm. intake grate participate in autoplace algorithm.
2012-08-20: Added temporary nodes for storage tank and intake grating, but 2012-08-20: Added temporary nodes for storage tank and intake grating, but
without autoplace. without autoplace.
2012-08-19: Pumps and valves now fully participate in the 2012-08-19: Pumps and valves now fully participate in the
auto-rotate/auto-place algorithm. auto-rotate/auto-place algorithm.
2012-08-18: Total rewrite again. All pipes are now nice and round-looking, and 2012-08-18: Total rewrite again. All pipes are now nice and round-looking, and
they auto-connect! Also added temporary nodes for pump and valve (each with an they auto-connect! Also added temporary nodes for pump and valve (each with an
on/off setting - punch to change). No crafting recipes yet and the pipes still on/off setting - punch to change). No crafting recipes yet and the pipes still
don't do anything useful yet. Soon. don't do anything useful yet. Soon.
2012-08-06: Moved this changelog off the forum post and into a separate file. 2012-08-06: Moved this changelog off the forum post and into a separate file.
2012-08-05 (multiple updates): Rewrote pipeworks to use loops and tables to 2012-08-05 (multiple updates): Rewrote pipeworks to use loops and tables to
create the nodes. Requires far less code now. Added -X, +X, -Y, +Y, -Z, +Z create the nodes. Requires far less code now. Added -X, +X, -Y, +Y, -Z, +Z
capped stubs and a short centered horizontal segment. Changed node definitions capped stubs and a short centered horizontal segment. Changed node definitions
so that the aforementioned "short centered" segment is given on dig/drop. so that the aforementioned "short centered" segment is given on dig/drop.
Renamed it to just "pipeworks:pipe" (and pipe_loaded). Added empty/loaded Renamed it to just "pipeworks:pipe" (and pipe_loaded). Added empty/loaded
indicator images to the capped ends, removed some redundant comments. Made the indicator images to the capped ends, removed some redundant comments. Made the
empty/loaded indication at the capped end more prominent. empty/loaded indication at the capped end more prominent.
2012-07-21: Added screenshot showing pipes as they look now that nodebox 2012-07-21: Added screenshot showing pipes as they look now that nodebox
texture rotation is fixed. texture rotation is fixed.
2012-07-18: Changed the mod name and all internals to 'pipeworks' instead of 2012-07-18: Changed the mod name and all internals to 'pipeworks' instead of
'pipes'... after a couple of mistakes :-) 'pipes'... after a couple of mistakes :-)
2012-07-12: moved project to github. 2012-07-12: moved project to github.

View File

@ -1,3 +1,96 @@
local S = minetest.get_translator("pipeworks")
-- Random variables
pipeworks.expect_infinite_stacks = true
if minetest.get_modpath("unified_inventory") or not minetest.settings:get_bool("creative_mode") then
pipeworks.expect_infinite_stacks = false
end
pipeworks.meseadjlist={{x=0,y=0,z=1},{x=0,y=0,z=-1},{x=0,y=1,z=0},{x=0,y=-1,z=0},{x=1,y=0,z=0},{x=-1,y=0,z=0}}
pipeworks.rules_all = {{x=0, y=0, z=1},{x=0, y=0, z=-1},{x=1, y=0, z=0},{x=-1, y=0, z=0},
{x=0, y=1, z=1},{x=0, y=1, z=-1},{x=1, y=1, z=0},{x=-1, y=1, z=0},
{x=0, y=-1, z=1},{x=0, y=-1, z=-1},{x=1, y=-1, z=0},{x=-1, y=-1, z=0},
{x=0, y=1, z=0}, {x=0, y=-1, z=0}}
pipeworks.mesecons_rules={{x=0,y=0,z=1},{x=0,y=0,z=-1},{x=1,y=0,z=0},{x=-1,y=0,z=0},{x=0,y=1,z=0},{x=0,y=-1,z=0}}
pipeworks.digilines_rules={{x=0,y=0,z=1},{x=0,y=0,z=-1},{x=1,y=0,z=0},{x=-1,y=0,z=0},{x=0,y=1,z=0},{x=0,y=-1,z=0}}
pipeworks.liquid_texture = minetest.registered_nodes[pipeworks.liquids.water.flowing].tiles[1]
if type(pipeworks.liquid_texture) == "table" then pipeworks.liquid_texture = pipeworks.liquid_texture.name end
pipeworks.button_off = {text="", texture="pipeworks_button_off.png", addopts="false;false;pipeworks_button_interm.png"}
pipeworks.button_on = {text="", texture="pipeworks_button_on.png", addopts="false;false;pipeworks_button_interm.png"}
pipeworks.button_base = "image_button[0,4.3;1,0.6"
pipeworks.button_label = "label[0.9,4.31;"..S("Allow splitting incoming stacks from tubes").."]"
-- Helper functions
function pipeworks.fix_image_names(table, replacement)
local outtable={}
for i in ipairs(table) do
outtable[i]=string.gsub(table[i], "_XXXXX", replacement)
end
return outtable
end
local function overlay_tube_texture(texture)
-- The texture appears the first time to be colorized as the opaque background.
return ("(%s)^[noalpha^[colorize:#dadada^(%s)"):format(texture, texture)
end
function pipeworks.make_tube_tile(tile)
if pipeworks.use_real_entities then
return tile
elseif type(tile) == "string" then
return overlay_tube_texture(tile)
else
tile = table.copy(tile)
if tile.color then
-- Won't work 100% of the time, but good enough.
tile.name = tile.name .. "^[multiply:" .. minetest.colorspec_to_colorstring(tile.color)
tile.color = nil
end
tile.name = overlay_tube_texture(tile.name)
tile.backface_culling = nil -- The texture is opaque
return tile
end
end
function pipeworks.add_node_box(t, b)
if not t or not b then return end
for i in ipairs(b)
do table.insert(t, b[i])
end
end
function pipeworks.may_configure(pos, player)
local name = player:get_player_name()
local meta = minetest.get_meta(pos)
local owner = meta:get_string("owner")
if owner ~= "" and owner == name then -- wielders and filters
return true
end
return not minetest.is_protected(pos, name)
end
function pipeworks.replace_name(tbl,tr,name)
local ntbl={}
for key,i in pairs(tbl) do
if type(i)=="string" then
ntbl[key]=string.gsub(i,tr,name)
elseif type(i)=="table" then
ntbl[key]=pipeworks.replace_name(i,tr,name)
else
ntbl[key]=i
end
end
return ntbl
end
---------------------- ----------------------
-- Vector functions -- -- Vector functions --
---------------------- ----------------------
@ -114,7 +207,7 @@ local fs_helpers = {}
pipeworks.fs_helpers = fs_helpers pipeworks.fs_helpers = fs_helpers
function fs_helpers.on_receive_fields(pos, fields) function fs_helpers.on_receive_fields(pos, fields)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
for field, value in pairs(fields) do for field in pairs(fields) do
if pipeworks.string_startswith(field, "fs_helpers_cycling:") then if pipeworks.string_startswith(field, "fs_helpers_cycling:") then
local l = field:split(":") local l = field:split(":")
local new_value = tonumber(l[2]) local new_value = tonumber(l[2])
@ -143,6 +236,81 @@ function fs_helpers.cycling_button(meta, base, meta_name, values)
return base..";"..(texture_name and texture_name..";" or "")..field..";"..minetest.formspec_escape(text)..(addopts and ";"..addopts or "").."]" return base..";"..(texture_name and texture_name..";" or "")..field..";"..minetest.formspec_escape(text)..(addopts and ";"..addopts or "").."]"
end end
function fs_helpers.get_inv(y)
local fs = {}
if minetest.get_modpath("i3") then
local inv_x = i3.settings.legacy_inventory and 0.75 or 0.22
local inv_y = (y + 0.4) or 6.9
local size, spacing = 1, 0.1
local hotbar_len = i3.settings.hotbar_len or (i3.settings.legacy_inventory and 8 or 9)
local inv_size = i3.settings.inv_size or (hotbar_len * 4)
table.insert(fs, "style_type[box;colors=#77777710,#77777710,#777,#777]")
for i = 0, hotbar_len - 1 do
table.insert(fs, "box["..(i * size + inv_x + (i * spacing))..","..inv_y..";"..size..","..size..";]")
end
table.insert(fs, "style_type[list;size="..size..";spacing="..spacing.."]")
table.insert(fs, "list[current_player;main;"..inv_x..","..inv_y..";"..hotbar_len..",1;]")
table.insert(fs, "style_type[box;colors=#666]")
for i=0, 2 do
for j=0, hotbar_len - 1 do
table.insert(fs, "box["..0.2+(j*0.1)+(j*size)..","..(inv_y+size+spacing+0.05)+(i*0.1)+(i*size)..";"..size..","..size..";]")
end
end
table.insert(fs, "style_type[list;size="..size..";spacing="..spacing.."]")
table.insert(fs, "list[current_player;main;"..inv_x..","..(inv_y + 1.15)..";"..hotbar_len..","..(inv_size / hotbar_len)..";"..hotbar_len.."]")
elseif minetest.get_modpath("mcl_formspec") then
local inv_x = 0.22
local inv_y = (y + 0.4) or 6.9
local size, spacing = 1, 0.1
local hotbar_len = 9
local inv_size = hotbar_len * 4
table.insert(fs, "style_type[box;colors=#77777710,#77777710,#777,#777]")
for i = 0, hotbar_len - 1 do
table.insert(fs, "box["..(i * size + inv_x + (i * spacing))..","..inv_y..";"..size..","..size..";]")
end
table.insert(fs, "style_type[list;size="..size..";spacing="..spacing.."]")
table.insert(fs, "list[current_player;main;"..inv_x..","..inv_y..";"..hotbar_len..",1;]")
table.insert(fs, "style_type[box;colors=#666]")
for i=0, 2 do
for j=0, hotbar_len - 1 do
table.insert(fs, "box["..0.2+(j*0.1)+(j*size)..","..(inv_y+size+spacing+0.05)+(i*0.1)+(i*size)..";"..size..","..size..";]")
end
end
table.insert(fs, "style_type[list;size="..size..";spacing="..spacing.."]")
table.insert(fs, "list[current_player;main;"..inv_x..","..(inv_y + 1.15)..";"..hotbar_len..","..(inv_size / hotbar_len)..";"..hotbar_len.."]")
else
table.insert(fs, "list[current_player;main;0.22,"..y..";8,4;]")
end
return table.concat(fs, "")
end
function fs_helpers.get_prepends(size)
local prepend = {}
if minetest.get_modpath("i3") then
prepend = {
"no_prepend[]",
"bgcolor[black;neither]",
"background9[0,0;"..size..";i3_bg_full.png;false;10]",
"style_type[button;border=false;bgimg=[combine:16x16^[noalpha^[colorize:#6b6b6b]",
"listcolors[#0000;#ffffff20]"
}
end
return table.concat(prepend, "")
end
--------- ---------
-- Env -- -- Env --
--------- ---------
@ -173,6 +341,183 @@ local function get_set_wrap(name, is_dynamic)
end) end)
end end
local fake_player_metatable = {
is_player = delay(true),
is_fake_player = true,
-- dummy implementation of the rest of the player API:
add_player_velocity = delay(), -- deprecated
add_velocity = delay(),
get_acceleration = delay(), -- no-op for players
get_animation = delay({x = 0, y = 0}, 0, 0, false),
get_armor_groups = delay({}),
get_attach = delay(),
get_attribute = delay(), -- deprecated
get_bone_position = delay(vector.zero(), vector.zero()),
get_children = delay({}),
get_clouds = delay({
ambient = { r = 0, b = 0, g = 0, a = 0 },
color = { r = 0, b = 0, g = 0, a = 0 },
density = 0,
height = 120,
thickness = 10,
speed = vector.zero(),
}),
get_day_night_ratio = delay(),
get_entity_name = delay(),
get_formspec_prepend = delay(""),
get_fov = delay(0, false, 0),
get_lighting = delay({
exposure = {
center_weight_power = 1,
exposure_correction = 0,
luminance_max = -3,
luminance_min = -3,
speed_bright_dark = 1000,
speed_dark_bright = 1000,
},
saturation = 1,
shadows = {
intensity = .6212,
},
}),
get_local_animation = delay({x = 0, y = 0}, {x = 0, y = 0}, {x = 0, y = 0}, {x = 0, y = 0}, 30),
get_luaentity = delay(),
get_meta = delay({
contains = delay(false),
get = delay(),
set_string = delay(),
get_string = delay(""),
set_int = delay(),
get_int = delay(0),
set_float = delay(),
get_float = delay(0),
get_keys = delay({}),
to_table = delay({fields = {}}),
from_table = delay(false),
equals = delay(false),
}),
get_moon = delay({
scale = 1,
texture = "",
tonemap = "",
visible = false,
}),
get_physics_override = delay({
acceleration_air = 1,
acceleration_default = 1,
gravity = 1,
jump = 1,
liquid_fluidity = 1,
liquid_fluidity_smooth = 1,
liquid_sink = 1,
new_move = true,
sneak = true,
sneak_glitch = false,
speed = 1,
speed_climb = 1,
speed_crouch = 1,
}),
get_player_velocity = vector.zero, -- deprecated
get_rotation = delay(), -- no-op for players
get_sky = delay({ r = 0, g = 0, b = 0, a = 0 }, "regular", {}, true),
get_sky_color = delay({
dawn_horizon = { r = 0, g = 0, b = 0, a = 0 },
dawn_sky = { r = 0, g = 0, b = 0, a = 0 },
day_horizon = { r = 0, g = 0, b = 0, a = 0 },
day_sky = { r = 0, g = 0, b = 0, a = 0 },
fog_moon_tint = { r = 0, g = 0, b = 0, a = 0 },
fog_sun_tint = { r = 0, g = 0, b = 0, a = 0 },
fog_tint_type = "default",
indoors = { r = 0, g = 0, b = 0, a = 0 },
night_horizon = { r = 0, g = 0, b = 0, a = 0 },
night_sky = { r = 0, g = 0, b = 0, a = 0 },
}),
get_stars = delay({
count = 1000,
day_opacity = 0,
scale = 1,
star_color = { r = 0, g = 0, b = 0, a = 0 },
visible = true,
}),
get_sun = delay({
scale = 1,
sunrise = "",
sunrise_visible = true,
texture = "",
tonemap = "",
visible = true,
}),
get_texture_mod = delay(), -- no-op for players
get_velocity = vector.zero,
get_yaw = delay(), -- no-op for players
getacceleration = delay(), -- backward compatibility
getvelocity = vector.zero, -- backward compatibility
getyaw = delay(), -- backward compatibility
hud_add = delay(),
hud_change = delay(),
hud_get = delay(),
hud_get_flags = delay({
basic_debug = false,
breathbar = false,
chat = false,
crosshair = false,
healthbar = false,
hotbar = false,
minimap = false,
minimap_radar = false,
wielditem = false,
}),
hud_get_hotbar_image = delay(""),
hud_get_hotbar_itemcount = delay(1),
hud_get_hotbar_selected_image = delay(""),
hud_remove = delay(),
hud_set_flags = delay(),
hud_set_hotbar_image = delay(),
hud_set_hotbar_itemcount = delay(),
hud_set_hotbar_selected_image = delay(),
override_day_night_ratio = delay(),
punch = delay(),
remove = delay(),
respawn = delay(),
right_click = delay(),
send_mapblock = delay(),
set_acceleration = delay(),
set_animation = delay(),
set_animation_frame_speed = delay(),
set_armor_groups = delay(),
set_attach = delay(),
set_attribute = delay(), -- deprecated
set_bone_position = delay(),
set_clouds = delay(),
set_detach = delay(),
set_formspec_prepend = delay(),
set_fov = delay(),
set_lighting = delay(),
set_local_animation = delay(),
set_look_horizontal = delay(),
set_look_pitch = delay(),
set_look_vertical = delay(),
set_look_yaw = delay(),
set_minimap_modes = delay(),
set_moon = delay(),
set_nametag_attributes = delay(),
set_physics_override = delay(),
set_rotation = delay(), -- no-op for players
set_sky = delay(),
set_sprite = delay(), -- no-op for players
set_stars = delay(),
set_sun = delay(),
set_texture_mod = delay(), -- no-op for players
set_velocity = delay(), -- no-op for players
set_yaw = delay(), -- no-op for players
setacceleration = delay(), -- backward compatibility
setsprite = delay(), -- backward compatibility
settexturemod = delay(), -- backward compatibility
setvelocity = delay(), -- backward compatibility
setyaw = delay(), -- backward compatibility
}
function pipeworks.create_fake_player(def, is_dynamic) function pipeworks.create_fake_player(def, is_dynamic)
local wielded_item = ItemStack("") local wielded_item = ItemStack("")
if def.inventory and def.wield_list then if def.inventory and def.wield_list then
@ -180,10 +525,8 @@ function pipeworks.create_fake_player(def, is_dynamic)
end end
local p = { local p = {
get_player_name = delay(def.name), get_player_name = delay(def.name),
is_player = delay(true),
is_fake_player = true,
_formspec = def.formspec or default.gui_survival_form, _formspec = def.formspec or "",
_hp = def.hp or 20, _hp = def.hp or 20,
_breath = 11, _breath = 11,
_pos = def.position and table.copy(def.position) or vector.new(), _pos = def.position and table.copy(def.position) or vector.new(),
@ -202,12 +545,11 @@ function pipeworks.create_fake_player(def, is_dynamic)
get_eye_offset = function(self) get_eye_offset = function(self)
return self._eye_offset1, self._eye_offset3 return self._eye_offset1, self._eye_offset3
end, end,
get_look_dir = delay(def.look_dir or {x=0, y=0, z=1}), get_look_dir = delay(def.look_dir or vector.new()),
get_look_pitch = delay(def.look_pitch or 0), get_look_pitch = delay(def.look_pitch or 0),
get_look_yaw = delay(def.look_yaw or 0), get_look_yaw = delay(def.look_yaw or 0),
get_look_horizontal = delay(def.look_yaw or 0), get_look_horizontal = delay(def.look_yaw or 0),
get_look_vertical = delay(-(def.look_pitch or 0)), get_look_vertical = delay(-(def.look_pitch or 0)),
set_animation = delay(),
-- Controls -- Controls
get_player_control = delay({ get_player_control = delay({
@ -223,7 +565,7 @@ function pipeworks.create_fake_player(def, is_dynamic)
return self._inventory:set_stack(def.wield_list, return self._inventory:set_stack(def.wield_list,
self._wield_index, item) self._wield_index, item)
end end
_wielded_item = ItemStack(item) self._wielded_item = ItemStack(item)
end, end,
get_wielded_item = function(self, item) get_wielded_item = function(self, item)
if self._inventory and def.wield_list then if self._inventory and def.wield_list then
@ -233,57 +575,28 @@ function pipeworks.create_fake_player(def, is_dynamic)
return ItemStack(self._wielded_item) return ItemStack(self._wielded_item)
end, end,
get_wield_list = delay(def.wield_list), get_wield_list = delay(def.wield_list),
get_nametag_attributes = delay({
punch = delay(), bgcolor = false,
remove = delay(), color = { r = 0, g = 0, b = 0, a = 0 },
right_click = delay(), text = def.name,
set_attach = delay(), }),
set_detach = delay(),
set_bone_position = delay(),
hud_change = delay(),
} }
local _trash
-- Getter & setter functions -- Getter & setter functions
p.get_inventory_formspec, p.set_inventory_formspec p.get_inventory_formspec, p.set_inventory_formspec
= get_set_wrap("formspec", is_dynamic) = get_set_wrap("formspec", is_dynamic)
p.get_breath, p.set_breath = get_set_wrap("breath", is_dynamic) p.get_breath, p.set_breath = get_set_wrap("breath", is_dynamic)
p.get_hp, p.set_hp = get_set_wrap("hp", is_dynamic) p.get_hp, p.set_hp = get_set_wrap("hp", is_dynamic)
p.get_pos, p.set_pos = get_set_wrap("pos", is_dynamic) p.get_pos, p.set_pos = get_set_wrap("pos", is_dynamic)
_trash, p.move_to = get_set_wrap("pos", is_dynamic)
p.get_wield_index, p.set_wield_index = get_set_wrap("wield_index", true) p.get_wield_index, p.set_wield_index = get_set_wrap("wield_index", true)
p.get_properties, p.set_properties = get_set_wrap("properties", false) p.get_properties, p.set_properties = get_set_wrap("properties", false)
-- Backwards compatibilty -- For players, move_to and get_pos do the same
p.move_to = p.get_pos
-- Backwards compatibility
p.getpos = p.get_pos p.getpos = p.get_pos
p.setpos = p.set_pos p.setpos = p.set_pos
p.moveto = p.move_to p.moveto = p.move_to
setmetatable(p, { __index = fake_player_metatable })
-- TODO "implement" all these
-- set_armor_groups
-- get_armor_groups
-- get_animation
-- get_bone_position
-- get_player_velocity
-- set_look_pitch
-- set_look_yaw
-- set_physics_override
-- get_physics_override
-- hud_add
-- hud_remove
-- hud_get
-- hud_set_flags
-- hud_get_flags
-- hud_set_hotbar_itemcount
-- hud_get_hotbar_itemcount
-- hud_set_hotbar_image
-- hud_get_hotbar_image
-- hud_set_hotbar_selected_image
-- hud_get_hotbar_selected_image
-- hud_replace_builtin
-- set_sky
-- get_sky
-- override_day_night_ratio
-- get_day_night_ratio
-- set_local_animation
return p return p
end end

View File

@ -11,33 +11,72 @@ local tube_entry = "^pipeworks_tube_connection_wooden.png"
-- Chest Locals -- Chest Locals
local open_chests = {} local open_chests = {}
local function get_chest_formspec(pos) local get_chest_formspec
local spos = pos.x .. "," .. pos.y .. "," .. pos.z
local formspec =
"size[8,9]" ..
default.gui_bg ..
default.gui_bg_img ..
default.gui_slots ..
"list[nodemeta:" .. spos .. ";main;0,0.3;8,4;]" ..
"list[current_player;main;0,4.85;8,1;]" ..
"list[current_player;main;0,6.08;8,3;8]" ..
"listring[nodemeta:" .. spos .. ";main]" ..
"listring[current_player;main]" ..
default.get_hotbar_bg(0,4.85)
-- Pipeworks Switch if minetest.get_modpath("default") then
formspec = formspec .. function get_chest_formspec(pos)
fs_helpers.cycling_button( local spos = pos.x .. "," .. pos.y .. "," .. pos.z
minetest.get_meta(pos), local formspec =
pipeworks.button_base, "size[8,9]" ..
"splitstacks", default.gui_bg ..
{ default.gui_bg_img ..
pipeworks.button_off, default.gui_slots ..
pipeworks.button_on "list[nodemeta:" .. spos .. ";main;0,0.3;8,4;]" ..
} "list[current_player;main;0,4.85;8,1;]" ..
)..pipeworks.button_label "list[current_player;main;0,6.08;8,3;8]" ..
"listring[nodemeta:" .. spos .. ";main]" ..
"listring[current_player;main]" ..
default.get_hotbar_bg(0,4.85)
return formspec -- Pipeworks Switch
formspec = formspec ..
fs_helpers.cycling_button(
minetest.get_meta(pos),
pipeworks.button_base,
"splitstacks",
{
pipeworks.button_off,
pipeworks.button_on
}
)..pipeworks.button_label
return formspec
end
else
local function get_hotbar_bg(x,y)
local out = ""
for i=0,7,1 do
out = out .."image["..x+i..","..y..";1,1;gui_hb_bg.png]"
end
return out
end
function get_chest_formspec(pos)
local spos = pos.x .. "," .. pos.y .. "," .. pos.z
local formspec =
"size[10,9]" ..
"background9[8,8;8,9;hades_chests_chestui.png;true;8]"..
"list[nodemeta:" .. spos .. ";main;0,0.3;10,4;]" ..
"list[current_player;main;0,4.85;10,1;]" ..
"list[current_player;main;0,6.08;10,3;10]" ..
"listring[nodemeta:" .. spos .. ";main]" ..
"listring[current_player;main]" ..
get_hotbar_bg(0,4.85)
-- Pipeworks Switch
formspec = formspec ..
fs_helpers.cycling_button(
minetest.get_meta(pos),
pipeworks.button_base,
"splitstacks",
{
pipeworks.button_off,
pipeworks.button_on
}
)..pipeworks.button_label
return formspec
end
end end
local function chest_lid_obstructed(pos) local function chest_lid_obstructed(pos)
@ -65,13 +104,21 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
open_chests[pn] = nil open_chests[pn] = nil
for k, v in pairs(open_chests) do for _, v in pairs(open_chests) do
if v.pos.x == pos.x and v.pos.y == pos.y and v.pos.z == pos.z then if v.pos.x == pos.x and v.pos.y == pos.y and v.pos.z == pos.z then
return true return true
end end
end end
minetest.after(0.2, function() minetest.after(0.2, function()
minetest.swap_node(pos, { name = "default:" .. swap, param2 = node.param2 }) if minetest.get_modpath("default") then
local current_node = minetest.get_node(pos)
if current_node.name ~= "default:" .. swap .. "_open" then
-- the chest has already been replaced, don't try to replace what's there.
-- see: https://github.com/minetest/minetest_game/pull/3046
return
end
minetest.swap_node(pos, { name = "default:" .. swap, param2 = node.param2 })
end
-- Pipeworks notification -- Pipeworks notification
pipeworks.after_place(pos) pipeworks.after_place(pos)
@ -88,10 +135,18 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end) end)
-- Original Definitions -- Original Definitions
local old_chest_def = table.copy(minetest.registered_items["default:chest"]) local old_chest_def, old_chest_open_def, old_chest_locked_def, old_chest_locked_open_def
local old_chest_open_def = table.copy(minetest.registered_items["default:chest_open"]) if minetest.get_modpath("default") then
local old_chest_locked_def = table.copy(minetest.registered_items["default:chest_locked"]) old_chest_def = table.copy(minetest.registered_items["default:chest"])
local old_chest_locked_open_def = table.copy(minetest.registered_items["default:chest_locked_open"]) old_chest_open_def = table.copy(minetest.registered_items["default:chest_open"])
old_chest_locked_def = table.copy(minetest.registered_items["default:chest_locked"])
old_chest_locked_open_def = table.copy(minetest.registered_items["default:chest_locked_open"])
elseif minetest.get_modpath("hades_chests") then
old_chest_def = table.copy(minetest.registered_items["hades_chests:chest"])
old_chest_open_def = table.copy(minetest.registered_items["hades_chests:chest"])
old_chest_locked_def = table.copy(minetest.registered_items["hades_chests:chest_locked"])
old_chest_locked_open_def = table.copy(minetest.registered_items["hades_chests:chest_locked"])
end
-- Override Construction -- Override Construction
local override_protected, override, override_open, override_protected_open local override_protected, override, override_open, override_protected_open
@ -116,9 +171,11 @@ override_protected = {
minetest.sound_play(old_chest_locked_def.sound_open, {gain = 0.3, minetest.sound_play(old_chest_locked_def.sound_open, {gain = 0.3,
pos = pos, max_hear_distance = 10}) pos = pos, max_hear_distance = 10})
if not chest_lid_obstructed(pos) then if not chest_lid_obstructed(pos) then
minetest.swap_node(pos, if minetest.get_modpath("default") then
{ name = "default:" .. "chest_locked" .. "_open", minetest.swap_node(pos,
param2 = node.param2 }) { name = "default:" .. "chest_locked" .. "_open",
param2 = node.param2 })
end
end end
minetest.after(0.2, minetest.show_formspec, minetest.after(0.2, minetest.show_formspec,
clicker:get_player_name(), clicker:get_player_name(),
@ -160,9 +217,11 @@ override = {
minetest.sound_play(old_chest_def.sound_open, {gain = 0.3, pos = pos, minetest.sound_play(old_chest_def.sound_open, {gain = 0.3, pos = pos,
max_hear_distance = 10}) max_hear_distance = 10})
if not chest_lid_obstructed(pos) then if not chest_lid_obstructed(pos) then
minetest.swap_node(pos, { if minetest.get_modpath("default") then
name = "default:" .. "chest" .. "_open", minetest.swap_node(pos, {
param2 = node.param2 }) name = "default:" .. "chest" .. "_open",
param2 = node.param2 })
end
end end
minetest.after(0.2, minetest.show_formspec, minetest.after(0.2, minetest.show_formspec,
clicker:get_player_name(), clicker:get_player_name(),
@ -230,14 +289,21 @@ override.tiles = {
} }
-- Add the extra groups -- Add the extra groups
for i,v in ipairs({override_protected, override, override_open, override_protected_open}) do for _,v in ipairs({override_protected, override, override_open, override_protected_open}) do
v.groups.tubedevice = 1 v.groups.tubedevice = 1
v.groups.tubedevice_receiver = 1 v.groups.tubedevice_receiver = 1
end end
-- Override with the new modifications. -- Override with the new modifications.
minetest.override_item("default:chest", override) if minetest.get_modpath("default") then
minetest.override_item("default:chest_open", override_open) minetest.override_item("default:chest", override)
minetest.override_item("default:chest_locked", override_protected) minetest.override_item("default:chest_open", override_open)
minetest.override_item("default:chest_locked_open", override_protected_open) minetest.override_item("default:chest_locked", override_protected)
minetest.override_item("default:chest_locked_open", override_protected_open)
elseif minetest.get_modpath("hades_chests") then
minetest.override_item("hades_chests:chest", override)
--minetest.override_item("hades_chests:chest_open", override_open)
minetest.override_item("hades_chests:chest_locked", override_protected)
--minetest.override_item("hades_chests:chest_locked_open", override_protected_open)
end

View File

@ -1,280 +1,28 @@
-- this file is basically a modified copy of -- this file is basically a modified copy of
-- minetest_game/mods/default/furnaces.lua -- minetest_game/mods/default/furnaces.lua
-- translation support local def--, def_active
local S = minetest.get_translator("pipeworks") if minetest.get_modpath("default") then
local DS = minetest.get_translator("default") def = table.copy(minetest.registered_nodes["default:furnace"])
--def_active = table.copy(minetest.registered_nodes["default:furnace_active"])
local fs_helpers = pipeworks.fs_helpers elseif minetest.get_modpath("hades_furnaces") then
def = table.copy(minetest.registered_nodes["hades_furnaces:furnace"])
tube_entry = "^pipeworks_tube_connection_stony.png" --def_active = table.copy(minetest.registered_nodes["hades_furnaces:furnace_active"])
local function active_formspec(fuel_percent, item_percent, pos, meta)
local formspec =
"size[8,8.5]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"list[current_name;src;2.75,0.5;1,1;]"..
"list[current_name;fuel;2.75,2.5;1,1;]"..
"image[2.75,1.5;1,1;default_furnace_fire_bg.png^[lowpart:"..
(100-fuel_percent)..":default_furnace_fire_fg.png]"..
"image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[lowpart:"..
(item_percent)..":gui_furnace_arrow_fg.png^[transformR270]"..
"list[current_name;dst;4.75,0.96;2,2;]"..
"list[current_player;main;0,4.25;8,1;]"..
"list[current_player;main;0,5.5;8,3;8]"..
"listring[current_name;dst]"..
"listring[current_player;main]"..
"listring[current_name;src]"..
"listring[current_player;main]"..
"listring[current_name;fuel]"..
"listring[current_player;main]"..
default.get_hotbar_bg(0, 4.25) ..
fs_helpers.cycling_button(
meta,
"image_button[0,3.5;1,0.6",
"split_material_stacks",
{
pipeworks.button_off,
pipeworks.button_on
}
).."label[0.9,3.51;"..S("Allow splitting incoming material (not fuel) stacks from tubes").."]"
return formspec
end end
local function inactive_formspec(pos, meta) local tube_entry = "^pipeworks_tube_connection_stony.png"
local formspec = "size[8,8.5]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"list[current_name;src;2.75,0.5;1,1;]"..
"list[current_name;fuel;2.75,2.5;1,1;]"..
"image[2.75,1.5;1,1;default_furnace_fire_bg.png]"..
"image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[transformR270]"..
"list[current_name;dst;4.75,0.96;2,2;]"..
"list[current_player;main;0,4.25;8,1;]"..
"list[current_player;main;0,5.5;8,3;8]"..
"listring[current_name;dst]"..
"listring[current_player;main]"..
"listring[current_name;src]"..
"listring[current_player;main]"..
"listring[current_name;fuel]"..
"listring[current_player;main]"..
default.get_hotbar_bg(0, 4.25) ..
fs_helpers.cycling_button(
meta,
"image_button[0,3.5;1,0.6",
"split_material_stacks",
{
pipeworks.button_off,
pipeworks.button_on
}
).."label[0.9,3.51;"..S("Allow splitting incoming material (not fuel) stacks from tubes").."]"
return formspec
end
-- local groups = def.groups
-- Node callback functions that are the same for active and inactive furnace groups["tubedevice"] = 1
-- groups["tubedevice_receiver"] = 1
local groups_active = table.copy(groups)
local function can_dig(pos, player) groups_active["not_in_creative_inventory"] = 1
local meta = minetest.get_meta(pos);
local inv = meta:get_inventory()
return inv:is_empty("fuel") and inv:is_empty("dst") and inv:is_empty("src")
end
local function allow_metadata_inventory_put(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then
return 0
end
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
if listname == "fuel" then
if minetest.get_craft_result({method="fuel", width=1, items={stack}}).time ~= 0 then
if inv:is_empty("src") then
meta:set_string("infotext", DS("Furnace is empty"))
end
return stack:get_count()
else
return 0
end
elseif listname == "src" then
return stack:get_count()
elseif listname == "dst" then
return 0
end
end
local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local stack = inv:get_stack(from_list, from_index)
return allow_metadata_inventory_put(pos, to_list, to_index, stack, player)
end
local function allow_metadata_inventory_take(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then
return 0
end
return stack:get_count()
end
local function swap_node(pos, name)
local node = minetest.get_node(pos)
if node.name == name then
return
end
node.name = name
minetest.swap_node(pos, node)
end
local function furnace_node_timer(pos, elapsed)
--
-- Inizialize metadata
--
local meta = minetest.get_meta(pos)
local fuel_time = meta:get_float("fuel_time") or 0
local src_time = meta:get_float("src_time") or 0
local fuel_totaltime = meta:get_float("fuel_totaltime") or 0
local inv = meta:get_inventory()
local srclist, fuellist
local cookable, cooked
local fuel
local update = true
while update do
update = false
srclist = inv:get_list("src")
fuellist = inv:get_list("fuel")
--
-- Cooking
--
-- Check if we have cookable content
local aftercooked
cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
cookable = cooked.time ~= 0
-- Check if we have enough fuel to burn
if fuel_time < fuel_totaltime then
-- The furnace is currently active and has enough fuel
fuel_time = fuel_time + elapsed
-- If there is a cookable item then check if it is ready yet
if cookable then
src_time = src_time + elapsed
if src_time >= cooked.time then
-- Place result in dst list if possible
if inv:room_for_item("dst", cooked.item) then
inv:add_item("dst", cooked.item)
inv:set_stack("src", 1, aftercooked.items[1])
src_time = src_time - cooked.time
update = true
end
end
end
else
-- Furnace ran out of fuel
if cookable then
-- We need to get new fuel
local afterfuel
fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
if fuel.time == 0 then
-- No valid fuel in fuel list
fuel_totaltime = 0
src_time = 0
else
-- Take fuel from fuel list
inv:set_stack("fuel", 1, afterfuel.items[1])
update = true
fuel_totaltime = fuel.time + (fuel_time - fuel_totaltime)
src_time = src_time + elapsed
end
else
-- We don't need to get new fuel since there is no cookable item
fuel_totaltime = 0
src_time = 0
end
fuel_time = 0
end
elapsed = 0
end
if fuel and fuel_totaltime > fuel.time then
fuel_totaltime = fuel.time
end
if srclist[1]:is_empty() then
src_time = 0
end
--
-- Update formspec, infotext and node
--
local formspec = inactive_formspec(pos, meta)
local item_state
local item_percent = 0
if cookable then
item_percent = math.floor(src_time / cooked.time * 100)
if item_percent > 100 then
item_state = DS("100% (output full)")
else
item_state = DS("@1%", item_percent)
end
else
if srclist[1]:is_empty() then
item_state = DS("Empty")
else
item_state = DS("Not cookable")
end
end
local fuel_state = DS("Empty")
local active = DS("Furnace inactive")
local result = false
if fuel_totaltime ~= 0 then
active = DS("Furnace active")
local fuel_percent = math.floor(fuel_time / fuel_totaltime * 100)
fuel_state = DS("@1%", fuel_percent)
formspec = active_formspec(fuel_percent, item_percent, pos, meta)
swap_node(pos, "default:furnace_active")
-- make sure timer restarts automatically
result = true
else
if not fuellist[1]:is_empty() then
fuel_state = DS("@1%", "0")
end
swap_node(pos, "default:furnace")
-- stop timer on the inactive furnace
minetest.get_node_timer(pos):stop()
end
local infotext = active.." "..DS("(Item: @1; Fuel: @2)", item_state, fuel_state)
--
-- Set meta values
--
meta:set_float("fuel_totaltime", fuel_totaltime)
meta:set_float("fuel_time", fuel_time)
meta:set_float("src_time", src_time)
meta:set_string("formspec", formspec)
meta:set_string("infotext", infotext)
return result
end
-- --
-- Node definitions -- Node definitions
-- --
minetest.register_node(":default:furnace", { local override = {
description = DS("Furnace"),
tiles = { tiles = {
"default_furnace_top.png"..tube_entry, "default_furnace_top.png"..tube_entry,
"default_furnace_bottom.png"..tube_entry, "default_furnace_bottom.png"..tube_entry,
@ -283,7 +31,7 @@ minetest.register_node(":default:furnace", {
"default_furnace_side.png"..tube_entry, "default_furnace_side.png"..tube_entry,
"default_furnace_front.png" "default_furnace_front.png"
}, },
groups = {cracky = 2, tubedevice = 1, tubedevice_receiver = 1}, groups = groups,
tube = { tube = {
insert_object = function(pos, node, stack, direction) insert_object = function(pos, node, stack, direction)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
@ -311,59 +59,15 @@ minetest.register_node(":default:furnace", {
end end
end, end,
input_inventory = "dst", input_inventory = "dst",
connect_sides = {left = 1, right = 1, back = 1, front = 1, bottom = 1, top = 1} connect_sides = {left = 1, right = 1, back = 1, bottom = 1, top = 1}
}, },
paramtype2 = "facedir",
legacy_facedir_simple = true,
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
can_dig = can_dig,
on_timer = furnace_node_timer,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec", inactive_formspec(pos, meta))
local inv = meta:get_inventory()
inv:set_size('src', 1)
inv:set_size('fuel', 1)
inv:set_size('dst', 4)
end,
on_metadata_inventory_move = function(pos)
minetest.get_node_timer(pos):start(1.0)
end,
on_metadata_inventory_put = function(pos)
-- start timer function, it will sort out whether furnace can burn or not.
minetest.get_node_timer(pos):start(1.0)
end,
on_blast = function(pos)
local drops = {}
default.get_inventory_drops(pos, "src", drops)
default.get_inventory_drops(pos, "fuel", drops)
default.get_inventory_drops(pos, "dst", drops)
drops[#drops+1] = "default:furnace"
minetest.remove_node(pos)
return drops
end,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_move = allow_metadata_inventory_move,
allow_metadata_inventory_take = allow_metadata_inventory_take,
on_receive_fields = function(pos, formname, fields, sender)
if not pipeworks.may_configure(pos, sender) then return end
fs_helpers.on_receive_fields(pos, fields)
local meta = minetest.get_meta(pos)
local formspec = inactive_formspec(pos, meta)
meta:set_string("formspec", formspec)
end,
after_place_node = pipeworks.after_place, after_place_node = pipeworks.after_place,
after_dig_node = pipeworks.after_dig, after_dig_node = pipeworks.after_dig,
on_rotate = pipeworks.on_rotate on_rotate = pipeworks.on_rotate
}) }
minetest.register_node(":default:furnace_active", { local override_active = {
description = DS("Furnace"),
tiles = { tiles = {
"default_furnace_top.png"..tube_entry, "default_furnace_top.png"..tube_entry,
"default_furnace_bottom.png"..tube_entry, "default_furnace_bottom.png"..tube_entry,
@ -381,7 +85,7 @@ minetest.register_node(":default:furnace_active", {
}, },
} }
}, },
groups = {cracky = 2, tubedevice = 1, tubedevice_receiver = 1, not_in_creative_inventory = 1}, groups = groups_active,
tube = { tube = {
insert_object = function(pos,node,stack,direction) insert_object = function(pos,node,stack,direction)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
@ -402,37 +106,23 @@ minetest.register_node(":default:furnace_active", {
if direction.y == 1 then if direction.y == 1 then
return inv:room_for_item("fuel", stack) return inv:room_for_item("fuel", stack)
else else
if meta:get_int("split_material_stacks") == 1 then
stack = stack:peek_item(1)
end
return inv:room_for_item("src", stack) return inv:room_for_item("src", stack)
end end
end, end,
input_inventory = "dst", input_inventory = "dst",
connect_sides = {left = 1, right = 1, back = 1, front = 1, bottom = 1, top = 1} connect_sides = {left = 1, right = 1, back = 1, bottom = 1, top = 1}
}, },
paramtype2 = "facedir",
light_source = 8,
drop = "default:furnace",
legacy_facedir_simple = true,
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
on_timer = furnace_node_timer,
can_dig = can_dig,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_move = allow_metadata_inventory_move,
allow_metadata_inventory_take = allow_metadata_inventory_take,
on_receive_fields = function(pos, formname, fields, sender)
if not pipeworks.may_configure(pos, sender) then return end
fs_helpers.on_receive_fields(pos, fields)
local meta = minetest.get_meta(pos)
local formspec = active_formspec(0, 0, pos, meta)
meta:set_string("formspec", formspec)
end,
after_place_node = pipeworks.after_place, after_place_node = pipeworks.after_place,
after_dig_node = pipeworks.after_dig, after_dig_node = pipeworks.after_dig,
on_rotate = pipeworks.on_rotate on_rotate = pipeworks.on_rotate
}) }
if minetest.get_modpath("default") then
minetest.override_item("default:furnace", override)
minetest.override_item("default:furnace_active", override_active)
elseif minetest.get_modpath("hades_furnaces") then
minetest.override_item("hades_furnaces:furnace", override)
minetest.override_item("hades_furnaces:furnace_active", override_active)
end

View File

@ -1,87 +1,318 @@
-- Crafting recipes for pipes -- Crafting recipes for pipes
local materials = xcompat.materials
minetest.register_craft( { minetest.register_craft( {
output = "pipeworks:pipe_1_empty 12", output = "pipeworks:pipe_1_empty 12",
recipe = {
{ "default:steel_ingot", "default:steel_ingot", "default:steel_ingot" },
{ "", "", "" },
{ "default:steel_ingot", "default:steel_ingot", "default:steel_ingot" }
},
})
minetest.register_craft( {
output = "pipeworks:straight_pipe_empty 3",
recipe = {
{ "pipeworks:pipe_1_empty", "pipeworks:pipe_1_empty", "pipeworks:pipe_1_empty" },
},
})
minetest.register_craft( {
output = "pipeworks:spigot 3",
recipe = {
{ "pipeworks:pipe_1_empty", "" },
{ "", "pipeworks:pipe_1_empty" },
},
})
minetest.register_craft( {
output = "pipeworks:entry_panel_empty 2",
recipe = { recipe = {
{ "", "default:steel_ingot", "" }, { materials.steel_ingot, materials.steel_ingot, materials.steel_ingot },
{ "", "pipeworks:pipe_1_empty", "" }, { "", "", "" },
{ "", "default:steel_ingot", "" }, { materials.steel_ingot, materials.steel_ingot, materials.steel_ingot }
}, },
}) })
minetest.register_craft( {
output = "pipeworks:straight_pipe_empty 3",
recipe = {
{ "pipeworks:pipe_1_empty", "pipeworks:pipe_1_empty", "pipeworks:pipe_1_empty" },
},
})
minetest.register_craft( {
output = "pipeworks:spigot 3",
recipe = {
{ "pipeworks:pipe_1_empty", "" },
{ "", "pipeworks:pipe_1_empty" },
},
})
minetest.register_craft( {
output = "pipeworks:entry_panel_empty 2",
recipe = {
{ "", materials.steel_ingot, "" },
{ "", "pipeworks:pipe_1_empty", "" },
{ "", materials.steel_ingot, "" },
},
})
-- Various ancillary pipe devices -- Various ancillary pipe devices
minetest.register_craft( { minetest.register_craft( {
output = "pipeworks:pump_off 2", output = "pipeworks:pump_off 2",
recipe = { recipe = {
{ "default:stone", "default:steel_ingot", "default:stone" }, { materials.stone, materials.steel_ingot, materials.stone },
{ "default:copper_ingot", "default:mese_crystal_fragment", "default:copper_ingot" }, { materials.copper_ingot, materials.mese_crystal_fragment, materials.copper_ingot },
{ "default:steel_ingot", "default:steel_ingot", "default:steel_ingot" } { materials.steel_ingot, materials.steel_ingot, materials.steel_ingot }
}, },
}) })
minetest.register_craft( { minetest.register_craft( {
output = "pipeworks:valve_off_empty 2", output = "pipeworks:valve_off_empty 2",
recipe = { recipe = {
{ "", "group:stick", "" }, { "", "group:stick", "" },
{ "default:steel_ingot", "default:steel_ingot", "default:steel_ingot" }, { materials.steel_ingot, materials.steel_ingot, materials.steel_ingot },
{ "", "default:steel_ingot", "" } { "", materials.steel_ingot, "" }
}, },
}) })
minetest.register_craft( { minetest.register_craft( {
output = "pipeworks:storage_tank_0 2", output = "pipeworks:storage_tank_0 2",
recipe = { recipe = {
{ "", "default:steel_ingot", "default:steel_ingot" }, { "", materials.steel_ingot, materials.steel_ingot },
{ "default:steel_ingot", "default:glass", "default:steel_ingot" }, { materials.steel_ingot, materials.glass, materials.steel_ingot },
{ "default:steel_ingot", "default:steel_ingot", "" } { materials.steel_ingot, materials.steel_ingot, "" }
}, },
}) })
minetest.register_craft( { minetest.register_craft( {
output = "pipeworks:grating 2", output = "pipeworks:grating 2",
recipe = { recipe = {
{ "default:steel_ingot", "", "default:steel_ingot" }, { materials.steel_ingot, "", materials.steel_ingot },
{ "", "pipeworks:pipe_1_empty", "" }, { "", "pipeworks:pipe_1_empty", "" },
{ "default:steel_ingot", "", "default:steel_ingot" } { materials.steel_ingot, "", materials.steel_ingot }
}, },
}) })
minetest.register_craft( { minetest.register_craft( {
output = "pipeworks:flow_sensor_empty 2", output = "pipeworks:flow_sensor_empty 2",
recipe = { recipe = {
{ "pipeworks:pipe_1_empty", "mesecons:mesecon", "pipeworks:pipe_1_empty" }, { "pipeworks:pipe_1_empty", "mesecons:mesecon", "pipeworks:pipe_1_empty" },
}, },
}) })
minetest.register_craft( { minetest.register_craft( {
output = "pipeworks:fountainhead 2", output = "pipeworks:fountainhead 2",
recipe = { recipe = {
{ "pipeworks:pipe_1_empty" }, { "pipeworks:pipe_1_empty" },
{ "pipeworks:pipe_1_empty" } { "pipeworks:pipe_1_empty" }
}, },
}) })
-- injectors
minetest.register_craft( {
output = "pipeworks:filter 2",
recipe = {
{ materials.steel_ingot, materials.steel_ingot, "basic_materials:plastic_sheet" },
{ "group:stick", materials.mese_crystal, "basic_materials:plastic_sheet" },
{ materials.steel_ingot, materials.steel_ingot, "basic_materials:plastic_sheet" }
},
})
minetest.register_craft( {
output = "pipeworks:mese_filter 2",
recipe = {
{ materials.steel_ingot, materials.steel_ingot, "basic_materials:plastic_sheet" },
{ "group:stick", materials.mese, "basic_materials:plastic_sheet" },
{ materials.steel_ingot, materials.steel_ingot, "basic_materials:plastic_sheet" }
},
})
if minetest.get_modpath("digilines") then
minetest.register_craft( {
output = "pipeworks:digiline_filter 2",
recipe = {
{ materials.steel_ingot, materials.steel_ingot, "basic_materials:plastic_sheet" },
{ "group:stick", "digilines:wire_std_00000000", "basic_materials:plastic_sheet" },
{ materials.steel_ingot, materials.steel_ingot, "basic_materials:plastic_sheet" }
},
})
end
-- other
minetest.register_craft( {
output = "pipeworks:autocrafter 2",
recipe = {
{ materials.steel_ingot, materials.mese_crystal, materials.steel_ingot },
{ "basic_materials:plastic_sheet", materials.steel_ingot, "basic_materials:plastic_sheet" },
{ materials.steel_ingot, materials.mese_crystal, materials.steel_ingot }
},
})
minetest.register_craft( {
output = "pipeworks:steel_pane_embedded_tube 1",
recipe = {
{ "", materials.steel_ingot, "" },
{ "", "pipeworks:tube_1", "" },
{ "", materials.steel_ingot, "" }
},
})
minetest.register_craft({
output = "pipeworks:trashcan",
recipe = {
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" },
{ materials.steel_ingot, "", materials.steel_ingot },
{ materials.steel_ingot, materials.steel_ingot, materials.steel_ingot },
},
})
minetest.register_craft( {
output = "pipeworks:teleport_tube_1 2",
recipe = {
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" },
{ materials.desert_stone, materials.mese, materials.desert_stone },
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" }
},
})
if pipeworks.enable_priority_tube then
minetest.register_craft( {
output = "pipeworks:priority_tube_1 6",
recipe = {
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" },
{ materials.gold_ingot, "", materials.gold_ingot },
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" }
},
})
end
if pipeworks.enable_accelerator_tube then
minetest.register_craft( {
output = "pipeworks:accelerator_tube_1 2",
recipe = {
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" },
{ materials.mese_crystal_fragment, materials.steel_ingot, materials.mese_crystal_fragment },
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" }
},
})
end
if pipeworks.enable_crossing_tube then
minetest.register_craft( {
output = "pipeworks:crossing_tube_1 5",
recipe = {
{ "", "pipeworks:tube_1", "" },
{ "pipeworks:tube_1", "pipeworks:tube_1", "pipeworks:tube_1" },
{ "", "pipeworks:tube_1", "" }
},
})
end
if pipeworks.enable_one_way_tube then
minetest.register_craft({
output = "pipeworks:one_way_tube 2",
recipe = {
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" },
{ "group:stick", materials.mese_crystal, "basic_materials:plastic_sheet" },
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" }
},
})
end
if pipeworks.enable_mese_tube then
minetest.register_craft( {
output = "pipeworks:mese_tube_000000 2",
recipe = {
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" },
{ "", materials.mese_crystal, "" },
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" }
},
})
minetest.register_craft( {
type = "shapeless",
output = "pipeworks:mese_tube_000000",
recipe = {
"pipeworks:tube_1",
materials.mese_crystal_fragment,
materials.mese_crystal_fragment,
materials.mese_crystal_fragment,
materials.mese_crystal_fragment,
},
})
end
if pipeworks.enable_item_tags and pipeworks.enable_tag_tube then
minetest.register_craft( {
output = "pipeworks:tag_tube_000000 2",
recipe = {
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" },
{ materials.book, materials.mese_crystal, materials.book },
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" }
},
})
minetest.register_craft( {
type = "shapeless",
output = "pipeworks:tag_tube_000000",
recipe = {
"pipeworks:mese_tube_000000",
materials.book,
},
})
end
if pipeworks.enable_sand_tube then
minetest.register_craft( {
output = "pipeworks:sand_tube_1 2",
recipe = {
{"basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet"},
{"group:sand", "group:sand", "group:sand"},
{"basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet"}
},
})
minetest.register_craft( {
output = "pipeworks:sand_tube_1",
recipe = {
{"group:sand", "pipeworks:tube_1", "group:sand"},
},
})
end
if pipeworks.enable_mese_sand_tube then
minetest.register_craft( {
output = "pipeworks:mese_sand_tube_1 2",
recipe = {
{"basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" },
{"group:sand", materials.mese_crystal, "group:sand" },
{"basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" }
},
})
minetest.register_craft( {
type = "shapeless",
output = "pipeworks:mese_sand_tube_1",
recipe = {
"pipeworks:sand_tube_1",
materials.mese_crystal_fragment,
materials.mese_crystal_fragment,
materials.mese_crystal_fragment,
materials.mese_crystal_fragment,
},
})
end
if pipeworks.enable_deployer then
minetest.register_craft({
output = "pipeworks:deployer_off",
recipe = {
{ "group:wood", materials.chest, "group:wood" },
{ materials.stone, "mesecons:piston", materials.stone },
{ materials.stone, "mesecons:mesecon", materials.stone },
}
})
end
if pipeworks.enable_dispenser then
minetest.register_craft({
output = "pipeworks:dispenser_off",
recipe = {
{ materials.desert_sand, materials.chest, materials.desert_sand },
{ materials.stone, "mesecons:piston", materials.stone },
{ materials.stone, "mesecons:mesecon", materials.stone },
}
})
end
if pipeworks.enable_node_breaker then
minetest.register_craft({
output = "pipeworks:nodebreaker_off",
recipe = {
{ "basic_materials:gear_steel", "basic_materials:gear_steel", "basic_materials:gear_steel" },
{ materials.stone, "mesecons:piston", materials.stone },
{ "group:wood", "mesecons:mesecon", "group:wood" },
}
})
end

View File

@ -1,87 +0,0 @@
local S = minetest.get_translator("pipeworks")
local straight = function(pos, node, velocity, stack) return {velocity} end
minetest.register_node("pipeworks:steel_block_embedded_tube", {
description = S("Airtight steelblock embedded tube"),
tiles = {
"default_steel_block.png", "default_steel_block.png",
"default_steel_block.png", "default_steel_block.png",
"default_steel_block.png^pipeworks_tube_connection_metallic.png",
"default_steel_block.png^pipeworks_tube_connection_metallic.png",
},
paramtype = "light",
paramtype2 = "facedir",
groups = {cracky=1, oddly_breakable_by_hand = 1, tubedevice = 1},
legacy_facedir_simple = true,
sounds = default.node_sound_stone_defaults(),
tube = {
connect_sides = {front = 1, back = 1,},
priority = 50,
can_go = straight,
can_insert = function(pos, node, stack, direction)
local dir = minetest.facedir_to_dir(node.param2)
return vector.equals(dir, direction) or vector.equals(vector.multiply(dir, -1), direction)
end,
},
after_place_node = pipeworks.after_place,
after_dig_node = pipeworks.after_dig,
on_rotate = pipeworks.on_rotate,
})
minetest.register_craft( {
output = "pipeworks:steel_block_embedded_tube 1",
recipe = {
{ "default:steel_ingot", "default:steel_ingot", "default:steel_ingot" },
{ "default:steel_ingot", "pipeworks:tube_1", "default:steel_ingot" },
{ "default:steel_ingot", "default:steel_ingot", "default:steel_ingot" }
},
})
local pane_box = {
type = "fixed",
fixed = {
{ -9/64, -9/64, -8/16, 9/64, 9/64, 8/16 }, -- tube
{ -8/16, -8/16, -1/16, 8/16, 8/16, 1/16 } -- pane
}
}
minetest.register_node("pipeworks:steel_pane_embedded_tube", {
drawtype = "nodebox",
description = S("Airtight panel embedded tube"),
tiles = {
"pipeworks_pane_embedded_tube_sides.png^[transformR90",
"pipeworks_pane_embedded_tube_sides.png^[transformR90",
"pipeworks_pane_embedded_tube_sides.png",
"pipeworks_pane_embedded_tube_sides.png",
"pipeworks_pane_embedded_tube_ends.png", "pipeworks_pane_embedded_tube_ends.png",
},
node_box = pane_box,
selection_box = pane_box,
collision_box = pane_box,
paramtype = "light",
paramtype2 = "facedir",
groups = {cracky=1, oddly_breakable_by_hand = 1, tubedevice = 1},
legacy_facedir_simple = true,
sounds = default.node_sound_stone_defaults(),
tube = {
connect_sides = {front = 1, back = 1,},
priority = 50,
can_go = straight,
can_insert = function(pos, node, stack, direction)
local dir = minetest.facedir_to_dir(node.param2)
return vector.equals(dir, direction) or vector.equals(vector.multiply(dir, -1), direction)
end,
},
after_place_node = pipeworks.after_place,
after_dig_node = pipeworks.after_dig,
on_rotate = pipeworks.on_rotate,
})
minetest.register_craft( {
output = "pipeworks:steel_pane_embedded_tube 1",
recipe = {
{ "", "default:steel_ingot", "" },
{ "", "pipeworks:tube_1", "" },
{ "", "default:steel_ingot", "" }
},
})

View File

@ -4,6 +4,8 @@ local prefix = "pipeworks_"
local settings = { local settings = {
enable_pipes = true, enable_pipes = true,
enable_item_tags = true,
enable_tag_tube = true,
enable_lowpoly = false, enable_lowpoly = false,
enable_autocrafter = true, enable_autocrafter = true,
enable_deployer = true, enable_deployer = true,
@ -27,6 +29,8 @@ local settings = {
enable_cyclic_mode = true, enable_cyclic_mode = true,
drop_on_routing_fail = false, drop_on_routing_fail = false,
delete_item_on_clearobject = true, delete_item_on_clearobject = true,
use_real_entities = true,
entity_update_interval = 0,
} }
pipeworks.toggles = {} pipeworks.toggles = {}
@ -62,10 +66,9 @@ pipeworks.toggles.finite_water = nil
for name, value in pairs(settings) do for name, value in pairs(settings) do
local setting_type = type(value) local setting_type = type(value)
if setting_type == "boolean" then if setting_type == "boolean" then
pipeworks[name] = minetest.settings:get_bool(prefix..name) pipeworks[name] = minetest.settings:get_bool(prefix..name, value)
if pipeworks[name] == nil then elseif setting_type == "number" then
pipeworks[name] = value pipeworks[name] = tonumber(minetest.settings:get(prefix..name) or value)
end
else else
pipeworks[name] = value pipeworks[name] = value
end end

View File

@ -1,6 +1,8 @@
local S = minetest.get_translator("pipeworks") local S = minetest.get_translator("pipeworks")
local new_flow_logic_register = pipeworks.flowables.register local new_flow_logic_register = pipeworks.flowables.register
local texture_alpha_mode = minetest.features.use_texture_alpha_string_modes
local polys = "" local polys = ""
if pipeworks.enable_lowpoly then polys = "_lowpoly" end if pipeworks.enable_lowpoly then polys = "_lowpoly" end
@ -10,7 +12,7 @@ function pipeworks.fix_after_rotation(pos, node, user, mode, new_param2)
if string.find(node.name, "spigot") then new_param2 = new_param2 % 4 end if string.find(node.name, "spigot") then new_param2 = new_param2 % 4 end
newnode = string.gsub(node.name, "_on", "_off") local newnode = string.gsub(node.name, "_on", "_off")
minetest.swap_node(pos, { name = newnode, param2 = new_param2 }) minetest.swap_node(pos, { name = newnode, param2 = new_param2 })
pipeworks.scan_for_pipe_objects(pos) pipeworks.scan_for_pipe_objects(pos)
@ -20,7 +22,7 @@ end
function pipeworks.rotate_on_place(itemstack, placer, pointed_thing) function pipeworks.rotate_on_place(itemstack, placer, pointed_thing)
local playername = placer:get_player_name() local playername = placer:get_player_name()
if not minetest.is_protected(pointed_thing.under, playername) if not minetest.is_protected(pointed_thing.under, playername)
and not minetest.is_protected(pointed_thing.above, playername) then and not minetest.is_protected(pointed_thing.above, playername) then
local node = minetest.get_node(pointed_thing.under) local node = minetest.get_node(pointed_thing.under)
@ -28,17 +30,17 @@ function pipeworks.rotate_on_place(itemstack, placer, pointed_thing)
if (not placer:get_player_control().sneak) if (not placer:get_player_control().sneak)
and minetest.registered_nodes[node.name] and minetest.registered_nodes[node.name]
and minetest.registered_nodes[node.name].on_rightclick then and minetest.registered_nodes[node.name].on_rightclick then
minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under, node, placer, itemstack) minetest.registered_nodes[node.name].on_rightclick(pointed_thing.under,
node, placer, itemstack, pointed_thing)
else else
local pitch = placer:get_look_pitch() local pitch = -placer:get_look_vertical()
local above = pointed_thing.above local above = pointed_thing.above
local under = pointed_thing.under local under = pointed_thing.under
local fdir = minetest.dir_to_facedir(placer:get_look_dir()) local fdir = minetest.dir_to_facedir(placer:get_look_dir())
local undernode = minetest.get_node(under) local undernode = minetest.get_node(under)
local abovenode = minetest.get_node(above)
local uname = undernode.name local uname = undernode.name
local aname = abovenode.name
local isabove = (above.x == under.x) and (above.z == under.z) and (pitch > 0) local isabove = (above.x == under.x) and (above.z == under.z) and (pitch > 0)
local pos1 = above local pos1 = above
@ -105,6 +107,7 @@ if minetest.get_modpath("mesecons") then
} }
end end
--[[
local pipes_devicelist = { local pipes_devicelist = {
"pump", "pump",
"valve", "valve",
@ -120,18 +123,19 @@ local pipes_devicelist = {
"storage_tank_9", "storage_tank_9",
"storage_tank_10" "storage_tank_10"
} }
--]]
-- Now define the nodes. -- Now define the nodes.
local states = { "on", "off" } local states = { "on", "off" }
local dgroups = ""
for s in ipairs(states) do for s in ipairs(states) do
local dgroups
if states[s] == "off" then if states[s] == "off" then
dgroups = {snappy=3, pipe=1} dgroups = {snappy=3, pipe=1, dig_generic = 4, axey=1, handy=1, pickaxey=1}
else else
dgroups = {snappy=3, pipe=1, not_in_creative_inventory=1} dgroups = {snappy=3, pipe=1, not_in_creative_inventory=1, dig_generic = 4, axey=1, handy=1, pickaxey=1}
end end
local pumpname = "pipeworks:pump_"..states[s] local pumpname = "pipeworks:pump_"..states[s]
@ -140,10 +144,15 @@ for s in ipairs(states) do
drawtype = "mesh", drawtype = "mesh",
mesh = "pipeworks_pump"..polys..".obj", mesh = "pipeworks_pump"..polys..".obj",
tiles = { "pipeworks_pump_"..states[s]..".png" }, tiles = { "pipeworks_pump_"..states[s]..".png" },
use_texture_alpha = texture_alpha_mode and "clip" or true,
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
groups = dgroups, groups = dgroups,
sounds = default.node_sound_metal_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_metal_defaults",
},
walkable = true, walkable = true,
pipe_connections = { top = 1 }, pipe_connections = { top = 1 },
after_place_node = function(pos) after_place_node = function(pos)
@ -165,7 +174,7 @@ for s in ipairs(states) do
local fdir = node.param2 local fdir = node.param2
minetest.swap_node(pos, { name = "pipeworks:pump_"..states[3-s], param2 = fdir }) minetest.swap_node(pos, { name = "pipeworks:pump_"..states[3-s], param2 = fdir })
end, end,
on_rotate = screwdriver.rotate_simple on_rotate = screwdriver and screwdriver.rotate_simple or nil
}) })
-- FIXME: this currently assumes that pumps can only rotate around the fixed axis pointing Y+. -- FIXME: this currently assumes that pumps can only rotate around the fixed axis pointing Y+.
@ -187,15 +196,19 @@ for s in ipairs(states) do
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
selection_box = { selection_box = {
type = "fixed", type = "fixed",
fixed = { -5/16, -4/16, -8/16, 5/16, 5/16, 8/16 } fixed = { -5/16, -4/16, -8/16, 5/16, 5/16, 8/16 }
}, },
collision_box = { collision_box = {
type = "fixed", type = "fixed",
fixed = { -5/16, -4/16, -8/16, 5/16, 5/16, 8/16 } fixed = { -5/16, -4/16, -8/16, 5/16, 5/16, 8/16 }
}, },
groups = dgroups, groups = dgroups,
sounds = default.node_sound_metal_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_metal_defaults",
},
walkable = true, walkable = true,
on_place = pipeworks.rotate_on_place, on_place = pipeworks.rotate_on_place,
after_dig_node = function(pos) after_dig_node = function(pos)
@ -222,6 +235,8 @@ for s in ipairs(states) do
new_flow_logic_register.directional_horizonal_rotate(nodename_valve_empty, true) new_flow_logic_register.directional_horizonal_rotate(nodename_valve_empty, true)
end end
end end
pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:pump_off"
pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:valve_off_empty"
local nodename_valve_loaded = "pipeworks:valve_on_loaded" local nodename_valve_loaded = "pipeworks:valve_on_loaded"
minetest.register_node(nodename_valve_loaded, { minetest.register_node(nodename_valve_loaded, {
@ -233,15 +248,19 @@ minetest.register_node(nodename_valve_loaded, {
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
selection_box = { selection_box = {
type = "fixed", type = "fixed",
fixed = { -5/16, -4/16, -8/16, 5/16, 5/16, 8/16 } fixed = { -5/16, -4/16, -8/16, 5/16, 5/16, 8/16 }
}, },
collision_box = { collision_box = {
type = "fixed", type = "fixed",
fixed = { -5/16, -4/16, -8/16, 5/16, 5/16, 8/16 } fixed = { -5/16, -4/16, -8/16, 5/16, 5/16, 8/16 }
}, },
groups = {snappy=3, pipe=1, not_in_creative_inventory=1}, groups = {snappy=3, pipe=1, not_in_creative_inventory=1, dig_generic = 4, axey=1, handy=1, pickaxey=1},
sounds = default.node_sound_metal_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_metal_defaults",
},
walkable = true, walkable = true,
on_place = pipeworks.rotate_on_place, on_place = pipeworks.rotate_on_place,
after_dig_node = function(pos) after_dig_node = function(pos)
@ -282,6 +301,7 @@ minetest.register_node("pipeworks:grating", {
"pipeworks_grating_sides.png", "pipeworks_grating_sides.png",
"pipeworks_grating_sides.png" "pipeworks_grating_sides.png"
}, },
use_texture_alpha = texture_alpha_mode and "clip" or true,
drawtype = "nodebox", drawtype = "nodebox",
node_box = { node_box = {
type = "fixed", type = "fixed",
@ -289,8 +309,12 @@ minetest.register_node("pipeworks:grating", {
}, },
sunlight_propagates = true, sunlight_propagates = true,
paramtype = "light", paramtype = "light",
groups = {snappy=3, pipe=1}, groups = {snappy=3, pipe=1, dig_generic = 4, axey=1, handy=1, pickaxey=1},
sounds = default.node_sound_metal_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_metal_defaults",
},
walkable = true, walkable = true,
pipe_connections = { top = 1 }, pipe_connections = { top = 1 },
after_place_node = function(pos) after_place_node = function(pos)
@ -301,6 +325,7 @@ minetest.register_node("pipeworks:grating", {
end, end,
on_rotate = false on_rotate = false
}) })
pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:grating"
-- outlet spigot -- outlet spigot
@ -313,8 +338,12 @@ minetest.register_node(nodename_spigot_empty, {
sunlight_propagates = true, sunlight_propagates = true,
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
groups = {snappy=3, pipe=1}, groups = {snappy=3, pipe=1, dig_generic = 4, axey=1, handy=1, pickaxey=1},
sounds = default.node_sound_metal_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_metal_defaults",
},
walkable = true, walkable = true,
pipe_connections = { left=1, right=1, front=1, back=1, pipe_connections = { left=1, right=1, front=1, back=1,
left_param2 = 3, right_param2 = 1, front_param2 = 2, back_param2 = 0 }, left_param2 = 3, right_param2 = 1, front_param2 = 2, back_param2 = 0 },
@ -341,22 +370,19 @@ minetest.register_node(nodename_spigot_loaded, {
drawtype = "mesh", drawtype = "mesh",
mesh = "pipeworks_spigot_pouring"..polys..".obj", mesh = "pipeworks_spigot_pouring"..polys..".obj",
tiles = { tiles = {
{ minetest.registered_nodes[pipeworks.liquids.water.source].tiles[1],
name = "default_water_flowing_animated.png",
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 0.8,
},
},
{ name = "pipeworks_spigot.png" } { name = "pipeworks_spigot.png" }
}, },
use_texture_alpha = texture_alpha_mode and "blend" or true,
sunlight_propagates = true, sunlight_propagates = true,
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
groups = {snappy=3, pipe=1, not_in_creative_inventory=1}, groups = {snappy=3, pipe=1, not_in_creative_inventory=1, dig_generic = 4, axey=1, handy=1, pickaxey=1},
sounds = default.node_sound_metal_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_metal_defaults",
},
walkable = true, walkable = true,
pipe_connections = { left=1, right=1, front=1, back=1, pipe_connections = { left=1, right=1, front=1, back=1,
left_param2 = 3, right_param2 = 1, front_param2 = 2, back_param2 = 0 }, left_param2 = 3, right_param2 = 1, front_param2 = 2, back_param2 = 0 },
@ -378,6 +404,8 @@ minetest.register_node(nodename_spigot_loaded, {
drop = "pipeworks:spigot", drop = "pipeworks:spigot",
on_rotate = pipeworks.fix_after_rotation on_rotate = pipeworks.fix_after_rotation
}) })
pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:spigot"
-- new flow logic does not currently distinguish between these two visual states. -- new flow logic does not currently distinguish between these two visual states.
-- register both so existing flowing spigots continue to work (even if the visual doesn't match the spigot's behaviour). -- register both so existing flowing spigots continue to work (even if the visual doesn't match the spigot's behaviour).
new_flow_logic_register.directional_horizonal_rotate(nodename_spigot_empty, false) new_flow_logic_register.directional_horizonal_rotate(nodename_spigot_empty, false)
@ -409,8 +437,12 @@ minetest.register_node(nodename_panel_empty, {
tiles = { "pipeworks_entry_panel.png" }, tiles = { "pipeworks_entry_panel.png" },
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
groups = {snappy=3, pipe=1}, groups = {snappy=3, pipe=1, dig_generic = 4, axey=1, handy=1, pickaxey=1},
sounds = default.node_sound_metal_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_metal_defaults",
},
walkable = true, walkable = true,
on_place = pipeworks.rotate_on_place, on_place = pipeworks.rotate_on_place,
after_dig_node = function(pos) after_dig_node = function(pos)
@ -429,8 +461,12 @@ minetest.register_node(nodename_panel_loaded, {
tiles = { "pipeworks_entry_panel.png" }, tiles = { "pipeworks_entry_panel.png" },
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
groups = {snappy=3, pipe=1, not_in_creative_inventory=1}, groups = {snappy=3, pipe=1, not_in_creative_inventory=1, dig_generic = 4, axey=1, handy=1, pickaxey=1},
sounds = default.node_sound_metal_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_metal_defaults",
},
walkable = true, walkable = true,
on_place = pipeworks.rotate_on_place, on_place = pipeworks.rotate_on_place,
after_dig_node = function(pos) after_dig_node = function(pos)
@ -441,6 +477,9 @@ minetest.register_node(nodename_panel_loaded, {
drop = "pipeworks:entry_panel_empty", drop = "pipeworks:entry_panel_empty",
on_rotate = pipeworks.fix_after_rotation on_rotate = pipeworks.fix_after_rotation
}) })
pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:entry_panel_empty"
-- TODO: AFAIK the two panels have no visual difference, so are redundant under new flow logic - alias? -- TODO: AFAIK the two panels have no visual difference, so are redundant under new flow logic - alias?
new_flow_logic_register.directional_horizonal_rotate(nodename_panel_empty, true) new_flow_logic_register.directional_horizonal_rotate(nodename_panel_empty, true)
new_flow_logic_register.directional_horizonal_rotate(nodename_panel_loaded, true) new_flow_logic_register.directional_horizonal_rotate(nodename_panel_loaded, true)
@ -456,8 +495,12 @@ minetest.register_node(nodename_sensor_empty, {
sunlight_propagates = true, sunlight_propagates = true,
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
groups = {snappy=3, pipe=1}, groups = {snappy=3, pipe=1, dig_generic = 4, axey=1, handy=1, pickaxey=1},
sounds = default.node_sound_metal_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_metal_defaults",
},
walkable = true, walkable = true,
on_place = pipeworks.rotate_on_place, on_place = pipeworks.rotate_on_place,
after_dig_node = function(pos) after_dig_node = function(pos)
@ -465,7 +508,7 @@ minetest.register_node(nodename_sensor_empty, {
end, end,
on_construct = function(pos) on_construct = function(pos)
if mesecon then if mesecon then
mesecon.receptor_off(pos, rules) mesecon.receptor_off(pos, pipeworks.mesecons_rules)
end end
end, end,
selection_box = { selection_box = {
@ -495,8 +538,12 @@ minetest.register_node(nodename_sensor_loaded, {
sunlight_propagates = true, sunlight_propagates = true,
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
groups = {snappy=3, pipe=1, not_in_creative_inventory=1}, groups = {snappy=3, pipe=1, not_in_creative_inventory=1, dig_generic = 4, axey=1, handy=1, pickaxey=1},
sounds = default.node_sound_metal_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_metal_defaults",
},
walkable = true, walkable = true,
on_place = pipeworks.rotate_on_place, on_place = pipeworks.rotate_on_place,
after_dig_node = function(pos) after_dig_node = function(pos)
@ -504,7 +551,7 @@ minetest.register_node(nodename_sensor_loaded, {
end, end,
on_construct = function(pos) on_construct = function(pos)
if mesecon then if mesecon then
mesecon.receptor_on(pos, rules) mesecon.receptor_on(pos, pipeworks.mesecons_rules)
end end
end, end,
selection_box = { selection_box = {
@ -525,6 +572,8 @@ minetest.register_node(nodename_sensor_loaded, {
mesecons = pipereceptor_on, mesecons = pipereceptor_on,
on_rotate = pipeworks.fix_after_rotation on_rotate = pipeworks.fix_after_rotation
}) })
pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:flow_sensor_empty"
new_flow_logic_register.directional_horizonal_rotate(nodename_sensor_empty, true) new_flow_logic_register.directional_horizonal_rotate(nodename_sensor_empty, true)
new_flow_logic_register.directional_horizonal_rotate(nodename_sensor_loaded, true) new_flow_logic_register.directional_horizonal_rotate(nodename_sensor_loaded, true)
-- activate flow sensor at roughly half the pressure pumps drive pipes -- activate flow sensor at roughly half the pressure pumps drive pipes
@ -538,12 +587,12 @@ new_flow_logic_register.transition_simple_set(sensor_pressure_set, { mesecons=pi
-- TODO flow-logic-stub: these don't currently do anything under the new flow logic. -- TODO flow-logic-stub: these don't currently do anything under the new flow logic.
for fill = 0, 10 do for fill = 0, 10 do
local filldesc=S("empty") local filldesc=S("empty")
local sgroups = {snappy=3, pipe=1, tankfill=fill+1} local sgroups = {snappy=3, pipe=1, tankfill=fill+1, dig_generic = 4, axey=1, handy=1, pickaxey=1}
local image = nil local image = nil
if fill ~= 0 then if fill ~= 0 then
filldesc=S("@1% full", 10*fill) filldesc=S("@1% full", 10*fill)
sgroups = {snappy=3, pipe=1, tankfill=fill+1, not_in_creative_inventory=1} sgroups = {snappy=3, pipe=1, tankfill=fill+1, not_in_creative_inventory=1, dig_generic = 4, axey=1, handy=1, pickaxey=1}
image = "pipeworks_storage_tank_fittings.png" image = "pipeworks_storage_tank_fittings.png"
end end
@ -560,8 +609,12 @@ for fill = 0, 10 do
inventory_image = image, inventory_image = image,
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
groups = {snappy=3, pipe=1, tankfill=fill+1, not_in_creative_inventory=1}, groups = {snappy=3, pipe=1, tankfill=fill+1, not_in_creative_inventory=1, dig_generic = 4, axey=1, handy=1, pickaxey=1},
sounds = default.node_sound_metal_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_metal_defaults",
},
walkable = true, walkable = true,
drop = "pipeworks:storage_tank_0", drop = "pipeworks:storage_tank_0",
pipe_connections = { top = 1, bottom = 1}, pipe_connections = { top = 1, bottom = 1},
@ -589,7 +642,11 @@ for fill = 0, 10 do
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
groups = sgroups, groups = sgroups,
sounds = default.node_sound_metal_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_metal_defaults",
},
walkable = true, walkable = true,
drop = "pipeworks:storage_tank_0", drop = "pipeworks:storage_tank_0",
pipe_connections = { top = 1, bottom = 1}, pipe_connections = { top = 1, bottom = 1},
@ -603,6 +660,7 @@ for fill = 0, 10 do
on_rotate = false on_rotate = false
}) })
end end
pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:storage_tank_0"
-- fountainhead -- fountainhead
@ -614,8 +672,12 @@ minetest.register_node(nodename_fountain_empty, {
tiles = { "pipeworks_fountainhead.png" }, tiles = { "pipeworks_fountainhead.png" },
sunlight_propagates = true, sunlight_propagates = true,
paramtype = "light", paramtype = "light",
groups = {snappy=3, pipe=1}, groups = {snappy=3, pipe=1, dig_generic = 4, axey=1, handy=1, pickaxey=1},
sounds = default.node_sound_metal_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_metal_defaults",
},
walkable = true, walkable = true,
pipe_connections = { bottom = 1 }, pipe_connections = { bottom = 1 },
after_place_node = function(pos) after_place_node = function(pos)
@ -626,7 +688,7 @@ minetest.register_node(nodename_fountain_empty, {
end, end,
on_construct = function(pos) on_construct = function(pos)
if mesecon then if mesecon then
mesecon.receptor_on(pos, rules) mesecon.receptor_on(pos, pipeworks.mesecons_rules)
end end
end, end,
selection_box = { selection_box = {
@ -639,6 +701,7 @@ minetest.register_node(nodename_fountain_empty, {
}, },
on_rotate = false on_rotate = false
}) })
pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:fountainhead"
local nodename_fountain_loaded = "pipeworks:fountainhead_pouring" local nodename_fountain_loaded = "pipeworks:fountainhead_pouring"
minetest.register_node(nodename_fountain_loaded, { minetest.register_node(nodename_fountain_loaded, {
@ -648,8 +711,12 @@ minetest.register_node(nodename_fountain_loaded, {
tiles = { "pipeworks_fountainhead.png" }, tiles = { "pipeworks_fountainhead.png" },
sunlight_propagates = true, sunlight_propagates = true,
paramtype = "light", paramtype = "light",
groups = {snappy=3, pipe=1, not_in_creative_inventory=1}, groups = {snappy=3, pipe=1, not_in_creative_inventory=1, dig_generic = 4, axey=1, handy=1, pickaxey=1},
sounds = default.node_sound_metal_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_metal_defaults",
},
walkable = true, walkable = true,
pipe_connections = { bottom = 1 }, pipe_connections = { bottom = 1 },
after_place_node = function(pos) after_place_node = function(pos)
@ -661,7 +728,7 @@ minetest.register_node(nodename_fountain_loaded, {
end, end,
on_construct = function(pos) on_construct = function(pos)
if mesecon then if mesecon then
mesecon.receptor_on(pos, rules) mesecon.receptor_on(pos, pipeworks.mesecons_rules)
end end
end, end,
selection_box = { selection_box = {
@ -698,8 +765,12 @@ minetest.register_node(nodename_sp_empty, {
tiles = { "pipeworks_straight_pipe_empty.png" }, tiles = { "pipeworks_straight_pipe_empty.png" },
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
groups = {snappy=3, pipe=1}, groups = {snappy=3, pipe=1, dig_generic = 4, axey=1, handy=1, pickaxey=1},
sounds = default.node_sound_metal_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_metal_defaults",
},
walkable = true, walkable = true,
on_place = pipeworks.rotate_on_place, on_place = pipeworks.rotate_on_place,
after_dig_node = function(pos) after_dig_node = function(pos)
@ -720,8 +791,12 @@ minetest.register_node(nodename_sp_loaded, {
tiles = { "pipeworks_straight_pipe_loaded.png" }, tiles = { "pipeworks_straight_pipe_loaded.png" },
paramtype = "light", paramtype = "light",
paramtype2 = "facedir", paramtype2 = "facedir",
groups = {snappy=3, pipe=1, not_in_creative_inventory=1}, groups = {snappy=3, pipe=1, not_in_creative_inventory=1, dig_generic = 4, axey=1, handy=1, pickaxey=1},
sounds = default.node_sound_metal_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_metal_defaults",
},
walkable = true, walkable = true,
on_place = pipeworks.rotate_on_place, on_place = pipeworks.rotate_on_place,
after_dig_node = function(pos) after_dig_node = function(pos)
@ -734,6 +809,7 @@ minetest.register_node(nodename_sp_loaded, {
check_for_pole = pipeworks.check_for_vert_pipe, check_for_pole = pipeworks.check_for_vert_pipe,
check_for_horiz_pole = pipeworks.check_for_horiz_pipe check_for_horiz_pole = pipeworks.check_for_horiz_pipe
}) })
pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:straight_pipe_empty"
new_flow_logic_register.directional_horizonal_rotate(nodename_sp_empty, true) new_flow_logic_register.directional_horizonal_rotate(nodename_sp_empty, true)
new_flow_logic_register.directional_horizonal_rotate(nodename_sp_loaded, true) new_flow_logic_register.directional_horizonal_rotate(nodename_sp_loaded, true)

View File

@ -1,10 +1,6 @@
local S = minetest.get_translator("pipeworks") local S = minetest.get_translator("pipeworks")
local fs_helpers = pipeworks.fs_helpers local fs_helpers = pipeworks.fs_helpers
local function delay(x)
return (function() return x end)
end
local function set_filter_infotext(data, meta) local function set_filter_infotext(data, meta)
local infotext = S("@1 Filter-Injector", data.wise_desc) local infotext = S("@1 Filter-Injector", data.wise_desc)
if meta:get_int("slotseq_mode") == 2 then if meta:get_int("slotseq_mode") == 2 then
@ -18,38 +14,68 @@ local function set_filter_formspec(data, meta)
local formspec local formspec
if data.digiline then if data.digiline then
formspec = "size[8,2.7]".. local form_height = 3
"item_image[0,0;1,1;pipeworks:"..data.name.."]".. if pipeworks.enable_item_tags then
"label[1,0;"..minetest.formspec_escape(itemname).."]".. form_height = 4
"field[0.3,1.5;8.0,1;channel;"..S("Channel")..";${channel}]".. end
fs_helpers.cycling_button(meta, "button[0,2;4,1", "slotseq_mode", formspec =
("size[8.5,%f]"):format(form_height) ..
"item_image[0.2,0;1,1;pipeworks:"..data.name.."]"..
"label[1.2,0.2;"..minetest.formspec_escape(itemname).."]"..
"field[0.5,1.6;4.6,1;channel;"..S("Channel")..";${channel}]"..
"button[4.8,1.3;1.5,1;set_channel;"..S("Set").."]"..
fs_helpers.cycling_button(meta, ("button[0.2,%f;4.05,1"):format(form_height - 0.7), "slotseq_mode",
{S("Sequence slots by Priority"), {S("Sequence slots by Priority"),
S("Sequence slots Randomly"), S("Sequence slots Randomly"),
S("Sequence slots by Rotation")}).. S("Sequence slots by Rotation")})..
fs_helpers.cycling_button(meta, "button[4,2;4,1", "exmatch_mode", fs_helpers.cycling_button(meta, ("button[4.25,%f;4.05,1"):format(form_height - 0.7), "exmatch_mode",
{S("Exact match - off"), {S("Exact match - off"),
S("Exact match - on")}) S("Exact match - on")})..
("button_exit[6.3,%f;2,1;close;" .. S("Close") .. "]"):format(form_height - 1.7)
if pipeworks.enable_item_tags then
formspec = formspec ..
("field[0.5,%f;4.6,1;item_tags;"):format(form_height - 1.4) .. S("Item Tags") .. ";${item_tags}]" ..
("button[4.8,%f;1.5,1;set_item_tags;"):format(form_height - 1.7) .. S("Set") .. "]"
end
else else
local exmatch_button = "" local exmatch_button = ""
if data.stackwise then if data.stackwise then
exmatch_button = exmatch_button =
fs_helpers.cycling_button(meta, "button[4,3.5;4,1", "exmatch_mode", fs_helpers.cycling_button(meta, "button["..(10.2-(0.22)-4)..",4.5;4,1", "exmatch_mode",
{S("Exact match - off"), {S("Exact match - off"),
S("Exact match - on")}) S("Exact match - on")})
end end
local size = "10.2,11"
formspec = "size[8,8.5]".. local list_backgrounds = ""
"item_image[0,0;1,1;pipeworks:"..data.name.."]".. if minetest.get_modpath("i3") or minetest.get_modpath("mcl_formspec") then
"label[1,0;"..minetest.formspec_escape(itemname).."]".. list_backgrounds = "style_type[box;colors=#666]"
"label[0,1;"..S("Prefer item types:").."]".. for i=0, 7 do
"list[context;main;0,1.5;8,2;]".. for j=0, 1 do
fs_helpers.cycling_button(meta, "button[0,3.5;4,1", "slotseq_mode", list_backgrounds = list_backgrounds .. "box[".. 0.22+(i*1.25) ..",".. 1.75+(j*1.25) ..";1,1;]"
end
end
end
formspec =
"formspec_version[2]"..
"size["..size.."]"..
pipeworks.fs_helpers.get_prepends(size)..
"item_image[0.22,0.22;1,1;pipeworks:"..data.name.."]"..
"label[1.22,0.72;"..minetest.formspec_escape(itemname).."]"..
"label[0.22,1.5;"..S("Prefer item types:").."]"..
list_backgrounds..
"list[context;main;0.22,1.75;8,2;]"..
fs_helpers.cycling_button(meta, "button[0.22,4.5;4,1", "slotseq_mode",
{S("Sequence slots by Priority"), {S("Sequence slots by Priority"),
S("Sequence slots Randomly"), S("Sequence slots Randomly"),
S("Sequence slots by Rotation")}).. S("Sequence slots by Rotation")})..
exmatch_button.. exmatch_button..
"list[current_player;main;0,4.5;8,4;]" .. pipeworks.fs_helpers.get_inv(6)..
"listring[]" "listring[]"
if pipeworks.enable_item_tags then
formspec = formspec ..
"field[5.8,0.5;3,0.8;item_tags;" .. S("Item Tags") .. ";${item_tags}]" ..
"button[9,0.3;1,1.1;set_item_tags;" .. S("Set") .. "]"
end
end end
meta:set_string("formspec", formspec) meta:set_string("formspec", formspec)
end end
@ -66,8 +92,8 @@ local function punch_filter(data, filtpos, filtnode, msg)
local fromnode = minetest.get_node(frompos) local fromnode = minetest.get_node(frompos)
if not fromnode then return end if not fromnode then return end
local fromdef = minetest.registered_nodes[fromnode.name] local fromdef = minetest.registered_nodes[fromnode.name]
if not fromdef then return end if not fromdef or not fromdef.tube then return end
local fromtube = fromdef.tube local fromtube = table.copy(fromdef.tube)
local input_special_cases = { local input_special_cases = {
["technic:mv_electric_furnace"] = "dst", ["technic:mv_electric_furnace"] = "dst",
["technic:mv_electric_furnace_active"] = "dst", ["technic:mv_electric_furnace_active"] = "dst",
@ -111,6 +137,7 @@ local function punch_filter(data, filtpos, filtnode, msg)
local slotseq_mode local slotseq_mode
local exmatch_mode local exmatch_mode
local item_tags = pipeworks.sanitize_tags(filtmeta:get_string("item_tags"))
local filters = {} local filters = {}
if data.digiline then if data.digiline then
local function add_filter(name, group, count, wear, metadata) local function add_filter(name, group, count, wear, metadata)
@ -174,6 +201,12 @@ local function punch_filter(data, filtpos, filtnode, msg)
set_filter_formspec(data, filtmeta) set_filter_formspec(data, filtmeta)
end end
if type(msg.tags) == "table" or type(msg.tags) == "string" then
item_tags = pipeworks.sanitize_tags(msg.tags)
elseif type(msg.tag) == "string" then
item_tags = pipeworks.sanitize_tags({msg.tag})
end
if msg.nofire then if msg.nofire then
return return
end end
@ -326,7 +359,8 @@ local function punch_filter(data, filtpos, filtnode, msg)
end end
local pos = vector.add(frompos, vector.multiply(dir, 1.4)) local pos = vector.add(frompos, vector.multiply(dir, 1.4))
local start_pos = vector.add(frompos, dir) local start_pos = vector.add(frompos, dir)
local item1 = pipeworks.tube_inject_item(pos, start_pos, dir, item, fakePlayer:get_player_name()) pipeworks.tube_inject_item(pos, start_pos, dir, item,
fakePlayer:get_player_name(), item_tags)
return true -- only fire one item, please return true -- only fire one item, please
end end
end end
@ -375,9 +409,13 @@ for _, data in ipairs({
"pipeworks_"..data.name.."_top.png", "pipeworks_"..data.name.."_top.png",
}, },
paramtype2 = "facedir", paramtype2 = "facedir",
groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 2, mesecon = 2}, groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 2, mesecon = 2, axey=1, handy=1, pickaxey=1},
is_ground_content = false,
_mcl_hardness=0.8,
legacy_facedir_simple = true, legacy_facedir_simple = true,
sounds = default.node_sound_wood_defaults(), _sound_def = {
key = "node_sound_wood_defaults",
},
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
set_filter_formspec(data, meta) set_filter_formspec(data, meta)
@ -428,14 +466,22 @@ for _, data in ipairs({
end end
node.on_receive_fields = function(pos, formname, fields, sender) node.on_receive_fields = function(pos, formname, fields, sender)
if not pipeworks.may_configure(pos, sender) then return end if (fields.quit and not fields.key_enter_field)
or not pipeworks.may_configure(pos, sender) then
return
end
fs_helpers.on_receive_fields(pos, fields) fs_helpers.on_receive_fields(pos, fields)
if fields.channel then if fields.channel and (fields.key_enter_field == "channel" or fields.set_channel) then
minetest.get_meta(pos):set_string("channel", fields.channel) minetest.get_meta(pos):set_string("channel", fields.channel)
end end
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
if pipeworks.enable_item_tags and fields.item_tags and (fields.key_enter_field == "item_tags" or fields.set_item_tags) then
local tags = pipeworks.sanitize_tags(fields.item_tags)
meta:set_string("item_tags", table.concat(tags, ","))
end
--meta:set_int("slotseq_index", 1) --meta:set_int("slotseq_index", 1)
set_filter_formspec(data, meta) set_filter_formspec(data, meta)
set_filter_infotext(data, meta) set_filter_infotext(data, meta)
@ -457,6 +503,10 @@ for _, data in ipairs({
fs_helpers.on_receive_fields(pos, fields) fs_helpers.on_receive_fields(pos, fields)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
meta:set_int("slotseq_index", 1) meta:set_int("slotseq_index", 1)
if pipeworks.enable_item_tags and fields.item_tags and (fields.key_enter_field == "item_tags" or fields.set_item_tags) then
local tags = pipeworks.sanitize_tags(fields.item_tags)
meta:set_string("item_tags", table.concat(tags, ","))
end
set_filter_formspec(data, meta) set_filter_formspec(data, meta)
set_filter_infotext(data, meta) set_filter_infotext(data, meta)
end end
@ -475,35 +525,7 @@ for _, data in ipairs({
minetest.register_node("pipeworks:"..data.name, node) minetest.register_node("pipeworks:"..data.name, node)
end pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:"..data.name
minetest.register_craft( {
output = "pipeworks:filter 2",
recipe = {
{ "default:steel_ingot", "default:steel_ingot", "basic_materials:plastic_sheet" },
{ "group:stick", "default:mese_crystal", "basic_materials:plastic_sheet" },
{ "default:steel_ingot", "default:steel_ingot", "basic_materials:plastic_sheet" }
},
})
minetest.register_craft( {
output = "pipeworks:mese_filter 2",
recipe = {
{ "default:steel_ingot", "default:steel_ingot", "basic_materials:plastic_sheet" },
{ "group:stick", "default:mese", "basic_materials:plastic_sheet" },
{ "default:steel_ingot", "default:steel_ingot", "basic_materials:plastic_sheet" }
},
})
if minetest.get_modpath("digilines") then
minetest.register_craft( {
output = "pipeworks:digiline_filter 2",
recipe = {
{ "default:steel_ingot", "default:steel_ingot", "basic_materials:plastic_sheet" },
{ "group:stick", "digilines:wire_std_00000000", "basic_materials:plastic_sheet" },
{ "default:steel_ingot", "default:steel_ingot", "basic_materials:plastic_sheet" }
},
})
end end
--[[ --[[

View File

@ -60,8 +60,8 @@ pipeworks.check_for_inflows = function(pos,node)
end end
end end
end end
if newnode then if newnode then
minetest.add_node(pos,{name=newnode, param2 = node.param2}) minetest.add_node(pos,{name=newnode, param2 = node.param2})
minetest.get_meta(pos):set_string("source",minetest.pos_to_string(source)) minetest.get_meta(pos):set_string("source",minetest.pos_to_string(source))
end end
end end
@ -75,15 +75,15 @@ pipeworks.check_sources = function(pos,node)
newnode = string.gsub(node.name,"loaded","empty") newnode = string.gsub(node.name,"loaded","empty")
end end
if newnode then if newnode then
minetest.add_node(pos,{name=newnode, param2 = node.param2}) minetest.add_node(pos,{name=newnode, param2 = node.param2})
minetest.get_meta(pos):set_string("source","") minetest.get_meta(pos):set_string("source","")
end end
end end
pipeworks.spigot_check = function(pos, node) pipeworks.spigot_check = function(pos, node)
local belowname = minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z}).name local belowname = minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z}).name
if belowname and (belowname == "air" or belowname == "default:water_flowing" or belowname == "default:water_source") then if belowname and (belowname == "air" or belowname == pipeworks.liquids.water.flowing or belowname == pipeworks.liquids.water.source) then
local spigotname = minetest.get_node(pos).name local spigotname = minetest.get_node(pos).name
local fdir=node.param2 % 4 local fdir=node.param2 % 4
local check = { local check = {
@ -96,14 +96,14 @@ pipeworks.spigot_check = function(pos, node)
if near_node and string.find(near_node.name, "_loaded") then if near_node and string.find(near_node.name, "_loaded") then
if spigotname and spigotname == "pipeworks:spigot" then if spigotname and spigotname == "pipeworks:spigot" then
minetest.add_node(pos,{name = "pipeworks:spigot_pouring", param2 = fdir}) minetest.add_node(pos,{name = "pipeworks:spigot_pouring", param2 = fdir})
if finitewater or belowname ~= "default:water_source" then if finitewater or belowname ~= pipeworks.liquids.water.source then
minetest.add_node({x=pos.x,y=pos.y-1,z=pos.z},{name = "default:water_source"}) minetest.add_node({x=pos.x,y=pos.y-1,z=pos.z},{name = pipeworks.liquids.water.source})
end end
end end
else else
if spigotname == "pipeworks:spigot_pouring" then if spigotname == "pipeworks:spigot_pouring" then
minetest.add_node({x=pos.x,y=pos.y,z=pos.z},{name = "pipeworks:spigot", param2 = fdir}) minetest.add_node({x=pos.x,y=pos.y,z=pos.z},{name = "pipeworks:spigot", param2 = fdir})
if belowname == "default:water_source" and not finitewater then if belowname == pipeworks.liquids.water.source and not finitewater then
minetest.remove_node({x=pos.x,y=pos.y-1,z=pos.z}) minetest.remove_node({x=pos.x,y=pos.y-1,z=pos.z})
end end
end end
@ -113,20 +113,20 @@ end
pipeworks.fountainhead_check = function(pos, node) pipeworks.fountainhead_check = function(pos, node)
local abovename = minetest.get_node({x=pos.x,y=pos.y+1,z=pos.z}).name local abovename = minetest.get_node({x=pos.x,y=pos.y+1,z=pos.z}).name
if abovename and (abovename == "air" or abovename == "default:water_flowing" or abovename == "default:water_source") then if abovename and (abovename == "air" or abovename == pipeworks.liquids.water.flowing or abovename == pipeworks.liquids.water.source) then
local fountainhead_name = minetest.get_node(pos).name local fountainhead_name = minetest.get_node(pos).name
local near_node = minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z}) local near_node = minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z})
if near_node and string.find(near_node.name, "_loaded") then if near_node and string.find(near_node.name, "_loaded") then
if fountainhead_name and fountainhead_name == "pipeworks:fountainhead" then if fountainhead_name and fountainhead_name == "pipeworks:fountainhead" then
minetest.add_node(pos,{name = "pipeworks:fountainhead_pouring"}) minetest.add_node(pos,{name = "pipeworks:fountainhead_pouring"})
if finitewater or abovename ~= "default:water_source" then if finitewater or abovename ~= pipeworks.liquids.water.source then
minetest.add_node({x=pos.x,y=pos.y+1,z=pos.z},{name = "default:water_source"}) minetest.add_node({x=pos.x,y=pos.y+1,z=pos.z},{name = pipeworks.liquids.water.source})
end end
end end
else else
if fountainhead_name == "pipeworks:fountainhead_pouring" then if fountainhead_name == "pipeworks:fountainhead_pouring" then
minetest.add_node({x=pos.x,y=pos.y,z=pos.z},{name = "pipeworks:fountainhead"}) minetest.add_node({x=pos.x,y=pos.y,z=pos.z},{name = "pipeworks:fountainhead"})
if abovename == "default:water_source" and not finitewater then if abovename == pipeworks.liquids.water.source and not finitewater then
minetest.remove_node({x=pos.x,y=pos.y+1,z=pos.z}) minetest.remove_node({x=pos.x,y=pos.y+1,z=pos.z})
end end
end end

153
init.lua
View File

@ -4,13 +4,21 @@
-- and devices that they can connect to. -- and devices that they can connect to.
-- --
pipeworks = {} pipeworks = {
ui_cat_tube_list = {},
local DEBUG = false worldpath = minetest.get_worldpath(),
modpath = minetest.get_modpath("pipeworks"),
pipeworks.worldpath = minetest.get_worldpath() liquids = {
pipeworks.modpath = minetest.get_modpath("pipeworks") water = {
local S = minetest.get_translator("pipeworks") source = minetest.registered_nodes["mapgen_water_source"].name,
flowing = minetest.registered_nodes["mapgen_water_source"].liquid_alternative_flowing
},
river_water = {
source = minetest.registered_nodes["mapgen_river_water_source"].name,
flowing = minetest.registered_nodes["mapgen_river_water_source"].liquid_alternative_flowing
}
}
}
dofile(pipeworks.modpath.."/default_settings.lua") dofile(pipeworks.modpath.."/default_settings.lua")
-- Read the external config file if it exists. -- Read the external config file if it exists.
@ -23,76 +31,12 @@ end
if pipeworks.toggles.pipe_mode == "pressure" then if pipeworks.toggles.pipe_mode == "pressure" then
minetest.log("warning", "pipeworks pressure logic mode comes with caveats and differences in behaviour, you have been warned!") minetest.log("warning", "pipeworks pressure logic mode comes with caveats and differences in behaviour, you have been warned!")
end end
if pipeworks.entity_update_interval >= 0.2 and pipeworks.enable_accelerator_tube then
-- Random variables minetest.log("warning", "pipeworks accelerator tubes will not entirely work with an entity update interval 0.2 or above.")
pipeworks.expect_infinite_stacks = true
if minetest.get_modpath("unified_inventory") or not minetest.settings:get_bool("creative_mode") then
pipeworks.expect_infinite_stacks = false
end
pipeworks.meseadjlist={{x=0,y=0,z=1},{x=0,y=0,z=-1},{x=0,y=1,z=0},{x=0,y=-1,z=0},{x=1,y=0,z=0},{x=-1,y=0,z=0}}
pipeworks.rules_all = {{x=0, y=0, z=1},{x=0, y=0, z=-1},{x=1, y=0, z=0},{x=-1, y=0, z=0},
{x=0, y=1, z=1},{x=0, y=1, z=-1},{x=1, y=1, z=0},{x=-1, y=1, z=0},
{x=0, y=-1, z=1},{x=0, y=-1, z=-1},{x=1, y=-1, z=0},{x=-1, y=-1, z=0},
{x=0, y=1, z=0}, {x=0, y=-1, z=0}}
pipeworks.mesecons_rules={{x=0,y=0,z=1},{x=0,y=0,z=-1},{x=1,y=0,z=0},{x=-1,y=0,z=0},{x=0,y=1,z=0},{x=0,y=-1,z=0}}
pipeworks.digilines_rules={{x=0,y=0,z=1},{x=0,y=0,z=-1},{x=1,y=0,z=0},{x=-1,y=0,z=0},{x=0,y=1,z=0},{x=0,y=-1,z=0}}
pipeworks.liquid_texture = "default_water.png"
pipeworks.button_off = {text="", texture="pipeworks_button_off.png", addopts="false;false;pipeworks_button_interm.png"}
pipeworks.button_on = {text="", texture="pipeworks_button_on.png", addopts="false;false;pipeworks_button_interm.png"}
pipeworks.button_base = "image_button[0,4.3;1,0.6"
pipeworks.button_label = "label[0.9,4.31;"..S("Allow splitting incoming stacks from tubes").."]"
-- Helper functions
function pipeworks.fix_image_names(table, replacement)
local outtable={}
for i in ipairs(table) do
outtable[i]=string.gsub(table[i], "_XXXXX", replacement)
end
return outtable
end
function pipeworks.add_node_box(t, b)
if not t or not b then return end
for i in ipairs(b)
do table.insert(t, b[i])
end
end
function pipeworks.may_configure(pos, player)
local name = player:get_player_name()
local meta = minetest.get_meta(pos)
local owner = meta:get_string("owner")
if owner ~= "" and owner == name then -- wielders and filters
return true
end
return not minetest.is_protected(pos, name)
end
function pipeworks.replace_name(tbl,tr,name)
local ntbl={}
for key,i in pairs(tbl) do
if type(i)=="string" then
ntbl[key]=string.gsub(i,tr,name)
elseif type(i)=="table" then
ntbl[key]=pipeworks.replace_name(i,tr,name)
else
ntbl[key]=i
end
end
return ntbl
end end
pipeworks.logger = function(msg) pipeworks.logger = function(msg)
print("[pipeworks] "..msg) minetest.log("action", "[pipeworks] "..msg)
end end
------------------------------------------- -------------------------------------------
@ -114,16 +58,26 @@ dofile(pipeworks.modpath.."/autoplace_tubes.lua")
dofile(pipeworks.modpath.."/luaentity.lua") dofile(pipeworks.modpath.."/luaentity.lua")
dofile(pipeworks.modpath.."/item_transport.lua") dofile(pipeworks.modpath.."/item_transport.lua")
dofile(pipeworks.modpath.."/flowing_logic.lua") dofile(pipeworks.modpath.."/flowing_logic.lua")
dofile(pipeworks.modpath.."/crafts.lua")
dofile(pipeworks.modpath.."/tube_registration.lua")
dofile(pipeworks.modpath.."/routing_tubes.lua")
dofile(pipeworks.modpath.."/sorting_tubes.lua")
dofile(pipeworks.modpath.."/vacuum_tubes.lua")
dofile(pipeworks.modpath.."/signal_tubes.lua")
dofile(pipeworks.modpath.."/decorative_tubes.lua")
dofile(pipeworks.modpath.."/filter-injector.lua") dofile(pipeworks.modpath.."/filter-injector.lua")
dofile(pipeworks.modpath.."/trashcan.lua") dofile(pipeworks.modpath.."/trashcan.lua")
dofile(pipeworks.modpath.."/wielder.lua") dofile(pipeworks.modpath.."/wielder.lua")
dofile(pipeworks.modpath.."/tubes/registration.lua")
dofile(pipeworks.modpath.."/tubes/routing.lua")
dofile(pipeworks.modpath.."/tubes/sorting.lua")
dofile(pipeworks.modpath.."/tubes/signal.lua")
dofile(pipeworks.modpath.."/tubes/embedded_tube.lua")
dofile(pipeworks.modpath.."/tubes/pane_embedded_tube.lua")
dofile(pipeworks.modpath.."/tubes/tags.lua")
if pipeworks.enable_teleport_tube then
dofile(pipeworks.modpath.."/tubes/teleport.lua")
end
if pipeworks.enable_lua_tube and minetest.get_modpath("mesecons") then
dofile(pipeworks.modpath.."/tubes/lua.lua")
end
if pipeworks.enable_sand_tube or pipeworks.enable_mese_sand_tube then
dofile(pipeworks.modpath.."/tubes/vacuum.lua")
end
local logicdir = "/pressure_logic/" local logicdir = "/pressure_logic/"
@ -135,19 +89,40 @@ dofile(pipeworks.modpath..logicdir.."abms.lua")
dofile(pipeworks.modpath..logicdir.."abm_register.lua") dofile(pipeworks.modpath..logicdir.."abm_register.lua")
dofile(pipeworks.modpath..logicdir.."flowable_node_registry_install.lua") dofile(pipeworks.modpath..logicdir.."flowable_node_registry_install.lua")
if pipeworks.enable_pipes then dofile(pipeworks.modpath.."/pipes.lua") end if pipeworks.enable_pipes then
if pipeworks.enable_teleport_tube then dofile(pipeworks.modpath.."/teleport_tube.lua") end dofile(pipeworks.modpath.."/pipes.lua")
if pipeworks.enable_pipe_devices then dofile(pipeworks.modpath.."/devices.lua") end end
if pipeworks.enable_redefines then if pipeworks.enable_pipe_devices then
dofile(pipeworks.modpath.."/devices.lua")
end
if pipeworks.enable_redefines and (minetest.get_modpath("default") or minetest.get_modpath("hades_core")) then
dofile(pipeworks.modpath.."/compat-chests.lua") dofile(pipeworks.modpath.."/compat-chests.lua")
dofile(pipeworks.modpath.."/compat-furnaces.lua") dofile(pipeworks.modpath.."/compat-furnaces.lua")
end end
if pipeworks.enable_autocrafter then dofile(pipeworks.modpath.."/autocrafter.lua") end if pipeworks.enable_redefines and minetest.get_modpath("mcl_barrels") then
if pipeworks.enable_lua_tube and dofile(pipeworks.modpath.."/mcl_barrels.lua")
(minetest.get_modpath("mesecons") or minetest.get_modpath("digilines")) then
dofile(pipeworks.modpath.."/lua_tube.lua")
end end
if pipeworks.enable_redefines and minetest.get_modpath("mcl_furnaces") then
dofile(pipeworks.modpath.."/mcl_furnaces.lua")
end
if pipeworks.enable_autocrafter then
dofile(pipeworks.modpath.."/autocrafter.lua")
end
dofile(pipeworks.modpath.."/crafts.lua")
minetest.register_alias("pipeworks:pipe", "pipeworks:pipe_110000_empty") minetest.register_alias("pipeworks:pipe", "pipeworks:pipe_110000_empty")
-- Unified Inventory categories integration
if minetest.get_modpath("unified_inventory") and unified_inventory.registered_categories then
if not unified_inventory.registered_categories["automation"] then
unified_inventory.register_category("automation", {
symbol = "pipeworks:lua_tube000000",
label = "Automation components"
})
end
unified_inventory.add_category_items("automation", pipeworks.ui_cat_tube_list)
end
minetest.log("info", "Pipeworks loaded!") minetest.log("info", "Pipeworks loaded!")

View File

@ -1,13 +1,38 @@
local luaentity = pipeworks.luaentity local luaentity = pipeworks.luaentity
local enable_max_limit = minetest.settings:get("pipeworks_enable_items_per_tube_limit") local enable_max_limit = minetest.settings:get_bool("pipeworks_enable_items_per_tube_limit")
local max_tube_limit = tonumber(minetest.settings:get("pipeworks_max_items_per_tube")) or 30 local max_tube_limit = tonumber(minetest.settings:get("pipeworks_max_items_per_tube")) or 30
if enable_max_limit == nil then enable_max_limit = true end if enable_max_limit == nil then enable_max_limit = true end
if pipeworks.enable_item_tags then
local max_tag_length = tonumber(minetest.settings:get("pipeworks_max_item_tag_length")) or 32
local max_tags = tonumber(minetest.settings:get("pipeworks_max_item_tags")) or 16
function pipeworks.sanitize_tags(tags)
if type(tags) == "string" then
tags = tags:split(",")
end
local sanitized = {}
for i, tag in ipairs(tags) do
if type(tag) == "string" then
tag = tag:gsub("[%s,]", "") -- Remove whitespace and commas
tag = tag:gsub("%$%b%{%}", "") -- Remove special ${key} values
if tag ~= "" then
table.insert(sanitized, tag:sub(1, max_tag_length))
end
end
if #sanitized >= max_tags then
break
end
end
return sanitized
end
end
function pipeworks.tube_item(pos, item) function pipeworks.tube_item(pos, item)
error("obsolete pipeworks.tube_item() called; change caller to use pipeworks.tube_inject_item() instead") error("obsolete pipeworks.tube_item() called; change caller to use pipeworks.tube_inject_item() instead")
end end
function pipeworks.tube_inject_item(pos, start_pos, velocity, item, owner) function pipeworks.tube_inject_item(pos, start_pos, velocity, item, owner, tags)
-- Take item in any format -- Take item in any format
local stack = ItemStack(item) local stack = ItemStack(item)
local obj = luaentity.add_entity(pos, "pipeworks:tubed_item") local obj = luaentity.add_entity(pos, "pipeworks:tubed_item")
@ -15,6 +40,7 @@ function pipeworks.tube_inject_item(pos, start_pos, velocity, item, owner)
obj.start_pos = vector.new(start_pos) obj.start_pos = vector.new(start_pos)
obj:set_velocity(velocity) obj:set_velocity(velocity)
obj.owner = owner obj.owner = owner
obj.tags = tags
--obj:set_color("red") -- todo: this is test-only code --obj:set_color("red") -- todo: this is test-only code
return obj return obj
end end
@ -42,7 +68,7 @@ minetest.register_globalstep(function(dtime)
return return
end end
tube_item_count = {} tube_item_count = {}
for id, entity in pairs(luaentity.entities) do for _, entity in pairs(luaentity.entities) do
if entity.name == "pipeworks:tubed_item" then if entity.name == "pipeworks:tubed_item" then
local h = minetest.hash_node_position(vector.round(entity._pos)) local h = minetest.hash_node_position(vector.round(entity._pos))
tube_item_count[h] = (tube_item_count[h] or 0) + 1 tube_item_count[h] = (tube_item_count[h] or 0) + 1
@ -55,15 +81,22 @@ end)
-- tube overload mechanism: -- tube overload mechanism:
-- when the tube's item count (tracked in the above tube_item_count table) -- when the tube's item count (tracked in the above tube_item_count table)
-- exceeds the limit configured per tube, replace it with a broken one. -- exceeds the limit configured per tube, replace it with a broken one.
function pipeworks.break_tube(pos)
local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
meta:set_string("the_tube_was", minetest.serialize(node))
minetest.swap_node(pos, {name = "pipeworks:broken_tube_1"})
pipeworks.scan_for_tube_objects(pos)
end
local crunch_tube = function(pos, cnode, cmeta) local crunch_tube = function(pos, cnode, cmeta)
if enable_max_limit then if enable_max_limit then
local h = minetest.hash_node_position(pos) local h = minetest.hash_node_position(pos)
local itemcount = tube_item_count[h] or 0 local itemcount = tube_item_count[h] or 0
if itemcount > max_tube_limit then if itemcount > max_tube_limit then
cmeta:set_string("the_tube_was", minetest.serialize(cnode))
pipeworks.logger("Warning - a tube at "..minetest.pos_to_string(pos).." broke due to too many items ("..itemcount..")") pipeworks.logger("Warning - a tube at "..minetest.pos_to_string(pos).." broke due to too many items ("..itemcount..")")
minetest.swap_node(pos, {name = "pipeworks:broken_tube_1"}) pipeworks.break_tube(pos)
pipeworks.scan_for_tube_objects(pos)
end end
end end
end end
@ -72,13 +105,14 @@ end
-- compatibility behaviour for the existing can_go() callbacks, -- compatibility behaviour for the existing can_go() callbacks,
-- which can only specify a list of possible positions. -- which can only specify a list of possible positions.
local function go_next_compat(pos, cnode, cmeta, cycledir, vel, stack, owner) local function go_next_compat(pos, cnode, cmeta, cycledir, vel, stack, owner, tags)
local next_positions = {} local next_positions = {}
local max_priority = 0 local max_priority = 0
local can_go local can_go
if minetest.registered_nodes[cnode.name] and minetest.registered_nodes[cnode.name].tube and minetest.registered_nodes[cnode.name].tube.can_go then local def = minetest.registered_nodes[cnode.name]
can_go = minetest.registered_nodes[cnode.name].tube.can_go(pos, cnode, vel, stack) if def and def.tube and def.tube.can_go then
can_go = def.tube.can_go(pos, cnode, vel, stack, tags)
else else
local adjlist_string = minetest.get_meta(pos):get_string("adjlist") local adjlist_string = minetest.get_meta(pos):get_string("adjlist")
local adjlist = minetest.deserialize(adjlist_string) or default_adjlist -- backward compat: if not found, use old behavior: all directions local adjlist = minetest.deserialize(adjlist_string) or default_adjlist -- backward compat: if not found, use old behavior: all directions
@ -137,7 +171,7 @@ end
-- * a "multi-mode" data table (or nil if N/A) where a stack was split apart. -- * a "multi-mode" data table (or nil if N/A) where a stack was split apart.
-- if this is not nil, the luaentity spawns new tubed items for each new fragment stack, -- if this is not nil, the luaentity spawns new tubed items for each new fragment stack,
-- then deletes itself (i.e. the original item stack). -- then deletes itself (i.e. the original item stack).
local function go_next(pos, velocity, stack, owner) local function go_next(pos, velocity, stack, owner, tags)
local cnode = minetest.get_node(pos) local cnode = minetest.get_node(pos)
local cmeta = minetest.get_meta(pos) local cmeta = minetest.get_meta(pos)
local speed = math.abs(velocity.x + velocity.y + velocity.z) local speed = math.abs(velocity.x + velocity.y + velocity.z)
@ -165,7 +199,7 @@ local function go_next(pos, velocity, stack, owner)
-- n is the new value of the cycle counter. -- n is the new value of the cycle counter.
-- XXX: this probably needs cleaning up after being split out, -- XXX: this probably needs cleaning up after being split out,
-- seven args is a bit too many -- seven args is a bit too many
local n, found, new_velocity, multimode = go_next_compat(pos, cnode, cmeta, cycledir, vel, stack, owner) local n, found, new_velocity, multimode = go_next_compat(pos, cnode, cmeta, cycledir, vel, stack, owner, tags)
-- if not using output cycling, -- if not using output cycling,
-- don't update the field so it stays the same for the next item. -- don't update the field so it stays the same for the next item.
@ -194,6 +228,7 @@ minetest.register_entity("pipeworks:tubed_item", {
from_data = function(self, itemstring) from_data = function(self, itemstring)
local stack = ItemStack(itemstring) local stack = ItemStack(itemstring)
--[[
local itemtable = stack:to_table() local itemtable = stack:to_table()
local itemname = nil local itemname = nil
if itemtable then if itemtable then
@ -205,6 +240,7 @@ minetest.register_entity("pipeworks:tubed_item", {
item_texture = minetest.registered_items[itemname].inventory_image item_texture = minetest.registered_items[itemname].inventory_image
item_type = minetest.registered_items[itemname].type item_type = minetest.registered_items[itemname].type
end end
--]]
self.object:set_properties({ self.object:set_properties({
is_visible = true, is_visible = true,
textures = {stack:get_name()} textures = {stack:get_name()}
@ -267,6 +303,7 @@ luaentity.register_entity("pipeworks:tubed_item", {
color_entity = nil, color_entity = nil,
color = nil, color = nil,
start_pos = nil, start_pos = nil,
tags = nil,
set_item = function(self, item) set_item = function(self, item)
local itemstring = ItemStack(item):to_string() -- Accept any input format local itemstring = ItemStack(item):to_string() -- Accept any input format
@ -302,8 +339,6 @@ luaentity.register_entity("pipeworks:tubed_item", {
self:set_pos(pos) self:set_pos(pos)
end end
local stack = ItemStack(self.itemstring)
local velocity = self:get_velocity() local velocity = self:get_velocity()
local moved = false local moved = false
@ -320,12 +355,19 @@ luaentity.register_entity("pipeworks:tubed_item", {
moved = true moved = true
end end
if not moved then
return
end
local stack = ItemStack(self.itemstring)
pipeworks.load_position(self.start_pos) pipeworks.load_position(self.start_pos)
local node = minetest.get_node(self.start_pos) local node = minetest.get_node(self.start_pos)
if moved and minetest.get_item_group(node.name, "tubedevice_receiver") == 1 then if minetest.get_item_group(node.name, "tubedevice_receiver") == 1 then
local leftover local leftover
if minetest.registered_nodes[node.name].tube and minetest.registered_nodes[node.name].tube.insert_object then local def = minetest.registered_nodes[node.name]
leftover = minetest.registered_nodes[node.name].tube.insert_object(self.start_pos, node, stack, vel, self.owner) if def.tube and def.tube.insert_object then
leftover = def.tube.insert_object(self.start_pos, node, stack, vel, self.owner)
else else
leftover = stack leftover = stack
end end
@ -340,45 +382,50 @@ luaentity.register_entity("pipeworks:tubed_item", {
return return
end end
if moved then local tags
local found_next, new_velocity, multimode = go_next(self.start_pos, velocity, stack, self.owner) -- todo: color if pipeworks.enable_item_tags then
local rev_vel = vector.multiply(velocity, -1) tags = self.tags or {}
local rev_dir = vector.direction(self.start_pos,vector.add(self.start_pos,rev_vel)) end
local rev_node = minetest.get_node(vector.round(vector.add(self.start_pos,rev_dir))) local found_next, new_velocity, multimode = go_next(self.start_pos, velocity, stack, self.owner, tags) -- todo: color
local tube_present = minetest.get_item_group(rev_node.name,"tubedevice") == 1 if pipeworks.enable_item_tags then
if not found_next then self.tags = #tags > 0 and tags or nil
if pipeworks.drop_on_routing_fail or not tube_present or end
minetest.get_item_group(rev_node.name,"tube") ~= 1 then local rev_vel = vector.multiply(velocity, -1)
-- Using add_item instead of item_drop since this makes pipeworks backward local rev_dir = vector.direction(self.start_pos,vector.add(self.start_pos,rev_vel))
-- compatible with Minetest 0.4.13. local rev_node = minetest.get_node(vector.round(vector.add(self.start_pos,rev_dir)))
-- Using item_drop here makes Minetest 0.4.13 crash. local tube_present = minetest.get_item_group(rev_node.name,"tubedevice") == 1
local dropped_item = minetest.add_item(self.start_pos, stack) if not found_next then
if dropped_item then if pipeworks.drop_on_routing_fail or not tube_present or
dropped_item:set_velocity(vector.multiply(velocity, 5)) minetest.get_item_group(rev_node.name,"tube") ~= 1 then
self:remove() -- Using add_item instead of item_drop since this makes pipeworks backward
end -- compatible with Minetest 0.4.13.
return -- Using item_drop here makes Minetest 0.4.13 crash.
else local dropped_item = minetest.add_item(self.start_pos, stack)
velocity = vector.multiply(velocity, -1) if dropped_item then
self:set_pos(vector.subtract(self.start_pos, vector.multiply(vel, moved_by - 1))) dropped_item:set_velocity(vector.multiply(velocity, 5))
self:set_velocity(velocity) self:remove()
end end
elseif is_multimode(multimode) then
-- create new stacks according to returned data.
local s = self.start_pos
for _, split in ipairs(multimode) do
pipeworks.tube_inject_item(s, s, split.velocity, split.itemstack, self.owner)
end
-- remove ourself now the splits are sent
self:remove()
return return
else
velocity = vector.multiply(velocity, -1)
self:set_pos(vector.subtract(self.start_pos, vector.multiply(vel, moved_by - 1)))
self:set_velocity(velocity)
end end
elseif is_multimode(multimode) then
-- create new stacks according to returned data.
local s = self.start_pos
for _, split in ipairs(multimode) do
pipeworks.tube_inject_item(s, s, split.velocity, split.itemstack, self.owner)
end
-- remove ourself now the splits are sent
self:remove()
return
end
if new_velocity and not vector.equals(velocity, new_velocity) then if new_velocity and not vector.equals(velocity, new_velocity) then
local nvelr = math.abs(new_velocity.x + new_velocity.y + new_velocity.z) local nvelr = math.abs(new_velocity.x + new_velocity.y + new_velocity.z)
self:set_pos(vector.add(self.start_pos, vector.multiply(new_velocity, (moved_by - 1) / nvelr))) self:set_pos(vector.add(self.start_pos, vector.multiply(new_velocity, (moved_by - 1) / nvelr)))
self:set_velocity(new_velocity) self:set_velocity(new_velocity)
end
end end
end end
}) })
@ -391,7 +438,7 @@ if minetest.get_modpath("mesecons_mvps") then
for _, n in ipairs(moved_nodes) do for _, n in ipairs(moved_nodes) do
moved[minetest.hash_node_position(n.oldpos)] = vector.subtract(n.pos, n.oldpos) moved[minetest.hash_node_position(n.oldpos)] = vector.subtract(n.pos, n.oldpos)
end end
for id, entity in pairs(luaentity.entities) do for _, entity in pairs(luaentity.entities) do
if entity.name == "pipeworks:tubed_item" then if entity.name == "pipeworks:tubed_item" then
local pos = entity:get_pos() local pos = entity:get_pos()
local rpos = vector.round(pos) local rpos = vector.round(pos)

View File

@ -1,6 +1,6 @@
local S = minetest.get_translator("pipeworks") local S = minetest.get_translator("pipeworks")
if not minetest.get_modpath("auto_tree_tap") and if not minetest.get_modpath("auto_tree_tap") and
minetest.get_modpath("technic") then minetest.get_modpath("technic") then
minetest.register_abm({ minetest.register_abm({
@ -24,10 +24,13 @@ if not minetest.get_modpath("auto_tree_tap") and
description = S("Auto-Tap"), description = S("Auto-Tap"),
tiles = {"pipeworks_nodebreaker_top_off.png","pipeworks_nodebreaker_bottom_off.png","pipeworks_nodebreaker_side2_off.png","pipeworks_nodebreaker_side1_off.png", tiles = {"pipeworks_nodebreaker_top_off.png","pipeworks_nodebreaker_bottom_off.png","pipeworks_nodebreaker_side2_off.png","pipeworks_nodebreaker_side1_off.png",
"pipeworks_nodebreaker_back.png","pipeworks_nodebreaker_front_off.png"}, "pipeworks_nodebreaker_back.png","pipeworks_nodebreaker_front_off.png"},
is_ground_content = true, is_ground_content = false,
paramtype2 = "facedir", paramtype2 = "facedir",
groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2, mesecon = 2,tubedevice=1, not_in_creative_inventory=1 }, groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2, mesecon = 2,tubedevice=1, not_in_creative_inventory=1, axey=1, handy=1, pickaxey=1},
sounds = default.node_sound_stone_defaults(), _mcl_hardness=0.8,
_sound_def = {
key = "node_sound_stone_defaults",
},
tube = {connect_sides={back=1}}, tube = {connect_sides={back=1}},
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
@ -38,10 +41,10 @@ if not minetest.get_modpath("auto_tree_tap") and
after_place_node = function (pos, placer) after_place_node = function (pos, placer)
pipeworks.scan_for_tube_objects(pos, placer) pipeworks.scan_for_tube_objects(pos, placer)
local placer_pos = placer:get_pos() local placer_pos = placer:get_pos()
--correct for the player's height --correct for the player's height
if placer:is_player() then placer_pos.y = placer_pos.y + 1.5 end if placer:is_player() then placer_pos.y = placer_pos.y + 1.5 end
--correct for 6d facedir --correct for 6d facedir
if placer_pos then if placer_pos then
local dir = { local dir = {
@ -52,7 +55,6 @@ if not minetest.get_modpath("auto_tree_tap") and
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
node.param2 = minetest.dir_to_facedir(dir, true) node.param2 = minetest.dir_to_facedir(dir, true)
minetest.set_node(pos, node) minetest.set_node(pos, node)
minetest.log("action", "real (6d) facedir: " .. node.param2)
end end
end, end,
after_dig_node = pipeworks.scan_for_tube_objects, after_dig_node = pipeworks.scan_for_tube_objects,

View File

@ -3,6 +3,10 @@
# License: CC-by-SA 4.0 # License: CC-by-SA 4.0
# Author: Louis Royer <4259825-lroyer@users.noreply.gitlab.com> # Author: Louis Royer <4259825-lroyer@users.noreply.gitlab.com>
## generic interaction
Set=Fixer
Close=Fermer
## digilines interfacing ## digilines interfacing
Channel=Canal Channel=Canal
@ -86,11 +90,12 @@ Sorting pneumatic tube=Tuyau pneumatique triant
## teleport tube ## teleport tube
Receive=Reception Receive=Reception
channels are public by default=Les canaux sont publics par défaut Channels are public by default=Les canaux sont publics par défaut
use <player>:<channel> for fully private channels=Utilisez <joueur>:<canal> pour un canal entièrement privé Use <player>:<channel> for fully private channels=Utilisez <joueur>:<canal> pour un canal entièrement privé
use <player>;<channel> for private receivers=Utilisez <joueur>;<canal> pour une réception privée Use <player>;<channel> for private receivers=Utilisez <joueur>;<canal> pour une réception privée
Teleporting Pneumatic Tube Segment=Segment de tuyau pneumatique téléporteur Teleporting Pneumatic Tube Segment=Segment de tuyau pneumatique téléporteur
unconfigured Teleportation Tube=Tuyau téléporteur non-configuré Teleporting Tube=Tuyau pneumatique téléporteur
Unconfigured Teleportation Tube=Tuyau téléporteur non-configuré
Sorry, channel '@1' is reserved for exclusive use by @2=Désolé, le canal '@1' est réservé exclusivement à lutilisateur @2. Sorry, channel '@1' is reserved for exclusive use by @2=Désolé, le canal '@1' est réservé exclusivement à lutilisateur @2.
Sorry, receiving from channel '@1' is reserved for @2=Désolé, la réception depuis le canal '@1' est réservée pour @2. Sorry, receiving from channel '@1' is reserved for @2=Désolé, la réception depuis le canal '@1' est réservée pour @2.
Teleportation Tube @1 on '@2'=Tuyau de téléportation @1 sur '@2' Teleportation Tube @1 on '@2'=Tuyau de téléportation @1 sur '@2'
@ -102,7 +107,9 @@ Trash Can=Poubelle
Pneumatic tube segment (legacy)=Segment de tuyau pneumatique (obsolète) Pneumatic tube segment (legacy)=Segment de tuyau pneumatique (obsolète)
## vacuum tubes ## vacuum tubes
Radius=Rayon
Vacuuming Pneumatic Tube Segment=Segment de tuyau pneumatique aspirant Vacuuming Pneumatic Tube Segment=Segment de tuyau pneumatique aspirant
Adjustable Vacuuming Tube=Tuyau pneumatique aspirant réglable
Adjustable Vacuuming Pneumatic Tube Segment=Segment de tuyau pneumatique aspirant réglable Adjustable Vacuuming Pneumatic Tube Segment=Segment de tuyau pneumatique aspirant réglable
Adjustable Vacuuming Pneumatic Tube Segment (@1m)=Segment de tuyau pneumatique aspirant réglable (@1 m) Adjustable Vacuuming Pneumatic Tube Segment (@1m)=Segment de tuyau pneumatique aspirant réglable (@1 m)

View File

@ -2,6 +2,10 @@
# License: CC-by-SA 4.0 # License: CC-by-SA 4.0
# Author: pevernow <3450354617@qq.com> # Author: pevernow <3450354617@qq.com>
## generic interaction
Set=
Cancel=
## digilines interfacing ## digilines interfacing
Channel=频道 Channel=频道
@ -84,11 +88,12 @@ Sorting pneumatic tube=分类管道
## teleport tube ## teleport tube
Receive=接收 Receive=接收
channels are public by default=频道默认为公开 Channels are public by default=频道默认为公开
use <player>:<channel> for fully private channels=将<player>:<channel>用于完全私人的频道 Use <player>:<channel> for fully private channels=将<player>:<channel>用于完全私人的频道
use <player>;<channel> for private receivers=使用<player>;<channel>作为私人接收器 Use <player>;<channel> for private receivers=使用<player>;<channel>作为私人接收器
Teleporting Pneumatic Tube Segment=传送管道 Teleporting Pneumatic Tube Segment=传送管道
unconfigured Teleportation Tube=未配置的传送管道 Teleporting Tube=
Unconfigured Teleportation Tube=未配置的传送管道
Sorry, channel '@1' is reserved for exclusive use by @2=抱歉,频道‘@1保留供@2专用 Sorry, channel '@1' is reserved for exclusive use by @2=抱歉,频道‘@1保留供@2专用
Sorry, receiving from channel '@1' is reserved for @2=抱歉,从频道'@1'接收的内容已保留给'@2' Sorry, receiving from channel '@1' is reserved for @2=抱歉,从频道'@1'接收的内容已保留给'@2'
Teleportation Tube @1 on '@2'=传送管'@1'在'@2'上 Teleportation Tube @1 on '@2'=传送管'@1'在'@2'上
@ -100,7 +105,9 @@ Trash Can=垃圾箱
Pneumatic tube segment (legacy)=普通管道(旧式) Pneumatic tube segment (legacy)=普通管道(旧式)
## vacuum tubes ## vacuum tubes
Radius=
Vacuuming Pneumatic Tube Segment=拾取管道 Vacuuming Pneumatic Tube Segment=拾取管道
Adjustable Vacuuming Tube=
Adjustable Vacuuming Pneumatic Tube Segment=高级拾取管道 Adjustable Vacuuming Pneumatic Tube Segment=高级拾取管道
Adjustable Vacuuming Pneumatic Tube Segment (@1m)=高级拾取管道(@1m) Adjustable Vacuuming Pneumatic Tube Segment (@1m)=高级拾取管道(@1m)

View File

@ -3,6 +3,10 @@
# License: CC-by-SA 4.0 # License: CC-by-SA 4.0
# Author: # Author:
## generic interaction
Set=
Cancel=
## digilines interfacing ## digilines interfacing
Channel= Channel=
@ -86,11 +90,12 @@ Sorting pneumatic tube=
## teleport tube ## teleport tube
Receive= Receive=
channels are public by default= Channels are public by default=
use <player>:<channel> for fully private channels= Use <player>:<channel> for fully private channels=
use <player>;<channel> for private receivers= Use <player>;<channel> for private receivers=
Teleporting Pneumatic Tube Segment= Teleporting Pneumatic Tube Segment=
unconfigured Teleportation Tube= Teleporting Tube=
Unconfigured Teleportation Tube=
Sorry, channel '@1' is reserved for exclusive use by @2= Sorry, channel '@1' is reserved for exclusive use by @2=
Sorry, receiving from channel '@1' is reserved for @2= Sorry, receiving from channel '@1' is reserved for @2=
Teleportation Tube @1 on '@2'= Teleportation Tube @1 on '@2'=
@ -102,7 +107,9 @@ Trash Can=
Pneumatic tube segment (legacy)= Pneumatic tube segment (legacy)=
## vacuum tubes ## vacuum tubes
Radius=
Vacuuming Pneumatic Tube Segment= Vacuuming Pneumatic Tube Segment=
Adjustable Vacuuming Tube=
Adjustable Vacuuming Pneumatic Tube Segment= Adjustable Vacuuming Pneumatic Tube Segment=
Adjustable Vacuuming Pneumatic Tube Segment (@1m)= Adjustable Vacuuming Pneumatic Tube Segment (@1m)=

View File

@ -9,16 +9,16 @@ local filename = minetest.get_worldpath().."/luaentities"
local function read_file() local function read_file()
local f = io.open(filename, "r") local f = io.open(filename, "r")
if f == nil then return {} end if f == nil then return {} end
local t = f:read("*all") local t = f:read("*all")
f:close() f:close()
if t == "" or t == nil then return {} end if t == "" or t == nil then return {} end
return minetest.deserialize(t) or {} return minetest.deserialize(t) or {}
end end
local function write_file(tbl) local function write_file(tbl)
local f = io.open(filename, "w") local f = io.open(filename, "w")
f:write(minetest.serialize(tbl)) f:write(minetest.serialize(tbl))
f:close() f:close()
end end
local function read_entities() local function read_entities()
@ -36,7 +36,7 @@ local function read_entities()
y=math.min(30927,y) y=math.min(30927,y)
z=math.min(30927,z) z=math.min(30927,z)
entity.start_pos.x = x entity.start_pos.x = x
entity.start_pos.y = y entity.start_pos.y = y
entity.start_pos.z = z entity.start_pos.z = z
@ -73,31 +73,43 @@ local function get_blockpos(pos)
z = math.floor(pos.z / 16)} z = math.floor(pos.z / 16)}
end end
local active_blocks = {} -- These only contain active blocks near players (i.e., not forceloaded ones) local move_entities_globalstep_part1
local is_active
local move_entities_globalstep_part1 = function(dtime) if pipeworks.use_real_entities then
local active_block_range = tonumber(minetest.settings:get("active_block_range")) or 2 local active_blocks = {} -- These only contain active blocks near players (i.e., not forceloaded ones)
local new_active_blocks = {}
for _, player in ipairs(minetest.get_connected_players()) do
local blockpos = get_blockpos(player:get_pos())
local minp = vector.subtract(blockpos, active_block_range)
local maxp = vector.add(blockpos, active_block_range)
for x = minp.x, maxp.x do move_entities_globalstep_part1 = function(dtime)
for y = minp.y, maxp.y do local active_block_range = tonumber(minetest.settings:get("active_block_range")) or 2
for z = minp.z, maxp.z do local new_active_blocks = {}
local pos = {x = x, y = y, z = z} for _, player in ipairs(minetest.get_connected_players()) do
new_active_blocks[minetest.hash_node_position(pos)] = pos local blockpos = get_blockpos(player:get_pos())
end local minp = vector.subtract(blockpos, active_block_range)
end local maxp = vector.add(blockpos, active_block_range)
for x = minp.x, maxp.x do
for y = minp.y, maxp.y do
for z = minp.z, maxp.z do
local pos = {x = x, y = y, z = z}
new_active_blocks[minetest.hash_node_position(pos)] = pos
end
end
end
end end
active_blocks = new_active_blocks
-- todo: callbacks on block load/unload
end end
active_blocks = new_active_blocks
-- todo: callbacks on block load/unload
end
local function is_active(pos) is_active = function(pos)
return active_blocks[minetest.hash_node_position(get_blockpos(pos))] ~= nil return active_blocks[minetest.hash_node_position(get_blockpos(pos))] ~= nil
end
else
move_entities_globalstep_part1 = function()
end
is_active = function()
return false
end
end end
local entitydef_default = { local entitydef_default = {
@ -151,11 +163,15 @@ local entitydef_default = {
if not is_active(entity_pos) then if not is_active(entity_pos) then
return return
end end
local ent = minetest.add_entity(entity_pos, entity.name):get_luaentity() local object = minetest.add_entity(entity_pos, entity.name)
if not object then
return
end
local ent = object:get_luaentity()
ent:from_data(entity.data) ent:from_data(entity.data)
ent.parent_id = self._id ent.parent_id = self._id
ent.attached_id = index ent.attached_id = index
entity.entity = ent.object entity.entity = object
local master = self._attached_entities_master local master = self._attached_entities_master
if master then if master then
self:_attach(index, master) self:_attach(index, master)
@ -211,7 +227,7 @@ local entitydef_default = {
end end
end, end,
get_velocity = function(self) get_velocity = function(self)
return vector.new(self._velocity) return vector.new(self._velocity)
end, end,
set_velocity = function(self, velocity) set_velocity = function(self, velocity)
self._velocity = vector.new(velocity) self._velocity = vector.new(velocity)
@ -289,7 +305,7 @@ function luaentity.add_entity(pos, name)
_acceleration = {x = 0, y = 0, z = 0}, _acceleration = {x = 0, y = 0, z = 0},
_attached_entities = {}, _attached_entities = {},
} }
local prototype = luaentity.registered_entities[name] local prototype = luaentity.registered_entities[name]
setmetatable(entity, prototype) -- Default to prototype for other methods setmetatable(entity, prototype) -- Default to prototype for other methods
luaentity.entities[index] = entity luaentity.entities[index] = entity
@ -318,19 +334,20 @@ end
function luaentity.get_objects_inside_radius(pos, radius) function luaentity.get_objects_inside_radius(pos, radius)
local objects = {} local objects = {}
local index = 1 local index = 1
for id, entity in pairs(luaentity.entities) do for _, entity in pairs(luaentity.entities) do
if vector.distance(pos, entity:get_pos()) <= radius then if vector.distance(pos, entity:get_pos()) <= radius then
objects[index] = entity objects[index] = entity
index = index + 1 index = index + 1
end end
end end
return objects
end end
local move_entities_globalstep_part2 = function(dtime) local move_entities_globalstep_part2 = function(dtime)
if not luaentity.entities then if not luaentity.entities then
luaentity.entities = read_entities() luaentity.entities = read_entities()
end end
for id, entity in pairs(luaentity.entities) do for _, entity in pairs(luaentity.entities) do
local master = entity._attached_entities_master local master = entity._attached_entities_master
local master_def = master and entity._attached_entities[master] local master_def = master and entity._attached_entities[master]
local master_entity = master_def and master_def.entity local master_entity = master_def and master_def.entity
@ -369,13 +386,36 @@ local move_entities_globalstep_part2 = function(dtime)
end end
end end
local handle_active_blocks_timer = 0.1 -- dtime after which there is an update (or skip).
local dtime_threshold = pipeworks.entity_update_interval
-- Accumulated dtime since last update (or skip).
local dtime_accum = 0
-- Delayed dtime accumulated due to skipped updates.
local dtime_delayed = 0
local skip_update = false
minetest.register_globalstep(function(dtime) minetest.register_globalstep(function(dtime)
handle_active_blocks_timer = handle_active_blocks_timer + dtime if dtime >= 0.2 and dtime_delayed < 1 then
if dtime < 0.2 or handle_active_blocks_timer >= (dtime * 3) then -- Reduce activity when the server is lagging.
handle_active_blocks_timer = 0.1 skip_update = true
move_entities_globalstep_part1(dtime)
move_entities_globalstep_part2(dtime)
end end
dtime_accum = dtime_accum + dtime
if dtime_accum < dtime_threshold then
return
end
if skip_update then
dtime_delayed = dtime_delayed + dtime_accum
skip_update = false
else
move_entities_globalstep_part1(dtime_accum + dtime_delayed)
move_entities_globalstep_part2(dtime_accum + dtime_delayed)
dtime_delayed = 0
end
-- Tune the threshold so that the average interval is pipeworks.entity_update_interval.
dtime_threshold = math.max(dtime_threshold + (pipeworks.entity_update_interval - dtime_accum) / 10, 0)
dtime_accum = 0
end) end)

72
mcl_barrels.lua Normal file
View File

@ -0,0 +1,72 @@
-- this bit of code modifies the mcl barrels to be compatible with
-- pipeworks.
-- Pipeworks Specific
local tube_entry = "^pipeworks_tube_connection_wooden.png"
-- Original Definitions
local old_barrel = table.copy(minetest.registered_items["mcl_barrels:barrel_closed"])
local groups = old_barrel.groups
groups["tubedevice"] = 1
groups["tubedevice_receiver"] = 1
local groups_open = table.copy(groups)
groups_open["not_in_creative_inventory"] = 1
-- Override Construction
local override_barrel = {}
override_barrel.tiles = {
"mcl_barrels_barrel_top.png^[transformR270",
"mcl_barrels_barrel_bottom.png"..tube_entry,
"mcl_barrels_barrel_side.png"..tube_entry
}
override_barrel.after_place_node = function(pos, placer, itemstack, pointed_thing)
old_barrel.after_place_node(pos, placer, itemstack, pointed_thing)
pipeworks.after_place(pos, placer, itemstack, pointed_thing)
end
override_barrel.tube = {
insert_object = function(pos, node, stack, direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return inv:add_item("main", stack)
end,
can_insert = function(pos, node, stack, direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
if meta:get_int("splitstacks") == 1 then
stack = stack:peek_item(1)
end
return inv:room_for_item("main", stack)
end,
input_inventory = "main",
connect_sides = {left = 1, right = 1, back = 1, front = 1, bottom = 1}
}
override_barrel.after_dig_node = function(pos, oldnode, oldmetadata, digger)
old_barrel.after_dig_node(pos, oldnode, oldmetadata, digger)
pipeworks.after_dig(pos)
end
override_barrel.groups = table.copy(old_barrel.groups)
override_barrel.on_rotate = pipeworks.on_rotate
local override_barrel_open = table.copy(override_barrel)
override_barrel_open.tiles = {
"mcl_barrels_barrel_top_open.png",
"mcl_barrels_barrel_bottom.png"..tube_entry,
"mcl_barrels_barrel_side.png"..tube_entry
}
override_barrel_open.groups = groups_open
-- Override with the new modifications.
minetest.override_item("mcl_barrels:barrel_closed", override_barrel)
minetest.override_item("mcl_barrels:barrel_open", override_barrel_open)

376
mcl_furnaces.lua Normal file
View File

@ -0,0 +1,376 @@
local old_furnace = table.copy(minetest.registered_nodes["mcl_furnaces:furnace"])
local old_blast_furnace = table.copy(minetest.registered_nodes["mcl_blast_furnace:blast_furnace"])
local old_smoker = table.copy(minetest.registered_nodes["mcl_smoker:smoker"])
local tube_entry = "^pipeworks_tube_connection_stony.png"
-- groups
local furnace_groups = old_furnace.groups
furnace_groups["tubedevice"] = 1
furnace_groups["tubedevice_receiver"] = 1
local furnace_groups_active = table.copy(furnace_groups)
furnace_groups_active["not_in_creative_inventory"] = 1
local blast_furnace_groups = old_blast_furnace.groups
blast_furnace_groups["tubedevice"] = 1
blast_furnace_groups["tubedevice_receiver"] = 1
local blast_furnace_groups_active = table.copy(blast_furnace_groups)
blast_furnace_groups_active["not_in_creative_inventory"] = 1
local smoker_groups = old_smoker.groups
smoker_groups["tubedevice"] = 1
smoker_groups["tubedevice_receiver"] = 1
local smoker_groups_active = table.copy(smoker_groups)
smoker_groups_active["not_in_creative_inventory"] = 1
-- a hack to give the exp to fake players it's be dropped instead added to (fake) player inv
local function give_xp(pos, player)
local meta = minetest.get_meta(pos)
local dir = vector.divide(minetest.facedir_to_dir(minetest.get_node(pos).param2), -1.95)
local xp = meta:get_int("xp")
if xp > 0 then
mcl_experience.throw_xp(vector.add(pos, dir), xp)
meta:set_int("xp", 0)
end
end
local override = {}
override.tiles = {
"default_furnace_top.png"..tube_entry,
"default_furnace_bottom.png"..tube_entry,
"default_furnace_side.png"..tube_entry,
"default_furnace_side.png"..tube_entry,
"default_furnace_side.png"..tube_entry,
"default_furnace_front.png"
}
override.groups = furnace_groups
override.tube = {
insert_object = function(pos, node, stack, direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local timer = minetest.get_node_timer(pos)
if not timer:is_started() then
timer:start(1.0)
end
if direction.y == 1 then
return inv:add_item("fuel", stack)
else
return inv:add_item("src", stack)
end
end,
can_insert = function(pos,node,stack,direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
if direction.y == 1 then
return inv:room_for_item("fuel", stack)
else
if meta:get_int("split_material_stacks") == 1 then
stack = stack:peek_item(1)
end
return inv:room_for_item("src", stack)
end
end,
input_inventory = "dst",
connect_sides = {left = 1, right = 1, back = 1, bottom = 1, top = 1}
}
override.after_place_node = function(pos, placer, itemstack, pointed_thing)
pipeworks.after_place(pos, placer, itemstack, pointed_thing)
end
override.after_dig_node = function(pos, oldnode, oldmetadata, digger)
old_furnace.after_dig_node(pos, oldnode, oldmetadata, digger)
pipeworks.after_dig(pos)
end
override.on_metadata_inventory_take = function(pos, listname, index, stack, player)
if listname == "dst" then
if stack:get_name() == "mcl_core:iron_ingot" then
awards.unlock(player:get_player_name(), "mcl:acquireIron")
elseif stack:get_name() == "mcl_fishing:fish_cooked" then
awards.unlock(player:get_player_name(), "mcl:cookFish")
end
give_xp(pos, player)
end
end
override.on_rotate = pipeworks.on_rotate
local override_active = table.copy(override)
override_active.tiles = {
"default_furnace_top.png"..tube_entry,
"default_furnace_bottom.png"..tube_entry,
"default_furnace_side.png"..tube_entry,
"default_furnace_side.png"..tube_entry,
"default_furnace_side.png"..tube_entry,
"default_furnace_front_active.png",
}
override_active.groups = furnace_groups_active
override_active.tube = {
insert_object = function(pos,node,stack,direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local timer = minetest.get_node_timer(pos)
if not timer:is_started() then
timer:start(1.0)
end
if direction.y == 1 then
return inv:add_item("fuel", stack)
else
return inv:add_item("src", stack)
end
end,
can_insert = function(pos, node, stack, direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
if direction.y == 1 then
return inv:room_for_item("fuel", stack)
else
return inv:room_for_item("src", stack)
end
end,
input_inventory = "dst",
connect_sides = {left = 1, right = 1, back = 1, bottom = 1, top = 1}
}
--blast furnace
local override_blast_furnace = {}
override_blast_furnace.tiles = {
"blast_furnace_top.png"..tube_entry,
"blast_furnace_top.png"..tube_entry,
"blast_furnace_side.png"..tube_entry,
"blast_furnace_side.png"..tube_entry,
"blast_furnace_side.png"..tube_entry,
"blast_furnace_front.png"
}
override_blast_furnace.groups = blast_furnace_groups
override_blast_furnace.tube = {
insert_object = function(pos, node, stack, direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local timer = minetest.get_node_timer(pos)
if not timer:is_started() then
timer:start(1.0)
end
if direction.y == 1 then
return inv:add_item("fuel", stack)
else
return inv:add_item("src", stack)
end
end,
can_insert = function(pos,node,stack,direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
if direction.y == 1 then
return inv:room_for_item("fuel", stack)
else
if meta:get_int("split_material_stacks") == 1 then
stack = stack:peek_item(1)
end
return inv:room_for_item("src", stack)
end
end,
input_inventory = "dst",
connect_sides = {left = 1, right = 1, back = 1, bottom = 1, top = 1}
}
override_blast_furnace.after_place_node = function(pos, placer, itemstack, pointed_thing)
pipeworks.after_place(pos, placer, itemstack, pointed_thing)
end
override_blast_furnace.after_dig_node = function(pos, oldnode, oldmetadata, digger)
old_blast_furnace.after_dig_node(pos, oldnode, oldmetadata, digger)
pipeworks.after_dig(pos)
end
override_blast_furnace.on_metadata_inventory_take = function(pos, listname, index, stack, player)
-- Award smelting achievements
if listname == "dst" then
if stack:get_name() == "mcl_core:iron_ingot" then
awards.unlock(player:get_player_name(), "mcl:acquireIron")
end
give_xp(pos, player)
end
end
override_blast_furnace.on_rotate = pipeworks.on_rotate
local override_blast_active = table.copy(override)
override_blast_active.tiles = {
"blast_furnace_top.png"..tube_entry,
"blast_furnace_top.png"..tube_entry,
"blast_furnace_side.png"..tube_entry,
"blast_furnace_side.png"..tube_entry,
"blast_furnace_side.png"..tube_entry,
{
name = "blast_furnace_front_on.png",
animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 48 }
},
}
override_blast_active.groups = blast_furnace_groups_active
override_blast_active.tube = {
insert_object = function(pos,node,stack,direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local timer = minetest.get_node_timer(pos)
if not timer:is_started() then
timer:start(1.0)
end
if direction.y == 1 then
return inv:add_item("fuel", stack)
else
return inv:add_item("src", stack)
end
end,
can_insert = function(pos, node, stack, direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
if direction.y == 1 then
return inv:room_for_item("fuel", stack)
else
return inv:room_for_item("src", stack)
end
end,
input_inventory = "dst",
connect_sides = {left = 1, right = 1, back = 1, bottom = 1, top = 1}
}
-- smoker
local override_smoker = {}
override_smoker.tiles = {
"smoker_top.png"..tube_entry,
"smoker_bottom.png"..tube_entry,
"smoker_side.png"..tube_entry,
"smoker_side.png"..tube_entry,
"smoker_side.png"..tube_entry,
"smoker_front.png"
}
override_smoker.groups = smoker_groups
override_smoker.tube = {
insert_object = function(pos, node, stack, direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local timer = minetest.get_node_timer(pos)
if not timer:is_started() then
timer:start(1.0)
end
if direction.y == 1 then
return inv:add_item("fuel", stack)
else
return inv:add_item("src", stack)
end
end,
can_insert = function(pos,node,stack,direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
if direction.y == 1 then
return inv:room_for_item("fuel", stack)
else
if meta:get_int("split_material_stacks") == 1 then
stack = stack:peek_item(1)
end
return inv:room_for_item("src", stack)
end
end,
input_inventory = "dst",
connect_sides = {left = 1, right = 1, back = 1, bottom = 1, top = 1}
}
override_smoker.after_place_node = function(pos, placer, itemstack, pointed_thing)
pipeworks.after_place(pos, placer, itemstack, pointed_thing)
end
override_smoker.after_dig_node = function(pos, oldnode, oldmetadata, digger)
old_smoker.after_dig_node(pos, oldnode, oldmetadata, digger)
pipeworks.after_dig(pos)
end
override_smoker.on_metadata_inventory_take = function(pos, listname, index, stack, player)
-- Award fish achievements
if listname == "dst" then
if stack:get_name() == "mcl_fishing:fish_cooked" then
awards.unlock(player:get_player_name(), "mcl:cookFish")
end
give_xp(pos, player)
end
end
override_smoker.on_rotate = pipeworks.on_rotate
local override_smoker_active = table.copy(override)
override_smoker_active.tiles = {
"smoker_top.png"..tube_entry,
"smoker_bottom.png"..tube_entry,
"smoker_side.png"..tube_entry,
"smoker_side.png"..tube_entry,
"smoker_side.png"..tube_entry,
{
name = "smoker_front_on.png",
animation = { type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 48 }
},
}
override_smoker_active.groups = smoker_groups_active
override_smoker_active.tube = {
insert_object = function(pos,node,stack,direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local timer = minetest.get_node_timer(pos)
if not timer:is_started() then
timer:start(1.0)
end
if direction.y == 1 then
return inv:add_item("fuel", stack)
else
return inv:add_item("src", stack)
end
end,
can_insert = function(pos, node, stack, direction)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
if direction.y == 1 then
return inv:room_for_item("fuel", stack)
else
return inv:room_for_item("src", stack)
end
end,
input_inventory = "dst",
connect_sides = {left = 1, right = 1, back = 1, bottom = 1, top = 1}
}
-- override
minetest.override_item("mcl_furnaces:furnace", override)
minetest.override_item("mcl_furnaces:furnace_active", override_active)
minetest.override_item("mcl_blast_furnace:blast_furnace", override_blast_furnace)
minetest.override_item("mcl_blast_furnace:blast_furnace_active", override_blast_active)
minetest.override_item("mcl_smoker:smoker", override_smoker)
minetest.override_item("mcl_smoker:smoker_active", override_smoker_active)

View File

@ -1,5 +1,5 @@
name = pipeworks name = pipeworks
description = This mod uses mesh nodes and nodeboxes to supply a complete set of 3D pipes and tubes, along with devices that work with them. description = This mod uses mesh nodes and nodeboxes to supply a complete set of 3D pipes and tubes, along with devices that work with them.
depends = default, basic_materials, screwdriver depends = basic_materials, xcompat
optional_depends = mesecons, mesecons_mvps, digilines, signs_lib optional_depends = mesecons, mesecons_mvps, digilines, signs_lib, unified_inventory, default, screwdriver, fl_mapgen, sound_api, i3, hades_core, hades_furnaces, hades_chests, mcl_mapgen_core, mcl_barrels, mcl_furnaces, mcl_experience
min_minetest_version = 5.2.0 min_minetest_version = 5.5.0

View File

@ -11,11 +11,11 @@ local new_flow_logic_register = pipeworks.flowables.register
local polys = "" local polys = ""
if pipeworks.enable_lowpoly then polys = "_lowpoly" end if pipeworks.enable_lowpoly then polys = "_lowpoly" end
local vti = {4, 3, 2, 1, 6, 5} --~ local vti = {4, 3, 2, 1, 6, 5}
local cconnects = {{}, {1}, {1, 2}, {1, 3}, {1, 3, 5}, {1, 2, 3}, {1, 2, 3, 5}, {1, 2, 3, 4}, {1, 2, 3, 4, 5}, {1, 2, 3, 4, 5, 6}} local cconnects = {{}, {1}, {1, 2}, {1, 3}, {1, 3, 5}, {1, 2, 3}, {1, 2, 3, 5}, {1, 2, 3, 4}, {1, 2, 3, 4, 5}, {1, 2, 3, 4, 5, 6}}
for index, connects in ipairs(cconnects) do for index, connects in ipairs(cconnects) do
local outsel = {} local outsel = {}
local jx = 0 local jx = 0
local jy = 0 local jy = 0
local jz = 0 local jz = 0
@ -30,23 +30,25 @@ for index, connects in ipairs(cconnects) do
table.insert(outsel, pipeworks.pipe_selectboxes[v]) table.insert(outsel, pipeworks.pipe_selectboxes[v])
end end
--[[
if #connects == 1 then if #connects == 1 then
local v = connects[1] local v = connects[1]
v = v-1 + 2*(v%2) -- Opposite side v = v-1 + 2*(v%2) -- Opposite side
end end
--]]
local pgroups = {snappy = 3, pipe = 1, not_in_creative_inventory = 1}
local pgroups = {snappy = 3, pipe = 1, not_in_creative_inventory = 1, dig_generic = 4, axey=1, handy=1, pickaxey=1}
local pipedesc = S("Pipe Segment").." "..dump(connects) local pipedesc = S("Pipe Segment").." "..dump(connects)
if #connects == 0 then if #connects == 0 then
pgroups = {snappy = 3, tube = 1} pgroups = {snappy = 3, tube = 1, dig_generic = 4, axey=1, handy=1, pickaxey=1}
pipedesc = S("Pipe Segment") pipedesc = S("Pipe Segment")
end end
local outimg_e = { "pipeworks_pipe_plain.png" } local outimg_e = { "pipeworks_pipe_plain.png" }
local outimg_l = { "pipeworks_pipe_plain.png" } local outimg_l = { "pipeworks_pipe_plain.png" }
if index == 3 then if index == 3 then
outimg_e = { "pipeworks_pipe_3_empty.png" } outimg_e = { "pipeworks_pipe_3_empty.png" }
outimg_l = { "pipeworks_pipe_3_loaded.png" } outimg_l = { "pipeworks_pipe_3_loaded.png" }
end end
@ -74,7 +76,11 @@ for index, connects in ipairs(cconnects) do
fixed = outsel fixed = outsel
}, },
groups = pgroups, groups = pgroups,
sounds = default.node_sound_metal_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_metal_defaults",
},
walkable = true, walkable = true,
drop = "pipeworks:pipe_1_empty", drop = "pipeworks:pipe_1_empty",
after_place_node = function(pos) after_place_node = function(pos)
@ -88,8 +94,8 @@ for index, connects in ipairs(cconnects) do
check_for_horiz_pole = pipeworks.check_for_horiz_pipe, check_for_horiz_pole = pipeworks.check_for_horiz_pipe,
pipenumber = index pipenumber = index
}) })
local pgroups = {snappy = 3, pipe = 1, not_in_creative_inventory = 1} local pgroups = {snappy = 3, pipe = 1, not_in_creative_inventory = 1, dig_generic = 4, axey=1, handy=1, pickaxey=1}
minetest.register_node("pipeworks:pipe_"..index.."_loaded", { minetest.register_node("pipeworks:pipe_"..index.."_loaded", {
description = pipedesc, description = pipedesc,
@ -108,7 +114,11 @@ for index, connects in ipairs(cconnects) do
fixed = outsel fixed = outsel
}, },
groups = pgroups, groups = pgroups,
sounds = default.node_sound_metal_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_metal_defaults",
},
walkable = true, walkable = true,
drop = "pipeworks:pipe_1_empty", drop = "pipeworks:pipe_1_empty",
after_place_node = function(pos) after_place_node = function(pos)
@ -123,7 +133,7 @@ for index, connects in ipairs(cconnects) do
check_for_horiz_pole = pipeworks.check_for_horiz_pipe, check_for_horiz_pole = pipeworks.check_for_horiz_pipe,
pipenumber = index pipenumber = index
}) })
local emptypipe = "pipeworks:pipe_"..index.."_empty" local emptypipe = "pipeworks:pipe_"..index.."_empty"
local fullpipe = "pipeworks:pipe_"..index.."_loaded" local fullpipe = "pipeworks:pipe_"..index.."_loaded"
table.insert(pipes_empty_nodenames, emptypipe) table.insert(pipes_empty_nodenames, emptypipe)
@ -131,7 +141,7 @@ for index, connects in ipairs(cconnects) do
new_flow_logic_register.simple(emptypipe) new_flow_logic_register.simple(emptypipe)
new_flow_logic_register.simple(fullpipe) new_flow_logic_register.simple(fullpipe)
end end
pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:pipe_1_empty"
if REGISTER_COMPATIBILITY then if REGISTER_COMPATIBILITY then
@ -143,6 +153,7 @@ if REGISTER_COMPATIBILITY then
paramtype = "light", paramtype = "light",
description = S("Pipe Segment (legacy)"), description = S("Pipe Segment (legacy)"),
groups = {not_in_creative_inventory = 1, pipe_to_update = 1}, groups = {not_in_creative_inventory = 1, pipe_to_update = 1},
is_ground_content = false,
drop = "pipeworks:pipe_1_empty", drop = "pipeworks:pipe_1_empty",
after_place_node = function(pos) after_place_node = function(pos)
pipeworks.scan_for_pipe_objects(pos) pipeworks.scan_for_pipe_objects(pos)
@ -155,6 +166,7 @@ if REGISTER_COMPATIBILITY then
sunlight_propagates = true, sunlight_propagates = true,
paramtype = "light", paramtype = "light",
groups = {not_in_creative_inventory = 1, pipe_to_update = 1}, groups = {not_in_creative_inventory = 1, pipe_to_update = 1},
is_ground_content = false,
drop = "pipeworks:pipe_1_empty", drop = "pipeworks:pipe_1_empty",
after_place_node = function(pos) after_place_node = function(pos)
pipeworks.scan_for_pipe_objects(pos) pipeworks.scan_for_pipe_objects(pos)
@ -239,7 +251,7 @@ minetest.register_abm({
nodenames = {"pipeworks:spigot","pipeworks:spigot_pouring"}, nodenames = {"pipeworks:spigot","pipeworks:spigot_pouring"},
interval = 1, interval = 1,
chance = 1, chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider) action = function(pos, node, active_object_count, active_object_count_wider)
pipeworks.spigot_check(pos,node) pipeworks.spigot_check(pos,node)
end end
}) })
@ -248,7 +260,7 @@ minetest.register_abm({
nodenames = {"pipeworks:fountainhead","pipeworks:fountainhead_pouring"}, nodenames = {"pipeworks:fountainhead","pipeworks:fountainhead_pouring"},
interval = 1, interval = 1,
chance = 1, chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider) action = function(pos, node, active_object_count, active_object_count_wider)
pipeworks.fountainhead_check(pos,node) pipeworks.fountainhead_check(pos,node)
end end
}) })

View File

@ -29,7 +29,7 @@ end
local formatvec = function(vec) local sep="," return "("..tostring(vec.x)..sep..tostring(vec.y)..sep..tostring(vec.z)..")" end --~ local formatvec = function(vec) local sep="," return "("..tostring(vec.x)..sep..tostring(vec.y)..sep..tostring(vec.z)..")" end
@ -39,10 +39,10 @@ local formatvec = function(vec) local sep="," return "("..tostring(vec.x)..sep..
local check_for_liquids_v2 = function(pos, limit) local check_for_liquids_v2 = function(pos, limit)
local coords = make_coords_offsets(pos, false) local coords = make_coords_offsets(pos, false)
local total = 0 local total = 0
for index, tpos in ipairs(coords) do for _, tpos in ipairs(coords) do
if total >= limit then break end if total >= limit then break end
local name = minetest.get_node(tpos).name local name = minetest.get_node(tpos).name
if name == "default:water_source" then if name == pipeworks.liquids.water.source then
minetest.remove_node(tpos) minetest.remove_node(tpos)
total = total + 1 total = total + 1
end end
@ -69,11 +69,13 @@ end
-- logging is unreliable when something is crashing... -- logging is unreliable when something is crashing...
--[[
local nilexplode = function(caller, label, value) local nilexplode = function(caller, label, value)
if value == nil then if value == nil then
error(caller..": "..label.." was nil") error(caller..": "..label.." was nil")
end end
end end
--]]
@ -151,7 +153,7 @@ local get_neighbour_positions = function(pos, node)
-- then, check each possible neighbour to see if they can be reached from this node. -- then, check each possible neighbour to see if they can be reached from this node.
local connections = {} local connections = {}
for index, offset in ipairs(candidates) do for _, offset in ipairs(candidates) do
local npos = vector.add(pos, offset) local npos = vector.add(pos, offset)
local neighbour = minetest.get_node(npos) local neighbour = minetest.get_node(npos)
local nodename = neighbour.name local nodename = neighbour.name
@ -185,13 +187,12 @@ flowlogic.balance_pressure = function(pos, node, currentpressure)
-- local dname = "flowlogic.balance_pressure()@"..formatvec(pos).." " -- local dname = "flowlogic.balance_pressure()@"..formatvec(pos).." "
-- check the pressure of all nearby flowable nodes, and average it out. -- check the pressure of all nearby flowable nodes, and average it out.
-- pressure handles to average over
local connections = {}
-- unconditionally include self in nodes to average over. -- unconditionally include self in nodes to average over.
-- result of averaging will be returned as new pressure for main flow logic callback -- result of averaging will be returned as new pressure for main flow logic callback
local totalv = currentpressure local totalv = currentpressure
local totalc = 1 local totalc = 1
-- pressure handles to average over
local connections = get_neighbour_positions(pos, node) local connections = get_neighbour_positions(pos, node)
-- for each neighbour, add neighbour's pressure to the total to balance out -- for each neighbour, add neighbour's pressure to the total to balance out
@ -246,9 +247,9 @@ flowlogic.helpers.make_neighbour_output_fixed = function(neighbours)
-- in non-finite mode, pressure has to be sustained to keep the sources there. -- in non-finite mode, pressure has to be sustained to keep the sources there.
-- so in non-finite mode, placing water is dependent on the target node; -- so in non-finite mode, placing water is dependent on the target node;
-- draining pressure is not. -- draining pressure is not.
local canplace = (name == "air") or (name == "default:water_flowing") local canplace = (name == "air") or (name == pipeworks.liquids.water.flowing)
if canplace then if canplace then
minetest.swap_node(npos, {name="default:water_source"}) minetest.swap_node(npos, {name=pipeworks.liquids.water.source})
end end
if (not finitemode) or canplace then if (not finitemode) or canplace then
taken = taken + 1 taken = taken + 1
@ -267,7 +268,7 @@ flowlogic.helpers.make_neighbour_cleanup_fixed = function(neighbours)
for _, offset in pairs(neighbours) do for _, offset in pairs(neighbours) do
local npos = vector.add(pos, offset) local npos = vector.add(pos, offset)
local name = minetest.get_node(npos).name local name = minetest.get_node(npos).name
if (name == "default:water_source") then if (name == pipeworks.liquids.water.source) then
--pipeworks.logger("neighbour_cleanup_fixed removing "..formatvec(npos)) --pipeworks.logger("neighbour_cleanup_fixed removing "..formatvec(npos))
minetest.remove_node(npos) minetest.remove_node(npos)
end end
@ -287,7 +288,7 @@ flowlogic.run_output = function(pos, node, currentpressure, oldpressure, outputd
local upper = outputdef.upper local upper = outputdef.upper
local lower = outputdef.lower local lower = outputdef.lower
local result = currentpressure local result = currentpressure
local threshold = nil local threshold
if finitemode then threshold = lower else threshold = upper end if finitemode then threshold = lower else threshold = upper end
if currentpressure > threshold then if currentpressure > threshold then
local takenpressure = outputdef.outputfn(pos, node, currentpressure, finitemode) local takenpressure = outputdef.outputfn(pos, node, currentpressure, finitemode)
@ -316,7 +317,7 @@ flowlogic.run_transition = function(node, currentpressure)
local nodename_prev = simplesetdef[1].nodename local nodename_prev = simplesetdef[1].nodename
local result_nodename = node.name local result_nodename = node.name
for index, element in ipairs(simplesetdef) do for _, element in ipairs(simplesetdef) do
-- find the highest element that is below the current pressure. -- find the highest element that is below the current pressure.
local threshold = element.threshold local threshold = element.threshold
if threshold > currentpressure then if threshold > currentpressure then
@ -338,7 +339,9 @@ flowlogic.run_transition = function(node, currentpressure)
end end
if not found then if not found then
pipeworks.logger("flowlogic.run_transition() BUG no transition definitions found! nodename="..nodename.." currentpressure="..tostring(currentpressure)) pipeworks.logger("flowlogic.run_transition() BUG no transition " ..
"definitions found! node.name=" .. node.name ..
" currentpressure=" .. tostring(currentpressure))
end end
return result return result
@ -350,7 +353,7 @@ end
flowlogic.run_transition_post = function(pos, node) flowlogic.run_transition_post = function(pos, node)
local mesecons_def = minetest.registered_nodes[node.name].mesecons local mesecons_def = minetest.registered_nodes[node.name].mesecons
local mesecons_rules = pipeworks.flowables.transitions.mesecons[node.name] local mesecons_rules = pipeworks.flowables.transitions.mesecons[node.name]
if minetest.global_exists("mesecon") and (mesecons_def ~= nil) and mesecons_rules then if minetest.get_modpath("mesecons") and (mesecons_def ~= nil) and mesecons_rules then
if type(mesecons_def) ~= "table" then if type(mesecons_def) ~= "table" then
pipeworks.logger("flowlogic.run_transition_post() BUG mesecons def for "..node.name.."not a table: got "..tostring(mesecons_def)) pipeworks.logger("flowlogic.run_transition_post() BUG mesecons def for "..node.name.."not a table: got "..tostring(mesecons_def))
else else

View File

@ -26,8 +26,8 @@ local insertbase = function(nodename)
end end
local regwarning = function(kind, nodename) local regwarning = function(kind, nodename)
local tail = "" --~ local tail = ""
if pipeworks.toggles.pipe_mode ~= "pressure" then tail = " but pressure logic not enabled" end --~ if pipeworks.toggles.pipe_mode ~= "pressure" then tail = " but pressure logic not enabled" end
--pipeworks.logger(kind.." flow logic registry requested for "..nodename..tail) --pipeworks.logger(kind.." flow logic registry requested for "..nodename..tail)
end end
@ -106,7 +106,7 @@ register.directional_horizonal_rotate = function(nodename, doubleended)
end end
local directionfn = function(node, direction) local directionfn = function(node, direction)
local result = false local result = false
for index, endvec in ipairs(getends(node)) do for _, endvec in ipairs(getends(node)) do
if vector.equals(direction, endvec) then result = true end if vector.equals(direction, endvec) then result = true end
end end
return result return result

View File

@ -75,3 +75,15 @@ pipeworks_drop_on_routing_fail (Drop On Routing Fail) bool false
#Delete item on clearobject. #Delete item on clearobject.
pipeworks_delete_item_on_clearobject (Delete Item On Clearobject) bool true pipeworks_delete_item_on_clearobject (Delete Item On Clearobject) bool true
#Use real visible entities in tubes within active areas.
#When disabled, tubes are made opaque.
pipeworks_use_real_entities (Use Real Entities) bool true
#Target interval between tube entity steps.
#A high value may cause issues with tube entity visuals.
#A value 0.2 or above may cause issues with accelerator tubes.
pipeworks_entity_update_interval (Entity Update Interval) float 0 0 0.8
# if set to true, items passing through teleport tubes will log log where they came from and where they went.
pipeworks_log_teleport_tubes (Log Teleport Tubes) bool false

View File

@ -1,271 +0,0 @@
local S = minetest.get_translator("pipeworks")
local filename=minetest.get_worldpath() .. "/teleport_tubes"
local tp_tube_db = nil -- nil forces a read
local tp_tube_db_version = 2.0
local function hash(pos)
return string.format("%.30g", minetest.hash_node_position(pos))
end
local function save_tube_db()
local file, err = io.open(filename, "w")
if file then
tp_tube_db.version = tp_tube_db_version
file:write(minetest.serialize(tp_tube_db))
tp_tube_db.version = nil
io.close(file)
else
error(err)
end
end
local function migrate_tube_db()
local tmp_db = {}
tp_tube_db.version = nil
for key, val in pairs(tp_tube_db) do
if(val.channel ~= "") then -- skip unconfigured tubes
tmp_db[hash(val)] = val
end
end
tp_tube_db = tmp_db
save_tube_db()
end
local function read_tube_db()
local file = io.open(filename, "r")
if file ~= nil then
local file_content = file:read("*all")
io.close(file)
if file_content and file_content ~= "" then
tp_tube_db = minetest.deserialize(file_content)
if(not tp_tube_db.version or tonumber(tp_tube_db.version) < tp_tube_db_version) then
migrate_tube_db()
end
tp_tube_db.version = nil -- we add it back when saving
return tp_tube_db -- we read sucessfully
end
end
tp_tube_db = {}
return tp_tube_db
end
-- debug formatter for coordinates used below
local fmt = function(pos)
return pos.x..", "..pos.y..", "..pos.z
end
-- updates or adds a tube
local function set_tube(pos, channel, can_receive)
local tubes = tp_tube_db or read_tube_db()
local hash = hash(pos)
local tube = tubes[hash]
if tube then
tube.channel = channel
tube.cr = can_receive
save_tube_db()
return
end
-- we haven't found any tp tube to update, so lets add it
-- but sanity check that the hash has not already been inserted.
-- if so, complain very loudly and refuse the update so the player knows something is amiss.
-- to catch regressions of https://github.com/minetest-mods/pipeworks/issues/166
local existing = tp_tube_db[hash]
if existing ~= nil then
local e = "error"
minetest.log(e, "pipeworks teleport tube update refused due to position hash collision")
minetest.log(e, "collided hash: "..hash)
minetest.log(e, "tried-to-place tube: "..fmt(pos))
minetest.log(e, "existing tube: "..fmt(existing))
return
end
tp_tube_db[hash] = {x=pos.x,y=pos.y,z=pos.z,channel=channel,cr=can_receive}
save_tube_db()
end
local function remove_tube(pos)
local tubes = tp_tube_db or read_tube_db()
tubes[hash(pos)] = nil
save_tube_db()
end
local function read_node_with_vm(pos)
local vm = VoxelManip()
local MinEdge, MaxEdge = vm:read_from_map(pos, pos)
local data = vm:get_data()
local area = VoxelArea:new({MinEdge = MinEdge, MaxEdge = MaxEdge})
return minetest.get_name_from_content_id(data[area:index(pos.x, pos.y, pos.z)])
end
local function get_receivers(pos, channel)
local tubes = tp_tube_db or read_tube_db()
local receivers = {}
local dirty = false
for key, val in pairs(tubes) do
-- skip all non-receivers and the tube that it came from as early as possible, as this is called often
if (val.cr == 1 and val.channel == channel and (val.x ~= pos.x or val.y ~= pos.y or val.z ~= pos.z)) then
local is_loaded = (minetest.get_node_or_nil(val) ~= nil)
local node_name = is_loaded and minetest.get_node(pos).name or read_node_with_vm(val)
if minetest.registered_nodes[node_name] and minetest.registered_nodes[node_name].is_teleport_tube then
table.insert(receivers, val)
else
tp_tube_db[key] = nil
dirty = true
end
end
end
if dirty then
save_tube_db()
end
return receivers
end
local function update_meta(meta, can_receive)
meta:set_int("can_receive", can_receive and 1 or 0)
local cr_state = can_receive and "on" or "off"
meta:set_string("formspec","size[8.6,2.2]"..
"field[0.6,0.6;7,1;channel;"..S("Channel")..";${channel}]"..
"label[7.3,0;"..S("Receive").."]"..
"image_button[7.3,0.3;1,0.6;pipeworks_button_" .. cr_state .. ".png;cr" .. (can_receive and 0 or 1) .. ";;;false;pipeworks_button_interm.png]"..
"image[0.3,1.3;1,1;pipeworks_teleport_tube_inv.png]"..
"label[1.6,1.2;"..S("channels are public by default").."]" ..
"label[1.6,1.5;"..S("use <player>:<channel> for fully private channels").."]" ..
"label[1.6,1.8;"..S("use <player>\\;<channel> for private receivers").."]" ..
default.gui_bg..
default.gui_bg_img)
end
pipeworks.register_tube("pipeworks:teleport_tube", {
description = S("Teleporting Pneumatic Tube Segment"),
inventory_image = "pipeworks_teleport_tube_inv.png",
noctr = { "pipeworks_teleport_tube_noctr.png" },
plain = { "pipeworks_teleport_tube_plain.png" },
ends = { "pipeworks_teleport_tube_end.png" },
short = "pipeworks_teleport_tube_short.png",
node_def = {
is_teleport_tube = true,
tube = {
can_go = function(pos,node,velocity,stack)
velocity.x = 0
velocity.y = 0
velocity.z = 0
local channel = minetest.get_meta(pos):get_string("channel")
if channel == "" then return {} end
local target = get_receivers(pos, channel)
if target[1] == nil then return {} end
local d = math.random(1,#target)
pos.x = target[d].x
pos.y = target[d].y
pos.z = target[d].z
return pipeworks.meseadjlist
end
},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
update_meta(meta, true)
meta:set_string("infotext", S("unconfigured Teleportation Tube"))
end,
on_receive_fields = function(pos,formname,fields,sender)
if not fields.channel -- ignore escaping or clientside manipulation of the form
or not pipeworks.may_configure(pos, sender) then
return
end
local new_channel = tostring(fields.channel):trim()
local meta = minetest.get_meta(pos)
local can_receive = meta:get_int("can_receive")
-- check for private channels each time before actually changing anything
-- to not even allow switching between can_receive states of private channels
if new_channel ~= "" then
local sender_name = sender:get_player_name()
local name, mode = new_channel:match("^([^:;]+)([:;])")
if name and mode and name ~= sender_name then
--channels starting with '[name]:' can only be used by the named player
if mode == ":" then
minetest.chat_send_player(sender_name, S("Sorry, channel '@1' is reserved for exclusive use by @2",
new_channel, name))
return
--channels starting with '[name];' can be used by other players, but cannot be received from
elseif mode == ";" and (fields.cr1 or (can_receive ~= 0 and not fields.cr0)) then
minetest.chat_send_player(sender_name, S("Sorry, receiving from channel '@1' is reserved for @2",
new_channel, name))
return
end
end
end
local dirty = false
-- was the channel changed?
local channel = meta:get_string("channel")
if new_channel ~= channel then
channel = new_channel
meta:set_string("channel", channel)
dirty = true
end
-- test if a can_receive button was pressed
if fields.cr0 and can_receive ~= 0 then
can_receive = 0
update_meta(meta, false)
dirty = true
elseif fields.cr1 and can_receive ~= 1 then
can_receive = 1
update_meta(meta, true)
dirty = true
end
-- save if we changed something, handle the empty channel while we're at it
if dirty then
if channel ~= "" then
set_tube(pos, channel, can_receive)
local cr_description = (can_receive == 1) and "sending and receiving" or "sending"
meta:set_string("infotext", S("Teleportation Tube @1 on '@2'", cr_description, channel))
else
-- remove empty channel tubes, to not have to search through them
remove_tube(pos)
meta:set_string("infotext", S("unconfigured Teleportation Tube"))
end
end
end,
on_destruct = function(pos)
remove_tube(pos)
end
},
})
minetest.register_craft( {
output = "pipeworks:teleport_tube_1 2",
recipe = {
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" },
{ "default:desert_stone", "default:mese", "default:desert_stone" },
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" }
},
})
if minetest.get_modpath("mesecons_mvps") ~= nil then
mesecon.register_on_mvps_move(function(moved_nodes)
for _, n in ipairs(moved_nodes) do
if string.find(n.node.name, "pipeworks:teleport_tube") ~= nil then
local meta = minetest.get_meta(n.pos)
set_tube(n.pos, meta:get_string("channel"), meta:get_int("can_receive"))
end
end
end)
end
-- Expose teleport tube database API for other mods
pipeworks.tptube = {
hash = hash,
save_tube_db = save_tube_db,
get_db = function() return tp_tube_db or read_tube_db() end,
tp_tube_db_version = tp_tube_db_version
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 875 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 496 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 747 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 753 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 864 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 865 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 863 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 864 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 871 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 860 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 B

View File

@ -1,7 +1,7 @@
local S = minetest.get_translator("pipeworks") local S = minetest.get_translator("pipeworks")
minetest.register_node("pipeworks:trashcan", { minetest.register_node("pipeworks:trashcan", {
description = S("Trash Can"), description = S("Trash Can"),
drawtype = "normal", drawtype = "normal",
tiles = { tiles = {
"pipeworks_trashcan_bottom.png", "pipeworks_trashcan_bottom.png",
"pipeworks_trashcan_bottom.png", "pipeworks_trashcan_bottom.png",
@ -9,43 +9,44 @@ minetest.register_node("pipeworks:trashcan", {
"pipeworks_trashcan_side.png", "pipeworks_trashcan_side.png",
"pipeworks_trashcan_side.png", "pipeworks_trashcan_side.png",
"pipeworks_trashcan_side.png", "pipeworks_trashcan_side.png",
}, },
groups = {snappy = 3, tubedevice = 1, tubedevice_receiver = 1}, groups = {snappy = 3, tubedevice = 1, tubedevice_receiver = 1, dig_generic = 4, axey=1, handy=1, pickaxey=1},
is_ground_content = false,
_mcl_hardness=0.8,
tube = { tube = {
insert_object = function(pos, node, stack, direction) insert_object = function(pos, node, stack, direction)
return ItemStack("") return ItemStack("")
end, end,
connect_sides = {left = 1, right = 1, front = 1, back = 1, top = 1, bottom = 1}, connect_sides = {left = 1, right = 1, front = 1, back = 1, top = 1, bottom = 1},
priority = 1, -- Lower than anything else priority = 1, -- Lower than anything else
}, },
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local size = "10.2,9"
local list_background = ""
if minetest.get_modpath("i3") or minetest.get_modpath("mcl_formspec") then
list_background = "style_type[box;colors=#666]box[4.5,2;1,1;]"
end
meta:set_string("formspec", meta:set_string("formspec",
"size[8,7]".. "formspec_version[2]" ..
"item_image[0,0;1,1;pipeworks:trashcan]".. "size["..size.."]"..
"label[1,0;"..S("Trash Can").."]".. pipeworks.fs_helpers.get_prepends(size) ..
"list[context;trash;3.5,1;1,1;]".. "item_image[0.5,0.5;1,1;pipeworks:trashcan]"..
default.gui_bg.. "label[1.5,1;"..S("Trash Can").."]"..
default.gui_bg_img.. list_background..
default.gui_slots.. "list[context;trash;4.5,2;1,1;]"..
default.get_hotbar_bg(0,3) .. --"list[current_player;main;0,3;8,4;]" ..
"list[current_player;main;0,3;8,4;]" .. pipeworks.fs_helpers.get_inv(4)..
"listring[]") "listring[context;trash]"..
"listring[current_player;main]"
)
meta:set_string("infotext", S("Trash Can")) meta:set_string("infotext", S("Trash Can"))
meta:get_inventory():set_size("trash", 1) meta:get_inventory():set_size("trash", 1)
end, end,
after_place_node = pipeworks.after_place, after_place_node = pipeworks.after_place,
after_dig_node = pipeworks.after_dig, after_dig_node = pipeworks.after_dig,
on_metadata_inventory_put = function(pos, listname, index, stack, player) on_metadata_inventory_put = function(pos, listname, index, stack, player)
minetest.get_meta(pos):get_inventory():set_stack(listname, index, ItemStack("")) minetest.get_meta(pos):get_inventory():set_stack(listname, index, ItemStack(""))
end, end,
}) })
pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:trashcan"
minetest.register_craft({
output = "pipeworks:trashcan",
recipe = {
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" },
{ "default:steel_ingot", "", "default:steel_ingot" },
{ "default:steel_ingot", "default:steel_ingot", "default:steel_ingot" },
},
})

69
tubes/embedded_tube.lua Normal file
View File

@ -0,0 +1,69 @@
local materials = xcompat.materials
local S = minetest.get_translator("pipeworks")
local straight = function(pos, node, velocity, stack) return {velocity} end
local steel_tex = "[combine:16x16^[noalpha^[colorize:#D3D3D3"
if minetest.get_modpath("default") then steel_tex = "default_steel_block.png" end
-- register an embedded tube
function pipeworks.register_embedded_tube(nodename, opts)
minetest.register_node(nodename, {
description = opts.description,
tiles = {
opts.base_texture,
opts.base_texture,
opts.base_texture,
opts.base_texture,
opts.base_texture .. "^pipeworks_tube_connection_metallic.png",
opts.base_texture .. "^pipeworks_tube_connection_metallic.png",
},
paramtype = "light",
paramtype2 = "facedir",
groups = {
cracky = 1,
oddly_breakable_by_hand = 1,
tubedevice = 1,
dig_glass = 2,
pickaxey=1,
handy=1
},
is_ground_content = false,
_mcl_hardness = 0.8,
legacy_facedir_simple = true,
_sound_def = {
key = "node_sound_stone_defaults",
},
tube = {
connect_sides = {
front = 1,
back = 1
},
priority = 50,
can_go = straight,
can_insert = function(pos, node, stack, direction)
local dir = minetest.facedir_to_dir(node.param2)
return vector.equals(dir, direction) or vector.equals(vector.multiply(dir, -1), direction)
end
},
after_place_node = pipeworks.after_place,
after_dig_node = pipeworks.after_dig,
on_rotate = pipeworks.on_rotate,
})
minetest.register_craft( {
output = nodename .. " 1",
recipe = {
{ opts.base_ingredient, opts.base_ingredient, opts.base_ingredient },
{ opts.base_ingredient, "pipeworks:tube_1", opts.base_ingredient },
{ opts.base_ingredient, opts.base_ingredient, opts.base_ingredient }
},
})
pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = nodename
end
-- steelblock embedded tube
pipeworks.register_embedded_tube("pipeworks:steel_block_embedded_tube", {
description = S("Airtight steelblock embedded tube"),
base_texture = steel_tex,
base_ingredient = materials.steel_ingot
})

View File

@ -370,7 +370,10 @@ local function clean_and_weigh_digiline_message(msg, back_references)
return msg, #msg + 25 return msg, #msg + 25
elseif t == "number" then elseif t == "number" then
-- Numbers are passed by value so need not be touched, and cost 8 bytes -- Numbers are passed by value so need not be touched, and cost 8 bytes
-- as all numbers in Lua are doubles. -- as all numbers in Lua are doubles. NaN values are removed.
if msg ~= msg then
return nil, 0
end
return msg, 8 return msg, 8
elseif t == "boolean" then elseif t == "boolean" then
-- Booleans are passed by value so need not be touched, and cost 1 -- Booleans are passed by value so need not be touched, and cost 1
@ -425,7 +428,7 @@ end
-- itbl: Flat table of functions to run after sandbox cleanup, used to prevent various security hazards -- itbl: Flat table of functions to run after sandbox cleanup, used to prevent various security hazards
local function get_digiline_send(pos, itbl, send_warning) local function get_digiline_send(pos, itbl, send_warning)
if not minetest.global_exists("digilines") then return end if not minetest.get_modpath("digilines") then return end
local chan_maxlen = mesecon.setting("luacontroller_digiline_channel_maxlen", 256) local chan_maxlen = mesecon.setting("luacontroller_digiline_channel_maxlen", 256)
local maxlen = mesecon.setting("luacontroller_digiline_maxlen", 50000) local maxlen = mesecon.setting("luacontroller_digiline_maxlen", 50000)
return function(channel, msg) return function(channel, msg)
@ -666,6 +669,7 @@ local function reset_formspec(meta, code, errmsg)
code = minetest.formspec_escape(code or "") code = minetest.formspec_escape(code or "")
errmsg = minetest.formspec_escape(tostring(errmsg or "")) errmsg = minetest.formspec_escape(tostring(errmsg or ""))
meta:set_string("formspec", "size[12,10]" meta:set_string("formspec", "size[12,10]"
.."style_type[label,textarea;font=mono]"
.."background[-0.2,-0.25;12.4,10.75;jeija_luac_background.png]" .."background[-0.2,-0.25;12.4,10.75;jeija_luac_background.png]"
.."label[0.1,8.3;"..errmsg.."]" .."label[0.1,8.3;"..errmsg.."]"
.."textarea[0.2,0.2;12.2,9.5;code;;"..code.."]" .."textarea[0.2,0.2;12.2,9.5;code;;"..code.."]"
@ -813,84 +817,58 @@ local tiles_base = {
"pipeworks_mese_tube_plain_2.png", "pipeworks_mese_tube_plain_1.png", "pipeworks_mese_tube_plain_2.png", "pipeworks_mese_tube_plain_1.png",
"pipeworks_mese_tube_plain_6.png", "pipeworks_mese_tube_plain_5.png"} "pipeworks_mese_tube_plain_6.png", "pipeworks_mese_tube_plain_5.png"}
local tiles_on_off = {
R__0 = "^pipeworks_lua_tube_port_%s.png",
R_90 = "^(pipeworks_lua_tube_port_%s.png^[transformR90)",
R180 = "^(pipeworks_lua_tube_port_%s.png^[transformR180)",
R270 = "^(pipeworks_lua_tube_port_%s.png^[transformR270)"
}
local texture_alpha_mode = minetest.features.use_texture_alpha_string_modes
and "clip" or true
for red = 0, 1 do -- 0 = off 1 = on for red = 0, 1 do -- 0 = off 1 = on
for blue = 0, 1 do for blue = 0, 1 do
for yellow = 0, 1 do for yellow = 0, 1 do
for green = 0, 1 do for green = 0, 1 do
for black = 0, 1 do for black = 0, 1 do
for white = 0, 1 do for white = 0, 1 do
local cid = tostring(white)..tostring(black)..tostring(green).. local cid = white..black..green..yellow..blue..red
tostring(yellow)..tostring(blue)..tostring(red)
local node_name = BASENAME..cid local node_name = BASENAME..cid
local tiles = table.copy(tiles_base)
if red == 1 then
tiles[1] = tiles[1].."^(pipeworks_lua_tube_port_on.png^[transformR90)"
tiles[2] = tiles[2].."^(pipeworks_lua_tube_port_on.png^[transformR90)"
tiles[5] = tiles[5].."^(pipeworks_lua_tube_port_on.png^[transformR270)"
tiles[6] = tiles[6].."^(pipeworks_lua_tube_port_on.png^[transformR90)"
else
tiles[1] = tiles[1].."^(pipeworks_lua_tube_port_off.png^[transformR90)"
tiles[2] = tiles[2].."^(pipeworks_lua_tube_port_off.png^[transformR90)"
tiles[5] = tiles[5].."^(pipeworks_lua_tube_port_off.png^[transformR270)"
tiles[6] = tiles[6].."^(pipeworks_lua_tube_port_off.png^[transformR90)"
end
if blue == 1 then
tiles[1] = tiles[1].."^(pipeworks_lua_tube_port_on.png^[transformR270)"
tiles[2] = tiles[2].."^(pipeworks_lua_tube_port_on.png^[transformR270)"
tiles[5] = tiles[5].."^(pipeworks_lua_tube_port_on.png^[transformR90)"
tiles[6] = tiles[6].."^(pipeworks_lua_tube_port_on.png^[transformR270)"
else
tiles[1] = tiles[1].."^(pipeworks_lua_tube_port_off.png^[transformR270)"
tiles[2] = tiles[2].."^(pipeworks_lua_tube_port_off.png^[transformR270)"
tiles[5] = tiles[5].."^(pipeworks_lua_tube_port_off.png^[transformR90)"
tiles[6] = tiles[6].."^(pipeworks_lua_tube_port_off.png^[transformR270)"
end
if yellow == 1 then
tiles[3] = tiles[3].."^(pipeworks_lua_tube_port_on.png^[transformR180)"
tiles[4] = tiles[4].."^(pipeworks_lua_tube_port_on.png^[transformR180)"
tiles[5] = tiles[5].."^(pipeworks_lua_tube_port_on.png^[transformR180)"
tiles[6] = tiles[6].."^(pipeworks_lua_tube_port_on.png^[transformR180)"
else
tiles[3] = tiles[3].."^(pipeworks_lua_tube_port_off.png^[transformR180)"
tiles[4] = tiles[4].."^(pipeworks_lua_tube_port_off.png^[transformR180)"
tiles[5] = tiles[5].."^(pipeworks_lua_tube_port_off.png^[transformR180)"
tiles[6] = tiles[6].."^(pipeworks_lua_tube_port_off.png^[transformR180)"
end
if green == 1 then
tiles[3] = tiles[3].."^pipeworks_lua_tube_port_on.png"
tiles[4] = tiles[4].."^pipeworks_lua_tube_port_on.png"
tiles[5] = tiles[5].."^pipeworks_lua_tube_port_on.png"
tiles[6] = tiles[6].."^pipeworks_lua_tube_port_on.png"
else
tiles[3] = tiles[3].."^pipeworks_lua_tube_port_off.png"
tiles[4] = tiles[4].."^pipeworks_lua_tube_port_off.png"
tiles[5] = tiles[5].."^pipeworks_lua_tube_port_off.png"
tiles[6] = tiles[6].."^pipeworks_lua_tube_port_off.png"
end
if black == 1 then
tiles[1] = tiles[1].."^(pipeworks_lua_tube_port_on.png^[transformR180)"
tiles[2] = tiles[2].."^pipeworks_lua_tube_port_on.png"
tiles[3] = tiles[3].."^(pipeworks_lua_tube_port_on.png^[transformR90)"
tiles[4] = tiles[4].."^(pipeworks_lua_tube_port_on.png^[transformR270)"
else
tiles[1] = tiles[1].."^(pipeworks_lua_tube_port_off.png^[transformR180)"
tiles[2] = tiles[2].."^pipeworks_lua_tube_port_off.png"
tiles[3] = tiles[3].."^(pipeworks_lua_tube_port_off.png^[transformR90)"
tiles[4] = tiles[4].."^(pipeworks_lua_tube_port_off.png^[transformR270)"
end
if white == 1 then
tiles[1] = tiles[1].."^pipeworks_lua_tube_port_on.png"
tiles[2] = tiles[2].."^(pipeworks_lua_tube_port_on.png^[transformR180)"
tiles[3] = tiles[3].."^(pipeworks_lua_tube_port_on.png^[transformR270)"
tiles[4] = tiles[4].."^(pipeworks_lua_tube_port_on.png^[transformR90)"
else
tiles[1] = tiles[1].."^pipeworks_lua_tube_port_off.png"
tiles[2] = tiles[2].."^(pipeworks_lua_tube_port_off.png^[transformR180)"
tiles[3] = tiles[3].."^(pipeworks_lua_tube_port_off.png^[transformR270)"
tiles[4] = tiles[4].."^(pipeworks_lua_tube_port_off.png^[transformR90)"
end
local groups = {snappy = 3, tube = 1, tubedevice = 1, overheat = 1} local tiles = table.copy(tiles_base)
-- Red
tiles[1] = tiles[1]..tiles_on_off.R_90:format(red == 1 and "on" or "off");
tiles[2] = tiles[2]..tiles_on_off.R_90:format(red == 1 and "on" or "off");
tiles[5] = tiles[5]..tiles_on_off.R270:format(red == 1 and "on" or "off");
tiles[6] = tiles[6]..tiles_on_off.R_90:format(red == 1 and "on" or "off");
-- Blue
tiles[1] = tiles[1]..tiles_on_off.R270:format(blue == 1 and "on" or "off");
tiles[2] = tiles[2]..tiles_on_off.R270:format(blue == 1 and "on" or "off");
tiles[5] = tiles[5]..tiles_on_off.R_90:format(blue == 1 and "on" or "off");
tiles[6] = tiles[6]..tiles_on_off.R270:format(blue == 1 and "on" or "off");
-- Yellow
tiles[1] = tiles[1]..tiles_on_off.R180:format(yellow == 1 and "on" or "off");
tiles[2] = tiles[2]..tiles_on_off.R180:format(yellow == 1 and "on" or "off");
tiles[5] = tiles[5]..tiles_on_off.R180:format(yellow == 1 and "on" or "off");
tiles[6] = tiles[6]..tiles_on_off.R180:format(yellow == 1 and "on" or "off");
-- Green
tiles[3] = tiles[3]..tiles_on_off.R__0:format(green == 1 and "on" or "off");
tiles[4] = tiles[4]..tiles_on_off.R__0:format(green == 1 and "on" or "off");
tiles[5] = tiles[5]..tiles_on_off.R__0:format(green == 1 and "on" or "off");
tiles[6] = tiles[6]..tiles_on_off.R__0:format(green == 1 and "on" or "off");
-- Black
tiles[1] = tiles[1]..tiles_on_off.R180:format(black == 1 and "on" or "off");
tiles[2] = tiles[2]..tiles_on_off.R__0:format(black == 1 and "on" or "off");
tiles[3] = tiles[3]..tiles_on_off.R_90:format(black == 1 and "on" or "off");
tiles[4] = tiles[4]..tiles_on_off.R270:format(black == 1 and "on" or "off");
-- White
tiles[1] = tiles[1]..tiles_on_off.R__0:format(white == 1 and "on" or "off");
tiles[2] = tiles[2]..tiles_on_off.R180:format(white == 1 and "on" or "off");
tiles[3] = tiles[3]..tiles_on_off.R270:format(white == 1 and "on" or "off");
tiles[4] = tiles[4]..tiles_on_off.R_90:format(white == 1 and "on" or "off");
local groups = {snappy = 3, tube = 1, tubedevice = 1, overheat = 1, dig_generic = 4, axey=1, handy=1, pickaxey=1}
if red + blue + yellow + green + black + white ~= 0 then if red + blue + yellow + green + black + white ~= 0 then
groups.not_in_creative_inventory = 1 groups.not_in_creative_inventory = 1
end end
@ -933,16 +911,20 @@ for white = 0, 1 do
description = "Lua controlled Tube", description = "Lua controlled Tube",
drawtype = "nodebox", drawtype = "nodebox",
tiles = tiles, tiles = tiles,
use_texture_alpha = texture_alpha_mode,
paramtype = "light", paramtype = "light",
is_ground_content = false, is_ground_content = false,
groups = groups, groups = groups,
_mcl_hardness=0.8,
drop = BASENAME.."000000", drop = BASENAME.."000000",
sunlight_propagates = true, sunlight_propagates = true,
selection_box = selection_box, selection_box = selection_box,
node_box = node_box, node_box = node_box,
on_construct = reset_meta, on_construct = reset_meta,
on_receive_fields = on_receive_fields, on_receive_fields = on_receive_fields,
sounds = default.node_sound_wood_defaults(), _sound_def = {
key = "node_sound_wood_defaults",
},
mesecons = mesecons, mesecons = mesecons,
digiline = digiline, digiline = digiline,
-- Virtual portstates are the ports that -- Virtual portstates are the ports that
@ -966,10 +948,10 @@ for white = 0, 1 do
tube = { tube = {
connect_sides = {front = 1, back = 1, left = 1, right = 1, top = 1, bottom = 1}, connect_sides = {front = 1, back = 1, left = 1, right = 1, top = 1, bottom = 1},
priority = 50, priority = 50,
can_go = function(pos, node, velocity, stack) can_go = function(pos, node, velocity, stack, tags)
local src = {name = nil} local src = {name = nil}
-- add color of the incoming tube explicitly; referring to rules, in case they change later -- add color of the incoming tube explicitly; referring to rules, in case they change later
for color, rule in pairs(rules) do for _, rule in pairs(rules) do
if (-velocity.x == rule.x and -velocity.y == rule.y and -velocity.z == rule.z) then if (-velocity.x == rule.x and -velocity.y == rule.y and -velocity.z == rule.z) then
src.name = rule.name src.name = rule.name
break break
@ -981,19 +963,40 @@ for white = 0, 1 do
itemstring = stack:to_string(), itemstring = stack:to_string(),
item = stack:to_table(), item = stack:to_table(),
velocity = velocity, velocity = velocity,
tags = table.copy(tags),
side = src.name,
}) })
if not succ or type(msg) ~= "string" then if not succ then
return go_back(velocity) return go_back(velocity)
end end
local r = rules[msg] if type(msg) == "string" then
return r and {r} or go_back(velocity) local side = rules[msg]
return side and {side} or go_back(velocity)
elseif type(msg) == "table" then
if pipeworks.enable_item_tags then
local new_tags
if type(msg.tags) == "table" or type(msg.tags) == "string" then
new_tags = pipeworks.sanitize_tags(msg.tags)
elseif type(msg.tag) == "string" then
new_tags = pipeworks.sanitize_tags({msg.tag})
end
if new_tags then
for i=1, math.max(#tags, #new_tags) do
tags[i] = new_tags[i]
end
end
end
local side = rules[msg.side]
return side and {side} or go_back(velocity)
end
return go_back(velocity)
end, end,
}, },
after_place_node = pipeworks.after_place, after_place_node = pipeworks.after_place,
on_blast = function(pos, intensity) on_blast = function(pos, intensity)
if not intensity or intensity > 1 + 3^0.5 then if not intensity or intensity > 1 + 3^0.5 then
minetest.remove_node(pos) minetest.remove_node(pos)
return {string.format("%s_%s", name, dropname)} return
end end
minetest.swap_node(pos, {name = "pipeworks:broken_tube_1"}) minetest.swap_node(pos, {name = "pipeworks:broken_tube_1"})
pipeworks.scan_for_tube_objects(pos) pipeworks.scan_for_tube_objects(pos)
@ -1006,6 +1009,8 @@ end
end end
end end
pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = BASENAME.."000000"
------------------------------------ ------------------------------------
-- Overheated Lua controlled Tube -- -- Overheated Lua controlled Tube --
------------------------------------ ------------------------------------
@ -1039,17 +1044,21 @@ tiles_burnt[4] = tiles_burnt[4].."^(pipeworks_lua_tube_port_burnt.png^[transform
minetest.register_node(BASENAME .. "_burnt", { minetest.register_node(BASENAME .. "_burnt", {
drawtype = "nodebox", drawtype = "nodebox",
tiles = tiles_burnt, tiles = tiles_burnt,
use_texture_alpha = texture_alpha_mode,
is_burnt = true, is_burnt = true,
paramtype = "light", paramtype = "light",
is_ground_content = false, is_ground_content = false,
groups = {snappy = 3, tube = 1, tubedevice = 1, not_in_creative_inventory=1}, groups = {snappy = 3, tube = 1, tubedevice = 1, not_in_creative_inventory=1, dig_generic = 4, axey=1, handy=1, pickaxey=1},
_mcl_hardness=0.8,
drop = BASENAME.."000000", drop = BASENAME.."000000",
sunlight_propagates = true, sunlight_propagates = true,
selection_box = selection_box, selection_box = selection_box,
node_box = node_box, node_box = node_box,
on_construct = reset_meta, on_construct = reset_meta,
on_receive_fields = on_receive_fields, on_receive_fields = on_receive_fields,
sounds = default.node_sound_wood_defaults(), _sound_def = {
key = "node_sound_wood_defaults",
},
virtual_portstates = {red = false, blue = false, yellow = false, virtual_portstates = {red = false, blue = false, yellow = false,
green = false, black = false, white = false}, green = false, black = false, white = false},
mesecons = { mesecons = {
@ -1070,7 +1079,7 @@ minetest.register_node(BASENAME .. "_burnt", {
on_blast = function(pos, intensity) on_blast = function(pos, intensity)
if not intensity or intensity > 1 + 3^0.5 then if not intensity or intensity > 1 + 3^0.5 then
minetest.remove_node(pos) minetest.remove_node(pos)
return {string.format("%s_%s", name, dropname)} return
end end
minetest.swap_node(pos, {name = "pipeworks:broken_tube_1"}) minetest.swap_node(pos, {name = "pipeworks:broken_tube_1"})
pipeworks.scan_for_tube_objects(pos) pipeworks.scan_for_tube_objects(pos)

View File

@ -0,0 +1,53 @@
local S = minetest.get_translator("pipeworks")
local straight = function(pos, node, velocity, stack) return {velocity} end
local pane_box = {
type = "fixed",
fixed = {
{ -9/64, -9/64, -8/16, 9/64, 9/64, 8/16 }, -- tube
{ -8/16, -8/16, -1/16, 8/16, 8/16, 1/16 } -- pane
}
}
local texture_alpha_mode = minetest.features.use_texture_alpha_string_modes
and "clip" or true
minetest.register_node("pipeworks:steel_pane_embedded_tube", {
drawtype = "nodebox",
description = S("Airtight panel embedded tube"),
tiles = {
pipeworks.make_tube_tile("pipeworks_pane_embedded_tube_sides.png^[transformR90"),
pipeworks.make_tube_tile("pipeworks_pane_embedded_tube_sides.png^[transformR90"),
pipeworks.make_tube_tile("pipeworks_pane_embedded_tube_sides.png"),
pipeworks.make_tube_tile("pipeworks_pane_embedded_tube_sides.png"),
pipeworks.make_tube_tile("pipeworks_pane_embedded_tube_ends.png"),
pipeworks.make_tube_tile("pipeworks_pane_embedded_tube_ends.png"),
},
use_texture_alpha = texture_alpha_mode,
node_box = pane_box,
selection_box = pane_box,
collision_box = pane_box,
paramtype = "light",
paramtype2 = "facedir",
groups = {cracky=1, oddly_breakable_by_hand = 1, tubedevice = 1, dig_glass = 2, pickaxey=1, handy=1},
is_ground_content = false,
_mcl_hardness=0.8,
legacy_facedir_simple = true,
_sound_def = {
key = "node_sound_stone_defaults",
},
tube = {
connect_sides = {front = 1, back = 1,},
priority = 50,
can_go = straight,
can_insert = function(pos, node, stack, direction)
local dir = minetest.facedir_to_dir(node.param2)
return vector.equals(dir, direction) or vector.equals(vector.multiply(dir, -1), direction)
end,
},
after_place_node = pipeworks.after_place,
after_dig_node = pipeworks.after_dig,
on_rotate = pipeworks.on_rotate,
})
pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:steel_pane_embedded_tube"

View File

@ -26,6 +26,11 @@ local texture_mt = {
end end
} }
-- This will remove any semi-transparent pixels
-- because that is still buggy in Minetest, force this as default
local texture_alpha_mode = minetest.features.use_texture_alpha_string_modes
and "clip" or true
local register_one_tube = function(name, tname, dropname, desc, plain, noctrs, ends, short, inv, special, connects, style) local register_one_tube = function(name, tname, dropname, desc, plain, noctrs, ends, short, inv, special, connects, style)
noctrs = noctrs or default_noctrs noctrs = noctrs or default_noctrs
setmetatable(noctrs, texture_mt) setmetatable(noctrs, texture_mt)
@ -56,13 +61,13 @@ local register_one_tube = function(name, tname, dropname, desc, plain, noctrs, e
outimgs[vti[v]] = ends[v] outimgs[vti[v]] = ends[v]
end end
local tgroups = {snappy = 3, tube = 1, tubedevice = 1, not_in_creative_inventory = 1} local tgroups = {snappy = 3, tube = 1, tubedevice = 1, not_in_creative_inventory = 1, dig_generic = 4, axey=1, handy=1, pickaxey=1}
local tubedesc = string.format("%s %s", desc, dump(connects)) local tubedesc = string.format("%s %s", desc, dump(connects))
local iimg = type(plain[1]) == "table" and plain[1].name or plain[1] local iimg = type(plain[1]) == "table" and plain[1].name or plain[1]
local wscale = {x = 1, y = 1, z = 1} local wscale = {x = 1, y = 1, z = 1}
if #connects == 0 then if #connects == 0 then
tgroups = {snappy = 3, tube = 1, tubedevice = 1} tgroups = {snappy = 3, tube = 1, tubedevice = 1, dig_generic = 4, axey=1, handy=1, pickaxey=1}
tubedesc = desc tubedesc = desc
iimg=inv iimg=inv
outimgs = { outimgs = {
@ -75,6 +80,10 @@ local register_one_tube = function(name, tname, dropname, desc, plain, noctrs, e
wscale = {x = 1, y = 1, z = 0.01} wscale = {x = 1, y = 1, z = 0.01}
end end
for i, tile in ipairs(outimgs) do
outimgs[i] = pipeworks.make_tube_tile(tile)
end
local rname = string.format("%s_%s", name, tname) local rname = string.format("%s_%s", name, tname)
table.insert(tubenodes, rname) table.insert(tubenodes, rname)
@ -82,6 +91,7 @@ local register_one_tube = function(name, tname, dropname, desc, plain, noctrs, e
description = tubedesc, description = tubedesc,
drawtype = "nodebox", drawtype = "nodebox",
tiles = outimgs, tiles = outimgs,
use_texture_alpha = texture_alpha_mode,
sunlight_propagates = true, sunlight_propagates = true,
inventory_image = iimg, inventory_image = iimg,
wield_image = iimg, wield_image = iimg,
@ -96,7 +106,11 @@ local register_one_tube = function(name, tname, dropname, desc, plain, noctrs, e
fixed = outboxes fixed = outboxes
}, },
groups = tgroups, groups = tgroups,
sounds = default.node_sound_wood_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_wood_defaults",
},
walkable = true, walkable = true,
stack_max = 99, stack_max = 99,
basename = name, basename = name,
@ -107,6 +121,18 @@ local register_one_tube = function(name, tname, dropname, desc, plain, noctrs, e
connect_sides = {front = 1, back = 1, left = 1, right = 1, top = 1, bottom = 1}, connect_sides = {front = 1, back = 1, left = 1, right = 1, top = 1, bottom = 1},
priority = 50 priority = 50
}, },
on_punch = function(pos, node, player, pointed)
local playername = player:get_player_name()
if minetest.is_protected(pos, playername) and not minetest.check_player_privs(playername, {protection_bypass=true}) then
return minetest.node_punch(pos, node, player, pointed)
end
if pipeworks.check_and_wear_hammer(player) then
local wieldname = player:get_wielded_item():get_name()
pipeworks.logger(string.format("%s struck a tube at %s with %s to break it.", playername, minetest.pos_to_string(pos), wieldname))
pipeworks.break_tube(pos)
end
return minetest.node_punch(pos, node, player, pointed)
end,
after_place_node = pipeworks.after_place, after_place_node = pipeworks.after_place,
after_dig_node = pipeworks.after_dig, after_dig_node = pipeworks.after_dig,
on_rotate = false, on_rotate = false,
@ -182,6 +208,7 @@ local register_all_tubes = function(name, desc, plain, noctrs, ends, short, inv,
end end
end end
end end
pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = name.."_000000"
else else
-- 6d tubes: uses only 10 nodes instead of 64, but the textures must be rotated -- 6d tubes: uses only 10 nodes instead of 64, but the textures must be rotated
local cconnects = {{}, {1}, {1, 2}, {1, 3}, {1, 3, 5}, {1, 2, 3}, {1, 2, 3, 5}, {1, 2, 3, 4}, {1, 2, 3, 4, 5}, {1, 2, 3, 4, 5, 6}} local cconnects = {{}, {1}, {1, 2}, {1, 3}, {1, 3, 5}, {1, 2, 3}, {1, 2, 3, 5}, {1, 2, 3, 4}, {1, 2, 3, 4, 5}, {1, 2, 3, 4, 5, 6}}
@ -201,9 +228,11 @@ local register_all_tubes = function(name, desc, plain, noctrs, ends, short, inv,
description = S("Pneumatic tube segment (legacy)"), description = S("Pneumatic tube segment (legacy)"),
after_place_node = pipeworks.after_place, after_place_node = pipeworks.after_place,
groups = {not_in_creative_inventory = 1, tube_to_update = 1, tube = 1}, groups = {not_in_creative_inventory = 1, tube_to_update = 1, tube = 1},
is_ground_content = false,
tube = {connect_sides = {front = 1, back = 1, left = 1, right = 1, top = 1, bottom = 1}}, tube = {connect_sides = {front = 1, back = 1, left = 1, right = 1, top = 1, bottom = 1}},
drop = name.."_1", drop = name.."_1",
}) })
pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = name.."_1"
table.insert(tubenodes, cname) table.insert(tubenodes, cname)
for xm = 0, 1 do for xm = 0, 1 do
for xp = 0, 1 do for xp = 0, 1 do

View File

@ -10,6 +10,35 @@ minetest.register_craft( {
}, },
}) })
-- The hammers that can be used to break/repair tubes
local allowed_hammers = {
"anvil:hammer",
"cottages:hammer",
"glooptest:hammer_steel",
"glooptest:hammer_bronze",
"glooptest:hammer_diamond",
"glooptest:hammer_mese",
"glooptest:hammer_alatro",
"glooptest:hammer_arol"
}
-- Convert the above list to a format that's easier to look up
for _,hammer in ipairs(allowed_hammers) do
allowed_hammers[hammer] = true
end
-- Check if the player is holding a suitable hammer or not - if they are, apply wear to it
function pipeworks.check_and_wear_hammer(player)
local itemstack = player:get_wielded_item()
local wieldname = itemstack:get_name()
if allowed_hammers[wieldname] then
itemstack:add_wear(1000)
player:set_wielded_item(itemstack)
return true
end
return false
end
local nodecolor = 0xffff3030 local nodecolor = 0xffff3030
pipeworks.register_tube("pipeworks:broken_tube", { pipeworks.register_tube("pipeworks:broken_tube", {
@ -21,6 +50,7 @@ pipeworks.register_tube("pipeworks:broken_tube", {
node_def = { node_def = {
drop = "pipeworks:tube_1", drop = "pipeworks:tube_1",
groups = {not_in_creative_inventory = 1, tubedevice_receiver = 1}, groups = {not_in_creative_inventory = 1, tubedevice_receiver = 1},
is_ground_content = false,
tube = { tube = {
insert_object = function(pos, node, stack, direction) insert_object = function(pos, node, stack, direction)
minetest.item_drop(stack, nil, pos) minetest.item_drop(stack, nil, pos)
@ -35,31 +65,50 @@ pipeworks.register_tube("pipeworks:broken_tube", {
local itemstack = puncher:get_wielded_item() local itemstack = puncher:get_wielded_item()
local wieldname = itemstack:get_name() local wieldname = itemstack:get_name()
local playername = puncher:get_player_name() local playername = puncher:get_player_name()
local log_msg = playername.." struck a broken tube at "..minetest.pos_to_string(pos).."\n" local log_msg = playername.." struck a broken tube at "..minetest.pos_to_string(pos).."\n "
if wieldname == "anvil:hammer" local meta = minetest.get_meta(pos)
or wieldname == "cottages:hammer" local was_node = minetest.deserialize(meta:get_string("the_tube_was"))
or wieldname == "glooptest:hammer_steel" if not was_node then
or wieldname == "glooptest:hammer_bronze" pipeworks.logger(log_msg.."but it can't be repaired.")
or wieldname == "glooptest:hammer_diamond" return
or wieldname == "glooptest:hammer_mese" end
or wieldname == "glooptest:hammer_alatro" if not pipeworks.check_and_wear_hammer(puncher) then
or wieldname == "glooptest:hammer_arol" then if wieldname == "" then
local meta = minetest.get_meta(pos) pipeworks.logger(log_msg.."by hand. It's not very effective.")
local was_node = minetest.deserialize(meta:get_string("the_tube_was")) if minetest.settings:get_bool("enable_damage") then
if was_node and was_node ~= "" then minetest.chat_send_player(playername,S("Broken tubes may be a bit sharp. Perhaps try with a hammer?"))
pipeworks.logger(log_msg.." with "..wieldname.." to repair it.") puncher:set_hp(puncher:get_hp()-1)
end
else
pipeworks.logger(log_msg.."with "..wieldname.." but that tool is too weak.")
end
return
end
log_msg = log_msg.."with "..wieldname.." to repair it"
local nodedef = minetest.registered_nodes[was_node.name]
if nodedef then
pipeworks.logger(log_msg..".")
if nodedef.tube and nodedef.tube.on_repair then
nodedef.tube.on_repair(pos, was_node)
else
minetest.swap_node(pos, { name = was_node.name, param2 = was_node.param2 }) minetest.swap_node(pos, { name = was_node.name, param2 = was_node.param2 })
pipeworks.scan_for_tube_objects(pos) pipeworks.scan_for_tube_objects(pos)
itemstack:add_wear(1000)
puncher:set_wielded_item(itemstack)
return itemstack
else
pipeworks.logger(log_msg.." but it can't be repaired.")
end end
meta:set_string("the_tube_was", "")
else else
pipeworks.logger(log_msg.." with "..wieldname.." but that tool is too weak.") pipeworks.logger(log_msg.." but original node "..was_node.name.." is not registered anymore.")
minetest.chat_send_player(playername, S("This tube cannot be repaired."))
end end
end end,
allow_metadata_inventory_put = function()
return 0
end,
allow_metadata_inventory_move = function()
return 0
end,
allow_metadata_inventory_take = function()
return 0
end,
} }
}) })
@ -79,14 +128,6 @@ if pipeworks.enable_priority_tube then
tube = { priority = 150 } -- higher than tubedevices (100) tube = { priority = 150 } -- higher than tubedevices (100)
}, },
}) })
minetest.register_craft( {
output = "pipeworks:priority_tube_1 6",
recipe = {
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" },
{ "default:gold_ingot", "", "default:gold_ingot" },
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" }
},
})
end end
if pipeworks.enable_accelerator_tube then if pipeworks.enable_accelerator_tube then
@ -104,14 +145,6 @@ if pipeworks.enable_accelerator_tube then
end} end}
}, },
}) })
minetest.register_craft( {
output = "pipeworks:accelerator_tube_1 2",
recipe = {
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" },
{ "default:mese_crystal_fragment", "default:steel_ingot", "default:mese_crystal_fragment" },
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" }
},
})
end end
if pipeworks.enable_crossing_tube then if pipeworks.enable_crossing_tube then
@ -126,28 +159,32 @@ if pipeworks.enable_crossing_tube then
tube = {can_go = function(pos, node, velocity, stack) return {velocity} end } tube = {can_go = function(pos, node, velocity, stack) return {velocity} end }
}, },
}) })
minetest.register_craft( {
output = "pipeworks:crossing_tube_1 5",
recipe = {
{ "", "pipeworks:tube_1", "" },
{ "pipeworks:tube_1", "pipeworks:tube_1", "pipeworks:tube_1" },
{ "", "pipeworks:tube_1", "" }
},
})
end end
local texture_alpha_mode = minetest.features.use_texture_alpha_string_modes
and "clip" or true
if pipeworks.enable_one_way_tube then if pipeworks.enable_one_way_tube then
local tiles = {"pipeworks_one_way_tube_top.png", "pipeworks_one_way_tube_top.png", "pipeworks_one_way_tube_output.png",
"pipeworks_one_way_tube_input.png", "pipeworks_one_way_tube_side.png", "pipeworks_one_way_tube_top.png"}
for i, tile in ipairs(tiles) do
tiles[i] = pipeworks.make_tube_tile(tile)
end
minetest.register_node("pipeworks:one_way_tube", { minetest.register_node("pipeworks:one_way_tube", {
description = S("One way tube"), description = S("One way tube"),
tiles = {"pipeworks_one_way_tube_top.png", "pipeworks_one_way_tube_top.png", "pipeworks_one_way_tube_output.png", tiles = tiles,
"pipeworks_one_way_tube_input.png", "pipeworks_one_way_tube_side.png", "pipeworks_one_way_tube_top.png"}, use_texture_alpha = texture_alpha_mode,
paramtype2 = "facedir", paramtype2 = "facedir",
drawtype = "nodebox", drawtype = "nodebox",
paramtype = "light", paramtype = "light",
node_box = {type = "fixed", node_box = {type = "fixed",
fixed = {{-1/2, -9/64, -9/64, 1/2, 9/64, 9/64}}}, fixed = {{-1/2, -9/64, -9/64, 1/2, 9/64, 9/64}}},
groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 2, tubedevice = 1}, groups = {snappy = 2, choppy = 2, oddly_breakable_by_hand = 2, tubedevice = 1, axey=1, handy=1, pickaxey=1},
sounds = default.node_sound_wood_defaults(), is_ground_content = false,
_mcl_hardness=0.8,
_sound_def = {
key = "node_sound_wood_defaults",
},
tube = { tube = {
connect_sides = {left = 1, right = 1}, connect_sides = {left = 1, right = 1},
can_go = function(pos, node, velocity, stack) can_go = function(pos, node, velocity, stack)
@ -165,12 +202,5 @@ if pipeworks.enable_one_way_tube then
check_for_pole = pipeworks.check_for_vert_tube, check_for_pole = pipeworks.check_for_vert_tube,
check_for_horiz_pole = pipeworks.check_for_horiz_tube check_for_horiz_pole = pipeworks.check_for_horiz_tube
}) })
minetest.register_craft({ pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:one_way_tube"
output = "pipeworks:one_way_tube 2",
recipe = {
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" },
{ "group:stick", "default:mese_crystal", "basic_materials:plastic_sheet" },
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" }
},
})
end end

View File

@ -1,6 +1,18 @@
local S = minetest.get_translator("pipeworks") local S = minetest.get_translator("pipeworks")
if pipeworks.enable_detector_tube then
local detector_tube_step = 5 * tonumber(minetest.settings:get("dedicated_server_step")) -- the minetest.after() calls below can sometimes trigger after a tube
-- breaks, at which point item_exit() is no longer valid, so we have to make
-- sure that there even IS a callback to run, first.
local function after_break(pos)
local name = minetest.get_node(pos).name
if minetest.registered_nodes[name].item_exit then
minetest.registered_nodes[name].item_exit(pos)
end
end
if minetest.get_modpath("mesecons") and pipeworks.enable_detector_tube then
local detector_tube_step = 5 * (tonumber(minetest.settings:get("dedicated_server_step")) or 0.09)
pipeworks.register_tube("pipeworks:detector_tube_on", { pipeworks.register_tube("pipeworks:detector_tube_on", {
description = S("Detecting Pneumatic Tube Segment on"), description = S("Detecting Pneumatic Tube Segment on"),
inventory_image = "pipeworks_detector_tube_inv.png", inventory_image = "pipeworks_detector_tube_inv.png",
@ -8,11 +20,10 @@ if pipeworks.enable_detector_tube then
node_def = { node_def = {
tube = {can_go = function(pos, node, velocity, stack) tube = {can_go = function(pos, node, velocity, stack)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local name = minetest.get_node(pos).name
local nitems = meta:get_int("nitems")+1 local nitems = meta:get_int("nitems")+1
meta:set_int("nitems", nitems) meta:set_int("nitems", nitems)
local saved_pos = vector.new(pos) local saved_pos = vector.new(pos)
minetest.after(detector_tube_step, minetest.registered_nodes[name].item_exit, saved_pos) minetest.after(detector_tube_step, after_break, saved_pos)
return pipeworks.notvel(pipeworks.meseadjlist,velocity) return pipeworks.notvel(pipeworks.meseadjlist,velocity)
end}, end},
groups = {mesecon = 2, not_in_creative_inventory = 1}, groups = {mesecon = 2, not_in_creative_inventory = 1},
@ -34,9 +45,7 @@ if pipeworks.enable_detector_tube then
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
meta:set_int("nitems", 1) meta:set_int("nitems", 1)
local name = minetest.get_node(pos).name minetest.after(detector_tube_step, after_break, pos)
local saved_pos = vector.new(pos)
minetest.after(detector_tube_step, minetest.registered_nodes[name].item_exit, saved_pos)
end, end,
}, },
}) })
@ -87,13 +96,20 @@ if digiline_enabled and pipeworks.enable_digiline_detector_tube then
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
meta:set_string("formspec", meta:set_string("formspec",
"size[8.6,2.2]".. "size[8.5,2.2]"..
"field[0.6,0.6;8,1;channel;"..S("Channel")..";${channel}]".. "image[0.2,0;1,1;pipeworks_digiline_detector_tube_inv.png]"..
"image[0.3,1.3;1,1;pipeworks_digiline_detector_tube_inv.png]".. "label[1.2,0.2;"..S("Digiline Detecting Tube").."]"..
"label[1.6,1.2;"..S("Digiline Detecting Tube").."]" "field[0.5,1.6;4.6,1;channel;"..S("Channel")..";${channel}]"..
"button[4.8,1.3;1.5,1;set_channel;"..S("Set").."]"..
"button_exit[6.3,1.3;2,1;close;"..S("Close").."]"
) )
end, end,
on_receive_fields = function(pos, formname, fields, sender) on_receive_fields = function(pos, formname, fields, sender)
if (fields.quit and not fields.key_enter_field)
or (fields.key_enter_field ~= "channel" and not fields.set_channel)
or not pipeworks.may_configure(pos, sender) then
return
end
if fields.channel then if fields.channel then
minetest.get_meta(pos):set_string("channel", fields.channel) minetest.get_meta(pos):set_string("channel", fields.channel)
end end
@ -121,7 +137,7 @@ if digiline_enabled and pipeworks.enable_digiline_detector_tube then
}) })
end end
if pipeworks.enable_conductor_tube then if minetest.get_modpath("mesecons") and pipeworks.enable_conductor_tube then
pipeworks.register_tube("pipeworks:conductor_tube_off", { pipeworks.register_tube("pipeworks:conductor_tube_off", {
description = S("Conducting Pneumatic Tube Segment"), description = S("Conducting Pneumatic Tube Segment"),
inventory_image = "pipeworks_conductor_tube_inv.png", inventory_image = "pipeworks_conductor_tube_inv.png",

View File

@ -16,29 +16,43 @@ if pipeworks.enable_mese_tube then
local buttons_formspec = "" local buttons_formspec = ""
for i = 0, 5 do for i = 0, 5 do
buttons_formspec = buttons_formspec .. fs_helpers.cycling_button(meta, buttons_formspec = buttons_formspec .. fs_helpers.cycling_button(meta,
"image_button[7,"..(i+0.2)..";1,0.6", "l"..(i+1).."s", "image_button[9,"..(i+(i*0.25)+0.5)..";1,0.6", "l"..(i+1).."s",
{ {
pipeworks.button_off, pipeworks.button_off,
pipeworks.button_on pipeworks.button_on
} }
) )
end end
local list_backgrounds = ""
if minetest.get_modpath("i3") or minetest.get_modpath("mcl_formspec") then
list_backgrounds = "style_type[box;colors=#666]"
for i=0, 5 do
for j=0, 5 do
list_backgrounds = list_backgrounds .. "box[".. 1.5+(i*1.25) ..",".. 0.25+(j*1.25) ..";1,1;]"
end
end
end
local size = "10.2,13"
meta:set_string("formspec", meta:set_string("formspec",
"size[8,11]".. "formspec_version[2]"..
"list[context;line1;1,0;6,1;]".. "size["..size.."]"..
"list[context;line2;1,1;6,1;]".. pipeworks.fs_helpers.get_prepends(size)..
"list[context;line3;1,2;6,1;]".. "list[context;line1;1.5,0.25;6,1;]"..
"list[context;line4;1,3;6,1;]".. "list[context;line2;1.5,1.50;6,1;]"..
"list[context;line5;1,4;6,1;]".. "list[context;line3;1.5,2.75;6,1;]"..
"list[context;line6;1,5;6,1;]".. "list[context;line4;1.5,4.00;6,1;]"..
"image[0,0;1,1;pipeworks_white.png]".. "list[context;line5;1.5,5.25;6,1;]"..
"image[0,1;1,1;pipeworks_black.png]".. "list[context;line6;1.5,6.50;6,1;]"..
"image[0,2;1,1;pipeworks_green.png]".. list_backgrounds..
"image[0,3;1,1;pipeworks_yellow.png]".. "image[0.22,0.25;1,1;pipeworks_white.png]"..
"image[0,4;1,1;pipeworks_blue.png]".. "image[0.22,1.50;1,1;pipeworks_black.png]"..
"image[0,5;1,1;pipeworks_red.png]".. "image[0.22,2.75;1,1;pipeworks_green.png]"..
"image[0.22,4.00;1,1;pipeworks_yellow.png]"..
"image[0.22,5.25;1,1;pipeworks_blue.png]"..
"image[0.22,6.50;1,1;pipeworks_red.png]"..
buttons_formspec.. buttons_formspec..
"list[current_player;main;0,7;8,4;]" .. --"list[current_player;main;0,8;8,4;]" ..
pipeworks.fs_helpers.get_inv(8)..
"listring[current_player;main]" .. "listring[current_player;main]" ..
"listring[current_player;main]" .. "listring[current_player;main]" ..
"listring[context;line1]" .. "listring[context;line1]" ..
@ -110,9 +124,22 @@ if pipeworks.enable_mese_tube then
update_formspec(pos) update_formspec(pos)
meta:set_string("infotext", S("Sorting pneumatic tube")) meta:set_string("infotext", S("Sorting pneumatic tube"))
end, end,
after_place_node = function(pos, placer, itemstack, pointed_thing)
if placer and placer:is_player() and placer:get_player_control().aux1 then
local meta = minetest.get_meta(pos)
for i = 1, 6 do
meta:set_int("l"..tostring(i).."s", 0)
end
update_formspec(pos)
end
return pipeworks.after_place(pos, placer, itemstack, pointed_thing)
end,
on_punch = update_formspec, on_punch = update_formspec,
on_receive_fields = function(pos, formname, fields, sender) on_receive_fields = function(pos, formname, fields, sender)
if not pipeworks.may_configure(pos, sender) then return end if (fields.quit and not fields.key_enter_field)
or not pipeworks.may_configure(pos, sender) then
return
end
fs_helpers.on_receive_fields(pos, fields) fs_helpers.on_receive_fields(pos, fields)
update_formspec(pos) update_formspec(pos)
end, end,
@ -150,25 +177,4 @@ if pipeworks.enable_mese_tube then
end, end,
}, },
}) })
minetest.register_craft( {
output = "pipeworks:mese_tube_000000 2",
recipe = {
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" },
{ "", "default:mese_crystal", "" },
{ "basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" }
},
})
minetest.register_craft( {
type = "shapeless",
output = "pipeworks:mese_tube_000000",
recipe = {
"pipeworks:tube_1",
"default:mese_crystal_fragment",
"default:mese_crystal_fragment",
"default:mese_crystal_fragment",
"default:mese_crystal_fragment"
},
})
end end

139
tubes/tags.lua Normal file
View File

@ -0,0 +1,139 @@
local S = minetest.get_translator("pipeworks")
local fs_helpers = pipeworks.fs_helpers
if not pipeworks.enable_item_tags or not pipeworks.enable_tag_tube then return end
local help_text = minetest.formspec_escape(
S("Separate multiple tags using commas.").."\n"..
S("Use \"<none>\" to match items without tags.")
)
local update_formspec = function(pos)
local meta = minetest.get_meta(pos)
local buttons_formspec = ""
for i = 0, 5 do
buttons_formspec = buttons_formspec .. fs_helpers.cycling_button(meta,
"image_button[9," .. (i + (i * 0.25) + 0.5) .. ";1,0.6", "l" .. (i + 1) .. "s",
{
pipeworks.button_off,
pipeworks.button_on
}
)
end
local size = "10.2,9"
meta:set_string("formspec",
"formspec_version[2]" ..
"size[" .. size .. "]" ..
pipeworks.fs_helpers.get_prepends(size) ..
"field[1.5,0.25;7.25,1;tags1;;${tags1}]" ..
"field[1.5,1.5;7.25,1;tags2;;${tags2}]" ..
"field[1.5,2.75;7.25,1;tags3;;${tags3}]" ..
"field[1.5,4.0;7.25,1;tags4;;${tags4}]" ..
"field[1.5,5.25;7.25,1;tags5;;${tags5}]" ..
"field[1.5,6.5;7.25,1;tags6;;${tags6}]" ..
"image[0.22,0.25;1,1;pipeworks_white.png]" ..
"image[0.22,1.50;1,1;pipeworks_black.png]" ..
"image[0.22,2.75;1,1;pipeworks_green.png]" ..
"image[0.22,4.00;1,1;pipeworks_yellow.png]" ..
"image[0.22,5.25;1,1;pipeworks_blue.png]" ..
"image[0.22,6.50;1,1;pipeworks_red.png]" ..
buttons_formspec ..
"label[0.22,7.9;"..help_text.."]"..
"button[7.25,7.8;1.5,0.8;set_item_tags;" .. S("Set") .. "]"
)
end
pipeworks.register_tube("pipeworks:tag_tube", {
description = S("Tag Sorting Pneumatic Tube Segment"),
inventory_image = "pipeworks_tag_tube_inv.png",
noctr = { "pipeworks_tag_tube_noctr_1.png", "pipeworks_tag_tube_noctr_2.png", "pipeworks_tag_tube_noctr_3.png",
"pipeworks_tag_tube_noctr_4.png", "pipeworks_tag_tube_noctr_5.png", "pipeworks_tag_tube_noctr_6.png" },
plain = { "pipeworks_tag_tube_plain_1.png", "pipeworks_tag_tube_plain_2.png", "pipeworks_tag_tube_plain_3.png",
"pipeworks_tag_tube_plain_4.png", "pipeworks_tag_tube_plain_5.png", "pipeworks_tag_tube_plain_6.png" },
ends = { "pipeworks_tag_tube_end.png" },
short = "pipeworks_tag_tube_short.png",
no_facedir = true, -- Must use old tubes, since the textures are rotated with 6d ones
node_def = {
tube = {
can_go = function(pos, node, velocity, stack, tags)
local tbl, tbln = {}, 0
local found, foundn = {}, 0
local meta = minetest.get_meta(pos)
local tag_hash = {}
if #tags > 0 then
for _,tag in ipairs(tags) do
tag_hash[tag] = true
end
else
tag_hash["<none>"] = true -- Matches items without tags
end
for i, vect in ipairs(pipeworks.meseadjlist) do
local npos = vector.add(pos, vect)
local node = minetest.get_node(npos)
local reg_node = minetest.registered_nodes[node.name]
if meta:get_int("l" .. i .. "s") == 1 and reg_node then
local tube_def = reg_node.tube
if not tube_def or not tube_def.can_insert or
tube_def.can_insert(npos, node, stack, vect) then
local side_tags = meta:get_string("tags" .. i)
if side_tags ~= "" then
side_tags = pipeworks.sanitize_tags(side_tags)
for _,tag in ipairs(side_tags) do
if tag_hash[tag] then
foundn = foundn + 1
found[foundn] = vect
break
end
end
else
tbln = tbln + 1
tbl[tbln] = vect
end
end
end
end
return (foundn > 0) and found or tbl
end
},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
for i = 1, 6 do
meta:set_int("l" .. tostring(i) .. "s", 1)
end
update_formspec(pos)
meta:set_string("infotext", S("Tag sorting pneumatic tube"))
end,
after_place_node = function(pos, placer, itemstack, pointed_thing)
if placer and placer:is_player() and placer:get_player_control().aux1 then
local meta = minetest.get_meta(pos)
for i = 1, 6 do
meta:set_int("l" .. tostring(i) .. "s", 0)
end
update_formspec(pos)
end
return pipeworks.after_place(pos, placer, itemstack, pointed_thing)
end,
on_receive_fields = function(pos, formname, fields, sender)
if (fields.quit and not fields.key_enter_field)
or not pipeworks.may_configure(pos, sender) then
return
end
local meta = minetest.get_meta(pos)
for i = 1, 6 do
local field_name = "tags" .. tostring(i)
if fields[field_name] then
local tags = pipeworks.sanitize_tags(fields[field_name])
meta:set_string(field_name, table.concat(tags, ","))
end
end
fs_helpers.on_receive_fields(pos, fields)
update_formspec(pos)
end,
can_dig = function(pos, player)
return true
end,
},
})

374
tubes/teleport.lua Normal file
View File

@ -0,0 +1,374 @@
local S = minetest.get_translator("pipeworks")
local filename = minetest.get_worldpath().."/teleport_tubes" -- Only used for backward-compat
local storage = minetest.get_mod_storage()
local enable_logging = minetest.settings:get_bool("pipeworks_log_teleport_tubes", false)
local has_digilines = minetest.get_modpath("digilines")
-- V1: Serialized text file indexed by vector position.
-- V2: Serialized text file indexed by hash position.
-- V3: Mod storage using serialized tables.
-- V4: Mod storage using "<can_receive>:<channel>" format.
local tube_db_version = 4
local tube_db = {}
local receiver_cache = {}
local function hash_pos(pos)
vector.round(pos)
return string.format("%.0f", minetest.hash_node_position(pos))
end
local function serialize_tube(tube)
return string.format("%d:%s", tube.cr, tube.channel)
end
local function deserialize_tube(hash, str)
local sep = str:sub(2, 2) == ":"
local cr = tonumber(str:sub(1, 1))
local channel = str:sub(3)
if sep and cr and channel then
local pos = minetest.get_position_from_hash(tonumber(hash))
return {x = pos.x, y = pos.y, z = pos.z, cr = cr, channel = channel}
end
end
local function save_tube_db()
receiver_cache = {}
local fields = {version = tube_db_version}
for key, val in pairs(tube_db) do
fields[key] = serialize_tube(val)
end
storage:from_table({fields = fields})
end
local function save_tube(hash)
local tube = tube_db[hash]
receiver_cache[tube.channel] = nil
storage:set_string(hash, serialize_tube(tube))
end
local function remove_tube(pos)
local hash = hash_pos(pos)
if tube_db[hash] then
receiver_cache[tube_db[hash].channel] = nil
tube_db[hash] = nil
storage:set_string(hash, "")
end
end
local function migrate_tube_db()
if storage:get_int("version") == 3 then
for key, val in pairs(storage:to_table().fields) do
if tonumber(key) then
tube_db[key] = minetest.deserialize(val)
elseif key ~= "version" then
error("Unknown field in teleport tube database: "..key)
end
end
save_tube_db()
return
end
local file = io.open(filename, "r")
if file then
local content = file:read("*all")
io.close(file)
if content and content ~= "" then
tube_db = minetest.deserialize(content)
end
end
local version = tube_db.version or 0
tube_db.version = nil
if version < 2 then
local tmp_db = {}
for _, val in pairs(tube_db) do
if val.channel ~= "" then -- Skip unconfigured tubes
tmp_db[hash_pos(val)] = val
end
end
tube_db = tmp_db
end
save_tube_db()
end
local function read_tube_db()
local version = storage:get_int("version")
if version < tube_db_version then
migrate_tube_db()
elseif version > tube_db_version then
error("Cannot read teleport tube database of version "..version)
else
for key, val in pairs(storage:to_table().fields) do
if tonumber(key) then
tube_db[key] = deserialize_tube(key, val)
elseif key ~= "version" then
error("Unknown field in teleport tube database: "..key)
end
end
end
tube_db.version = nil
end
local function set_tube(pos, channel, cr)
local hash = hash_pos(pos)
local tube = tube_db[hash]
if tube then
if tube.channel ~= channel or tube.cr ~= cr then
tube.channel = channel
tube.cr = cr
save_tube(hash)
end
else
tube_db[hash] = {x = pos.x, y = pos.y, z = pos.z, channel = channel, cr = cr}
save_tube(hash)
end
end
local function get_receivers(pos, channel)
local hash = hash_pos(pos)
local cache = receiver_cache[channel] or {}
if cache[hash] then
return cache[hash]
end
local receivers = {}
for key, val in pairs(tube_db) do
if val.cr == 1 and val.channel == channel and not vector.equals(val, pos) then
minetest.load_area(val)
local node_name = minetest.get_node(val).name
if node_name:find("pipeworks:teleport_tube") then
table.insert(receivers, val)
else
remove_tube(val)
end
end
end
cache[hash] = receivers
receiver_cache[channel] = cache
return receivers
end
local help_text = minetest.formspec_escape(
S("Channels are public by default").."\n"..
S("Use <player>:<channel> for fully private channels").."\n"..
S("Use <player>;<channel> for private receivers")
)
local size = has_digilines and "8,5.9" or "8,4.4"
local formspec = "formspec_version[2]size["..size.."]"..
pipeworks.fs_helpers.get_prepends(size)..
"image[0.5,0.3;1,1;pipeworks_teleport_tube_inv.png]"..
"label[1.75,0.8;"..S("Teleporting Tube").."]"..
"field[0.5,1.7;5,0.8;channel;"..S("Channel")..";${channel}]"..
"button_exit[5.5,1.7;2,0.8;save;"..S("Save").."]"..
"label[6.5,0.6;"..S("Receive").."]"..
"label[0.5,2.8;"..help_text.."]"
if has_digilines then
formspec = formspec..
"field[0.5,4.6;5,0.8;digiline_channel;"..S("Digiline Channel")..";${digiline_channel}]"..
"button_exit[5.5,4.6;2,0.8;save;"..S("Save").."]"
end
local function update_meta(meta)
local channel = meta:get_string("channel")
local cr = meta:get_int("can_receive") == 1
if channel == "" then
meta:set_string("infotext", S("Unconfigured Teleportation Tube"))
else
local desc = cr and "sending and receiving" or "sending"
meta:set_string("infotext", S("Teleportation Tube @1 on '@2'", desc, channel))
end
local state = cr and "on" or "off"
meta:set_string("formspec", formspec..
"image_button[6.4,0.8;1,0.6;pipeworks_button_"..state..
".png;cr_"..state..";;;false;pipeworks_button_interm.png]")
end
local function update_tube(pos, channel, cr, player_name)
local meta = minetest.get_meta(pos)
if meta:get_string("channel") == channel and meta:get_int("can_receive") == cr then
return
end
if channel == "" then
meta:set_string("channel", "")
meta:set_int("can_receive", cr)
remove_tube(pos)
return
end
local name, mode = channel:match("^([^:;]+)([:;])")
if name and mode and name ~= player_name then
if mode == ":" then
minetest.chat_send_player(player_name,
S("Sorry, channel '@1' is reserved for exclusive use by @2", channel, name))
return
elseif mode == ";" and cr ~= 0 then
minetest.chat_send_player(player_name,
S("Sorry, receiving from channel '@1' is reserved for @2", channel, name))
return
end
end
meta:set_string("channel", channel)
meta:set_int("can_receive", cr)
set_tube(pos, channel, cr)
end
local function receive_fields(pos, _, fields, sender)
if not fields.channel or not pipeworks.may_configure(pos, sender) then
return
end
local meta = minetest.get_meta(pos)
local channel = fields.channel:trim()
local cr = meta:get_int("can_receive")
if fields.cr_on then
cr = 0
elseif fields.cr_off then
cr = 1
end
if has_digilines and fields.digiline_channel then
meta:set_string("digiline_channel", fields.digiline_channel)
end
update_tube(pos, channel, cr, sender:get_player_name())
update_meta(meta)
end
local function can_go(pos, node, velocity, stack)
velocity.x = 0
velocity.y = 0
velocity.z = 0
local src_meta = minetest.get_meta(pos)
local channel = src_meta:get_string("channel")
if channel == "" then
return {}
end
local receivers = get_receivers(pos, channel)
if #receivers == 0 then
return {}
end
local target = receivers[math.random(1, #receivers)]
if enable_logging then
local src_owner = src_meta:get_string("owner")
local dst_meta = minetest.get_meta(pos)
local dst_owner = dst_meta:get_string("owner")
minetest.log("action", string.format("[pipeworks] %s teleported from %s (owner=%s) to %s (owner=%s) via %s",
stack:to_string(), minetest.pos_to_string(pos), src_owner, minetest.pos_to_string(target), dst_owner, channel
))
end
pos.x = target.x
pos.y = target.y
pos.z = target.z
return pipeworks.meseadjlist
end
local function repair_tube(pos, node)
minetest.swap_node(pos, {name = node.name, param2 = node.param2})
pipeworks.scan_for_tube_objects(pos)
local meta = minetest.get_meta(pos)
local channel = meta:get_string("channel")
if channel ~= "" then
set_tube(pos, channel, meta:get_int("can_receive"))
end
update_meta(meta)
end
local function digiline_action(pos, _, digiline_channel, msg)
local meta = minetest.get_meta(pos)
if digiline_channel ~= meta:get_string("digiline_channel") then
return
end
local channel = meta:get_string("channel")
local can_receive = meta:get_int("can_receive")
if type(msg) == "string" then
channel = msg
elseif type(msg) == "table" then
if type(msg.channel) == "string" then
channel = msg.channel
end
if msg.can_receive == 1 or msg.can_receive == true then
can_receive = 1
elseif msg.can_receive == 0 or msg.can_receive == false then
can_receive = 0
end
else
return
end
local player_name = meta:get_string("owner")
update_tube(pos, channel, can_receive, player_name)
update_meta(meta)
end
local def = {
tube = {
can_go = can_go,
on_repair = repair_tube,
},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_int("can_receive", 1) -- Enabled by default
update_meta(meta)
end,
on_receive_fields = receive_fields,
on_destruct = remove_tube,
}
if has_digilines then
def.after_place_node = function(pos, placer)
-- Set owner for digilines
minetest.get_meta(pos):set_string("owner", placer:get_player_name())
pipeworks.after_place(pos)
end
def.digiline = {
receptor = {
rules = pipeworks.digilines_rules,
},
effector = {
rules = pipeworks.digilines_rules,
action = digiline_action,
}
}
end
pipeworks.register_tube("pipeworks:teleport_tube", {
description = S("Teleporting Pneumatic Tube Segment"),
inventory_image = "pipeworks_teleport_tube_inv.png",
noctr = { "pipeworks_teleport_tube_noctr.png" },
plain = { "pipeworks_teleport_tube_plain.png" },
ends = { "pipeworks_teleport_tube_end.png" },
short = "pipeworks_teleport_tube_short.png",
node_def = def,
})
if minetest.get_modpath("mesecons_mvps") then
-- Update tubes when moved by pistons
mesecon.register_on_mvps_move(function(moved_nodes)
for _, n in ipairs(moved_nodes) do
if n.node.name:find("pipeworks:teleport_tube") then
local meta = minetest.get_meta(n.pos)
set_tube(n.pos, meta:get_string("channel"), meta:get_int("can_receive"))
end
end
end)
end
-- Expose teleport tube database API for other mods
pipeworks.tptube = {
version = tube_db_version,
hash = hash_pos,
get_db = function() return tube_db end,
save_tube_db = save_tube_db,
remove_tube = remove_tube,
set_tube = set_tube,
save_tube = save_tube,
update_tube = update_tube,
update_meta = function(meta, cr)
-- Legacy behaviour
if cr ~= nil then
meta:set_int("can_receive", cr and 1 or 0)
end
update_meta(meta)
end,
}
-- Load the database
read_tube_db()

114
tubes/vacuum.lua Normal file
View File

@ -0,0 +1,114 @@
local S = minetest.get_translator("pipeworks")
local enable_max = minetest.settings:get_bool("pipeworks_enable_items_per_tube_limit", true)
local max_items = tonumber(minetest.settings:get("pipeworks_max_items_per_tube")) or 30
max_items = math.ceil(max_items / 2) -- Limit vacuuming to half the max limit
local function vacuum(pos, radius)
radius = radius + 0.5
local min_pos = vector.subtract(pos, radius)
local max_pos = vector.add(pos, radius)
local count = 0
for _, obj in pairs(minetest.get_objects_in_area(min_pos, max_pos)) do
local entity = obj:get_luaentity()
if entity and entity.name == "__builtin:item" then
if entity.itemstring ~= "" then
pipeworks.tube_inject_item(pos, pos, vector.new(0, 0, 0), entity.itemstring)
entity.itemstring = ""
count = count + 1
end
obj:remove()
if enable_max and count >= max_items then
return -- Don't break tube by vacuuming too many items
end
end
end
end
local function set_timer(pos)
local timer = minetest.get_node_timer(pos)
-- Randomize timer so not all tubes vacuum at the same time
timer:start(math.random(10, 20) * 0.1)
end
local function repair_tube(pos, was_node)
minetest.swap_node(pos, {name = was_node.name, param2 = was_node.param2})
pipeworks.scan_for_tube_objects(pos)
set_timer(pos)
end
if pipeworks.enable_sand_tube then
pipeworks.register_tube("pipeworks:sand_tube", {
description = S("Vacuuming Pneumatic Tube Segment"),
inventory_image = "pipeworks_sand_tube_inv.png",
short = "pipeworks_sand_tube_short.png",
noctr = {"pipeworks_sand_tube_noctr.png"},
plain = {"pipeworks_sand_tube_plain.png"},
ends = {"pipeworks_sand_tube_end.png"},
node_def = {
groups = {vacuum_tube = 1},
tube = {
on_repair = repair_tube,
},
on_construct = set_timer,
on_timer = function(pos, elapsed)
vacuum(pos, 2)
set_timer(pos)
end,
},
})
end
if pipeworks.enable_mese_sand_tube then
local formspec = "formspec_version[2]size[8,3]"..
pipeworks.fs_helpers.get_prepends("8,3")..
"image[0.5,0.3;1,1;pipeworks_mese_sand_tube_inv.png]"..
"label[1.75,0.8;"..S("Adjustable Vacuuming Tube").."]"..
"field[0.5,1.7;5,0.8;dist;"..S("Radius")..";${dist}]"..
"button_exit[5.5,1.7;2,0.8;save;"..S("Save").."]"
pipeworks.register_tube("pipeworks:mese_sand_tube", {
description = S("Adjustable Vacuuming Tube"),
inventory_image = "pipeworks_mese_sand_tube_inv.png",
short = "pipeworks_mese_sand_tube_short.png",
noctr = {"pipeworks_mese_sand_tube_noctr.png"},
plain = {"pipeworks_mese_sand_tube_plain.png"},
ends = {"pipeworks_mese_sand_tube_end.png"},
node_def = {
groups = {vacuum_tube = 1},
tube = {
on_repair = repair_tube,
},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_int("dist", 2)
meta:set_string("formspec", formspec)
meta:set_string("infotext", S("Adjustable Vacuuming Tube (@1m)", 2))
set_timer(pos)
end,
on_timer = function(pos, elapsed)
local radius = minetest.get_meta(pos):get_int("dist")
vacuum(pos, radius)
set_timer(pos)
end,
on_receive_fields = function(pos, _, fields, sender)
if not fields.dist or not pipeworks.may_configure(pos, sender) then
return
end
local meta = minetest.get_meta(pos)
local dist = math.min(math.max(tonumber(fields.dist) or 0, 0), 8)
meta:set_int("dist", dist)
meta:set_string("infotext", S("Adjustable Vacuuming Tube (@1m)", dist))
end,
},
})
end
minetest.register_lbm({
label = "Vacuum tube node timer starter",
name = "pipeworks:vacuum_tube_start",
nodenames = {"group:vacuum_tube"},
run_at_every_load = false,
action = set_timer,
})

View File

@ -1,119 +0,0 @@
local S = minetest.get_translator("pipeworks")
if pipeworks.enable_sand_tube then
pipeworks.register_tube("pipeworks:sand_tube", {
description = S("Vacuuming Pneumatic Tube Segment"),
inventory_image = "pipeworks_sand_tube_inv.png",
short = "pipeworks_sand_tube_short.png",
noctr = {"pipeworks_sand_tube_noctr.png"},
plain = {"pipeworks_sand_tube_plain.png"},
ends = {"pipeworks_sand_tube_end.png"},
node_def = {groups = {vacuum_tube = 1}},
})
minetest.register_craft( {
output = "pipeworks:sand_tube_1 2",
recipe = {
{"basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet"},
{"group:sand", "group:sand", "group:sand"},
{"basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet"}
},
})
minetest.register_craft( {
output = "pipeworks:sand_tube_1",
recipe = {
{"group:sand", "pipeworks:tube_1", "group:sand"},
},
})
end
if pipeworks.enable_mese_sand_tube then
pipeworks.register_tube("pipeworks:mese_sand_tube", {
description = S("Adjustable Vacuuming Pneumatic Tube Segment"),
inventory_image = "pipeworks_mese_sand_tube_inv.png",
short = "pipeworks_mese_sand_tube_short.png",
noctr = {"pipeworks_mese_sand_tube_noctr.png"},
plain = {"pipeworks_mese_sand_tube_plain.png"},
ends = {"pipeworks_mese_sand_tube_end.png"},
node_def = {
groups = {vacuum_tube = 1},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_int("dist", 0)
meta:set_string("formspec", "size[2.1,0.8]"..
"image[0,0;1,1;pipeworks_mese_sand_tube_inv.png]"..
"field[1.3,0.4;1,1;dist;radius;${dist}]"..
default.gui_bg..
default.gui_bg_img)
meta:set_string("infotext", S("Adjustable Vacuuming Pneumatic Tube Segment"))
end,
on_receive_fields = function(pos,formname,fields,sender)
if not pipeworks.may_configure(pos, sender) then return end
local meta = minetest.get_meta(pos)
local dist = tonumber(fields.dist)
if dist then
dist = math.max(0, dist)
dist = math.min(8, dist)
meta:set_int("dist", dist)
meta:set_string("infotext", (S("Adjustable Vacuuming Pneumatic Tube Segment (@1m)", dist)))
end
end,
},
})
minetest.register_craft( {
output = "pipeworks:mese_sand_tube_1 2",
recipe = {
{"basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" },
{"group:sand", "default:mese_crystal", "group:sand" },
{"basic_materials:plastic_sheet", "basic_materials:plastic_sheet", "basic_materials:plastic_sheet" }
},
})
minetest.register_craft( {
type = "shapeless",
output = "pipeworks:mese_sand_tube_1",
recipe = {
"pipeworks:sand_tube_1",
"default:mese_crystal_fragment",
"default:mese_crystal_fragment",
"default:mese_crystal_fragment",
"default:mese_crystal_fragment"
},
})
end
local function vacuum(pos, radius)
radius = radius + 0.5
for _, object in pairs(minetest.get_objects_inside_radius(pos, math.sqrt(3) * radius)) do
local lua_entity = object:get_luaentity()
if not object:is_player() and lua_entity and lua_entity.name == "__builtin:item" then
local obj_pos = object:get_pos()
local minpos = vector.subtract(pos, radius)
local maxpos = vector.add(pos, radius)
if obj_pos.x >= minpos.x and obj_pos.x <= maxpos.x
and obj_pos.y >= minpos.y and obj_pos.y <= maxpos.y
and obj_pos.z >= minpos.z and obj_pos.z <= maxpos.z then
if lua_entity.itemstring ~= "" then
pipeworks.tube_inject_item(pos, pos, vector.new(0, 0, 0), lua_entity.itemstring)
lua_entity.itemstring = ""
end
object:remove()
end
end
end
end
minetest.register_abm({nodenames = {"group:vacuum_tube"},
interval = 1,
chance = 1,
label = "Vacuum tubes",
action = function(pos, node, active_object_count, active_object_count_wider)
if node.name:find("pipeworks:sand_tube") then
vacuum(pos, 2)
else
local radius = minetest.get_meta(pos):get_int("dist")
vacuum(pos, radius)
end
end
})

View File

@ -1,22 +1,33 @@
local S = minetest.get_translator("pipeworks") local S = minetest.get_translator("pipeworks")
local assumed_eye_pos = vector.new(0, 1.5, 0) local assumed_eye_pos = vector.new(0, 1.5, 0)
local function vector_copy(v)
return { x = v.x, y = v.y, z = v.z }
end
local function delay(x) local function delay(x)
return (function() return x end) return (function() return x end)
end end
local function set_wielder_formspec(data, meta) local function set_wielder_formspec(data, meta)
local size = "10.2,"..(7+data.wield_inv_height)
local list_background = ""
if minetest.get_modpath("i3") or minetest.get_modpath("mcl_formspec") then
list_background = "style_type[box;colors=#666]"
for i=0, data.wield_inv_height-1 do
for j=0, data.wield_inv_width-1 do
list_background = list_background .. "box[".. ((10-data.wield_inv_width)*0.5)+(i*1.25) ..",".. 1+(j*1.25) ..";1,1;]"
end
end
end
meta:set_string("formspec", meta:set_string("formspec",
"invsize[8,"..(6+data.wield_inv_height)..";]".. "formspec_version[2]" ..
"item_image[0,0;1,1;"..data.name_base.."_off]".. "size["..size.."]"..
"label[1,0;"..minetest.formspec_escape(data.description).."]".. pipeworks.fs_helpers.get_prepends(size)..
"list[current_name;"..minetest.formspec_escape(data.wield_inv_name)..";"..((8-data.wield_inv_width)*0.5)..",1;"..data.wield_inv_width..","..data.wield_inv_height..";]".. "item_image[0.5,0.5;1,1;"..data.name_base.."_off]"..
"list[current_player;main;0,"..(2+data.wield_inv_height)..";8,4;]" .. "label[1.5,1;"..minetest.formspec_escape(data.description).."]"..
"listring[]") list_background ..
"list[context;"..minetest.formspec_escape(data.wield_inv_name)..";"..((10-data.wield_inv_width)*0.5)..",1;"..data.wield_inv_width..","..data.wield_inv_height..";]"..
pipeworks.fs_helpers.get_inv((2+data.wield_inv_height)) ..
"listring[context;"..minetest.formspec_escape(data.wield_inv_name).."]" ..
"listring[current_player;main]"
)
meta:set_string("infotext", data.description) meta:set_string("infotext", data.description)
end end
@ -135,7 +146,7 @@ local function register_wielder(data)
data.fixup_node = data.fixup_node or function (pos, node) end data.fixup_node = data.fixup_node or function (pos, node) end
data.fixup_oldmetadata = data.fixup_oldmetadata or function (m) return m end data.fixup_oldmetadata = data.fixup_oldmetadata or function (m) return m end
for _, state in ipairs({ "off", "on" }) do for _, state in ipairs({ "off", "on" }) do
local groups = { snappy=2, choppy=2, oddly_breakable_by_hand=2, mesecon=2, tubedevice=1, tubedevice_receiver=1 } local groups = { snappy=2, choppy=2, oddly_breakable_by_hand=2, mesecon=2, tubedevice=1, tubedevice_receiver=1, axey=1, handy=1, pickaxey=1 }
if state == "on" then groups.not_in_creative_inventory = 1 end if state == "on" then groups.not_in_creative_inventory = 1 end
local tile_images = {} local tile_images = {}
for _, face in ipairs({ "top", "bottom", "side2", "side1", "back", "front" }) do for _, face in ipairs({ "top", "bottom", "side2", "side1", "back", "front" }) do
@ -184,11 +195,14 @@ local function register_wielder(data)
return stack:get_count() return stack:get_count()
end, end,
}, },
is_ground_content = true, is_ground_content = false,
paramtype2 = "facedir", paramtype2 = "facedir",
tubelike = 1, tubelike = 1,
groups = groups, groups = groups,
sounds = default.node_sound_stone_defaults(), _mcl_hardness=0.6,
_sound_def = {
key = "node_sound_stone_defaults",
},
drop = data.name_base.."_off", drop = data.name_base.."_off",
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
@ -211,7 +225,6 @@ local function register_wielder(data)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
node.param2 = minetest.dir_to_facedir(dir, true) node.param2 = minetest.dir_to_facedir(dir, true)
minetest.set_node(pos, node) minetest.set_node(pos, node)
minetest.log("action", "real (6d) facedir: " .. node.param2)
end end
minetest.get_meta(pos):set_string("owner", placer:get_player_name()) minetest.get_meta(pos):set_string("owner", placer:get_player_name())
end, end,
@ -323,6 +336,10 @@ if pipeworks.enable_node_breaker then
masquerade_as_owner = true, masquerade_as_owner = true,
sneak = false, sneak = false,
act = function(virtplayer, pointed_thing) act = function(virtplayer, pointed_thing)
if minetest.is_protected(vector.add(virtplayer:get_pos(), assumed_eye_pos), virtplayer:get_player_name()) then
return
end
--local dname = "nodebreaker.act() " --local dname = "nodebreaker.act() "
local wieldstack = virtplayer:get_wielded_item() local wieldstack = virtplayer:get_wielded_item()
local oldwieldstack = ItemStack(wieldstack) local oldwieldstack = ItemStack(wieldstack)
@ -353,7 +370,7 @@ if pipeworks.enable_node_breaker then
{pos=pointed_thing.under, gain=sound.gain}) {pos=pointed_thing.under, gain=sound.gain})
end end
wieldstack = virtplayer:get_wielded_item() wieldstack = virtplayer:get_wielded_item()
else --~ else
--pipeworks.logger(dname.."couldn't dig node!") --pipeworks.logger(dname.."couldn't dig node!")
end end
end end
@ -375,14 +392,7 @@ if pipeworks.enable_node_breaker then
eject_drops = true, eject_drops = true,
} }
register_wielder(data) register_wielder(data)
minetest.register_craft({ pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:nodebreaker_off"
output = "pipeworks:nodebreaker_off",
recipe = {
{ "basic_materials:gear_steel", "basic_materials:gear_steel", "basic_materials:gear_steel" },
{ "default:stone", "mesecons:piston", "default:stone" },
{ "group:wood", "mesecons:mesecon", "group:wood" },
}
})
-- aliases for when someone had technic installed, but then uninstalled it but not pipeworks -- aliases for when someone had technic installed, but then uninstalled it but not pipeworks
minetest.register_alias("technic:nodebreaker_off", "pipeworks:nodebreaker_off") minetest.register_alias("technic:nodebreaker_off", "pipeworks:nodebreaker_off")
minetest.register_alias("technic:nodebreaker_on", "pipeworks:nodebreaker_on") minetest.register_alias("technic:nodebreaker_on", "pipeworks:nodebreaker_on")
@ -421,19 +431,16 @@ if pipeworks.enable_deployer then
masquerade_as_owner = true, masquerade_as_owner = true,
sneak = false, sneak = false,
act = function(virtplayer, pointed_thing) act = function(virtplayer, pointed_thing)
if minetest.is_protected(vector.add(virtplayer:get_pos(), assumed_eye_pos), virtplayer:get_player_name()) then
return
end
local wieldstack = virtplayer:get_wielded_item() local wieldstack = virtplayer:get_wielded_item()
virtplayer:set_wielded_item((minetest.registered_items[wieldstack:get_name()] or {on_place=minetest.item_place}).on_place(wieldstack, virtplayer, pointed_thing) or wieldstack) virtplayer:set_wielded_item((minetest.registered_items[wieldstack:get_name()] or {on_place=minetest.item_place}).on_place(wieldstack, virtplayer, pointed_thing) or wieldstack)
end, end,
eject_drops = false, eject_drops = false,
}) })
minetest.register_craft({ pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:deployer_off"
output = "pipeworks:deployer_off",
recipe = {
{ "group:wood", "default:chest", "group:wood" },
{ "default:stone", "mesecons:piston", "default:stone" },
{ "default:stone", "mesecons:mesecon", "default:stone" },
}
})
-- aliases for when someone had technic installed, but then uninstalled it but not pipeworks -- aliases for when someone had technic installed, but then uninstalled it but not pipeworks
minetest.register_alias("technic:deployer_off", "pipeworks:deployer_off") minetest.register_alias("technic:deployer_off", "pipeworks:deployer_off")
minetest.register_alias("technic:deployer_on", "pipeworks:deployer_on") minetest.register_alias("technic:deployer_on", "pipeworks:deployer_on")
@ -461,12 +468,5 @@ if pipeworks.enable_dispenser then
end, end,
eject_drops = false, eject_drops = false,
}) })
minetest.register_craft({ pipeworks.ui_cat_tube_list[#pipeworks.ui_cat_tube_list+1] = "pipeworks:dispenser_off"
output = "pipeworks:dispenser_off",
recipe = {
{ "default:desert_sand", "default:chest", "default:desert_sand" },
{ "default:stone", "mesecons:piston", "default:stone" },
{ "default:stone", "mesecons:mesecon", "default:stone" },
}
})
end end