push minetest server

This commit is contained in:
Grégory Lebreton 2025-01-20 12:59:40 +01:00
commit 946e7d9621
590 changed files with 19973 additions and 0 deletions

17
README.md Normal file
View File

@ -0,0 +1,17 @@
# MINETEST SERVER
## PRE REQUIS
- docker
### DEPLOYER LOCALEMENT
```bash
```
### DEPLOYER SUR INTERNET
```bash
```

3497
conf/minetest.conf Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,4 @@
License information for Development Test
----------------------------------------
The same license as for Luanti applies.

View File

@ -0,0 +1,50 @@
# Development Test (devtest)
This is a basic testing environment that contains a bunch of things to test the engine, but it could also be used as a minimal testbed for testing out mods.
## Features
* Basic nodes for mapgen
* Basic, minimal map generator
* Lots of example nodes for testing drawtypes, param2, light level, and many other node properties
* Example entities
* Other example items
* Formspec test (via `/test_formspec` command)
* Automated unit tests (disabled by default)
* Tools for manipulating nodes and entities, like the "Param2 Tool"
## Getting started
Basically, just create a world and start. A few important things to note:
* Items are gotten from the “Chest of Everything” (`chest_of_everything:chest`)
* When you lost your initial items, type in `/stuff` command to get them back
* By default, Creative Mode activates infinite node placement. This behavior can be changed with the `devtest_infplace` setting
* Use the `/infplace` command to toggle infinite node placement in-game
* Use the Param2 Tool to change the param2 of nodes; it's useful to experiment with the various drawtype test nodes
* Check out the game settings and server commands for additional tests and features
Confused by a certain node or item? Check out for inline code comments. The usages of most tools are explained in their tooltips.
### Example tests
* You can use this to test what happens if a player is simultaneously in 2 nodes with `damage_per_second` but with a different value.
* Or use the Falling Node Tool on various test nodes to see how they behave when falling.
* You could also use this as a testbed for dependency-free mods, e.g. to test out how your formspecs behave without theming.
## Random notes
* Textures of drawtype test nodes have a red dot at the top left corner. This is to see whether the textures are oriented properly
## Design philosophy
This should loosely follow the following principles:
* Engine testing: The main focus of this is to aid testing of *engine* features, such as mapgen or node drawtypes
* Mod testing: The secondary focus is to help modders as well, either as a minimal testbed for mods or even as a code example
* Minimal interference: Under default settings, it shall not interfere with APIs except on explicit user wish. Non-trivial tests and features need to be enabled by a setting first
* Convenience: Have various tools to make usage easier and more convenient
* Reproducing engine bugs: When an engine bug was found, consider creating a test case
* Clarity: Textures and names need to be designed to keep different things clearly visually apart at a glance
* Low loading time: It must load blazing-fast so stuff can be tested quickly

View File

@ -0,0 +1,4 @@
title = Development Test
description = Testing environment to help with testing the engine features of Luanti. It can also be helpful in mod development.
first_mod = first_mod
last_mod = last_mod

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 B

View File

@ -0,0 +1,361 @@
local WATER_ALPHA = "^[opacity:" .. 160
local WATER_VISC = 1
local LAVA_VISC = 7
--
-- Node definitions
--
-- Register nodes
core.register_node("basenodes:stone", {
description = "Stone",
tiles = {"default_stone.png"},
groups = {cracky=3},
})
core.register_node("basenodes:desert_stone", {
description = "Desert Stone",
tiles = {"default_desert_stone.png"},
groups = {cracky=3},
})
core.register_node("basenodes:dirt_with_grass", {
description = "Dirt with Grass",
tiles ={"default_grass.png",
-- a little dot on the bottom to distinguish it from dirt
"default_dirt.png^basenodes_dirt_with_grass_bottom.png",
{name = "default_dirt.png^default_grass_side.png",
tileable_vertical = false}},
groups = {crumbly=3, soil=1},
})
core.register_node("basenodes:dirt_with_snow", {
description = "Dirt with Snow",
tiles ={"basenodes_dirt_with_snow.png",
-- a little dot on the bottom to distinguish it from dirt
"default_dirt.png^basenodes_dirt_with_snow_bottom.png",
{name = "default_dirt.png^default_snow_side.png",
tileable_vertical = false}},
groups = {crumbly=3, soil=1},
})
core.register_node("basenodes:dirt", {
description = "Dirt",
tiles ={"default_dirt.png"},
groups = {crumbly=3, soil=1},
})
core.register_node("basenodes:sand", {
description = "Sand",
tiles ={"default_sand.png"},
groups = {crumbly=3},
})
core.register_node("basenodes:desert_sand", {
description = "Desert Sand",
tiles ={"default_desert_sand.png"},
groups = {crumbly=3},
})
core.register_node("basenodes:gravel", {
description = "Gravel",
tiles ={"default_gravel.png"},
groups = {crumbly=2},
})
core.register_node("basenodes:junglegrass", {
description = "Jungle Grass",
drawtype = "plantlike",
tiles ={"default_junglegrass.png"},
inventory_image = "default_junglegrass.png",
wield_image = "default_junglegrass.png",
paramtype = "light",
walkable = false,
groups = {snappy=3},
})
core.register_node("basenodes:tree", {
description = "Normal Tree Trunk",
tiles = {"default_tree_top.png", "default_tree_top.png", "default_tree.png"},
is_ground_content = false,
groups = {choppy=2,oddly_breakable_by_hand=1},
})
core.register_node("basenodes:leaves", {
description = "Normal Leaves",
drawtype = "allfaces_optional",
tiles = {"default_leaves.png"},
paramtype = "light",
is_ground_content = false,
groups = {snappy=3},
})
core.register_node("basenodes:jungletree", {
description = "Jungle Tree Trunk",
tiles = {"default_jungletree_top.png", "default_jungletree_top.png", "default_jungletree.png"},
is_ground_content = false,
groups = {choppy=2,oddly_breakable_by_hand=1},
})
core.register_node("basenodes:jungleleaves", {
description = "Jungle Leaves",
drawtype = "allfaces_optional",
tiles = {"default_jungleleaves.png"},
paramtype = "light",
is_ground_content = false,
groups = {snappy=3},
})
core.register_node("basenodes:pine_tree", {
description = "Pine Tree Trunk",
tiles = {"default_pine_tree_top.png", "default_pine_tree_top.png", "default_pine_tree.png"},
is_ground_content = false,
groups = {choppy=2,oddly_breakable_by_hand=1},
})
core.register_node("basenodes:pine_needles", {
description = "Pine Needles",
drawtype = "allfaces_optional",
tiles = {"default_pine_needles.png"},
paramtype = "light",
is_ground_content = false,
groups = {snappy=3},
})
core.register_node("basenodes:water_source", {
description = "Water Source".."\n"..
"Swimmable, spreading, renewable liquid".."\n"..
"Drowning damage: 1",
drawtype = "liquid",
waving = 3,
tiles = {"default_water.png"..WATER_ALPHA},
special_tiles = {
{name = "default_water.png"..WATER_ALPHA, backface_culling = false},
{name = "default_water.png"..WATER_ALPHA, backface_culling = true},
},
use_texture_alpha = "blend",
paramtype = "light",
walkable = false,
pointable = false,
diggable = false,
buildable_to = true,
is_ground_content = false,
drowning = 1,
liquidtype = "source",
liquid_alternative_flowing = "basenodes:water_flowing",
liquid_alternative_source = "basenodes:water_source",
liquid_viscosity = WATER_VISC,
post_effect_color = {a = 64, r = 100, g = 100, b = 200},
post_effect_color_shaded = true,
groups = {water = 3, liquid = 3},
})
core.register_node("basenodes:water_flowing", {
description = "Flowing Water".."\n"..
"Swimmable, spreading, renewable liquid".."\n"..
"Drowning damage: 1",
drawtype = "flowingliquid",
waving = 3,
tiles = {"default_water_flowing.png"},
special_tiles = {
{name = "default_water_flowing.png"..WATER_ALPHA,
backface_culling = false},
{name = "default_water_flowing.png"..WATER_ALPHA,
backface_culling = false},
},
use_texture_alpha = "blend",
paramtype = "light",
paramtype2 = "flowingliquid",
walkable = false,
pointable = false,
diggable = false,
buildable_to = true,
is_ground_content = false,
drowning = 1,
liquidtype = "flowing",
liquid_alternative_flowing = "basenodes:water_flowing",
liquid_alternative_source = "basenodes:water_source",
liquid_viscosity = WATER_VISC,
post_effect_color = {a = 64, r = 100, g = 100, b = 200},
post_effect_color_shaded = true,
groups = {water = 3, liquid = 3},
})
core.register_node("basenodes:river_water_source", {
description = "River Water Source".."\n"..
"Swimmable, spreading, non-renewable liquid".."\n"..
"Drowning damage: 1",
drawtype = "liquid",
waving = 3,
tiles = { "default_river_water.png"..WATER_ALPHA },
special_tiles = {
{name = "default_river_water.png"..WATER_ALPHA, backface_culling = false},
{name = "default_river_water.png"..WATER_ALPHA, backface_culling = true},
},
use_texture_alpha = "blend",
paramtype = "light",
walkable = false,
pointable = false,
diggable = false,
buildable_to = true,
is_ground_content = false,
drowning = 1,
liquidtype = "source",
liquid_alternative_flowing = "basenodes:river_water_flowing",
liquid_alternative_source = "basenodes:river_water_source",
liquid_viscosity = 1,
liquid_renewable = false,
liquid_range = 2,
post_effect_color = {a = 103, r = 30, g = 76, b = 90},
post_effect_color_shaded = true,
groups = {water = 3, liquid = 3, },
})
core.register_node("basenodes:river_water_flowing", {
description = "Flowing River Water".."\n"..
"Swimmable, spreading, non-renewable liquid".."\n"..
"Drowning damage: 1",
drawtype = "flowingliquid",
waving = 3,
tiles = {"default_river_water_flowing.png"..WATER_ALPHA},
special_tiles = {
{name = "default_river_water_flowing.png"..WATER_ALPHA,
backface_culling = false},
{name = "default_river_water_flowing.png"..WATER_ALPHA,
backface_culling = false},
},
use_texture_alpha = "blend",
paramtype = "light",
paramtype2 = "flowingliquid",
walkable = false,
pointable = false,
diggable = false,
buildable_to = true,
is_ground_content = false,
drowning = 1,
liquidtype = "flowing",
liquid_alternative_flowing = "basenodes:river_water_flowing",
liquid_alternative_source = "basenodes:river_water_source",
liquid_viscosity = 1,
liquid_renewable = false,
liquid_range = 2,
post_effect_color = {a = 103, r = 30, g = 76, b = 90},
post_effect_color_shaded = true,
groups = {water = 3, liquid = 3, },
})
core.register_node("basenodes:lava_flowing", {
description = "Flowing Lava".."\n"..
"Swimmable, spreading, renewable liquid".."\n"..
"4 damage per second".."\n"..
"Drowning damage: 1",
drawtype = "flowingliquid",
tiles = {"default_lava_flowing.png"},
special_tiles = {
{name="default_lava_flowing.png", backface_culling = false},
{name="default_lava_flowing.png", backface_culling = false},
},
paramtype = "light",
light_source = core.LIGHT_MAX,
walkable = false,
pointable = false,
diggable = false,
buildable_to = true,
is_ground_content = false,
drowning = 1,
damage_per_second = 4,
liquidtype = "flowing",
liquid_alternative_flowing = "basenodes:lava_flowing",
liquid_alternative_source = "basenodes:lava_source",
liquid_viscosity = LAVA_VISC,
post_effect_color = {a=192, r=255, g=64, b=0},
groups = {lava=3, liquid=1},
})
core.register_node("basenodes:lava_source", {
description = "Lava Source".."\n"..
"Swimmable, spreading, renewable liquid".."\n"..
"4 damage per second".."\n"..
"Drowning damage: 1",
drawtype = "liquid",
tiles = { "default_lava.png" },
special_tiles = {
{name = "default_lava.png", backface_culling = false},
{name = "default_lava.png", backface_culling = true},
},
paramtype = "light",
light_source = core.LIGHT_MAX,
walkable = false,
pointable = false,
diggable = false,
buildable_to = true,
is_ground_content = false,
drowning = 1,
damage_per_second = 4,
liquidtype = "source",
liquid_alternative_flowing = "basenodes:lava_flowing",
liquid_alternative_source = "basenodes:lava_source",
liquid_viscosity = LAVA_VISC,
post_effect_color = {a=192, r=255, g=64, b=0},
groups = {lava=3, liquid=1},
})
core.register_node("basenodes:cobble", {
description = "Cobblestone",
tiles ={"default_cobble.png"},
is_ground_content = false,
groups = {cracky=3},
})
core.register_node("basenodes:mossycobble", {
description = "Mossy Cobblestone",
tiles ={"default_mossycobble.png"},
is_ground_content = false,
groups = {cracky=3},
})
core.register_node("basenodes:apple", {
description = "Apple".."\n"..
"Punch: Eat (+2)",
drawtype = "plantlike",
tiles ={"default_apple.png"},
inventory_image = "default_apple.png",
paramtype = "light",
is_ground_content = false,
sunlight_propagates = true,
walkable = false,
groups = {dig_immediate=3},
-- Make eatable because why not?
on_use = core.item_eat(2),
})
core.register_node("basenodes:ice", {
description = "Ice",
tiles ={"default_ice.png"},
groups = {cracky=3},
})
-- The snow nodes intentionally have different tints to make them more
-- distinguishable
core.register_node("basenodes:snow", {
description = "Snow Sheet",
tiles = {"basenodes_snow_sheet.png"},
groups = {crumbly=3},
walkable = false,
paramtype = "light",
drawtype = "nodebox",
node_box = {
type = "fixed",
fixed = {-0.5, -0.5, -0.5, 0.5, -0.25, 0.5},
},
})
core.register_node("basenodes:snowblock", {
description = "Snow Block",
tiles ={"default_snow.png"},
groups = {crumbly=3},
})

View File

@ -0,0 +1,2 @@
name = basenodes
description = Contains basic nodes for mapgen

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 293 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 584 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 782 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 697 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 399 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 883 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 496 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 760 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 796 B

View File

@ -0,0 +1,7 @@
The dirt_with_grass folder is for testing loading textures from subfolders.
If it works correctly, the default_grass_side.png file in the folder is used but
default_grass.png is not overwritten by the file in the folder.
default_dirt.png should be overwritten by the default_dirt.png in the unittests
mod which depends on basenodes.

View File

@ -0,0 +1,582 @@
--
-- Tool definitions
--
--[[ TOOLS SUMMARY:
Tool types:
* Hand: basic tool/weapon (special capabilities in creative mode)
* Pickaxe: dig cracky
* Axe: dig choppy
* Shovel: dig crumbly
* Shears: dig snappy
* Sword: deal damage
* Dagger: deal damage, but faster
Tool materials:
* Wood: dig nodes of rating 3
* Stone: dig nodes of rating 3 or 2
* Steel: dig nodes of rating 3, 2 or 1
* Mese: dig "everything" instantly
* n-Uses: can be used n times before breaking
]]
-- The hand
if core.settings:get_bool("creative_mode") then
local digtime = 42
local caps = {times = {digtime, digtime, digtime}, uses = 0, maxlevel = 256}
core.register_item(":", {
type = "none",
wield_image = "wieldhand.png",
wield_scale = {x = 1, y = 1, z = 2.5},
range = 10,
tool_capabilities = {
full_punch_interval = 0.5,
max_drop_level = 3,
groupcaps = {
crumbly = caps,
cracky = caps,
snappy = caps,
choppy = caps,
oddly_breakable_by_hand = caps,
-- dig_immediate group doesn't use value 1. Value 3 is instant dig
dig_immediate =
{times = {[2] = digtime, [3] = 0}, uses = 0, maxlevel = 256},
},
damage_groups = {fleshy = 10},
}
})
else
core.register_item(":", {
type = "none",
wield_image = "wieldhand.png",
wield_scale = {x = 1, y = 1, z = 2.5},
tool_capabilities = {
full_punch_interval = 0.9,
max_drop_level = 0,
groupcaps = {
crumbly = {times = {[2] = 3.00, [3] = 0.70}, uses = 0, maxlevel = 1},
snappy = {times = {[3] = 0.40}, uses = 0, maxlevel = 1},
oddly_breakable_by_hand =
{times = {[1] = 3.50, [2] = 2.00, [3] = 0.70}, uses = 0}
},
damage_groups = {fleshy = 1},
}
})
end
-- Mese Pickaxe: special tool that digs "everything" instantly
core.register_tool("basetools:pick_mese", {
description = "Mese Pickaxe".."\n"..
"Digs diggable nodes instantly.",
inventory_image = "basetools_mesepick.png",
tool_capabilities = {
full_punch_interval = 1.0,
max_drop_level=3,
groupcaps={
cracky={times={[1]=0.0, [2]=0.0, [3]=0.0}, maxlevel=255},
crumbly={times={[1]=0.0, [2]=0.0, [3]=0.0}, maxlevel=255},
snappy={times={[1]=0.0, [2]=0.0, [3]=0.0}, maxlevel=255},
choppy={times={[1]=0.0, [2]=0.0, [3]=0.0}, maxlevel=255},
dig_immediate={times={[1]=0.0, [2]=0.0, [3]=0.0}, maxlevel=255},
},
damage_groups = {fleshy=100},
},
})
-- A variant of the mese pickaxe that is not affected by the 0.15s digging delay
core.register_tool("basetools:pick_mese_no_delay", {
description = "Mese Pickaxe (no delay)".."\n"..
"Digs diggable nodes instantly.".."\n"..
"There is no delay between digging each node,\n"..
'but the "repeat_dig_time" setting is still respected.',
inventory_image = "basetools_mesepick_no_delay.png",
tool_capabilities = {
full_punch_interval = 1.0,
max_drop_level=3,
groupcaps={
cracky={times={[1]=0.001, [2]=0.001, [3]=0.001}, maxlevel=255},
crumbly={times={[1]=0.001, [2]=0.001, [3]=0.001}, maxlevel=255},
snappy={times={[1]=0.001, [2]=0.001, [3]=0.001}, maxlevel=255},
choppy={times={[1]=0.001, [2]=0.001, [3]=0.001}, maxlevel=255},
dig_immediate={times={[1]=0.001, [2]=0.001, [3]=0.001}, maxlevel=255},
},
damage_groups = {fleshy=100},
},
})
--
-- Pickaxes: Dig cracky
--
core.register_tool("basetools:pick_wood", {
description = "Wooden Pickaxe".."\n"..
"Digs cracky=3",
inventory_image = "basetools_woodpick.png",
tool_capabilities = {
max_drop_level=0,
groupcaps={
cracky={times={[3]=2.00}, uses=30, maxlevel=0}
},
},
})
core.register_tool("basetools:pick_stone", {
description = "Stone Pickaxe".."\n"..
"Digs cracky=2..3",
inventory_image = "basetools_stonepick.png",
tool_capabilities = {
max_drop_level=0,
groupcaps={
cracky={times={[2]=1.20, [3]=0.80}, uses=60, maxlevel=0}
},
},
})
core.register_tool("basetools:pick_steel", {
description = "Steel Pickaxe".."\n"..
"Digs cracky=1..3",
inventory_image = "basetools_steelpick.png",
tool_capabilities = {
max_drop_level=1,
groupcaps={
cracky={times={[1]=4.00, [2]=1.60, [3]=1.00}, uses=90, maxlevel=0}
},
},
})
core.register_tool("basetools:pick_steel_l1", {
description = "Steel Pickaxe Level 1".."\n"..
"Digs cracky=1..3".."\n"..
"maxlevel=1",
inventory_image = "basetools_steelpick_l1.png",
tool_capabilities = {
max_drop_level=1,
groupcaps={
cracky={times={[1]=4.00, [2]=1.60, [3]=1.00}, uses=90, maxlevel=1}
},
},
})
core.register_tool("basetools:pick_steel_l2", {
description = "Steel Pickaxe Level 2".."\n"..
"Digs cracky=1..3".."\n"..
"maxlevel=2",
inventory_image = "basetools_steelpick_l2.png",
tool_capabilities = {
max_drop_level=1,
groupcaps={
cracky={times={[1]=4.00, [2]=1.60, [3]=1.00}, uses=90, maxlevel=2}
},
},
})
--
-- Shovels (dig crumbly)
--
core.register_tool("basetools:shovel_wood", {
description = "Wooden Shovel".."\n"..
"Digs crumbly=3",
inventory_image = "basetools_woodshovel.png",
tool_capabilities = {
max_drop_level=0,
groupcaps={
crumbly={times={[3]=0.50}, uses=30, maxlevel=0}
},
},
})
core.register_tool("basetools:shovel_stone", {
description = "Stone Shovel".."\n"..
"Digs crumbly=2..3",
inventory_image = "basetools_stoneshovel.png",
tool_capabilities = {
max_drop_level=0,
groupcaps={
crumbly={times={[2]=0.50, [3]=0.30}, uses=60, maxlevel=0}
},
},
})
core.register_tool("basetools:shovel_steel", {
description = "Steel Shovel".."\n"..
"Digs crumbly=1..3",
inventory_image = "basetools_steelshovel.png",
tool_capabilities = {
max_drop_level=1,
groupcaps={
crumbly={times={[1]=1.00, [2]=0.70, [3]=0.60}, uses=90, maxlevel=0}
},
},
})
--
-- Axes (dig choppy)
--
core.register_tool("basetools:axe_wood", {
description = "Wooden Axe".."\n"..
"Digs choppy=3",
inventory_image = "basetools_woodaxe.png",
tool_capabilities = {
max_drop_level=0,
groupcaps={
choppy={times={[3]=0.80}, uses=30, maxlevel=0},
},
},
})
core.register_tool("basetools:axe_stone", {
description = "Stone Axe".."\n"..
"Digs choppy=2..3",
inventory_image = "basetools_stoneaxe.png",
tool_capabilities = {
max_drop_level=0,
groupcaps={
choppy={times={[2]=1.00, [3]=0.60}, uses=60, maxlevel=0},
},
},
})
core.register_tool("basetools:axe_steel", {
description = "Steel Axe".."\n"..
"Digs choppy=1..3",
inventory_image = "basetools_steelaxe.png",
tool_capabilities = {
max_drop_level=1,
groupcaps={
choppy={times={[1]=2.00, [2]=0.80, [3]=0.40}, uses=90, maxlevel=0},
},
},
})
--
-- Shears (dig snappy)
--
core.register_tool("basetools:shears_wood", {
description = "Wooden Shears".."\n"..
"Digs snappy=3",
inventory_image = "basetools_woodshears.png",
tool_capabilities = {
max_drop_level=0,
groupcaps={
snappy={times={[3]=1.00}, uses=30, maxlevel=0},
},
},
})
core.register_tool("basetools:shears_stone", {
description = "Stone Shears".."\n"..
"Digs snappy=2..3",
inventory_image = "basetools_stoneshears.png",
tool_capabilities = {
max_drop_level=0,
groupcaps={
snappy={times={[2]=1.00, [3]=0.50}, uses=60, maxlevel=0},
},
},
})
core.register_tool("basetools:shears_steel", {
description = "Steel Shears".."\n"..
"Digs snappy=1..3",
inventory_image = "basetools_steelshears.png",
tool_capabilities = {
max_drop_level=1,
groupcaps={
snappy={times={[1]=1.00, [2]=0.50, [3]=0.25}, uses=90, maxlevel=0},
},
},
})
--
-- Swords (deal damage)
--
core.register_tool("basetools:sword_wood", {
description = "Wooden Sword".."\n"..
"Damage: fleshy=2",
inventory_image = "basetools_woodsword.png",
tool_capabilities = {
full_punch_interval = 1.0,
damage_groups = {fleshy=2},
}
})
core.register_tool("basetools:sword_stone", {
description = "Stone Sword".."\n"..
"Damage: fleshy=5",
inventory_image = "basetools_stonesword.png",
tool_capabilities = {
full_punch_interval = 1.0,
max_drop_level=0,
damage_groups = {fleshy=5},
}
})
core.register_tool("basetools:sword_steel", {
description = "Steel Sword".."\n"..
"Damage: fleshy=10",
inventory_image = "basetools_steelsword.png",
tool_capabilities = {
full_punch_interval = 1.0,
max_drop_level=1,
damage_groups = {fleshy=10},
}
})
core.register_tool("basetools:sword_titanium", {
description = "Titanium Sword".."\n"..
"Damage: fleshy=100",
inventory_image = "basetools_titaniumsword.png",
tool_capabilities = {
full_punch_interval = 1.0,
max_drop_level=1,
damage_groups = {fleshy=100},
}
})
core.register_tool("basetools:sword_blood", {
description = "Blood Sword".."\n"..
"Damage: fleshy=1000",
inventory_image = "basetools_bloodsword.png",
tool_capabilities = {
full_punch_interval = 1.0,
max_drop_level=1,
damage_groups = {fleshy=1000},
}
})
-- Max. damage sword
core.register_tool("basetools:sword_mese", {
description = "Mese Sword".."\n"..
"Damage: fleshy=32767, fiery=32767, icy=32767".."\n"..
"Full Punch Interval: 0.0s",
inventory_image = "basetools_mesesword.png",
tool_capabilities = {
full_punch_interval = 0.0,
max_drop_level=1,
damage_groups = {fleshy=32767, fiery=32767, icy=32767},
}
})
-- Fire/Ice sword: Deal damage to non-fleshy damage groups
core.register_tool("basetools:sword_fire", {
description = "Fire Sword".."\n"..
"Damage: icy=10",
inventory_image = "basetools_firesword.png",
tool_capabilities = {
full_punch_interval = 1.0,
max_drop_level=0,
damage_groups = {icy=10},
}
})
core.register_tool("basetools:sword_ice", {
description = "Ice Sword".."\n"..
"Damage: fiery=10",
inventory_image = "basetools_icesword.png",
tool_capabilities = {
full_punch_interval = 1.0,
max_drop_level=0,
damage_groups = {fiery=10},
}
})
core.register_tool("basetools:sword_elemental", {
description = "Elemental Sword".."\n"..
"Damage: fiery=10, icy=10",
inventory_image = "basetools_elementalsword.png",
tool_capabilities = {
full_punch_interval = 1.0,
max_drop_level=0,
damage_groups = {fiery=10, icy=10},
}
})
-- Healing weapons: heal HP
core.register_tool("basetools:dagger_heal", {
description = "Healing Dagger".."\n"..
"Heal: fleshy=1".."\n"..
"Full Punch Interval: 0.5s",
inventory_image = "basetools_healdagger.png",
tool_capabilities = {
full_punch_interval = 0.5,
damage_groups = {fleshy=-1},
}
})
core.register_tool("basetools:sword_heal", {
description = "Healing Sword".."\n"..
"Heal: fleshy=10",
inventory_image = "basetools_healsword.png",
tool_capabilities = {
full_punch_interval = 1.0,
damage_groups = {fleshy=-10},
}
})
core.register_tool("basetools:sword_heal_super", {
description = "Super Healing Sword".."\n"..
"Heal: fleshy=32768, fiery=32768, icy=32768",
inventory_image = "basetools_superhealsword.png",
tool_capabilities = {
full_punch_interval = 1.0,
damage_groups = {fleshy=-32768, fiery=-32768, icy=-32768},
}
})
--
-- Dagger: Low damage, fast punch interval
--
core.register_tool("basetools:dagger_wood", {
description = "Wooden Dagger".."\n"..
"Damage: fleshy=1".."\n"..
"Full Punch Interval: 0.5s",
inventory_image = "basetools_wooddagger.png",
tool_capabilities = {
full_punch_interval = 0.5,
max_drop_level=0,
damage_groups = {fleshy=1},
}
})
core.register_tool("basetools:dagger_steel", {
description = "Steel Dagger".."\n"..
"Damage: fleshy=2".."\n"..
"Full Punch Interval: 0.5s",
inventory_image = "basetools_steeldagger.png",
tool_capabilities = {
full_punch_interval = 0.5,
max_drop_level=0,
damage_groups = {fleshy=2},
}
})
-- Test tool uses, punch_attack_uses, and wear bar coloring
local tool_params = {
{uses = 1},
{uses = 2},
{uses = 3},
{
uses = 5,
wear_color = "#5865f2",
wear_description = "Solid color: #5865f2",
},
{
uses = 10,
wear_color = "slateblue",
wear_description = "Solid color: slateblue",
},
{
uses = 50,
wear_color = {
color_stops = {
[0] = "red",
[0.5] = "yellow",
[1.0] = "blue"
},
blend = "linear"
},
wear_description = "Ranges from blue to yellow to red",
},
{
uses = 100,
wear_color = {
color_stops = {
[0] = "#ffff00",
[0.2] = "#ff00ff",
[0.3] = "#ffff00",
[0.45] = "#c0ffee",
[0.6] = {r=255, g=255, b=0, a=100}, -- continues until the end
},
blend = "constant"
},
wear_description = "Misc. colors, constant interpolation",
},
{uses = 1e3},
{uses = 1e4},
{uses = 65535},
}
for i, params in ipairs(tool_params) do
local uses = params.uses
local ustring = uses.."-Use"..(uses == 1 and "" or "s")
local color = string.format("#FF00%02X", math.floor(((i-1)/#tool_params) * 255))
core.register_tool("basetools:pick_uses_"..string.format("%05d", uses), {
description = ustring.." Pickaxe".."\n"..
"Digs cracky=3"..
(params.wear_description and "\n".."Wear bar: " .. params.wear_description or ""),
inventory_image = "basetools_usespick.png^[colorize:"..color..":127",
tool_capabilities = {
max_drop_level=0,
groupcaps={
cracky={times={[3]=0.1, [2]=0.2, [1]=0.3}, uses=uses, maxlevel=0}
},
},
wear_color = params.wear_color
})
core.register_tool("basetools:sword_uses_"..string.format("%05d", uses), {
description = ustring.." Sword".."\n"..
"Damage: fleshy=1",
inventory_image = "basetools_usessword.png^[colorize:"..color..":127",
tool_capabilities = {
damage_groups = {fleshy=1},
punch_attack_uses = uses,
},
})
end
core.register_chatcommand("wear_color", {
params = "[idx]",
description = "Set wear bar color override",
func = function(player_name, param)
local player = core.get_player_by_name(player_name)
if not player then return end
local wear_color = nil
local wear_desc = "Reset override"
if param ~= "" then
local params = tool_params[tonumber(param)]
if not params then
return false, "idx out of bounds"
end
wear_color = params.wear_color
wear_desc = "Set override: "..(params.wear_description or "Default behavior")
end
local tool = player:get_wielded_item()
if tool:get_count() == 0 then
return false, "Tool not found"
end
tool:get_meta():set_wear_bar_params(wear_color)
player:set_wielded_item(tool)
return true, wear_desc
end
})
-- Punch handler to set random color & wear
local wear_on_use = function(itemstack, user, pointed_thing)
local meta = itemstack:get_meta()
local color = math.random(0, 0xFFFFFF)
local colorstr = string.format("#%06x", color)
meta:set_wear_bar_params(colorstr)
core.log("action", "[basetool] Wear bar color of "..itemstack:get_name().." changed to "..colorstr)
itemstack:set_wear(math.random(0, 65535))
return itemstack
end
-- Place handler to clear item metadata color
local wear_on_place = function(itemstack, user, pointed_thing)
local meta = itemstack:get_meta()
meta:set_wear_bar_params(nil)
return itemstack
end
core.register_tool("basetools:random_wear_bar", {
description = "Wear Bar Color Test\n" ..
"Punch: Set random color & wear\n" ..
"Place: Clear color",
-- Base texture: A grayscale square (can be colorized)
inventory_image = "basetools_usespick.png^[colorize:#FFFFFF:127",
tool_capabilities = {
max_drop_level=0,
groupcaps={
cracky={times={[3]=0.1, [2]=0.2, [1]=0.3}, uses=1000, maxlevel=0}
},
},
on_use = wear_on_use,
on_place = wear_on_place,
on_secondary_use = wear_on_place,
})

View File

@ -0,0 +1,2 @@
name = basetools
description = Contains basic digging tools

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

View File

@ -0,0 +1,189 @@
-- Safeguard against too much optimization. This way the results cannot be optimized
-- away, but they can be garbage collected (due to __mode = "k").
_G._bench_content_ids_data = setmetatable({}, {__mode = "k"})
local function bench_name2content()
local t = {}
_G._bench_content_ids_data[t] = true
local get_content_id = core.get_content_id
local start = core.get_us_time()
for i = 1, 200 do
for name in pairs(core.registered_nodes) do
t[#t + 1] = get_content_id(name)
end
end
local finish = core.get_us_time()
return (finish - start) / 1000
end
local function bench_content2name()
local t = {}
_G._bench_content_ids_data[t] = true
-- Try to estimate the highest content ID that's used
-- (not accurate but good enough for this test)
local n = 0
for _ in pairs(core.registered_nodes) do
n = n + 1
end
local get_name_from_content_id = core.get_name_from_content_id
local start = core.get_us_time()
for i = 1, 200 do
for j = 0, n do
t[#t + 1] = get_name_from_content_id(j)
end
end
local finish = core.get_us_time()
return (finish - start) / 1000
end
core.register_chatcommand("bench_name2content", {
params = "",
description = "Benchmark: Conversion from node names to content IDs",
func = function(name, param)
core.chat_send_player(name, "Benchmarking core.get_content_id. Warming up ...")
bench_name2content()
core.chat_send_player(name, "Warming up finished, now benchmarking ...")
local time = bench_name2content()
return true, ("Time: %.2f ms"):format(time)
end,
})
core.register_chatcommand("bench_content2name", {
params = "",
description = "Benchmark: Conversion from content IDs to node names",
func = function(name, param)
core.chat_send_player(name, "Benchmarking core.get_name_from_content_id. Warming up ...")
bench_content2name()
core.chat_send_player(name, "Warming up finished, now benchmarking ...")
local time = bench_content2name()
return true, ("Time: %.2f ms"):format(time)
end,
})
local function get_positions_cube(ppos)
local pos_list = {}
local i = 1
for x=2,100 do
for y=2,100 do
for z=2,100 do
pos_list[i] = ppos:offset(x, y, z)
i = i + 1
end
end
end
return pos_list
end
core.register_chatcommand("bench_bulk_set_node", {
params = "",
description = "Benchmark: Bulk-set 99×99×99 stone nodes",
func = function(name, param)
local player = core.get_player_by_name(name)
if not player then
return false, "No player."
end
local pos_list = get_positions_cube(player:get_pos())
core.chat_send_player(name, "Benchmarking core.bulk_set_node. Warming up ...")
-- warm up with stone to prevent having different callbacks
-- due to different node topology
core.bulk_set_node(pos_list, {name = "mapgen_stone"})
core.chat_send_player(name, "Warming up finished, now benchmarking ...")
local start_time = core.get_us_time()
for i=1,#pos_list do
core.set_node(pos_list[i], {name = "mapgen_stone"})
end
local middle_time = core.get_us_time()
core.bulk_set_node(pos_list, {name = "mapgen_stone"})
local end_time = core.get_us_time()
local msg = string.format("Benchmark results: core.set_node loop: %.2f ms; core.bulk_set_node: %.2f ms",
((middle_time - start_time)) / 1000,
((end_time - middle_time)) / 1000
)
return true, msg
end,
})
core.register_chatcommand("bench_bulk_get_node", {
params = "",
description = "Benchmark: Bulk-get 99×99×99 nodes",
func = function(name, param)
local player = core.get_player_by_name(name)
if not player then
return false, "No player."
end
local pos_list = get_positions_cube(player:get_pos())
local function bench()
local start_time = core.get_us_time()
for i=1,#pos_list do
local n = core.get_node(pos_list[i])
-- Make sure the name lookup is never optimized away.
-- Table allocation might still be omitted. But only accessing
-- the name of a node is a common pattern anyways.
if n.name == "benchmarks:nonexistent_node" then
error("should never happen")
end
end
return core.get_us_time() - start_time
end
core.chat_send_player(name, "Benchmarking core.get_node. Warming up ...")
bench()
core.chat_send_player(name, "Warming up finished, now benchmarking ...")
local result_us = bench()
local msg = string.format("Benchmark results: core.get_node loop 1: %.2f ms",
result_us / 1000)
return true, msg
end,
})
core.register_chatcommand("bench_bulk_swap_node", {
params = "",
description = "Benchmark: Bulk-swap 99×99×99 stone nodes",
func = function(name, param)
local player = core.get_player_by_name(name)
if not player then
return false, "No player."
end
local pos_list = get_positions_cube(player:get_pos())
core.chat_send_player(name, "Benchmarking core.bulk_swap_node. Warming up ...")
-- warm up because first execution otherwise becomes
-- significantly slower
core.bulk_swap_node(pos_list, {name = "mapgen_stone"})
core.chat_send_player(name, "Warming up finished, now benchmarking ...")
local start_time = core.get_us_time()
for i=1,#pos_list do
core.swap_node(pos_list[i], {name = "mapgen_stone"})
end
local middle_time = core.get_us_time()
core.bulk_swap_node(pos_list, {name = "mapgen_stone"})
local end_time = core.get_us_time()
local msg = string.format("Benchmark results: core.swap_node loop: %.2f ms; core.bulk_swap_node: %.2f ms",
((middle_time - start_time)) / 1000,
((end_time - middle_time)) / 1000
)
return true, msg
end,
})

View File

@ -0,0 +1,2 @@
name = benchmarks
description = Adds some benchmark chat commands

View File

@ -0,0 +1,11 @@
-- Register stuff with empty definitions to test if Luanti fallback options
-- for these things work properly.
-- The itemstrings are deliberately kept descriptive to keep them easy to
-- recognize.
core.register_node("broken:node_with_empty_definition", {})
core.register_tool("broken:tool_with_empty_definition", {})
core.register_craftitem("broken:craftitem_with_empty_definition", {})
core.register_entity("broken:entity_with_empty_definition", {})

View File

@ -0,0 +1,2 @@
name = broken
description = Register items and an entity with empty definitions to test fallback

View File

@ -0,0 +1,27 @@
-- Bucket: Punch liquid source or flowing liquid to collect it
core.register_tool("bucket:bucket", {
description = "Bucket".."\n"..
"Picks up liquid nodes",
inventory_image = "bucket.png",
stack_max = 1,
liquids_pointable = true,
groups = { disable_repair = 1 },
on_use = function(itemstack, user, pointed_thing)
-- Must be pointing to node
if pointed_thing.type ~= "node" then
return
end
-- Check if pointing to a liquid
local n = core.get_node(pointed_thing.under)
local def = core.registered_nodes[n.name]
if def ~= nil and (def.liquidtype == "source" or def.liquidtype == "flowing") then
core.add_node(pointed_thing.under, {name="air"})
local inv = user:get_inventory()
if inv then
inv:add_item("main", ItemStack(n.name))
end
end
end,
})

View File

@ -0,0 +1,2 @@
name = bucket
description = Minimal bucket to pick up liquids

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

View File

@ -0,0 +1,101 @@
-- Entities that test their callbacks
local message = function(msg)
core.log("action", "[callbacks] "..msg)
core.chat_send_all(msg)
end
local get_object_name = function(obj)
local name = "<nil>"
if obj then
if obj:is_player() then
name = obj:get_player_name()
else
name = "<entity>"
end
end
return name
end
local spos = function(self)
return core.pos_to_string(vector.round(self.object:get_pos()))
end
-- Callback test entity (all callbacks except on_step)
core.register_entity("callbacks:callback", {
initial_properties = {
visual = "upright_sprite",
textures = { "callbacks_callback_entity.png" },
},
on_activate = function(self, staticdata, dtime_s)
message("Callback entity: on_activate! pos="..spos(self).."; dtime_s="..dtime_s)
end,
on_deactivate = function(self, removal)
message("Callback entity: on_deactivate! pos="..spos(self) .. "; removal=" .. tostring(removal))
end,
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
local name = get_object_name(puncher)
message(
"Callback entity: on_punch! "..
"pos="..spos(self).."; puncher="..name.."; "..
"time_from_last_punch="..time_from_last_punch.."; "..
"tool_capabilities="..tostring(dump(tool_capabilities)).."; "..
"dir="..tostring(dump(dir)).."; damage="..damage)
end,
on_rightclick = function(self, clicker)
local name = get_object_name(clicker)
message("Callback entity: on_rightclick! pos="..spos(self).."; clicker="..name)
end,
on_death = function(self, killer)
local name = get_object_name(killer)
message("Callback entity: on_death! pos="..spos(self).."; killer="..name)
end,
on_attach_child = function(self, child)
local name = get_object_name(child)
message("Callback entity: on_attach_child! pos="..spos(self).."; child="..name)
end,
on_detach_child = function(self, child)
local name = get_object_name(child)
message("Callback entity: on_detach_child! pos="..spos(self).."; child="..name)
end,
on_detach = function(self, parent)
local name = get_object_name(parent)
message("Callback entity: on_detach! pos="..spos(self).."; parent="..name)
end,
get_staticdata = function(self)
message("Callback entity: get_staticdata! pos="..spos(self))
end,
})
-- Only test on_step callback
core.register_entity("callbacks:callback_step", {
visual = "upright_sprite",
textures = { "callbacks_callback_entity_step.png" },
on_step = function(self, dtime)
message("on_step callback entity: on_step! pos="..spos(self).."; dtime="..dtime)
end,
})
-- Callback punch with nil puncher
core.register_entity("callbacks:callback_puncher", {
initial_properties = {
visual = "upright_sprite",
textures = { "callbacks_callback_entity.png" },
infotext = "Callback entity for nil puncher test.",
},
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
if puncher then
puncher:punch(nil, time_from_last_punch, tool_capabilities, dir)
self.object:punch(nil, time_from_last_punch, tool_capabilities, dir)
else
message(
"Callback entity: on_punch with nil puncher "..
"pos="..spos(self).."; "..
"time_from_last_punch="..time_from_last_punch.."; "..
"tool_capabilities="..dump(tool_capabilities).."; "..
"dir="..dump(dir).."; damage="..damage)
end
end,
})

View File

@ -0,0 +1,4 @@
dofile(core.get_modpath("callbacks").."/items.lua")
dofile(core.get_modpath("callbacks").."/nodes.lua")
dofile(core.get_modpath("callbacks").."/entities.lua")
dofile(core.get_modpath("callbacks").."/players.lua")

View File

@ -0,0 +1,120 @@
--
-- Item callbacks
--
local function print_to_everything(msg)
core.log("action", "[callbacks] " .. msg)
core.chat_send_all(msg)
end
core.register_craftitem("callbacks:callback_item_1", {
description = "Callback Test Item 1".."\n"..
"Tests callbacks: on_secondary_use, on_drop, on_pickup, on_use, after_use".."\n"..
"Punch/Drop + Sneak: Switch to Callback Test Item 2".."\n"..
"Aux1 + pickup item: Print additional on_pickup arguments",
inventory_image = "callbacks_callback_item_1.png",
wield_image = "callbacks_callback_item_1.png",
groups = { callback_test = 1 },
on_secondary_use = function(itemstack, user, pointed_thing)
print_to_everything("[callbacks:callback_item_1 on_secondary_use] " .. itemstack:get_name())
local ctrl = user and user:get_player_control() or {}
if ctrl.sneak then
itemstack = ItemStack(itemstack)
itemstack:set_name("callbacks:callback_item_2")
return itemstack
end
end,
on_drop = function(itemstack, dropper, pos)
print_to_everything("[callbacks:callback_item_1 on_drop] " .. itemstack:get_name())
local ctrl = dropper and dropper:get_player_control() or {}
if ctrl.sneak then
itemstack = ItemStack(itemstack)
itemstack:set_name("callbacks:callback_item_2")
end
return core.item_drop(itemstack, dropper, pos)
end,
on_pickup = function(itemstack, picker, pointed_thing, ...)
print_to_everything("[callbacks:callback_item_1 on_pickup]")
assert(pointed_thing.ref:get_luaentity().name == "__builtin:item")
local ctrl = picker and picker:get_player_control() or {}
if ctrl.aux1 then
-- Debug message
print_to_everything("on_pickup dump:")
print_to_everything(dump({...}))
end
if ctrl.sneak then
-- Pick up one item of the other kind at once
local taken = itemstack:take_item()
taken:set_name("callbacks:callback_item_2")
local leftover = core.item_pickup(taken, picker, pointed_thing, ...)
leftover:set_name("callbacks:callback_item_1")
itemstack:add_item(leftover)
return itemstack
elseif ctrl.up then
-- Don't pick up
return
elseif ctrl.left then
-- Eat it
return core.do_item_eat(2, nil, itemstack, picker, pointed_thing)
else
-- Normal: pick up everything
return core.item_pickup(itemstack, picker, pointed_thing, ...)
end
end,
on_use = function(itemstack, user, pointed_thing)
print_to_everything("[callbacks:callback_item_1 on_use] " .. itemstack:get_name())
local ctrl = user and user:get_player_control() or {}
if ctrl.sneak then
itemstack = ItemStack(itemstack)
itemstack:set_name("callbacks:callback_item_2")
return itemstack
end
end,
after_use = function(itemstack, user, node, digparams) -- never called
print_to_everything("[callbacks:callback_item_1 after_use]")
local ctrl = user and user:get_player_control() or {}
if ctrl.up then
itemstack = ItemStack(itemstack)
itemstack:set_name("callbacks:callback_item_2")
return itemstack
end
end,
})
core.register_craftitem("callbacks:callback_item_2", {
description = "Callback Test Item 2".."\n"..
"Punch to switch to Callback Test Item 1",
inventory_image = "callbacks_callback_item_2.png",
wield_image = "callbacks_callback_item_2.png",
groups = { callback_test = 1 },
on_use = function(itemstack, user, pointed_thing)
print_to_everything("[callbacks:callback_item_2 on_use]")
itemstack = ItemStack(itemstack)
itemstack:set_name("callbacks:callback_item_1")
return itemstack
end,
})
core.register_on_item_pickup(function(itemstack, picker, pointed_thing, time_from_last_punch, ...)
assert(not pointed_thing or pointed_thing.ref:get_luaentity().name == "__builtin:item")
local item_name = itemstack:get_name()
if item_name ~= "callbacks:callback_item_1" and item_name ~= "callbacks:callback_item_2" then
return
end
print_to_everything("["..item_name.." register_on_item_pickup]")
local ctrl = picker and picker:get_player_control() or {}
if item_name == "callbacks:callback_item_2" and not ctrl.sneak then
-- Same here. Pick up the other item type.
itemstack:set_name("callbacks:callback_item_1")
return picker:get_inventory():add_item("main", itemstack)
end
end)

View File

@ -0,0 +1,2 @@
name = callbacks
description = Adds various callback-related stuff

View File

@ -0,0 +1,51 @@
local function print_to_everything(msg)
core.log("action", "[callbacks] " .. msg)
core.chat_send_all(msg)
end
core.register_node("callbacks:callback_node", {
description = "Callback Test Node (construct/destruct/timer)".."\n"..
"Tests callbacks: on_construct, after_place_node, on_destruct, after_destruct, after_dig_node, on_timer",
tiles = {"callbacks_callback_node.png"},
groups = {callback_test=1, dig_immediate=3},
-- This was known to cause a bug in core.item_place_node() when used
-- via core.place_node(), causing a placer with no position
paramtype2 = "facedir",
drop = "",
on_construct = function(pos)
print_to_everything("callbacks:callback_node:on_construct("..core.pos_to_string(pos)..")")
local meta = core.get_meta(pos)
meta:set_string("mine", "test")
local timer = core.get_node_timer(pos)
timer:start(4, 3)
end,
after_place_node = function(pos, placer)
print_to_everything("callbacks:callback_node:after_place_node("..core.pos_to_string(pos)..")")
local meta = core.get_meta(pos)
if meta:get_string("mine") == "test" then
print_to_everything("correct metadata found")
else
print_to_everything("incorrect metadata found")
end
end,
on_destruct = function(pos)
print_to_everything("callbacks:callback_node:on_destruct("..core.pos_to_string(pos)..")")
end,
after_destruct = function(pos)
print_to_everything("callbacks:callback_node:after_destruct("..core.pos_to_string(pos)..")")
end,
after_dig_node = function(pos, oldnode, oldmetadata, digger)
print_to_everything("callbacks:callback_node:after_dig_node("..core.pos_to_string(pos)..")")
end,
on_timer = function(pos, elapsed)
print_to_everything("callbacks:callback_node:on_timer(): elapsed="..dump(elapsed))
return true
end,
})

View File

@ -0,0 +1,11 @@
local message = function(msg)
core.log("action", "[callbacks] "..msg)
core.chat_send_all(msg)
end
core.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage)
if not hitter then
message("Player "..player:get_player_name().." punched without hitter.")
end
end)

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

Some files were not shown because too many files have changed in this diff Show More