From 711a32d20cc7bad4f28b300ff2dfd45aee186a46 Mon Sep 17 00:00:00 2001 From: Vanessa Ezekowitz Date: Fri, 26 Dec 2014 16:51:02 -0500 Subject: [PATCH] initial commit: auto-closing doors forked from Home Decor's doors code --- README | 0 depends.txt | 1 + door_models.lua | 18 + init.lua | 433 ++++++++++++++++++ .../autoclose_doors_plain_left_bottom.png | Bin 0 -> 539 bytes textures/autoclose_doors_plain_left_inv.png | Bin 0 -> 475 bytes textures/autoclose_doors_plain_left_top.png | Bin 0 -> 561 bytes textures/autoclose_doors_plain_lrb.png | Bin 0 -> 185 bytes textures/autoclose_doors_plain_lrt.png | Bin 0 -> 185 bytes .../autoclose_doors_plain_right_bottom.png | Bin 0 -> 537 bytes textures/autoclose_doors_plain_right_top.png | Bin 0 -> 554 bytes textures/autoclose_doors_plain_tb.png | Bin 0 -> 165 bytes 12 files changed, 452 insertions(+) create mode 100644 README create mode 100644 depends.txt create mode 100644 door_models.lua create mode 100644 init.lua create mode 100644 textures/autoclose_doors_plain_left_bottom.png create mode 100644 textures/autoclose_doors_plain_left_inv.png create mode 100644 textures/autoclose_doors_plain_left_top.png create mode 100644 textures/autoclose_doors_plain_lrb.png create mode 100644 textures/autoclose_doors_plain_lrt.png create mode 100644 textures/autoclose_doors_plain_right_bottom.png create mode 100644 textures/autoclose_doors_plain_right_top.png create mode 100644 textures/autoclose_doors_plain_tb.png diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/depends.txt b/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/depends.txt @@ -0,0 +1 @@ +default diff --git a/door_models.lua b/door_models.lua new file mode 100644 index 0000000..9e506d4 --- /dev/null +++ b/door_models.lua @@ -0,0 +1,18 @@ + +local S = autoclose_doors.gettext + +autoclose_doors.door_models = { + { + "plain", + S("Auto-closing door, plain"), + + {{ -8/16, -8/16, 6/16, 8/16, 8/16, 8/16 }}, + + {{ -8/16, -8/16, 6/16, 8/16, 8/16, 8/16 }}, + + {{ -8/16, -8/16, 6/16, 8/16, 8/16, 8/16 }}, + + {{ -8/16, -8/16, 6/16, 8/16, 8/16, 8/16 }} + }, +} + diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..6f33cca --- /dev/null +++ b/init.lua @@ -0,0 +1,433 @@ +-- Auto-closing doors +-- forked from homedecor's door code + +autoclose_doors = {} + +-- Boilerplate to support localized strings if intllib mod is installed. +local S +if autoclose_doors.intllib_modpath then + dofile(autoclose_doors.intllib_modpath.."/intllib.lua") + S = intllib.Getter(minetest.get_current_modname()) +else + S = function ( s ) return s end +end +autoclose_doors.gettext = S + +-- + +function autoclose_doors.get_nodedef_field(nodename, fieldname) + if not minetest.registered_nodes[nodename] then + return nil + end + return minetest.registered_nodes[nodename][fieldname] +end + +-- the model file + +local modpath = minetest.get_modpath("autoclose_doors") +dofile(modpath.."/door_models.lua") + +-- the good stuff! + +local function isSolid(pos,adj) + local adj = {x=adj[1],y=adj[2],z=adj[3]} + local node = minetest.get_node(vector.add(pos,adj)) + if node then + local idef = minetest.registered_nodes[minetest.get_node(vector.add(pos,adj)).name] + if idef then + return idef.walkable + end + end + return false +end + +local function countSolids(pos,node,level) + local solids = 0 + for x = -1, 1 do + for z = -1, 1 do + local y = 0 + if node.param2 == 5 then + y = -level + else + y = level + end + -- special cases when x == z == 0 + if x == 0 and z == 0 then + if level == 1 then + -- when looking past the trap door, cannot be solid in center + if isSolid(pos,{x,y,z}) then + return false + end + -- no else. it doesn't matter if x == y == z is solid, that's us. + end + elseif isSolid(pos,{x,y,z}) then + solids = solids + 1 + end + end + end + return solids +end + +local function calculateClosed(pos) + local node = minetest.get_node(pos) + -- the door is considered closed if it is closing off something. + + local solids = 0 + local direction = node.param2 % 6 + local isTrap = direction == 0 or direction == 5 + if isTrap then + -- the trap door is considered closed when all nodes on its sides are solid + -- or all nodes in the 3x3 above/below it are solid except the center + for level = 0, 1 do + local fail = false + local solids = countSolids(pos,node,level) + if solids == 8 then + return true + end + end + return false + else + -- the door is considered closed when the nodes on its sides are solid + -- or the 3 nodes in its facing direction are solid nonsolid solid + + -- sorry I dunno the math to figure whether to x or z + if direction == 1 or direction == 2 then + if isSolid(pos,{0,0,-1}) and isSolid(pos,{0,0,1}) then + if string.find(node.name,'_bottom_') then + return calculateClosed({x=pos.x,y=pos.y+1,z=pos.z}) + else + return true + end + end + local x + if direction == 1 then + x = 1 + else + x = -1 + end + if isSolid(pos,{x,0,-1}) and not isSolid(pos,{x,0,0}) and isSolid(pos,{x,0,1}) then + if string.find(node.name,'_bottom_') then + return calculateClosed({x=pos.x,y=pos.y+1,z=pos.z}) + else + return true + end + end + return false + else + -- direction == 3 or 4 + if isSolid(pos,{-1,0,0}) and isSolid(pos,{1,0,0}) then + if string.find(node.name,'_bottom_') then + return calculateClosed({x=pos.x,y=pos.y+1,z=pos.z}) + else + return true + end + end + local z + if direction == 3 then + z = 1 + else + z = -1 + end + if isSolid(pos,{-1,0,z}) and not isSolid(pos,{0,0,z}) and isSolid(pos,{1,0,z}) then + if string.find(node.name,'_bottom_') then + return calculateClosed({x=pos.x,y=pos.y+1,z=pos.z}) + else + return true + end + end + return false + end + error("What direction is this???",direction) + end +end + +-- isClosed flag, is 0 or 1 0 = open, 1 = closed +local function getClosed(pos) + local isClosed = minetest.get_meta(pos):get_string('closed') + if isClosed=='' then + if calculateClosed(pos) then + return true + else + return false + end + else + isClosed = tonumber(isClosed) + -- may be closed or open (1 or 0) + return isClosed == 1 + end +end + +local function addDoorNode(pos,def,isClosed) + if isClosed then + isClosed = 1 + else + isClosed = 0 + end + minetest.add_node(pos, def) + minetest.get_meta(pos):set_int('closed',isClosed) +end + +local sides = {"left", "right"} +local rsides = {"right", "left"} + +for i in ipairs(sides) do + local side = sides[i] + local rside = rsides[i] + + for j in ipairs(autoclose_doors.door_models) do + local doorname = autoclose_doors.door_models[j][1] + local doordesc = autoclose_doors.door_models[j][2] + local nodeboxes_top = autoclose_doors.door_models[j][5] + local nodeboxes_bottom = autoclose_doors.door_models[j][6] + local texalpha = false + + if side == "left" then + nodeboxes_top = autoclose_doors.door_models[j][3] + nodeboxes_bottom = autoclose_doors.door_models[j][4] + end + + local lower_top_side = "autoclose_doors_"..doorname.."_tb.png" + local upper_bottom_side = "autoclose_doors_"..doorname.."_tb.png" + + local tiles_upper = { + "autoclose_doors_"..doorname.."_tb.png", + upper_bottom_side, + "autoclose_doors_"..doorname.."_lrt.png", + "autoclose_doors_"..doorname.."_lrt.png", + "autoclose_doors_"..doorname.."_"..rside.."_top.png", + "autoclose_doors_"..doorname.."_"..side.."_top.png", + } + + local tiles_lower = { + lower_top_side, + "autoclose_doors_"..doorname.."_tb.png", + "autoclose_doors_"..doorname.."_lrb.png", + "autoclose_doors_"..doorname.."_lrb.png", + "autoclose_doors_"..doorname.."_"..rside.."_bottom.png", + "autoclose_doors_"..doorname.."_"..side.."_bottom.png", + } + + local selectboxes_top = { + type = "fixed", + fixed = { -0.5, -1.5, 6/16, 0.5, 0.5, 8/16} + } + + local selectboxes_bottom = { + type = "fixed", + fixed = { -0.5, -0.5, 6/16, 0.5, 1.5, 8/16} + } + + minetest.register_node("autoclose_doors:"..doorname.."_top_"..side, { + description = doordesc.." "..S("(Top Half, %s-opening)"):format(side), + drawtype = "nodebox", + tiles = tiles_upper, + paramtype = "light", + paramtype2 = "facedir", + groups = {snappy=3, not_in_creative_inventory=1}, + sounds = default.node_sound_wood_defaults(), + walkable = true, + use_texture_alpha = texalpha, + selection_box = selectboxes_top, + node_box = { + type = "fixed", + fixed = nodeboxes_top + }, + drop = "autoclose_doors:"..doorname.."_bottom_"..side, + after_dig_node = function(pos, oldnode, oldmetadata, digger) + if minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name == "autoclose_doors:"..doorname.."_bottom_"..side then + minetest.remove_node({x=pos.x, y=pos.y-1, z=pos.z}) + end + end, + on_rightclick = function(pos, node, clicker) + autoclose_doors.flip_door({x=pos.x, y=pos.y-1, z=pos.z}, node, clicker, doorname, side) + end + }) + + local dgroups = {snappy=3, not_in_creative_inventory=1} + if side == "left" then + dgroups = {snappy=3} + end + + minetest.register_node("autoclose_doors:"..doorname.."_bottom_"..side, { + description = doordesc.." "..S("(%s-opening)"):format(side), + drawtype = "nodebox", + tiles = tiles_lower, + inventory_image = "autoclose_doors_"..doorname.."_left_inv.png", + wield_image = "autoclose_doors_"..doorname.."_left_inv.png", + paramtype = "light", + paramtype2 = "facedir", + groups = dgroups, + sounds = default.node_sound_wood_defaults(), + walkable = true, + use_texture_alpha = texalpha, + selection_box = selectboxes_bottom, + node_box = { + type = "fixed", + fixed = nodeboxes_bottom + }, + after_dig_node = function(pos, oldnode, oldmetadata, digger) + if minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z}).name == "autoclose_doors:"..doorname.."_top_"..side then + minetest.remove_node({x=pos.x, y=pos.y+1, z=pos.z}) + end + end, + on_place = function(itemstack, placer, pointed_thing) + local keys=placer:get_player_control() + autoclose_doors.place_door(itemstack, placer, pointed_thing, doorname, keys["sneak"]) + return itemstack + end, + on_rightclick = function(pos, node, clicker) + autoclose_doors.flip_door(pos, node, clicker, doorname, side) + end, + -- both left and right doors may be used for open or closed doors + -- so they have to have both action_on and action_off and just + -- check when that action is invoked if to continue + + on_punch = function(pos, node, puncher) + minetest.get_meta(pos):set_string('closed',nil) + end, + drop = "autoclose_doors:"..doorname.."_bottom_left", + mesecons = { + effector = { + action_on = function(pos,node) + local isClosed = getClosed(pos) + if isClosed then + autoclose_doors.flip_door(pos,node,nil,doorname,side,isClosed) + end + end, + action_off = function(pos,node) + local isClosed = getClosed(pos) + if not isClosed then + autoclose_doors.flip_door(pos,node,nil,doorname,side,isClosed) + end + end + } + } + }) + + minetest.register_abm({ + nodenames = {"autoclose_doors:"..doorname.."_bottom_"..side}, + chance = 1, + interval = 10, + action = function(pos, node, active_object_count, active_object_count_wider) + if not getClosed(pos) then + autoclose_doors.flip_door(pos, node, nil, doorname, side, false) + end + end + }) + end +end + +----- helper functions + +function autoclose_doors.place_door(itemstack, placer, pointed_thing, name, forceright) + + local pointed = pointed_thing.under + local pnode = minetest.get_node(pointed) + local pname = pnode.name + local rnodedef = minetest.registered_nodes[pname] + + if rnodedef then + + if rnodedef.on_rightclick then + rnodedef.on_rightclick(pointed_thing.under, pnode, placer, itemstack) + return + end + + local pos1 = nil + local pos2 = nil + + if rnodedef["buildable_to"] then + pos1 = pointed + pos2 = {x=pointed.x, y=pointed.y+1, z=pointed.z} + else + pos1 = pointed_thing.above + pos2 = {x=pointed_thing.above.x, y=pointed_thing.above.y+1, z=pointed_thing.above.z} + end + + local node_bottom = minetest.get_node(pos1) + local node_top = minetest.get_node(pos2) + + if minetest.is_protected(pos1, placer:get_player_name()) then + minetest.record_protection_violation(pos1, + placer:get_player_name()) + return + end + + if minetest.is_protected(pos2, placer:get_player_name()) then + minetest.record_protection_violation(pos2, + placer:get_player_name()) + return + end + + if not autoclose_doors.get_nodedef_field(node_bottom.name, "buildable_to") + or not autoclose_doors.get_nodedef_field(node_top.name, "buildable_to") then + minetest.chat_send_player( placer:get_player_name(), S('Not enough space above that spot to place a door!') ) + else + local fdir = minetest.dir_to_facedir(placer:get_look_dir()) + local p_tests = { + {x=pos1.x-1, y=pos1.y, z=pos1.z}, + {x=pos1.x, y=pos1.y, z=pos1.z+1}, + {x=pos1.x+1, y=pos1.y, z=pos1.z}, + {x=pos1.x, y=pos1.y, z=pos1.z-1}, + } + print("fdir="..fdir) + local testnode = minetest.get_node(p_tests[fdir+1]) + local side = "left" + + if string.find(testnode.name, "autoclose_doors:"..name.."_bottom_left") or forceright then + side = "right" + end + + local def = { name = "autoclose_doors:"..name.."_bottom_"..side, param2=fdir} + addDoorNode(pos1, def, true) + minetest.add_node(pos2, { name = "autoclose_doors:"..name.."_top_"..side, param2=fdir}) + if not autoclose_doors.expect_infinite_stacks then + itemstack:take_item() + return itemstack + end + end + end +end + +-- to open a door, you switch left for right and subtract from param2, or vice versa right for left +-- that is to say open "right" doors become left door nodes, and open left doors right door nodes. +-- also adjusting param2 so the node is at 90 degrees. + +function autoclose_doors.flip_door(pos, node, player, name, side, isClosed) + if isClosed == nil then + isClosed = getClosed(pos) + end + -- this is where we swap the isClosed status! + -- i.e. if isClosed, we're adding an open door + -- and if not isClosed, a closed door + isClosed = not isClosed + + local rside = nil + local nfdir = nil + local ofdir = node.param2 or 0 + if side == "left" then + rside = "right" + nfdir=ofdir - 1 + if nfdir < 0 then nfdir = 3 end + else + rside = "left" + nfdir=ofdir + 1 + if nfdir > 3 then nfdir = 0 end + end + local sound; + if isClosed then + sound = 'close' + else + sound = 'open' + end + minetest.sound_play("autoclose_doors_"..sound, { + pos=pos, + max_hear_distance = 5, + gain = 2, + }) + -- XXX: does the top half have to remember open/closed too? + minetest.add_node({x=pos.x, y=pos.y+1, z=pos.z}, { name = "autoclose_doors:"..name.."_top_"..rside, param2=nfdir}) + + addDoorNode(pos,{ name = "autoclose_doors:"..name.."_bottom_"..rside, param2=nfdir },isClosed) +end + diff --git a/textures/autoclose_doors_plain_left_bottom.png b/textures/autoclose_doors_plain_left_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..17e5479dcd0471f101e220e12b806d45e9779f62 GIT binary patch literal 539 zcmV+$0_6RPP)| zPiquG5Jz8C|JiIr5Cs*92)UTEU_igT-@%)BjRzry5KMMwrn`O~dNxs0ry6Fu=GCie zJ3Bkm=hM#ZZX&splXJYS03eWrM#7hGkW!-7%Eyx(-!HDoA5M?C-CbfBhuBRG8|RU9 zU+DaukQQLi?Op)nnqe~dc|8b{gP9=!3D&|7&m({JY{RBFx#W!1M9t2d7h6(t+>DTr zz}#?i%(!Rtqvy1{U(~XYdj!HjqDK${UkN1Pa_}IzAu|xf;hh_~g)p(A8WIF6svsgj zMucGo5yDbqo)&)JP2?v>l~AVE%yv_Tw6(y$acDqmDsnPh5#%(+SF#UO-TN9`24_6vcmc-kW*z()Utn{Id}R1#x3txh-{};KmQ2pTIBYP6QV!E<_L)>Pi<TNFdhD+@P!;^;J{Q*0-x3sRi^an$Bw|iQ4DiVQK0$=15&hqxlK%T$b6Yp}~ zd_I&H?|(?;^Y(xcl!!gUSS;mux@aGvu&{Szd3^t-Zk7;LdHU#vYJy)Q(@rpMBHnvK zf~bP3Fb_f#V1K;E8f_*tO@qc6gCU3rB0`d!>(w7VuG52Cy)mV8fRGs>&kdS&7#vR9 z3F^|Z*zk0`;k2^~2+{o0tv#4AZ33DE5irI831gK-T%$<7$e7PEF4PWV41$swgILeW zv*LKIX&P_%8+s?hR(h>SpJ6Ic)w^xp*%v~3}^YSAvkd`5^BqEEl` z1-*Cc z!lYMbi0I^P2b|MBLx*0JjF(|K}taxiqvwu?s zc)7Mb_0R#gaoiyUVy+Fzl~Nm9U$?1koHu}qAOc^uw$I*ytC!|z&4_(&&{z80c>CdW z3eQ%Td^p@;V{>>4fBtC6^U)s7oY*DBP0xMnpbK;<%;58LkysN8^Bu8E0VUC;HbV>( zZ_ZW<3PHe)C@7^GxttSMY2-R9e3C1jGImi!8><<9?>Pdy_QYHc;8R{eNi k{H?OZSNbB)fBwR((Pp^(en->=pj#L`UHx3vIVCg!0G75%LjV8( literal 0 HcmV?d00001 diff --git a/textures/autoclose_doors_plain_lrt.png b/textures/autoclose_doors_plain_lrt.png new file mode 100644 index 0000000000000000000000000000000000000000..a0418829d9d1f9aab8ee1f22fddb0014038a2654 GIT binary patch literal 185 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|4W2HJAsXk;UUK9+WWeKc@tL(J zcSzFlzU~6{cl8Y4JUnzSn3U~k+MN8&|5}gCyX~)k)$r`w^72sjPri3gIFb+Xdzlt_ z)d{FF9OPeRHtqW}_RobXUdLO%1`7z<3oxy^#>jGImi!8><<9?>Pdy_QYHc;8R{eNi k{H?OZSNbB)fBwR((Pp^(en->=pj#L`UHx3vIVCg!0G75%LjV8( literal 0 HcmV?d00001 diff --git a/textures/autoclose_doors_plain_right_bottom.png b/textures/autoclose_doors_plain_right_bottom.png new file mode 100644 index 0000000000000000000000000000000000000000..9bbc3da4e560d38d1adf3952081adc362929105e GIT binary patch literal 537 zcmV+!0_OdRP)| zPi|B(42M5EPG*K~5S0o-aDiTc18@Y+z){(823AlB2`W^8loEEMxE2@Ge<+KDc{}U1C zKprvgfJbmuj#x2R1it@TNU9_S5h1oT$R_5TK7g0cckHra*$gR(V#@2w11TvgvStHO zK}8YSLV@mI(2qYUxnaYdKp=wQjtA(fAR^FEP$#JnA`sx4PX+59NU%y3BEX3=D0hbt z+yxPE4p;chjt0f`eg=I z6_P61jFb{q`#@@^^+9b;>x0(EgryVSW3wD|cgApRsRNeIQU~|7;}H|2$|LDdZFpcM zE8$aq$#Vil1XVeI6`7rxY6NzM^~}YgU?nG%Ov!_NG5Dw75nKIpE(Mv4l0p)0mMct9 zT6b!5?rVR_euXgH36BYyPF*^8cX!zFzA~0ZZH-~C5P1OSu??=wU2rD^q&8~pytz1H zIV-6vZ?B#q^>!t%5P=V;4@Xr{g|w}sFqxTRhh5>@kAB|1;p_G>r*1?b5vW4W2|>

3&8 literal 0 HcmV?d00001 diff --git a/textures/autoclose_doors_plain_right_top.png b/textures/autoclose_doors_plain_right_top.png new file mode 100644 index 0000000000000000000000000000000000000000..cd0be2bdb5cb5aee21a2d4409ab4349e55b8a7f8 GIT binary patch literal 554 zcmV+_0@eMAP)abjZs0i1bRqV=(T|T15rPUO z1XP9D{+Wp5=9o_h4(86!lRw0qz=Lr3yAV_f+9M+K4j?cW^Z9)F#(<@y#1tcv134<2 zTL;tX8Q#5I^}U0AK7HA}z<*eO>~(z13AfN@h9h(J^JwN+TjULJcTP`FiPao&=0`mb zcW}1_zLZModhU(Rh@+*9c_in!P?(dDqAu_vQzv2&qMH$e5`*&b)e~>cY4*RX0PojV z=N>xXHjO)kKrFQ(rP9~N_KzKEo8}FmB8b5E?VZbK;Lgnftr@W^4Z2EK8lS&iOySMi zitq35vAMN>fq(mA#mm_d&77E%;-**LbtwmO3Jd&j5Q#N08fIcn0VR=BTPO@OZ!RMR zg&^QY6qLRirN1JszESF;@T62qS22S)o)lWwQ~I8b=Z{=u_K|>6jZzvLYb);Vm>DWC zDLtiB#$8WLNr_FlzdS-+bRku8b4Q>RKrm| zVVh=xgTe~DWM4fF$6!U literal 0 HcmV?d00001