Procházet zdrojové kódy

Xpanes: Convert to connected nodeboxes

I've rewritten this to use connected nodeboxes, but with a caveat. In
order to make flat nodes look better, I'm keeping one non-connected
pane that is flat around to convert flat sections to the flat nodes
instead of connected, as these look better and are easier to work
with. Once more sides are needed we convert the panes on the fly to
connected nodes and recalculate the shape.

We don't paint any of the half-panes that the previous generation of
xpanes did. There's no need and it's harder to work with. Updating the
nodes also seems more natural and placement and removal works straight
forward.

The conversion of old panes relies on an LBM, and does a reasonable
conversion job, but it's not exact, since the panes behave slightly
different now.

The game API documentation was wrong to begin with. We discard param
nr. 2 of the API entirely, and correct the tile usage text.
Auke Kok před 8 roky
rodič
revize
54235f3276
4 změnil soubory, kde provedl 136 přidání a 133 odebrání
  1. 1 1
      game_api.txt
  2. 1 0
      mods/xpanes/README.txt
  3. 133 132
      mods/xpanes/init.lua
  4. 1 0
      mods/xpanes/license.txt

+ 1 - 1
game_api.txt

@@ -421,7 +421,7 @@ Creates panes that automatically connect to each other
 ### Pane definition
 
 	{
-		textures = {"texture_Bottom_top", "texture_left_right", "texture_front_back"}, -- More tiles aren't supported
+		textures = {"texture for sides", (unused), "texture for top and bottom"}, -- More tiles aren't supported
 		groups = {group = rating}, -- Uses the known node groups, see [Known damage and digging time defining groups]
 		sounds = SoundSpec,        -- See [#Default sounds]
 		recipe = {{"","","","","","","","",""}}, -- Recipe field only

+ 1 - 0
mods/xpanes/README.txt

@@ -6,6 +6,7 @@ Authors of source code
 ----------------------
 Originally by xyz (MIT)
 BlockMen (MIT)
+sofar (MIT)
 Various Minetest developers and contributors (MIT)
 
 Authors of media (textures)

+ 133 - 132
mods/xpanes/init.lua

@@ -1,156 +1,146 @@
-xpanes = {}
 
-local function rshift(x, by)
-	return math.floor(x / 2 ^ by)
+local function is_pane(pos)
+	return minetest.get_item_group(minetest.get_node(pos).name, "pane") > 0
 end
 
-local directions = {
-	{x = 1, y = 0, z = 0},
-	{x = 0, y = 0, z = 1},
-	{x = -1, y = 0, z = 0},
-	{x = 0, y = 0, z = -1},
-}
-
-local function update_pane(pos, name)
-	if not minetest.get_node(pos).name:find("^xpanes:"..name) then
-		return
+local function connects_dir(pos, name, dir)
+	local aside = vector.add(pos, minetest.facedir_to_dir(dir))
+	if is_pane(aside) then
+		return true
 	end
-	local sum = 0
-	for i, dir in pairs(directions) do
-		local node = minetest.get_node(vector.add(pos, dir))
-		local def = minetest.registered_nodes[node.name]
-		local pane_num = def and def.groups.pane or 0
-		if pane_num > 0 or not def or (def.walkable ~= false and
-				def.drawtype ~= "nodebox") then
-			sum = sum + 2 ^ (i - 1)
-		end
+
+	local connects_to = minetest.registered_nodes[name].connects_to
+	if not connects_to then
+		return false
 	end
-	if sum == 0 then
-		sum = 15
+	local list = minetest.find_nodes_in_area(aside, aside, connects_to)
+
+	if #list > 0 then
+		return true
 	end
-	minetest.set_node(pos, {name = "xpanes:"..name.."_"..sum})
+
+	return false
 end
 
-local function update_nearby(pos, node)
-	node = node or minetest.get_node(pos)
-	local name = node.name
-	if not name or node.name:sub(1, 7) ~= "xpanes:" then
+local function swap(pos, node, name, param2)
+	if node.name == name and node.param2 == param2 then
 		return
 	end
-	local underscore_pos = string.find(name, "_[^_]*$") or 0
-	local len = name:len()
-	local num = tonumber(name:sub(underscore_pos+1, len))
-	if not num or num < 1 or num > 15 then
-		name = name:sub(8)
-	else
-		name = name:sub(8, underscore_pos - 1)
-	end
-	for i, dir in pairs(directions) do
-		update_pane(vector.add(pos, dir), name)
-	end
+
+	minetest.set_node(pos, {name = name, param2 = param2})
 end
 
-minetest.register_on_placenode(update_nearby)
-minetest.register_on_dignode(update_nearby)
-
-local half_boxes = {
-	{0,     -0.5, -1/32, 0.5,  0.5, 1/32},
-	{-1/32, -0.5, 0,     1/32, 0.5, 0.5},
-	{-0.5,  -0.5, -1/32, 0,    0.5, 1/32},
-	{-1/32, -0.5, -0.5,  1/32, 0.5, 0}
-}
-
-local full_boxes = {
-	{-0.5,  -0.5, -1/32, 0.5,  0.5, 1/32},
-	{-1/32, -0.5, -0.5,  1/32, 0.5, 0.5}
-}
-
-local sb_half_boxes = {
-	{0,     -0.5, -0.06, 0.5,  0.5, 0.06},
-	{-0.06, -0.5, 0,     0.06, 0.5, 0.5},
-	{-0.5,  -0.5, -0.06, 0,    0.5, 0.06},
-	{-0.06, -0.5, -0.5,  0.06, 0.5, 0}
-}
-
-local sb_full_boxes = {
-	{-0.5,  -0.5, -0.06, 0.5,  0.5, 0.06},
-	{-0.06, -0.5, -0.5,  0.06, 0.5, 0.5}
-}
-
-local pane_def_fields = {
-	drawtype = "airlike",
-	paramtype = "light",
-	is_ground_content = false,
-	sunlight_propagates = true,
-	walkable = false,
-	pointable = false,
-	diggable = false,
-	buildable_to = true,
-	air_equivalent = true,
-}
+local function update_pane(pos)
+	if not is_pane(pos) then
+		return
+	end
+	local node = minetest.get_node(pos)
+	local name = node.name
+	if name:sub(-5) == "_flat" then
+		name = name:sub(1, -6)
+	end
 
-function xpanes.register_pane(name, def)
-	for i = 1, 15 do
-		local need = {}
-		local cnt = 0
-		for j = 1, 4 do
-			if rshift(i, j - 1) % 2 == 1 then
-				need[j] = true
-				cnt = cnt + 1
-			end
-		end
-		local take = {}
-		local take2 = {}
-		if need[1] == true and need[3] == true then
-			need[1] = nil
-			need[3] = nil
-			table.insert(take, full_boxes[1])
-			table.insert(take2, sb_full_boxes[1])
+	local any = node.param2
+	local c = {}
+	local count = 0
+	for dir = 0, 3 do
+		c[dir] = connects_dir(pos, name, dir)
+		if c[dir] then
+			any = dir
+			count = count + 1
 		end
-		if need[2] == true and need[4] == true then
-			need[2] = nil
-			need[4] = nil
-			table.insert(take, full_boxes[2])
-			table.insert(take2, sb_full_boxes[2])
-		end
-		for k in pairs(need) do
-			table.insert(take, half_boxes[k])
-			table.insert(take2, sb_half_boxes[k])
-		end
-		local texture = def.textures[1]
-		if cnt == 1 then
-			texture = def.textures[1].."^"..def.textures[2]
+	end
+
+	if count == 0 then
+		swap(pos, node, name .. "_flat", any)
+	elseif count == 1 then
+		swap(pos, node, name .. "_flat", (any + 1) % 4)
+	elseif count == 2 then
+		if (c[0] and c[2]) or (c[1] and c[3]) then
+			swap(pos, node, name .. "_flat", (any + 1) % 4)
+		else
+			swap(pos, node, name, 0)
 		end
-		minetest.register_node(":xpanes:"..name.."_"..i, {
-			drawtype = "nodebox",
-			tiles = {def.textures[3], def.textures[3], texture},
-			paramtype = "light",
-			groups = def.groups,
-			drop = "xpanes:"..name,
-			sounds = def.sounds,
-			node_box = {
-				type = "fixed",
-				fixed = take
-			},
-			selection_box = {
-				type = "fixed",
-				fixed = take2
-			}
-		})
+	else
+		swap(pos, node, name, 0)
+	end
+end
+
+minetest.register_on_placenode(function(pos, node)
+	if minetest.get_item_group(node, "pane") then
+		update_pane(pos)
+	end
+	for i = 0, 3 do
+		local dir = minetest.facedir_to_dir(i)
+		update_pane(vector.add(pos, dir))
 	end
+end)
 
-	for k, v in pairs(pane_def_fields) do
-		def[k] = def[k] or v
+minetest.register_on_dignode(function(pos)
+	for i = 0, 3 do
+		local dir = minetest.facedir_to_dir(i)
+		update_pane(vector.add(pos, dir))
 	end
+end)
 
-	def.on_construct = function(pos)
-		update_pane(pos, name)
+xpanes = {}
+function xpanes.register_pane(name, def)
+	for i = 1, 15 do
+		minetest.register_alias("xpanes:" .. name .. "_" .. i, "xpanes:" .. name .. "_flat")
 	end
 
-	minetest.register_node(":xpanes:"..name, def)
+	local flatgroups = table.copy(def.groups)
+	flatgroups.pane = 1
+	minetest.register_node(":xpanes:" .. name .. "_flat", {
+		description = def.description,
+		drawtype = "nodebox",
+		paramtype = "light",
+		is_ground_content = false,
+		sunlight_propagates = true,
+		inventory_image = def.inventory_image,
+		wield_image = def.wield_image,
+		paramtype2 = "facedir",
+		tiles = {def.textures[3], def.textures[3], def.textures[1]},
+		groups = flatgroups,
+		drop = "xpanes:" .. name .. "_flat",
+		sounds = def.sounds,
+		node_box = {
+			type = "fixed",
+			fixed = {{-1/2, -1/2, -1/32, 1/2, 1/2, 1/32}},
+		},
+		selection_box = {
+			type = "fixed",
+			fixed = {{-1/2, -1/2, -1/32, 1/2, 1/2, 1/32}},
+		},
+		connect_sides = { "left", "right" },
+	})
+
+	local groups = table.copy(def.groups)
+	groups.pane = 1
+	groups.not_in_creative_inventory = 1
+	minetest.register_node(":xpanes:" .. name, {
+		drawtype = "nodebox",
+		paramtype = "light",
+		is_ground_content = false,
+		sunlight_propagates = true,
+		description = def.description,
+		tiles = {def.textures[3], def.textures[3], def.textures[1]},
+		groups = groups,
+		drop = "xpanes:" .. name .. "_flat",
+		sounds = def.sounds,
+		node_box = {
+			type = "connected",
+			fixed = {{-1/32, -1/2, -1/32, 1/32, 1/2, 1/32}},
+			connect_front = {{-1/32, -1/2, -1/2, 1/32, 1/2, -1/32}},
+			connect_left = {{-1/2, -1/2, -1/32, -1/32, 1/2, 1/32}},
+			connect_back = {{-1/32, -1/2, 1/32, 1/32, 1/2, 1/2}},
+			connect_right = {{1/32, -1/2, -1/32, 1/2, 1/2, 1/32}},
+		},
+		connects_to = {"group:pane", "group:stone", "group:glass", "group:wood", "group:tree"},
+	})
 
 	minetest.register_craft({
-		output = "xpanes:"..name.." 16",
+		output = "xpanes:" .. name .. "_flat 16",
 		recipe = def.recipe
 	})
 end
@@ -161,7 +151,7 @@ xpanes.register_pane("pane", {
 	inventory_image = "default_glass.png",
 	wield_image = "default_glass.png",
 	sounds = default.node_sound_glass_defaults(),
-	groups = {snappy=2, cracky=3, oddly_breakable_by_hand=3, pane=1},
+	groups = {snappy=2, cracky=3, oddly_breakable_by_hand=3},
 	recipe = {
 		{"default:glass", "default:glass", "default:glass"},
 		{"default:glass", "default:glass", "default:glass"}
@@ -173,7 +163,7 @@ xpanes.register_pane("bar", {
 	textures = {"xpanes_bar.png","xpanes_bar.png","xpanes_space.png"},
 	inventory_image = "xpanes_bar.png",
 	wield_image = "xpanes_bar.png",
-	groups = {cracky=2, pane=1},
+	groups = {cracky=2},
 	sounds = default.node_sound_stone_defaults(),
 	recipe = {
 		{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
@@ -181,3 +171,14 @@ xpanes.register_pane("bar", {
 	}
 })
 
+minetest.register_lbm({
+	name = "xpanes:gen2",
+	nodenames = {"group:pane"},
+	action = function(pos, node)
+		update_pane(pos)
+		for i = 0, 3 do
+			local dir = minetest.facedir_to_dir(i)
+			update_pane(vector.add(pos, dir))
+		end
+	end
+})

+ 1 - 0
mods/xpanes/license.txt

@@ -4,6 +4,7 @@ License of source code
 The MIT License (MIT)
 Copyright (C) 2014-2016 xyz
 Copyright (C) 2014-2016 BlockMen
+Copyright (C) 2016 Auke Kok <sofar@foo-projects.org>
 Copyright (C) 2014-2016 Various Minetest developers and contributors
 
 Permission is hereby granted, free of charge, to any person obtaining a copy of this