Improve move-controller, remove 'move' command
This commit is contained in:
parent
b3ddc91489
commit
deab00aa07
@ -27,6 +27,32 @@ local Input = {
|
|||||||
20,21,22,23, -- 6
|
20,21,22,23, -- 6
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- Input data for facedir_to_rotation
|
||||||
|
local PARAM2_TO_ROT = {[0] =
|
||||||
|
1,39,35,47,
|
||||||
|
49,38,32,48,
|
||||||
|
17,14,56,8,
|
||||||
|
2,50,12,28,
|
||||||
|
4,20,10,52,
|
||||||
|
3,7,11,15
|
||||||
|
}
|
||||||
|
|
||||||
|
local Rotations = {}
|
||||||
|
|
||||||
|
for x = 0,3 do
|
||||||
|
for y = 0,3 do
|
||||||
|
for z = 0,3 do
|
||||||
|
Rotations[#Rotations + 1] = {x=x*math.pi/2, y=y*math.pi/2, z=z*math.pi/2}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function techage.facedir_to_rotation(facedir)
|
||||||
|
local idx = PARAM2_TO_ROT[facedir] or 0
|
||||||
|
return Rotations[idx]
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- allowed for digging
|
-- allowed for digging
|
||||||
local RegisteredNodesToBeDug = {}
|
local RegisteredNodesToBeDug = {}
|
||||||
|
|
||||||
|
@ -1620,7 +1620,6 @@ techage.manual_DE.aText = {
|
|||||||
"\n"..
|
"\n"..
|
||||||
" - 'a2b' Bewege Block von A nach B\n"..
|
" - 'a2b' Bewege Block von A nach B\n"..
|
||||||
" - 'b2a' Bewege Block von B nach A\n"..
|
" - 'b2a' Bewege Block von B nach A\n"..
|
||||||
" - 'move' Bewege Block auf die andere Seite\n"..
|
|
||||||
"\n"..
|
"\n"..
|
||||||
"\n"..
|
"\n"..
|
||||||
"\n",
|
"\n",
|
||||||
|
@ -1618,7 +1618,6 @@ techage.manual_EN.aText = {
|
|||||||
"\n"..
|
"\n"..
|
||||||
" - 'a2b' Move block from A to B.\n"..
|
" - 'a2b' Move block from A to B.\n"..
|
||||||
" - 'b2a' Move block from B to A.\n"..
|
" - 'b2a' Move block from B to A.\n"..
|
||||||
" - 'move' Move block to the other side\n"..
|
|
||||||
"\n"..
|
"\n"..
|
||||||
"\n"..
|
"\n"..
|
||||||
"\n",
|
"\n",
|
||||||
|
@ -143,6 +143,21 @@ end
|
|||||||
|
|
||||||
local lcd_box = {-8/16, -4/16, 7.75/16, 8/16, 4/16, 8/16}
|
local lcd_box = {-8/16, -4/16, 7.75/16, 8/16, 4/16, 8/16}
|
||||||
|
|
||||||
|
local function can_access(pos, player)
|
||||||
|
local meta = M(pos)
|
||||||
|
local playername = player:get_player_name()
|
||||||
|
local access = meta:get_string("access")
|
||||||
|
local owner = meta:get_string("owner")
|
||||||
|
local protected = minetest.is_protected(pos, playername)
|
||||||
|
|
||||||
|
if access == "private" and playername ~= owner then
|
||||||
|
return false
|
||||||
|
elseif access == "protected" and protected then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
minetest.register_node("techage:ta4_button_2x", {
|
minetest.register_node("techage:ta4_button_2x", {
|
||||||
description = S("TA4 2x Button"),
|
description = S("TA4 2x Button"),
|
||||||
inventory_image = 'techage_smartline_button_2x.png',
|
inventory_image = 'techage_smartline_button_2x.png',
|
||||||
@ -177,14 +192,8 @@ minetest.register_node("techage:ta4_button_2x", {
|
|||||||
|
|
||||||
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||||
if clicker and clicker:is_player() then
|
if clicker and clicker:is_player() then
|
||||||
local playername = clicker:get_player_name()
|
-- Check access settings
|
||||||
if minetest.is_protected(pos, playername) then
|
if not can_access(pos, clicker) then
|
||||||
return
|
|
||||||
end
|
|
||||||
-- Check node settings in addition
|
|
||||||
local access = M(pos):get_string("access")
|
|
||||||
local owner = M(pos):get_string("owner")
|
|
||||||
if access == "private" and playername ~= owner then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -195,6 +195,21 @@ end
|
|||||||
|
|
||||||
local lcd_box = {-8/16, -8/16, 7.75/16, 8/16, 8/16, 8/16}
|
local lcd_box = {-8/16, -8/16, 7.75/16, 8/16, 8/16, 8/16}
|
||||||
|
|
||||||
|
local function can_access(pos, player)
|
||||||
|
local meta = M(pos)
|
||||||
|
local playername = player:get_player_name()
|
||||||
|
local access = meta:get_string("access")
|
||||||
|
local owner = meta:get_string("owner")
|
||||||
|
local protected = minetest.is_protected(pos, playername)
|
||||||
|
|
||||||
|
if access == "private" and playername ~= owner then
|
||||||
|
return false
|
||||||
|
elseif access == "protected" and protected then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
minetest.register_node("techage:ta4_button_4x", {
|
minetest.register_node("techage:ta4_button_4x", {
|
||||||
description = S("TA4 4x Button"),
|
description = S("TA4 4x Button"),
|
||||||
inventory_image = 'techage_smartline_button_4x.png',
|
inventory_image = 'techage_smartline_button_4x.png',
|
||||||
@ -231,14 +246,8 @@ minetest.register_node("techage:ta4_button_4x", {
|
|||||||
|
|
||||||
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||||
if clicker and clicker:is_player() then
|
if clicker and clicker:is_player() then
|
||||||
local playername = clicker:get_player_name()
|
-- Check access settings
|
||||||
if minetest.is_protected(pos, playername) then
|
if not can_access(pos, clicker) then
|
||||||
return
|
|
||||||
end
|
|
||||||
-- Check node settings in addition
|
|
||||||
local access = M(pos):get_string("access")
|
|
||||||
local owner = M(pos):get_string("owner")
|
|
||||||
if access == "private" and playername ~= owner then
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -48,8 +48,10 @@ end
|
|||||||
-- determine exact position of attached entities
|
-- determine exact position of attached entities
|
||||||
local function obj_pos(obj)
|
local function obj_pos(obj)
|
||||||
local _, _, pos = obj:get_attach()
|
local _, _, pos = obj:get_attach()
|
||||||
pos = vector.divide(pos, 29)
|
if pos then
|
||||||
return vector.add(obj:get_pos(), pos)
|
pos = vector.divide(pos, 29)
|
||||||
|
return vector.add(obj:get_pos(), pos)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check access conflicts with other mods
|
-- Check access conflicts with other mods
|
||||||
@ -77,9 +79,11 @@ end
|
|||||||
|
|
||||||
local function detach_player(player)
|
local function detach_player(player)
|
||||||
local pos = obj_pos(player)
|
local pos = obj_pos(player)
|
||||||
player:set_detach()
|
if pos then
|
||||||
player:set_properties({visual_size = {x=1, y=1}})
|
player:set_detach()
|
||||||
player:set_pos(pos)
|
player:set_properties({visual_size = {x=1, y=1}})
|
||||||
|
player:set_pos(pos)
|
||||||
|
end
|
||||||
-- TODO: move to save position
|
-- TODO: move to save position
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -153,14 +157,13 @@ local function entity_to_node(pos, obj)
|
|||||||
local self = obj:get_luaentity()
|
local self = obj:get_luaentity()
|
||||||
if self then
|
if self then
|
||||||
local name = self.item or "air"
|
local name = self.item or "air"
|
||||||
|
local param2 = self.param2 or 0
|
||||||
local metadata = self.metadata or {}
|
local metadata = self.metadata or {}
|
||||||
local rot = obj:get_rotation()
|
local rot = obj:get_rotation()
|
||||||
detach_objects(pos, self)
|
detach_objects(pos, self)
|
||||||
obj:remove()
|
obj:remove()
|
||||||
|
|
||||||
pos = vector.round(pos)
|
pos = vector.round(pos)
|
||||||
local dir = minetest.yaw_to_dir(rot.y or 0)
|
|
||||||
local param2 = minetest.dir_to_facedir(dir) or 0
|
|
||||||
local node = minetest.get_node(pos)
|
local node = minetest.get_node(pos)
|
||||||
local ndef1 = minetest.registered_nodes[name]
|
local ndef1 = minetest.registered_nodes[name]
|
||||||
local ndef2 = minetest.registered_nodes[node.name]
|
local ndef2 = minetest.registered_nodes[node.name]
|
||||||
@ -184,7 +187,7 @@ local function entity_to_node(pos, obj)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function node_to_entity(pos, handover)
|
local function node_to_entity(pos, handover, pos_2to1)
|
||||||
local meta = M(pos)
|
local meta = M(pos)
|
||||||
local node, metadata
|
local node, metadata
|
||||||
|
|
||||||
@ -198,17 +201,18 @@ local function node_to_entity(pos, handover)
|
|||||||
metadata = meta:to_table()
|
metadata = meta:to_table()
|
||||||
minetest.remove_node(pos)
|
minetest.remove_node(pos)
|
||||||
end
|
end
|
||||||
local dir = minetest.facedir_to_dir(node.param2)
|
|
||||||
local yaw = minetest.dir_to_yaw(dir)
|
|
||||||
local obj = minetest.add_entity(pos, "techage:move_item")
|
local obj = minetest.add_entity(pos, "techage:move_item")
|
||||||
if obj then
|
if obj then
|
||||||
local self = obj:get_luaentity()
|
local self = obj:get_luaentity()
|
||||||
obj:set_rotation({x=0, y=yaw, z=0})
|
local rot = techage.facedir_to_rotation(node.param2)
|
||||||
|
obj:set_rotation(rot)
|
||||||
obj:set_properties({wield_item=node.name})
|
obj:set_properties({wield_item=node.name})
|
||||||
obj:set_armor_groups({immortal=1})
|
obj:set_armor_groups({immortal=1})
|
||||||
self.item = node.name
|
self.item = node.name
|
||||||
|
self.param2 = node.param2
|
||||||
self.metadata = metadata or {}
|
self.metadata = metadata or {}
|
||||||
self.handover = handover
|
self.handover = handover
|
||||||
|
self.pos_2to1 = pos_2to1
|
||||||
self.start_pos = table.copy(pos)
|
self.start_pos = table.copy(pos)
|
||||||
return obj
|
return obj
|
||||||
end
|
end
|
||||||
@ -247,10 +251,7 @@ local function handover_to(pos, self)
|
|||||||
local mem = techage.get_mem(info.pos)
|
local mem = techage.get_mem(info.pos)
|
||||||
if not mem.entities_are_there then
|
if not mem.entities_are_there then
|
||||||
mem.entities_are_there = true
|
mem.entities_are_there = true
|
||||||
-- copy move direction
|
minetest.after(0.2, techage.send_single, "0", self.handover, "handover", self.pos_2to1)
|
||||||
--print("techage.get_nvm(pos).pos_2to1", techage.get_nvm(pos).pos_2to1)
|
|
||||||
techage.get_nvm(info.pos).pos_2to1 = techage.get_nvm(pos).pos_2to1
|
|
||||||
minetest.after(0.2, techage.send_single, "0", self.handover, "handover")
|
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@ -303,13 +304,15 @@ minetest.register_entity("techage:move_item", {
|
|||||||
local pos = obj:get_pos()
|
local pos = obj:get_pos()
|
||||||
local dist = vector.distance(pos, self.dest_pos)
|
local dist = vector.distance(pos, self.dest_pos)
|
||||||
local speed = vector.length(obj:get_velocity())
|
local speed = vector.length(obj:get_velocity())
|
||||||
|
self.old_dist = self.old_dist or dist
|
||||||
|
|
||||||
-- Landing
|
-- Landing
|
||||||
if dist < 0.05 then
|
if dist < 0.05 or dist > self.old_dist then
|
||||||
obj:move_to(self.dest_pos, true)
|
obj:move_to(self.dest_pos, true)
|
||||||
obj:set_acceleration({x=0, y=0, z=0})
|
obj:set_acceleration({x=0, y=0, z=0})
|
||||||
obj:set_velocity({x=0, y=0, z=0})
|
obj:set_velocity({x=0, y=0, z=0})
|
||||||
self.dest_pos = nil
|
self.dest_pos = nil
|
||||||
|
self.old_dist = nil
|
||||||
if not self.handover or not handover_to(pos, self) then
|
if not self.handover or not handover_to(pos, self) then
|
||||||
minetest.after(0.5, entity_to_node, pos, obj)
|
minetest.after(0.5, entity_to_node, pos, obj)
|
||||||
end
|
end
|
||||||
@ -317,6 +320,8 @@ minetest.register_entity("techage:move_item", {
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self.old_dist = dist
|
||||||
|
|
||||||
-- Braking or limit max speed
|
-- Braking or limit max speed
|
||||||
if speed > (dist * 2) or speed > self.max_speed then
|
if speed > (dist * 2) or speed > self.max_speed then
|
||||||
local speed = math.min(speed, math.max(dist * 2, MIN_SPEED))
|
local speed = math.min(speed, math.max(dist * 2, MIN_SPEED))
|
||||||
@ -527,10 +532,9 @@ local function formspec(nvm, meta)
|
|||||||
"label[0.3,4.3;" .. status .. "]"
|
"label[0.3,4.3;" .. status .. "]"
|
||||||
end
|
end
|
||||||
|
|
||||||
local function move_node(pos, pos1, pos2, max_speed, handover, height)
|
local function move_node(pos, pos1, pos2, max_speed, handover, height, pos_2to1)
|
||||||
local meta = M(pos)
|
|
||||||
local dir = determine_dir(pos1, pos2)
|
local dir = determine_dir(pos1, pos2)
|
||||||
local obj = node_to_entity(pos1, handover)
|
local obj = node_to_entity(pos1, handover, pos_2to1)
|
||||||
local self = obj:get_luaentity()
|
local self = obj:get_luaentity()
|
||||||
self.players = {}
|
self.players = {}
|
||||||
self.entities = {}
|
self.entities = {}
|
||||||
@ -547,7 +551,7 @@ local function move_node(pos, pos1, pos2, max_speed, handover, height)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function move_nodes(pos, lpos1, lpos2, handover)
|
local function move_nodes(pos, lpos1, lpos2, handover, pos_2to1)
|
||||||
local meta = M(pos)
|
local meta = M(pos)
|
||||||
local owner = meta:get_string("owner")
|
local owner = meta:get_string("owner")
|
||||||
local max_speed = meta:contains("max_speed") and meta:get_int("max_speed") or MAX_SPEED
|
local max_speed = meta:contains("max_speed") and meta:get_int("max_speed") or MAX_SPEED
|
||||||
@ -560,7 +564,7 @@ local function move_nodes(pos, lpos1, lpos2, handover)
|
|||||||
local pos2 = lpos2[idx]
|
local pos2 = lpos2[idx]
|
||||||
if not minetest.is_protected(pos1, owner) and not minetest.is_protected(pos2, owner) then
|
if not minetest.is_protected(pos1, owner) and not minetest.is_protected(pos2, owner) then
|
||||||
if is_simple_node(pos1) and is_valid_dest(pos2) then
|
if is_simple_node(pos1) and is_valid_dest(pos2) then
|
||||||
move_node(pos, pos1, pos2, max_speed, handover, height)
|
move_node(pos, pos1, pos2, max_speed, handover, height, pos_2to1)
|
||||||
else
|
else
|
||||||
if not is_simple_node(pos1) then
|
if not is_simple_node(pos1) then
|
||||||
meta:set_string("status", S("No valid node at the start position"))
|
meta:set_string("status", S("No valid node at the start position"))
|
||||||
@ -634,41 +638,37 @@ local function moveon_nodes(pos, lpos1, lpos2, handover)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
local function move_to_other_pos(pos)
|
local function move_to_other_pos(pos, pos_2to1)
|
||||||
local meta = M(pos)
|
local meta = M(pos)
|
||||||
local nvm = techage.get_nvm(pos)
|
local nvm = techage.get_nvm(pos)
|
||||||
|
|
||||||
if nvm.pos_2to1 then
|
if pos_2to1 then
|
||||||
local lpos1 = nvm.lpos1 or {}
|
local lpos1 = nvm.lpos1 or {}
|
||||||
local lpos2 = nvm.lpos2 or {}
|
local lpos2 = nvm.lpos2 or {}
|
||||||
nvm.pos_2to1 = false
|
|
||||||
local handover = meta:contains("handoverA") and meta:get_string("handoverA")
|
local handover = meta:contains("handoverA") and meta:get_string("handoverA")
|
||||||
return move_nodes(pos, lpos2, lpos1, handover)
|
return move_nodes(pos, lpos2, lpos1, handover, pos_2to1)
|
||||||
else
|
else
|
||||||
local lpos1 = nvm.lpos1 or {}
|
local lpos1 = nvm.lpos1 or {}
|
||||||
local lpos2 = nvm.lpos2 or {}
|
local lpos2 = nvm.lpos2 or {}
|
||||||
nvm.pos_2to1 = true
|
|
||||||
local handover = meta:contains("handoverB") and meta:get_string("handoverB")
|
local handover = meta:contains("handoverB") and meta:get_string("handoverB")
|
||||||
return move_nodes(pos, lpos1, lpos2, handover)
|
return move_nodes(pos, lpos1, lpos2, handover, pos_2to1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function takeover(pos)
|
local function takeover(pos, pos_2to1)
|
||||||
local meta = M(pos)
|
local meta = M(pos)
|
||||||
local nvm = techage.get_nvm(pos)
|
local nvm = techage.get_nvm(pos)
|
||||||
local mem = techage.get_mem(pos)
|
local mem = techage.get_mem(pos)
|
||||||
mem.entities_are_there = nil
|
mem.entities_are_there = nil
|
||||||
|
|
||||||
if nvm.pos_2to1 then
|
if pos_2to1 then
|
||||||
local lpos1 = nvm.lpos1 or {}
|
local lpos1 = nvm.lpos1 or {}
|
||||||
local lpos2 = nvm.lpos2 or {}
|
local lpos2 = nvm.lpos2 or {}
|
||||||
nvm.pos_2to1 = false
|
|
||||||
local handover = meta:contains("handoverA") and meta:get_string("handoverA")
|
local handover = meta:contains("handoverA") and meta:get_string("handoverA")
|
||||||
return moveon_nodes(pos, lpos2, lpos1, handover)
|
return moveon_nodes(pos, lpos2, lpos1, handover)
|
||||||
else
|
else
|
||||||
local lpos1 = nvm.lpos1 or {}
|
local lpos1 = nvm.lpos1 or {}
|
||||||
local lpos2 = nvm.lpos2 or {}
|
local lpos2 = nvm.lpos2 or {}
|
||||||
nvm.pos_2to1 = true
|
|
||||||
local handover = meta:contains("handoverB") and meta:get_string("handoverB")
|
local handover = meta:contains("handoverB") and meta:get_string("handoverB")
|
||||||
return moveon_nodes(pos, lpos1, lpos2, handover)
|
return moveon_nodes(pos, lpos1, lpos2, handover)
|
||||||
end
|
end
|
||||||
@ -733,15 +733,14 @@ minetest.register_node("techage:ta4_movecontroller", {
|
|||||||
elseif fields.moveAB then
|
elseif fields.moveAB then
|
||||||
meta:set_string("status", "")
|
meta:set_string("status", "")
|
||||||
nvm.pos_2to1 = false
|
nvm.pos_2to1 = false
|
||||||
if move_to_other_pos(pos) then
|
if move_to_other_pos(pos, false) then
|
||||||
meta:set_string("formspec", formspec(nvm, meta))
|
meta:set_string("formspec", formspec(nvm, meta))
|
||||||
local name = player:get_player_name()
|
local name = player:get_player_name()
|
||||||
MarkedNodes[name] = nil
|
MarkedNodes[name] = nil
|
||||||
end
|
end
|
||||||
elseif fields.moveBA then
|
elseif fields.moveBA then
|
||||||
meta:set_string("status", "")
|
meta:set_string("status", "")
|
||||||
nvm.pos_2to1 = true
|
if move_to_other_pos(pos, true) then
|
||||||
if move_to_other_pos(pos) then
|
|
||||||
meta:set_string("formspec", formspec(nvm, meta))
|
meta:set_string("formspec", formspec(nvm, meta))
|
||||||
local name = player:get_player_name()
|
local name = player:get_player_name()
|
||||||
MarkedNodes[name] = nil
|
MarkedNodes[name] = nil
|
||||||
@ -763,24 +762,18 @@ minetest.register_node("techage:ta4_movecontroller", {
|
|||||||
sounds = default.node_sound_wood_defaults(),
|
sounds = default.node_sound_wood_defaults(),
|
||||||
})
|
})
|
||||||
|
|
||||||
local INFO = [[Commands: 'a2b', 'b2a', 'move']]
|
local INFO = [[Commands: 'a2b', 'b2a']]
|
||||||
|
|
||||||
techage.register_node({"techage:ta4_movecontroller"}, {
|
techage.register_node({"techage:ta4_movecontroller"}, {
|
||||||
on_recv_message = function(pos, src, topic, payload)
|
on_recv_message = function(pos, src, topic, payload)
|
||||||
if topic == "info" then
|
if topic == "info" then
|
||||||
return INFO
|
return INFO
|
||||||
elseif topic == "a2b" then
|
elseif topic == "a2b" then
|
||||||
local nvm = techage.get_nvm(pos)
|
return move_to_other_pos(pos, false)
|
||||||
nvm.pos_2to1 = false
|
|
||||||
return move_to_other_pos(pos)
|
|
||||||
elseif topic == "b2a" then
|
elseif topic == "b2a" then
|
||||||
local nvm = techage.get_nvm(pos)
|
return move_to_other_pos(pos, true)
|
||||||
nvm.pos_2to1 = true
|
|
||||||
return move_to_other_pos(pos)
|
|
||||||
elseif topic == "move" then
|
|
||||||
return move_to_other_pos(pos)
|
|
||||||
elseif topic == "handover" then
|
elseif topic == "handover" then
|
||||||
return takeover(pos)
|
return takeover(pos, payload)
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end,
|
end,
|
||||||
|
@ -541,7 +541,6 @@ Der Move Controller unterstützt folgende techage Kommandos:
|
|||||||
|
|
||||||
- `a2b` Bewege Block von A nach B
|
- `a2b` Bewege Block von A nach B
|
||||||
- `b2a` Bewege Block von B nach A
|
- `b2a` Bewege Block von B nach A
|
||||||
- `move` Bewege Block auf die andere Seite
|
|
||||||
|
|
||||||
[ta4_movecontroller|image]
|
[ta4_movecontroller|image]
|
||||||
|
|
||||||
|
@ -535,7 +535,6 @@ The Move Controller supports the following techage commands:
|
|||||||
|
|
||||||
- `a2b` Move block from A to B.
|
- `a2b` Move block from A to B.
|
||||||
- `b2a` Move block from B to A.
|
- `b2a` Move block from B to A.
|
||||||
- `move` Move block to the other side
|
|
||||||
|
|
||||||
[ta4_movecontroller|image]
|
[ta4_movecontroller|image]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user