Compare commits
71 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
1923b6acde | ||
|
d6942aa43b | ||
|
31f37b0665 | ||
|
80c611d640 | ||
|
720dda3178 | ||
|
fc81d35ccd | ||
|
ae27cb8f4f | ||
|
78c81f5da6 | ||
|
e66f056590 | ||
|
26a7dbb78f | ||
|
34d2c56f6d | ||
|
7ac1756f09 | ||
|
2c426f53f6 | ||
|
5b1335dbea | ||
|
5e479b9ac5 | ||
|
4832eb0470 | ||
|
2a2cfa4113 | ||
|
c81ed3725d | ||
|
7a746e5660 | ||
|
f1cf8c3fb0 | ||
|
32188e3eba | ||
|
e513314ae8 | ||
|
92f31e08cc | ||
|
8dfd5aade1 | ||
|
a62ef6c183 | ||
|
2b91f0d013 | ||
|
254ae5a4d5 | ||
|
ed5b525dd8 | ||
|
06c2c9881a | ||
|
617ab9b30e | ||
|
4ce65f20e2 | ||
|
20e6a3b379 | ||
|
5502e5f052 | ||
|
1f33988ac5 | ||
|
06e42034f3 | ||
|
2d5e149ba9 | ||
|
0e3d242ec6 | ||
|
0ef5c3eee7 | ||
|
08991e877c | ||
|
1156940f99 | ||
|
ec7410b4e7 | ||
|
6ba25ff14c | ||
|
98cd448992 | ||
|
2248c5aba6 | ||
|
46ccd93fc9 | ||
|
454aa6ccc9 | ||
|
89c0c1f5a1 | ||
|
1ad835bd53 | ||
|
2e745748eb | ||
|
dde5e29a45 | ||
|
7a297813ca | ||
|
06e4527ad9 | ||
|
0ecd7a357d | ||
|
2b41a41052 | ||
|
e39cfeae84 | ||
|
ba85e514bf | ||
|
a84365d3e9 | ||
|
b8222cdebe | ||
|
b981444b7c | ||
|
569e4bfa78 | ||
|
3a896b4a90 | ||
|
992616a3f0 | ||
|
d88cfbf9d8 | ||
|
e4d2154bac | ||
|
8610d1e88f | ||
|
4a10d2f68c | ||
|
bac5e5ebf1 | ||
|
7b391dd8f3 | ||
|
d7fab3bd96 | ||
|
b05c312968 | ||
|
0d8afaff76 |
32
API.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# API for X-Decor-libre
|
||||||
|
|
||||||
|
X-Decor-libre is mostly self-contained but it allows for limited extension with
|
||||||
|
a simple API. Not that extensibility is not the main goal of this mod.
|
||||||
|
|
||||||
|
The function documentation can be found in the respective source code files
|
||||||
|
under the header "--[[ API FUNCTIONS ]]".
|
||||||
|
|
||||||
|
These are the features:
|
||||||
|
|
||||||
|
## Add custom tool enchantments
|
||||||
|
|
||||||
|
You can register tools to be able to be enchanted at the enchanting table.
|
||||||
|
|
||||||
|
See `src/enchanting.lua` for details.
|
||||||
|
|
||||||
|
## Add custom hammers
|
||||||
|
|
||||||
|
You can add a custom hammer for repairing tools at the workbench,
|
||||||
|
using custom stats.
|
||||||
|
|
||||||
|
See `src/workbench.lua` for details.
|
||||||
|
|
||||||
|
## EXPERIMENTAL: Add cut nodes
|
||||||
|
|
||||||
|
You can register "cut" node variants of an existing node which can
|
||||||
|
be created at the workbench.
|
||||||
|
This will add thin stairs, half stairs, panels, microcubes, etc.
|
||||||
|
|
||||||
|
THIS FEATURE IS EXPERIMENTAL!
|
||||||
|
|
||||||
|
See `src/workbench.lua` for details.
|
@ -29,9 +29,9 @@ You need a chessboard to play. Craft yourself a chessboard like this:
|
|||||||
BWB
|
BWB
|
||||||
sss
|
sss
|
||||||
|
|
||||||
B = Black Dye
|
* B = Black Dye
|
||||||
W = White Dye
|
* W = White Dye
|
||||||
s = Wooden Slab (from apple tree)
|
* s = Wooden Slab (from apple tree)
|
||||||
|
|
||||||
Place the chessboard and examine it. You will see a close-up of the chessboard.
|
Place the chessboard and examine it. You will see a close-up of the chessboard.
|
||||||
|
|
||||||
@ -64,8 +64,7 @@ It is written in a figurine long algebraic notation (see appendix).
|
|||||||
|
|
||||||
The two boxes below the list of moves is where all the captured pieces
|
The two boxes below the list of moves is where all the captured pieces
|
||||||
go. This has no gameplay significance but it may serve as a visual
|
go. This has no gameplay significance but it may serve as a visual
|
||||||
aid to see how badly hurt the player's “armies” are. This section
|
aid to see how badly hurt the player's “armies” are.
|
||||||
may change
|
|
||||||
|
|
||||||
The top right corner is used for starting a new game. Press
|
The top right corner is used for starting a new game. Press
|
||||||
“New Game” to start a new game. This ends the current game.
|
“New Game” to start a new game. This ends the current game.
|
||||||
@ -121,7 +120,7 @@ a capturing move are identical. Only for the pawn it is different
|
|||||||
|
|
||||||
If the square of the king is attacked, he and the player playing him
|
If the square of the king is attacked, he and the player playing him
|
||||||
is considered to be in “check”.
|
is considered to be in “check”.
|
||||||
If a player is in check, any move which would put or leave the own
|
While a player is in check, any move which would their own
|
||||||
king under attack is not allowed.
|
king under attack is not allowed.
|
||||||
|
|
||||||
#### How to actually move
|
#### How to actually move
|
||||||
@ -149,9 +148,6 @@ The rook looks like a tower and can move to any of square that lies
|
|||||||
in a straight horizontal or vertical line from it.
|
in a straight horizontal or vertical line from it.
|
||||||
It cannot move beyond pieces that are in the way.
|
It cannot move beyond pieces that are in the way.
|
||||||
|
|
||||||
The rook can move on a square occupied by an opponent, which
|
|
||||||
w
|
|
||||||
|
|
||||||
The rook may be involved in Castling, see “King” below.
|
The rook may be involved in Castling, see “King” below.
|
||||||
|
|
||||||
#### Bishop
|
#### Bishop
|
||||||
@ -218,7 +214,7 @@ If all the conditions are met, here’s how you castle:
|
|||||||
Place the king two squares towards the rook you want to castle with.
|
Place the king two squares towards the rook you want to castle with.
|
||||||
This square is where the king will end up. The rook will then
|
This square is where the king will end up. The rook will then
|
||||||
automatically move towards the king and “jump” to the square
|
automatically move towards the king and “jump” to the square
|
||||||
behind the king, from the rooks viewpoint.
|
behind the king, from the rook’s viewpoint.
|
||||||
|
|
||||||
**Remember**: You *must* move the king (not the rook) if you want
|
**Remember**: You *must* move the king (not the rook) if you want
|
||||||
to castle. If you move the rook instead, this is considered
|
to castle. If you move the rook instead, this is considered
|
||||||
@ -234,10 +230,12 @@ pieces have started).
|
|||||||
The pawn’s basic moves are:
|
The pawn’s basic moves are:
|
||||||
|
|
||||||
1. Single step: The pawn moves one step vertically towards the
|
1. Single step: The pawn moves one step vertically towards the
|
||||||
opponent’s side. It is not possible to walk backwards.
|
opponent’s side.
|
||||||
2. Double step: Like a single step, but it moves two squares instead.
|
2. Double step: Like a single step, but it moves two squares instead.
|
||||||
This is only possible from the pawn’s start position.
|
This is only possible from the pawn’s start position.
|
||||||
|
|
||||||
|
A pawn can never move backwards.
|
||||||
|
|
||||||
In both cases, the destination square must be empty as well as any crossed square.
|
In both cases, the destination square must be empty as well as any crossed square.
|
||||||
The pawn cannot capture by a single or double step, however.
|
The pawn cannot capture by a single or double step, however.
|
||||||
|
|
||||||
@ -289,7 +287,7 @@ is not taken, it will be gone from that point on.
|
|||||||
|
|
||||||
##### Promotion
|
##### Promotion
|
||||||
|
|
||||||
When a pawn reaches the other end of the chessboard (from its viewpoint)
|
When a pawn reaches the other end of the chessboard (from its viewpoint),
|
||||||
it will be promoted. A promotion is considered to be part of the move.
|
it will be promoted. A promotion is considered to be part of the move.
|
||||||
|
|
||||||
When promotion happens, the boxes where normally the captured pieces go
|
When promotion happens, the boxes where normally the captured pieces go
|
||||||
@ -300,7 +298,7 @@ Just click the corresponding button. These buttons only work for the
|
|||||||
current player. Promotion is mandatory and no other moves are possible
|
current player. Promotion is mandatory and no other moves are possible
|
||||||
until it is completed.
|
until it is completed.
|
||||||
|
|
||||||
Once a piece was selected, the pawn will be replaced replaced, which
|
Once a piece was selected, the pawn will be replaced, which
|
||||||
immediately activates its powers. This ends the move.
|
immediately activates its powers. This ends the move.
|
||||||
|
|
||||||
### The end of the game
|
### The end of the game
|
||||||
@ -438,8 +436,10 @@ dig the chessboard.
|
|||||||
|
|
||||||
### The Chess Notation
|
### The Chess Notation
|
||||||
|
|
||||||
The list of moves is in a special notation called “algebraic notation”. There are many
|
The chessboard interface shows a list of all moves on the right side.
|
||||||
variants of it, so this section explains what it means in X-Decor-libre.
|
|
||||||
|
The list of moves is written in a special notation called “algebraic notation”.
|
||||||
|
There are many variants of it, so this section explains what it means in X-Decor-libre.
|
||||||
|
|
||||||
This mod uses a longform figurine algebraic notation. “figurine” means that
|
This mod uses a longform figurine algebraic notation. “figurine” means that
|
||||||
icons are used for the chess pieces. “longform” means the start
|
icons are used for the chess pieces. “longform” means the start
|
||||||
@ -493,7 +493,7 @@ When a player castles, it is notated the following way:
|
|||||||
|
|
||||||
#### Game completion
|
#### Game completion
|
||||||
|
|
||||||
If the game completed, the end of the game showing the result is listed in a final separate line as:
|
If the game came to an end, the game result is written in a final separate line as:
|
||||||
|
|
||||||
* “1–0” if White won
|
* “1–0” if White won
|
||||||
* “0–1” if Black won
|
* “0–1” if Black won
|
||||||
@ -501,11 +501,11 @@ If the game completed, the end of the game showing the result is listed in a fin
|
|||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
1. d2—d4 e7—e6
|
1. d2–d4 e7–e6
|
||||||
2. ♔e1–d2 ♛d8–h4
|
2. ♔e1–d2 ♛d8–h4
|
||||||
3. d4–d5 e6×d5
|
3. d4–d5 e6×d5
|
||||||
...
|
...
|
||||||
8. d8×d8♖ ♞b8-c6
|
8. d8×d8♖ ♞b8–c6
|
||||||
9. e2–e4 d4×e3 e.p.
|
9. e2–e4 d4×e3 e.p.
|
||||||
|
|
||||||
Explanation of the moves:
|
Explanation of the moves:
|
||||||
@ -513,7 +513,7 @@ Explanation of the moves:
|
|||||||
* 1.: First fullmove: White moves pawn from d2 to d4, Black moves pawn from e7 to e6
|
* 1.: First fullmove: White moves pawn from d2 to d4, Black moves pawn from e7 to e6
|
||||||
* 2.: Second fullmove: White moves king from e1 to d2, Black moves queen from d8 to h4
|
* 2.: Second fullmove: White moves king from e1 to d2, Black moves queen from d8 to h4
|
||||||
* 3.: Third fullmove: White moves pawn from d4 to d5, Black moves pawn from d6 to d5 and captures
|
* 3.: Third fullmove: White moves pawn from d4 to d5, Black moves pawn from d6 to d5 and captures
|
||||||
* 8.: Eight fullmove: White moves pawn from d7 to d8, captures a piece and promotes it to rook, Black moves knight from b8 to c6
|
* 8.: Eighth fullmove: White moves pawn from d7 to d8, captures a piece and promotes it to rook, Black moves knight from b8 to c6
|
||||||
* 9.: Ninth fullmove: White moves pawn from e2 to e4, black moves pawn from d4 to e3 and captures en passant
|
* 9.: Ninth fullmove: White moves pawn from e2 to e4, black moves pawn from d4 to e3 and captures en passant
|
||||||
|
|
||||||
#### Other symbols
|
#### Other symbols
|
||||||
|
22
README.md
@ -1,14 +1,23 @@
|
|||||||
## X-Decor-libre [`xdecor`] ##
|
## X-Decor-libre [`xdecor`] ##
|
||||||
|
|
||||||
[![ContentDB](https://content.minetest.net/packages/Wuzzy/xdecor/shields/downloads/)](https://content.minetest.net/packages/Wuzzy/xdecor/)
|
[![ContentDB](https://content.luanti.org/packages/Wuzzy/xdecor/shields/downloads/)](https://content.luanti.org/packages/Wuzzy/xdecor/)
|
||||||
|
|
||||||
X-Decor-libre is a libre Minetest mod which adds various decorative blocks
|
X-Decor-libre is a libre Luanti mod which adds various decorative blocks
|
||||||
as well as simple gimmicks.
|
as well as simple gimmicks.
|
||||||
|
|
||||||
This is a libre version (free software, free media) of the X-Decor mod for Minetest.
|
This is a libre version (free software, free media) of the X-Decor mod for Luanti.
|
||||||
It is the same as X-Decor, except with all the non-free files replaced and with
|
It is the same as X-Decor, except with all the non-free files replaced and with
|
||||||
bugfixes. There are no new features.
|
bugfixes. There are no new features.
|
||||||
|
|
||||||
|
## New blocks
|
||||||
|
|
||||||
|
This mod adds many decoration blocks: Flower pot, weathervane, radio, speaker,
|
||||||
|
wooden tile, new bricks, lamps, candles, new doors, packed ice, and more.
|
||||||
|
|
||||||
|
This mod also adds 7 new block shapes for many Minetest Game blocks. They can
|
||||||
|
be created by using the workbench. This includes panels, mini blocks and flat
|
||||||
|
stairs.
|
||||||
|
|
||||||
## Special nodes
|
## Special nodes
|
||||||
|
|
||||||
Most blocks in this mod are purely decorative, but there are also many special
|
Most blocks in this mod are purely decorative, but there are also many special
|
||||||
@ -34,11 +43,13 @@ blocks with special features:
|
|||||||
* Pressure Plate: Step on it to activate doors next to it
|
* Pressure Plate: Step on it to activate doors next to it
|
||||||
* Chessboard: Play Chess against a player or the computer (see `CHESS_README.md`)
|
* Chessboard: Play Chess against a player or the computer (see `CHESS_README.md`)
|
||||||
|
|
||||||
The radio and speaker are purely decorative and have no special functionality.
|
## For developers
|
||||||
|
|
||||||
|
X-Decor-libre can be extended in a limited fashion. See `API.md` for details.
|
||||||
|
|
||||||
### X-Decor-libre vs X-Decor
|
### X-Decor-libre vs X-Decor
|
||||||
|
|
||||||
X-Decor is a popular mod in Minetest but it is (as the time of writing this text)
|
X-Decor is a popular mod in Luanti but it is (as the time of writing this text)
|
||||||
non-free software, there are various files under proprietary licenses.
|
non-free software, there are various files under proprietary licenses.
|
||||||
|
|
||||||
The purpose of this repository is to provide the community a fully-free fork of
|
The purpose of this repository is to provide the community a fully-free fork of
|
||||||
@ -100,7 +111,6 @@ Maintenance updates:
|
|||||||
* Storage blocks now drop their inventory when exploded
|
* Storage blocks now drop their inventory when exploded
|
||||||
* Made several strings translatable
|
* Made several strings translatable
|
||||||
* Translation updates
|
* Translation updates
|
||||||
* Add support for playerphysics mod
|
|
||||||
* Add description to every setting
|
* Add description to every setting
|
||||||
* Add tooltip extensions for some interactive items (uses `tt` mod)
|
* Add tooltip extensions for some interactive items (uses `tt` mod)
|
||||||
* Add crafting guide support for `unified_inventory` mod (honey)
|
* Add crafting guide support for `unified_inventory` mod (honey)
|
||||||
|
@ -1,50 +1,76 @@
|
|||||||
local mod_playerphysics = minetest.get_modpath("playerphysics") ~= nil
|
|
||||||
local mod_player_api = minetest.get_modpath("player_api") ~= nil
|
local mod_player_api = minetest.get_modpath("player_api") ~= nil
|
||||||
|
|
||||||
local function top_face(pointed_thing)
|
local sitting = {}
|
||||||
if not pointed_thing then return end
|
local seats_occupied = {}
|
||||||
return pointed_thing.above.y > pointed_thing.under.y
|
|
||||||
|
local function bottom_face(pointed_thing)
|
||||||
|
if not pointed_thing then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
return pointed_thing.above.y < pointed_thing.under.y
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function stand_up(player_name)
|
||||||
|
if not mod_player_api then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local player = minetest.get_player_by_name(player_name)
|
||||||
|
if not player then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
player_api.player_attached[player_name] = false
|
||||||
|
|
||||||
|
local old_anim = player_api.get_animation(player)
|
||||||
|
if old_anim and old_anim.animation == "sit" then
|
||||||
|
player_api.set_animation(player, "stand")
|
||||||
|
end
|
||||||
|
|
||||||
|
local hash = minetest.hash_node_position(sitting[player_name])
|
||||||
|
seats_occupied[hash] = nil
|
||||||
|
sitting[player_name] = nil
|
||||||
|
|
||||||
|
minetest.log("action", "[xdecor] "..player_name.." stands up at "..minetest.pos_to_string(player:get_pos(), 0))
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[ Used when player interacts with "sittable" node to sit down
|
||||||
|
or stand up when interacting with that node again. Should
|
||||||
|
be used in `on_rightclick` handler
|
||||||
|
* `pos`: Position where to sit down player (MUST only use integers for coordinates!)
|
||||||
|
* `node`: Node table of node to sit on
|
||||||
|
* `clicker`: Player who interacted with node (from `on_rightclick`)
|
||||||
|
* `pointed_thing`: From `on_rightclick` ]]
|
||||||
function xdecor.sit(pos, node, clicker, pointed_thing)
|
function xdecor.sit(pos, node, clicker, pointed_thing)
|
||||||
if not mod_player_api then return end
|
if not mod_player_api then
|
||||||
if not top_face(pointed_thing) then return end
|
return
|
||||||
|
end
|
||||||
|
-- Can't sit down if bottom face was pointed at
|
||||||
|
if bottom_face(pointed_thing) then
|
||||||
|
return
|
||||||
|
end
|
||||||
local player_name = clicker:get_player_name()
|
local player_name = clicker:get_player_name()
|
||||||
local objs = minetest.get_objects_inside_radius(pos, 0.1)
|
local objs = minetest.get_objects_inside_radius(pos, 0.1)
|
||||||
local vel = clicker:get_velocity()
|
local vel = clicker:get_velocity()
|
||||||
local ctrl = clicker:get_player_control()
|
local ctrl = clicker:get_player_control()
|
||||||
|
|
||||||
for _, obj in pairs(objs) do
|
-- Stand up if sitting
|
||||||
if obj:is_player() and obj:get_player_name() ~= player_name then
|
if sitting[player_name] then
|
||||||
return
|
stand_up(player_name)
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if player_api.player_attached[player_name] then
|
-- Sit down if not sitting and not attached
|
||||||
clicker:set_pos(pos)
|
elseif not sitting[player_name] and not player_api.player_attached[player_name] and node.param2 <= 3 and
|
||||||
clicker:set_eye_offset(vector.new(), vector.new())
|
|
||||||
if mod_playerphysics then
|
|
||||||
playerphysics.remove_physics_factor(clicker, "speed", "xdecor:sit_speed")
|
|
||||||
playerphysics.remove_physics_factor(clicker, "jump", "xdecor:sit_jump")
|
|
||||||
else
|
|
||||||
clicker:set_physics_override({speed = 1, jump = 1})
|
|
||||||
end
|
|
||||||
player_api.player_attached[player_name] = false
|
|
||||||
player_api.set_animation(clicker, "stand", 30)
|
|
||||||
|
|
||||||
elseif not player_api.player_attached[player_name] and node.param2 <= 3 and
|
|
||||||
not ctrl.sneak and vector.equals(vel, vector.new()) then
|
not ctrl.sneak and vector.equals(vel, vector.new()) then
|
||||||
|
|
||||||
clicker:set_eye_offset({x = 0, y = -7, z = 2}, vector.new())
|
-- Can't sit down on note already occupied by player
|
||||||
if mod_playerphysics then
|
local hash = minetest.hash_node_position(pos)
|
||||||
playerphysics.add_physics_factor(clicker, "speed", "xdecor:sit_speed", 0)
|
if seats_occupied[hash] then
|
||||||
playerphysics.add_physics_factor(clicker, "jump", "xdecor:sit_jump", 0)
|
return
|
||||||
else
|
|
||||||
clicker:set_physics_override({speed = 0, jump = 0})
|
|
||||||
end
|
end
|
||||||
clicker:set_pos(pos)
|
|
||||||
player_api.player_attached[player_name] = true
|
player_api.player_attached[player_name] = true
|
||||||
player_api.set_animation(clicker, "sit", 30)
|
player_api.set_animation(clicker, "sit")
|
||||||
|
sitting[player_name] = table.copy(pos)
|
||||||
|
seats_occupied[hash] = player_name
|
||||||
|
clicker:set_pos(pos)
|
||||||
|
|
||||||
if node.param2 == 0 then
|
if node.param2 == 0 then
|
||||||
clicker:set_look_horizontal(0)
|
clicker:set_look_horizontal(0)
|
||||||
@ -55,19 +81,74 @@ function xdecor.sit(pos, node, clicker, pointed_thing)
|
|||||||
elseif node.param2 == 3 then
|
elseif node.param2 == 3 then
|
||||||
clicker:set_look_horizontal(math.pi/2)
|
clicker:set_look_horizontal(math.pi/2)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
minetest.log("action", "[xdecor] "..player_name.." sits down at "..minetest.pos_to_string(pos, 0))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Called when `digger` (a player object) wants to
|
||||||
|
-- dig a node at pos. Returns true if it's allowed,
|
||||||
|
-- false otherwise. This checks if the node at pos
|
||||||
|
-- is an occupied sittable node.
|
||||||
|
-- Can be used for the `can_dig` node function.
|
||||||
function xdecor.sit_dig(pos, digger)
|
function xdecor.sit_dig(pos, digger)
|
||||||
if not mod_player_api then
|
if not mod_player_api then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
for _, player in pairs(minetest.get_objects_inside_radius(pos, 0.1)) do
|
local hash = minetest.hash_node_position(pos)
|
||||||
if player:is_player() and
|
if seats_occupied[hash] then
|
||||||
player_api.player_attached[player:get_player_name()] then
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- To be called when a seat (sittable node) got destroyed
|
||||||
|
-- to clean up state. Precisely, this should be used
|
||||||
|
-- as the `after_destruct` handler.
|
||||||
|
function xdecor.sit_destruct(pos)
|
||||||
|
local hash = minetest.hash_node_position(pos)
|
||||||
|
local occupier = seats_occupied[hash]
|
||||||
|
if occupier then
|
||||||
|
stand_up(occupier)
|
||||||
|
seats_occupied[hash] = nil
|
||||||
|
sitting[occupier] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Automatically cause players to stand up if they pressed a control
|
||||||
|
-- or moved away from the seat
|
||||||
|
minetest.register_globalstep(function(dtime)
|
||||||
|
local to_stand_up = {}
|
||||||
|
for player_name, sitting_pos in pairs(sitting) do
|
||||||
|
local player = minetest.get_player_by_name(player_name)
|
||||||
|
if player then
|
||||||
|
local ctrl = player:get_player_control()
|
||||||
|
if ctrl.up or ctrl.down or ctrl.left or ctrl.right or ctrl.sneak or ctrl.jump then
|
||||||
|
table.insert(to_stand_up, player_name)
|
||||||
|
elseif vector.distance(player:get_pos(), sitting_pos) > 0.55 then
|
||||||
|
table.insert(to_stand_up, player_name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for s=1, #to_stand_up do
|
||||||
|
stand_up(to_stand_up[s])
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Force player to stand on death (to the seat is released)
|
||||||
|
minetest.register_on_dieplayer(function(player)
|
||||||
|
local player_name = player:get_player_name()
|
||||||
|
if sitting[player_name] then
|
||||||
|
stand_up(player_name)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
minetest.register_on_leaveplayer(function(player)
|
||||||
|
local player_name = player:get_player_name()
|
||||||
|
if sitting[player_name] then
|
||||||
|
local hash = minetest.hash_node_position(sitting[player_name])
|
||||||
|
seats_occupied[hash] = nil
|
||||||
|
sitting[player_name] = nil
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
16
init.lua
@ -12,6 +12,7 @@ dofile(modpath .. "/handlers/registration.lua")
|
|||||||
dofile(modpath .. "/src/nodes.lua")
|
dofile(modpath .. "/src/nodes.lua")
|
||||||
dofile(modpath .. "/src/recipes.lua")
|
dofile(modpath .. "/src/recipes.lua")
|
||||||
|
|
||||||
|
-- Load modules that can be enabled and disabled by settings
|
||||||
local subpart = {
|
local subpart = {
|
||||||
"chess",
|
"chess",
|
||||||
"cooking",
|
"cooking",
|
||||||
@ -21,14 +22,23 @@ local subpart = {
|
|||||||
"mailbox",
|
"mailbox",
|
||||||
"mechanisms",
|
"mechanisms",
|
||||||
"rope",
|
"rope",
|
||||||
|
-- Workbench MUST be loaded after all other subparts that register nodes
|
||||||
|
-- last for the default 'cut node' registrations to work
|
||||||
"workbench",
|
"workbench",
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, name in ipairs(subpart) do
|
for _, name in ipairs(subpart) do
|
||||||
local enable = minetest.settings:get_bool("enable_xdecor_" .. name)
|
local enable = minetest.settings:get_bool("enable_xdecor_" .. name, true)
|
||||||
if enable or enable == nil then
|
if enable then
|
||||||
dofile(modpath .. "/src/" .. name .. ".lua")
|
dofile(modpath .. "/src/" .. name .. ".lua")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--print(string.format("[xdecor] loaded in %.2f ms", (os.clock()-t)*1000))
|
-- Special case: enchanted tools. This code is split from enchanting to
|
||||||
|
-- deal with loading order.
|
||||||
|
-- Enchanted tools registered last because they depend on previous
|
||||||
|
-- subparts
|
||||||
|
local enable_enchanting = minetest.settings:get_bool("enable_xdecor_enchanting", true)
|
||||||
|
if enable_enchanting then
|
||||||
|
dofile(modpath .. "/src/enchanted_tools.lua")
|
||||||
|
end
|
||||||
|
@ -1,15 +1,41 @@
|
|||||||
# textdomain: xdecor
|
# textdomain: xdecor
|
||||||
|
A libre decoration mod meant to be simple and well-featured.=
|
||||||
|
@1 Stair=
|
||||||
|
Inner @1 Stair=
|
||||||
|
Outer @1 Stair=
|
||||||
|
@1 Slab=
|
||||||
Weak Computer=
|
Weak Computer=
|
||||||
Weak Computer 1=
|
Weak Computer 1=
|
||||||
Weak Computer 2=
|
Weak Computer 2=
|
||||||
Chess=
|
Chess=
|
||||||
Chess Debug=
|
Chess Debug=
|
||||||
|
Select a game mode=
|
||||||
|
Select a mode:=
|
||||||
|
Singleplayer=
|
||||||
|
Multiplayer=
|
||||||
|
Bot vs Bot=
|
||||||
check=
|
check=
|
||||||
checkmate=
|
checkmate=
|
||||||
resigned=
|
resigned=
|
||||||
winner=
|
winner=
|
||||||
loser=
|
loser=
|
||||||
draw=
|
draw=
|
||||||
|
PROMOTION@nFOR BLACK!=
|
||||||
|
Promote pawn to:=
|
||||||
|
PROMOTION@nFOR WHITE!=
|
||||||
|
DRAW CLAIM@nBY WHITE!=
|
||||||
|
DRAW CLAIM@nBY BLACK!=
|
||||||
|
The player has invoked the 50-move rule for the next move. The next move might draw the game.=
|
||||||
|
The player has invoked the threefold-repetition rule for the next move. The next move might draw the game.=
|
||||||
|
New game=
|
||||||
|
Resign=
|
||||||
|
Select a color:=
|
||||||
|
White=
|
||||||
|
Black=
|
||||||
|
Invoke the 50-move rule for your next move=
|
||||||
|
Invoke the 50-move rule and draw the game=
|
||||||
|
Invoke the threefold repetition rule and draw the game=
|
||||||
|
Invoke the threefold repetition rule for your next move=
|
||||||
You have checkmated @1. You win!=
|
You have checkmated @1. You win!=
|
||||||
You were checkmated by @1. You lose!=
|
You were checkmated by @1. You lose!=
|
||||||
The game ended up in a stalemate! It's a draw!=
|
The game ended up in a stalemate! It's a draw!=
|
||||||
@ -54,27 +80,6 @@ White Queen=
|
|||||||
Black Queen=
|
Black Queen=
|
||||||
White King=
|
White King=
|
||||||
Black King=
|
Black King=
|
||||||
Select a game mode=
|
|
||||||
Select a mode:=
|
|
||||||
Singleplayer=
|
|
||||||
Multiplayer=
|
|
||||||
Bot vs Bot=
|
|
||||||
PROMOTION@nFOR BLACK!=
|
|
||||||
Promote pawn to:=
|
|
||||||
PROMOTION@nFOR WHITE!=
|
|
||||||
DRAW CLAIM@nBY WHITE!=
|
|
||||||
DRAW CLAIM@nBY BLACK!=
|
|
||||||
The player has invoked the 50-move rule for the next move. The next move might draw the game.=
|
|
||||||
The player has invoked the threefold-repetition rule for the next move. The next move might draw the game.=
|
|
||||||
New game=
|
|
||||||
Resign=
|
|
||||||
Select a color:=
|
|
||||||
White=
|
|
||||||
Black=
|
|
||||||
Invoke the 50-move rule for your next move=
|
|
||||||
Invoke the 50-move rule and draw the game=
|
|
||||||
Invoke the threefold repetition rule and draw the game=
|
|
||||||
Invoke the threefold repetition rule for your next move=
|
|
||||||
Light a fire below to heat it up=
|
Light a fire below to heat it up=
|
||||||
Use a bowl to eat the soup=
|
Use a bowl to eat the soup=
|
||||||
Drop foods inside to make a soup=
|
Drop foods inside to make a soup=
|
||||||
@ -100,40 +105,33 @@ Bowl of soup=
|
|||||||
Efficiency=
|
Efficiency=
|
||||||
Durability=
|
Durability=
|
||||||
Sharpness=
|
Sharpness=
|
||||||
|
@1 (+@2%)=
|
||||||
|
Your weapon inflicts more damage=
|
||||||
|
Your tool lasts longer=
|
||||||
|
Your tool digs faster=
|
||||||
Enchantment Table=
|
Enchantment Table=
|
||||||
Enchant your tools with mese crystals=
|
Enchant your tools with mese crystals=
|
||||||
Enchanted @1 @2@n@3=
|
Enchanted @1@n@2=
|
||||||
Enchanted @1 @2=
|
Enchanted @1=
|
||||||
Steel=
|
|
||||||
Bronze=
|
|
||||||
Mese=
|
|
||||||
Diamond=
|
|
||||||
Axe=
|
|
||||||
Pickaxe=
|
|
||||||
Shovel=
|
|
||||||
Sword=
|
|
||||||
Your weapon inflicts more damages=
|
|
||||||
Your tool last longer=
|
|
||||||
Your tool digs faster=
|
|
||||||
Artificial Hive=
|
|
||||||
Bees live here and produce honey=
|
|
||||||
Honey=
|
|
||||||
Made by bees=
|
|
||||||
The bees are busy making honey.=
|
The bees are busy making honey.=
|
||||||
The bees are looking for flowers.=
|
The bees are looking for flowers.=
|
||||||
The bees want to pollinate more flowers.=
|
The bees want to pollinate more flowers.=
|
||||||
The bees are idle.=
|
The bees are idle.=
|
||||||
The bees are resting.=
|
The bees are resting.=
|
||||||
|
Artificial Hive=
|
||||||
|
Bees live here and produce honey=
|
||||||
|
Honey=
|
||||||
|
Made by bees=
|
||||||
@1 (owned by @2)=
|
@1 (owned by @2)=
|
||||||
Item Frame=
|
Item Frame=
|
||||||
For presenting a single item=
|
For presenting a single item=
|
||||||
@1's Mailbox=
|
|
||||||
The mailbox is full.=
|
|
||||||
Mailbox=
|
|
||||||
Lets other players give you things=
|
|
||||||
× @1=
|
× @1=
|
||||||
|
Mailbox=
|
||||||
Last donators=
|
Last donators=
|
||||||
Send your goods to@n@1=
|
Send your goods to@n@1=
|
||||||
|
@1's Mailbox=
|
||||||
|
The mailbox is full.=
|
||||||
|
Lets other players give you things=
|
||||||
Opens doors when stepped on=
|
Opens doors when stepped on=
|
||||||
Wooden Pressure Plate=
|
Wooden Pressure Plate=
|
||||||
Stone Pressure Plate=
|
Stone Pressure Plate=
|
||||||
@ -196,10 +194,6 @@ Television=
|
|||||||
Wood Framed Glass=
|
Wood Framed Glass=
|
||||||
Radio=
|
Radio=
|
||||||
Speaker=
|
Speaker=
|
||||||
@1 Stair=
|
|
||||||
Inner @1 Stair=
|
|
||||||
Outer @1 Stair=
|
|
||||||
@1 Slab=
|
|
||||||
Rope=
|
Rope=
|
||||||
Nanoslab=
|
Nanoslab=
|
||||||
Micropanel=
|
Micropanel=
|
||||||
@ -211,13 +205,13 @@ Slab=
|
|||||||
Double Panel=
|
Double Panel=
|
||||||
Half-Stair=
|
Half-Stair=
|
||||||
Stair=
|
Stair=
|
||||||
Work Bench=
|
|
||||||
For cutting blocks, repairing tools with a hammer, crafting and storing items=
|
|
||||||
@1 @2=
|
|
||||||
Hammer=
|
|
||||||
Repairs tools at the work bench=
|
|
||||||
Cut=
|
Cut=
|
||||||
Repair=
|
Repair=
|
||||||
Crafting=
|
Crafting=
|
||||||
Storage=
|
Storage=
|
||||||
Back=
|
Back=
|
||||||
|
Work Bench=
|
||||||
|
For cutting blocks, repairing tools with a hammer, crafting and storing items=
|
||||||
|
@1 @2=
|
||||||
|
Repairs tools at the work bench=
|
||||||
|
Hammer=
|
||||||
|
@ -1,15 +1,41 @@
|
|||||||
# textdomain: xdecor
|
# textdomain: xdecor
|
||||||
|
A libre decoration mod meant to be simple and well-featured.=Eine freie simple Dekorationsmod mit netten Features.
|
||||||
|
@1 Stair=@1treppe
|
||||||
|
Inner @1 Stair=Innere @1treppe
|
||||||
|
Outer @1 Stair=Äußere @1treppe
|
||||||
|
@1 Slab=@1platte
|
||||||
Weak Computer=Schwacher Computer
|
Weak Computer=Schwacher Computer
|
||||||
Weak Computer 1=Schwacher Computer 1
|
Weak Computer 1=Schwacher Computer 1
|
||||||
Weak Computer 2=Schwacher Computer 2
|
Weak Computer 2=Schwacher Computer 2
|
||||||
Chess=Schach
|
Chess=Schach
|
||||||
Chess Debug=Schachdebug
|
Chess Debug=Schachdebug
|
||||||
|
Select a game mode=Wählen Sie einen Spielmodus
|
||||||
|
Select a mode:=Modus wählen:
|
||||||
|
Singleplayer=Einzelspieler
|
||||||
|
Multiplayer=Mehrspieler
|
||||||
|
Bot vs Bot=Bot vs. Bot
|
||||||
check=Schach
|
check=Schach
|
||||||
checkmate=Schachmatt
|
checkmate=Schachmatt
|
||||||
resigned=aufgegeben
|
resigned=aufgegeben
|
||||||
winner=Sieger
|
winner=Sieger
|
||||||
loser=Verlierer
|
loser=Verlierer
|
||||||
draw=Remis
|
draw=Remis
|
||||||
|
PROMOTION@nFOR BLACK!=UMWANDLUNG@nFÜR SCHWARZ!
|
||||||
|
Promote pawn to:=Bauer umwandeln zu:
|
||||||
|
PROMOTION@nFOR WHITE!=UMWANDLUNG@nFÜR WEISS!
|
||||||
|
DRAW CLAIM@nBY WHITE!=REMISANSPRUCH@nVON WEISS!
|
||||||
|
DRAW CLAIM@nBY BLACK!=REMISANSPRUCH@nVON SCHWARZ!
|
||||||
|
The player has invoked the 50-move rule for the next move. The next move might draw the game.=Der Spieler will für den nächsten Zug die 50-Züge-Regel anwenden. Der nächste Zug könnte die Partie remis enden lassen.
|
||||||
|
The player has invoked the threefold-repetition rule for the next move. The next move might draw the game.=Der Spieler will für den nächsten Zug die Regel für wiederholte Stellungen anwenden. Der nächste Zug könnte die Partie remis enden lassen.
|
||||||
|
New game=Neues Spiel
|
||||||
|
Resign=Aufgeben
|
||||||
|
Select a color:=Farbe wählen:
|
||||||
|
White=Weiß
|
||||||
|
Black=Schwarz
|
||||||
|
Invoke the 50-move rule for your next move=50-Züge-Regel für den nächsten Zug anwenden
|
||||||
|
Invoke the 50-move rule and draw the game=50-Züge-Regel anwenden und die Partie remis enden lassen
|
||||||
|
Invoke the threefold repetition rule and draw the game=Stellungswiederholungsregel anwenden und die Partie remis enden lassen
|
||||||
|
Invoke the threefold repetition rule for your next move=Stellungswiederholungsregel für den nächsten Zug anwenden
|
||||||
You have checkmated @1. You win!=Sie haben @1 schachmatt gesetzt. Sieg!
|
You have checkmated @1. You win!=Sie haben @1 schachmatt gesetzt. Sieg!
|
||||||
You were checkmated by @1. You lose!=Sie wurden von @1 schachmatt gesetzt. Niederlage!
|
You were checkmated by @1. You lose!=Sie wurden von @1 schachmatt gesetzt. Niederlage!
|
||||||
The game ended up in a stalemate! It's a draw!=Das Partie endete in einem Patt. Das ist ein Remis!
|
The game ended up in a stalemate! It's a draw!=Das Partie endete in einem Patt. Das ist ein Remis!
|
||||||
@ -54,27 +80,6 @@ White Queen=Weiße Dame
|
|||||||
Black Queen=Schwarze Dame
|
Black Queen=Schwarze Dame
|
||||||
White King=Weißer König
|
White King=Weißer König
|
||||||
Black King=Schwarzer König
|
Black King=Schwarzer König
|
||||||
Select a game mode=Wählen Sie einen Spielmodus
|
|
||||||
Select a mode:=Modus wählen:
|
|
||||||
Singleplayer=Einzelspieler
|
|
||||||
Multiplayer=Mehrspieler
|
|
||||||
Bot vs Bot=Bot vs. Bot
|
|
||||||
PROMOTION@nFOR BLACK!=UMWANDLUNG@nFÜR SCHWARZ!
|
|
||||||
Promote pawn to:=Bauer umwandeln zu:
|
|
||||||
PROMOTION@nFOR WHITE!=UMWANDLUNG@nFÜR WEISS!
|
|
||||||
DRAW CLAIM@nBY WHITE!=REMISANSPRUCH@nVON WEISS!
|
|
||||||
DRAW CLAIM@nBY BLACK!=REMISANSPRUCH@nVON SCHWARZ!
|
|
||||||
The player has invoked the 50-move rule for the next move. The next move might draw the game.=Der Spieler will für den nächsten Zug die 50-Züge-Regel anwenden. Der nächste Zug könnte die Partie remis enden lassen.
|
|
||||||
The player has invoked the threefold-repetition rule for the next move. The next move might draw the game.=Der Spieler will für den nächsten Zug die Regel für wiederholte Stellungen anwenden. Der nächste Zug könnte die Partie remis enden lassen.
|
|
||||||
New game=Neues Spiel
|
|
||||||
Resign=Aufgeben
|
|
||||||
Select a color:=Farbe wählen:
|
|
||||||
White=Weiß
|
|
||||||
Black=Schwarz
|
|
||||||
Invoke the 50-move rule for your next move=50-Züge-Regel für den nächsten Zug anwenden
|
|
||||||
Invoke the 50-move rule and draw the game=50-Züge-Regel anwenden und die Partie remis enden lassen
|
|
||||||
Invoke the threefold repetition rule and draw the game=Stellungswiederholungsregel anwenden und die Partie remis enden lassen
|
|
||||||
Invoke the threefold repetition rule for your next move=Stellungswiederholungsregel für den nächsten Zug anwenden
|
|
||||||
Light a fire below to heat it up=Entfachen Sie unten ein Feuer, um ihn zu erhitzen
|
Light a fire below to heat it up=Entfachen Sie unten ein Feuer, um ihn zu erhitzen
|
||||||
Use a bowl to eat the soup=Schüssel benutzen, um die Suppe zu essen
|
Use a bowl to eat the soup=Schüssel benutzen, um die Suppe zu essen
|
||||||
Drop foods inside to make a soup=Nahrungsmittel einwerfen, um Suppe zu machen
|
Drop foods inside to make a soup=Nahrungsmittel einwerfen, um Suppe zu machen
|
||||||
@ -100,40 +105,33 @@ Bowl of soup=Schüssel mit Suppe
|
|||||||
Efficiency=Effizienz
|
Efficiency=Effizienz
|
||||||
Durability=Haltbarkeit
|
Durability=Haltbarkeit
|
||||||
Sharpness=Schärfe
|
Sharpness=Schärfe
|
||||||
|
@1 (+@2%)=@1 (+@2%)
|
||||||
|
Your weapon inflicts more damage=Ihre Waffe richtet mehr Schaden an
|
||||||
|
Your tool lasts longer=Ihr Werkzeug hält länger
|
||||||
|
Your tool digs faster=Ihr Werkzeug arbeitet schneller
|
||||||
Enchantment Table=Zaubertisch
|
Enchantment Table=Zaubertisch
|
||||||
Enchant your tools with mese crystals=Werkzeuge mit Mesekristallen verzaubern
|
Enchant your tools with mese crystals=Werkzeuge mit Mesekristallen verzaubern
|
||||||
Enchanted @1 @2@n@3=@1@2 (verzaubert)@n@3
|
Enchanted @1@n@2=@1 (verzaubert)@n@2
|
||||||
Enchanted @1 @2=@1@2 (verzaubert)
|
Enchanted @1=@1 (verzaubert)
|
||||||
Steel=Eisen
|
|
||||||
Bronze=Bronze
|
|
||||||
Mese=Mese
|
|
||||||
Diamond=Diamant
|
|
||||||
Axe=axt
|
|
||||||
Pickaxe=spitzhacke
|
|
||||||
Shovel=schaufel
|
|
||||||
Sword=schwert
|
|
||||||
Your weapon inflicts more damages=Ihre Waffe richtet mehr Schaden an
|
|
||||||
Your tool last longer=Ihr Werkzeug hält länger
|
|
||||||
Your tool digs faster=Ihr Werkzeug arbeitet schneller
|
|
||||||
Artificial Hive=Künstlicher Bienenstock
|
|
||||||
Bees live here and produce honey=Hier leben Bienen, die Honig produzieren
|
|
||||||
Honey=Honig
|
|
||||||
Made by bees=Hergestellt von Bienen
|
|
||||||
The bees are busy making honey.=Die Bienen sind beschäftigt, Honig herzustellen.
|
The bees are busy making honey.=Die Bienen sind beschäftigt, Honig herzustellen.
|
||||||
The bees are looking for flowers.=Die Bienen halten nach Blumen Ausschau.
|
The bees are looking for flowers.=Die Bienen halten nach Blumen Ausschau.
|
||||||
The bees want to pollinate more flowers.=Die Bienen wollen mehr Blumen bestäuben.
|
The bees want to pollinate more flowers.=Die Bienen wollen mehr Blumen bestäuben.
|
||||||
The bees are idle.=Die Bienen sind unbeschäftigt.
|
The bees are idle.=Die Bienen sind unbeschäftigt.
|
||||||
The bees are resting.=Die Bienen ruhen sich aus.
|
The bees are resting.=Die Bienen ruhen sich aus.
|
||||||
|
Artificial Hive=Künstlicher Bienenstock
|
||||||
|
Bees live here and produce honey=Hier leben Bienen, die Honig produzieren
|
||||||
|
Honey=Honig
|
||||||
|
Made by bees=Hergestellt von Bienen
|
||||||
@1 (owned by @2)=@1 (Eigentum von @2)
|
@1 (owned by @2)=@1 (Eigentum von @2)
|
||||||
Item Frame=Gegenstandsrahmen
|
Item Frame=Gegenstandsrahmen
|
||||||
For presenting a single item=Präsentiert einen einzelnen Gegenstand
|
For presenting a single item=Präsentiert einen einzelnen Gegenstand
|
||||||
@1's Mailbox=Briefkasten von @1
|
|
||||||
The mailbox is full.=Der Briefkasten ist voll.
|
|
||||||
Mailbox=Briefkasten
|
|
||||||
Lets other players give you things=Hiermit kann man von anderen Spielern Dinge erhalten
|
|
||||||
× @1=× @1
|
× @1=× @1
|
||||||
|
Mailbox=Briefkasten
|
||||||
Last donators=Letzte Spender
|
Last donators=Letzte Spender
|
||||||
Send your goods to@n@1=Senden Sie Ihre Waren an@n@1
|
Send your goods to@n@1=Senden Sie Ihre Waren an@n@1
|
||||||
|
@1's Mailbox=Briefkasten von @1
|
||||||
|
The mailbox is full.=Der Briefkasten ist voll.
|
||||||
|
Lets other players give you things=Hiermit kann man von anderen Spielern Dinge erhalten
|
||||||
Opens doors when stepped on=Öffnet Türen beim Betreten
|
Opens doors when stepped on=Öffnet Türen beim Betreten
|
||||||
Wooden Pressure Plate=Holzdruckplatte
|
Wooden Pressure Plate=Holzdruckplatte
|
||||||
Stone Pressure Plate=Steindruckplatte
|
Stone Pressure Plate=Steindruckplatte
|
||||||
@ -196,10 +194,6 @@ Television=Fernseher
|
|||||||
Wood Framed Glass=Holzrahmenglas
|
Wood Framed Glass=Holzrahmenglas
|
||||||
Radio=Radio
|
Radio=Radio
|
||||||
Speaker=Lautsprecher
|
Speaker=Lautsprecher
|
||||||
@1 Stair=@1treppe
|
|
||||||
Inner @1 Stair=Innere @1treppe
|
|
||||||
Outer @1 Stair=Äußere @1treppe
|
|
||||||
@1 Slab=@1platte
|
|
||||||
Rope=Seil
|
Rope=Seil
|
||||||
Nanoslab=nanoplatte
|
Nanoslab=nanoplatte
|
||||||
Micropanel=mikropaneel
|
Micropanel=mikropaneel
|
||||||
@ -211,13 +205,13 @@ Slab=platte
|
|||||||
Double Panel=doppelpaneel
|
Double Panel=doppelpaneel
|
||||||
Half-Stair=halbtreppe
|
Half-Stair=halbtreppe
|
||||||
Stair=Treppe
|
Stair=Treppe
|
||||||
Work Bench=Werkbank
|
|
||||||
For cutting blocks, repairing tools with a hammer, crafting and storing items=Für Blockzuschnitt, Werkzeugreparatur mit Hammer, Fertigung und Lagerung
|
|
||||||
@1 @2=@1@2
|
|
||||||
Hammer=Hammer
|
|
||||||
Repairs tools at the work bench=Repariert Werkzeuge an der Werkbank
|
|
||||||
Cut=Zuschnitt
|
Cut=Zuschnitt
|
||||||
Repair=Reparatur
|
Repair=Reparatur
|
||||||
Crafting=Fertigung
|
Crafting=Fertigung
|
||||||
Storage=Lager
|
Storage=Lager
|
||||||
Back=Zurück
|
Back=Zurück
|
||||||
|
Work Bench=Werkbank
|
||||||
|
For cutting blocks, repairing tools with a hammer, crafting and storing items=Für Blockzuschnitt, Werkzeugreparatur mit Hammer, Fertigung und Lagerung
|
||||||
|
@1 @2=@1@2
|
||||||
|
Repairs tools at the work bench=Repariert Werkzeuge an der Werkbank
|
||||||
|
Hammer=Hammer
|
||||||
|
@ -1,15 +1,41 @@
|
|||||||
# textdomain: xdecor
|
# textdomain: xdecor
|
||||||
|
A libre decoration mod meant to be simple and well-featured.=
|
||||||
|
@1 Stair=
|
||||||
|
Inner @1 Stair=
|
||||||
|
Outer @1 Stair=
|
||||||
|
@1 Slab=
|
||||||
Weak Computer=
|
Weak Computer=
|
||||||
Weak Computer 1=
|
Weak Computer 1=
|
||||||
Weak Computer 2=
|
Weak Computer 2=
|
||||||
Chess=Echecs
|
Chess=Echecs
|
||||||
Chess Debug=
|
Chess Debug=
|
||||||
|
Select a game mode=
|
||||||
|
Select a mode:=Sélectionnez un mode de jeu:
|
||||||
|
Singleplayer=Solo
|
||||||
|
Multiplayer=Multijoueur
|
||||||
|
Bot vs Bot=
|
||||||
check=échec
|
check=échec
|
||||||
checkmate=
|
checkmate=
|
||||||
resigned=
|
resigned=
|
||||||
winner=
|
winner=
|
||||||
loser=
|
loser=
|
||||||
draw=
|
draw=
|
||||||
|
PROMOTION@nFOR BLACK!=
|
||||||
|
Promote pawn to:=
|
||||||
|
PROMOTION@nFOR WHITE!=
|
||||||
|
DRAW CLAIM@nBY WHITE!=
|
||||||
|
DRAW CLAIM@nBY BLACK!=
|
||||||
|
The player has invoked the 50-move rule for the next move. The next move might draw the game.=
|
||||||
|
The player has invoked the threefold-repetition rule for the next move. The next move might draw the game.=
|
||||||
|
New game=Nouvelle partie
|
||||||
|
Resign=
|
||||||
|
Select a color:=
|
||||||
|
White=
|
||||||
|
Black=
|
||||||
|
Invoke the 50-move rule for your next move=
|
||||||
|
Invoke the 50-move rule and draw the game=
|
||||||
|
Invoke the threefold repetition rule and draw the game=
|
||||||
|
Invoke the threefold repetition rule for your next move=
|
||||||
You have checkmated @1. You win!=
|
You have checkmated @1. You win!=
|
||||||
You were checkmated by @1. You lose!=
|
You were checkmated by @1. You lose!=
|
||||||
The game ended up in a stalemate! It's a draw!=
|
The game ended up in a stalemate! It's a draw!=
|
||||||
@ -54,27 +80,6 @@ White Queen=Reine blanche
|
|||||||
Black Queen=Reine noire
|
Black Queen=Reine noire
|
||||||
White King=Roi blanc
|
White King=Roi blanc
|
||||||
Black King=Roi noir
|
Black King=Roi noir
|
||||||
Select a game mode=
|
|
||||||
Select a mode:=Sélectionnez un mode de jeu:
|
|
||||||
Singleplayer=Solo
|
|
||||||
Multiplayer=Multijoueur
|
|
||||||
Bot vs Bot=
|
|
||||||
PROMOTION@nFOR BLACK!=
|
|
||||||
Promote pawn to:=
|
|
||||||
PROMOTION@nFOR WHITE!=
|
|
||||||
DRAW CLAIM@nBY WHITE!=
|
|
||||||
DRAW CLAIM@nBY BLACK!=
|
|
||||||
The player has invoked the 50-move rule for the next move. The next move might draw the game.=
|
|
||||||
The player has invoked the threefold-repetition rule for the next move. The next move might draw the game.=
|
|
||||||
New game=Nouvelle partie
|
|
||||||
Resign=
|
|
||||||
Select a color:=
|
|
||||||
White=
|
|
||||||
Black=
|
|
||||||
Invoke the 50-move rule for your next move=
|
|
||||||
Invoke the 50-move rule and draw the game=
|
|
||||||
Invoke the threefold repetition rule and draw the game=
|
|
||||||
Invoke the threefold repetition rule for your next move=
|
|
||||||
Light a fire below to heat it up=
|
Light a fire below to heat it up=
|
||||||
Use a bowl to eat the soup=Utilisez un bol pour boire la soupe
|
Use a bowl to eat the soup=Utilisez un bol pour boire la soupe
|
||||||
Drop foods inside to make a soup=Placez des ingrédients à l’intérieur pour faire une soupe
|
Drop foods inside to make a soup=Placez des ingrédients à l’intérieur pour faire une soupe
|
||||||
@ -100,40 +105,33 @@ Bowl of soup=Bol de soupe
|
|||||||
Efficiency=Efficacité
|
Efficiency=Efficacité
|
||||||
Durability=Durabilité
|
Durability=Durabilité
|
||||||
Sharpness=Tranchant
|
Sharpness=Tranchant
|
||||||
|
@1 (+@2%)=
|
||||||
|
Your weapon inflicts more damage=Votre arme inflige plus de dégâts
|
||||||
|
Your tool lasts longer=Votre outil dure plus longtemps
|
||||||
|
Your tool digs faster=Votre outil creuse plus vite
|
||||||
Enchantment Table=Table d’enchantements
|
Enchantment Table=Table d’enchantements
|
||||||
Enchant your tools with mese crystals=
|
Enchant your tools with mese crystals=
|
||||||
Enchanted @1 @2@n@3=@2 en @1 enchantée@n@3
|
Enchanted @1@n@2=
|
||||||
Enchanted @1 @2=@2 en @1 enchantée
|
Enchanted @1=
|
||||||
Steel=Fer
|
|
||||||
Bronze=Bronze
|
|
||||||
Mese=Mese
|
|
||||||
Diamond=Diamant
|
|
||||||
Axe=Hache
|
|
||||||
Pickaxe=Pioche
|
|
||||||
Shovel=Pelle
|
|
||||||
Sword=Épée
|
|
||||||
Your weapon inflicts more damages=Votre arme inflige plus de dégâts
|
|
||||||
Your tool last longer=Votre outil dure plus longtemps
|
|
||||||
Your tool digs faster=Votre outil creuse plus vite
|
|
||||||
Artificial Hive=Ruche artificielle
|
|
||||||
Bees live here and produce honey=
|
|
||||||
Honey=Miel
|
|
||||||
Made by bees=
|
|
||||||
The bees are busy making honey.=
|
The bees are busy making honey.=
|
||||||
The bees are looking for flowers.=
|
The bees are looking for flowers.=
|
||||||
The bees want to pollinate more flowers.=
|
The bees want to pollinate more flowers.=
|
||||||
The bees are idle.=
|
The bees are idle.=
|
||||||
The bees are resting.=
|
The bees are resting.=
|
||||||
|
Artificial Hive=Ruche artificielle
|
||||||
|
Bees live here and produce honey=
|
||||||
|
Honey=Miel
|
||||||
|
Made by bees=
|
||||||
@1 (owned by @2)=@1 (propriété de @2)
|
@1 (owned by @2)=@1 (propriété de @2)
|
||||||
Item Frame=Cadre
|
Item Frame=Cadre
|
||||||
For presenting a single item=
|
For presenting a single item=
|
||||||
@1's Mailbox=Boite aux lettres de @1
|
|
||||||
The mailbox is full.=La boite aux lettres est pleine.
|
|
||||||
Mailbox=Boite aux lettres
|
|
||||||
Lets other players give you things=
|
|
||||||
× @1=
|
× @1=
|
||||||
|
Mailbox=Boite aux lettres
|
||||||
Last donators=Derniers donateurs
|
Last donators=Derniers donateurs
|
||||||
Send your goods to@n@1=Envoyer vos biens à@n@1
|
Send your goods to@n@1=Envoyer vos biens à@n@1
|
||||||
|
@1's Mailbox=Boite aux lettres de @1
|
||||||
|
The mailbox is full.=La boite aux lettres est pleine.
|
||||||
|
Lets other players give you things=
|
||||||
Opens doors when stepped on=
|
Opens doors when stepped on=
|
||||||
Wooden Pressure Plate=Plaque de pression en bois
|
Wooden Pressure Plate=Plaque de pression en bois
|
||||||
Stone Pressure Plate=Plaque de pression en pierre
|
Stone Pressure Plate=Plaque de pression en pierre
|
||||||
@ -196,10 +194,6 @@ Television=Télévision
|
|||||||
Wood Framed Glass=Verre encadré par du bois
|
Wood Framed Glass=Verre encadré par du bois
|
||||||
Radio=
|
Radio=
|
||||||
Speaker=
|
Speaker=
|
||||||
@1 Stair=
|
|
||||||
Inner @1 Stair=
|
|
||||||
Outer @1 Stair=
|
|
||||||
@1 Slab=
|
|
||||||
Rope=Corde
|
Rope=Corde
|
||||||
Nanoslab=
|
Nanoslab=
|
||||||
Micropanel=
|
Micropanel=
|
||||||
@ -211,21 +205,22 @@ Slab=
|
|||||||
Double Panel=
|
Double Panel=
|
||||||
Half-Stair=
|
Half-Stair=
|
||||||
Stair=
|
Stair=
|
||||||
Work Bench=Atelier
|
|
||||||
For cutting blocks, repairing tools with a hammer, crafting and storing items=
|
|
||||||
@1 @2=
|
|
||||||
Hammer=Marteau
|
|
||||||
Repairs tools at the work bench=
|
|
||||||
Cut=Couper
|
Cut=Couper
|
||||||
Repair=Réparer
|
Repair=Réparer
|
||||||
Crafting=Fabrication
|
Crafting=Fabrication
|
||||||
Storage=Stockage
|
Storage=Stockage
|
||||||
Back=Retour
|
Back=Retour
|
||||||
|
Work Bench=Atelier
|
||||||
|
For cutting blocks, repairing tools with a hammer, crafting and storing items=
|
||||||
|
@1 @2=
|
||||||
|
Repairs tools at the work bench=
|
||||||
|
Hammer=Marteau
|
||||||
|
|
||||||
|
|
||||||
##### not used anymore #####
|
##### not used anymore #####
|
||||||
|
|
||||||
Dumb AI=IA stupide
|
Enchanted @1 @2@n@3=@2 en @1 enchantée@n@3
|
||||||
|
Enchanted @1 @2=@2 en @1 enchantée
|
||||||
You can't reset the chessboard, a game has been started. If you aren't a current player, try again in @1=Vous ne pouvez pas mettre à zéro l’échiquier, une partie a été commencée. Si ce n’est pas votre tour de jouer, réessayez dans @1
|
You can't reset the chessboard, a game has been started. If you aren't a current player, try again in @1=Vous ne pouvez pas mettre à zéro l’échiquier, une partie a été commencée. Si ce n’est pas votre tour de jouer, réessayez dans @1
|
||||||
You can't dig the chessboard, a game has been started. Reset it first if you're a current player, or dig it again in @1=Vous ne pouvez pas récupérer l’échiquier, une partie à été commencée. Remettez le à zéro si vous c’est votre tour de jouer, ou réessayez dans @1
|
You can't dig the chessboard, a game has been started. Reset it first if you're a current player, or dig it again in @1=Vous ne pouvez pas récupérer l’échiquier, une partie à été commencée. Remettez le à zéro si vous c’est votre tour de jouer, ou réessayez dans @1
|
||||||
Cauldron (idle)=Chaudron (inactif)
|
Cauldron (idle)=Chaudron (inactif)
|
||||||
|
@ -1,47 +1,75 @@
|
|||||||
# textdomain: xdecor
|
# textdomain: xdecor
|
||||||
Weak Computer=
|
# author: Zughy (chess)
|
||||||
Weak Computer 1=
|
# Nota per chi traduce: ho usato italiano inclusivo (ə per il singolare) e usato il participio presente per giocatore e spettatore (=giocante e osservante) come esperimento di inclusività. Per gli apostrofi ho usato ` (un - un' -> un`)
|
||||||
Weak Computer 2=
|
A libre decoration mod meant to be simple and well-featured.=
|
||||||
|
@1 Stair=
|
||||||
|
Inner @1 Stair=
|
||||||
|
Outer @1 Stair=
|
||||||
|
@1 Slab=
|
||||||
|
Weak Computer=Computer facile
|
||||||
|
Weak Computer 1=Computer facile 1
|
||||||
|
Weak Computer 2=Computer facile 2
|
||||||
Chess=Scacchi
|
Chess=Scacchi
|
||||||
Chess Debug=
|
Chess Debug=Debug scacchi
|
||||||
|
Select a game mode=Seleziona modalità di gioco
|
||||||
|
Select a mode:=Seleziona una modalità:
|
||||||
|
Singleplayer=Giocante singolə
|
||||||
|
Multiplayer=Multigiocante
|
||||||
|
Bot vs Bot=Bot contro Bot
|
||||||
check=scacco
|
check=scacco
|
||||||
checkmate=
|
checkmate=scacco matto
|
||||||
resigned=
|
resigned=arresə
|
||||||
winner=
|
winner=vince
|
||||||
loser=
|
loser=perde
|
||||||
draw=
|
draw=patta
|
||||||
You have checkmated @1. You win!=
|
PROMOTION@nFOR BLACK!=PROMOZIONE@nPER IL NERO!
|
||||||
You were checkmated by @1. You lose!=
|
Promote pawn to:=Promuovi pedone a:
|
||||||
The game ended up in a stalemate! It's a draw!=
|
PROMOTION@nFOR WHITE!=PROMOZIONE@nPER IL BIANCO!
|
||||||
The game ended up in a dead position! It's a draw!=
|
DRAW CLAIM@nBY WHITE!=PATTA DICHIARATA@nDAL BIANCO!
|
||||||
No piece was captured and no pawn was moved for 75 consecutive moves of each player. It's a draw!=
|
DRAW CLAIM@nBY BLACK!=PATTA DICHIARATA@nDAL NERO!
|
||||||
You have drawn the game by invoking the 50-move rule.=
|
The player has invoked the 50-move rule for the next move. The next move might draw the game.=Lə giocante ha invocato la regola delle 50 mosse per la prossima mossa. Quest'ultima potrebbe portare a una patta.
|
||||||
@1 has drawn the game by invoking the 50-move rule.=
|
The player has invoked the threefold-repetition rule for the next move. The next move might draw the game.=Lə giocante ha invocato la regola della tripla ripetizione per la prossima mossa. Quest'ultima potrebbe portare a una patta
|
||||||
You have failed to make a game-drawing move. The game continues.=
|
New game=Nuova partita
|
||||||
@1 made a draw claim using the 50-move rule but it was false. The game continues.=
|
Resign=Arrenditi
|
||||||
The exact same position has occured 5 times. It's a draw!=
|
Select a color:=Seleziona un colore:
|
||||||
You have drawn the game by invoking the threefold repetition rule.=
|
White=Bianco
|
||||||
@1 has drawn the game by invoking the threefold repetition rule.=
|
Black=Nero
|
||||||
@1 made a draw claim using the threefold repetition rule but it was false. The game continues.=
|
Invoke the 50-move rule for your next move=Invoca la regola delle 50 mosse per la tua prossima mossa
|
||||||
|
Invoke the 50-move rule and draw the game=Invoca la regola delle 50 mosse e chiudi in patta
|
||||||
|
Invoke the threefold repetition rule and draw the game=Invoca la regola della tripla ripetizione e chiudi in patta
|
||||||
|
Invoke the threefold repetition rule for your next move=Invoca la regola della tripla ripetizione per la tua prossima mossa
|
||||||
|
You have checkmated @1. You win!=Scacco matto a @1. Hai vinto!
|
||||||
|
You were checkmated by @1. You lose!=Scacco matto da @1. Hai perso!
|
||||||
|
The game ended up in a stalemate! It's a draw!=È uno stallo! Patta!
|
||||||
|
The game ended up in a dead position! It's a draw!=È una posizione morta! Patta!
|
||||||
|
No piece was captured and no pawn was moved for 75 consecutive moves of each player. It's a draw!=Nessun giocante ha catturato pezzi né mosso pedoni per 75 mosse consecutive. Patta!
|
||||||
|
You have drawn the game by invoking the 50-move rule.=Hai chiuso in patta con l'invocazione della regola delle 50 mosse.
|
||||||
|
@1 has drawn the game by invoking the 50-move rule.=@1 ha chiuso in patta con l'invocazione della regola delle 50 mosse.
|
||||||
|
You have failed to make a game-drawing move. The game continues.=Non sei riuscitə a fare una mossa che portasse a una patta. Il gioco continua.
|
||||||
|
@1 made a draw claim using the 50-move rule but it was false. The game continues.=@1 ha tentato la patta con la regola delle 50 mosse ma ha fallito. La partita continua.
|
||||||
|
The exact same position has occured 5 times. It's a draw!=La stessa identica mossa si è ripetuta per 5 volte. Patta!
|
||||||
|
You have drawn the game by invoking the threefold repetition rule.=Hai chiuso in patta con l'invocazione della regola della tripla ripetizione.
|
||||||
|
@1 has drawn the game by invoking the threefold repetition rule.=@1 ha chiuso in patta con l'invocazione della regola della tripla ripetizione.
|
||||||
|
@1 made a draw claim using the threefold repetition rule but it was false. The game continues.=@1 ha tentato la patta con la regola della tripla ripetizione ma ha fallito. La partita continua.
|
||||||
Chess Board=Scacchiera
|
Chess Board=Scacchiera
|
||||||
Someone else plays white pieces!=Qualcun altro gioca con il bianco!
|
Someone else plays white pieces!=Qualcun`altrə sta già giocando con il bianco!
|
||||||
It's not your turn!=
|
It's not your turn!=Non è il tuo turno!
|
||||||
Someone else plays black pieces!=Qualcun altro gioca con il nero!
|
Someone else plays black pieces!=Qualcun`altrə sta già giocando con il nero!
|
||||||
Black cannot move first!=
|
Black cannot move first!=Il nero non può muovere per primo!
|
||||||
@1 s=
|
@1 s=@1 s
|
||||||
@1 min @2 s=
|
@1 min @2 s=@1 min @2 s
|
||||||
You can't reset the chessboard, a game has been started. Try again in @1.=
|
You can't reset the chessboard, a game has been started. Try again in @1.=Non puoi ripristinare la scacchiera, c'è una partita in corso. Riprova tra @1.
|
||||||
Resigning is not possible yet.=
|
Resigning is not possible yet.=Non ci si può ancora arrendere.
|
||||||
You have resigned.=
|
You have resigned.=Ti sei arresə.
|
||||||
@1 has resigned. You win!=
|
@1 has resigned. You win!=@1 si è arresə. Hai vinto!
|
||||||
You can't resign, you're not playing in this game.=
|
You can't resign, you're not playing in this game.=Non ti puoi arrendere, non stai giocando in questa partita.
|
||||||
You can't claim a draw, it's not your turn!=
|
You can't claim a draw, it's not your turn!=Non puoi chiamare patta, non è il tuo turno!
|
||||||
You're only a spectator in this game of Chess.=
|
You're only a spectator in this game of Chess.=Sei solo un`osservante in questa partita di scacchi.
|
||||||
This isn't the time for promotion.=
|
This isn't the time for promotion.=Non è il momento per una promozione.
|
||||||
It's not your turn! This promotion is meant for the other player.=
|
It's not your turn! This promotion is meant for the other player.=Non è il tuo turno! Questa promozione spetta all'altrə giocante.
|
||||||
You can't dig the chessboard, a game has been started. Reset it first or dig it again in @1.=
|
You can't dig the chessboard, a game has been started. Reset it first or dig it again in @1.=Non puoi rimuovere la scacchiera, c'è una partita in corso. Ripristinala prima, o riprova a rimuoverla in @1.
|
||||||
You can't dig the chessboard, a game has been started. Try it again in @1.=
|
You can't dig the chessboard, a game has been started. Try it again in @1.=Non puoi rimuovere la scacchiera, c'è una partita in corso. Riprova tra @1.
|
||||||
Play a game of Chess against another player or the computer=
|
Play a game of Chess against another player or the computer=Gioca una partita a scacchi contro un`altrə giocante o contro il computer
|
||||||
White Pawn=Pedone bianco
|
White Pawn=Pedone bianco
|
||||||
Black Pawn=Pedone nero
|
Black Pawn=Pedone nero
|
||||||
White Rook=Torre bianca
|
White Rook=Torre bianca
|
||||||
@ -54,27 +82,6 @@ White Queen=Regina bianca
|
|||||||
Black Queen=Regina nera
|
Black Queen=Regina nera
|
||||||
White King=Re bianco
|
White King=Re bianco
|
||||||
Black King=Re nero
|
Black King=Re nero
|
||||||
Select a game mode=
|
|
||||||
Select a mode:=Selezionare una modalità
|
|
||||||
Singleplayer=Singolo giocatore
|
|
||||||
Multiplayer=Multigiocatore
|
|
||||||
Bot vs Bot=
|
|
||||||
PROMOTION@nFOR BLACK!=
|
|
||||||
Promote pawn to:=
|
|
||||||
PROMOTION@nFOR WHITE!=
|
|
||||||
DRAW CLAIM@nBY WHITE!=
|
|
||||||
DRAW CLAIM@nBY BLACK!=
|
|
||||||
The player has invoked the 50-move rule for the next move. The next move might draw the game.=
|
|
||||||
The player has invoked the threefold-repetition rule for the next move. The next move might draw the game.=
|
|
||||||
New game=Nuova partita
|
|
||||||
Resign=
|
|
||||||
Select a color:=
|
|
||||||
White=
|
|
||||||
Black=
|
|
||||||
Invoke the 50-move rule for your next move=
|
|
||||||
Invoke the 50-move rule and draw the game=
|
|
||||||
Invoke the threefold repetition rule and draw the game=
|
|
||||||
Invoke the threefold repetition rule for your next move=
|
|
||||||
Light a fire below to heat it up=
|
Light a fire below to heat it up=
|
||||||
Use a bowl to eat the soup=Utilizzare una ciotola per mangiare la zuppa
|
Use a bowl to eat the soup=Utilizzare una ciotola per mangiare la zuppa
|
||||||
Drop foods inside to make a soup=Mettere gli ingredienti all'interno per fare una zuppa
|
Drop foods inside to make a soup=Mettere gli ingredienti all'interno per fare una zuppa
|
||||||
@ -100,40 +107,33 @@ Bowl of soup=Ciotola di zuppa
|
|||||||
Efficiency=Efficacia
|
Efficiency=Efficacia
|
||||||
Durability=Durabilità
|
Durability=Durabilità
|
||||||
Sharpness=Affilatezza
|
Sharpness=Affilatezza
|
||||||
|
@1 (+@2%)=
|
||||||
|
Your weapon inflicts more damage=La tua arma infligge più danno
|
||||||
|
Your tool lasts longer=Il tuo utensile dura di più
|
||||||
|
Your tool digs faster=Il tuo utensile scava più rapidamente
|
||||||
Enchantment Table=Tavolo per migliorie
|
Enchantment Table=Tavolo per migliorie
|
||||||
Enchant your tools with mese crystals=
|
Enchant your tools with mese crystals=
|
||||||
Enchanted @1 @2@n@3=@2 su @1 incantesimo@n@3
|
Enchanted @1@n@2=
|
||||||
Enchanted @1 @2=@2 su @1 incantesimo
|
Enchanted @1=
|
||||||
Steel=Acciaio
|
|
||||||
Bronze=Bronzo
|
|
||||||
Mese=Mese
|
|
||||||
Diamond=Diamante
|
|
||||||
Axe=Ascia
|
|
||||||
Pickaxe=Piccone
|
|
||||||
Shovel=Pala
|
|
||||||
Sword=Spada
|
|
||||||
Your weapon inflicts more damages=La tua arma infligge più danno
|
|
||||||
Your tool last longer=Il tuo utensile dura di più
|
|
||||||
Your tool digs faster=Il tuo utensile scava più rapidamente
|
|
||||||
Artificial Hive=Favo artificiale
|
|
||||||
Bees live here and produce honey=
|
|
||||||
Honey=Miele
|
|
||||||
Made by bees=
|
|
||||||
The bees are busy making honey.=
|
The bees are busy making honey.=
|
||||||
The bees are looking for flowers.=
|
The bees are looking for flowers.=
|
||||||
The bees want to pollinate more flowers.=
|
The bees want to pollinate more flowers.=
|
||||||
The bees are idle.=
|
The bees are idle.=
|
||||||
The bees are resting.=
|
The bees are resting.=
|
||||||
|
Artificial Hive=Favo artificiale
|
||||||
|
Bees live here and produce honey=
|
||||||
|
Honey=Miele
|
||||||
|
Made by bees=
|
||||||
@1 (owned by @2)=@1 (proprietà di @2)
|
@1 (owned by @2)=@1 (proprietà di @2)
|
||||||
Item Frame=Teca
|
Item Frame=Teca
|
||||||
For presenting a single item=
|
For presenting a single item=
|
||||||
@1's Mailbox=Cassetta delle lettere di @1
|
|
||||||
The mailbox is full.=La cassetta delle lettere è piena
|
|
||||||
Mailbox=Cassetta delle lettere
|
|
||||||
Lets other players give you things=
|
|
||||||
× @1=
|
× @1=
|
||||||
|
Mailbox=Cassetta delle lettere
|
||||||
Last donators=Ultimi donatori
|
Last donators=Ultimi donatori
|
||||||
Send your goods to@n@1=Invia i tuoi item a@n@1
|
Send your goods to@n@1=Invia i tuoi item a@n@1
|
||||||
|
@1's Mailbox=Cassetta delle lettere di @1
|
||||||
|
The mailbox is full.=La cassetta delle lettere è piena
|
||||||
|
Lets other players give you things=
|
||||||
Opens doors when stepped on=
|
Opens doors when stepped on=
|
||||||
Wooden Pressure Plate=Placca di pressione di legno
|
Wooden Pressure Plate=Placca di pressione di legno
|
||||||
Stone Pressure Plate=Placca di pressione di pietra
|
Stone Pressure Plate=Placca di pressione di pietra
|
||||||
@ -196,10 +196,6 @@ Television=Televisione
|
|||||||
Wood Framed Glass=Cornice in legno con vetro
|
Wood Framed Glass=Cornice in legno con vetro
|
||||||
Radio=
|
Radio=
|
||||||
Speaker=
|
Speaker=
|
||||||
@1 Stair=
|
|
||||||
Inner @1 Stair=
|
|
||||||
Outer @1 Stair=
|
|
||||||
@1 Slab=
|
|
||||||
Rope=Corda
|
Rope=Corda
|
||||||
Nanoslab=
|
Nanoslab=
|
||||||
Micropanel=
|
Micropanel=
|
||||||
@ -211,23 +207,22 @@ Slab=
|
|||||||
Double Panel=
|
Double Panel=
|
||||||
Half-Stair=
|
Half-Stair=
|
||||||
Stair=
|
Stair=
|
||||||
Work Bench=Banco da lavoro
|
|
||||||
For cutting blocks, repairing tools with a hammer, crafting and storing items=
|
|
||||||
@1 @2=
|
|
||||||
Hammer=Martello
|
|
||||||
Repairs tools at the work bench=
|
|
||||||
Cut=Tagliare
|
Cut=Tagliare
|
||||||
Repair=Riparare
|
Repair=Riparare
|
||||||
Crafting=Fabbricare
|
Crafting=Fabbricare
|
||||||
Storage=Conservare
|
Storage=Conservare
|
||||||
Back=Indietro
|
Back=Indietro
|
||||||
|
Work Bench=Banco da lavoro
|
||||||
|
For cutting blocks, repairing tools with a hammer, crafting and storing items=
|
||||||
|
@1 @2=
|
||||||
|
Repairs tools at the work bench=
|
||||||
|
Hammer=Martello
|
||||||
|
|
||||||
|
|
||||||
##### not used anymore #####
|
##### not used anymore #####
|
||||||
|
|
||||||
Dumb AI=AI stupida
|
Enchanted @1 @2@n@3=@2 su @1 incantesimo@n@3
|
||||||
You can't reset the chessboard, a game has been started. If you aren't a current player, try again in @1=Non si può resettare la partita, un gioco è in corso. Se non si è uno dei giocatori, riprovare in @1
|
Enchanted @1 @2=@2 su @1 incantesimo
|
||||||
You can't dig the chessboard, a game has been started. Reset it first if you're a current player, or dig it again in @1=Non si può scavare la scacchiera, una partita è in corso. Resettarla se si è uno dei giocatori, o riprovare in @1
|
|
||||||
Cauldron (idle)=Calderone (inattivo)
|
Cauldron (idle)=Calderone (inattivo)
|
||||||
Cauldron (active) - Drop foods inside to make a soup=Calderone (attivo) - Mettere gli ingredienti all'interno per fare una zuppa.
|
Cauldron (active) - Drop foods inside to make a soup=Calderone (attivo) - Mettere gli ingredienti all'interno per fare una zuppa.
|
||||||
Cauldron (active) - Use a bowl to eat the soup=Calderone (actif) - Utilizzare una ciotola per mangiare la zuppa
|
Cauldron (active) - Use a bowl to eat the soup=Calderone (actif) - Utilizzare una ciotola per mangiare la zuppa
|
||||||
|
6
mod.conf
@ -1,6 +1,6 @@
|
|||||||
name = xdecor
|
name = xdecor
|
||||||
title = X-Decor-libre
|
title = X-Decor-libre
|
||||||
description = A decoration mod meant to be simple and well-featured (libre version).
|
description = A libre decoration mod meant to be simple and well-featured.
|
||||||
depends = default, bucket, doors, farming, stairs, xpanes
|
depends = default, bucket, doors, farming, stairs, xpanes
|
||||||
optional_depends = playerphysics, player_api, fire, moreblocks, mesecons, unified_inventory, tt
|
optional_depends = player_api, fire, moreblocks, mesecons, unified_inventory, tt, toolranks
|
||||||
min_minetest_version = 5.7.0
|
min_minetest_version = 5.9
|
||||||
|
132
src/chess.lua
@ -327,11 +327,10 @@ local function en_passant_to_string(double_step)
|
|||||||
return s_en_passant
|
return s_en_passant
|
||||||
end
|
end
|
||||||
|
|
||||||
local function can_castle(meta, board, from_list, from_idx, to_idx)
|
local function can_castle(board, from_idx, to_idx, castlingRights)
|
||||||
local from_x, from_y = index_to_xy(from_idx)
|
local from_x, from_y = index_to_xy(from_idx)
|
||||||
local to_x, to_y = index_to_xy(to_idx)
|
local to_x, to_y = index_to_xy(to_idx)
|
||||||
local inv = meta:get_inventory()
|
local kingPiece = board[from_idx]
|
||||||
local kingPiece = inv:get_stack(from_list, from_idx):get_name()
|
|
||||||
local kingColor
|
local kingColor
|
||||||
if kingPiece:find("black") then
|
if kingPiece:find("black") then
|
||||||
kingColor = "black"
|
kingColor = "black"
|
||||||
@ -340,21 +339,21 @@ local function can_castle(meta, board, from_list, from_idx, to_idx)
|
|||||||
end
|
end
|
||||||
local possible_castles = {
|
local possible_castles = {
|
||||||
-- white queenside
|
-- white queenside
|
||||||
{ y = 7, to_x = 2, rook_idx = 57, rook_goal = 60, acheck_dir = -1, color = "white", meta = "castlingWhiteL", rook_id = 1 },
|
{ y = 7, to_x = 2, rook_idx = 57, rook_goal = 60, acheck_dir = -1, color = "white", rightName = "castlingWhiteL", rook_id = 1 },
|
||||||
-- white kingside
|
-- white kingside
|
||||||
{ y = 7, to_x = 6, rook_idx = 64, rook_goal = 62, acheck_dir = 1, color = "white", meta = "castlingWhiteR", rook_id = 2 },
|
{ y = 7, to_x = 6, rook_idx = 64, rook_goal = 62, acheck_dir = 1, color = "white", rightName = "castlingWhiteR", rook_id = 2 },
|
||||||
-- black queenside
|
-- black queenside
|
||||||
{ y = 0, to_x = 2, rook_idx = 1, rook_goal = 4, acheck_dir = -1, color = "black", meta = "castlingBlackL", rook_id = 1 },
|
{ y = 0, to_x = 2, rook_idx = 1, rook_goal = 4, acheck_dir = -1, color = "black", rightName = "castlingBlackL", rook_id = 1 },
|
||||||
-- black kingside
|
-- black kingside
|
||||||
{ y = 0, to_x = 6, rook_idx = 8, rook_goal = 6, acheck_dir = 1, color = "black", meta = "castlingBlackR", rook_id = 2 },
|
{ y = 0, to_x = 6, rook_idx = 8, rook_goal = 6, acheck_dir = 1, color = "black", rightName = "castlingBlackR", rook_id = 2 },
|
||||||
}
|
}
|
||||||
|
|
||||||
for p=1, #possible_castles do
|
for p=1, #possible_castles do
|
||||||
local pc = possible_castles[p]
|
local pc = possible_castles[p]
|
||||||
if pc.color == kingColor and pc.to_x == to_x and to_y == pc.y and from_y == pc.y then
|
if pc.color == kingColor and pc.to_x == to_x and to_y == pc.y and from_y == pc.y then
|
||||||
local castlingMeta = meta:get_int(pc.meta)
|
local castlingRightVal = castlingRights[pc.rightName]
|
||||||
local rookPiece = inv:get_stack(from_list, pc.rook_idx):get_name()
|
local rookPiece = board[pc.rook_idx]
|
||||||
if castlingMeta == 1 and rookPiece == "realchess:rook_"..kingColor.."_"..pc.rook_id then
|
if castlingRightVal == 1 and rookPiece == "realchess:rook_"..kingColor.."_"..pc.rook_id then
|
||||||
-- Check if all squares between king and rook are empty
|
-- Check if all squares between king and rook are empty
|
||||||
local empty_start, empty_end
|
local empty_start, empty_end
|
||||||
if pc.acheck_dir == -1 then
|
if pc.acheck_dir == -1 then
|
||||||
@ -367,7 +366,7 @@ local function can_castle(meta, board, from_list, from_idx, to_idx)
|
|||||||
empty_end = pc.rook_idx - 1
|
empty_end = pc.rook_idx - 1
|
||||||
end
|
end
|
||||||
for i = empty_start, empty_end do
|
for i = empty_start, empty_end do
|
||||||
if inv:get_stack(from_list, i):get_name() ~= "" then
|
if board[i] ~= "" then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -389,15 +388,15 @@ end
|
|||||||
-- Checks if a square to check if there is a piece that can be captured en passant. Returns true if this
|
-- Checks if a square to check if there is a piece that can be captured en passant. Returns true if this
|
||||||
-- is the case, false otherwise.
|
-- is the case, false otherwise.
|
||||||
-- Parameters:
|
-- Parameters:
|
||||||
-- * meta: chessboard node metadata
|
-- * board: chessboard table
|
||||||
-- * victim_color: color of the opponent to capture a piece from. "white" or "black". (so in White's turn, pass "black" here)
|
-- * victim_color: color of the opponent to capture a piece from. "white" or "black". (so in White's turn, pass "black" here)
|
||||||
-- * victim_index: board index of the square where you expect the victim to be
|
-- * victim_index: board index of the square where you expect the victim to be
|
||||||
local function can_capture_en_passant(meta, victim_color, victim_index)
|
-- * prevDoublePawnStepTo: if a pawn did a double-step in the previous halfmove, this is the board index of the destination.
|
||||||
local inv = meta:get_inventory()
|
-- if no pawn made a double-step in the previous halfmove, this is nil or 0.
|
||||||
local victimPiece = inv:get_stack("board", victim_index)
|
local function can_capture_en_passant(board, victim_color, victim_index, prevDoublePawnStepTo)
|
||||||
local double_step_index = meta:get_int("prevDoublePawnStepTo")
|
local victimPiece = board[victim_index]
|
||||||
local victim_name = victimPiece:get_name()
|
local double_step_index = prevDoublePawnStepTo or 0
|
||||||
if double_step_index ~= 0 and double_step_index == victim_index and victim_name:find(victim_color) and victim_name:sub(11,14) == "pawn" then
|
if double_step_index ~= 0 and double_step_index == victim_index and victimPiece:find(victim_color) and victimPiece:sub(11,14) == "pawn" then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
@ -413,7 +412,7 @@ end
|
|||||||
-- Any key with a numeric value is a possible destination.
|
-- Any key with a numeric value is a possible destination.
|
||||||
-- The numeric value is a move rating for the bot and is 0 by default.
|
-- The numeric value is a move rating for the bot and is 0 by default.
|
||||||
-- Example: { [4] = 0, [9] = 0 } -- can move to squares 4 and 9
|
-- Example: { [4] = 0, [9] = 0 } -- can move to squares 4 and 9
|
||||||
local function get_theoretical_moves_from(meta, board, from_idx)
|
local function get_theoretical_moves_from(board, from_idx, prevDoublePawnStepTo, castlingRights)
|
||||||
local piece, color = board[from_idx]:match(":(%w+)_(%w+)")
|
local piece, color = board[from_idx]:match(":(%w+)_(%w+)")
|
||||||
if not piece then
|
if not piece then
|
||||||
return {}
|
return {}
|
||||||
@ -450,7 +449,7 @@ local function get_theoretical_moves_from(meta, board, from_idx)
|
|||||||
can_capture = true
|
can_capture = true
|
||||||
else
|
else
|
||||||
-- en passant
|
-- en passant
|
||||||
if can_capture_en_passant(meta, "black", xy_to_index(to_x, from_y)) then
|
if can_capture_en_passant(board, "black", xy_to_index(to_x, from_y), prevDoublePawnStepTo) then
|
||||||
can_capture = true
|
can_capture = true
|
||||||
en_passant = true
|
en_passant = true
|
||||||
end
|
end
|
||||||
@ -505,7 +504,7 @@ local function get_theoretical_moves_from(meta, board, from_idx)
|
|||||||
can_capture = true
|
can_capture = true
|
||||||
else
|
else
|
||||||
-- en passant
|
-- en passant
|
||||||
if can_capture_en_passant(meta, "white", xy_to_index(to_x, from_y)) then
|
if can_capture_en_passant(board, "white", xy_to_index(to_x, from_y), prevDoublePawnStepTo) then
|
||||||
can_capture = true
|
can_capture = true
|
||||||
en_passant = true
|
en_passant = true
|
||||||
end
|
end
|
||||||
@ -783,11 +782,10 @@ local function get_theoretical_moves_from(meta, board, from_idx)
|
|||||||
|
|
||||||
-- KING
|
-- KING
|
||||||
elseif piece == "king" then
|
elseif piece == "king" then
|
||||||
local inv = meta:get_inventory()
|
|
||||||
-- King can't move to any attacked square
|
-- King can't move to any attacked square
|
||||||
-- king_board simulates the board with the king moved already.
|
-- king_board simulates the board with the king moved already.
|
||||||
-- Required for the attacked() check to work
|
-- Required for the attacked() check to work
|
||||||
local king_board = realchess.board_to_table(inv)
|
local king_board = table.copy(board)
|
||||||
king_board[to_idx] = king_board[from_idx]
|
king_board[to_idx] = king_board[from_idx]
|
||||||
king_board[from_idx] = ""
|
king_board[from_idx] = ""
|
||||||
if realchess.attacked(color, to_idx, king_board) then
|
if realchess.attacked(color, to_idx, king_board) then
|
||||||
@ -805,7 +803,7 @@ local function get_theoretical_moves_from(meta, board, from_idx)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if dx > 1 or dy > 1 then
|
if dx > 1 or dy > 1 then
|
||||||
local cc = can_castle(meta, board, "board", from_idx, to_idx)
|
local cc = can_castle(board, from_idx, to_idx, castlingRights)
|
||||||
if not cc then
|
if not cc then
|
||||||
moves[to_idx] = nil
|
moves[to_idx] = nil
|
||||||
end
|
end
|
||||||
@ -847,10 +845,10 @@ end
|
|||||||
-- origin_index is the board index for the square to start the piece from (as string)
|
-- origin_index is the board index for the square to start the piece from (as string)
|
||||||
-- and this is the key for a list of destination indixes.
|
-- and this is the key for a list of destination indixes.
|
||||||
-- r1, r2, r3 ... are numeric values (normally 0) to "rate" this square for the bot.
|
-- r1, r2, r3 ... are numeric values (normally 0) to "rate" this square for the bot.
|
||||||
function realchess.get_theoretical_moves_for(meta, board, player)
|
function realchess.get_theoretical_moves_for(board, player, prevDoublePawnStepTo, castlingRights)
|
||||||
local moves = {}
|
local moves = {}
|
||||||
for i = 1, 64 do
|
for i = 1, 64 do
|
||||||
local possibleMoves = get_theoretical_moves_from(meta, board, i)
|
local possibleMoves = get_theoretical_moves_from(board, i, prevDoublePawnStepTo, castlingRights)
|
||||||
if next(possibleMoves) then
|
if next(possibleMoves) then
|
||||||
local stack_name = board[i]
|
local stack_name = board[i]
|
||||||
if stack_name:find(player) then
|
if stack_name:find(player) then
|
||||||
@ -1089,7 +1087,11 @@ end
|
|||||||
|
|
||||||
local function get_figurine_id(piece_itemname)
|
local function get_figurine_id(piece_itemname)
|
||||||
local piece_s = piece_itemname:match(":(%w+_%w+)")
|
local piece_s = piece_itemname:match(":(%w+_%w+)")
|
||||||
|
if not piece_s then
|
||||||
|
return MOVES_LIST_SYMBOL_EMPTY
|
||||||
|
else
|
||||||
return figurines_str:match("(%d+)=chess_figurine_" .. piece_s)
|
return figurines_str:match("(%d+)=chess_figurine_" .. piece_s)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -1678,17 +1680,17 @@ local function update_formspec(meta)
|
|||||||
local turnWhite = minetest.colorize("#000001", playerWhiteDisplay)
|
local turnWhite = minetest.colorize("#000001", playerWhiteDisplay)
|
||||||
|
|
||||||
-- several status words for the player
|
-- several status words for the player
|
||||||
-- player is in check
|
--~ Chess: player is in check
|
||||||
local check_s = minetest.colorize("#FF8000", "["..S("check").."]")
|
local check_s = minetest.colorize("#FF8000", "["..S("check").."]")
|
||||||
-- player has been checkmated
|
--~ Chess: player has been checkmated
|
||||||
local mate_s = minetest.colorize("#FF0000", "["..S("checkmate").."]")
|
local mate_s = minetest.colorize("#FF0000", "["..S("checkmate").."]")
|
||||||
-- player has resigned
|
--~ Chess: player has resigned
|
||||||
local resign_s = minetest.colorize("#FF0000", "["..S("resigned").."]")
|
local resign_s = minetest.colorize("#FF0000", "["..S("resigned").."]")
|
||||||
-- player has won
|
--~ Chess: player has won
|
||||||
local win_s = minetest.colorize("#26AB2B", "["..S("winner").."]")
|
local win_s = minetest.colorize("#26AB2B", "["..S("winner").."]")
|
||||||
-- player has lost
|
--~ Chess: player has lost
|
||||||
local lose_s = minetest.colorize("#FF0000", "["..S("loser").."]")
|
local lose_s = minetest.colorize("#FF0000", "["..S("loser").."]")
|
||||||
-- player has a draw
|
--~ Chess: player has a draw
|
||||||
local draw_s = minetest.colorize("#FF00FF", "["..S("draw").."]")
|
local draw_s = minetest.colorize("#FF00FF", "["..S("draw").."]")
|
||||||
|
|
||||||
local status_black = ""
|
local status_black = ""
|
||||||
@ -1733,6 +1735,7 @@ local function update_formspec(meta)
|
|||||||
if promotion == "black" then
|
if promotion == "black" then
|
||||||
eaten_img = ""
|
eaten_img = ""
|
||||||
promotion_formstring =
|
promotion_formstring =
|
||||||
|
--~ Chess: Shown when black player can promote a pawn. Space for text is limited.
|
||||||
"label[10.1,6.35;"..FS("PROMOTION\nFOR BLACK!").."]" ..
|
"label[10.1,6.35;"..FS("PROMOTION\nFOR BLACK!").."]" ..
|
||||||
"animated_image[10.05,7.2;2,2;p_img_white;pawn_black_promo_anim.png;5;100]"
|
"animated_image[10.05,7.2;2,2;p_img_white;pawn_black_promo_anim.png;5;100]"
|
||||||
if botColor ~= "black" and botColor ~= "both" then
|
if botColor ~= "black" and botColor ~= "both" then
|
||||||
@ -1748,6 +1751,7 @@ local function update_formspec(meta)
|
|||||||
elseif promotion == "white" then
|
elseif promotion == "white" then
|
||||||
eaten_img = ""
|
eaten_img = ""
|
||||||
promotion_formstring =
|
promotion_formstring =
|
||||||
|
--~ Chess: Shown when white player can promote a pawn. Space for text is limited.
|
||||||
"label[10.1,6.35;"..FS("PROMOTION\nFOR WHITE!").."]" ..
|
"label[10.1,6.35;"..FS("PROMOTION\nFOR WHITE!").."]" ..
|
||||||
"animated_image[10.05,7.2;2,2;p_img_white;pawn_white_promo_anim.png;5;100]"
|
"animated_image[10.05,7.2;2,2;p_img_white;pawn_white_promo_anim.png;5;100]"
|
||||||
if botColor ~= "white" and botColor ~= "both" then
|
if botColor ~= "white" and botColor ~= "both" then
|
||||||
@ -1765,8 +1769,10 @@ local function update_formspec(meta)
|
|||||||
local draw_claim_formstring = ""
|
local draw_claim_formstring = ""
|
||||||
if drawClaim ~= "" and gameResult == "" then
|
if drawClaim ~= "" and gameResult == "" then
|
||||||
if lastMove == "black" or lastMove == "" then
|
if lastMove == "black" or lastMove == "" then
|
||||||
|
--~ Chess: Shown when white player wants to claim a draw. Space for text is limited.
|
||||||
draw_claim_formstring = "label[10.1,6.35;"..FS("DRAW CLAIM\nBY WHITE!").."]"
|
draw_claim_formstring = "label[10.1,6.35;"..FS("DRAW CLAIM\nBY WHITE!").."]"
|
||||||
else
|
else
|
||||||
|
--~ Chess: Shown when black player wants to claim a draw. Space for text is limited.
|
||||||
draw_claim_formstring = "label[10.1,6.35;"..FS("DRAW CLAIM\nBY BLACK!").."]"
|
draw_claim_formstring = "label[10.1,6.35;"..FS("DRAW CLAIM\nBY BLACK!").."]"
|
||||||
end
|
end
|
||||||
if drawClaim == "50_move_rule" then
|
if drawClaim == "50_move_rule" then
|
||||||
@ -1790,6 +1796,7 @@ local function update_formspec(meta)
|
|||||||
|
|
||||||
if playerActionsAvailable and (playerWhite ~= "" and playerBlack ~= "") then
|
if playerActionsAvailable and (playerWhite ~= "" and playerBlack ~= "") then
|
||||||
game_buttons = game_buttons .. "image_button[14.56,9.7;0.8,0.8;chess_resign.png;resign;]" ..
|
game_buttons = game_buttons .. "image_button[14.56,9.7;0.8,0.8;chess_resign.png;resign;]" ..
|
||||||
|
--~ Resign in Chess
|
||||||
"tooltip[resign;"..FS("Resign").."]"
|
"tooltip[resign;"..FS("Resign").."]"
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1810,12 +1817,14 @@ local function update_formspec(meta)
|
|||||||
-- Will trigger "draw claim" mode in which player must do the final move that triggers the draw
|
-- Will trigger "draw claim" mode in which player must do the final move that triggers the draw
|
||||||
game_buttons = game_buttons .. "image_button[13.36,9.7;0.8,0.8;chess_draw_50move_next.png;draw_50_moves;]"..
|
game_buttons = game_buttons .. "image_button[13.36,9.7;0.8,0.8;chess_draw_50move_next.png;draw_50_moves;]"..
|
||||||
"tooltip[draw_50_moves;"..
|
"tooltip[draw_50_moves;"..
|
||||||
|
--~ Chess
|
||||||
FS("Invoke the 50-move rule for your next move").."]"
|
FS("Invoke the 50-move rule for your next move").."]"
|
||||||
elseif halfmoveClock >= DRAWCLAIM_LONGGAME_PLAYER then
|
elseif halfmoveClock >= DRAWCLAIM_LONGGAME_PLAYER then
|
||||||
-- When the 50 moves without capture / pawn move have occured occur.
|
-- When the 50 moves without capture / pawn move have occured occur.
|
||||||
-- Will insta-draw.
|
-- Will insta-draw.
|
||||||
game_buttons = game_buttons .. "image_button[13.36,9.7;0.8,0.8;chess_draw_50move.png;draw_50_moves;]"..
|
game_buttons = game_buttons .. "image_button[13.36,9.7;0.8,0.8;chess_draw_50move.png;draw_50_moves;]"..
|
||||||
"tooltip[draw_50_moves;"..
|
"tooltip[draw_50_moves;"..
|
||||||
|
--~ Chess
|
||||||
FS("Invoke the 50-move rule and draw the game").."]"
|
FS("Invoke the 50-move rule and draw the game").."]"
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1828,12 +1837,14 @@ local function update_formspec(meta)
|
|||||||
-- Will insta-draw.
|
-- Will insta-draw.
|
||||||
game_buttons = game_buttons .. "image_button[12.36,9.7;0.8,0.8;chess_draw_repeat3.png;draw_repeat_3;]"..
|
game_buttons = game_buttons .. "image_button[12.36,9.7;0.8,0.8;chess_draw_repeat3.png;draw_repeat_3;]"..
|
||||||
"tooltip[draw_repeat_3;"..
|
"tooltip[draw_repeat_3;"..
|
||||||
|
--~ Chess
|
||||||
FS("Invoke the threefold repetition rule and draw the game").."]"
|
FS("Invoke the threefold repetition rule and draw the game").."]"
|
||||||
elseif maxRepeatedPositions >= 2 then
|
elseif maxRepeatedPositions >= 2 then
|
||||||
-- If the same position may be about to occur 3 times.
|
-- If the same position may be about to occur 3 times.
|
||||||
-- Will trigger "draw claim" mode in which player must do the final move that triggers the draw.
|
-- Will trigger "draw claim" mode in which player must do the final move that triggers the draw.
|
||||||
game_buttons = game_buttons .. "image_button[12.36,9.7;0.8,0.8;chess_draw_repeat3_next.png;draw_repeat_3;]"..
|
game_buttons = game_buttons .. "image_button[12.36,9.7;0.8,0.8;chess_draw_repeat3_next.png;draw_repeat_3;]"..
|
||||||
"tooltip[draw_repeat_3;"..
|
"tooltip[draw_repeat_3;"..
|
||||||
|
--~ Chess
|
||||||
FS("Invoke the threefold repetition rule for your next move").."]"
|
FS("Invoke the threefold repetition rule for your next move").."]"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1893,19 +1904,26 @@ local function update_formspec(meta)
|
|||||||
meta:set_string("formspec", formspec)
|
meta:set_string("formspec", formspec)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function update_game_result(meta)
|
local function update_game_result(meta, lastMove)
|
||||||
local inv = meta:get_inventory()
|
local inv = meta:get_inventory()
|
||||||
local board_t = realchess.board_to_table(inv)
|
local board_t = realchess.board_to_table(inv)
|
||||||
|
|
||||||
local playerWhite = meta:get_string("playerWhite")
|
local playerWhite = meta:get_string("playerWhite")
|
||||||
local playerBlack = meta:get_string("playerBlack")
|
local playerBlack = meta:get_string("playerBlack")
|
||||||
|
local prevDoublePawnStepTo = meta:get_int("prevDoublePawnStepTo")
|
||||||
|
local castlingRights = {
|
||||||
|
castlingWhiteR = meta:get_int("castlingWhiteR"),
|
||||||
|
castlingWhiteL = meta:get_int("castlingWhiteL"),
|
||||||
|
castlingBlackR = meta:get_int("castlingBlackR"),
|
||||||
|
castlingBlackL = meta:get_int("castlingBlackL"),
|
||||||
|
}
|
||||||
|
|
||||||
update_formspec(meta)
|
update_formspec(meta)
|
||||||
local blackCanMove = false
|
local blackCanMove = false
|
||||||
local whiteCanMove = false
|
local whiteCanMove = false
|
||||||
|
|
||||||
local blackMoves = realchess.get_theoretical_moves_for(meta, board_t, "black")
|
local blackMoves = realchess.get_theoretical_moves_for(board_t, "black", prevDoublePawnStepTo, castlingRights)
|
||||||
local whiteMoves = realchess.get_theoretical_moves_for(meta, board_t, "white")
|
local whiteMoves = realchess.get_theoretical_moves_for(board_t, "white", prevDoublePawnStepTo, castlingRights)
|
||||||
if next(blackMoves) then
|
if next(blackMoves) then
|
||||||
blackCanMove = true
|
blackCanMove = true
|
||||||
end
|
end
|
||||||
@ -1913,9 +1931,6 @@ local function update_game_result(meta)
|
|||||||
whiteCanMove = true
|
whiteCanMove = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- assume lastMove was updated *after* the player moved
|
|
||||||
local lastMove = meta:get_string("lastMove")
|
|
||||||
|
|
||||||
local black_king_idx, white_king_idx = realchess.locate_kings(board_t)
|
local black_king_idx, white_king_idx = realchess.locate_kings(board_t)
|
||||||
if not black_king_idx or not white_king_idx then
|
if not black_king_idx or not white_king_idx then
|
||||||
minetest.log("error", "[xdecor] Chess: Insufficient kings on chessboard!")
|
minetest.log("error", "[xdecor] Chess: Insufficient kings on chessboard!")
|
||||||
@ -1968,6 +1983,7 @@ local function update_game_result(meta)
|
|||||||
meta:set_string("gameResult", "draw")
|
meta:set_string("gameResult", "draw")
|
||||||
meta:set_string("gameResultReason", "stalemate")
|
meta:set_string("gameResultReason", "stalemate")
|
||||||
add_special_to_moves_list(meta, "draw")
|
add_special_to_moves_list(meta, "draw")
|
||||||
|
--~ Chess message
|
||||||
send_message_2(playerWhite, playerBlack, S("The game ended up in a stalemate! It's a draw!"), botColor)
|
send_message_2(playerWhite, playerBlack, S("The game ended up in a stalemate! It's a draw!"), botColor)
|
||||||
minetest.log("action", "[xdecor] Chess: A game between "..playerWhite.." and "..playerBlack.." ended in a draw by stalemate")
|
minetest.log("action", "[xdecor] Chess: A game between "..playerWhite.." and "..playerBlack.." ended in a draw by stalemate")
|
||||||
return
|
return
|
||||||
@ -1988,6 +2004,7 @@ local function update_game_result(meta)
|
|||||||
meta:set_string("gameResult", "draw")
|
meta:set_string("gameResult", "draw")
|
||||||
meta:set_string("gameResultReason", "stalemate")
|
meta:set_string("gameResultReason", "stalemate")
|
||||||
add_special_to_moves_list(meta, "draw")
|
add_special_to_moves_list(meta, "draw")
|
||||||
|
--~ Chess message
|
||||||
send_message_2(playerWhite, playerBlack, S("The game ended up in a stalemate! It's a draw!"), botColor)
|
send_message_2(playerWhite, playerBlack, S("The game ended up in a stalemate! It's a draw!"), botColor)
|
||||||
minetest.log("action", "[xdecor] Chess: A game between "..playerWhite.." and "..playerBlack.." ended in a draw by stalemate")
|
minetest.log("action", "[xdecor] Chess: A game between "..playerWhite.." and "..playerBlack.." ended in a draw by stalemate")
|
||||||
return
|
return
|
||||||
@ -1999,6 +2016,7 @@ local function update_game_result(meta)
|
|||||||
meta:set_string("gameResult", "draw")
|
meta:set_string("gameResult", "draw")
|
||||||
meta:set_string("gameResultReason", "dead_position")
|
meta:set_string("gameResultReason", "dead_position")
|
||||||
add_special_to_moves_list(meta, "draw")
|
add_special_to_moves_list(meta, "draw")
|
||||||
|
--~ Chess message
|
||||||
send_message_2(playerWhite, playerBlack, S("The game ended up in a dead position! It's a draw!"), botColor)
|
send_message_2(playerWhite, playerBlack, S("The game ended up in a dead position! It's a draw!"), botColor)
|
||||||
minetest.log("action", "[xdecor] Chess: A game between "..playerWhite.." and "..playerBlack.." ended in a draw by dead position")
|
minetest.log("action", "[xdecor] Chess: A game between "..playerWhite.." and "..playerBlack.." ended in a draw by dead position")
|
||||||
end
|
end
|
||||||
@ -2114,6 +2132,7 @@ local function update_game_result(meta)
|
|||||||
meta:set_string("gameResult", "draw")
|
meta:set_string("gameResult", "draw")
|
||||||
meta:set_string("gameResultReason", "same_position_5")
|
meta:set_string("gameResultReason", "same_position_5")
|
||||||
add_special_to_moves_list(meta, "draw")
|
add_special_to_moves_list(meta, "draw")
|
||||||
|
--~ Chess message when the fivefold repetition has happened
|
||||||
local msg = S("The exact same position has occured 5 times. It's a draw!")
|
local msg = S("The exact same position has occured 5 times. It's a draw!")
|
||||||
send_message_2(playerWhite, playerBlack, msg, botColor)
|
send_message_2(playerWhite, playerBlack, msg, botColor)
|
||||||
minetest.log("action", "[xdecor] Chess: A game between "..playerWhite.." and "..playerBlack.." ended in a draw because the same position has appeared 5 times")
|
minetest.log("action", "[xdecor] Chess: A game between "..playerWhite.." and "..playerBlack.." ended in a draw because the same position has appeared 5 times")
|
||||||
@ -2233,6 +2252,7 @@ function realchess.move(meta, from_list, from_index, to_list, to_index, playerNa
|
|||||||
local lastMove = meta:get_string("lastMove")
|
local lastMove = meta:get_string("lastMove")
|
||||||
local playerWhite = meta:get_string("playerWhite")
|
local playerWhite = meta:get_string("playerWhite")
|
||||||
local playerBlack = meta:get_string("playerBlack")
|
local playerBlack = meta:get_string("playerBlack")
|
||||||
|
local prevDoublePawnStepTo = meta:get_int("prevDoublePawnStepTo")
|
||||||
local kingMoved = false
|
local kingMoved = false
|
||||||
local thisMove -- Will replace lastMove when move is legal
|
local thisMove -- Will replace lastMove when move is legal
|
||||||
|
|
||||||
@ -2349,7 +2369,8 @@ function realchess.move(meta, from_list, from_index, to_list, to_index, playerNa
|
|||||||
can_capture = true
|
can_capture = true
|
||||||
else
|
else
|
||||||
-- en passant
|
-- en passant
|
||||||
if can_capture_en_passant(meta, "black", xy_to_index(to_x, from_y)) then
|
local board = realchess.board_to_table(inv)
|
||||||
|
if can_capture_en_passant(board, "black", xy_to_index(to_x, from_y), prevDoublePawnStepTo) then
|
||||||
can_capture = true
|
can_capture = true
|
||||||
en_passant_target = xy_to_index(to_x, from_y)
|
en_passant_target = xy_to_index(to_x, from_y)
|
||||||
end
|
end
|
||||||
@ -2417,7 +2438,8 @@ function realchess.move(meta, from_list, from_index, to_list, to_index, playerNa
|
|||||||
can_capture = true
|
can_capture = true
|
||||||
else
|
else
|
||||||
-- en passant
|
-- en passant
|
||||||
if can_capture_en_passant(meta, "white", xy_to_index(to_x, from_y)) then
|
local board = realchess.board_to_table(inv)
|
||||||
|
if can_capture_en_passant(board, "white", xy_to_index(to_x, from_y), prevDoublePawnStepTo) then
|
||||||
can_capture = true
|
can_capture = true
|
||||||
en_passant_target = xy_to_index(to_x, from_y)
|
en_passant_target = xy_to_index(to_x, from_y)
|
||||||
end
|
end
|
||||||
@ -2669,9 +2691,15 @@ function realchess.move(meta, from_list, from_index, to_list, to_index, playerNa
|
|||||||
local check = true
|
local check = true
|
||||||
local inv = meta:get_inventory()
|
local inv = meta:get_inventory()
|
||||||
local board = realchess.board_to_table(inv)
|
local board = realchess.board_to_table(inv)
|
||||||
|
local castlingRights = {
|
||||||
|
castlingWhiteR = meta:get_int("castlingWhiteR"),
|
||||||
|
castlingWhiteL = meta:get_int("castlingWhiteL"),
|
||||||
|
castlingBlackR = meta:get_int("castlingBlackR"),
|
||||||
|
castlingBlackL = meta:get_int("castlingBlackL"),
|
||||||
|
}
|
||||||
|
|
||||||
-- Castling
|
-- Castling
|
||||||
local cc, rook_start, rook_goal, rook_name = can_castle(meta, board, from_list, from_index, to_index)
|
local cc, rook_start, rook_goal, rook_name = can_castle(board, from_index, to_index, castlingRights)
|
||||||
if cc then
|
if cc then
|
||||||
inv:set_stack(from_list, rook_goal, rook_name)
|
inv:set_stack(from_list, rook_goal, rook_name)
|
||||||
inv:set_stack(from_list, rook_start, "")
|
inv:set_stack(from_list, rook_start, "")
|
||||||
@ -2799,11 +2827,11 @@ local function timeout_format(timeout_limit)
|
|||||||
local seconds = time_remaining % 60
|
local seconds = time_remaining % 60
|
||||||
|
|
||||||
if minutes == 0 then
|
if minutes == 0 then
|
||||||
-- number of seconds
|
--~ number of seconds
|
||||||
return S("@1 s", seconds)
|
return S("@1 s", seconds)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- number of minutes and seconds
|
--~ number of minutes and seconds
|
||||||
return S("@1 min @2 s", minutes, seconds)
|
return S("@1 min @2 s", minutes, seconds)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2885,6 +2913,7 @@ function realchess.fields(pos, _, fields, sender)
|
|||||||
local lastMove = meta:get_string("lastMove")
|
local lastMove = meta:get_string("lastMove")
|
||||||
if (playerName == playerWhite and playerWhite == "") or (playerName == playerBlack and playerBlack == "") then
|
if (playerName == playerWhite and playerWhite == "") or (playerName == playerBlack and playerBlack == "") then
|
||||||
-- Can't resign before the player name has been recorded
|
-- Can't resign before the player name has been recorded
|
||||||
|
--~ Chess message when player tried to resign too early
|
||||||
send_message(playerName, S("Resigning is not possible yet."))
|
send_message(playerName, S("Resigning is not possible yet."))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -3035,9 +3064,11 @@ function realchess.fields(pos, _, fields, sender)
|
|||||||
local pcolor = promo:sub(-5)
|
local pcolor = promo:sub(-5)
|
||||||
local activePromo = meta:get_string("promotionActive")
|
local activePromo = meta:get_string("promotionActive")
|
||||||
if activePromo == "" then
|
if activePromo == "" then
|
||||||
|
--~ Chess message
|
||||||
send_message(playerName, S("This isn't the time for promotion."))
|
send_message(playerName, S("This isn't the time for promotion."))
|
||||||
return
|
return
|
||||||
elseif activePromo ~= pcolor then
|
elseif activePromo ~= pcolor then
|
||||||
|
--~ Chess message
|
||||||
send_message(playerName, S("It's not your turn! This promotion is meant for the other player."))
|
send_message(playerName, S("It's not your turn! This promotion is meant for the other player."))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -3045,6 +3076,7 @@ function realchess.fields(pos, _, fields, sender)
|
|||||||
realchess.promote_pawn(meta, pcolor, promo:sub(1, -7))
|
realchess.promote_pawn(meta, pcolor, promo:sub(1, -7))
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
|
--~ Chess message
|
||||||
send_message(playerName, S("It's not your turn! This promotion is meant for the other player."))
|
send_message(playerName, S("It's not your turn! This promotion is meant for the other player."))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -3111,16 +3143,19 @@ function realchess.move_piece(meta, pieceFrom, from_list, from_index, to_list, t
|
|||||||
add_to_eaten_list(meta, pieceTo)
|
add_to_eaten_list(meta, pieceTo)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local lastMove = meta:get_string("lastMove")
|
||||||
|
if lastMove == "" then lastMove = "black" end
|
||||||
|
|
||||||
local promo = meta:get_string("promotionActive") ~= ""
|
local promo = meta:get_string("promotionActive") ~= ""
|
||||||
if not promo then
|
if not promo then
|
||||||
update_game_result(meta)
|
update_game_result(meta, lastMove)
|
||||||
|
lastMove = meta:get_string("lastMove")
|
||||||
|
if lastMove == "" then lastMove = "black" end
|
||||||
end
|
end
|
||||||
update_formspec(meta)
|
update_formspec(meta)
|
||||||
|
|
||||||
local botColor = meta:get_string("botColor")
|
local botColor = meta:get_string("botColor")
|
||||||
if botColor == "" then botColor = "black" end
|
if botColor == "" then botColor = "black" end
|
||||||
local lastMove = meta:get_string("lastMove")
|
|
||||||
if lastMove == "" then lastMove = "black" end
|
|
||||||
local mode = meta:get_string("mode")
|
local mode = meta:get_string("mode")
|
||||||
local gameResult = meta:get_string("gameResult")
|
local gameResult = meta:get_string("gameResult")
|
||||||
-- Let the bot play when it its turn
|
-- Let the bot play when it its turn
|
||||||
@ -3208,6 +3243,7 @@ function realchess.promote_pawn(meta, color, promoteTo)
|
|||||||
meta:set_int("promotionPawnFromIdx", 0)
|
meta:set_int("promotionPawnFromIdx", 0)
|
||||||
meta:set_int("promotionPawnToIdx", 0)
|
meta:set_int("promotionPawnToIdx", 0)
|
||||||
realchess.update_state(meta, from_idx, to_idx, color, promoteFrom:get_name(), pstr)
|
realchess.update_state(meta, from_idx, to_idx, color, promoteFrom:get_name(), pstr)
|
||||||
|
update_game_result(meta, color)
|
||||||
update_formspec(meta)
|
update_formspec(meta)
|
||||||
|
|
||||||
local botColor = meta:get_string("botColor")
|
local botColor = meta:get_string("botColor")
|
||||||
@ -3270,13 +3306,13 @@ if ENABLE_CHESS_GAMES then
|
|||||||
realchess.move(meta, from_list, from_index, to_list, to_index, playerName)
|
realchess.move(meta, from_list, from_index, to_list, to_index, playerName)
|
||||||
-- We always return 0 to disable all *builtin* inventory moves, since
|
-- We always return 0 to disable all *builtin* inventory moves, since
|
||||||
-- we do it ourselves. This should be fine because there shouldn't be a
|
-- we do it ourselves. This should be fine because there shouldn't be a
|
||||||
-- conflict between this mod and Minetest then.
|
-- conflict between this mod and Luanti then.
|
||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
chessboarddef.allow_metadata_inventory_take = function() return 0 end
|
chessboarddef.allow_metadata_inventory_take = function() return 0 end
|
||||||
chessboarddef.allow_metadata_inventory_put = function() return 0 end
|
chessboarddef.allow_metadata_inventory_put = function() return 0 end
|
||||||
-- Note: There is no on_move function because we put the entire move handling
|
-- Note: There is no on_move function because we put the entire move handling
|
||||||
-- into the allow function above. The reason for this is of Minetest's
|
-- into the allow function above. The reason for this is of Luanti's
|
||||||
-- awkward behavior when swapping items.
|
-- awkward behavior when swapping items.
|
||||||
|
|
||||||
minetest.register_lbm({
|
minetest.register_lbm({
|
||||||
|
120
src/chessbot.lua
@ -36,15 +36,60 @@ local function best_move(moves)
|
|||||||
return tonumber(choice_from), choice_to
|
return tonumber(choice_from), choice_to
|
||||||
end
|
end
|
||||||
|
|
||||||
function chessbot.move(inv, meta)
|
function chessbot.choose_move(board_t, meta_t)
|
||||||
local board_t = realchess.board_to_table(inv)
|
local lastMove = meta_t["lastMove"]
|
||||||
local lastMove = meta:get_string("lastMove")
|
local gameResult = meta_t["gameResult"]
|
||||||
local gameResult = meta:get_string("gameResult")
|
local botColor = meta_t["botColor"]
|
||||||
local botColor = meta:get_string("botColor")
|
local prevDoublePawnStepTo = meta_t["prevDoublePawnStepTo"]
|
||||||
|
local castlingRights = {
|
||||||
|
castlingWhiteR = meta_t["castlingWhiteR"],
|
||||||
|
castlingWhiteL = meta_t["castlingWhiteL"],
|
||||||
|
castlingBlackR = meta_t["castlingBlackR"],
|
||||||
|
castlingBlackL = meta_t["castlingBlackL"],
|
||||||
|
}
|
||||||
|
|
||||||
if botColor == "" then
|
if botColor == "" then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local currentBotColor, opponentColor
|
local currentBotColor, opponentColor
|
||||||
|
if botColor == "black" then
|
||||||
|
currentBotColor = "black"
|
||||||
|
opponentColor = "white"
|
||||||
|
elseif botColor == "white" then
|
||||||
|
currentBotColor = "white"
|
||||||
|
opponentColor = "black"
|
||||||
|
elseif botColor == "both" then
|
||||||
|
opponentColor = lastMove
|
||||||
|
if lastMove == "black" or lastMove == "" then
|
||||||
|
currentBotColor = "white"
|
||||||
|
else
|
||||||
|
currentBotColor = "black"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (lastMove == opponentColor or ((botColor == "white" or botColor == "both") and lastMove == "")) and gameResult == "" then
|
||||||
|
|
||||||
|
local moves = realchess.get_theoretical_moves_for(board_t, currentBotColor, prevDoublePawnStepTo, castlingRights)
|
||||||
|
local safe_moves, safe_moves_count = realchess.get_king_safe_moves(moves, board_t, currentBotColor)
|
||||||
|
if safe_moves_count == 0 then
|
||||||
|
-- No safe move: stalemate or checkmate
|
||||||
|
end
|
||||||
|
local choice_from, choice_to = best_move(safe_moves)
|
||||||
|
if choice_from == nil then
|
||||||
|
-- No best move: stalemate or checkmate
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
return choice_from, choice_to
|
||||||
|
else
|
||||||
|
minetest.log("error", "[xdecor] Chess: chessbot.choose_move was apparently called in an invalid game state!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
chessbot.perform_move = function(choice_from, choice_to, meta)
|
||||||
|
local lastMove = meta:get_string("lastMove")
|
||||||
|
local botColor = meta:get_string("botColor")
|
||||||
|
local currentBotColor, opponentColor
|
||||||
local botName
|
local botName
|
||||||
if botColor == "black" then
|
if botColor == "black" then
|
||||||
currentBotColor = "black"
|
currentBotColor = "black"
|
||||||
@ -60,34 +105,26 @@ function chessbot.move(inv, meta)
|
|||||||
currentBotColor = "black"
|
currentBotColor = "black"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Bot resigns if no move chosen
|
||||||
|
if not choice_from or not choice_to then
|
||||||
|
realchess.resign(meta, currentBotColor)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
if currentBotColor == "white" then
|
if currentBotColor == "white" then
|
||||||
botName = meta:get_string("playerWhite")
|
botName = meta:get_string("playerWhite")
|
||||||
else
|
else
|
||||||
botName = meta:get_string("playerBlack")
|
botName = meta:get_string("playerBlack")
|
||||||
end
|
end
|
||||||
if (lastMove == opponentColor or ((botColor == "white" or botColor == "both") and lastMove == "")) and gameResult == "" then
|
|
||||||
|
|
||||||
local moves = realchess.get_theoretical_moves_for(meta, board_t, currentBotColor)
|
|
||||||
local safe_moves, safe_moves_count = realchess.get_king_safe_moves(moves, board_t, currentBotColor)
|
|
||||||
if safe_moves_count == 0 then
|
|
||||||
-- No safe move: stalemate or checkmate
|
|
||||||
end
|
|
||||||
local choice_from, choice_to = best_move(safe_moves)
|
|
||||||
if choice_from == nil then
|
|
||||||
-- No best move: stalemate or checkmate
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local pieceFrom = inv:get_stack("board", choice_from):get_name()
|
|
||||||
local pieceTo = inv:get_stack("board", choice_to):get_name()
|
|
||||||
|
|
||||||
minetest.after(BOT_DELAY_MOVE, function()
|
|
||||||
local gameResult = meta:get_string("gameResult")
|
local gameResult = meta:get_string("gameResult")
|
||||||
if gameResult ~= "" then
|
if gameResult ~= "" then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local botColor = meta:get_string("botColor")
|
local botColor = meta:get_string("botColor")
|
||||||
if botColor == "" then
|
if botColor == "" then
|
||||||
|
minetest.log("error", "[xdecor] Chess: chessbot.perform_move: botColor in meta string was empty!")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local lastMove = meta:get_string("lastMove")
|
local lastMove = meta:get_string("lastMove")
|
||||||
@ -110,12 +147,17 @@ function chessbot.move(inv, meta)
|
|||||||
if not moveOK then
|
if not moveOK then
|
||||||
realchess.resign(meta, currentBotColor)
|
realchess.resign(meta, currentBotColor)
|
||||||
end
|
end
|
||||||
end
|
else
|
||||||
end)
|
minetest.log("error", "[xdecor] Chess: chessbot.perform_move: No last move!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function chessbot.promote(inv, meta, pawnIndex)
|
function chessbot.choose_promote(board_t, pawnIndex)
|
||||||
|
-- Bot always promotes to queen
|
||||||
|
return "queen"
|
||||||
|
end
|
||||||
|
|
||||||
|
function chessbot.perform_promote(meta, promoteTo)
|
||||||
minetest.after(BOT_DELAY_PROMOTE, function()
|
minetest.after(BOT_DELAY_PROMOTE, function()
|
||||||
local lastMove = meta:get_string("lastMove")
|
local lastMove = meta:get_string("lastMove")
|
||||||
local color
|
local color
|
||||||
@ -124,9 +166,35 @@ function chessbot.promote(inv, meta, pawnIndex)
|
|||||||
else
|
else
|
||||||
color = "black"
|
color = "black"
|
||||||
end
|
end
|
||||||
-- Always promote to queen
|
realchess.promote_pawn(meta, color, promoteTo)
|
||||||
realchess.promote_pawn(meta, color, "queen")
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function chessbot.move(inv, meta)
|
||||||
|
local board_t = realchess.board_to_table(inv)
|
||||||
|
local meta_t = {
|
||||||
|
lastMove = meta:get_string("lastMove"),
|
||||||
|
gameResult = meta:get_string("gameResult"),
|
||||||
|
botColor = meta:get_string("botColor"),
|
||||||
|
prevDoublePawnStepTo = meta:get_int("prevDoublePawnStepTo"),
|
||||||
|
castlingWhiteL = meta:get_int("castlingWhiteL"),
|
||||||
|
castlingWhiteR = meta:get_int("castlingWhiteR"),
|
||||||
|
castlingBlackL = meta:get_int("castlingBlackL"),
|
||||||
|
castlingBlackR = meta:get_int("castlingBlackR"),
|
||||||
|
}
|
||||||
|
local choice_from, choice_to = chessbot.choose_move(board_t, meta_t)
|
||||||
|
minetest.after(BOT_DELAY_MOVE, function()
|
||||||
|
chessbot.perform_move(choice_from, choice_to, meta)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function chessbot.promote(inv, meta, pawnIndex)
|
||||||
|
local board_t = realchess.board_to_table(inv)
|
||||||
|
local promoteTo = chessbot.choose_promote(board_t, pawnIndex)
|
||||||
|
if not promoteTo then
|
||||||
|
promoteTo = "queen"
|
||||||
|
end
|
||||||
|
chessbot.perform_promote(meta, promoteTo)
|
||||||
|
end
|
||||||
|
|
||||||
return chessbot
|
return chessbot
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
local cauldron, sounds = {}, {}
|
local cauldron, sounds = {}, {}
|
||||||
local S = minetest.get_translator("xdecor")
|
local S = minetest.get_translator("xdecor")
|
||||||
|
|
||||||
|
-- Set to true to print soup ingredients and fire nodes to console
|
||||||
|
local DEBUG_RECOGNIZED_ITEMS = false
|
||||||
|
|
||||||
|
--~ cauldron hint
|
||||||
local hint_fire = S("Light a fire below to heat it up")
|
local hint_fire = S("Light a fire below to heat it up")
|
||||||
|
--~ cauldron hint
|
||||||
local hint_eat = S("Use a bowl to eat the soup")
|
local hint_eat = S("Use a bowl to eat the soup")
|
||||||
|
--~ cauldron hint
|
||||||
local hint_recipe = S("Drop foods inside to make a soup")
|
local hint_recipe = S("Drop foods inside to make a soup")
|
||||||
|
|
||||||
local infotexts = {
|
local infotexts = {
|
||||||
@ -21,13 +27,28 @@ local function set_infotext(meta, node)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add more ingredients here that make a soup.
|
-- HACKY list of soup ingredients.
|
||||||
|
-- The cauldron will check if any of these strings are contained in the itemname
|
||||||
|
-- after the ":".
|
||||||
local ingredients_list = {
|
local ingredients_list = {
|
||||||
"apple", "mushroom", "honey", "pumpkin", "egg", "bread", "meat",
|
"apple", "mushroom", "honey", "pumpkin", "egg", "bread", "meat",
|
||||||
"chicken", "carrot", "potato", "melon", "rhubarb", "cucumber",
|
"chicken", "carrot", "potato", "melon", "rhubarb", "cucumber",
|
||||||
"corn", "beans", "berries", "grapes", "tomato", "wheat"
|
"corn", "beans", "berries", "grapes", "tomato", "wheat"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- List of items that can never be soup ingredients. Overwrites anything else.
|
||||||
|
local non_ingredients = {
|
||||||
|
-- xdecor
|
||||||
|
"xdecor:bowl_soup",
|
||||||
|
-- Minetest Game: default
|
||||||
|
"default:apple_mark", "default:blueberry_bush_leaves_with_berries",
|
||||||
|
-- Minetest Game: farming
|
||||||
|
"farming:seed_wheat",
|
||||||
|
"farming:wheat_1", "farming:wheat_2", "farming:wheat_3", "farming:wheat_4",
|
||||||
|
"farming:wheat_5", "farming:wheat_6", "farming:wheat_7", "farming:wheat_8",
|
||||||
|
}
|
||||||
|
local non_ingredients_keyed = table.key_value_swap(non_ingredients)
|
||||||
|
|
||||||
cauldron.cbox = {
|
cauldron.cbox = {
|
||||||
{0, 0, 0, 16, 16, 0},
|
{0, 0, 0, 16, 16, 0},
|
||||||
{0, 0, 16, 16, 16, 0},
|
{0, 0, 16, 16, 16, 0},
|
||||||
@ -36,12 +57,17 @@ cauldron.cbox = {
|
|||||||
{0, 0, 0, 16, 8, 16}
|
{0, 0, 0, 16, 8, 16}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- Returns true is given item is a fire
|
||||||
|
local function is_fire(itemstring)
|
||||||
|
return minetest.get_item_group(itemstring, "fire") ~= 0
|
||||||
|
end
|
||||||
|
|
||||||
-- Returns true if the node at pos is above fire
|
-- Returns true if the node at pos is above fire
|
||||||
local function is_heated(pos)
|
local function is_heated(pos)
|
||||||
local below_node = {x = pos.x, y = pos.y - 1, z = pos.z}
|
local below_node = {x = pos.x, y = pos.y - 1, z = pos.z}
|
||||||
local nn = minetest.get_node(below_node).name
|
local nn = minetest.get_node(below_node).name
|
||||||
-- Check fire group
|
-- Check fire group
|
||||||
if minetest.get_item_group(nn, "fire") ~= 0 then
|
if is_fire(nn) then
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
@ -159,6 +185,23 @@ local function eatable(itemstring)
|
|||||||
return string.format("%q", string.dump(on_use_def)):find("item_eat")
|
return string.format("%q", string.dump(on_use_def)):find("item_eat")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Checks if the given item can be used as ingredient for the soup
|
||||||
|
local function is_ingredient(itemstring)
|
||||||
|
if non_ingredients_keyed[itemstring] then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local basename = itemstring:match(":([%w_]+)")
|
||||||
|
if not basename then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
for _, ingredient in ipairs(ingredients_list) do
|
||||||
|
if eatable(itemstring) or basename:find(ingredient) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
function cauldron.boiling_timer(pos)
|
function cauldron.boiling_timer(pos)
|
||||||
-- Cool down cauldron if there is no fire
|
-- Cool down cauldron if there is no fire
|
||||||
local node = minetest.get_node(pos)
|
local node = minetest.get_node(pos)
|
||||||
@ -192,13 +235,12 @@ function cauldron.boiling_timer(pos)
|
|||||||
for _, obj in pairs(objs) do
|
for _, obj in pairs(objs) do
|
||||||
if obj and not obj:is_player() and obj:get_luaentity().itemstring then
|
if obj and not obj:is_player() and obj:get_luaentity().itemstring then
|
||||||
local itemstring = obj:get_luaentity().itemstring
|
local itemstring = obj:get_luaentity().itemstring
|
||||||
local food = itemstring:match(":([%w_]+)")
|
local item = ItemStack(itemstring)
|
||||||
|
local itemname = item:get_name()
|
||||||
|
|
||||||
for _, ingredient in ipairs(ingredients_list) do
|
if is_ingredient(itemname) then
|
||||||
if food and (eatable(itemstring) or food:find(ingredient)) then
|
local basename = itemstring:match(":([%w_]+)")
|
||||||
ingredients[#ingredients + 1] = food
|
table.insert(ingredients, basename)
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -247,7 +289,7 @@ xdecor.register("cauldron_empty", {
|
|||||||
groups = {cracky=2, oddly_breakable_by_hand=1,cauldron=1},
|
groups = {cracky=2, oddly_breakable_by_hand=1,cauldron=1},
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
on_rotate = screwdriver.rotate_simple,
|
on_rotate = screwdriver.rotate_simple,
|
||||||
tiles = {"xdecor_cauldron_top_empty.png", "xdecor_cauldron_sides.png"},
|
tiles = {"xdecor_cauldron_top_empty.png", "xdecor_cauldron_bottom.png", "xdecor_cauldron_sides.png"},
|
||||||
sounds = default.node_sound_metal_defaults(),
|
sounds = default.node_sound_metal_defaults(),
|
||||||
collision_box = xdecor.pixelbox(16, cauldron.cbox),
|
collision_box = xdecor.pixelbox(16, cauldron.cbox),
|
||||||
on_rightclick = cauldron.filling,
|
on_rightclick = cauldron.filling,
|
||||||
@ -264,7 +306,7 @@ xdecor.register("cauldron_idle", {
|
|||||||
groups = {cracky=2, oddly_breakable_by_hand=1, not_in_creative_inventory=1,cauldron=2},
|
groups = {cracky=2, oddly_breakable_by_hand=1, not_in_creative_inventory=1,cauldron=2},
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
on_rotate = screwdriver.rotate_simple,
|
on_rotate = screwdriver.rotate_simple,
|
||||||
tiles = {"xdecor_cauldron_top_idle.png", "xdecor_cauldron_sides.png"},
|
tiles = {"xdecor_cauldron_top_idle.png", "xdecor_cauldron_bottom.png", "xdecor_cauldron_sides.png"},
|
||||||
sounds = default.node_sound_metal_defaults(),
|
sounds = default.node_sound_metal_defaults(),
|
||||||
drop = "xdecor:cauldron_empty",
|
drop = "xdecor:cauldron_empty",
|
||||||
collision_box = xdecor.pixelbox(16, cauldron.cbox),
|
collision_box = xdecor.pixelbox(16, cauldron.cbox),
|
||||||
@ -278,7 +320,7 @@ xdecor.register("cauldron_idle_river_water", {
|
|||||||
groups = {cracky=2, oddly_breakable_by_hand=1, not_in_creative_inventory=1,cauldron=2},
|
groups = {cracky=2, oddly_breakable_by_hand=1, not_in_creative_inventory=1,cauldron=2},
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
on_rotate = screwdriver.rotate_simple,
|
on_rotate = screwdriver.rotate_simple,
|
||||||
tiles = {"xdecor_cauldron_top_idle_river_water.png", "xdecor_cauldron_sides.png"},
|
tiles = {"xdecor_cauldron_top_idle_river_water.png", "xdecor_cauldron_bottom.png", "xdecor_cauldron_sides.png"},
|
||||||
sounds = default.node_sound_metal_defaults(),
|
sounds = default.node_sound_metal_defaults(),
|
||||||
drop = "xdecor:cauldron_empty",
|
drop = "xdecor:cauldron_empty",
|
||||||
collision_box = xdecor.pixelbox(16, cauldron.cbox),
|
collision_box = xdecor.pixelbox(16, cauldron.cbox),
|
||||||
@ -293,7 +335,7 @@ xdecor.register("cauldron_idle_soup", {
|
|||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
on_rotate = screwdriver.rotate_simple,
|
on_rotate = screwdriver.rotate_simple,
|
||||||
drop = "xdecor:cauldron_empty",
|
drop = "xdecor:cauldron_empty",
|
||||||
tiles = {"xdecor_cauldron_top_idle_soup.png", "xdecor_cauldron_sides.png"},
|
tiles = {"xdecor_cauldron_top_idle_soup.png", "xdecor_cauldron_bottom.png", "xdecor_cauldron_sides.png"},
|
||||||
sounds = default.node_sound_metal_defaults(),
|
sounds = default.node_sound_metal_defaults(),
|
||||||
collision_box = xdecor.pixelbox(16, cauldron.cbox),
|
collision_box = xdecor.pixelbox(16, cauldron.cbox),
|
||||||
on_construct = function(pos)
|
on_construct = function(pos)
|
||||||
@ -320,6 +362,7 @@ xdecor.register("cauldron_boiling", {
|
|||||||
name = "xdecor_cauldron_top_anim_boiling_water.png",
|
name = "xdecor_cauldron_top_anim_boiling_water.png",
|
||||||
animation = {type = "vertical_frames", length = 3.0}
|
animation = {type = "vertical_frames", length = 3.0}
|
||||||
},
|
},
|
||||||
|
"xdecor_cauldron_bottom.png",
|
||||||
"xdecor_cauldron_sides.png"
|
"xdecor_cauldron_sides.png"
|
||||||
},
|
},
|
||||||
sounds = default.node_sound_metal_defaults(),
|
sounds = default.node_sound_metal_defaults(),
|
||||||
@ -344,6 +387,7 @@ xdecor.register("cauldron_boiling_river_water", {
|
|||||||
name = "xdecor_cauldron_top_anim_boiling_river_water.png",
|
name = "xdecor_cauldron_top_anim_boiling_river_water.png",
|
||||||
animation = {type = "vertical_frames", length = 3.0}
|
animation = {type = "vertical_frames", length = 3.0}
|
||||||
},
|
},
|
||||||
|
"xdecor_cauldron_bottom.png",
|
||||||
"xdecor_cauldron_sides.png"
|
"xdecor_cauldron_sides.png"
|
||||||
},
|
},
|
||||||
sounds = default.node_sound_metal_defaults(),
|
sounds = default.node_sound_metal_defaults(),
|
||||||
@ -370,6 +414,7 @@ xdecor.register("cauldron_soup", {
|
|||||||
name = "xdecor_cauldron_top_anim_soup.png",
|
name = "xdecor_cauldron_top_anim_soup.png",
|
||||||
animation = {type = "vertical_frames", length = 3.0}
|
animation = {type = "vertical_frames", length = 3.0}
|
||||||
},
|
},
|
||||||
|
"xdecor_cauldron_bottom.png",
|
||||||
"xdecor_cauldron_sides.png"
|
"xdecor_cauldron_sides.png"
|
||||||
},
|
},
|
||||||
sounds = default.node_sound_metal_defaults(),
|
sounds = default.node_sound_metal_defaults(),
|
||||||
@ -447,3 +492,26 @@ minetest.register_lbm({
|
|||||||
set_infotext(meta, node)
|
set_infotext(meta, node)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if DEBUG_RECOGNIZED_ITEMS then
|
||||||
|
-- Print all soup ingredients and fire nodes
|
||||||
|
-- in console
|
||||||
|
minetest.register_on_mods_loaded(function()
|
||||||
|
local ingredients = {}
|
||||||
|
local fires = {}
|
||||||
|
for k,v in pairs(minetest.registered_items) do
|
||||||
|
if is_ingredient(k) then
|
||||||
|
table.insert(ingredients, k)
|
||||||
|
end
|
||||||
|
if is_fire(k) then
|
||||||
|
table.insert(fires, k)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.sort(ingredients)
|
||||||
|
table.sort(fires)
|
||||||
|
local str_i = table.concat(ingredients, ", ")
|
||||||
|
local str_f = table.concat(fires, ", ")
|
||||||
|
print("[xdecor] List of ingredients for soup: "..str_i)
|
||||||
|
print("[xdecor] List of nodes that can heat cauldron: "..str_f)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
115
src/enchanted_tools.lua
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
-- Register enchanted tools.
|
||||||
|
|
||||||
|
local S = minetest.get_translator("xdecor")
|
||||||
|
|
||||||
|
-- Number of uses for the (normal) steel hoe from Minetest Game (as of 01/12/20224)
|
||||||
|
-- This is technically redundant because we cannot access that number
|
||||||
|
-- directly, but it's unlikely to change in future because Minetest Game is
|
||||||
|
-- unlikely to change.
|
||||||
|
local STEEL_HOE_USES = 500
|
||||||
|
|
||||||
|
-- Modifier of the steel hoe uses for the enchanted steel hoe
|
||||||
|
local STEEL_HOE_USES_MODIFIER = 2.2
|
||||||
|
|
||||||
|
-- Modifier of the bug net uses for the enchanted bug net
|
||||||
|
local BUG_NET_USES_MODIFIER = 4
|
||||||
|
|
||||||
|
-- Multiplies by much faster the fast hammer repairs
|
||||||
|
local HAMMER_FAST_MODIFIER = 1.3
|
||||||
|
|
||||||
|
-- Reduces the wear taken by the hammer for a single repair step
|
||||||
|
-- (absolute value)
|
||||||
|
local HAMMER_DURABLE_MODIFIER = 100
|
||||||
|
|
||||||
|
-- Register enchantments for default tools from Minetest Game
|
||||||
|
local materials = {"steel", "bronze", "mese", "diamond"}
|
||||||
|
local tooltypes = {
|
||||||
|
{ "axe", { "durable", "fast" }, "choppy" },
|
||||||
|
{ "pick", { "durable", "fast" }, "cracky" },
|
||||||
|
{ "shovel", { "durable", "fast" }, "crumbly" },
|
||||||
|
{ "sword", { "sharp" }, nil },
|
||||||
|
}
|
||||||
|
for t=1, #tooltypes do
|
||||||
|
for m=1, #materials do
|
||||||
|
local tooltype = tooltypes[t][1]
|
||||||
|
local enchants = tooltypes[t][2]
|
||||||
|
local dig_group = tooltypes[t][3]
|
||||||
|
local material = materials[m]
|
||||||
|
xdecor.register_enchantable_tool("default:"..tooltype.."_"..material, {
|
||||||
|
enchants = enchants,
|
||||||
|
dig_group = dig_group,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Register enchantment for bug net
|
||||||
|
xdecor.register_enchantable_tool("fireflies:bug_net", {
|
||||||
|
enchants = { "durable" },
|
||||||
|
dig_group = "catchable",
|
||||||
|
bonuses = {
|
||||||
|
uses = BUG_NET_USES_MODIFIER,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Register enchanted steel hoe (more durability)
|
||||||
|
if farming.register_hoe then
|
||||||
|
local percent = math.round((STEEL_HOE_USES_MODIFIER - 1) * 100)
|
||||||
|
local hitem = ItemStack("farming:hoe_steel")
|
||||||
|
local hdesc = hitem:get_short_description() or "farming:hoe_steel"
|
||||||
|
local ehdesc, ehsdesc = xdecor.enchant_description(hdesc, "durable", percent)
|
||||||
|
farming.register_hoe(":farming:enchanted_hoe_steel_durable", {
|
||||||
|
description = ehdesc,
|
||||||
|
short_description = ehsdesc,
|
||||||
|
inventory_image = xdecor.enchant_texture("farming_tool_steelhoe.png"),
|
||||||
|
max_uses = STEEL_HOE_USES * STEEL_HOE_USES_MODIFIER,
|
||||||
|
groups = {hoe = 1, not_in_creative_inventory = 1}
|
||||||
|
})
|
||||||
|
|
||||||
|
xdecor.register_custom_enchantable_tool("farming:hoe_steel", {
|
||||||
|
durable = "farming:enchanted_hoe_steel_durable",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Register enchanted hammer (more durbility and efficiency)
|
||||||
|
local hammerdef = minetest.registered_items["xdecor:hammer"]
|
||||||
|
if hammerdef then
|
||||||
|
local hitem = ItemStack("xdecor:hammer")
|
||||||
|
local hdesc = hitem:get_short_description() or "xdecor:hammer"
|
||||||
|
local repair = hammerdef._xdecor_hammer_repair
|
||||||
|
local repair_cost = hammerdef._xdecor_hammer_repair_cost
|
||||||
|
|
||||||
|
-- Durable hammer (reduces wear taken by each repair step)
|
||||||
|
local d_repair_cost_modified = repair_cost - HAMMER_DURABLE_MODIFIER
|
||||||
|
local d_percent = math.round(100 - d_repair_cost_modified/repair_cost * 100)
|
||||||
|
local d_ehdesc, d_ehsdesc = xdecor.enchant_description(hdesc, "durable", d_percent)
|
||||||
|
|
||||||
|
xdecor.register_hammer("xdecor:enchanted_hammer_durable", {
|
||||||
|
description = d_ehdesc,
|
||||||
|
short_description = d_ehsdesc,
|
||||||
|
image = xdecor.enchant_texture("xdecor_hammer.png"),
|
||||||
|
repair_cost = d_repair_cost_modified,
|
||||||
|
groups = {repair_hammer = 1, not_in_creative_inventory = 1}
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Fast hammer (increases both repair amount and repair cost per
|
||||||
|
-- repair step by an equal amount)
|
||||||
|
local f_repair_modified = math.round(repair * HAMMER_FAST_MODIFIER)
|
||||||
|
local repair_diff = f_repair_modified - repair
|
||||||
|
local f_repair_cost_modified = repair_cost + repair_diff
|
||||||
|
local f_percent = math.round(HAMMER_FAST_MODIFIER * 100 - 100)
|
||||||
|
local f_ehdesc, f_ehsdesc = xdecor.enchant_description(hdesc, "fast", f_percent)
|
||||||
|
|
||||||
|
xdecor.register_hammer("xdecor:enchanted_hammer_fast", {
|
||||||
|
description = f_ehdesc,
|
||||||
|
short_description = f_ehsdesc,
|
||||||
|
image = xdecor.enchant_texture("xdecor_hammer.png"),
|
||||||
|
repair = f_repair_modified,
|
||||||
|
repair_cost = f_repair_cost_modified,
|
||||||
|
groups = {repair_hammer = 1, not_in_creative_inventory = 1}
|
||||||
|
})
|
||||||
|
|
||||||
|
xdecor.register_custom_enchantable_tool("xdecor:hammer", {
|
||||||
|
durable = "xdecor:enchanted_hammer_durable",
|
||||||
|
fast = "xdecor:enchanted_hammer_fast",
|
||||||
|
})
|
||||||
|
end
|
@ -1,69 +1,84 @@
|
|||||||
|
local enchanting = {}
|
||||||
|
|
||||||
screwdriver = screwdriver or {}
|
screwdriver = screwdriver or {}
|
||||||
local S = minetest.get_translator("xdecor")
|
local S = minetest.get_translator("xdecor")
|
||||||
|
local NS = function(s) return s end
|
||||||
local FS = function(...) return minetest.formspec_escape(S(...)) end
|
local FS = function(...) return minetest.formspec_escape(S(...)) end
|
||||||
local ceil, abs, random = math.ceil, math.abs, math.random
|
local ceil, abs, random = math.ceil, math.abs, math.random
|
||||||
local reg_tools = minetest.registered_tools
|
local reg_tools = minetest.registered_tools
|
||||||
|
local reg_enchantable_tools = {}
|
||||||
|
local available_tool_enchants = {}
|
||||||
|
|
||||||
-- Cost in Mese crystal(s) for enchanting.
|
-- Cost in Mese crystal(s) for enchanting.
|
||||||
local mese_cost = 1
|
local MESE_COST = 1
|
||||||
|
|
||||||
-- Force of the enchantments.
|
-- Default strenth of the enchantments
|
||||||
local enchanting = {
|
local DEFAULT_ENCHANTING_USES = 1.2 -- Durability
|
||||||
uses = 1.2, -- Durability
|
local DEFAULT_ENCHANTING_TIMES = 0.1 -- Efficiency
|
||||||
times = 0.1, -- Efficiency
|
local DEFAULT_ENCHANTING_DAMAGES = 1 -- Sharpness
|
||||||
damages = 1, -- Sharpness
|
|
||||||
}
|
|
||||||
|
|
||||||
local function cap(str) return
|
|
||||||
str:gsub("^%l", string.upper)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function to_percent(orig_value, final_value)
|
local function to_percent(orig_value, final_value)
|
||||||
return abs(ceil(((final_value - orig_value) / orig_value) * 100))
|
return abs(ceil(((final_value - orig_value) / orig_value) * 100))
|
||||||
end
|
end
|
||||||
|
|
||||||
function enchanting:get_tooltip(enchant, orig_caps, fleshy)
|
function enchanting:get_tooltip_raw(enchant, percent)
|
||||||
|
local specs = {
|
||||||
|
durable = "#00baff",
|
||||||
|
fast = "#74ff49",
|
||||||
|
sharp = "#ffff00",
|
||||||
|
}
|
||||||
|
local enchant_loc = {
|
||||||
|
--~ Enchantment
|
||||||
|
fast = S("Efficiency"),
|
||||||
|
--~ Enchantment
|
||||||
|
durable = S("Durability"),
|
||||||
|
--~ Enchantment
|
||||||
|
sharp = S("Sharpness"),
|
||||||
|
}
|
||||||
|
|
||||||
|
if minetest.colorize then
|
||||||
|
--~ Tooltip in format "<enchantment name> (+<bonus>%)", e.g. "Efficiency (+5%)"
|
||||||
|
return minetest.colorize(specs[enchant], S("@1 (+@2%)", enchant_loc[enchant], percent))
|
||||||
|
else
|
||||||
|
return S("@1 (+@2%)", enchant_loc[enchant], percent)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function enchanting:get_tooltip(enchant, orig_caps, fleshy, bonus_defs)
|
||||||
local bonus = {durable = 0, efficiency = 0, damages = 0}
|
local bonus = {durable = 0, efficiency = 0, damages = 0}
|
||||||
|
|
||||||
if orig_caps then
|
if orig_caps then
|
||||||
bonus.durable = to_percent(orig_caps.uses, orig_caps.uses * enchanting.uses)
|
bonus.durable = to_percent(orig_caps.uses, orig_caps.uses * bonus_defs.uses)
|
||||||
local sum_caps_times = 0
|
local sum_caps_times = 0
|
||||||
for i=1, #orig_caps.times do
|
for i=1, #orig_caps.times do
|
||||||
sum_caps_times = sum_caps_times + orig_caps.times[i]
|
sum_caps_times = sum_caps_times + orig_caps.times[i]
|
||||||
end
|
end
|
||||||
local average_caps_time = sum_caps_times / #orig_caps.times
|
local average_caps_time = sum_caps_times / #orig_caps.times
|
||||||
bonus.efficiency = to_percent(average_caps_time, average_caps_time -
|
bonus.efficiency = to_percent(average_caps_time, average_caps_time -
|
||||||
enchanting.times)
|
bonus_defs.times)
|
||||||
end
|
end
|
||||||
|
|
||||||
if fleshy then
|
if fleshy then
|
||||||
bonus.damages = to_percent(fleshy, fleshy + enchanting.damages)
|
bonus.damages = to_percent(fleshy, fleshy + bonus_defs.damages)
|
||||||
end
|
end
|
||||||
|
|
||||||
local specs = { -- not finished, to complete
|
local specs = {
|
||||||
durable = {"#00baff", " (+" .. bonus.durable .. "%)"},
|
durable = bonus.durable,
|
||||||
fast = {"#74ff49", " (+" .. bonus.efficiency .. "%)"},
|
fast = bonus.efficiency,
|
||||||
sharp = {"#ffff00", " (+" .. bonus.damages .. "%)"},
|
sharp = bonus.damages,
|
||||||
}
|
}
|
||||||
|
local percent = specs[enchant]
|
||||||
local enchant_loc = {
|
return enchanting:get_tooltip_raw(enchant, percent)
|
||||||
fast = S("Efficiency"),
|
|
||||||
durable = S("Durability"),
|
|
||||||
sharp = S("Sharpness"),
|
|
||||||
}
|
|
||||||
|
|
||||||
return minetest.colorize and minetest.colorize(specs[enchant][1],
|
|
||||||
enchant_loc[enchant] .. specs[enchant][2]) or
|
|
||||||
enchant_loc[enchant] .. specs[enchant][2]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local enchant_buttons = {
|
local enchant_buttons = {
|
||||||
"image_button[3.6,0.67;4.75,0.85;bg_btn.png;fast;"..FS("Efficiency").."]" ..
|
fast = "image_button[3.6,0.67;4.75,0.85;bg_btn.png;fast;"..FS("Efficiency").."]",
|
||||||
"image_button[3.6,1.65;4.75,1.05;bg_btn.png;durable;"..FS("Durability").."]",
|
durable = "image_button[3.6,1.65;4.75,1.05;bg_btn.png;durable;"..FS("Durability").."]",
|
||||||
"image_button[3.6,2.8;4.75,0.85;bg_btn.png;sharp;"..FS("Sharpness").."]",
|
sharp = "image_button[3.6,2.8;4.75,0.85;bg_btn.png;sharp;"..FS("Sharpness").."]",
|
||||||
}
|
}
|
||||||
|
|
||||||
function enchanting.formspec(pos, num)
|
function enchanting.formspec(pos, enchants)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
local formspec = [[
|
local formspec = [[
|
||||||
size[9,8.6;]
|
size[9,8.6;]
|
||||||
@ -80,27 +95,28 @@ function enchanting.formspec(pos, num)
|
|||||||
listring[context;mese]
|
listring[context;mese]
|
||||||
image[2,2.9;1,1;mese_layout.png]
|
image[2,2.9;1,1;mese_layout.png]
|
||||||
]]
|
]]
|
||||||
.."tooltip[sharp;"..FS("Your weapon inflicts more damages").."]"
|
--~ Sharpness enchantment
|
||||||
.."tooltip[durable;"..FS("Your tool last longer").."]"
|
.."tooltip[sharp;"..FS("Your weapon inflicts more damage").."]"
|
||||||
|
--~ Durability enchantment
|
||||||
|
.."tooltip[durable;"..FS("Your tool lasts longer").."]"
|
||||||
|
--~ Efficiency enchantment
|
||||||
.."tooltip[fast;"..FS("Your tool digs faster").."]"
|
.."tooltip[fast;"..FS("Your tool digs faster").."]"
|
||||||
..default.gui_slots .. default.get_hotbar_bg(0.55, 4.5)
|
..default.gui_slots .. default.get_hotbar_bg(0.55, 4.5)
|
||||||
|
|
||||||
formspec = formspec .. (enchant_buttons[num] or "")
|
if enchants then
|
||||||
|
for e=1, #enchants do
|
||||||
|
formspec = formspec .. enchant_buttons[enchants[e]]
|
||||||
|
end
|
||||||
|
end
|
||||||
meta:set_string("formspec", formspec)
|
meta:set_string("formspec", formspec)
|
||||||
end
|
end
|
||||||
|
|
||||||
function enchanting.on_put(pos, listname, _, stack)
|
function enchanting.on_put(pos, listname, _, stack)
|
||||||
if listname == "tool" then
|
if listname == "tool" then
|
||||||
local stackname = stack:get_name()
|
local stackname = stack:get_name()
|
||||||
local tool_groups = {
|
local enchants = available_tool_enchants[stackname]
|
||||||
"axe, pick, shovel",
|
if enchants then
|
||||||
"sword",
|
enchanting.formspec(pos, enchants)
|
||||||
}
|
|
||||||
|
|
||||||
for idx, tools in ipairs(tool_groups) do
|
|
||||||
if tools:find(stackname:match(":(%w+)")) then
|
|
||||||
enchanting.formspec(pos, idx)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -114,7 +130,7 @@ function enchanting.fields(pos, _, fields, sender)
|
|||||||
local mod, name = tool:get_name():match("(.*):(.*)")
|
local mod, name = tool:get_name():match("(.*):(.*)")
|
||||||
local enchanted_tool = (mod or "") .. ":enchanted_" .. (name or "") .. "_" .. next(fields)
|
local enchanted_tool = (mod or "") .. ":enchanted_" .. (name or "") .. "_" .. next(fields)
|
||||||
|
|
||||||
if mese:get_count() >= mese_cost and reg_tools[enchanted_tool] then
|
if mese:get_count() >= MESE_COST and reg_tools[enchanted_tool] then
|
||||||
minetest.sound_play("xdecor_enchanting", {
|
minetest.sound_play("xdecor_enchanting", {
|
||||||
to_player = sender:get_player_name(),
|
to_player = sender:get_player_name(),
|
||||||
gain = 0.8
|
gain = 0.8
|
||||||
@ -122,7 +138,7 @@ function enchanting.fields(pos, _, fields, sender)
|
|||||||
|
|
||||||
tool:replace(enchanted_tool)
|
tool:replace(enchanted_tool)
|
||||||
tool:add_wear(orig_wear)
|
tool:add_wear(orig_wear)
|
||||||
mese:take_item(mese_cost)
|
mese:take_item(MESE_COST)
|
||||||
inv:set_stack("mese", 1, mese)
|
inv:set_stack("mese", 1, mese)
|
||||||
inv:set_stack("tool", 1, tool)
|
inv:set_stack("tool", 1, tool)
|
||||||
end
|
end
|
||||||
@ -140,12 +156,13 @@ function enchanting.blast(pos)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function allowed(tool)
|
local function allowed(tool)
|
||||||
if not tool then return end
|
if not tool then
|
||||||
|
return false
|
||||||
for item in pairs(reg_tools) do
|
|
||||||
if item:find("enchanted_" .. tool) then
|
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
|
if reg_enchantable_tools[tool] then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -154,7 +171,7 @@ function enchanting.put(_, listname, _, stack)
|
|||||||
if listname == "mese" and (stackname == "default:mese_crystal" or
|
if listname == "mese" and (stackname == "default:mese_crystal" or
|
||||||
stackname == "imese:industrial_mese_crystal") then
|
stackname == "imese:industrial_mese_crystal") then
|
||||||
return stack:get_count()
|
return stack:get_count()
|
||||||
elseif listname == "tool" and allowed(stackname:match("[^:]+$")) then
|
elseif listname == "tool" and allowed(stackname) then
|
||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -248,6 +265,7 @@ xdecor.register("enchantment_table", {
|
|||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_entity("xdecor:book_open", {
|
minetest.register_entity("xdecor:book_open", {
|
||||||
|
initial_properties = {
|
||||||
visual = "sprite",
|
visual = "sprite",
|
||||||
visual_size = {x=0.75, y=0.75},
|
visual_size = {x=0.75, y=0.75},
|
||||||
collisionbox = {0,0,0,0,0,0},
|
collisionbox = {0,0,0,0,0,0},
|
||||||
@ -255,6 +273,7 @@ minetest.register_entity("xdecor:book_open", {
|
|||||||
physical = false,
|
physical = false,
|
||||||
textures = {"xdecor_book_open.png"},
|
textures = {"xdecor_book_open.png"},
|
||||||
static_save = false,
|
static_save = false,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_lbm({
|
minetest.register_lbm({
|
||||||
@ -276,65 +295,112 @@ minetest.register_lbm({
|
|||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
function enchanting:register_tools(mod, def)
|
function enchanting:enchant_texture(img)
|
||||||
for tool in pairs(def.tools) do
|
if img == nil or img == "" or type(img) ~= "string" then
|
||||||
for material in def.materials:gmatch("[%w_]+") do
|
return "no_texture.png"
|
||||||
for enchant in def.tools[tool].enchants:gmatch("[%w_]+") do
|
else
|
||||||
local original_tool = reg_tools[mod .. ":" .. tool .. "_" .. material]
|
return "("..img.. ")^[colorize:violet:50"
|
||||||
if not original_tool then break end
|
end
|
||||||
local original_toolcaps = original_tool.tool_capabilities
|
end
|
||||||
|
|
||||||
if original_toolcaps then
|
function enchanting:register_tool(original_tool_name, def)
|
||||||
|
local original_tool = reg_tools[original_tool_name]
|
||||||
|
if not original_tool then
|
||||||
|
minetest.log("error", "[xdecor] Called enchanting:register_tool for non-existing tool: "..original_too_name)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local original_toolcaps = original_tool.tool_capabilities
|
||||||
|
if not original_toolcaps then
|
||||||
|
minetest.log("error", "[xdecor] Called enchanting:register_tool for tool without tool_capabilities: "..original_too_name)
|
||||||
|
return
|
||||||
|
end
|
||||||
local original_damage_groups = original_toolcaps.damage_groups
|
local original_damage_groups = original_toolcaps.damage_groups
|
||||||
local original_groupcaps = original_toolcaps.groupcaps
|
local original_groupcaps = original_toolcaps.groupcaps
|
||||||
|
local original_basename = original_tool_name:match(".*:(.*)")
|
||||||
|
local toolitem = ItemStack(original_tool_name)
|
||||||
|
local original_desc = toolitem:get_short_description() or original_tool_name
|
||||||
|
local groups
|
||||||
|
if def.groups then
|
||||||
|
groups = table.copy(def.groups)
|
||||||
|
elseif original_tool.groups then
|
||||||
|
groups = table.copy(original_tool.groups)
|
||||||
|
else
|
||||||
|
groups = {}
|
||||||
|
end
|
||||||
|
groups.not_in_creative_inventory = 1
|
||||||
|
for _, enchant in ipairs(def.enchants) do
|
||||||
local groupcaps = table.copy(original_groupcaps)
|
local groupcaps = table.copy(original_groupcaps)
|
||||||
local fleshy = original_damage_groups.fleshy
|
|
||||||
local full_punch_interval = original_toolcaps.full_punch_interval
|
local full_punch_interval = original_toolcaps.full_punch_interval
|
||||||
local max_drop_level = original_toolcaps.max_drop_level
|
local max_drop_level = original_toolcaps.max_drop_level
|
||||||
local group = next(original_groupcaps)
|
local dig_group = def.dig_group
|
||||||
|
local fleshy
|
||||||
|
|
||||||
|
if not def.bonuses then
|
||||||
|
def.bonuses = {}
|
||||||
|
end
|
||||||
|
local bonus_defs = {
|
||||||
|
uses = def.bonuses.uses or DEFAULT_ENCHANTING_USES,
|
||||||
|
times = def.bonuses.times or DEFAULT_ENCHANTING_TIMES,
|
||||||
|
damages = def.bonuses.damages or DEFAULT_ENCHANTING_DAMAGES,
|
||||||
|
}
|
||||||
|
|
||||||
if enchant == "durable" then
|
if enchant == "durable" then
|
||||||
groupcaps[group].uses = ceil(original_groupcaps[group].uses *
|
groupcaps[dig_group].uses = ceil(original_groupcaps[dig_group].uses *
|
||||||
enchanting.uses)
|
bonus_defs.uses)
|
||||||
elseif enchant == "fast" then
|
elseif enchant == "fast" then
|
||||||
for i, time in pairs(original_groupcaps[group].times) do
|
for i, time in pairs(original_groupcaps[dig_group].times) do
|
||||||
groupcaps[group].times[i] = time - enchanting.times
|
groupcaps[dig_group].times[i] = time - bonus_defs.times
|
||||||
end
|
end
|
||||||
elseif enchant == "sharp" then
|
elseif enchant == "sharp" then
|
||||||
fleshy = fleshy + enchanting.damages
|
fleshy = original_damage_groups.fleshy
|
||||||
|
fleshy = fleshy + bonus_defs.damages
|
||||||
|
else
|
||||||
|
minetest.log("error", "[xdecor] Called enchanting:register_tool with unsupported enchant: "..tostring(enchant))
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local arg1 = def.material_desc[material] or cap(material)
|
local arg1 = original_desc
|
||||||
local arg2 = def.tools[tool].desc or cap(tool)
|
local arg2 = self:get_tooltip(enchant, original_groupcaps[dig_group], fleshy, bonus_defs)
|
||||||
local arg3 = self:get_tooltip(enchant, original_groupcaps[group], fleshy)
|
local enchantedTool = original_tool.mod_origin .. ":enchanted_" .. original_basename .. "_" .. enchant
|
||||||
minetest.register_tool(":" .. mod .. ":enchanted_" .. tool .. "_" .. material .. "_" .. enchant, {
|
|
||||||
description = S("Enchanted @1 @2\n@3", arg1, arg2, arg3),
|
local invimg = original_tool.inventory_image
|
||||||
short_description = S("Enchanted @1 @2", arg1, arg2),
|
invimg = enchanting:enchant_texture(invimg)
|
||||||
inventory_image = original_tool.inventory_image .. "^[colorize:violet:50",
|
local wieldimg = original_tool.wield_image
|
||||||
wield_image = original_tool.wield_image,
|
if wieldimg == nil or wieldimg == "" then
|
||||||
groups = {not_in_creative_inventory = 1},
|
wieldimg = invimg
|
||||||
|
end
|
||||||
|
minetest.register_tool(":" .. enchantedTool, {
|
||||||
|
--~ Enchanted tool description, e.g. "Enchanted Diamond Sword". @1 is the original tool name, @2 is the enchantment text, e.g. "Durability (+20%)"
|
||||||
|
description = S("Enchanted @1\n@2", arg1, arg2),
|
||||||
|
--~ Enchanted tool description, e.g. "Enchanted Diamond Sword"
|
||||||
|
short_description = S("Enchanted @1", arg1),
|
||||||
|
inventory_image = invimg,
|
||||||
|
wield_image = wieldimg,
|
||||||
|
groups = groups,
|
||||||
tool_capabilities = {
|
tool_capabilities = {
|
||||||
groupcaps = groupcaps, damage_groups = {fleshy = fleshy},
|
groupcaps = groupcaps, damage_groups = {fleshy = fleshy},
|
||||||
full_punch_interval = full_punch_interval,
|
full_punch_interval = full_punch_interval,
|
||||||
max_drop_level = max_drop_level
|
max_drop_level = max_drop_level
|
||||||
}
|
},
|
||||||
|
pointabilities = original_tool.pointabilities,
|
||||||
})
|
})
|
||||||
|
if minetest.get_modpath("toolranks") then
|
||||||
|
toolranks.add_tool(enchantedTool)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
available_tool_enchants[original_tool_name] = table.copy(def.enchants)
|
||||||
end
|
reg_enchantable_tools[original_tool_name] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
enchanting:register_tools("default", {
|
function enchanting:register_custom_tool(original_tool_name, enchanted_tools)
|
||||||
materials = "steel, bronze, mese, diamond",
|
if not available_tool_enchants[original_tool_name] then
|
||||||
material_desc = {steel = S("Steel"), bronze = S("Bronze"), mese = S("Mese"), diamond = S("Diamond")},
|
available_tool_enchants[original_tool_name] = {}
|
||||||
tools = {
|
end
|
||||||
axe = {enchants = "durable, fast", desc = S("Axe")},
|
for enchant, v in pairs(enchanted_tools) do
|
||||||
pick = {enchants = "durable, fast", desc = S("Pickaxe")},
|
table.insert(available_tool_enchants[original_tool_name], enchant)
|
||||||
shovel = {enchants = "durable, fast", desc = S("Shovel")},
|
end
|
||||||
sword = {enchants = "sharp", desc = S("Sword")}
|
reg_enchantable_tools[original_tool_name] = true
|
||||||
},
|
end
|
||||||
})
|
|
||||||
|
|
||||||
-- Recipes
|
-- Recipes
|
||||||
|
|
||||||
@ -346,3 +412,95 @@ minetest.register_craft({
|
|||||||
{"default:obsidian", "default:obsidian", "default:obsidian"}
|
{"default:obsidian", "default:obsidian", "default:obsidian"}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
--[[ API FUNCTIONS ]]
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Register one or more enchantments for an already defined tool.
|
||||||
|
This will register a new tool for each enchantment. The new tools will
|
||||||
|
have the following changes over the original:
|
||||||
|
* New description and short_description
|
||||||
|
* Apply a purple glow on wield_image and inventory_image using
|
||||||
|
"(<original_texture_string>)^[colorize:purple"
|
||||||
|
* Change tool_capabilities and damage_groups, depending on
|
||||||
|
enchantments.
|
||||||
|
* Have groups set to { not_in_creative_inventory = 1 }
|
||||||
|
|
||||||
|
The new tools will follow this naming scheme:
|
||||||
|
|
||||||
|
<original_mod>:enchanted_<original_basename>_<enchantment>
|
||||||
|
|
||||||
|
e.g. example:sword_diamond with the enchantment "sharp" will
|
||||||
|
have "example:enchanted_sword_diamond_sharp" added.
|
||||||
|
|
||||||
|
You must make sure this name is available before calling this
|
||||||
|
function.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
* toolname: Itemstring of original tool to enchant
|
||||||
|
* def: Definition table with the following fields:
|
||||||
|
* enchants: a list of strings, one for each enchantment to add.
|
||||||
|
there must be at least one enchantment.
|
||||||
|
Available enchantments:
|
||||||
|
* "durable": Durability (tool lasts longer)
|
||||||
|
* "fast": Efficiency (tool digs faster)
|
||||||
|
* "sharp": Sharpness (more damage using the damage group "fleshy")
|
||||||
|
* dig_group: Must be specified if Durability or Efficiency is used.
|
||||||
|
This defines the tool's digging group that enchantment will improve.
|
||||||
|
* bonuses: optional table to customize the enchantment "strengths":
|
||||||
|
* uses: multiplies number of uses (Durability) (default: 1.2)
|
||||||
|
* times: subtracts from digging time; higher = faster (Efficiency) (default: 0.1)
|
||||||
|
* damages: adds to damage (Sharpness) (default: 1)
|
||||||
|
* groups: optional table specifying all item groups. If specified,
|
||||||
|
this should at least contain `not_in_creative_inventory=1`.
|
||||||
|
If unspecified (recommended), the enchanted tools will inherit all
|
||||||
|
groups from the original tool, plus they receive `not_in_creative_inventory=1`
|
||||||
|
]]
|
||||||
|
xdecor.register_enchantable_tool = function(toolname, def)
|
||||||
|
enchanting:register_tool(toolname, def)
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[ Registers a custom tool enchantment.
|
||||||
|
Here, you are fully free to design the tool yourself.
|
||||||
|
|
||||||
|
The enchanted tools should follow these guidelines:
|
||||||
|
|
||||||
|
1) Use xdecor.enchant_description to generate the description and short_description
|
||||||
|
2) Use xdecor.enchant_texture to generate the inventory_image and wield_image
|
||||||
|
3) Set groups to { not_in_creative_inventory = 1 }
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
* toolname: Itemstring of original tool to enchant
|
||||||
|
* enchanted_tools: Table of enchanted tools.
|
||||||
|
* The keys are enchantment names from "enchants" in xdecor.register_enchantable_tool
|
||||||
|
* The values are the itemstrings of the enchanted tools for those
|
||||||
|
enchantments
|
||||||
|
]]
|
||||||
|
xdecor.register_custom_enchantable_tool = function(toolname, enchanted_tools)
|
||||||
|
enchanting:register_custom_tool(toolname, enchanted_tools)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Takes a texture (string) and applies an "enchanting" modifier on it.
|
||||||
|
-- Useful when you want to register custom tool enchantments.
|
||||||
|
xdecor.enchant_texture = function(texture)
|
||||||
|
return enchanting:enchant_texture(texture)
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Takes a description of a normal tool and modifies it for the enchanted tool variant.
|
||||||
|
Arguments:
|
||||||
|
* description: Original description to modify
|
||||||
|
* enchant: Enchantment type. One of the enchantment names from "enchants" in xdecor.register_enchantable_tool
|
||||||
|
* percent: Percentage to display
|
||||||
|
|
||||||
|
Returns: <description>, <short_description>
|
||||||
|
|
||||||
|
-- Useful when you want to register custom tool enchantments.
|
||||||
|
]]
|
||||||
|
xdecor.enchant_description = function(description, enchant, percent)
|
||||||
|
local append = enchanting:get_tooltip_raw(enchant, percent)
|
||||||
|
local desc = S("Enchanted @1\n@2", description, append)
|
||||||
|
local short_desc S("Enchanted @1", description)
|
||||||
|
return desc, short_desc
|
||||||
|
end
|
||||||
|
|
||||||
|
@ -121,6 +121,7 @@ end
|
|||||||
|
|
||||||
xdecor.register("hive", {
|
xdecor.register("hive", {
|
||||||
description = S("Artificial Hive"),
|
description = S("Artificial Hive"),
|
||||||
|
--~ Tooltip of artificial hive
|
||||||
_tt_help = S("Bees live here and produce honey"),
|
_tt_help = S("Bees live here and produce honey"),
|
||||||
tiles = {"xdecor_hive_top.png", "xdecor_hive_top.png",
|
tiles = {"xdecor_hive_top.png", "xdecor_hive_top.png",
|
||||||
"xdecor_hive_side.png", "xdecor_hive_side.png",
|
"xdecor_hive_side.png", "xdecor_hive_side.png",
|
||||||
|
@ -73,7 +73,9 @@ function itemframe.set_infotext(meta)
|
|||||||
local owner = meta:get_string("owner")
|
local owner = meta:get_string("owner")
|
||||||
if itemstring == "" then
|
if itemstring == "" then
|
||||||
if owner ~= "" then
|
if owner ~= "" then
|
||||||
meta:set_string("infotext", S("@1 (owned by @2)", S("Item Frame"), owner))
|
--~ Item frame infotext. @1 = item frame name, @2 = owner name (player)
|
||||||
|
meta:set_string("infotext", S("@1 (owned by @2)",
|
||||||
|
S("Item Frame"), owner))
|
||||||
else
|
else
|
||||||
meta:set_string("infotext", S("Item Frame"))
|
meta:set_string("infotext", S("Item Frame"))
|
||||||
end
|
end
|
||||||
@ -158,6 +160,7 @@ end
|
|||||||
|
|
||||||
xdecor.register("itemframe", {
|
xdecor.register("itemframe", {
|
||||||
description = S("Item Frame"),
|
description = S("Item Frame"),
|
||||||
|
--~ Item frame tooltip
|
||||||
_tt_help = S("For presenting a single item"),
|
_tt_help = S("For presenting a single item"),
|
||||||
groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3},
|
groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3},
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
@ -181,12 +184,14 @@ xdecor.register("itemframe", {
|
|||||||
})
|
})
|
||||||
|
|
||||||
minetest.register_entity("xdecor:f_item", {
|
minetest.register_entity("xdecor:f_item", {
|
||||||
|
initial_properties = {
|
||||||
visual = "wielditem",
|
visual = "wielditem",
|
||||||
visual_size = {x = 0.33, y = 0.33},
|
visual_size = {x = 0.33, y = 0.33},
|
||||||
collisionbox = {0,0,0,0,0,0},
|
collisionbox = {0,0,0,0,0,0},
|
||||||
pointable = false,
|
pointable = false,
|
||||||
physical = false,
|
physical = false,
|
||||||
textures = {"air"},
|
textures = {"air"},
|
||||||
|
},
|
||||||
on_activate = function(self, staticdata)
|
on_activate = function(self, staticdata)
|
||||||
local pos = self.object:get_pos()
|
local pos = self.object:get_pos()
|
||||||
if minetest.get_node(pos).name ~= "xdecor:itemframe" then
|
if minetest.get_node(pos).name ~= "xdecor:itemframe" then
|
||||||
|
@ -61,7 +61,7 @@ function mailbox:formspec(pos, owner, is_owner)
|
|||||||
-- List of donors. A line looks like this:
|
-- List of donors. A line looks like this:
|
||||||
-- <donor name> <item icon> × <item count>
|
-- <donor name> <item icon> × <item count>
|
||||||
giver = giver .. "#FFFF00," .. giver_name .. "," .. i ..
|
giver = giver .. "#FFFF00," .. giver_name .. "," .. i ..
|
||||||
-- Times a certain item count; used for the mailbox donor list
|
--~ Used in the mailbox donor list. Will be displayed as item icon followed by this string. @1 = item count
|
||||||
",#FFFFFF," .. FS("× @1", stack_count) .. ","
|
",#FFFFFF," .. FS("× @1", stack_count) .. ","
|
||||||
|
|
||||||
img = img .. i .. "=" ..
|
img = img .. i .. "=" ..
|
||||||
@ -180,6 +180,7 @@ end
|
|||||||
|
|
||||||
xdecor.register("mailbox", {
|
xdecor.register("mailbox", {
|
||||||
description = S("Mailbox"),
|
description = S("Mailbox"),
|
||||||
|
--~ Mailbox tooltip
|
||||||
_tt_help = S("Lets other players give you things"),
|
_tt_help = S("Lets other players give you things"),
|
||||||
tiles = {"xdecor_mailbox_top.png", "xdecor_mailbox_bottom.png",
|
tiles = {"xdecor_mailbox_top.png", "xdecor_mailbox_bottom.png",
|
||||||
"xdecor_mailbox_side.png", "xdecor_mailbox_side.png",
|
"xdecor_mailbox_side.png", "xdecor_mailbox_side.png",
|
||||||
|
@ -57,6 +57,7 @@ end
|
|||||||
function plate.register(material, desc, def)
|
function plate.register(material, desc, def)
|
||||||
xdecor.register("pressure_" .. material .. "_off", {
|
xdecor.register("pressure_" .. material .. "_off", {
|
||||||
description = def.description or (desc .. " Pressure Plate"),
|
description = def.description or (desc .. " Pressure Plate"),
|
||||||
|
--~ Pressure plate tooltip
|
||||||
_tt_help = S("Opens doors when stepped on"),
|
_tt_help = S("Opens doors when stepped on"),
|
||||||
tiles = {"xdecor_pressure_" .. material .. ".png"},
|
tiles = {"xdecor_pressure_" .. material .. ".png"},
|
||||||
use_texture_alpha = ALPHA_OPAQUE,
|
use_texture_alpha = ALPHA_OPAQUE,
|
||||||
@ -98,6 +99,7 @@ plate.register("stone", "Stone", {
|
|||||||
|
|
||||||
xdecor.register("lever_off", {
|
xdecor.register("lever_off", {
|
||||||
description = S("Lever"),
|
description = S("Lever"),
|
||||||
|
--~ Lever tooltip
|
||||||
_tt_help = S("Opens doors when pulled"),
|
_tt_help = S("Opens doors when pulled"),
|
||||||
tiles = {"xdecor_lever_off.png"},
|
tiles = {"xdecor_lever_off.png"},
|
||||||
use_texture_alpha = ALPHA_OPAQUE,
|
use_texture_alpha = ALPHA_OPAQUE,
|
||||||
|
@ -200,7 +200,7 @@ xdecor.register("chair", {
|
|||||||
description = S("Chair"),
|
description = S("Chair"),
|
||||||
tiles = {"xdecor_wood.png"},
|
tiles = {"xdecor_wood.png"},
|
||||||
sounds = default.node_sound_wood_defaults(),
|
sounds = default.node_sound_wood_defaults(),
|
||||||
groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 2},
|
groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 2, sittable = 1},
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
on_rotate = screwdriver.rotate_simple,
|
on_rotate = screwdriver.rotate_simple,
|
||||||
node_box = xdecor.pixelbox(16, {
|
node_box = xdecor.pixelbox(16, {
|
||||||
@ -212,8 +212,8 @@ xdecor.register("chair", {
|
|||||||
{3, 6, 3, 10, 2, 8}
|
{3, 6, 3, 10, 2, 8}
|
||||||
}),
|
}),
|
||||||
can_dig = xdecor.sit_dig,
|
can_dig = xdecor.sit_dig,
|
||||||
|
after_destruct = xdecor.sit_destruct,
|
||||||
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||||
pos.y = pos.y + 0 -- Sitting position
|
|
||||||
xdecor.sit(pos, node, clicker, pointed_thing)
|
xdecor.sit(pos, node, clicker, pointed_thing)
|
||||||
return itemstack
|
return itemstack
|
||||||
end,
|
end,
|
||||||
@ -234,9 +234,11 @@ xdecor.register("cobweb", {
|
|||||||
})
|
})
|
||||||
|
|
||||||
local curtain_colors = {
|
local curtain_colors = {
|
||||||
red = S("Red Curtain"),
|
red = { S("Red Curtain"), "wool_red.png", "wool:red" },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local CURTAIN_OFFSET = 1/16
|
||||||
|
|
||||||
-- For preserve_metadata for curtains.
|
-- For preserve_metadata for curtains.
|
||||||
-- Erases metadata from the drops
|
-- Erases metadata from the drops
|
||||||
-- because the item metadata should be empty
|
-- because the item metadata should be empty
|
||||||
@ -248,20 +250,27 @@ local cleanup_curtain_meta = function(_,_,_,drops)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for c, desc in pairs(curtain_colors) do
|
for c, info in pairs(curtain_colors) do
|
||||||
|
local desc = info[1]
|
||||||
|
local base_texture = info[2]
|
||||||
|
local craft_item = info[3]
|
||||||
xdecor.register("curtain_" .. c, {
|
xdecor.register("curtain_" .. c, {
|
||||||
description = desc,
|
description = desc,
|
||||||
walkable = false,
|
walkable = false,
|
||||||
tiles = {"wool_white.png"},
|
tiles = {base_texture, "("..base_texture..")^[transformFY", base_texture},
|
||||||
color = c,
|
use_texture_alpha = ALPHA_CLIP,
|
||||||
inventory_image = "wool_white.png^[colorize:" .. c ..
|
inventory_image = base_texture.."^xdecor_curtain_open_overlay.png^[makealpha:255,126,126",
|
||||||
":170^xdecor_curtain_open_overlay.png^[makealpha:255,126,126",
|
wield_image = base_texture.."^xdecor_curtain_open_overlay.png^[makealpha:255,126,126",
|
||||||
wield_image = "wool_white.png^[colorize:" .. c .. ":170",
|
drawtype = "nodebox",
|
||||||
drawtype = "signlike",
|
paramtype2 = "wallmounted",
|
||||||
paramtype2 = "colorwallmounted",
|
node_box = {
|
||||||
|
type = "wallmounted",
|
||||||
|
wall_side = { -0.5, -0.5, -0.5, -0.5+CURTAIN_OFFSET, 0.5, 0.5 },
|
||||||
|
wall_top = { -0.5, 0.5-CURTAIN_OFFSET, -0.5, 0.5, 0.5, 0.5 },
|
||||||
|
wall_bottom = { -0.5, -0.5, -0.5, 0.5, -0.5+CURTAIN_OFFSET, 0.5 },
|
||||||
|
},
|
||||||
groups = {dig_immediate = 3, flammable = 3},
|
groups = {dig_immediate = 3, flammable = 3},
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
selection_box = {type = "wallmounted"},
|
|
||||||
on_rightclick = function(pos, node, _, itemstack)
|
on_rightclick = function(pos, node, _, itemstack)
|
||||||
minetest.set_node(pos, {name = "xdecor:curtain_open_" .. c, param2 = node.param2})
|
minetest.set_node(pos, {name = "xdecor:curtain_open_" .. c, param2 = node.param2})
|
||||||
return itemstack
|
return itemstack
|
||||||
@ -269,15 +278,28 @@ for c, desc in pairs(curtain_colors) do
|
|||||||
preserve_metadata = cleanup_curtain_meta,
|
preserve_metadata = cleanup_curtain_meta,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
local open_tile = base_texture.."^xdecor_curtain_open_overlay.png^[makealpha:255,126,126"
|
||||||
xdecor.register("curtain_open_" .. c, {
|
xdecor.register("curtain_open_" .. c, {
|
||||||
tiles = {"wool_white.png^xdecor_curtain_open_overlay.png^[makealpha:255,126,126"},
|
tiles = {
|
||||||
color = c,
|
open_tile,
|
||||||
drawtype = "signlike",
|
"("..open_tile..")^[transformFY",
|
||||||
paramtype2 = "colorwallmounted",
|
base_texture,
|
||||||
|
base_texture,
|
||||||
|
base_texture.."^xdecor_curtain_open_overlay_top.png^[makealpha:255,126,126",
|
||||||
|
base_texture.."^xdecor_curtain_open_overlay_bottom.png^[makealpha:255,126,126",
|
||||||
|
},
|
||||||
|
use_texture_alpha = ALPHA_CLIP,
|
||||||
|
drawtype = "nodebox",
|
||||||
|
paramtype2 = "wallmounted",
|
||||||
|
node_box = {
|
||||||
|
type = "wallmounted",
|
||||||
|
wall_side = { -0.5, -0.5, -0.5, -0.5+CURTAIN_OFFSET, 0.5, 0.5 },
|
||||||
|
wall_top = { -0.5, 0.5-CURTAIN_OFFSET, -0.5, 0.5, 0.5, 0.5 },
|
||||||
|
wall_bottom = { -0.5, -0.5, -0.5, 0.5, -0.5+CURTAIN_OFFSET, 0.5 },
|
||||||
|
},
|
||||||
walkable = false,
|
walkable = false,
|
||||||
groups = {dig_immediate = 3, flammable = 3, not_in_creative_inventory = 1},
|
groups = {dig_immediate = 3, flammable = 3, not_in_creative_inventory = 1},
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
selection_box = {type="wallmounted"},
|
|
||||||
drop = "xdecor:curtain_" .. c,
|
drop = "xdecor:curtain_" .. c,
|
||||||
on_rightclick = function(pos, node, _, itemstack)
|
on_rightclick = function(pos, node, _, itemstack)
|
||||||
minetest.set_node(pos, {name="xdecor:curtain_" .. c, param2 = node.param2})
|
minetest.set_node(pos, {name="xdecor:curtain_" .. c, param2 = node.param2})
|
||||||
@ -289,8 +311,8 @@ for c, desc in pairs(curtain_colors) do
|
|||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
output = "xdecor:curtain_" .. c .. " 4",
|
output = "xdecor:curtain_" .. c .. " 4",
|
||||||
recipe = {
|
recipe = {
|
||||||
{"", "wool:" .. c, ""},
|
{"", craft_item, ""},
|
||||||
{"", "wool:" .. c, ""}
|
{"", craft_item, ""}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
@ -298,13 +320,13 @@ end
|
|||||||
xdecor.register("cushion", {
|
xdecor.register("cushion", {
|
||||||
description = S("Cushion"),
|
description = S("Cushion"),
|
||||||
tiles = {"xdecor_cushion.png"},
|
tiles = {"xdecor_cushion.png"},
|
||||||
groups = {snappy = 3, flammable = 3, fall_damage_add_percent = -50},
|
groups = {snappy = 3, flammable = 3, fall_damage_add_percent = -50, sittable = 1},
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
on_place = minetest.rotate_node,
|
on_place = minetest.rotate_node,
|
||||||
node_box = xdecor.nodebox.slab_y(0.5),
|
node_box = xdecor.nodebox.slab_y(0.5),
|
||||||
can_dig = xdecor.sit_dig,
|
can_dig = xdecor.sit_dig,
|
||||||
|
after_destruct = xdecor.sit_destruct,
|
||||||
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
||||||
pos.y = pos.y + 0 -- Sitting position
|
|
||||||
xdecor.sit(pos, node, clicker, pointed_thing)
|
xdecor.sit(pos, node, clicker, pointed_thing)
|
||||||
return itemstack
|
return itemstack
|
||||||
end
|
end
|
||||||
@ -658,11 +680,12 @@ local painting_box = {
|
|||||||
|
|
||||||
xdecor.register("painting_1", {
|
xdecor.register("painting_1", {
|
||||||
description = S("Painting"),
|
description = S("Painting"),
|
||||||
tiles = {"xdecor_painting_1.png"},
|
tiles = {"xdecor_painting_1.png","xdecor_painting_1.png^[transformR180","xdecor_painting_1.png"},
|
||||||
use_texture_alpha = ALPHA_OPAQUE,
|
use_texture_alpha = ALPHA_OPAQUE,
|
||||||
inventory_image = "xdecor_painting_empty.png",
|
inventory_image = "xdecor_painting_empty.png",
|
||||||
wield_image = "xdecor_painting_empty.png",
|
wield_image = "xdecor_painting_empty.png",
|
||||||
paramtype2 = "wallmounted",
|
paramtype2 = "wallmounted",
|
||||||
|
wallmounted_rotate_vertical = true,
|
||||||
sunlight_propagates = true,
|
sunlight_propagates = true,
|
||||||
groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 2, attached_node = 1},
|
groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 2, attached_node = 1},
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
@ -711,9 +734,10 @@ xdecor.register("painting_1", {
|
|||||||
|
|
||||||
for i = 2, 4 do
|
for i = 2, 4 do
|
||||||
xdecor.register("painting_" .. i, {
|
xdecor.register("painting_" .. i, {
|
||||||
tiles = {"xdecor_painting_" .. i .. ".png"},
|
tiles = {"xdecor_painting_"..i..".png","xdecor_painting_"..i..".png^[transformR180","xdecor_painting_"..i..".png"},
|
||||||
use_texture_alpha = ALPHA_OPAQUE,
|
use_texture_alpha = ALPHA_OPAQUE,
|
||||||
paramtype2 = "wallmounted",
|
paramtype2 = "wallmounted",
|
||||||
|
wallmounted_rotate_vertical = true,
|
||||||
drop = "xdecor:painting_1",
|
drop = "xdecor:painting_1",
|
||||||
sunlight_propagates = true,
|
sunlight_propagates = true,
|
||||||
groups = {
|
groups = {
|
||||||
@ -806,11 +830,26 @@ xdecor.register("tatami", {
|
|||||||
|
|
||||||
xdecor.register("trampoline", {
|
xdecor.register("trampoline", {
|
||||||
description = S("Trampoline"),
|
description = S("Trampoline"),
|
||||||
tiles = {"xdecor_trampoline.png", "mailbox_blank16.png", "xdecor_trampoline_sides.png"},
|
tiles = {"xdecor_trampoline.png", "xdecor_trampoline_bottom.png", "xdecor_trampoline_sides.png"},
|
||||||
use_texture_alpha = ALPHA_CLIP,
|
use_texture_alpha = ALPHA_CLIP,
|
||||||
groups = {cracky = 3, oddly_breakable_by_hand = 1, fall_damage_add_percent = -80, bouncy = 90},
|
groups = {cracky = 3, oddly_breakable_by_hand = 1, fall_damage_add_percent = -80, bouncy = 90},
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
node_box = xdecor.nodebox.slab_y(0.5),
|
node_box = {
|
||||||
|
type = "fixed",
|
||||||
|
fixed = {
|
||||||
|
{ -0.5, -1/16, -0.5, 0.5, 0, 0.5 }, -- bouncy top
|
||||||
|
{ -0.5, -0.5, -0.5, -3/16, 0, -3/16 }, -- leg 1
|
||||||
|
{ 3/16, -0.5, -0.5, 0.5, 0, -3/16 }, -- leg 2
|
||||||
|
{ -0.5, -0.5, 3/16, -3/16, 0, 0.5 }, -- leg 3
|
||||||
|
{ 3/16, -0.5, 3/16, 0.5, 0, 0.5 }, -- leg 4
|
||||||
|
{ -3/16, -5/16, -0.5, 3/16, -1/16, -7/16 }, -- connector 1
|
||||||
|
{ -0.5, -5/16, -3/16, -7/16, -1/16, 3/16 }, -- connector 2
|
||||||
|
{ -3/16, -5/16, 7/16, 3/16, -1/16, 0.5 }, -- connector 3
|
||||||
|
{ 7/16, -5/16, -3/16, 0.5, -1/16, 3/16 }, -- connector 4
|
||||||
|
},
|
||||||
|
},
|
||||||
|
selection_box = xdecor.nodebox.slab_y(0.5),
|
||||||
|
collision_box = xdecor.nodebox.slab_y(0.5),
|
||||||
sounds = default.node_sound_defaults({
|
sounds = default.node_sound_defaults({
|
||||||
footstep = {
|
footstep = {
|
||||||
name = "xdecor_bouncy",
|
name = "xdecor_bouncy",
|
||||||
@ -901,6 +940,7 @@ xdecor.register("woodframed_glass", {
|
|||||||
|
|
||||||
local devices = {
|
local devices = {
|
||||||
{ "radio", S("Radio"), default.node_sound_metal_defaults() },
|
{ "radio", S("Radio"), default.node_sound_metal_defaults() },
|
||||||
|
--~ as in "loudspeaker"
|
||||||
{ "speaker", S("Speaker"), default.node_sound_metal_defaults() },
|
{ "speaker", S("Speaker"), default.node_sound_metal_defaults() },
|
||||||
}
|
}
|
||||||
for _, v in pairs(devices) do
|
for _, v in pairs(devices) do
|
||||||
|
47
src/rope.lua
@ -1,10 +1,16 @@
|
|||||||
local rope = {}
|
local rope = {}
|
||||||
local S = minetest.get_translator("xdecor")
|
local S = minetest.get_translator("xdecor")
|
||||||
|
|
||||||
|
-- Maximum length a rope can extend to
|
||||||
|
local MAX_ROPES = 30
|
||||||
|
|
||||||
local ropesounds = default.node_sound_leaves_defaults()
|
local ropesounds = default.node_sound_leaves_defaults()
|
||||||
|
|
||||||
-- Code by Mirko K. (modified by Temperest, Wulfsdad, kilbith and Wuzzy) (License: GPL).
|
-- Code by Mirko K. (modified by Temperest, Wulfsdad, kilbith and Wuzzy) (License: GPL).
|
||||||
function rope.place(itemstack, placer, pointed_thing)
|
function rope.place(itemstack, placer, pointed_thing)
|
||||||
|
local creative = minetest.is_creative_enabled(placer:get_player_name())
|
||||||
|
local protection_bypass = minetest.check_player_privs(placer, "protection_bypass")
|
||||||
|
local pname = placer:get_player_name()
|
||||||
if pointed_thing.type == "node" then
|
if pointed_thing.type == "node" then
|
||||||
-- Use pointed node's on_rightclick function first, if present
|
-- Use pointed node's on_rightclick function first, if present
|
||||||
if placer and not placer:get_player_control().sneak then
|
if placer and not placer:get_player_control().sneak then
|
||||||
@ -15,32 +21,45 @@ function rope.place(itemstack, placer, pointed_thing)
|
|||||||
end
|
end
|
||||||
local pos = pointed_thing.above
|
local pos = pointed_thing.above
|
||||||
-- Check protection
|
-- Check protection
|
||||||
if minetest.is_protected(pos, placer:get_player_name()) and
|
if minetest.is_protected(pos, pname) and not protection_bypass then
|
||||||
not minetest.check_player_privs(placer, "protection_bypass") then
|
minetest.record_protection_violation(pos, pname)
|
||||||
minetest.record_protection_violation(pos, placer:get_player_name())
|
|
||||||
return itemstack
|
return itemstack
|
||||||
end
|
end
|
||||||
|
|
||||||
local oldnode = minetest.get_node(pos)
|
local oldnode = minetest.get_node(pos)
|
||||||
local stackname = itemstack:get_name()
|
local stackname = itemstack:get_name()
|
||||||
-- Limit max. rope length to max. stack size
|
-- Limit rope length to max. stack size or MAX_ROPES (whatever is smaller).
|
||||||
-- Prevents the rope to extend infinitely in Creative Mode
|
-- Prevents the rope to extend infinitely in Creative Mode.
|
||||||
local max_ropes = itemstack:get_stack_max()
|
local max_ropes = math.min(itemstack:get_stack_max(), MAX_ROPES)
|
||||||
|
|
||||||
|
-- Start placing ropes and extend it downwards until we hit an obstacle,
|
||||||
|
-- run out of ropes or hit the maximum rope length.
|
||||||
local start_pos = table.copy(pos)
|
local start_pos = table.copy(pos)
|
||||||
local ropes_placed = 0
|
local ropes_to_place = 0
|
||||||
while oldnode.name == "air" and not itemstack:is_empty() and ropes_placed < max_ropes do
|
local new_rope_nodes = {}
|
||||||
local newnode = {name = stackname, param1 = 0}
|
while oldnode.name == "air" and (creative or (ropes_to_place < itemstack:get_count())) and ropes_to_place < max_ropes do
|
||||||
minetest.set_node(pos, newnode)
|
-- Stop extending rope into protected area
|
||||||
if not minetest.is_creative_enabled(placer:get_player_name()) then
|
if minetest.is_protected(pos, pname) and not protection_bypass then
|
||||||
itemstack:take_item()
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
|
table.insert(new_rope_nodes, table.copy(pos))
|
||||||
pos.y = pos.y - 1
|
pos.y = pos.y - 1
|
||||||
oldnode = minetest.get_node(pos)
|
oldnode = minetest.get_node(pos)
|
||||||
ropes_placed = ropes_placed + 1
|
ropes_to_place = ropes_to_place + 1
|
||||||
end
|
end
|
||||||
|
local newnode = {name = stackname}
|
||||||
|
if ropes_to_place == 1 then
|
||||||
|
minetest.set_node(new_rope_nodes[1], newnode)
|
||||||
|
else
|
||||||
|
minetest.bulk_set_node(new_rope_nodes, newnode)
|
||||||
|
end
|
||||||
|
if not creative then
|
||||||
|
itemstack:take_item(ropes_to_place)
|
||||||
|
end
|
||||||
|
|
||||||
-- Play placement sound manually
|
-- Play placement sound manually
|
||||||
if ropes_placed > 0 then
|
if ropes_to_place > 0 then
|
||||||
minetest.sound_play(ropesounds.place, {pos=start_pos}, true)
|
minetest.sound_play(ropesounds.place, {pos=start_pos}, true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -7,6 +7,9 @@ local min, ceil = math.min, math.ceil
|
|||||||
local S = minetest.get_translator("xdecor")
|
local S = minetest.get_translator("xdecor")
|
||||||
local FS = function(...) return minetest.formspec_escape(S(...)) end
|
local FS = function(...) return minetest.formspec_escape(S(...)) end
|
||||||
|
|
||||||
|
local DEFAULT_HAMMER_REPAIR = 500
|
||||||
|
local DEFAULT_HAMMER_REPAIR_COST = 700
|
||||||
|
|
||||||
|
|
||||||
-- Nodeboxes definitions
|
-- Nodeboxes definitions
|
||||||
workbench.defs = {
|
workbench.defs = {
|
||||||
@ -35,7 +38,7 @@ end
|
|||||||
|
|
||||||
-- Tools allowed to be repaired
|
-- Tools allowed to be repaired
|
||||||
function workbench:repairable(stack)
|
function workbench:repairable(stack)
|
||||||
-- Explicitly registeded as repairable: Overrides everything else
|
-- Explicitly registered as repairable: Overrides everything else
|
||||||
if custom_repairable[stack] then
|
if custom_repairable[stack] then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@ -109,16 +112,16 @@ function workbench:get_output(inv, input, name)
|
|||||||
inv:set_list("forms", output)
|
inv:set_list("forms", output)
|
||||||
end
|
end
|
||||||
|
|
||||||
function workbench:register_special_cut(nodename, cutlist)
|
local main_fs = ""..
|
||||||
registered_cuttable_nodes[nodename] = true
|
--~ Verb shown in workbench form where you can cut a node
|
||||||
special_cuts[nodename] = cutlist
|
"label[0.9,1.23;"..FS("Cut").."]"
|
||||||
end
|
--~ Verb shown in workbench form where you can repair an item
|
||||||
|
|
||||||
local main_fs = "label[0.9,1.23;"..FS("Cut").."]"
|
|
||||||
.."label[0.9,2.23;"..FS("Repair").."]"
|
.."label[0.9,2.23;"..FS("Repair").."]"
|
||||||
..[[ box[-0.05,1;2.05,0.9;#555555]
|
..[[ box[-0.05,1;2.05,0.9;#555555]
|
||||||
box[-0.05,2;2.05,0.9;#555555] ]]
|
box[-0.05,2;2.05,0.9;#555555] ]]
|
||||||
|
--~ Button in workbench form
|
||||||
.."button[0,0;2,1;craft;"..FS("Crafting").."]"
|
.."button[0,0;2,1;craft;"..FS("Crafting").."]"
|
||||||
|
--~ Button in workbench form
|
||||||
.."button[2,0;2,1;storage;"..FS("Storage").."]"
|
.."button[2,0;2,1;storage;"..FS("Storage").."]"
|
||||||
..[[ image[3,1;1,1;gui_arrow.png]
|
..[[ image[3,1;1,1;gui_arrow.png]
|
||||||
image[0,1;1,1;worktable_saw.png]
|
image[0,1;1,1;worktable_saw.png]
|
||||||
@ -216,9 +219,11 @@ function workbench.timer(pos)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local hammerdef = hammer:get_definition()
|
||||||
|
|
||||||
-- Tool's wearing range: 0-65535; 0 = new condition
|
-- Tool's wearing range: 0-65535; 0 = new condition
|
||||||
tool:add_wear(-500)
|
tool:add_wear(-hammerdef._xdecor_hammer_repair or DEFAULT_HAMMER_REPAIR)
|
||||||
hammer:add_wear(700)
|
hammer:add_wear(hammerdef._xdecor_hammer_repair_cost or DEFAULT_HAMMER_REPAIR_COST)
|
||||||
|
|
||||||
inv:set_stack("tool", 1, tool)
|
inv:set_stack("tool", 1, tool)
|
||||||
inv:set_stack("hammer", 1, hammer)
|
inv:set_stack("hammer", 1, hammer)
|
||||||
@ -230,7 +235,7 @@ function workbench.allow_put(pos, listname, index, stack, player)
|
|||||||
local stackname = stack:get_name()
|
local stackname = stack:get_name()
|
||||||
if (listname == "tool" and workbench:repairable(stackname)) or
|
if (listname == "tool" and workbench:repairable(stackname)) or
|
||||||
(listname == "input" and workbench:cuttable(stackname)) or
|
(listname == "input" and workbench:cuttable(stackname)) or
|
||||||
(listname == "hammer" and stackname == "xdecor:hammer") or
|
(listname == "hammer" and minetest.get_item_group(stackname, "repair_hammer") == 1) or
|
||||||
listname == "storage" then
|
listname == "storage" then
|
||||||
return stack:get_count()
|
return stack:get_count()
|
||||||
end
|
end
|
||||||
@ -255,7 +260,7 @@ function workbench.allow_move(pos, from_list, from_index, to_list, to_index, cou
|
|||||||
elseif (to_list == "hammer" and from_list == "tool") or (to_list == "tool" and from_list == "hammer") then
|
elseif (to_list == "hammer" and from_list == "tool") or (to_list == "tool" and from_list == "hammer") then
|
||||||
local inv = minetest.get_inventory({type="node", pos=pos})
|
local inv = minetest.get_inventory({type="node", pos=pos})
|
||||||
local stack = inv:get_stack(from_list, from_index)
|
local stack = inv:get_stack(from_list, from_index)
|
||||||
if stack:get_name() == "xdecor:hammer" then
|
if minetest.get_item_group(stack:get_name(), "repair_hammer") == 1 then
|
||||||
return count
|
return count
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -310,7 +315,7 @@ xdecor.register("workbench", {
|
|||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
sounds = default.node_sound_wood_defaults(),
|
sounds = default.node_sound_wood_defaults(),
|
||||||
tiles = {
|
tiles = {
|
||||||
"xdecor_workbench_top.png","xdecor_workbench_top.png",
|
"xdecor_workbench_top.png","xdecor_workbench_bottom.png",
|
||||||
"xdecor_workbench_sides.png", "xdecor_workbench_sides.png",
|
"xdecor_workbench_sides.png", "xdecor_workbench_sides.png",
|
||||||
"xdecor_workbench_front.png", "xdecor_workbench_front.png"
|
"xdecor_workbench_front.png", "xdecor_workbench_front.png"
|
||||||
},
|
},
|
||||||
@ -328,29 +333,11 @@ xdecor.register("workbench", {
|
|||||||
allow_metadata_inventory_move = workbench.allow_move
|
allow_metadata_inventory_move = workbench.allow_move
|
||||||
})
|
})
|
||||||
|
|
||||||
|
local function register_cut_raw(node, workbench_def)
|
||||||
minetest.register_on_mods_loaded(function()
|
|
||||||
local cuttable_nodes = {}
|
|
||||||
|
|
||||||
-- Nodes allowed to be cut:
|
|
||||||
-- Only the regular, solid blocks without metas or explosivity
|
|
||||||
-- from the xdecor or default mods.
|
|
||||||
for nodename, def in pairs(minetest.registered_nodes) do
|
|
||||||
local nodenamesplit = string.split(nodename, ":")
|
|
||||||
local modname = nodenamesplit[1]
|
|
||||||
if (modname == "xdecor" or modname == "default") and xdecor.stairs_valid_def(def) then
|
|
||||||
cuttable_nodes[#cuttable_nodes + 1] = nodename
|
|
||||||
registered_cuttable_nodes[nodename] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, d in ipairs(workbench.defs) do
|
|
||||||
for i = 1, #cuttable_nodes do
|
|
||||||
local node = cuttable_nodes[i]
|
|
||||||
local mod_name, item_name = node:match("^(.-):(.*)")
|
local mod_name, item_name = node:match("^(.-):(.*)")
|
||||||
local def = minetest.registered_nodes[node]
|
local def = minetest.registered_nodes[node]
|
||||||
|
|
||||||
if item_name and d[3] then
|
if item_name and workbench_def[3] then
|
||||||
local groups = {}
|
local groups = {}
|
||||||
local tiles
|
local tiles
|
||||||
groups.not_in_creative_inventory = 1
|
groups.not_in_creative_inventory = 1
|
||||||
@ -419,7 +406,7 @@ for i = 1, #cuttable_nodes do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local cutname = d[1]
|
local cutname = workbench_def[1]
|
||||||
local tiles_special_cut
|
local tiles_special_cut
|
||||||
if custom_tiles and custom_tiles[cutname] then
|
if custom_tiles and custom_tiles[cutname] then
|
||||||
tiles_special_cut = custom_tiles[cutname]
|
tiles_special_cut = custom_tiles[cutname]
|
||||||
@ -427,9 +414,14 @@ for i = 1, #cuttable_nodes do
|
|||||||
tiles_special_cut = tiles
|
tiles_special_cut = tiles
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_node(":" .. node .. "_" .. cutname, {
|
local cutnodename = node .. "_" .. cutname
|
||||||
-- @1: Base node description (e.g. "Stone"); @2: modifier (e.g. "Nanoslab")
|
if minetest.registered_nodes[cutnodename] then
|
||||||
description = S("@1 @2", def.description, d[4]),
|
minetest.log("error", "[xdecor] register_cut_raw: Refusing to register node "..cutnodename.." becaut it was already registered!")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
minetest.register_node(":" .. cutnodename, {
|
||||||
|
--~ Format of the description of a cut node. @1: Base node description (e.g. "Stone"); @2: modifier (e.g. "Nanoslab")
|
||||||
|
description = S("@1 @2", def.description, workbench_def[4]),
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
paramtype2 = "facedir",
|
paramtype2 = "facedir",
|
||||||
drawtype = "nodebox",
|
drawtype = "nodebox",
|
||||||
@ -438,7 +430,7 @@ for i = 1, #cuttable_nodes do
|
|||||||
use_texture_alpha = def.use_texture_alpha,
|
use_texture_alpha = def.use_texture_alpha,
|
||||||
groups = groups,
|
groups = groups,
|
||||||
is_ground_content = def.is_ground_content,
|
is_ground_content = def.is_ground_content,
|
||||||
node_box = xdecor.pixelbox(16, d[3]),
|
node_box = xdecor.pixelbox(16, workbench_def[3]),
|
||||||
sunlight_propagates = true,
|
sunlight_propagates = true,
|
||||||
on_place = minetest.rotate_node
|
on_place = minetest.rotate_node
|
||||||
})
|
})
|
||||||
@ -453,32 +445,35 @@ for i = 1, #cuttable_nodes do
|
|||||||
("stairs:stair_outer_%s"):format(item_name)
|
("stairs:stair_outer_%s"):format(item_name)
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- Craft items
|
function workbench:register_cut(nodename, cutlist)
|
||||||
|
if registered_cuttable_nodes[nodename] then
|
||||||
minetest.register_tool("xdecor:hammer", {
|
minetest.log("error", "[xdecor] Workbench: Tried to register cut for node "..node..", but it was already registered!")
|
||||||
description = S("Hammer"),
|
return false
|
||||||
_tt_help = S("Repairs tools at the work bench"),
|
|
||||||
inventory_image = "xdecor_hammer.png",
|
|
||||||
wield_image = "xdecor_hammer.png",
|
|
||||||
on_use = function() do
|
|
||||||
return end
|
|
||||||
end
|
end
|
||||||
})
|
local ok = true
|
||||||
|
for _, d in ipairs(workbench.defs) do
|
||||||
|
local ok = register_cut_raw(nodename, d)
|
||||||
|
if not ok then
|
||||||
|
ok = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
registered_cuttable_nodes[nodename] = true
|
||||||
|
return ok
|
||||||
|
end
|
||||||
|
|
||||||
-- Recipes
|
function workbench:register_special_cut(nodename, cutlist)
|
||||||
|
if registered_cuttable_nodes[nodename] or special_cuts[nodename] then
|
||||||
minetest.register_craft({
|
minetest.log("error", "[xdecor] Workbench: Tried to register special cut for node "..nodename..", but it was already registered!")
|
||||||
output = "xdecor:hammer",
|
return false
|
||||||
recipe = {
|
end
|
||||||
{"default:steel_ingot", "group:stick", "default:steel_ingot"},
|
registered_cuttable_nodes[nodename] = true
|
||||||
{"", "group:stick", ""}
|
special_cuts[nodename] = cutlist
|
||||||
}
|
end
|
||||||
})
|
|
||||||
|
|
||||||
|
-- Workbench craft
|
||||||
minetest.register_craft({
|
minetest.register_craft({
|
||||||
output = "xdecor:workbench",
|
output = "xdecor:workbench",
|
||||||
recipe = {
|
recipe = {
|
||||||
@ -487,6 +482,121 @@ minetest.register_craft({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
-- Register default cuttable blocks
|
||||||
|
do
|
||||||
|
local cuttable_nodes = {}
|
||||||
|
|
||||||
|
-- Nodes allowed to be cut:
|
||||||
|
-- Only the regular, solid blocks without metas or explosivity
|
||||||
|
-- from the xdecor or default mods.
|
||||||
|
for nodename, def in pairs(minetest.registered_nodes) do
|
||||||
|
local nodenamesplit = string.split(nodename, ":")
|
||||||
|
local modname = nodenamesplit[1]
|
||||||
|
if (modname == "xdecor" or modname == "default") and xdecor.stairs_valid_def(def) then
|
||||||
|
cuttable_nodes[#cuttable_nodes + 1] = nodename
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1, #cuttable_nodes do
|
||||||
|
local node = cuttable_nodes[i]
|
||||||
|
workbench:register_cut(node)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Special cuts for cushion block and cabinet
|
-- Special cuts for cushion block and cabinet
|
||||||
workbench:register_special_cut("xdecor:cushion_block", { slab = "xdecor:cushion" })
|
workbench:register_special_cut("xdecor:cushion_block", { slab = "xdecor:cushion" })
|
||||||
workbench:register_special_cut("xdecor:cabinet", { slab = "xdecor:cabinet_half" })
|
workbench:register_special_cut("xdecor:cabinet", { slab = "xdecor:cabinet_half" })
|
||||||
|
|
||||||
|
--[[ API FUNCTIONS ]]
|
||||||
|
|
||||||
|
--[[ Register a custom hammer (for repairing).
|
||||||
|
A hammer repair items at the work bench. The workbench repeatedly
|
||||||
|
checks if a hammer and a repairable tool are in the slots. The hammer
|
||||||
|
will repair the tool in regular intervals. This is called a "step".
|
||||||
|
In each step, the hammer reduces the wear of the repairable
|
||||||
|
tool but increases its own wear, each by a fixed amount.
|
||||||
|
|
||||||
|
This function allows you to register a custom hammer with custom
|
||||||
|
name, item image and wear stats.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
* name: Internal itemname
|
||||||
|
* def: Definition table:
|
||||||
|
* description: Item `description`
|
||||||
|
* image: Inventory image and wield image
|
||||||
|
* groups: Item groups (MUST contain at least `repair_hammer = 1`)
|
||||||
|
* repair: How much item wear the hammer repairs per step
|
||||||
|
* repair_cost: How much item wear the hammer takes itself per step
|
||||||
|
|
||||||
|
Note: Mind the implication of repair_cost! If repair_cost is lower than
|
||||||
|
repair, this means practically infinite durability if you have two
|
||||||
|
hammers that repair each other. If repair_cost is higher than repair,
|
||||||
|
then hammers will break eventually.
|
||||||
|
]]
|
||||||
|
function xdecor.register_hammer(name, def)
|
||||||
|
minetest.register_tool(name, {
|
||||||
|
description = def.description,
|
||||||
|
_tt_help = S("Repairs tools at the work bench"),
|
||||||
|
inventory_image = def.image,
|
||||||
|
wield_image = def.image,
|
||||||
|
on_use = function() do
|
||||||
|
return end
|
||||||
|
end,
|
||||||
|
groups = def.groups,
|
||||||
|
_xdecor_hammer_repair = def.repair or DEFAULT_HAMMER_REPAIR,
|
||||||
|
_xdecor_hammer_repair_cost = def.repair_cost or DEFAULT_HAMMER_REPAIR_COST,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[ EXPERIMENTAL FUNCTION:
|
||||||
|
Registers various 'cut' node variants for the node with the given nodename,
|
||||||
|
which will be available in the workbench.
|
||||||
|
This must only be called once per node. Calling it again is an error.
|
||||||
|
|
||||||
|
The following nodes will be registered:
|
||||||
|
|
||||||
|
* <nodename>_nanoslab
|
||||||
|
* <nodename>_micropanel
|
||||||
|
* <nodename>_microslab
|
||||||
|
* <nodename>_thinstair
|
||||||
|
* <nodename>_cube
|
||||||
|
* <nodename>_panel
|
||||||
|
* <nodename>_doublepanel
|
||||||
|
* <nodename>_halfstair
|
||||||
|
|
||||||
|
You MUST make sure these names are not already taken before
|
||||||
|
calling this function. Failing to do so is an error.
|
||||||
|
|
||||||
|
Additionally, a slab, stair, inner stair and outer stair
|
||||||
|
will be registered by using the `stairs` mod if the slab
|
||||||
|
node does not exist yet. Refer to the `stairs` mod documentation
|
||||||
|
for details.
|
||||||
|
|
||||||
|
Returns true if all nodes were registered successfully,
|
||||||
|
returns false (and writes to error log) if any error occurred.
|
||||||
|
]]
|
||||||
|
xdecor.register_cut = function(nodename)
|
||||||
|
return workbench:register_cut(nodename)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--[[ END OF API FUNCTIONS ]]
|
||||||
|
|
||||||
|
|
||||||
|
-- Register xdecor's built-in hammer
|
||||||
|
xdecor.register_hammer("xdecor:hammer", {
|
||||||
|
description = S("Hammer"),
|
||||||
|
image = "xdecor_hammer.png",
|
||||||
|
groups = { repair_hammer = 1 },
|
||||||
|
repair = DEFAULT_HAMMER_REPAIR,
|
||||||
|
repair_cost = DEFAULT_HAMMER_REPAIR_COST,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Hammer recipes
|
||||||
|
minetest.register_craft({
|
||||||
|
output = "xdecor:hammer",
|
||||||
|
recipe = {
|
||||||
|
{"default:steel_ingot", "group:stick", "default:steel_ingot"},
|
||||||
|
{"", "group:stick", ""}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
BIN
textures/xdecor_cauldron_bottom.png
Normal file
After Width: | Height: | Size: 153 B |
BIN
textures/xdecor_curtain_open_overlay_bottom.png
Normal file
After Width: | Height: | Size: 97 B |
BIN
textures/xdecor_curtain_open_overlay_side.png
Normal file
After Width: | Height: | Size: 107 B |
BIN
textures/xdecor_curtain_open_overlay_top.png
Normal file
After Width: | Height: | Size: 93 B |
Before Width: | Height: | Size: 582 B After Width: | Height: | Size: 785 B |
Before Width: | Height: | Size: 174 B After Width: | Height: | Size: 273 B |
BIN
textures/xdecor_trampoline_bottom.png
Normal file
After Width: | Height: | Size: 237 B |
Before Width: | Height: | Size: 288 B After Width: | Height: | Size: 165 B |
BIN
textures/xdecor_workbench_bottom.png
Normal file
After Width: | Height: | Size: 648 B |