diff --git a/basic_machines/recycler.lua b/basic_machines/recycler.lua index ce85b3f..f2adfc2 100644 --- a/basic_machines/recycler.lua +++ b/basic_machines/recycler.lua @@ -26,40 +26,44 @@ local CYCLE_TIME = 8 local Recipes = {} local SpecialItems = { - ["techage:sieved_gravel"] = "default:sand", - ["basic_materials:heating_element"] = "default:copper_ingot", - ["techage:ta4_wlanchip"] = "", - ["techage:basalt_cobble"] = "default:sand", - ["default:stone"] = "techage:sieved_gravel", - ["default:wood"] = "default:stick 5", - ["basic_materials:concrete_block"] = "techage:sieved_gravel", - ["dye:green"] = "", - ["dye:red"] = "", - ["dye:white"] = "", - ["dye:blue"] = "", - ["dye:brown"] = "", + ["techage:sieved_gravel"] = "default:sand", + ["basic_materials:heating_element"] = "default:copper_ingot", + ["techage:ta4_wlanchip"] = "", + ["techage:basalt_cobble"] = "default:sand", + ["default:stone"] = "techage:sieved_gravel", + ["default:wood"] = "default:stick 5", + ["basic_materials:concrete_block"] = "techage:sieved_gravel", + ["dye:green"] = "", + ["dye:red"] = "", + ["dye:white"] = "", + ["dye:blue"] = "", + ["dye:brown"] = "", ["dye:cyan"] = "", ["dye:yellow"] = "", ["dye:grey"] = "", ["dye:orange"] = "", - ["dye:black"] = "", - ["techage:basalt_glass_thin"] = "", - ["group:stone"] = "techage:sieved_gravel", - ["basic_materials:plastic_sheet"] = "", - ["group:wood"] = "default:stick 5", - ["techage:basalt_glass"] = "", - ["default:junglewood"] = "default:stick 5", - ["techage:ta4_silicon_wafer"] = "", - ["default:cobble"] = "techage:sieved_gravel", - ["default:pick_diamond"] = "default:stick", - ["techage:hammer_steel"] = "default:stick", - ["default:paper"] = "", - ["stairs:slab_basalt_glass2"] = "", - ["techage:basalt_stone"] = "techage:sieved_gravel", - ["techage:ta4_ramchip"] = "", + ["dye:black"] = "", + ["techage:basalt_glass_thin"] = "", + ["group:stone"] = "techage:sieved_gravel", + ["basic_materials:plastic_sheet"] = "", + ["group:wood"] = "default:stick 5", + ["techage:basalt_glass"] = "", + ["default:junglewood"] = "default:stick 5", + ["techage:ta4_silicon_wafer"] = "", + ["default:cobble"] = "techage:sieved_gravel", + ["default:pick_diamond"] = "default:stick", + ["techage:hammer_steel"] = "default:stick", + ["default:paper"] = "", + ["stairs:slab_basalt_glass2"] = "", + ["techage:basalt_stone"] = "techage:sieved_gravel", + ["techage:ta4_ramchip"] = "", ["protector:chest"] = "default:chest", ["techage:ta4_rotor_blade"] = "", ["techage:ta4_carbon_fiber"] = "", + ["techage:ta4_round_ceramic"] = "", + ["techage:ta4_furnace_ceramic"] = "", + ["techage:ta5_aichip"] = "", + ["techage:ta4_leds"] = "", } local function formspec(self, pos, nvm) diff --git a/basis/assemble.lua b/basis/assemble.lua index 8437c1f..b176495 100644 --- a/basis/assemble.lua +++ b/basis/assemble.lua @@ -124,3 +124,118 @@ function techage.assemble.remove(pos, AssemblyPlan, player_name) remove(pos, node.param2, AssemblyPlan, #AssemblyPlan) nvm.assemble_build = false end + +-------------------------------------------------------------------------------- +-- Assembly functions based on nodes from node inventory +-------------------------------------------------------------------------------- +local function play_sound(pos, sound) + minetest.sound_play(sound, { + pos = pos, + gain = 1, + max_hear_distance = 10, + }) +end + +local function build_inv(pos, inv, param2, AssemblyPlan, player_name, idx) + local item = AssemblyPlan[idx] + if item ~= nil then + local y, path, fd_offs, node_name = item[1], item[2], item[3], item[4] + local pos1 = dest_pos(pos, param2, path, y) + if not minetest.is_protected(pos1, player_name) then + local node = minetest.get_node(pos1) + if techage.is_air_like(node.name) then + local stack = inv:remove_item("src", ItemStack(node_name)) + if stack:get_count() == 1 then + minetest.add_node(pos1, {name=node_name, param2=(param2 + fd_offs) % 4}) + play_sound(pos, "default_place_node_hard") + local ndef = minetest.registered_nodes[node_name] + if ndef and ndef.after_place_node then + local placer = minetest.get_player_by_name(player_name) + ndef.after_place_node(pos1, placer, ItemStack(node_name)) + end + end + end + end + minetest.after(0.5, build_inv, pos, inv, param2, AssemblyPlan, player_name, idx + 1) + else + local nvm = techage.get_nvm(pos) + nvm.assemble_locked = false + end +end + +local function remove_inv(pos, inv, param2, AssemblyPlan, player_name, idx) + local item = AssemblyPlan[idx] + if item ~= nil then + local y, path, fd_offs, node_name = item[1], item[2], item[3], item[4] + local pos1 = dest_pos(pos, param2, path, y) + if not minetest.is_protected(pos1, player_name) then + local stack = ItemStack(node_name) + if inv:room_for_item("src", stack) then + local node = minetest.get_node(pos1) + if node.name == node_name then + minetest.remove_node(pos1) + inv:add_item("src", stack) + play_sound(pos, "default_dig_cracky") + local ndef = minetest.registered_nodes[node_name] + if ndef and ndef.after_dig_node then + local digger = minetest.get_player_by_name(player_name) + ndef.after_dig_node(pos1, pos, ItemStack(node_name), {}, digger) + end + end + end + end + minetest.after(0.5, remove_inv, pos, inv, param2, AssemblyPlan, player_name, idx - 1) + else + local nvm = techage.get_nvm(pos) + nvm.assemble_locked = false + end +end + +function techage.assemble.build_inv(pos, inv, AssemblyPlan, player_name) + -- check protection + if minetest.is_protected(pos, player_name) then + return + end + local nvm = techage.get_nvm(pos) + if nvm.assemble_locked then + return + end + local node = minetest.get_node(pos) + nvm.assemble_locked = true + build_inv(pos, inv, node.param2, AssemblyPlan, player_name, 1) +end + +function techage.assemble.remove_inv(pos, inv, AssemblyPlan, player_name) + -- check protection + if minetest.is_protected(pos, player_name) then + return + end + local nvm = techage.get_nvm(pos) + if nvm.assemble_locked then + return + end + local node = minetest.get_node(pos) + nvm.assemble_locked = true + remove_inv(pos, inv, node.param2, AssemblyPlan, player_name, #AssemblyPlan) +end + +function techage.assemble.count_items(AssemblyPlan) + local t = {} + for _, item in ipairs(AssemblyPlan) do + local node_name = item[4] + local ndef = minetest.registered_nodes[node_name] + local name = ndef.description + if not t[name] then + t[name] = 1 + else + t[name] = t[name] + 1 + end + end + return t +end + +-- Determine the destination position based on the given route +-- param2, and a route table like : {0,3} +-- 0 = forward, 1 = right, 2 = backward, 3 = left +-- techage.assemble.get_pos(pos, param2, route, y_offs) +techage.assemble.get_pos = dest_pos diff --git a/basis/fly_lib.lua b/basis/fly_lib.lua index 15784d8..7ea3156 100644 --- a/basis/fly_lib.lua +++ b/basis/fly_lib.lua @@ -81,15 +81,23 @@ end function flylib.to_path(s, max_dist) local tPath + local dist = 0 for _, line in ipairs(strsplit(s)) do line = trim(line) line = string.split(line, "--", true, 1)[1] or "" if line ~= "" then local v = flylib.to_vector(line) - if v and (not max_dist or flylib.distance(v) <= max_dist) then - tPath = tPath or {} - tPath[#tPath + 1] = v + if v then + --dist = dist + flylib.distance(v) + --if not max_dist or dist <= max_dist then + tPath = tPath or {} + tPath[#tPath + 1] = v + --else + -- return tPath, S("Error: Max. length of the flight route exceeded !!") + --end + else + return tPath, S("Error: Invalid path !!") end end end @@ -614,10 +622,13 @@ end function flylib.move_to_other_pos(pos, move2to1) local meta = M(pos) local nvm = techage.get_nvm(pos) - local lpath = flylib.to_path(meta:get_string("path")) or {} + local lpath, err = flylib.to_path(meta:get_string("path")) or {} local max_speed = meta:contains("max_speed") and meta:get_int("max_speed") or MAX_SPEED local height = meta:contains("height") and meta:get_float("height") or 1 local handover + + if err then return false end + height = techage.in_range(height, 0, 1) max_speed = techage.in_range(max_speed, MIN_SPEED, MAX_SPEED) nvm.lpos1 = nvm.lpos1 or {} diff --git a/basis/laser_lib.lua b/basis/laser_lib.lua index 802b3c3..135fe61 100644 --- a/basis/laser_lib.lua +++ b/basis/laser_lib.lua @@ -42,7 +42,7 @@ local function get_positions(pos, mem, dir) return true -- no new values end --- return both both laser entities the pos and length +-- return for both laser entities the pos and length local function get_laser_length_and_pos(pos1, pos2, dir) local dist = vector.distance(pos1, pos2) @@ -133,5 +133,14 @@ function techage.renew_laser(pos, force) return res end +function techage.add_laser(pos, pos1, pos2) + local dir = vector.direction(pos1, pos2) + local param2 = minetest.dir_to_facedir(dir) + local size, pos3, pos4 = get_laser_length_and_pos(pos1, pos2, dir) + if size then + add_laser(pos, pos3, pos4, size, param2) + end +end + -- techage.del_laser(pos) techage.del_laser = del_laser diff --git a/basis/lib.lua b/basis/lib.lua index e3d2219..201d270 100644 --- a/basis/lib.lua +++ b/basis/lib.lua @@ -456,6 +456,42 @@ function techage.wrench_tooltip(x, y) "tooltip["..x..","..y..";0.5,0.5;"..tooltip..";#0C3D32;#FFFFFF]" end +------------------------------------------------------------------------------- +-- Terminal history buffer +------------------------------------------------------------------------------- +local BUFFER_DEPTH = 10 + +function techage.historybuffer_add(pos, s) + local mem = techage.get_mem(pos) + mem.hisbuf = mem.hisbuf or {} + + if #s > 2 then + table.insert(mem.hisbuf, s) + if #mem.hisbuf > BUFFER_DEPTH then + table.remove(mem.hisbuf, 1) + end + mem.hisbuf_idx = #mem.hisbuf + 1 + end +end + +function techage.historybuffer_priv(pos) + local mem = techage.get_mem(pos) + mem.hisbuf = mem.hisbuf or {} + mem.hisbuf_idx = mem.hisbuf_idx or 1 + + mem.hisbuf_idx = math.max(1, mem.hisbuf_idx - 1) + return mem.hisbuf[mem.hisbuf_idx] +end + +function techage.historybuffer_next(pos) + local mem = techage.get_mem(pos) + mem.hisbuf = mem.hisbuf or {} + mem.hisbuf_idx = mem.hisbuf_idx or 1 + + mem.hisbuf_idx = math.min(#mem.hisbuf, mem.hisbuf_idx + 1) + return mem.hisbuf[mem.hisbuf_idx] +end + ------------------------------------------------------------------------------- -- Player TA5 Experience Points ------------------------------------------------------------------------------- @@ -468,12 +504,30 @@ function techage.get_expoints(player) end end -function techage.add_expoint(player) +-- Can only be used from one collider +function techage.add_expoint(player, number) if player and player.get_meta then local meta = player:get_meta() if meta then - meta:set_int("techage_ex_points", meta:get_int("techage_ex_points") + 1) - return true + if not meta:contains("techage_collider_number") then + meta:set_string("techage_collider_number", number) + end + if meta:get_string("techage_collider_number") == number then + meta:set_int("techage_ex_points", meta:get_int("techage_ex_points") + 1) + return true + else + minetest.chat_send_player(player:get_player_name(), "[techage] More than one collider is not allowed!") + return false + end + end + end +end + +function techage.on_remove_collider(player) + if player and player.get_meta then + local meta = player:get_meta() + if meta then + meta:set_string("techage_collider_number", "") end end end diff --git a/basis/oggfiles.lua b/basis/oggfiles.lua new file mode 100644 index 0000000..ffe7c82 --- /dev/null +++ b/basis/oggfiles.lua @@ -0,0 +1,103 @@ +techage.OggFileList = { + "autobahn_motor", -- ./mods/autobahn/sounds + "signs_bot_ping", -- ./mods/signs_bot/sounds + "signs_bot_go_away", -- ./mods/signs_bot/sounds + "signs_bot_step", -- ./mods/signs_bot/sounds + "signs_bot_pong", -- ./mods/signs_bot/sounds + "signs_bot_error", -- ./mods/signs_bot/sounds + "normal2", -- ./mods/hyperloop/sounds + "up2", -- ./mods/hyperloop/sounds + "down2", -- ./mods/hyperloop/sounds + "ele_norm", -- ./mods/hyperloop/sounds + "door", -- ./mods/hyperloop/sounds + "hyperloop_crowbar", -- ./mods/hyperloop/sounds + "ele_door", -- ./mods/hyperloop/sounds + "techage_watermill", -- ./mods/techage/sounds + "techage_button", -- ./mods/techage/sounds + "techage_steamengine", -- ./mods/techage/sounds + "techage_generator", -- ./mods/techage/sounds + "techage_gasflare", -- ./mods/techage/sounds + "techage_explore", -- ./mods/techage/sounds + "techage_mill", -- ./mods/techage/sounds + "techage_reactor", -- ./mods/techage/sounds + "techage_valve", -- ./mods/techage/sounds + "techage_oildrill", -- ./mods/techage/sounds + "techage_turbine", -- ./mods/techage/sounds + "techage_booster", -- ./mods/techage/sounds + "techage_quarry", -- ./mods/techage/sounds + "techage_reboiler", -- ./mods/techage/sounds + "jetpack_loop", -- ./mods/jetpack/sounds + "paperflip1", -- ./mods/unified_inventory/sounds + "teleport", -- ./mods/unified_inventory/sounds + "electricity", -- ./mods/unified_inventory/sounds + "owl", -- ./mods/unified_inventory/sounds + "click", -- ./mods/unified_inventory/sounds + "birds", -- ./mods/unified_inventory/sounds + "paperflip2", -- ./mods/unified_inventory/sounds + "dingdong", -- ./mods/unified_inventory/sounds + "trash", -- ./mods/unified_inventory/sounds + "trash_all", -- ./mods/unified_inventory/sounds + "ta4_jetpack", -- ./mods/ta4_jetpack/sounds + "ta4_jetpack_alarm", -- ./mods/ta4_jetpack/sounds + "ta4_jetpack_on", -- ./mods/ta4_jetpack/sounds + "player_damage", -- ./games/minetest_game/mods/player_api/sounds + "env_sounds_water", -- ./games/minetest_game/mods/env_sounds/sounds + "env_sounds_lava", -- ./games/minetest_game/mods/env_sounds/sounds + "doors_door_close", -- ./games/minetest_game/mods/doors/sounds + "doors_steel_door_close", -- ./games/minetest_game/mods/doors/sounds + "doors_door_open", -- ./games/minetest_game/mods/doors/sounds + "doors_fencegate_close", -- ./games/minetest_game/mods/doors/sounds + "doors_glass_door_close", -- ./games/minetest_game/mods/doors/sounds + "doors_fencegate_open", -- ./games/minetest_game/mods/doors/sounds + "doors_glass_door_open", -- ./games/minetest_game/mods/doors/sounds + "doors_steel_door_open", -- ./games/minetest_game/mods/doors/sounds + "fire_flint_and_steel", -- ./games/minetest_game/mods/fire/sounds + "fire_large", -- ./games/minetest_game/mods/fire/sounds + "fire_fire", -- ./games/minetest_game/mods/fire/sounds + "fire_extinguish_flame", -- ./games/minetest_game/mods/fire/sounds + "fire_small", -- ./games/minetest_game/mods/fire/sounds + "tnt_ignite", -- ./games/minetest_game/mods/tnt/sounds + "tnt_gunpowder_burning", -- ./games/minetest_game/mods/tnt/sounds + "tnt_explode", -- ./games/minetest_game/mods/tnt/sounds + "carts_cart_new", -- ./games/minetest_game/mods/carts/sounds + "carts_cart_moving", -- ./games/minetest_game/mods/carts/sounds + "xpanes_steel_bar_door_open", -- ./games/minetest_game/mods/xpanes/sounds + "xpanes_steel_bar_door_close", -- ./games/minetest_game/mods/xpanes/sounds + "default_break_glass", -- ./games/minetest_game/mods/default/sounds + "default_dig_dig_immediate", -- ./games/minetest_game/mods/default/sounds + "default_dig_cracky", -- ./games/minetest_game/mods/default/sounds + "default_dig_choppy", -- ./games/minetest_game/mods/default/sounds + "default_water_footstep", -- ./games/minetest_game/mods/default/sounds + "player_damage", -- ./games/minetest_game/mods/default/sounds + "default_gravel_footstep", -- ./games/minetest_game/mods/default/sounds + "default_dig_metal", -- ./games/minetest_game/mods/default/sounds + "default_gravel_dug", -- ./games/minetest_game/mods/default/sounds + "default_hard_footstep", -- ./games/minetest_game/mods/default/sounds + "default_sand_footstep", -- ./games/minetest_game/mods/default/sounds + "default_grass_footstep", -- ./games/minetest_game/mods/default/sounds + "default_chest_close", -- ./games/minetest_game/mods/default/sounds + "default_cool_lava", -- ./games/minetest_game/mods/default/sounds + "default_place_node_hard", -- ./games/minetest_game/mods/default/sounds + "default_ice_dug", -- ./games/minetest_game/mods/default/sounds + "default_dig_crumbly", -- ./games/minetest_game/mods/default/sounds + "default_tool_breaks", -- ./games/minetest_game/mods/default/sounds + "default_ice_footstep", -- ./games/minetest_game/mods/default/sounds + "default_dig_cracky", -- ./games/minetest_game/mods/default/sounds + "default_chest_open", -- ./games/minetest_game/mods/default/sounds + "default_gravel_dig", -- ./games/minetest_game/mods/default/sounds + "default_dig_oddly_breakable_by_hand", -- ./games/minetest_game/mods/default/sounds + "default_dug_metal", -- ./games/minetest_game/mods/default/sounds + "default_dirt_footstep", -- ./games/minetest_game/mods/default/sounds + "default_dig_choppy", -- ./games/minetest_game/mods/default/sounds + "default_glass_footstep", -- ./games/minetest_game/mods/default/sounds + "default_snow_footstep", -- ./games/minetest_game/mods/default/sounds + "default_place_node", -- ./games/minetest_game/mods/default/sounds + "default_dig_snappy", -- ./games/minetest_game/mods/default/sounds + "default_dug_node", -- ./games/minetest_game/mods/default/sounds + "default_metal_footstep", -- ./games/minetest_game/mods/default/sounds + "default_ice_dig", -- ./games/minetest_game/mods/default/sounds + "default_place_node_metal", -- ./games/minetest_game/mods/default/sounds + "default_wood_footstep", -- ./games/minetest_game/mods/default/sounds + "default_furnace_active", -- ./games/minetest_game/mods/default/sounds + "default_item_smoke", -- ./games/minetest_game/mods/default/sounds +} diff --git a/collider/cooler.lua b/collider/cooler.lua new file mode 100644 index 0000000..4161b08 --- /dev/null +++ b/collider/cooler.lua @@ -0,0 +1,91 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019-2021 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + TA4 Cooler as part of the Collider + +]]-- + +-- for lazy programmers +local M = minetest.get_meta +local S = techage.S + +local Pipe = techage.LiquidPipe + +minetest.register_node("techage:ta4_collider_cooler", { + description = S("TA4 Collider Cooler"), + tiles = { + -- up, down, right, left, back, front + { + image = "techage_appl_cooler4.png^techage_frame4_ta4_top.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 32, + aspect_h = 32, + length = 0.4, + }, + }, + { + image = "techage_appl_cooler4.png^techage_frame4_ta4_top.png", + backface_culling = false, + animation = { + type = "vertical_frames", + aspect_w = 32, + aspect_h = 32, + length = 0.4, + }, + }, + "techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_hole_pipe.png", + "techage_filling_ta4.png^techage_frame_ta4.png^techage_appl_hole_pipe.png", + "techage_filling_ta4.png^techage_frame_ta4.png^techage_cooler.png", + "techage_filling_ta4.png^techage_frame_ta4.png^techage_cooler.png", + }, + drawtype = "nodebox", + paramtype2 = "facedir", + groups = {cracky = 1}, + on_rotate = screwdriver.disallow, + is_ground_content = false, + sounds = default.node_sound_metal_defaults(), + networks = { + pipe2 = {}, + }, + + after_place_node = function(pos, placer, itemstack) + Pipe:after_place_node(pos) + end, + + after_dig_node = function(pos, oldnode) + Pipe:after_dig_node(pos) + techage.del_mem(pos) + end, +}) + +Pipe:add_secondary_node_names({"techage:ta4_collider_cooler"}) +Pipe:set_valid_sides("techage:ta4_collider_cooler", {"R", "L"}) + +techage.register_node({"techage:ta4_collider_cooler"}, { + on_transfer = function(pos, in_dir, topic, payload) + if topic == "cooler" then + return true + else + return false + end + end, +}) + +minetest.register_craft({ + output = "techage:ta4_collider_cooler", + recipe = { + {'', 'dye:blue', ''}, + {'', 'techage:cooler', ''}, + {'', 'techage:aluminum', ''}, + }, +}) + diff --git a/collider/detector.lua b/collider/detector.lua new file mode 100644 index 0000000..7470858 --- /dev/null +++ b/collider/detector.lua @@ -0,0 +1,379 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019-2021 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + TA4 Detector as part of the Collider + +]]-- + +-- for lazy programmers +local M = minetest.get_meta +local S = techage.S +local S2P = minetest.string_to_pos +local P2S = minetest.pos_to_string +local getpos = techage.assemble.get_pos + +local CYCLE_TIME = 2 +local TNO_MAGNETS = 22 +local PROBABILITY = 90 -- every 30 min. + +local function tube_damage_check(pos, node, meta, nvm) + local resp = techage.tube_inlet_command(pos, "check") + if resp then + return true + end + return false, "Tube defect" +end + +local Schedule = {[0] = + -- Route: 0 = forward, 1 = right, 2 = backward, 3 = left + -- Gas left/right + {name = "techage:ta4_collider_pipe_inlet", yoffs = 1, route = {3,3,3,2}, check = techage.gas_inlet_check}, + {name = "techage:ta4_collider_pipe_inlet", yoffs = 1, route = {1,1,1,2}, check = techage.gas_inlet_check}, + -- Power left/right + {name = "techage:ta4_collider_cable_inlet", yoffs = 2, route = {3,3,3}, check = techage.power_inlet_check}, + {name = "techage:ta4_collider_cable_inlet", yoffs = 2, route = {1,1,1}, check = techage.power_inlet_check}, + -- Tube left/right + --{name = "techage:ta4_collider_tube_inlet", yoffs = 1, route = {3,3,3}, check = techage.tube_inlet_check, no_vacuum=true}, + --{name = "techage:ta4_collider_tube_inlet", yoffs = 1, route = {1,1,1}, check = techage.tube_inlet_check, no_vacuum=true}, + -- Cooler + {name = "techage:ta4_collider_pipe_inlet", yoffs = 0, route = {0}, check = techage.cooler_check}, + {name = "techage:ta4_collider_pipe_inlet", yoffs = 2, route = {0}, check = techage.cooler_check}, + -- Air outlet + {name = "techage:ta4_collider_pipe_outlet", yoffs = 2, route = {}, check = techage.air_outlet_check}, +} + +local TIME_SLOTS = #Schedule + 2 + +local function play_sound(pos) + minetest.sound_play("techage_hum", { + pos = pos, + gain = 0.5, + max_hear_distance = 10, + }) +end + +local function terminal_message(pos, msg) + local term_num = M(pos):contains("term_num") and M(pos):get_string("term_num") + local own_num = M(pos):get_string("node_number") + + if term_num and own_num then + techage.send_single(own_num, term_num, "text", msg) + end +end + +local function experience_points(pos) + if math.random(PROBABILITY) == 1 then + local owner = M(pos):get_string("owner") + local own_num = M(pos):get_string("node_number") + local player = minetest.get_player_by_name(owner) + if player then + if techage.add_expoint(player, own_num) then + terminal_message(pos, "Experience point reached!") + end + end + end +end + +local function check_state(pos) + -- Cyclically check all connections + local param2 = minetest.get_node(pos).param2 + local nvm = techage.get_nvm(pos) + nvm.ticks = (nvm.ticks or 0) + 1 + local idx = nvm.ticks % TIME_SLOTS + local item = Schedule[idx] + + if idx == 1 then + nvm.result = true + end + + if item then + local pos2 = getpos(pos, param2, item.route, item.yoffs) + local nvm2 = techage.get_nvm(pos2) + local meta2 = M(pos2) + local node2 = minetest.get_node(pos2) + if item.name == node2.name then + local res, err = item.check(pos2, node2, meta2, nvm2) + --print("check_state", idx, res, err) + if not res then + nvm.result = false + nvm.runnning = false + terminal_message(pos, (err or "unknown") .. "!!!") + return nvm.result + end + else + nvm.result = false + nvm.runnning = false + terminal_message(pos, "Detector defect!!!") + end + elseif idx == #Schedule + 1 then + return nvm.result + end +end + +local function add_laser(pos) + local param2 = minetest.get_node(pos).param2 + local pos1 = getpos(pos, param2, {3,3}, 1) + local pos2 = getpos(pos, param2, {1,1,1}, 1) + techage.del_laser(pos) + techage.add_laser(pos, pos1, pos2) +end + +local function create_task(pos, task) + local mem = techage.get_mem(pos) + if not mem.co then + mem.co = coroutine.create(task) + end + + local _, err = coroutine.resume(mem.co, pos) + if err then + mem.co = nil + --print(err) + return + end + minetest.after(0.4, create_task, pos) +end + +-- Call on_cyclic_check of all magents so that the magnets don't need a FLB. +local function magnet_on_cyclic_check(pos, nvm) + local ndef = minetest.registered_nodes["techage:ta4_magnet"] + for idx,pos2 in ipairs(nvm.magnet_positions or {}) do + local res = ndef.on_cyclic_check(pos2) + if res == -2 then + terminal_message(pos, "Magnet #" .. idx .. " defect!!!") + return false + elseif res == -1 then + terminal_message(pos, "Vacuum defect!!!") + techage.air_outlet_reset({x=pos.x, y=pos.y + 2, z=pos.z}) + return false + end + end + return true +end + +minetest.register_node("techage:ta4_detector_core", { + description = S("TA4 Collider Detector Core"), + tiles = { + -- up, down, right, left, back, front + "default_steel_block.png", + "default_steel_block.png", + "default_steel_block.png^techage_collider_detector_core.png", + "default_steel_block.png^techage_collider_detector_core.png", + "default_steel_block.png^techage_collider_detector_core.png", + "default_steel_block.png^techage_collider_detector_core.png", + }, + drawtype = "nodebox", + paramtype2 = "facedir", + groups = {cracky = 1}, + is_ground_content = false, + sounds = default.node_sound_metal_defaults(), + + after_place_node = function(pos, placer, itemstack) + local nvm = techage.get_nvm(pos) + local meta = M(pos) + local own_num = techage.add_node(pos, "techage:ta4_detector_core") + meta:set_string("node_number", own_num) + meta:set_string("owner", placer:get_player_name()) + M({x=pos.x, y=pos.y - 1, z=pos.z}):set_string("infotext", S("TA4 Collider Detector " .. own_num)) + minetest.get_node_timer(pos):start(CYCLE_TIME) + end, + + on_timer = function(pos, elapsed) + local nvm = techage.get_nvm(pos) + if not magnet_on_cyclic_check(pos, nvm) then + techage.del_laser(pos) + if nvm.running then + terminal_message(pos, "Detector stopped.") + nvm.running = false + end + nvm.magnet_positions = nil + elseif nvm.running then + local res = check_state(pos) + if res == true then + experience_points(pos) + add_laser(pos) + if nvm.ticks <= TIME_SLOTS then -- only once + terminal_message(pos, "Detector running.") + end + elseif res == false then + techage.del_laser(pos) + nvm.running = false + nvm.magnet_positions = nil + terminal_message(pos, "Detector stopped.") + end + if nvm.running then + play_sound(pos) + end + end + return true + end, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + techage.on_remove_collider(digger) + techage.remove_node(pos, oldnode, oldmetadata) + techage.del_mem(pos) + end, +}) + +local function check_expr(own_num, term_num, text, expr) + techage.send_single(own_num, term_num, "text", text .. "..." .. (expr and "ok" or "error!!!")) + return expr +end + +local function start_task(pos) + local term_num = M(pos):contains("term_num") and M(pos):get_string("term_num") + local param2 = minetest.get_node(pos).param2 + local pos2 = getpos(pos, param2, {3,3,3}, 1) + local own_num = M(pos):get_string("node_number") + local nvm = techage.get_nvm(pos) + nvm.magnet_positions = {} + + if term_num and param2 and pos2 then + techage.send_single(own_num, term_num, "text", "#### Start ####") + + coroutine.yield() + local resp = techage.tube_inlet_command(pos2, "enumerate", 1) + if not check_expr(own_num, term_num, "- Check number of magnets", resp == TNO_MAGNETS) then + return + end + + coroutine.yield() + techage.send_single(own_num, term_num, "text", "- Check position of magnets...") + resp = techage.tube_inlet_command(pos2, "distance") + if resp ~= true then + techage.send_single(own_num, term_num, "append", "#" .. resp .. " defect!!!") + return + end + techage.send_single(own_num, term_num, "append", "ok") + + coroutine.yield() + techage.send_single(own_num, term_num, "text", "- Start magnets...") + for num = 1, TNO_MAGNETS do + local resp = techage.tube_inlet_command(pos2, "pos", num) + if not resp or type(resp) ~= "table" then + techage.send_single(own_num, term_num, "append", "#" .. num .. " defect!!!") + nvm.magnet_positions = nil + return + else + nvm.magnet_positions[#nvm.magnet_positions + 1] = resp + end + coroutine.yield() + end + techage.send_single(own_num, term_num, "append", "ok") + + coroutine.yield() + techage.send_single(own_num, term_num, "text", "- Check magnets...") + -- The check will be performed by the timer, so wait 5 sec. + for i = 1,14 do + coroutine.yield() + end + if nvm.magnet_positions then + techage.send_single(own_num, term_num, "append", "ok") + else + return + end + + coroutine.yield() + techage.send_single(own_num, term_num, "text", "- Check detector...") + for _,item in ipairs(Schedule)do + local pos2 = getpos(pos, param2, item.route, item.yoffs) + local nvm2 = techage.get_nvm(pos2) + local meta2 = M(pos2) + local node2 = minetest.get_node(pos2) + if item.name == node2.name then + local res, err = item.check(pos2, node2, meta2, nvm2) + if not res then + techage.send_single(own_num, term_num, "append", err .. "!!!") + nvm.magnet_positions = nil + return + end + else + techage.send_single(own_num, term_num, "append", "defect!!!") + nvm.magnet_positions = nil + return + end + coroutine.yield() + end + techage.send_single(own_num, term_num, "append", "ok") + + coroutine.yield() + techage.send_single(own_num, term_num, "text", "Ready.") + nvm.ticks = 0 + nvm.running = true + end +end + +local function test_magnet(pos, payload) + local term_num = M(pos):contains("term_num") and M(pos):get_string("term_num") + local param2 = minetest.get_node(pos).param2 + local pos2 = getpos(pos, param2, {3,3,3}, 1) + local own_num = M(pos):get_string("node_number") + local magnet_num = tonumber(payload) + local res, err = techage.tube_inlet_command(pos2, "test", magnet_num) + if res then + techage.send_single(own_num, term_num, "text", "magnet #" .. magnet_num .. ": ok") + else + techage.send_single(own_num, term_num, "text", "magnet #" .. magnet_num .. ": " .. err .. "!!!") + end +end + +techage.register_node({"techage:ta4_detector_core"}, { + on_recv_message = function(pos, src, topic, payload) + local nvm = techage.get_nvm(pos) + if topic == "connect" then + M(pos):set_string("term_num", src) + return true + elseif topic == "start" then + create_task(pos, start_task) + return true + elseif topic == "stop" then + nvm.running = false + techage.del_laser(pos) + return "Detector stopped." + elseif topic == "status" then + if nvm.running == true then + return "running" + elseif nvm.result == false then + return "fault" + else + return "stopped" + end + elseif topic == "test"then + if payload and tonumber(payload) then + test_magnet(pos, payload) + return true + else + return "Invalid magnet number" + end + elseif topic == "points" then + local owner = M(pos):get_string("owner") + local player = minetest.get_player_by_name(owner) + if player then + local points = techage.get_expoints(player) + return "Ex. Points = " .. points + end + else + return "unsupported" + end + end, + on_node_load = function(pos) + minetest.get_node_timer(pos):start(CYCLE_TIME) + end, +}) + + +minetest.register_craft({ + output = "techage:ta4_detector_core", + recipe = { + {'techage:aluminum', 'basic_materials:heating_element', 'default:steel_ingot'}, + {'default:diamond', 'techage:ta4_wlanchip', 'techage:electric_cableS'}, + {'default:steel_ingot', '', 'techage:aluminum'}, + }, +}) + diff --git a/collider/inlets.lua b/collider/inlets.lua new file mode 100644 index 0000000..baf7c35 --- /dev/null +++ b/collider/inlets.lua @@ -0,0 +1,364 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019-2021 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + TA4 Tube/Pipe Inlets as part of the Collider + +]]-- + +-- for lazy programmers +local M = minetest.get_meta +local S = techage.S + +local PWR_NEEDED = 15 +local CYCLE_TIME = 2 +local GAS_CAPA = 20 +local AIR_CAPA = 1000 + +local VTube = techage.VTube +local Pipe = techage.LiquidPipe +local Cable = techage.ElectricCable +local power = networks.power +local liquid = networks.liquid + +-------------------------------------------------------------------------------- +-- Tube Inlet +-------------------------------------------------------------------------------- +minetest.register_node("techage:ta4_collider_tube_inlet", { + description = S("TA4 Collider Tube Inlet"), + tiles = { + -- up, down, right, left, back, front + "default_steel_block.png", + "default_steel_block.png", + "default_steel_block.png", + "default_steel_block.png", + "default_steel_block.png", + "default_steel_block.png^techage_collider_tube_open.png", + }, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-4/8, -4/8, -4/8, -1/8, 4/8, 4/8}, + { 1/8, -4/8, -4/8, 4/8, 4/8, 4/8}, + {-4/8, 1/8, -4/8, 4/8, 4/8, 4/8}, + {-4/8, -4/8, -4/8, 4/8, -1/8, 4/8}, + }, + }, + selection_box = { + type = "fixed", + fixed = {-4/8, -4/8, -4/8, 4/8, 4/8, 4/8}, + }, + paramtype2 = "facedir", + groups = {cracky = 1}, + on_rotate = screwdriver.disallow, + is_ground_content = false, + sounds = default.node_sound_metal_defaults(), + + after_place_node = function(pos, placer, itemstack) + VTube:after_place_node(pos) + end, + + after_dig_node = function(pos, oldnode) + VTube:after_dig_node(pos) + techage.del_mem(pos) + end, +}) + +VTube:add_secondary_node_names({"techage:ta4_collider_tube_inlet"}) +VTube:set_valid_sides("techage:ta4_collider_tube_inlet", {"F"}) + +-- Called from the detector via tube ring +techage.register_node({"techage:ta4_collider_tube_inlet"}, { + on_transfer = function(pos, in_dir, topic, payload) + if topic == "distance" then + return pos + elseif topic == "enumerate" and payload then + return payload - 1 + elseif topic == "check" then + local nvm = techage.get_nvm(pos) + nvm.check_received = true + return true + end + end, +}) + +-- Used by the detector to check the tube connection +function techage.tube_inlet_command(pos, command, payload) + if command == "distance" then + local pos2 = techage.transfer(pos, "F", command, payload, VTube, {"techage:ta4_magnet"}) + if type(pos2) == "table" then + local dist = math.abs(pos.x - pos2.x) + math.abs(pos.z - pos2.z) + if pos.y == pos2.y and dist == VTube.max_tube_length + 1 then + return true + end + return 0 + else + return pos2 + end + end + return techage.transfer(pos, "F", command, payload, VTube, {"techage:ta4_magnet"}) +end + +minetest.register_craft({ + output = "techage:ta4_collider_tube_inlet", + recipe = { + {'', '', ''}, + {'techage:ta4_vtubeS', 'default:steelblock', ''}, + {'', '', ''}, + }, +}) + +-------------------------------------------------------------------------------- +-- Pipe Inlet (gas) +-------------------------------------------------------------------------------- +minetest.register_node("techage:ta4_collider_pipe_inlet", { + description = S("TA4 Collider Pipe Inlet"), + tiles = { + -- up, down, right, left, back, front + "default_steel_block.png", + "default_steel_block.png", + "default_steel_block.png", + "default_steel_block.png", + "default_steel_block.png", + "default_steel_block.png^techage_appl_hole_pipe.png", + }, + drawtype = "nodebox", + paramtype2 = "facedir", + groups = {cracky = 1}, + on_rotate = screwdriver.disallow, + is_ground_content = false, + sounds = default.node_sound_metal_defaults(), + networks = { + pipe2 = {}, + }, + + after_place_node = function(pos, placer, itemstack) + local nvm = techage.get_nvm(pos) + Pipe:after_place_node(pos) + nvm.liquid = {} + end, + + after_dig_node = function(pos, oldnode) + Pipe:after_dig_node(pos) + techage.del_mem(pos) + end, +}) + +liquid.register_nodes({"techage:ta4_collider_pipe_inlet"}, Pipe, "tank", {"F"}, { + capa = GAS_CAPA, + peek = function(pos, indir) + local nvm = techage.get_nvm(pos) + return liquid.srv_peek(nvm) + end, + put = function(pos, indir, name, amount) + local nvm = techage.get_nvm(pos) + return liquid.srv_put(nvm, name, amount, GAS_CAPA) + end, + take = function(pos, indir, name, amount) + local nvm = techage.get_nvm(pos) + return liquid.srv_take(nvm, name, amount) + end, + untake = function(pos, indir, name, amount) + local nvm = techage.get_nvm(pos) + liquid.srv_put(nvm, name, amount, GAS_CAPA) + end, +}) + +techage.register_node({"techage:ta4_collider_pipe_inlet"}, { + on_transfer = function(pos, in_dir, topic, payload) + -- called from heatexchanger + if topic == "detector" then + local nvm = techage.get_nvm(pos) + nvm.detector_received = true + return true + end + end, +}) + +-- Used by the detector to check for gas pressure +function techage.gas_inlet_check(pos, node, meta, nvm) + nvm.liquid = nvm.liquid or {} + if nvm.liquid.amount == GAS_CAPA and nvm.liquid.name == "techage:hydrogen" then + return true + end + return false, "no gas" +end + +-- Used by the detector to check for cooler connection +function techage.cooler_check(pos, node, meta, nvm) + if nvm.detector_received then + nvm.detector_received = nil + return true + end + return false, "Cooler defect" +end + +minetest.register_craft({ + output = "techage:ta4_collider_pipe_inlet", + recipe = { + {'', '', ''}, + {'techage:ta3_pipeS', 'default:steelblock', ''}, + {'', '', ''}, + }, +}) + + +-------------------------------------------------------------------------------- +-- Pipe Outlet (air) +-------------------------------------------------------------------------------- +local function init_air(nvm) + nvm.liquid = { + amount = AIR_CAPA, + name = "air", + } + return nvm.liquid +end + +minetest.register_node("techage:ta4_collider_pipe_outlet", { + description = S("TA4 Collider Pipe Outlet"), + tiles = { + -- up, down, right, left, back, front + "default_steel_block.png^techage_appl_hole_pipe.png", + "default_steel_block.png", + "default_steel_block.png", + "default_steel_block.png", + "default_steel_block.png", + "default_steel_block.png", + }, + drawtype = "nodebox", + paramtype2 = "facedir", + groups = {cracky = 1}, + on_rotate = screwdriver.disallow, + is_ground_content = false, + sounds = default.node_sound_metal_defaults(), + networks = { + pipe2 = {}, + }, + + after_place_node = function(pos, placer, itemstack) + local nvm = techage.get_nvm(pos) + init_air(nvm) + Pipe:after_place_node(pos) + end, + + after_dig_node = function(pos, oldnode) + Pipe:after_dig_node(pos) + techage.del_mem(pos) + end, +}) + +liquid.register_nodes({"techage:ta4_collider_pipe_outlet"}, Pipe, "tank", {"U"}, { + capa = AIR_CAPA, + peek = function(pos, indir) + local nvm = techage.get_nvm(pos) + return liquid.srv_peek(nvm) + end, + put = function(pos, indir, name, amount) + local nvm = techage.get_nvm(pos) + return liquid.srv_put(nvm, name, amount, AIR_CAPA) + end, + take = function(pos, indir, name, amount) + local nvm = techage.get_nvm(pos) + return liquid.srv_take(nvm, name, amount) + end, + untake = function(pos, indir, name, amount) + local nvm = techage.get_nvm(pos) + liquid.srv_put(nvm, name, amount, AIR_CAPA) + end, +}) + +-- Used by the detector to check the vacuum +function techage.air_outlet_check(pos, node, meta, nvm) + nvm.liquid = nvm.liquid or {} + if nvm.liquid.amount == 0 then + return true + end + return false, "no vacuum" +end + +function techage.air_outlet_reset(pos) + local nvm = techage.get_nvm(pos) + init_air(nvm) +end + +minetest.register_craft({ + output = "techage:ta4_collider_pipe_outlet", + recipe = { + {'', 'techage:ta3_pipeS', ''}, + {'', 'default:steelblock', ''}, + {'', '', ''}, + }, +}) + +-------------------------------------------------------------------------------- +-- Cable Inlet (power) +-------------------------------------------------------------------------------- +minetest.register_node("techage:ta4_collider_cable_inlet", { + description = S("TA4 Collider Cable Inlet"), + tiles = { + -- up, down, right, left, back, front + "default_steel_block.png", + "default_steel_block.png", + "default_steel_block.png", + "default_steel_block.png", + "default_steel_block.png", + "default_steel_block.png^techage_appl_hole_electric.png", + }, + drawtype = "nodebox", + paramtype2 = "facedir", + groups = {cracky = 1}, + on_rotate = screwdriver.disallow, + is_ground_content = false, + sounds = default.node_sound_metal_defaults(), + networks = { + pipe2 = {}, + }, + + after_place_node = function(pos, placer, itemstack) + Cable:after_place_node(pos) + minetest.get_node_timer(pos):start(CYCLE_TIME) + end, + + on_timer = function(pos, elapsed) + local nvm = techage.get_nvm(pos) + nvm.consumed = power.consume_power(pos, Cable, nil, PWR_NEEDED) + return true + end, + + after_dig_node = function(pos, oldnode) + Cable:after_dig_node(pos) + techage.del_mem(pos) + end, +}) + +-- Used by the detector to check for power +function techage.power_inlet_check(pos, node, meta, nvm) + if nvm.consumed == PWR_NEEDED then + return true + end + return false, "no power" +end + +power.register_nodes({"techage:ta4_collider_cable_inlet"}, Cable, "con", {"F"}) + +techage.register_node({"techage:ta4_collider_cable_inlet"}, { + on_node_load = function(pos) + minetest.get_node_timer(pos):start(CYCLE_TIME) + end, +}) + +minetest.register_craft({ + output = "techage:ta4_collider_cable_inlet", + recipe = { + {'', '', ''}, + {'techage:electric_cableS', 'default:steelblock', ''}, + {'', '', ''}, + }, +}) diff --git a/collider/magnet.lua b/collider/magnet.lua new file mode 100644 index 0000000..c84c95c --- /dev/null +++ b/collider/magnet.lua @@ -0,0 +1,271 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019-2021 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + TA4 Magnet as part of the Collider + +]]-- + +-- for lazy programmers +local M = minetest.get_meta +local S = techage.S +local S2P = minetest.string_to_pos +local P2S = minetest.pos_to_string + +local PWR_NEEDED = 5 +local CYCLE_TIME = 2 +local CAPACITY = 10 + +local Cable = techage.ElectricCable +local Pipe = techage.LiquidPipe +local VTube = techage.VTube +local power = networks.power +local liquid = networks.liquid + +minetest.register_node("techage:ta4_detector_magnet", { + description = S("TA4 Collider Detector Magnet"), + tiles = { + -- up, down, right, left, back, front + "techage_collider_magnet.png^techage_collider_magnet_appl.png", + "techage_collider_magnet.png^techage_collider_magnet_appl.png", + "techage_collider_magnet.png", + "techage_collider_magnet.png", + "techage_collider_magnet.png^techage_collider_magnet_appl.png", + "techage_collider_magnet.png^techage_collider_magnet_appl.png", + }, + drawtype = "nodebox", + paramtype2 = "facedir", + groups = {cracky = 1}, + is_ground_content = false, + sounds = default.node_sound_metal_defaults(), +}) + +minetest.register_node("techage:ta4_magnet", { + description = S("TA4 Collider Magnet"), + inventory_image = minetest.inventorycube( + "techage_collider_magnet.png^techage_appl_hole_electric.png", + "techage_collider_magnet.png^techage_appl_hole_pipe.png", + "techage_collider_magnet.png^techage_collider_magnet_tube.png"), + tiles = { + -- up, down, right, left, back, front + "techage_collider_magnet.png^techage_appl_hole_electric.png", + "techage_collider_magnet.png", + "techage_collider_magnet.png^techage_collider_magnet_tube.png", + "techage_collider_magnet.png^techage_collider_magnet_tube.png", + "techage_collider_magnet.png^techage_collider_magnet_appl.png^techage_appl_hole_pipe.png^techage_collider_magnet_sign.png", + "techage_collider_magnet.png^techage_collider_magnet_appl.png^techage_appl_hole_pipe.png^techage_collider_magnet_sign.png", + }, + drawtype = "nodebox", + use_texture_alpha = techage.CLIP, + node_box = { + type = "fixed", + fixed = { + {-11/16, -11/16, -11/16, 11/16, 11/16, -2/16}, + {-11/16, -11/16, 2/16, 11/16, 11/16, 11/16}, + {-11/16, 2/16, -11/16, 11/16, 11/16, 11/16}, + {-11/16, -11/16, -11/16, 11/16, -2/16, 11/16}, + }, + }, + selection_box = { + type = "fixed", + fixed = {-4/8, -4/8, -4/8, 4/8, 4/8, 4/8}, + }, + collision_box = { + type = "fixed", + fixed = {-11/16, -11/16, -11/16, 11/16, 11/16, 11/16}, + }, + wield_scale = {x = 0.8, y = 0.8, z = 0.8}, + paramtype2 = "facedir", + groups = {cracky = 1}, + on_rotate = screwdriver.disallow, + is_ground_content = false, + sounds = default.node_sound_metal_defaults(), + + after_place_node = function(pos, placer, itemstack) + if pos.y > techage.collider_min_depth then + minetest.remove_node(pos) + minetest.add_item(pos, ItemStack("techage:ta4_magnet")) + return + end + local nvm = techage.get_nvm(pos) + nvm.liquid = {} + Pipe:after_place_node(pos) + Cable:after_place_node(pos) + VTube:after_place_node(pos) + M(pos):set_string("infotext", S("TA4 Collider Magnet") .. " #0") + end, + + -- To be called by the detector + on_cyclic_check = function(pos) + local nvm = techage.get_nvm(pos) + nvm.liquid = nvm.liquid or {} + nvm.consumed = power.consume_power(pos, Cable, 6, PWR_NEEDED) + if nvm.tube_damage then + nvm.tube_damage = nil + return -1 + elseif nvm.liquid.amount == CAPACITY and + nvm.liquid.name == "techage:hydrogen" and + nvm.consumed == PWR_NEEDED then + return 0 + end + return -2 + end, + + tubelib2_on_update2 = function(pos, outdir, tlib2, node) + if tlib2.tube_type == "vtube" then + local nvm = techage.get_nvm(pos) + nvm.tube_damage = true + elseif tlib2.tube_type == "pipe2" then + local nvm = techage.get_nvm(pos) + nvm.liquid = nvm.liquid or {} + nvm.liquid.amount = 0 + end + end, + + after_dig_node = function(pos, oldnode) + Pipe:after_dig_node(pos) + Cable:after_dig_node(pos) + VTube:after_dig_node(pos) + techage.del_mem(pos) + end, +}) + +power.register_nodes({"techage:ta4_magnet"}, Cable, "con", {"U"}) +liquid.register_nodes({"techage:ta4_magnet"}, Pipe, "tank", {"F", "B"}, { + capa = CAPACITY, + peek = function(pos, indir) + local nvm = techage.get_nvm(pos) + return liquid.srv_peek(nvm) + end, + put = function(pos, indir, name, amount) + local nvm = techage.get_nvm(pos) + return liquid.srv_put(nvm, name, amount, CAPACITY) + end, + take = function(pos, indir, name, amount) + local nvm = techage.get_nvm(pos) + return liquid.srv_take(nvm, name, amount) + end, + untake = function(pos, indir, name, amount) + local nvm = techage.get_nvm(pos) + liquid.srv_put(nvm, name, amount, CAPACITY) + end, +}) + +VTube:add_secondary_node_names({"techage:ta4_magnet"}) +VTube:set_valid_sides("techage:ta4_magnet", {"R", "L"}) + +local function send_to_next(pos, in_dir, topic, payload) + return techage.transfer(pos, in_dir, topic, payload, VTube, + {"techage:ta4_magnet", "techage:ta4_collider_tube_inlet"}) +end + +--[[ +Commands +-------- + +distance : Check distance between all magnets. + Returns pos of next magnet or the number of the defect magnet. +enumerate : Give each magnet a unique number (1...n) +pos : Read the position +test : Test all magnet attributs. + Returns true or false, err +]]-- +techage.register_node({"techage:ta4_magnet"}, { + on_transfer = function(pos, in_dir, topic, payload) + local nvm = techage.get_nvm(pos) + if topic == "distance" then + local pos2 = send_to_next(pos, in_dir, topic, payload) + if type(pos2) == "table" then + local dist = math.abs(pos.x - pos2.x) + math.abs(pos.z - pos2.z) + if pos.y == pos2.y and dist == VTube.max_tube_length + 1 then + return pos + end + return nvm.number or 0 + else + return pos2 + end + elseif topic == "enumerate" and payload then + payload = tonumber(payload) or 1 + nvm.number = payload + M(pos):set_string("infotext", S("TA4 Collider Magnet") .. " #" .. payload) + return send_to_next(pos, in_dir, topic, payload + 1) + elseif topic == "pos" then + if payload and tonumber(payload) == nvm.number then + return pos + else + return send_to_next(pos, in_dir, topic, payload) + end + elseif topic == "test" then + if payload and tonumber(payload) == nvm.number then + if not nvm.liquid or nvm.liquid.amount < CAPACITY then + return false, "no gas" + elseif nvm.liquid.name ~= "techage:hydrogen" then + return false, "wrong gas" + elseif nvm.consumed ~= PWR_NEEDED then + return false, "no power" + elseif nvm.tube_damage then + nvm.tube_damage = nil + return false, "no vacuum" + end + return true + else + return send_to_next(pos, in_dir, topic, payload) + end + end + end, +}) + +minetest.register_node("techage:ta4_magnet_base", { + description = S("TA4 Collider Magnet Base"), + tiles = { + -- up, down, right, left, back, front + "default_steel_block.png", + }, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-6/16, -8/16, -6/16, 6/16, 5/16, 6/16}, + }, + }, + paramtype2 = "facedir", + groups = {cracky = 1}, + is_ground_content = false, + paramtype = "light", + use_texture_alpha = techage.CLIP, + sounds = default.node_sound_metal_defaults(), +}) + + +minetest.register_craft({ + output = "techage:ta4_detector_magnet 2", + recipe = { + {'default:steel_ingot', '', 'techage:aluminum'}, + {'dye:red', 'basic_materials:gold_wire', 'dye:brown'}, + {'techage:aluminum', '', 'default:steel_ingot'}, + }, +}) + +minetest.register_craft({ + output = "techage:ta4_magnet", + recipe = { + {'techage:ta3_pipeS', '', 'techage:electric_cableS'}, + {'techage:ta4_round_ceramic', 'techage:ta4_detector_magnet', 'techage:ta4_round_ceramic'}, + {'', '', ''}, + }, +}) + +minetest.register_craft({ + output = "techage:ta4_magnet_base 4", + recipe = { + {'techage:aluminum', 'default:steel_ingot', ''}, + {'techage:aluminum', 'default:steel_ingot', ''}, + {'techage:aluminum', 'default:steel_ingot', ''}, + }, +}) diff --git a/collider/terminal.lua b/collider/terminal.lua new file mode 100644 index 0000000..3d1c7ea --- /dev/null +++ b/collider/terminal.lua @@ -0,0 +1,208 @@ +--[[ + + Techage + ======= + + Copyright (C) 2020-2021 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + TA4 Terminal + +]]-- + +local M = minetest.get_meta +local S = techage.S + +local STR_LEN = 80 +local HELP = [[#### TA4 Terminal #### + +Send commands to the connected machine +and output text messages from the +machine. + +Commands can have up to 80 characters. +Local commands: +- clear = clear screen +- help = this message +- pub = switch to public use +- priv = switch to private use +- connect = connect the machine + +All other commands are machine dependent. +]] + +local function get_string(meta, num, default) + local s = meta:get_string("bttn_text"..num) + if not s or s == "" then + return default + end + return s +end + +local function formspec2(mem) + mem.command = mem.command or "" + mem.output = mem.output or "" + local output = minetest.formspec_escape(mem.output) + output = output:gsub("\n", ",") + local command = minetest.formspec_escape(mem.command) + local bttn_text1 = get_string(meta, 1, "User1") + local bttn_text2 = get_string(meta, 2, "User2") + local bttn_text3 = get_string(meta, 3, "User3") + local bttn_text4 = get_string(meta, 4, "User4") + local bttn_text5 = get_string(meta, 5, "User5") + local bttn_text6 = get_string(meta, 6, "User6") + local bttn_text7 = get_string(meta, 7, "User7") + local bttn_text8 = get_string(meta, 8, "User8") + local bttn_text9 = get_string(meta, 9, "User9") + return "size[10,8]".. + "style_type[table,field;font=mono]".. + "button[0,0;3.3,1;bttn1;"..bttn_text1.."]button[3.3,0;3.3,1;bttn2;"..bttn_text2.."]button[6.6,0;3.3,1;bttn3;"..bttn_text3.."]".. + "button[0,0.8;3.3,1;bttn4;"..bttn_text4.."]button[3.3,0.8;3.3,1;bttn5;"..bttn_text5.."]button[6.6,0.8;3.3,1;bttn6;"..bttn_text6.."]".. + "button[0,1.6;3.3,1;bttn7;"..bttn_text7.."]button[3.3,1.6;3.3,1;bttn8;"..bttn_text8.."]button[6.6,1.6;3.3,1;bttn9;"..bttn_text9.."]".. + "table[0,2.5;9.8,4.7;output;"..output..";200]".. + "field[0.4,7.7;7.6,1;cmnd;;"..mem.command.."]" .. + "field_close_on_enter[cmnd;false]".. + "button[7.9,7.4;2,1;enter;"..S("Enter").."]" +end + +local function output(pos, text) + local mem = techage.get_mem(pos) + mem.output = mem.output .. "\n" .. (text or "") + mem.output = mem.output:sub(-500,-1) + M(pos):set_string("formspec", formspec2(mem)) +end + +local function command(pos, mem, player) + local meta = minetest.get_meta(pos) + local owner = meta:get_string("owner") + + if mem.command == "clear" then + mem.output = "" + mem.command = "" + meta:set_string("formspec", formspec2(mem)) + elseif mem.command == "" then + output(pos, ">") + mem.command = "" + meta:set_string("formspec", formspec2(mem)) + elseif mem.command == "help" then + local meta = minetest.get_meta(pos) + mem.output = HELP + mem.command = "" + meta:set_string("formspec", formspec2(mem)) + elseif mem.command == "pub" and owner == player then + meta:set_int("public", 1) + output(pos, "> "..mem.command) + mem.command = "" + output(pos, "Switched to public use!") + elseif mem.command == "priv" and owner == player then + meta:set_int("public", 0) + output(pos, "> "..mem.command) + mem.command = "" + output(pos, "Switched to private use!") + elseif meta:get_int("public") == 1 or owner == player then + if mem.command == "clear" then + mem.output = + mem.command = "" + meta:set_string("formspec", formspec2(mem)) + end + end +end + +minetest.register_node("techage:ta4_terminal", { + description = "TA4 Collider Terminal", + tiles = { + -- up, down, right, left, back, front + 'techage_terminal1_top.png', + 'techage_terminal1_bottom.png', + 'techage_terminal1_side.png', + 'techage_terminal1_side.png', + 'techage_terminal1_bottom.png', + "techage_terminal1_front.png", + }, + drawtype = "nodebox", + node_box = { + type = "fixed", + fixed = { + {-12/32, -16/32, -8/32, 12/32, -14/32, 12/32}, + {-12/32, -14/32, 12/32, 12/32, 6/32, 14/32}, + }, + }, + selection_box = { + type = "fixed", + fixed = { + {-12/32, -16/32, -8/32, 12/32, -14/32, 12/32}, + {-12/32, -14/32, 12/32, 12/32, 6/32, 14/32}, + }, + }, + + after_place_node = function(pos, placer) + local number = techage.add_node(pos, minetest.get_node(pos).name) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", formspec1()) + meta:set_string("owner", placer:get_player_name()) + meta:set_string("infotext", S("TA4 Collider Terminal") .. ": " .. S("not connected") + end, + + on_receive_fields = function(pos, formname, fields, player) + local meta = minetest.get_meta(pos) + local mem = techage.get_mem(pos) + if fields.number and fields.number ~= "" then + local owner = meta:get_string("owner") + if techage.check_numbers(fields.number, owner) then + local own_number = meta:get_string("own_number") + if techage.send_single(own_number, fields.number, "connect") == true then + meta:set_string("number", fields.number) + meta:set_string("infotext", S("TA4 Collider Terminal") .. ": " .. S("connected with") .. " " .. fields.number) + meta:set_string("formspec", formspec2(mem)) + end + end + elseif (fields.enter or fields.key_enter_field) and fields.cmnd then + mem.command = string.sub(fields.cmnd, 1, STR_LEN) + command(pos, mem, player:get_player_name()) + elseif fields.key_up then + mem.command = pdp13.historybuffer_priv(pos) + meta:set_string("formspec", formspec2(mem)) + elseif fields.key_down then + mem.command = pdp13.historybuffer_next(pos) + meta:set_string("formspec", formspec2(mem)) + end + end, + + after_dig_node = function(pos, oldnode, oldmetadata) + techage.remove_node(pos, oldnode, oldmetadata) + end, + + paramtype = "light", + use_texture_alpha = techage.CLIP, + sunlight_propagates = true, + paramtype2 = "facedir", + groups = {choppy=2, cracky=2, crumbly=2}, + is_ground_content = false, + sounds = default.node_sound_metal_defaults(), +}) + +minetest.register_craft({ + output = "techage:ta4_terminal", + recipe = { + {"", "techage:ta4_display", ""}, + {"dye:black", "techage:ta4_wlanchip", "default:copper_ingot"}, + {"", "techage:aluminum", ""}, + }, +}) + +techage.register_node({"techage:ta4_terminal"}, { + on_recv_message = function(pos, src, topic, payload) + if topic == "term" then + output(pos, payload) + return true + elseif topic == "clear" then + local mem = techage.get_mem(pos) + mem.output = "" + mem.command = "" + M(pos):set_string("formspec", formspec2(mem)) + return true + end + end, +}) diff --git a/collider/vacuumtube.lua b/collider/vacuumtube.lua new file mode 100644 index 0000000..ad5b2be --- /dev/null +++ b/collider/vacuumtube.lua @@ -0,0 +1,130 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019-2021 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + TA4 Vacuum Tube as part of the Collider + +]]-- + +-- for lazy programmers +local M = minetest.get_meta +local S = techage.S + +local VTube = tubelib2.Tube:new({ + dirs_to_check = {1,2,3,4}, + max_tube_length = 5, + tube_type = "vtube", + show_infotext = false, + primary_node_names = {"techage:ta4_vtubeS", "techage:ta4_vtubeA"}, + secondary_node_names = {"techage:ta4_magnet"}, + after_place_tube = function(pos, param2, tube_type, num_tubes) + minetest.swap_node(pos, {name = "techage:ta4_vtube"..tube_type, param2 = param2}) + end, +}) + +techage.VTube = VTube + +minetest.register_node("techage:ta4_vtubeS", { + description = S("TA4 Vacuum Tube"), + drawtype = "nodebox", + tiles = { + -- up, down, right, left, back, front + "techage_collider_tube.png^[transformR90", + "techage_collider_tube.png^[transformR90", + "techage_collider_tube.png", + "techage_collider_tube.png", + 'techage_collider_tube_open.png', + 'techage_collider_tube_open.png', + }, + node_box = { + type = "fixed", + fixed = { + {-8/16, -8/16, -8/16, -6/16, 8/16, 8/16}, + { 6/16, -8/16, -8/16, 8/16, 8/16, 8/16}, + {-8/16, 6/16, -8/16, 8/16, 8/16, 8/16}, + {-8/16, -8/16, -8/16, 8/16, -6/16, 8/16}, + }, + }, + selection_box = { + type = "fixed", + fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16}, + }, + + after_place_node = function(pos, placer, itemstack, pointed_thing) + if not VTube:after_place_tube(pos, placer, pointed_thing) then + minetest.remove_node(pos) + return true + end + return false + end, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + VTube:after_dig_tube(pos, oldnode, oldmetadata) + end, + + paramtype2 = "facedir", -- important! + on_rotate = screwdriver.disallow, -- important! + paramtype = "light", + use_texture_alpha = techage.CLIP, + sunlight_propagates = true, + is_ground_content = false, + groups = {cracky = 2}, + sounds = default.node_sound_metal_defaults(), +}) + +minetest.register_node("techage:ta4_vtubeA", { + description = S("TA4 Vacuum Tube"), + drawtype = "nodebox", + tiles = { + -- up, down, right, left, back, front + "techage_collider_tube.png^[transformR90", + 'techage_collider_tube.png^techage_collider_tube_open.png', + "techage_collider_tube.png", + "techage_collider_tube.png", + "techage_collider_tube.png^[transformR90", + 'techage_collider_tube.png^techage_collider_tube_open.png', + }, + node_box = { + type = "fixed", + fixed = { + {-8/16, -8/16, -8/16, -6/16, 8/16, 8/16}, + { 6/16, -8/16, -8/16, 8/16, 8/16, 8/16}, + {-8/16, 6/16, -8/16, 8/16, 8/16, 8/16}, + {-8/16, -8/16, 6/16, 8/16, 8/16, 8/16}, + {-8/16, -8/16, -8/16, 8/16, -6/16, -6/16}, + }, + }, + selection_box = { + type = "fixed", + fixed = {-8/16, -8/16, -8/16, 8/16, 8/16, 8/16}, + }, + + after_dig_node = function(pos, oldnode, oldmetadata, digger) + VTube:after_dig_tube(pos, oldnode, oldmetadata) + end, + + paramtype2 = "facedir", -- important! + on_rotate = screwdriver.disallow, -- important! + paramtype = "light", + use_texture_alpha = techage.CLIP, + sunlight_propagates = true, + is_ground_content = false, + groups = {cracky = 1, not_in_creative_inventory=1}, + drop = "techage:ta4_vtubeS", + sounds = default.node_sound_metal_defaults(), +}) + +minetest.register_craft({ + output = "techage:ta4_vtubeS 4", + recipe = { + {'', 'default:steel_ingot', ''}, + {'techage:aluminum', 'dye:blue', 'techage:aluminum'}, + {'', 'default:steel_ingot', ''}, + }, +}) diff --git a/collider/worker.lua b/collider/worker.lua new file mode 100644 index 0000000..a5b3b63 --- /dev/null +++ b/collider/worker.lua @@ -0,0 +1,205 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019-2021 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + TA4 Detector Worlker as part of the Collider + +]]-- + +-- for lazy programmers +local M = minetest.get_meta +local S = techage.S + +local AssemblyPlan = { + -- y-offs, path, facedir-offs, name + -- 0 = forward, 1 = right, 2 = backward, 3 = left + + -- level 1 + -- left/right + { 1, {3,3,3,2}, 0, "default:steelblock"}, + { 1, {3,3,3}, 0, "default:steelblock"}, + { 1, {3,3,3,0}, 0, "default:steelblock"}, + { 1, {1,1,1,2}, 0, "default:steelblock"}, + { 1, {1,1,1}, 0, "default:steelblock"}, + { 1, {1,1,1,0}, 0, "default:steelblock"}, + -- front + { 1, {3,3,2}, 0, "default:steelblock"}, + { 1, {3,2}, 0, "default:steelblock"}, + { 1, {2}, 0, "default:steelblock"}, + { 1, {1,2}, 0, "default:steelblock"}, + { 1, {1,1,2}, 0, "default:steelblock"}, + -- back + { 1, {3,3,0}, 0, "default:steelblock"}, + { 1, {3,0}, 0, "default:steelblock"}, + { 1, {0}, 2, "techage:ta4_collider_pipe_inlet"}, + { 1, {1,0}, 0, "default:steelblock"}, + { 1, {1,1,0}, 0, "default:steelblock"}, + -- middle + { 1, {3,3}, 0, "techage:ta4_detector_magnet"}, + { 1, {3}, 0, "techage:ta4_detector_magnet"}, + { 1, {}, 0, "techage:ta4_detector_core"}, + { 1, {1}, 0, "techage:ta4_detector_magnet"}, + { 1, {1,1}, 0, "techage:ta4_detector_magnet"}, + + -- level 2 + -- left/right + { 2, {3,3,3,2}, 1, "techage:ta4_collider_pipe_inlet"}, + { 2, {3,3,3}, 1, "techage:ta4_collider_tube_inlet"}, + { 2, {3,3,3,0}, 0, "default:steelblock"}, + { 2, {1,1,1,2}, 3, "techage:ta4_collider_pipe_inlet"}, + { 2, {1,1,1}, 3, "techage:ta4_collider_tube_inlet"}, + { 2, {1,1,1,0}, 0, "default:steelblock"}, + -- front + { 2, {3,3,2}, 0, "techage:ta4_detector_magnet"}, + { 2, {3,2}, 0, "techage:ta4_detector_magnet"}, + { 2, {2}, 0, "default:obsidian_glass"}, + { 2, {1,2}, 0, "techage:ta4_detector_magnet"}, + { 2, {1,1,2}, 0, "techage:ta4_detector_magnet"}, + -- back + { 2, {3,3,0}, 0, "techage:ta4_detector_magnet"}, + { 2, {3,0}, 0, "techage:ta4_detector_magnet"}, + { 2, {0}, 0, "default:steelblock"}, + { 2, {1,0}, 0, "techage:ta4_detector_magnet"}, + { 2, {1,1,0}, 0, "techage:ta4_detector_magnet"}, + + -- level 3 + -- left/right + { 3, {3,3,3,2}, 0, "default:steelblock"}, + { 3, {3,3,3}, 1, "techage:ta4_collider_cable_inlet"}, + { 3, {3,3,3,0}, 0, "default:steelblock"}, + { 3, {1,1,1,2}, 0, "default:steelblock"}, + { 3, {1,1,1}, 3, "techage:ta4_collider_cable_inlet"}, + { 3, {1,1,1,0}, 0, "default:steelblock"}, + -- front + { 3, {3,3,2}, 0, "default:steelblock"}, + { 3, {3,2}, 0, "default:steelblock"}, + { 3, {2}, 0, "default:steelblock"}, + { 3, {1,2}, 0, "default:steelblock"}, + { 3, {1,1,2}, 0, "default:steelblock"}, + -- back + { 3, {3,3,0}, 0, "default:steelblock"}, + { 3, {3,0}, 0, "default:steelblock"}, + { 3, {0}, 2, "techage:ta4_collider_pipe_inlet"}, + { 3, {1,0}, 0, "default:steelblock"}, + { 3, {1,1,0}, 0, "default:steelblock"}, + -- middle + { 3, {3,3}, 0, "techage:ta4_detector_magnet"}, + { 3, {3}, 0, "techage:ta4_detector_magnet"}, + { 3, {}, 0, "techage:ta4_collider_pipe_outlet"}, + { 3, {1}, 0, "techage:ta4_detector_magnet"}, + { 3, {1,1}, 0, "techage:ta4_detector_magnet"}, +} + +local t = {} +for name, cnt in pairs(techage.assemble.count_items(AssemblyPlan)) do + t[#t + 1] = " - " .. cnt .. " " .. name +end +local LABEL = table.concat(t, "\n") + +local function build(pos, player_name) + minetest.chat_send_player(player_name, S("[TA4] Detector is being built!")) + local inv = M(pos):get_inventory() + techage.assemble.build_inv(pos, inv, AssemblyPlan, player_name) +end + +local function remove(pos, player_name) + minetest.chat_send_player(player_name, S("[TA4] Detector is being removed!")) + local inv = M(pos):get_inventory() + techage.assemble.remove_inv(pos, inv, AssemblyPlan, player_name) +end + + +local function formspec() + return "size[8,8.2]".. + "list[context;src;5,0;3,3;]".. + "label[0.2,-0.2;" .. S("Item list") .. ":\n" .. LABEL .. "]" .. + "button_exit[0,3.5;4,1;build;" .. S("Build detector") .. "]" .. + "button_exit[4,3.5;4,1;remove;" .. S("Remove detector") .. "]" .. + "list[current_player;main;0,4.5;8,4;]".. + "listring[context;src]".. + "listring[current_player;main]" +end + +minetest.register_node("techage:ta4_collider_detector_worker", { + description = S("TA4 Collider Detector Worker"), + tiles = { + -- up, down, right, left, back, front + "default_steel_block.png^techage_collider_detector_appl.png^techage_collider_detector_banner.png", + "default_steel_block.png^techage_collider_detector_banner.png", + "default_steel_block.png^techage_collider_detector_banner.png", + "default_steel_block.png^techage_collider_detector_banner.png", + "default_steel_block.png^techage_collider_detector_banner.png", + "default_steel_block.png^techage_collider_detector_appl.png^techage_collider_detector_banner.png", + }, + drawtype = "nodebox", + paramtype2 = "facedir", + groups = {cracky = 1}, + on_rotate = screwdriver.disallow, + is_ground_content = false, + sounds = default.node_sound_metal_defaults(), + + after_place_node = function(pos, placer, itemstack) + if pos.y > (techage.collider_min_depth - 2) then + minetest.remove_node(pos) + minetest.add_item(pos, ItemStack("techage:ta4_collider_detector_worker")) + return + end + local inv = M(pos):get_inventory() + inv:set_size("src", 9) + M(pos):set_string("formspec", formspec()) + end, + + on_receive_fields = function(pos, formname, fields, player) + if minetest.is_protected(pos, player:get_player_name()) then + return + end + + local nvm = techage.get_nvm(pos) + if fields.build then + if not nvm.assemble_locked then + build(pos, player:get_player_name()) + end + elseif fields.remove then + if not nvm.assemble_locked then + remove(pos, player:get_player_name()) + end + end + end, + + after_dig_node = function(pos, oldnode) + techage.del_mem(pos) + end, + + can_dig = function(pos, player) + if minetest.is_protected(pos, player:get_player_name()) then + return false + end + local nvm = techage.get_nvm(pos) + if nvm.assemble_locked or nvm.assemble_build then + minetest.after(30, function(pos) + local nvm = techage.get_nvm(pos) + nvm.assemble_locked = false + end, pos) + return false + end + local inv = M(pos):get_inventory() + return inv:is_empty("src") + end, +}) + + +minetest.register_craft({ + output = "techage:ta4_collider_detector_worker", + recipe = { + {'techage:aluminum', 'default:chest', 'default:steel_ingot'}, + {'', 'basic_materials:gear_steel', ''}, + {'default:steel_ingot', 'default:mese_crystal', 'techage:aluminum'}, + }, +}) + diff --git a/energy_storage/heatexchanger1.lua b/energy_storage/heatexchanger1.lua index 78f562b..198f587 100644 --- a/energy_storage/heatexchanger1.lua +++ b/energy_storage/heatexchanger1.lua @@ -25,12 +25,12 @@ local power = networks.power local function turbine_cmnd(pos, topic, payload) return techage.transfer(pos, "R", topic, payload, Pipe, - {"techage:ta4_turbine", "techage:ta4_turbine_on"}) + {"techage:ta4_turbine", "techage:ta4_turbine_on", "techage:ta4_collider_cooler"}) end local function inlet_cmnd(pos, topic, payload) return techage.transfer(pos, "L", topic, payload, Pipe, - {"techage:ta4_pipe_inlet"}) + {"techage:ta4_pipe_inlet", "techage:ta4_collider_pipe_inlet"}) end minetest.register_node("techage:heatexchanger1", { @@ -83,7 +83,7 @@ techage.register_node({"techage:heatexchanger1"}, { on_transfer = function(pos, indir, topic, payload) local nvm = techage.get_nvm(pos) -- used by heatexchanger2 - if topic == "diameter" or topic == "volume" or topic == "window" then + if topic == "diameter" or topic == "volume" or topic == "window" or topic == "detector" then return inlet_cmnd(pos, topic, payload) else return turbine_cmnd(pos, topic, payload) diff --git a/energy_storage/heatexchanger2.lua b/energy_storage/heatexchanger2.lua index 591acc8..b57bf94 100644 --- a/energy_storage/heatexchanger2.lua +++ b/energy_storage/heatexchanger2.lua @@ -9,6 +9,7 @@ See LICENSE.txt for more information TA4 Heat Exchanger2 (middle part) + (alternatively used as cooler for the TA4 collider) ]]-- @@ -31,6 +32,7 @@ local PWR_CAPA = { [9] = GRVL_CAPA * 7 * 7 * 7, -- 286 kuh } local DOWN = 5 +local PWR_NEEDED = 5 local function heatexchanger1_cmnd(pos, topic, payload) return techage.transfer({x = pos.x, y = pos.y - 1, z = pos.z}, @@ -75,7 +77,25 @@ local function stop_sound(pos) end end +local function cooler_formspec(self, pos, nvm) + return "size[4,2]".. + "box[0,-0.1;3.8,0.5;#c6e8ff]" .. + "label[0.2,-0.1;" .. minetest.colorize( "#000000", S("TA4 Heat Exchanger")) .. "]" .. + "image_button[1.5,1;1,1;".. self:get_state_button_image(nvm) ..";state_button;]".. + "tooltip[1.5,1;1,1;"..self:get_state_tooltip(nvm).."]" +end + local function can_start(pos, nvm) + -- Used as cooler for the collider? + if heatexchanger1_cmnd(pos, "detector") then + if power.power_available(pos, Cable, DOWN) then + nvm.used_as_cooler = true + return true + else + return S("No power") + end + end + -- Used as heat exchanger local netID = networks.determine_netID(pos, Cable, DOWN) if heatexchanger1_cmnd(pos, "netID") ~= netID then return S("Power network connection error") @@ -97,21 +117,32 @@ local function can_start(pos, nvm) end local function start_node(pos, nvm) - nvm.win_pos = heatexchanger1_cmnd(pos, "window") - power.start_storage_calc(pos, Cable, DOWN) - play_sound(pos) - heatexchanger1_cmnd(pos, "start") + if nvm.used_as_cooler then + play_sound(pos) + else + nvm.win_pos = heatexchanger1_cmnd(pos, "window") + power.start_storage_calc(pos, Cable, DOWN) + play_sound(pos) + heatexchanger1_cmnd(pos, "start") + end end local function stop_node(pos, nvm) - power.start_storage_calc(pos, Cable, DOWN) - stop_sound(pos) - heatexchanger1_cmnd(pos, "stop") + if nvm.used_as_cooler then + stop_sound(pos) + else + power.start_storage_calc(pos, Cable, DOWN) + stop_sound(pos) + heatexchanger1_cmnd(pos, "stop") + end end local function formspec(self, pos, nvm) local data + if nvm.used_as_cooler then + return cooler_formspec(self, pos, nvm) + end if techage.is_running(nvm) then data = power.get_network_data(pos, Cable, DOWN) end @@ -135,11 +166,9 @@ local function check_TES_integrity(pos, nvm) end if (nvm.ticks % 30) == 0 then -- every minute return heatexchanger1_cmnd(pos, "volume") - end - if (nvm.ticks % 30) == 10 then -- every minute - return heatexchanger3_cmnd(pos, "diameter") ~= nil or S("inlet/pipe error") - end - if (nvm.ticks % 30) == 20 then -- every minute + elseif (nvm.ticks % 30) == 10 then -- every minute + return heatexchanger1_cmnd(pos, "diameter") ~= nil or S("inlet/pipe error") + elseif (nvm.ticks % 30) == 20 then -- every minute return heatexchanger3_cmnd(pos, "diameter") ~= nil or S("inlet/pipe error") end local netID = networks.determine_netID(pos, Cable, DOWN) @@ -166,8 +195,38 @@ local State = techage.NodeStates:new({ formspec_func = formspec, }) +local function cooler_timer(pos, nvm) + local err = false + if power.consume_power(pos, Cable, DOWN, PWR_NEEDED) ~= PWR_NEEDED then + State:fault(pos, nvm, "No power") + stop_sound(pos) + return true + end + + -- Cyclically check pipe connections + nvm.ticks = (nvm.ticks or 0) + 1 + if (nvm.ticks % 5) == 0 then -- every 10 s + err = heatexchanger1_cmnd(pos, "detector") ~= true + elseif (nvm.ticks % 5) == 1 then -- every 10 s + err = heatexchanger3_cmnd(pos, "detector") ~= true + elseif (nvm.ticks % 5) == 2 then -- every 10 s + err = heatexchanger1_cmnd(pos, "cooler") ~= true + elseif (nvm.ticks % 5) == 3 then -- every 10 s + err = heatexchanger3_cmnd(pos, "cooler") ~= true + end + if err then + State:fault(pos, nvm, "Pipe connection error") + stop_sound(pos) + end + return true +end + local function node_timer(pos, elapsed) local nvm = techage.get_nvm(pos) + if nvm.used_as_cooler then + cooler_timer(pos, nvm) + return true + end local res = check_TES_integrity(pos, nvm) if res ~= true then State:fault(pos, nvm, res) diff --git a/energy_storage/heatexchanger3.lua b/energy_storage/heatexchanger3.lua index 0fa9688..70f3713 100644 --- a/energy_storage/heatexchanger3.lua +++ b/energy_storage/heatexchanger3.lua @@ -42,9 +42,14 @@ local function after_dig_node(pos, oldnode) Pipe:after_dig_node(pos) end +local function cooler_cmnd(pos, topic, payload) + return techage.transfer(pos, "R", topic, payload, Pipe, + {"techage:ta4_collider_cooler"}) +end + local function inlet_cmnd(pos, topic, payload) return techage.transfer(pos, "L", topic, payload, Pipe, - {"techage:ta4_pipe_inlet"}) + {"techage:ta4_pipe_inlet", "techage:ta4_collider_pipe_inlet"}) end minetest.register_node("techage:heatexchanger3", { @@ -77,7 +82,11 @@ Pipe:add_secondary_node_names({"techage:heatexchanger3"}) -- command interface, used by heatexchanger2 techage.register_node({"techage:heatexchanger3"}, { on_transfer = function(pos, indir, topic, payload) - return inlet_cmnd(pos, topic, payload) + if topic == "cooler" then + return cooler_cmnd(pos, topic, payload) + else + return inlet_cmnd(pos, topic, payload) + end end, }) diff --git a/init.lua b/init.lua index 231e738..f482367 100644 --- a/init.lua +++ b/init.lua @@ -55,6 +55,7 @@ techage.max_num_forceload_blocks = tonumber(minetest.settings:get("techage_max_n techage.basalt_stone_enabled = minetest.settings:get_bool("techage_basalt_stone_enabled") ~= false techage.ore_rarity = tonumber(minetest.settings:get("techage_ore_rarity")) or 1 techage.modified_recipes_enabled = minetest.settings:get_bool("techage_modified_recipes_enabled") ~= false +techage.collider_min_depth = tonumber(minetest.settings:get("techage_collider_min_depth")) or -30 -- allow to load marshal and sqlite3 techage.IE = minetest.request_insecure_environment() @@ -98,6 +99,7 @@ dofile(MP.."/basis/windturbine_lib.lua") dofile(MP.."/basis/laser_lib.lua") dofile(MP.."/basis/legacy.lua") dofile(MP.."/basis/hyperloop.lua") +dofile(MP.."/basis/oggfiles.lua") -- Main doc dofile(MP.."/doc/manual_DE.lua") @@ -294,6 +296,7 @@ dofile(MP.."/move_controller/doorcontroller2.lua") -- new dofile(MP.."/move_controller/movecontroller.lua") dofile(MP.."/move_controller/turncontroller.lua") dofile(MP.."/move_controller/flycontroller.lua") +dofile(MP.."/move_controller/soundblock.lua") -- Test @@ -377,6 +380,14 @@ dofile(MP.."/items/moreblocks.lua") dofile(MP.."/carts/tank_cart.lua") dofile(MP.."/carts/chest_cart.lua") +-- Collider +dofile(MP.."/collider/vacuumtube.lua") +dofile(MP.."/collider/magnet.lua") +dofile(MP.."/collider/inlets.lua") +dofile(MP.."/collider/cooler.lua") +dofile(MP.."/collider/detector.lua") +dofile(MP.."/collider/worker.lua") + -- Prevent other mods from using IE techage.IE = nil diff --git a/items/ceramic.lua b/items/ceramic.lua index 62aa79b..357fb00 100644 --- a/items/ceramic.lua +++ b/items/ceramic.lua @@ -52,4 +52,18 @@ techage.furnace.register_recipe({ "techage:ta4_ceramic_material", }, time = 16, +}) + +minetest.register_craftitem("techage:ta4_round_ceramic", { + description = S("TA4 Round Ceramic"), + inventory_image = "techage_round_ceramic.png", +}) + +techage.furnace.register_recipe({ + output = "techage:ta4_round_ceramic 2", + recipe = { + "techage:ta4_ceramic_material", "techage:ta4_ceramic_material", + "techage:ta4_ceramic_material", "techage:ta4_ceramic_material", + }, + time = 16, }) \ No newline at end of file diff --git a/liquids/pump.lua b/liquids/pump.lua index 258ea53..e50b245 100644 --- a/liquids/pump.lua +++ b/liquids/pump.lua @@ -56,6 +56,11 @@ local function pumping(pos, nvm, state, capa) if taken > 0 then local leftover = liquid.put(pos, Pipe, outdir, name, taken, mem.dbg_cycles > 0) if leftover and leftover > 0 then + -- air needs no tank + if name == "air" then + state:keep_running(pos, nvm, COUNTDOWN_TICKS) + return 0 + end liquid.untake(pos, Pipe, Flip[outdir], name, leftover) if leftover == taken then state:blocked(pos, nvm) diff --git a/logic/terminal.lua b/logic/terminal.lua index 7bf483f..cf63084 100644 --- a/logic/terminal.lua +++ b/logic/terminal.lua @@ -3,7 +3,7 @@ Terminal ======== - Copyright (C) 2018-2020 Joachim Stolberg + Copyright (C) 2018-2021 Joachim Stolberg AGPL v3 See LICENSE.txt for more information @@ -15,22 +15,36 @@ local M = minetest.get_meta local S = techage.S -local HELP_TA3 = "Syntax:\n".. -" cmd \n".. -"\n".. -"like: cmd 181 on\n".. -"or: cmd 4573 state\n".. -"\n".. -"Local commands:\n".. -"- clear = clear screen\n".. -"- help = this message\n".. -"- pub = switch to public use of buttons\n".. -"- priv = switch to private use of buttons\n".. -"To program a user button with a command:\n".. -" set \n".. -"e.g.: set 1 ON cmd 123 on" +local HELP_TA3 = [[ #### TA3 Terminal #### +Send commands to machines and output the results. +Local commands: +- Clear screen with 'clear' +- Output this message with 'help' +- Switch to public use of buttons with 'pub' +- Switch to private use of buttons with 'priv' +- Program a user button with + 'set ' + Example: 'set 1 ON cmd 1234 on' +- send a command with 'cmd ' + Example: 'cmd 1234 on']] -local CMNDS_TA3 = S("Syntax error, try help") +local HELP_TA4 = [[ #### TA4 Terminal #### +Send commands to machines and output the results. +Local commands: +- Clear screen with 'clear' +- Output this message with 'help' +- Switch to public use of buttons with 'pub' +- Switch to private use of buttons with 'priv' +- Program a user button with + 'set ' + Example: 'set 1 ON cmd 1234 on' +- send a command with 'cmd ' + Example: 'cmd 1234 on' +- Connect to a machine with 'connect ' +If connected, compact commands like 'status' +are possible.]] + +local SYNTAX_ERR = S("Syntax error, try help") local function get_string(meta, num, default) local s = meta:get_string("bttn_text"..num) @@ -54,24 +68,28 @@ local function formspec2(meta) local bttn_text7 = get_string(meta, 7, "User7") local bttn_text8 = get_string(meta, 8, "User8") local bttn_text9 = get_string(meta, 9, "User9") - return "size[10,8]".. - default.gui_bg.. - default.gui_bg_img.. - default.gui_slots.. - "style_type[table,field;font=mono]".. - "button[0,0;3.3,1;bttn1;"..bttn_text1.."]button[3.3,0;3.3,1;bttn2;"..bttn_text2.."]button[6.6,0;3.3,1;bttn3;"..bttn_text3.."]".. - "button[0,0.8;3.3,1;bttn4;"..bttn_text4.."]button[3.3,0.8;3.3,1;bttn5;"..bttn_text5.."]button[6.6,0.8;3.3,1;bttn6;"..bttn_text6.."]".. - "button[0,1.6;3.3,1;bttn7;"..bttn_text7.."]button[3.3,1.6;3.3,1;bttn8;"..bttn_text8.."]button[6.6,1.6;3.3,1;bttn9;"..bttn_text9.."]".. - "table[0,2.5;9.8,4.7;output;"..output..";200]".. - "field[0.4,7.7;7.6,1;cmnd;;"..command.."]" .. + return "size[10,8.5]".. + --"style_type[table,field;font=mono]".. + "button[0,-0.2;3.3,1;bttn1;"..bttn_text1.."]button[3.3,-0.2;3.3,1;bttn2;"..bttn_text2.."]button[6.6,-0.2;3.3,1;bttn3;"..bttn_text3.."]".. + "button[0,0.6;3.3,1;bttn4;"..bttn_text4.."]button[3.3,0.6;3.3,1;bttn5;"..bttn_text5.."]button[6.6,0.6;3.3,1;bttn6;"..bttn_text6.."]".. + "button[0,1.4;3.3,1;bttn7;"..bttn_text7.."]button[3.3,1.4;3.3,1;bttn8;"..bttn_text8.."]button[6.6,1.4;3.3,1;bttn9;"..bttn_text9.."]".. + "table[0,2.3;9.8,5.6;output;"..output..";200]".. + "field[0.4,8.2;7.6,1;cmnd;;"..command.."]" .. "field_close_on_enter[cmnd;false]".. - "button[7.9,7.4;2,1;ok;"..S("Enter").."]" + "button[7.9,7.9;2,1;ok;"..S("Enter").."]" end local function output(pos, text) local meta = minetest.get_meta(pos) text = meta:get_string("output") .. "\n" .. (text or "") - text = text:sub(-500,-1) + text = text:sub(-1000,-1) + meta:set_string("output", text) + meta:set_string("formspec", formspec2(meta)) +end + +local function append(pos, text) + local meta = minetest.get_meta(pos) + text = meta:get_string("output") .. (text or "") meta:set_string("output", text) meta:set_string("formspec", formspec2(meta)) end @@ -84,37 +102,146 @@ local function get_line_text(pos, num) return line:gsub("^[%s$]*(.-)%s*$", "%1") end +local function server_debug(pos, command, player) + local cmnd, payload = command:match('^pipe%s+([%w_]+)%s*(.*)$') + if cmnd then + if not minetest.check_player_privs(player, "server") then + output(pos, "server privs missing") + return + end + local resp = techage.transfer( + pos, + "B", -- outdir + cmnd, -- topic + payload, -- payload + techage.LiquidPipe, -- network + nil) -- valid nodes + output(pos, dump(resp)) + return true + end + + cmnd, payload = command:match('^axle%s+([%w_]+)%s*(.*)$') + if cmnd then + if not minetest.check_player_privs(player, "server") then + output(pos, "server privs missing") + return + end + local resp = techage.transfer( + pos, + "B", -- outdir + cmnd, -- topic + payload, -- payload + techage.TA1Axle, -- network + nil) -- valid nodes + output(pos, dump(resp)) + return true + end + + cmnd, payload = command:match('^vtube%s+([%w_]+)%s*(.*)$') + if cmnd then + if not minetest.check_player_privs(player, "server") then + output(pos, "server privs missing") + return + end + local resp = techage.transfer( + pos, + "B", -- outdir + cmnd, -- topic + payload, -- payload + techage.VTube, -- network + nil) -- valid nodes + output(pos, dump(resp)) + return true + end +end -local function command(pos, command, player) +local function command(pos, command, player, is_ta4) local meta = minetest.get_meta(pos) local owner = meta:get_string("owner") or "" - if command then - command = command:sub(1,80) - command = string.trim(command) - - if command == "clear" then - meta:set_string("output", "") - meta:set_string("formspec", formspec2(meta)) - elseif command == "help" then - local meta = minetest.get_meta(pos) - meta:set_string("output", HELP_TA3) - meta:set_string("formspec", formspec2(meta)) - elseif command == "pub" then - meta:set_int("public", 1) - output(pos, player..":$ "..command) - output(pos, S("Switched to public use!")) - elseif command == "priv" then - meta:set_int("public", 0) - output(pos, player..":$ "..command) - output(pos, S("Switched to private use!")) + command = command:sub(1,80) + command = string.trim(command) + local cmnd, data = command:match('^(%w+)%s*(.*)$') + + if cmnd == "clear" then + meta:set_string("output", "") + meta:set_string("formspec", formspec2(meta)) + elseif cmnd == "" then + output(pos, "$") + elseif cmnd == "help" then + if is_ta4 then + output(pos, HELP_TA4) else - output(pos, "$ "..command) + output(pos, HELP_TA3) + end + elseif cmnd == "pub" then + meta:set_int("public", 1) + output(pos, "$ "..command) + output(pos, "Switched to public buttons!") + elseif cmnd == "priv" then + meta:set_int("public", 0) + output(pos, "$ "..command) + output(pos, "Switched to private buttons!") + elseif cmnd == "connect" and data then + output(pos, "$ "..command) + if techage.not_protected(data, owner, owner) then local own_num = meta:get_string("node_number") - local num, cmnd, payload = command:match('^cmd%s+([0-9]+)%s+(%w+)%s*(.*)$') - if num and cmnd then - if techage.not_protected(num, owner, owner) then - local resp = techage.send_single(own_num, num, cmnd, payload) + local resp = techage.send_single(own_num, data, cmnd) + if resp then + meta:set_string("connected_to", data) + output(pos, "Connected.") + else + meta:set_string("connected_to", "") + output(pos, "Not connected!") + end + else + output(pos, "Protection error!") + end + else + output(pos, "$ "..command) + local own_num = meta:get_string("node_number") + local connected_to = meta:contains("connected_to") and meta:get_string("connected_to") + local bttn_num, label, num, cmnd, payload + + num, cmnd, payload = command:match('^cmd%s+([0-9]+)%s+(%w+)%s*(.*)$') + if num and cmnd then + if techage.not_protected(num, owner, owner) then + local resp = techage.send_single(own_num, num, cmnd, payload) + if type(resp) == "string" then + output(pos, resp) + else + output(pos, dump(resp)) + end + end + return + end + + num, cmnd = command:match('^turn%s+([0-9]+)%s+([onf]+)$') + if num and (cmnd == "on" or cmnd == "off") then + if techage.not_protected(num, owner, owner) then + local resp = techage.send_single(own_num, num, cmnd) + output(pos, dump(resp)) + end + return + end + + bttn_num, label, cmnd = command:match('^set%s+([1-9])%s+([%w_]+)%s+(.+)$') + if bttn_num and label and cmnd then + meta:set_string("bttn_text"..bttn_num, label) + meta:set_string("bttn_cmnd"..bttn_num, cmnd) + meta:set_string("formspec", formspec2(meta)) + return + end + + if server_debug(pos, command, player) then + return + end + + if connected_to then + local cmnd, payload = command:match('^(%w+)%s*(.*)$') + if cmnd then + local resp = techage.send_single(own_num, connected_to, cmnd, payload) + if resp ~= true then if type(resp) == "string" then output(pos, resp) else @@ -123,59 +250,10 @@ local function command(pos, command, player) end return end - num, cmnd = command:match('^turn%s+([0-9]+)%s+([onf]+)$') - if num and (cmnd == "on" or cmnd == "off") then - if techage.not_protected(num, owner, owner) then - local resp = techage.send_single(own_num, num, cmnd) - output(pos, dump(resp)) - end - return - end - local bttn_num, label, cmnd = command:match('^set%s+([1-9])%s+([%w_]+)%s+(.+)$') - if bttn_num and label and cmnd then - meta:set_string("bttn_text"..bttn_num, label) - meta:set_string("bttn_cmnd"..bttn_num, cmnd) - meta:set_string("formspec", formspec2(meta)) - return - end - - local cmnd, payload = command:match('^pipe%s+([%w_]+)%s*(.*)$') - if cmnd then - if not minetest.check_player_privs(player, "server") then - output(pos, "server privs missing") - return - end - local resp = techage.transfer( - pos, - "B", -- outdir - cmnd, -- topic - payload, -- payload - techage.LiquidPipe, -- network - nil) -- valid nodes - output(pos, dump(resp)) - return - end - - local cmnd, payload = command:match('^axle%s+([%w_]+)%s*(.*)$') - if cmnd then - if not minetest.check_player_privs(player, "server") then - output(pos, "server privs missing") - return - end - local resp = techage.transfer( - pos, - "B", -- outdir - cmnd, -- topic - payload, -- payload - techage.TA1Axle, -- network - nil) -- valid nodes - output(pos, dump(resp)) - return - end - - if command ~= "" then - output(pos, CMNDS_TA3) - end + end + + if command ~= "" then + output(pos, SYNTAX_ERR) end end end @@ -186,9 +264,9 @@ local function send_cmnd(pos, meta, num) command(pos, cmnd, owner) end -local function register_terminal(num, tiles, node_box, selection_box) - minetest.register_node("techage:terminal"..num, { - description = S("TA3 Terminal"), +local function register_terminal(name, description, tiles, node_box, selection_box) + minetest.register_node("techage:"..name, { + description = description, tiles = tiles, drawtype = "nodebox", node_box = node_box, @@ -201,7 +279,7 @@ local function register_terminal(num, tiles, node_box, selection_box) meta:set_string("command", S("commands like: help")) meta:set_string("formspec", formspec2(meta)) meta:set_string("owner", placer:get_player_name()) - meta:set_string("infotext", S("TA3 Terminal") .. " " .. number) + meta:set_string("infotext", description .. " " .. number) end, on_receive_fields = function(pos, formname, fields, player) @@ -216,11 +294,21 @@ local function register_terminal(num, tiles, node_box, selection_box) meta:set_string("command", s) meta:set_string("formspec", formspec2(meta)) return - elseif (fields.key_enter == "true" or fields.ok) and fields.cmnd ~= "" then - command(pos, fields.cmnd, player:get_player_name()) + elseif (fields.ok or fields.key_enter_field) and fields.cmnd then + local is_ta4 = string.find(description, "TA4") + command(pos, fields.cmnd, player:get_player_name(), is_ta4) + techage.historybuffer_add(pos, fields.cmnd) meta:set_string("command", "") meta:set_string("formspec", formspec2(meta)) return + elseif fields.key_up then + meta:set_string("command", techage.historybuffer_priv(pos)) + meta:set_string("formspec", formspec2(meta)) + return + elseif fields.key_down then + meta:set_string("command", techage.historybuffer_next(pos)) + meta:set_string("formspec", formspec2(meta)) + return end end if public or not protected then @@ -251,7 +339,7 @@ local function register_terminal(num, tiles, node_box, selection_box) }) end -register_terminal("2", { +register_terminal("terminal2", S("TA3 Terminal"), { -- up, down, right, left, back, front 'techage_terminal2_top.png', 'techage_terminal2_side.png', @@ -277,7 +365,33 @@ register_terminal("2", { fixed = { {-12/32, -16/32, -4/32, 12/32, 6/32, 16/32}, }, - }) + } +) + +register_terminal("terminal3", S("TA4 Terminal"), { + -- up, down, right, left, back, front + 'techage_terminal1_top.png', + 'techage_terminal1_bottom.png', + 'techage_terminal1_side.png', + 'techage_terminal1_side.png', + 'techage_terminal1_bottom.png', + "techage_terminal1_front.png", + }, + { + type = "fixed", + fixed = { + {-12/32, -16/32, -8/32, 12/32, -14/32, 12/32}, + {-12/32, -14/32, 12/32, 12/32, 6/32, 14/32}, + }, + }, + { + type = "fixed", + fixed = { + {-12/32, -16/32, -8/32, 12/32, -14/32, 12/32}, + {-12/32, -14/32, 12/32, 12/32, 6/32, 14/32}, + }, + } +) minetest.register_craft({ output = "techage:terminal2", @@ -288,6 +402,15 @@ minetest.register_craft({ }, }) +minetest.register_craft({ + output = "techage:terminal3", + recipe = { + {"techage:basalt_glass_thin", "", ""}, + {"techage:ta4_leds", "", ""}, + {"techage:aluminum", "techage:ta4_wlanchip", "techage:ta4_ramchip"}, + }, +}) + techage.register_node({"techage:terminal2"}, { on_recv_message = function(pos, src, topic, payload) output(pos, "src="..src..", cmd="..dump(topic)..", data="..dump(payload)) @@ -302,3 +425,16 @@ techage.register_node({"techage:terminal2"}, { end end, }) + +techage.register_node({"techage:terminal3"}, { + on_recv_message = function(pos, src, topic, payload) + if topic == "text" then + output(pos, payload) + elseif topic == "append" then + append(pos, payload) + else + output(pos, "src="..src..", cmd="..dump(topic)..", data="..dump(payload)) + end + return true + end, +}) diff --git a/move_controller/flycontroller.lua b/move_controller/flycontroller.lua index efe34db..45cc1d9 100644 --- a/move_controller/flycontroller.lua +++ b/move_controller/flycontroller.lua @@ -47,18 +47,20 @@ local WRENCH_MENU = { local function formspec(nvm, meta) local status = meta:get_string("status") local path = meta:contains("path") and meta:get_string("path") or "0,3,0" - return "size[8,7]" .. + return "size[8,6.7]" .. "style_type[textarea;font=mono;textcolor=#FFFFFF;border=true]" .. "box[0,-0.1;7.2,0.5;#c6e8ff]" .. "label[0.2,-0.1;" .. minetest.colorize( "#000000", S("TA5 Fly Controller")) .. "]" .. techage.wrench_image(7.4, -0.05) .. "button[0.1,0.7;3.8,1;record;" .. S("Record") .. "]" .. "button[4.1,0.7;3.8,1;done;" .. S("Done") .. "]" .. - "textarea[0.4,2.1;3.8,3.8;path;" .. S("Move path (A to B)") .. ";"..path.."]" .. - "button[4.1,3.2;3.8,1;store;" .. S("Store") .. "]" .. - "button[0.1,5.5;3.8,1;moveAB;" .. S("Move A-B") .. "]" .. - "button[4.1,5.5;3.8,1;moveBA;" .. S("Move B-A") .. "]" .. - "label[0.3,6.5;" .. status .. "]" + "textarea[0.4,2.1;3.8,4.4;path;" .. S("Move path (A to B)") .. ";"..path.."]" .. + "button[4.1,1.8;3.8,1;store;" .. S("Store") .. "]" .. + "button[4.1,2.6;3.8,1;test;" .. S("Test") .. "]" .. + "button[4.1,3.4;3.8,1;moveAB;" .. S("Move A-B") .. "]" .. + "button[4.1,4.2;3.8,1;moveBA;" .. S("Move B-A") .. "]" .. + "button[4.1,5.0;3.8,1;move;" .. S("Move") .. "]" .. + "label[0.3,6.3;" .. status .. "]" end @@ -110,17 +112,46 @@ minetest.register_node("techage:ta5_flycontroller", { mark.stop(name) meta:set_string("formspec", formspec(nvm, meta)) elseif fields.store then - if fly.to_path(fields.path, MAX_DIST) then + local _, err = fly.to_path(fields.path, MAX_DIST) + if not err then meta:set_string("path", fields.path) meta:set_string("status", S("Stored")) else - meta:set_string("status", S("Error: Invalid path !!")) + meta:set_string("status", err) end meta:set_string("formspec", formspec(nvm, meta)) local name = player:get_player_name() mark.stop(name) nvm.moveBA = false nvm.running = true + elseif fields.test then + local path, err = fly.to_path(fields.path, MAX_DIST) + if err then + meta:set_string("status", err) + elseif path and nvm.lpos1 then + local pos = table.copy(nvm.lpos1[1]) + if pos then + for _, offs in ipairs(path) do + local pos2 = vector.add(pos, offs) + local s = string.format("[TA4 Fly Controller] %s + %s = %s", P2S(pos), P2S(offs), P2S(pos2)) + minetest.chat_send_player(player:get_player_name(), s) + pos = pos2 + end + meta:set_string("status", S("See chat output")) + else + minetest.chat_send_player(player:get_player_name(), S("[TA4 Fly Controller] Recording is missing!")) + meta:set_string("status", S("Error: Recording is missing !!")) + end + else + if nvm.lpos1 then + minetest.chat_send_player(player:get_player_name(), S("[TA4 Fly Controller] Invalid path!")) + meta:set_string("status", S("Error: Invalid path !!")) + else + minetest.chat_send_player(player:get_player_name(), S("[TA4 Fly Controller] Recording is missing!")) + meta:set_string("status", S("Error: Recording is missing !!")) + end + end + meta:set_string("formspec", formspec(nvm, meta)) elseif fields.moveAB then meta:set_string("status", "") if fly.move_to_other_pos(pos, false) then @@ -139,6 +170,16 @@ minetest.register_node("techage:ta5_flycontroller", { mark.stop(name) end meta:set_string("formspec", formspec(nvm, meta)) + elseif fields.move then + meta:set_string("status", "") + nvm.moveBA = nvm.moveBA == false + if fly.move_to_other_pos(pos, nvm.moveBA == false) then + nvm.running = true + meta:set_string("formspec", formspec(nvm, meta)) + local name = player:get_player_name() + mark.stop(name) + end + meta:set_string("formspec", formspec(nvm, meta)) end end, diff --git a/move_controller/soundblock.lua b/move_controller/soundblock.lua new file mode 100644 index 0000000..87982bc --- /dev/null +++ b/move_controller/soundblock.lua @@ -0,0 +1,128 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2021 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + Sound Block + +]]-- + +-- for lazy programmers +local M = minetest.get_meta +local S = techage.S + +local t = {} +for idx, ogg in ipairs(techage.OggFileList) do + t[idx] = idx .. "," .. ogg +end +local OGG_FILES = table.concat(t, ",") + +local logic = techage.logic + +local GAIN = {0.05 ,0.1, 0.2, 0.5, 1.0} + + +local function play_sound(pos, ogg, gain) + minetest.sound_play(ogg, { + pos = pos, + gain = GAIN[gain or 1] or 1, + max_hear_distance = 15}) +end + +local function formspec(meta) + local idx = meta:contains("idx") and meta:get_int("idx") or 1 + local gain = meta:contains("gain") and meta:get_int("gain") or 1 + return "size[8,8]".. + "tablecolumns[text,width=5;text]".. + "table[0,0;8,6;oggfiles;" .. OGG_FILES .. ";" .. idx .. "]" .. + "dropdown[0,6.5;5.5,1.4;gain;1,2,3,4,5;" .. gain .. "]" .. + "button[2.5,7.2;3,1;play;" .. S("Play") .. "]" +end + +minetest.register_node("techage:ta3_soundblock", { + description = S("TA3 Sound Block"), + tiles = { + -- up, down, right, left, back, front + "techage_filling_ta3.png^techage_frame_ta3_top.png", + "techage_filling_ta3.png^techage_frame_ta3_top.png", + "techage_filling_ta3.png^techage_frame_ta3.png^techage_appl_sound.png", + }, + + after_place_node = function(pos, placer) + local meta = M(pos) + logic.after_place_node(pos, placer, "techage:ta3_soundblock", S("TA3 Sound Block")) + logic.infotext(meta, S("TA3 Sound Block")) + meta:set_string("formspec", formspec(meta)) + end, + + on_receive_fields = function(pos, formname, fields, player) + if minetest.is_protected(pos, player:get_player_name()) then + return + end + + if fields.oggfiles then + local mem = techage.get_mem(pos) + local t = minetest.explode_table_event(fields.oggfiles) + mem.idx = t.row + end + if fields.gain then + M(pos):set_int("gain", tonumber(fields.gain) or 1) + end + if fields.play then + local mem = techage.get_mem(pos) + M(pos):set_int("idx", mem.idx or 1) + local ogg = techage.OggFileList[mem.idx or 1] or techage.OggFileList[1] + play_sound(pos, ogg, M(pos):get_int("gain")) + end + end, + + paramtype2 = "facedir", + groups = {choppy=2, cracky=2, crumbly=2}, + is_ground_content = false, + sounds = default.node_sound_wood_defaults(), +}) + +local INFO = [[Commands: 'on', 'sound', 'gain']] + +techage.register_node({"techage:ta3_soundblock"}, { + on_recv_message = function(pos, src, topic, payload) + if topic == "info" then + return INFO + elseif topic == "on" then + local mem = techage.get_mem(pos) + if not mem.blocking_time or (mem.blocking_time < minetest.get_gametime()) then + local idx = M(pos):get_int("idx") + local ogg = techage.OggFileList[idx or 1] or techage.OggFileList[1] + local gain = M(pos):get_float("gain") + play_sound(pos, ogg, gain) + mem.blocking_time = minetest.get_gametime() + 2 + return true + end + elseif topic == "sound" then + M(pos):get_int("idx", tonumber(payload or 1) or 1) + elseif topic == "gain" then + M(pos):get_int("gain", tonumber(payload or 1) or 1) + else + return "unsupported" + end + end, + on_node_load = function(pos) + local meta = M(pos) + meta:set_string("formspec", formspec(meta)) + end +}) + +minetest.register_craft({ + output = "techage:ta3_soundblock", + recipe = { + {"", "group:wood",""}, + {"techage:vacuum_tube", "basic_materials:gold_wire", "techage:usmium_nuggets"}, + {"", "group:wood", ""}, + }, +}) + diff --git a/settingtypes.txt b/settingtypes.txt index ac0117b..377539a 100644 --- a/settingtypes.txt +++ b/settingtypes.txt @@ -29,4 +29,8 @@ techage_use_sqlite (use sqlite database) bool false # To reduce the server CPU load, the number of sent techage commands # per player and minute can be limited. -techage_command_limit (Max. number of commands sent per minute) int 1200 \ No newline at end of file +techage_command_limit (Max. number of commands sent per minute) int 1200 + +# Colliders are huge systems and should not be built on the surface. +# 'techage_collider_min_depth specifies' the min. depth (Y) to build a TA4 Collider +techage_collider_min_depth (Min. depth to build a TA4 Collider) int -30 \ No newline at end of file diff --git a/sounds/techage_hum.ogg b/sounds/techage_hum.ogg new file mode 100644 index 0000000..b90b66d Binary files /dev/null and b/sounds/techage_hum.ogg differ diff --git a/sounds/techage_watermill.ogg b/sounds/techage_watermill.ogg index 3e6486a..246479b 100644 Binary files a/sounds/techage_watermill.ogg and b/sounds/techage_watermill.ogg differ diff --git a/ta1_watermill/watermill.lua b/ta1_watermill/watermill.lua index d9b04a3..b029ae9 100644 --- a/ta1_watermill/watermill.lua +++ b/ta1_watermill/watermill.lua @@ -271,7 +271,7 @@ minetest.register_entity("techage:ta1_watermill_entity", { stop_wheel(pos, self) end trigger_consumer(pos, self.facedir) - minetest.sound_play("techage_watermill", {gain = 0.3, pos = pos, + minetest.sound_play("techage_watermill", {gain = 0.5, pos = pos, max_hear_distance = 10}, true) end end, diff --git a/textures/techage_appl_sound.png b/textures/techage_appl_sound.png new file mode 100644 index 0000000..4efea64 Binary files /dev/null and b/textures/techage_appl_sound.png differ diff --git a/textures/techage_collider_detector_appl.png b/textures/techage_collider_detector_appl.png new file mode 100644 index 0000000..fa8776b Binary files /dev/null and b/textures/techage_collider_detector_appl.png differ diff --git a/textures/techage_collider_detector_banner.png b/textures/techage_collider_detector_banner.png new file mode 100644 index 0000000..1718dba Binary files /dev/null and b/textures/techage_collider_detector_banner.png differ diff --git a/textures/techage_collider_detector_core.png b/textures/techage_collider_detector_core.png new file mode 100644 index 0000000..b0edd8d Binary files /dev/null and b/textures/techage_collider_detector_core.png differ diff --git a/textures/techage_collider_magnet.png b/textures/techage_collider_magnet.png new file mode 100644 index 0000000..7a81fd5 Binary files /dev/null and b/textures/techage_collider_magnet.png differ diff --git a/textures/techage_collider_magnet_appl.png b/textures/techage_collider_magnet_appl.png new file mode 100644 index 0000000..2f748e1 Binary files /dev/null and b/textures/techage_collider_magnet_appl.png differ diff --git a/textures/techage_collider_magnet_sign.png b/textures/techage_collider_magnet_sign.png new file mode 100644 index 0000000..5493297 Binary files /dev/null and b/textures/techage_collider_magnet_sign.png differ diff --git a/textures/techage_collider_magnet_tube.png b/textures/techage_collider_magnet_tube.png new file mode 100644 index 0000000..040c3e5 Binary files /dev/null and b/textures/techage_collider_magnet_tube.png differ diff --git a/textures/techage_collider_plan.png b/textures/techage_collider_plan.png new file mode 100644 index 0000000..3cdc09d Binary files /dev/null and b/textures/techage_collider_plan.png differ diff --git a/textures/techage_collider_tube.png b/textures/techage_collider_tube.png new file mode 100644 index 0000000..2ef480b Binary files /dev/null and b/textures/techage_collider_tube.png differ diff --git a/textures/techage_collider_tube_open.png b/textures/techage_collider_tube_open.png new file mode 100644 index 0000000..21af706 Binary files /dev/null and b/textures/techage_collider_tube_open.png differ diff --git a/textures/techage_round_ceramic.png b/textures/techage_round_ceramic.png new file mode 100644 index 0000000..70d5dd6 Binary files /dev/null and b/textures/techage_round_ceramic.png differ