mirror of
https://github.com/luanti-org/luanti.git
synced 2025-07-02 16:38:41 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
0976b89add
257 changed files with 3805 additions and 3840 deletions
2
.github/workflows/lua.yml
vendored
2
.github/workflows/lua.yml
vendored
|
@ -35,7 +35,7 @@ jobs:
|
|||
|
||||
- name: Integration test + devtest
|
||||
run: |
|
||||
./util/test_multiplayer.sh
|
||||
serverconf="profiler.load=true" ./util/test_multiplayer.sh
|
||||
|
||||
luacheck:
|
||||
name: "Builtin Luacheck and Unit Tests"
|
||||
|
|
4
.github/workflows/macos.yml
vendored
4
.github/workflows/macos.yml
vendored
|
@ -29,8 +29,8 @@ on:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
# use macOS 13 since it's the last one that still runs on x86
|
||||
runs-on: macos-13
|
||||
# use lowest possible macOS running on x86_64 to support more users
|
||||
runs-on: macos-12
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Install deps
|
||||
|
|
|
@ -56,6 +56,11 @@ if((WIN32 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR APPLE)
|
|||
endif()
|
||||
set(ENABLE_LTO ${DEFAULT_ENABLE_LTO} CACHE BOOL "Use Link Time Optimization")
|
||||
|
||||
set(BUILD_WITH_TRACY FALSE CACHE BOOL
|
||||
"Fetch and build with the Tracy profiler client")
|
||||
set(FETCH_TRACY_GIT_TAG "master" CACHE STRING
|
||||
"Git tag for fetching Tracy client. Match with your server (gui) version")
|
||||
|
||||
set(DEFAULT_RUN_IN_PLACE FALSE)
|
||||
if(WIN32)
|
||||
set(DEFAULT_RUN_IN_PLACE TRUE)
|
||||
|
@ -370,3 +375,19 @@ if(BUILD_DOCUMENTATION)
|
|||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Fetch Tracy
|
||||
if(BUILD_WITH_TRACY)
|
||||
include(FetchContent)
|
||||
|
||||
message(STATUS "Fetching Tracy (${FETCH_TRACY_GIT_TAG})...")
|
||||
FetchContent_Declare(
|
||||
tracy
|
||||
GIT_REPOSITORY https://github.com/wolfpld/tracy.git
|
||||
GIT_TAG ${FETCH_TRACY_GIT_TAG}
|
||||
GIT_SHALLOW TRUE
|
||||
GIT_PROGRESS TRUE
|
||||
)
|
||||
FetchContent_MakeAvailable(tracy)
|
||||
message(STATUS "Fetching Tracy - done")
|
||||
endif()
|
||||
|
|
|
@ -119,6 +119,7 @@ Command-line options
|
|||
Compiling
|
||||
---------
|
||||
|
||||
- [Compiling - common information](doc/compiling/README.md)
|
||||
- [Compiling on GNU/Linux](doc/compiling/linux.md)
|
||||
- [Compiling on Windows](doc/compiling/windows.md)
|
||||
- [Compiling on MacOS](doc/compiling/macos.md)
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
-- CSM death formspec. Only used when clientside modding is enabled, otherwise
|
||||
-- handled by the engine.
|
||||
|
||||
core.register_on_death(function()
|
||||
local formspec = "size[11,5.5]bgcolor[#320000b4;true]" ..
|
||||
"label[4.85,1.35;" .. fgettext("You died") ..
|
||||
"]button_exit[4,3;3,0.5;btn_respawn;".. fgettext("Respawn") .."]"
|
||||
core.show_formspec("bultin:death", formspec)
|
||||
end)
|
||||
|
||||
core.register_on_formspec_input(function(formname, fields)
|
||||
if formname == "bultin:death" then
|
||||
core.send_respawn()
|
||||
end
|
||||
end)
|
|
@ -9,6 +9,5 @@ dofile(commonpath .. "mod_storage.lua")
|
|||
dofile(commonpath .. "chatcommands.lua")
|
||||
dofile(commonpath .. "information_formspecs.lua")
|
||||
dofile(clientpath .. "chatcommands.lua")
|
||||
dofile(clientpath .. "death_formspec.lua")
|
||||
dofile(clientpath .. "misc.lua")
|
||||
assert(loadfile(commonpath .. "item_s.lua"))({}) -- Just for push/read node functions
|
||||
|
|
|
@ -23,6 +23,8 @@ core.add_node = core.set_node
|
|||
-- we don't deal with metadata currently
|
||||
core.swap_node = core.set_node
|
||||
|
||||
core.bulk_swap_node = core.bulk_set_node
|
||||
|
||||
function core.remove_node(pos)
|
||||
return core.vmanip:set_node_at(pos, {name="air"})
|
||||
end
|
||||
|
|
|
@ -28,10 +28,8 @@ local function buttonbar_formspec(self)
|
|||
end
|
||||
|
||||
local formspec = {
|
||||
"style_type[box;noclip=true]",
|
||||
string.format("box[%f,%f;%f,%f;%s]", self.pos.x, self.pos.y, self.size.x,
|
||||
self.size.y, self.bgcolor),
|
||||
"style_type[box;noclip=false]",
|
||||
}
|
||||
|
||||
local btn_size = self.size.y - 2*BASE_SPACING
|
||||
|
@ -71,7 +69,7 @@ local function buttonbar_formspec(self)
|
|||
y = self.pos.y + BASE_SPACING,
|
||||
}
|
||||
|
||||
table.insert(formspec, string.format("image_button[%f,%f;%f,%f;%s;%s;%s;true;false]tooltip[%s;%s]",
|
||||
table.insert(formspec, string.format("image_button[%f,%f;%f,%f;%s;%s;%s;false;false]tooltip[%s;%s]",
|
||||
btn_pos.x, btn_pos.y, btn_size, btn_size, btn.image, btn.name,
|
||||
btn.caption, btn.name, btn.tooltip))
|
||||
end
|
||||
|
@ -86,9 +84,6 @@ local function buttonbar_formspec(self)
|
|||
y = self.pos.y + BASE_SPACING,
|
||||
}
|
||||
|
||||
table.insert(formspec, string.format("style[%s,%s;noclip=true]",
|
||||
self.btn_prev_name, self.btn_next_name))
|
||||
|
||||
table.insert(formspec, string.format("button[%f,%f;%f,%f;%s;<]",
|
||||
btn_prev_pos.x, btn_prev_pos.y, get_scroll_btn_width(), btn_size,
|
||||
self.btn_prev_name))
|
||||
|
|
|
@ -66,11 +66,22 @@ local function get_formspec(self)
|
|||
|
||||
local content, prepend = tab.get_formspec(self, tab.name, tab.tabdata, tab.tabsize)
|
||||
|
||||
local tsize = tab.tabsize or { width = self.width, height = self.height }
|
||||
local ENABLE_TOUCH = core.settings:get_bool("enable_touch")
|
||||
|
||||
local orig_tsize = tab.tabsize or { width = self.width, height = self.height }
|
||||
local tsize = { width = orig_tsize.width, height = orig_tsize.height }
|
||||
tsize.height = tsize.height
|
||||
+ TABHEADER_H -- tabheader included in formspec size
|
||||
+ (ENABLE_TOUCH and GAMEBAR_OFFSET_TOUCH or GAMEBAR_OFFSET_DESKTOP)
|
||||
+ GAMEBAR_H -- gamebar included in formspec size
|
||||
|
||||
if self.parent == nil and not prepend then
|
||||
prepend = string.format("size[%f,%f,%s]", tsize.width, tsize.height,
|
||||
dump(self.fixed_size))
|
||||
|
||||
local anchor_pos = TABHEADER_H + orig_tsize.height / 2
|
||||
prepend = prepend .. ("anchor[0.5,%f]"):format(anchor_pos / tsize.height)
|
||||
|
||||
if tab.formspec_version then
|
||||
prepend = ("formspec_version[%d]"):format(tab.formspec_version) .. prepend
|
||||
end
|
||||
|
@ -78,12 +89,15 @@ local function get_formspec(self)
|
|||
|
||||
local end_button_size = 0.75
|
||||
|
||||
local tab_header_size = { width = tsize.width, height = 0.85 }
|
||||
local tab_header_size = { width = tsize.width, height = TABHEADER_H }
|
||||
if self.end_button then
|
||||
tab_header_size.width = tab_header_size.width - end_button_size - 0.1
|
||||
end
|
||||
|
||||
local formspec = (prepend or "") .. self:tab_header(tab_header_size) .. content
|
||||
local formspec = (prepend or "")
|
||||
formspec = formspec .. ("bgcolor[;neither]container[0,%f]box[0,0;%f,%f;#0000008C]"):format(
|
||||
TABHEADER_H, orig_tsize.width, orig_tsize.height)
|
||||
formspec = formspec .. self:tab_header(tab_header_size) .. content
|
||||
|
||||
if self.end_button then
|
||||
formspec = formspec ..
|
||||
|
@ -98,6 +112,8 @@ local function get_formspec(self)
|
|||
self.end_button.name)
|
||||
end
|
||||
|
||||
formspec = formspec .. "container_end[]"
|
||||
|
||||
return formspec
|
||||
end
|
||||
|
||||
|
|
31
builtin/game/death_screen.lua
Normal file
31
builtin/game/death_screen.lua
Normal file
|
@ -0,0 +1,31 @@
|
|||
local F = core.formspec_escape
|
||||
local S = core.get_translator("__builtin")
|
||||
|
||||
function core.show_death_screen(player, _reason)
|
||||
local fs = {
|
||||
"formspec_version[1]",
|
||||
"size[11,5.5,true]",
|
||||
"bgcolor[#320000b4;true]",
|
||||
"label[4.85,1.35;", F(S("You died")), "]",
|
||||
"button_exit[4,3;3,0.5;btn_respawn;", F(S("Respawn")), "]",
|
||||
}
|
||||
core.show_formspec(player:get_player_name(), "__builtin:death", table.concat(fs, ""))
|
||||
end
|
||||
|
||||
core.register_on_dieplayer(function(player, reason)
|
||||
core.show_death_screen(player, reason)
|
||||
end)
|
||||
|
||||
core.register_on_joinplayer(function(player)
|
||||
if player:get_hp() == 0 then
|
||||
core.show_death_screen(player, nil)
|
||||
end
|
||||
end)
|
||||
|
||||
core.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname == "__builtin:death" and fields.quit and player:get_hp() == 0 then
|
||||
player:respawn()
|
||||
core.log("action", player:get_player_name() .. " respawns at " ..
|
||||
player:get_pos():to_string())
|
||||
end
|
||||
end)
|
|
@ -43,6 +43,8 @@ core.features = {
|
|||
moveresult_new_pos = true,
|
||||
override_item_remove_fields = true,
|
||||
hotbar_hud_element = true,
|
||||
bulk_lbms = true,
|
||||
abm_without_neighbors = true,
|
||||
}
|
||||
|
||||
function core.has_feature(arg)
|
||||
|
|
|
@ -38,6 +38,7 @@ dofile(gamepath .. "forceloading.lua")
|
|||
dofile(gamepath .. "hud.lua")
|
||||
dofile(gamepath .. "knockback.lua")
|
||||
dofile(gamepath .. "async.lua")
|
||||
dofile(gamepath .. "death_screen.lua")
|
||||
|
||||
core.after(0, builtin_shared.cache_content_ids)
|
||||
|
||||
|
|
|
@ -6,14 +6,14 @@ local S = core.get_translator("__builtin")
|
|||
-- Misc. API functions
|
||||
--
|
||||
|
||||
-- @spec core.kick_player(String, String) :: Boolean
|
||||
function core.kick_player(player_name, reason)
|
||||
-- @spec core.kick_player(String, String, Boolean) :: Boolean
|
||||
function core.kick_player(player_name, reason, reconnect)
|
||||
if type(reason) == "string" then
|
||||
reason = "Kicked: " .. reason
|
||||
else
|
||||
reason = "Kicked."
|
||||
end
|
||||
return core.disconnect_player(player_name, reason)
|
||||
return core.disconnect_player(player_name, reason, reconnect)
|
||||
end
|
||||
|
||||
function core.check_player_privs(name, ...)
|
||||
|
@ -298,3 +298,28 @@ do
|
|||
return valid_object_iterator(core.get_objects_in_area(min_pos, max_pos))
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Helper for LBM execution, called from C++
|
||||
--
|
||||
|
||||
function core.run_lbm(id, pos_list, dtime_s)
|
||||
local lbm = core.registered_lbms[id]
|
||||
assert(lbm, "Entry with given id not found in registered_lbms table")
|
||||
core.set_last_run_mod(lbm.mod_origin)
|
||||
if lbm.bulk_action then
|
||||
return lbm.bulk_action(pos_list, dtime_s)
|
||||
end
|
||||
-- emulate non-bulk LBMs
|
||||
local expect = core.get_node(pos_list[1]).name
|
||||
-- engine guarantees that
|
||||
-- 1) all nodes are the same content type
|
||||
-- 2) the list is up-to-date when we're called
|
||||
assert(expect ~= "ignore")
|
||||
for _, pos in ipairs(pos_list) do
|
||||
local n = core.get_node(pos)
|
||||
if n.name == expect then -- might have been changed by previous call
|
||||
lbm.action(pos, n, dtime_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -105,7 +105,12 @@ function core.register_lbm(spec)
|
|||
-- Add to core.registered_lbms
|
||||
check_modname_prefix(spec.name)
|
||||
check_node_list(spec.nodenames, "nodenames")
|
||||
assert(type(spec.action) == "function", "Required field 'action' of type function")
|
||||
local have = spec.action ~= nil
|
||||
local have_bulk = spec.bulk_action ~= nil
|
||||
assert(not have or type(spec.action) == "function", "Field 'action' must be a function")
|
||||
assert(not have_bulk or type(spec.bulk_action) == "function", "Field 'bulk_action' must be a function")
|
||||
assert(have ~= have_bulk, "Either 'action' or 'bulk_action' must be present")
|
||||
|
||||
core.registered_lbms[#core.registered_lbms + 1] = spec
|
||||
spec.mod_origin = core.get_current_modname() or "??"
|
||||
end
|
||||
|
|
3
builtin/locale/__builtin.be.tr
Normal file
3
builtin/locale/__builtin.be.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Вы загінулі
|
||||
Respawn=Адрадзіцца
|
3
builtin/locale/__builtin.bg.tr
Normal file
3
builtin/locale/__builtin.bg.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Умряхте
|
||||
Respawn=Прераждане
|
3
builtin/locale/__builtin.ca.tr
Normal file
3
builtin/locale/__builtin.ca.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Has mort
|
||||
Respawn=Reaparèixer
|
3
builtin/locale/__builtin.cs.tr
Normal file
3
builtin/locale/__builtin.cs.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Zemřel jsi
|
||||
Respawn=Oživit
|
3
builtin/locale/__builtin.cy.tr
Normal file
3
builtin/locale/__builtin.cy.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Buest ti farw
|
||||
Respawn=Atgyfodi
|
3
builtin/locale/__builtin.da.tr
Normal file
3
builtin/locale/__builtin.da.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Du døde
|
||||
Respawn=Genopstå
|
|
@ -244,3 +244,5 @@ A total of @1 sample(s) were taken.=Es wurden insgesamt @1 Datenpunkt(e) aufgeze
|
|||
The output is limited to '@1'.=Die Ausgabe ist beschränkt auf „@1“.
|
||||
Saving of profile failed: @1=Speichern des Profils fehlgeschlagen: @1
|
||||
Profile saved to @1=Profil abgespeichert nach @1
|
||||
You died=Sie sind gestorben
|
||||
Respawn=Wiederbeleben
|
||||
|
|
3
builtin/locale/__builtin.el.tr
Normal file
3
builtin/locale/__builtin.el.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Πέθανες
|
||||
Respawn=Επανεμφάνηση
|
|
@ -244,3 +244,5 @@ A total of @1 sample(s) were taken.=Sume @1 ekzemplero(j) konserviĝis.
|
|||
The output is limited to '@1'.=La eligo estas limigita al «@1».
|
||||
Saving of profile failed: @1=Konservado de profilo malsukcesis: @1
|
||||
Profile saved to @1=Profilo konservita al @1
|
||||
You died=Vi mortis
|
||||
Respawn=Renaskiĝi
|
||||
|
|
3
builtin/locale/__builtin.es.tr
Normal file
3
builtin/locale/__builtin.es.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Has muerto
|
||||
Respawn=Reaparecer
|
3
builtin/locale/__builtin.et.tr
Normal file
3
builtin/locale/__builtin.et.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Said surma
|
||||
Respawn=Ärka ellu
|
3
builtin/locale/__builtin.eu.tr
Normal file
3
builtin/locale/__builtin.eu.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Hil zara
|
||||
Respawn=Birsortu
|
3
builtin/locale/__builtin.fi.tr
Normal file
3
builtin/locale/__builtin.fi.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Kuolit
|
||||
Respawn=Synny uudelleen
|
3
builtin/locale/__builtin.fil.tr
Normal file
3
builtin/locale/__builtin.fil.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Namatay ka
|
||||
Respawn=Mag-respawn
|
|
@ -244,3 +244,5 @@ A total of @1 sample(s) were taken.=@1 échantillons ont été collectés.
|
|||
The output is limited to '@1'.=La sortie est limitée à '@1'.
|
||||
Saving of profile failed: @1=La sauvegarde du profil a échoué : @1
|
||||
Profile saved to @1=Le profil a été sauvegardé dans @1
|
||||
You died=Vous êtes mort
|
||||
Respawn=Réapparaître
|
||||
|
|
3
builtin/locale/__builtin.ga.tr
Normal file
3
builtin/locale/__builtin.ga.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Fuair tú bás
|
||||
Respawn=Athsceith
|
3
builtin/locale/__builtin.gl.tr
Normal file
3
builtin/locale/__builtin.gl.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Morreches
|
||||
Respawn=Reaparecer
|
3
builtin/locale/__builtin.hu.tr
Normal file
3
builtin/locale/__builtin.hu.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Meghaltál
|
||||
Respawn=Újraéledés
|
|
@ -244,3 +244,5 @@ A total of @1 sample(s) were taken.=Total @1 sampel yang diambil.
|
|||
The output is limited to '@1'.=Keluaran dibatasi ke '@1'.
|
||||
Saving of profile failed: @1=Penyimpanan profil gagal: @1
|
||||
Profile saved to @1=Profil disimpan ke @1
|
||||
You died=Anda mati
|
||||
Respawn=Bangkit kembali
|
||||
|
|
|
@ -245,3 +245,5 @@ A total of @1 sample(s) were taken.=Son stati ottenuti campioni per un totale di
|
|||
The output is limited to '@1'.=L'output è limitato a '@1'.
|
||||
Saving of profile failed: @1=Errore nel salvare il profilo: @1
|
||||
Profile saved to @1=Profilo salvato in @1
|
||||
You died=Sei morto
|
||||
Respawn=Rinasci
|
||||
|
|
3
builtin/locale/__builtin.ja.tr
Normal file
3
builtin/locale/__builtin.ja.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=死んでしまった
|
||||
Respawn=リスポーン
|
3
builtin/locale/__builtin.jbo.tr
Normal file
3
builtin/locale/__builtin.jbo.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=.i do morsi
|
||||
Respawn=tolcanci
|
3
builtin/locale/__builtin.jv.tr
Normal file
3
builtin/locale/__builtin.jv.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Panjenengan pejah
|
||||
Respawn=Bangkit Malilh
|
3
builtin/locale/__builtin.ko.tr
Normal file
3
builtin/locale/__builtin.ko.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=사망했습니다
|
||||
Respawn=리스폰
|
3
builtin/locale/__builtin.kv.tr
Normal file
3
builtin/locale/__builtin.kv.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Кулінныд
|
||||
Respawn=Ловзьыны
|
3
builtin/locale/__builtin.ky.tr
Normal file
3
builtin/locale/__builtin.ky.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Сиз өлдүңүз.
|
||||
Respawn=Кайтадан жаралуу
|
3
builtin/locale/__builtin.lt.tr
Normal file
3
builtin/locale/__builtin.lt.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Jūs numirėte
|
||||
Respawn=Prisikelti
|
3
builtin/locale/__builtin.lv.tr
Normal file
3
builtin/locale/__builtin.lv.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Jūs nomirāt
|
||||
Respawn=Atdzīvoties
|
3
builtin/locale/__builtin.lzh.tr
Normal file
3
builtin/locale/__builtin.lzh.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=尔死矣
|
||||
Respawn=复生
|
3
builtin/locale/__builtin.mn.tr
Normal file
3
builtin/locale/__builtin.mn.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Та үхсэн
|
||||
Respawn=Дахин төрөх
|
3
builtin/locale/__builtin.mr.tr
Normal file
3
builtin/locale/__builtin.mr.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=तू मेलास
|
||||
Respawn=पुनर्जन्म
|
|
@ -244,3 +244,5 @@ A total of @1 sample(s) were taken.=Sebanyak @1 sampel telah diambil secara kese
|
|||
The output is limited to '@1'.=Output dihadkan kepada '@1'.
|
||||
Saving of profile failed: @1=Penyimpanan profil telah gagal: @1
|
||||
Profile saved to @1=Profil telah disimpan ke @1
|
||||
You died=Anda telah meninggal
|
||||
Respawn=Jelma semula
|
||||
|
|
3
builtin/locale/__builtin.nb.tr
Normal file
3
builtin/locale/__builtin.nb.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Du døde
|
||||
Respawn=Gjenoppstå
|
3
builtin/locale/__builtin.nl.tr
Normal file
3
builtin/locale/__builtin.nl.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Je bent gestorven
|
||||
Respawn=Herboren worden
|
3
builtin/locale/__builtin.nn.tr
Normal file
3
builtin/locale/__builtin.nn.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Du døydde
|
||||
Respawn=Kom opp att
|
3
builtin/locale/__builtin.oc.tr
Normal file
3
builtin/locale/__builtin.oc.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Setz mòrt·a
|
||||
Respawn=Tornar
|
3
builtin/locale/__builtin.pl.tr
Normal file
3
builtin/locale/__builtin.pl.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Nie żyjesz
|
||||
Respawn=Wróć do gry
|
3
builtin/locale/__builtin.pt.tr
Normal file
3
builtin/locale/__builtin.pt.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Você morreu
|
||||
Respawn=Renascer
|
|
@ -244,3 +244,5 @@ A total of @1 sample(s) were taken.=Um total de @1 amostra(s) foi coletada.
|
|||
The output is limited to '@1'.=A saída é limitada a '@1'.
|
||||
Saving of profile failed: @1=Falha ao salvar o perfil: @1
|
||||
Profile saved to @1=Perfil salvo em @1
|
||||
You died=Você morreu
|
||||
Respawn=Reviver
|
||||
|
|
3
builtin/locale/__builtin.ro.tr
Normal file
3
builtin/locale/__builtin.ro.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Ai murit
|
||||
Respawn=Reînviere
|
|
@ -244,3 +244,5 @@ A total of @1 sample(s) were taken.=Всего было взято @1 образ
|
|||
The output is limited to '@1'.=Вывод ограничен значением '@1'.
|
||||
Saving of profile failed: @1=Не удалось сохранить данные профилирования: @1
|
||||
Profile saved to @1=Данные профилирования сохранены в @1
|
||||
You died=Вы умерли
|
||||
Respawn=Возродиться
|
||||
|
|
3
builtin/locale/__builtin.sk.tr
Normal file
3
builtin/locale/__builtin.sk.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Zomrel si
|
||||
Respawn=Oživiť
|
3
builtin/locale/__builtin.sl.tr
Normal file
3
builtin/locale/__builtin.sl.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Umrl si
|
||||
Respawn=Ponovno oživi
|
3
builtin/locale/__builtin.sr_Cyrl.tr
Normal file
3
builtin/locale/__builtin.sr_Cyrl.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Умро си
|
||||
Respawn=Врати се у живот
|
3
builtin/locale/__builtin.sr_Latn.tr
Normal file
3
builtin/locale/__builtin.sr_Latn.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Umro/la si.
|
||||
Respawn=Vrati se u zivot
|
3
builtin/locale/__builtin.sv.tr
Normal file
3
builtin/locale/__builtin.sv.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Du dog
|
||||
Respawn=Återuppstå
|
3
builtin/locale/__builtin.sw.tr
Normal file
3
builtin/locale/__builtin.sw.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Umekufa.
|
||||
Respawn=Respawn
|
3
builtin/locale/__builtin.tok.tr
Normal file
3
builtin/locale/__builtin.tok.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=sina moli
|
||||
Respawn=o kama sin
|
3
builtin/locale/__builtin.tr.tr
Normal file
3
builtin/locale/__builtin.tr.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Öldün
|
||||
Respawn=Yeniden Canlan
|
3
builtin/locale/__builtin.tt.tr
Normal file
3
builtin/locale/__builtin.tt.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Сез үлдегез
|
||||
Respawn=Тергезелергә
|
3
builtin/locale/__builtin.uk.tr
Normal file
3
builtin/locale/__builtin.uk.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Ви загинули
|
||||
Respawn=Відродитися
|
3
builtin/locale/__builtin.vi.tr
Normal file
3
builtin/locale/__builtin.vi.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=Bạn đã bị chết
|
||||
Respawn=Hồi sinh
|
3
builtin/locale/__builtin.zh_CN.tr
Normal file
3
builtin/locale/__builtin.zh_CN.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=您已死亡
|
||||
Respawn=重生
|
3
builtin/locale/__builtin.zh_TW.tr
Normal file
3
builtin/locale/__builtin.zh_TW.tr
Normal file
|
@ -0,0 +1,3 @@
|
|||
# textdomain: __builtin
|
||||
You died=您已死亡
|
||||
Respawn=重生
|
|
@ -23,6 +23,13 @@ mt_color_dark_green = "#25C191"
|
|||
mt_color_orange = "#FF8800"
|
||||
mt_color_red = "#FF3300"
|
||||
|
||||
MAIN_TAB_W = 15.5
|
||||
MAIN_TAB_H = 7.1
|
||||
TABHEADER_H = 0.85
|
||||
GAMEBAR_H = 1.25
|
||||
GAMEBAR_OFFSET_DESKTOP = 0.375
|
||||
GAMEBAR_OFFSET_TOUCH = 0.15
|
||||
|
||||
local menupath = core.get_mainmenu_path()
|
||||
local basepath = core.get_builtin_path()
|
||||
defaulttexturedir = core.get_texturepath_share() .. DIR_DELIM .. "base" ..
|
||||
|
@ -89,7 +96,7 @@ local function init_globals()
|
|||
mm_game_theme.set_engine() -- This is just a fallback.
|
||||
|
||||
-- Create main tabview
|
||||
local tv_main = tabview_create("maintab", {x = 15.5, y = 7.1}, {x = 0, y = 0})
|
||||
local tv_main = tabview_create("maintab", {x = MAIN_TAB_W, y = MAIN_TAB_H}, {x = 0, y = 0})
|
||||
|
||||
tv_main:set_autosave_tab(true)
|
||||
tv_main:add(tabs.local_game)
|
||||
|
|
|
@ -92,10 +92,16 @@ function singleplayer_refresh_gamebar()
|
|||
end
|
||||
end
|
||||
|
||||
local ENABLE_TOUCH = core.settings:get_bool("enable_touch")
|
||||
|
||||
local gamebar_pos_y = MAIN_TAB_H
|
||||
+ TABHEADER_H -- tabheader included in formspec size
|
||||
+ (ENABLE_TOUCH and GAMEBAR_OFFSET_TOUCH or GAMEBAR_OFFSET_DESKTOP)
|
||||
|
||||
local btnbar = buttonbar_create(
|
||||
"game_button_bar",
|
||||
core.settings:get_bool("touch_gui") and {x = 0, y = 7.25} or {x = 0, y = 7.475},
|
||||
{x = 15.5, y = 1.25},
|
||||
{x = 0, y = gamebar_pos_y},
|
||||
{x = MAIN_TAB_W, y = GAMEBAR_H},
|
||||
"#000000",
|
||||
game_buttonbar_button_handler)
|
||||
|
||||
|
|
|
@ -217,8 +217,9 @@ local function init()
|
|||
-- Wrap register_lbm() to automatically instrument lbms.
|
||||
local orig_register_lbm = core.register_lbm
|
||||
core.register_lbm = function(spec)
|
||||
spec.action = instrument {
|
||||
func = spec.action,
|
||||
local k = spec.bulk_action ~= nil and "bulk_action" or "action"
|
||||
spec[k] = instrument {
|
||||
func = spec[k],
|
||||
class = "LBM",
|
||||
label = spec.label or spec.name,
|
||||
}
|
||||
|
|
|
@ -403,6 +403,11 @@ enable_clouds (Clouds) bool true
|
|||
# Requires: enable_clouds
|
||||
enable_3d_clouds (3D clouds) bool true
|
||||
|
||||
# Use smooth cloud shading.
|
||||
#
|
||||
# Requires: enable_3d_clouds, enable_clouds
|
||||
soft_clouds (Soft clouds) bool false
|
||||
|
||||
[**Filtering and Antialiasing]
|
||||
|
||||
# Use mipmaps when scaling textures. May slightly increase performance,
|
||||
|
@ -505,6 +510,11 @@ water_wave_length (Waving liquids wavelength) float 20.0 0.1
|
|||
# Requires: shaders, enable_waving_water
|
||||
water_wave_speed (Waving liquids wave speed) float 5.0
|
||||
|
||||
# When enabled, liquid reflections are simulated.
|
||||
#
|
||||
# Requires: shaders, enable_waving_water, enable_dynamic_shadows
|
||||
enable_water_reflections (Liquid reflections) bool false
|
||||
|
||||
[**Dynamic shadows]
|
||||
|
||||
# Set to true to enable Shadow Mapping.
|
||||
|
@ -661,6 +671,18 @@ bloom_radius (Bloom Radius) float 1 0.1 8
|
|||
# Requires: shaders, enable_post_processing, enable_bloom
|
||||
enable_volumetric_lighting (Volumetric lighting) bool false
|
||||
|
||||
[**Other Effects]
|
||||
|
||||
# Simulate translucency when looking at foliage in the sunlight.
|
||||
#
|
||||
# Requires: shaders, enable_dynamic_shadows
|
||||
enable_translucent_foliage (Translucent foliage) bool false
|
||||
|
||||
# Apply specular shading to nodes.
|
||||
#
|
||||
# Requires: shaders, enable_dynamic_shadows
|
||||
enable_node_specular (Node specular) bool false
|
||||
|
||||
[*Audio]
|
||||
|
||||
# Volume of all sounds.
|
||||
|
@ -1030,7 +1052,7 @@ mapgen_limit (Map generation limit) int 31007 0 31007
|
|||
# Global map generation attributes.
|
||||
# In Mapgen v6 the 'decorations' flag controls all decorations except trees
|
||||
# and jungle grass, in all other mapgens this flag controls all decorations.
|
||||
mg_flags (Mapgen flags) flags caves,dungeons,light,decorations,biomes,ores caves,dungeons,light,decorations,biomes,ores,nocaves,nodungeons,nolight,nodecorations,nobiomes,noores
|
||||
mg_flags (Mapgen flags) flags caves,dungeons,light,decorations,biomes,ores caves,dungeons,light,decorations,biomes,ores
|
||||
|
||||
[*Biome API]
|
||||
|
||||
|
@ -1049,7 +1071,7 @@ mg_biome_np_humidity_blend (Humidity blend noise) noise_params_2d 0, 1.5, (8, 8,
|
|||
[*Mapgen V5]
|
||||
|
||||
# Map generation attributes specific to Mapgen v5.
|
||||
mgv5_spflags (Mapgen V5 specific flags) flags caverns caverns,nocaverns
|
||||
mgv5_spflags (Mapgen V5 specific flags) flags caverns caverns
|
||||
|
||||
# Controls width of tunnels, a smaller value creates wider tunnels.
|
||||
# Value >= 10.0 completely disables generation of tunnels and avoids the
|
||||
|
@ -1123,7 +1145,7 @@ mgv5_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500), 0, 2
|
|||
# When the 'snowbiomes' flag is enabled jungles are automatically enabled and
|
||||
# the 'jungles' flag is ignored.
|
||||
# The 'temples' flag disables generation of desert temples. Normal dungeons will appear instead.
|
||||
mgv6_spflags (Mapgen V6 specific flags) flags jungles,biomeblend,mudflow,snowbiomes,noflat,trees,temples jungles,biomeblend,mudflow,snowbiomes,flat,trees,temples,nojungles,nobiomeblend,nomudflow,nosnowbiomes,noflat,notrees,notemples
|
||||
mgv6_spflags (Mapgen V6 specific flags) flags jungles,biomeblend,mudflow,snowbiomes,noflat,trees,temples jungles,biomeblend,mudflow,snowbiomes,flat,trees,temples
|
||||
|
||||
# Deserts occur when np_biome exceeds this value.
|
||||
# When the 'snowbiomes' flag is enabled, this is ignored.
|
||||
|
@ -1179,7 +1201,7 @@ mgv6_np_apple_trees (Apple trees noise) noise_params_2d 0, 1, (100, 100, 100), 3
|
|||
# 'ridges': Rivers.
|
||||
# 'floatlands': Floating land masses in the atmosphere.
|
||||
# 'caverns': Giant caves deep underground.
|
||||
mgv7_spflags (Mapgen V7 specific flags) flags mountains,ridges,nofloatlands,caverns mountains,ridges,floatlands,caverns,nomountains,noridges,nofloatlands,nocaverns
|
||||
mgv7_spflags (Mapgen V7 specific flags) flags mountains,ridges,nofloatlands,caverns mountains,ridges,floatlands,caverns
|
||||
|
||||
# Y of mountain density gradient zero level. Used to shift mountains vertically.
|
||||
mgv7_mount_zero_level (Mountain zero level) int 0 -31000 31000
|
||||
|
@ -1313,7 +1335,7 @@ mgv7_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500), 0, 2
|
|||
[*Mapgen Carpathian]
|
||||
|
||||
# Map generation attributes specific to Mapgen Carpathian.
|
||||
mgcarpathian_spflags (Mapgen Carpathian specific flags) flags caverns,norivers caverns,rivers,nocaverns,norivers
|
||||
mgcarpathian_spflags (Mapgen Carpathian specific flags) flags caverns,norivers caverns,rivers
|
||||
|
||||
# Defines the base ground level.
|
||||
mgcarpathian_base_level (Base ground level) float 12.0
|
||||
|
@ -1422,7 +1444,7 @@ mgcarpathian_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 50
|
|||
|
||||
# Map generation attributes specific to Mapgen Flat.
|
||||
# Occasional lakes and hills can be added to the flat world.
|
||||
mgflat_spflags (Mapgen Flat specific flags) flags nolakes,nohills,nocaverns lakes,hills,caverns,nolakes,nohills,nocaverns
|
||||
mgflat_spflags (Mapgen Flat specific flags) flags nolakes,nohills,nocaverns lakes,hills,caverns
|
||||
|
||||
# Y of flat ground.
|
||||
mgflat_ground_level (Ground level) int 8 -31000 31000
|
||||
|
@ -1506,7 +1528,7 @@ mgflat_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500), 0,
|
|||
# Map generation attributes specific to Mapgen Fractal.
|
||||
# 'terrain' enables the generation of non-fractal terrain:
|
||||
# ocean, islands and underground.
|
||||
mgfractal_spflags (Mapgen Fractal specific flags) flags terrain terrain,noterrain
|
||||
mgfractal_spflags (Mapgen Fractal specific flags) flags terrain terrain
|
||||
|
||||
# Controls width of tunnels, a smaller value creates wider tunnels.
|
||||
# Value >= 10.0 completely disables generation of tunnels and avoids the
|
||||
|
@ -1640,7 +1662,7 @@ mgfractal_np_dungeons (Dungeon noise) noise_params_3d 0.9, 0.5, (500, 500, 500),
|
|||
# 'vary_river_depth': If enabled, low humidity and high heat causes rivers
|
||||
# to become shallower and occasionally dry.
|
||||
# 'altitude_dry': Reduces humidity with altitude.
|
||||
mgvalleys_spflags (Mapgen Valleys specific flags) flags altitude_chill,humid_rivers,vary_river_depth,altitude_dry altitude_chill,humid_rivers,vary_river_depth,altitude_dry,noaltitude_chill,nohumid_rivers,novary_river_depth,noaltitude_dry
|
||||
mgvalleys_spflags (Mapgen Valleys specific flags) flags altitude_chill,humid_rivers,vary_river_depth,altitude_dry altitude_chill,humid_rivers,vary_river_depth,altitude_dry
|
||||
|
||||
# The vertical distance over which heat drops by 20 if 'altitude_chill' is
|
||||
# enabled. Also, the vertical distance over which humidity drops by 10 if
|
||||
|
|
|
@ -11,7 +11,6 @@ attribute vec2 inTexCoord0;
|
|||
|
||||
uniform mat4 uWVPMatrix;
|
||||
uniform mat4 uWVMatrix;
|
||||
uniform mat4 uNMatrix;
|
||||
uniform mat4 uTMatrix0;
|
||||
|
||||
uniform float uThickness;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
uniform lowp vec4 emissiveColor;
|
||||
uniform lowp vec4 materialColor;
|
||||
|
||||
varying lowp vec4 varColor;
|
||||
|
||||
|
@ -14,7 +14,7 @@ void main(void)
|
|||
vec4 color = inVertexColor;
|
||||
#endif
|
||||
|
||||
color *= emissiveColor;
|
||||
color *= materialColor;
|
||||
varColor = color;
|
||||
|
||||
eyeVec = -(mWorldView * inVertexPosition).xyz;
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
#if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_TRANSPARENT || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_OPAQUE || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LIQUID_BASIC || MATERIAL_TYPE == TILE_MATERIAL_LIQUID_TRANSPARENT)
|
||||
#define MATERIAL_WAVING_LIQUID 1
|
||||
#endif
|
||||
|
||||
uniform sampler2D baseTexture;
|
||||
|
||||
uniform vec3 dayLight;
|
||||
|
@ -7,6 +11,7 @@ uniform float fogShadingParameter;
|
|||
|
||||
// The cameraOffset is the current center of the visible world.
|
||||
uniform highp vec3 cameraOffset;
|
||||
uniform vec3 cameraPosition;
|
||||
uniform float animationTimer;
|
||||
#ifdef ENABLE_DYNAMIC_SHADOWS
|
||||
// shadow texture
|
||||
|
@ -20,6 +25,7 @@ uniform float animationTimer;
|
|||
uniform vec4 CameraPos;
|
||||
uniform float xyPerspectiveBias0;
|
||||
uniform float xyPerspectiveBias1;
|
||||
uniform vec3 shadow_tint;
|
||||
|
||||
varying float adj_shadow_strength;
|
||||
varying float cosLight;
|
||||
|
@ -47,6 +53,49 @@ varying highp vec3 eyeVec;
|
|||
varying float nightRatio;
|
||||
|
||||
#ifdef ENABLE_DYNAMIC_SHADOWS
|
||||
#if (defined(MATERIAL_WAVING_LIQUID) && defined(ENABLE_WATER_REFLECTIONS) && ENABLE_WAVING_WATER)
|
||||
vec4 perm(vec4 x)
|
||||
{
|
||||
return mod(((x * 34.0) + 1.0) * x, 289.0);
|
||||
}
|
||||
|
||||
// Corresponding gradient of snoise
|
||||
vec3 gnoise(vec3 p){
|
||||
vec3 a = floor(p);
|
||||
vec3 d = p - a;
|
||||
vec3 dd = 6.0 * d * (1.0 - d);
|
||||
d = d * d * (3.0 - 2.0 * d);
|
||||
|
||||
vec4 b = a.xxyy + vec4(0.0, 1.0, 0.0, 1.0);
|
||||
vec4 k1 = perm(b.xyxy);
|
||||
vec4 k2 = perm(k1.xyxy + b.zzww);
|
||||
|
||||
vec4 c = k2 + a.zzzz;
|
||||
vec4 k3 = perm(c);
|
||||
vec4 k4 = perm(c + 1.0);
|
||||
|
||||
vec4 o1 = fract(k3 * (1.0 / 41.0));
|
||||
vec4 o2 = fract(k4 * (1.0 / 41.0));
|
||||
|
||||
vec4 o3 = o2 * d.z + o1 * (1.0 - d.z);
|
||||
vec2 o4 = o3.yw * d.x + o3.xz * (1.0 - d.x);
|
||||
|
||||
vec4 dz1 = (o2 - o1) * dd.z;
|
||||
vec2 dz2 = dz1.yw * d.x + dz1.xz * (1.0 - d.x);
|
||||
|
||||
vec2 dx = (o3.yw - o3.xz) * dd.x;
|
||||
|
||||
return vec3(
|
||||
dx.y * d.y + dx.x * (1. - d.y),
|
||||
(o4.y - o4.x) * dd.y,
|
||||
dz2.y * d.y + dz2.x * (1. - d.y)
|
||||
);
|
||||
}
|
||||
|
||||
vec2 wave_noise(vec3 p, float off) {
|
||||
return (gnoise(p + vec3(0.0, 0.0, off)) * 0.4 + gnoise(2.0 * p + vec3(0.0, off, off)) * 0.2 + gnoise(3.0 * p + vec3(0.0, off, off)) * 0.225 + gnoise(4.0 * p + vec3(-off, off, 0.0)) * 0.2).xz;
|
||||
}
|
||||
#endif
|
||||
|
||||
// assuming near is always 1.0
|
||||
float getLinearDepth()
|
||||
|
@ -66,6 +115,14 @@ float mtsmoothstep(in float edge0, in float edge1, in float x)
|
|||
return t * t * (3.0 - 2.0 * t);
|
||||
}
|
||||
|
||||
float shadowCutoff(float x) {
|
||||
#if defined(ENABLE_TRANSLUCENT_FOLIAGE) && MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES
|
||||
return mtsmoothstep(0.0, 0.002, x);
|
||||
#else
|
||||
return step(0.0, x);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef COLORED_SHADOWS
|
||||
|
||||
// c_precision of 128 fits within 7 base-10 digits
|
||||
|
@ -92,10 +149,10 @@ vec4 getHardShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDist
|
|||
{
|
||||
vec4 texDepth = texture2D(shadowsampler, smTexCoord.xy).rgba;
|
||||
|
||||
float visibility = step(0.0, realDistance - texDepth.r);
|
||||
float visibility = shadowCutoff(realDistance - texDepth.r);
|
||||
vec4 result = vec4(visibility, vec3(0.0,0.0,0.0));//unpackColor(texDepth.g));
|
||||
if (visibility < 0.1) {
|
||||
visibility = step(0.0, realDistance - texDepth.b);
|
||||
visibility = shadowCutoff(realDistance - texDepth.b);
|
||||
result = vec4(visibility, unpackColor(texDepth.a));
|
||||
}
|
||||
return result;
|
||||
|
@ -106,7 +163,7 @@ vec4 getHardShadowColor(sampler2D shadowsampler, vec2 smTexCoord, float realDist
|
|||
float getHardShadow(sampler2D shadowsampler, vec2 smTexCoord, float realDistance)
|
||||
{
|
||||
float texDepth = texture2D(shadowsampler, smTexCoord.xy).r;
|
||||
float visibility = step(0.0, realDistance - texDepth);
|
||||
float visibility = shadowCutoff(realDistance - texDepth);
|
||||
return visibility;
|
||||
}
|
||||
|
||||
|
@ -378,6 +435,9 @@ void main(void)
|
|||
vec4 col = vec4(color.rgb * varColor.rgb, 1.0);
|
||||
|
||||
#ifdef ENABLE_DYNAMIC_SHADOWS
|
||||
// Fragment normal, can differ from vNormal which is derived from vertex normals.
|
||||
vec3 fNormal = vNormal;
|
||||
|
||||
if (f_shadow_strength > 0.0) {
|
||||
float shadow_int = 0.0;
|
||||
vec3 shadow_color = vec3(0.0, 0.0, 0.0);
|
||||
|
@ -414,12 +474,19 @@ void main(void)
|
|||
// Power ratio was measured on torches in MTG (brightness = 14).
|
||||
float adjusted_night_ratio = pow(max(0.0, nightRatio), 0.6);
|
||||
|
||||
float shadow_uncorrected = shadow_int;
|
||||
|
||||
// Apply self-shadowing when light falls at a narrow angle to the surface
|
||||
// Cosine of the cut-off angle.
|
||||
const float self_shadow_cutoff_cosine = 0.035;
|
||||
if (f_normal_length != 0 && cosLight < self_shadow_cutoff_cosine) {
|
||||
shadow_int = max(shadow_int, 1 - clamp(cosLight, 0.0, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine);
|
||||
shadow_color = mix(vec3(0.0), shadow_color, min(cosLight, self_shadow_cutoff_cosine)/self_shadow_cutoff_cosine);
|
||||
|
||||
#if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES || MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS)
|
||||
// Prevents foliage from becoming insanely bright outside the shadow map.
|
||||
shadow_uncorrected = mix(shadow_int, shadow_uncorrected, clamp(distance_rate * 4.0 - 3.0, 0.0, 1.0));
|
||||
#endif
|
||||
}
|
||||
|
||||
shadow_int *= f_adj_shadow_strength;
|
||||
|
@ -428,8 +495,60 @@ void main(void)
|
|||
col.rgb =
|
||||
adjusted_night_ratio * col.rgb + // artificial light
|
||||
(1.0 - adjusted_night_ratio) * ( // natural light
|
||||
col.rgb * (1.0 - shadow_int * (1.0 - shadow_color)) + // filtered texture color
|
||||
col.rgb * (1.0 - shadow_int * (1.0 - shadow_color) * (1.0 - shadow_tint)) + // filtered texture color
|
||||
dayLight * shadow_color * shadow_int); // reflected filtered sunlight/moonlight
|
||||
|
||||
|
||||
vec3 reflect_ray = -normalize(v_LightDirection - fNormal * dot(v_LightDirection, fNormal) * 2.0);
|
||||
|
||||
vec3 viewVec = normalize(worldPosition + cameraOffset - cameraPosition);
|
||||
|
||||
// Water reflections
|
||||
#if (defined(MATERIAL_WAVING_LIQUID) && defined(ENABLE_WATER_REFLECTIONS) && ENABLE_WAVING_WATER)
|
||||
vec3 wavePos = worldPosition * vec3(2.0, 0.0, 2.0);
|
||||
float off = animationTimer * WATER_WAVE_SPEED * 10.0;
|
||||
wavePos.x /= WATER_WAVE_LENGTH * 3.0;
|
||||
wavePos.z /= WATER_WAVE_LENGTH * 2.0;
|
||||
|
||||
// This is an analogous method to the bumpmap, except we get the gradient information directly from gnoise.
|
||||
vec2 gradient = wave_noise(wavePos, off);
|
||||
fNormal = normalize(normalize(fNormal) + vec3(gradient.x, 0., gradient.y) * WATER_WAVE_HEIGHT * abs(fNormal.y) * 0.25);
|
||||
reflect_ray = -normalize(v_LightDirection - fNormal * dot(v_LightDirection, fNormal) * 2.0);
|
||||
float fresnel_factor = dot(fNormal, viewVec);
|
||||
|
||||
float brightness_factor = 1.0 - adjusted_night_ratio;
|
||||
|
||||
// A little trig hack. We go from the dot product of viewVec and normal to the dot product of viewVec and tangent to apply a fresnel effect.
|
||||
fresnel_factor = clamp(pow(1.0 - fresnel_factor * fresnel_factor, 8.0), 0.0, 1.0) * 0.8 + 0.2;
|
||||
col.rgb *= 0.5;
|
||||
vec3 reflection_color = mix(vec3(max(fogColor.r, max(fogColor.g, fogColor.b))), fogColor.rgb, f_shadow_strength);
|
||||
|
||||
// Sky reflection
|
||||
col.rgb += reflection_color * pow(fresnel_factor, 2.0) * 0.5 * brightness_factor;
|
||||
vec3 water_reflect_color = 12.0 * dayLight * fresnel_factor * mtsmoothstep(0.85, 0.9, pow(clamp(dot(reflect_ray, viewVec), 0.0, 1.0), 32.0)) * max(1.0 - shadow_uncorrected, 0.0);
|
||||
|
||||
// This line exists to prevent ridiculously bright reflection colors.
|
||||
water_reflect_color /= clamp(max(water_reflect_color.r, max(water_reflect_color.g, water_reflect_color.b)) * 0.375, 1.0, 400.0);
|
||||
col.rgb += water_reflect_color * f_adj_shadow_strength * brightness_factor;
|
||||
#endif
|
||||
|
||||
#if (defined(ENABLE_NODE_SPECULAR) && !defined(MATERIAL_WAVING_LIQUID))
|
||||
// Apply specular to blocks.
|
||||
if (dot(v_LightDirection, vNormal) < 0.0) {
|
||||
float intensity = 2.0 * (1.0 - (base.r * varColor.r));
|
||||
const float specular_exponent = 5.0;
|
||||
const float fresnel_exponent = 4.0;
|
||||
|
||||
col.rgb +=
|
||||
intensity * dayLight * (1.0 - nightRatio) * (1.0 - shadow_uncorrected) * f_adj_shadow_strength *
|
||||
pow(max(dot(reflect_ray, viewVec), 0.0), fresnel_exponent) * pow(1.0 - abs(dot(viewVec, fNormal)), specular_exponent);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (MATERIAL_TYPE == TILE_MATERIAL_WAVING_PLANTS || MATERIAL_TYPE == TILE_MATERIAL_WAVING_LEAVES) && defined(ENABLE_TRANSLUCENT_FOLIAGE)
|
||||
// Simulate translucent foliage.
|
||||
col.rgb += 4.0 * dayLight * base.rgb * normalize(base.rgb * varColor.rgb * varColor.rgb) * f_adj_shadow_strength * pow(max(-dot(v_LightDirection, viewVec), 0.0), 4.0) * max(1.0 - shadow_uncorrected, 0.0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -444,7 +563,13 @@ void main(void)
|
|||
// Note: clarity = (1 - fogginess)
|
||||
float clarity = clamp(fogShadingParameter
|
||||
- fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0);
|
||||
col = mix(fogColor, col, clarity);
|
||||
float fogColorMax = max(max(fogColor.r, fogColor.g), fogColor.b);
|
||||
// Prevent zero division.
|
||||
if (fogColorMax < 0.0000001) fogColorMax = 1.0;
|
||||
// For high clarity (light fog) we tint the fog color.
|
||||
// For this to not make the fog color artificially dark we need to normalize using the
|
||||
// fog color's brightest value. We then blend our base color with this to make the fog.
|
||||
col = mix(fogColor * pow(fogColor / fogColorMax, vec4(2.0 * clarity)), col, clarity);
|
||||
col = vec4(col.rgb, base.a);
|
||||
|
||||
gl_FragData[0] = col;
|
||||
|
|
|
@ -256,7 +256,9 @@ void main(void)
|
|||
z_bias *= pFactor * pFactor / f_textureresolution / f_shadowfar;
|
||||
|
||||
shadow_position = applyPerspectiveDistortion(m_ShadowViewProj * mWorld * (shadow_pos + vec4(normalOffsetScale * nNormal, 0.0))).xyz;
|
||||
#if !defined(ENABLE_TRANSLUCENT_FOLIAGE) || MATERIAL_TYPE != TILE_MATERIAL_WAVING_LEAVES
|
||||
shadow_position.z -= z_bias;
|
||||
#endif
|
||||
perspective_factor = pFactor;
|
||||
|
||||
if (f_timeofday < 0.2) {
|
||||
|
|
|
@ -20,6 +20,7 @@ uniform float animationTimer;
|
|||
uniform vec4 CameraPos;
|
||||
uniform float xyPerspectiveBias0;
|
||||
uniform float xyPerspectiveBias1;
|
||||
uniform vec3 shadow_tint;
|
||||
|
||||
varying float adj_shadow_strength;
|
||||
varying float cosLight;
|
||||
|
@ -432,7 +433,7 @@ void main(void)
|
|||
col.rgb =
|
||||
adjusted_night_ratio * col.rgb + // artificial light
|
||||
(1.0 - adjusted_night_ratio) * ( // natural light
|
||||
col.rgb * (1.0 - shadow_int * (1.0 - shadow_color)) + // filtered texture color
|
||||
col.rgb * (1.0 - shadow_int * (1.0 - shadow_color) * (1.0 - shadow_tint)) + // filtered texture color
|
||||
dayLight * shadow_color * shadow_int); // reflected filtered sunlight/moonlight
|
||||
}
|
||||
#endif
|
||||
|
@ -448,7 +449,13 @@ void main(void)
|
|||
// Note: clarity = (1 - fogginess)
|
||||
float clarity = clamp(fogShadingParameter
|
||||
- fogShadingParameter * length(eyeVec) / fogDistance, 0.0, 1.0);
|
||||
col = mix(fogColor, col, clarity);
|
||||
float fogColorMax = max(max(fogColor.r, fogColor.g), fogColor.b);
|
||||
// Prevent zero division.
|
||||
if (fogColorMax < 0.0000001) fogColorMax = 1.0;
|
||||
// For high clarity (light fog) we tint the fog color.
|
||||
// For this to not make the fog color artificially dark we need to normalize using the
|
||||
// fog color's brightest value. We then blend our base color with this to make the fog.
|
||||
col = mix(fogColor * pow(fogColor / fogColorMax, vec4(2.0 * clarity)), col, clarity);
|
||||
col = vec4(col.rgb, base.a);
|
||||
|
||||
gl_FragData[0] = col;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
uniform mat4 mWorld;
|
||||
uniform vec3 dayLight;
|
||||
uniform float animationTimer;
|
||||
uniform lowp vec4 emissiveColor;
|
||||
uniform lowp vec4 materialColor;
|
||||
|
||||
varying vec3 vNormal;
|
||||
varying vec3 vPosition;
|
||||
|
@ -91,7 +91,7 @@ float directional_ambient(vec3 normal)
|
|||
|
||||
void main(void)
|
||||
{
|
||||
varTexCoord = (mTexture * inTexCoord0).st;
|
||||
varTexCoord = (mTexture * vec4(inTexCoord0.xy, 1.0, 1.0)).st;
|
||||
gl_Position = mWorldViewProj * inVertexPosition;
|
||||
|
||||
vPosition = gl_Position.xyz;
|
||||
|
@ -115,7 +115,7 @@ void main(void)
|
|||
vec4 color = inVertexColor;
|
||||
#endif
|
||||
|
||||
color *= emissiveColor;
|
||||
color *= materialColor;
|
||||
|
||||
// The alpha gives the ratio of sunlight in the incoming light.
|
||||
nightRatio = 1.0 - color.a;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
uniform lowp vec4 emissiveColor;
|
||||
uniform lowp vec4 materialColor;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
gl_FragColor = emissiveColor;
|
||||
gl_FragColor = materialColor;
|
||||
}
|
||||
|
|
|
@ -46,7 +46,9 @@ float sampleVolumetricLight(vec2 uv, vec3 lightVec, float rawDepth)
|
|||
if (min(samplepos.x, samplepos.y) > 0. && max(samplepos.x, samplepos.y) < 1.)
|
||||
result += texture2D(depthmap, samplepos).r < 1. ? 0.0 : 1.0;
|
||||
}
|
||||
return result / samples;
|
||||
// We use the depth map to approximate the effect of depth on the light intensity.
|
||||
// The exponent was chosen based on aesthetic preference.
|
||||
return result / samples * pow(texture2D(depthmap, uv).r, 128.0);
|
||||
}
|
||||
|
||||
vec3 getDirectLightScatteringAtGround(vec3 v_LightDirection)
|
||||
|
|
|
@ -338,8 +338,6 @@ Call these functions only at load time!
|
|||
is checked to see if the command exists, but after the input is parsed.
|
||||
* Return `true` to mark the command as handled, which means that the default
|
||||
handlers will be prevented.
|
||||
* `minetest.register_on_death(function())`
|
||||
* Called when the local player dies
|
||||
* `minetest.register_on_hp_modification(function(hp))`
|
||||
* Called when server modified player's HP
|
||||
* `minetest.register_on_damage_taken(function(hp))`
|
||||
|
@ -487,8 +485,6 @@ Call these functions only at load time!
|
|||
* Returns `false` if the client is already disconnecting otherwise returns `true`.
|
||||
* `minetest.get_server_info()`
|
||||
* Returns [server info](#server-info).
|
||||
* `minetest.send_respawn()`
|
||||
* Sends a respawn request to the server.
|
||||
|
||||
### Storage API
|
||||
* `minetest.get_mod_storage()`:
|
||||
|
|
|
@ -22,6 +22,7 @@ General options and their default values:
|
|||
MinSizeRel - Release build with -Os passed to compiler to make executable as small as possible
|
||||
PRECOMPILE_HEADERS=FALSE - Precompile some headers (experimental; requires CMake 3.16 or later)
|
||||
PRECOMPILED_HEADERS_PATH= - Path to a file listing all headers to precompile (default points to src/precompiled_headers.txt)
|
||||
USE_SDL2=TRUE - Build with SDL2; Enables IrrlichtMt device SDL2
|
||||
ENABLE_CURL=ON - Build with cURL; Enables use of online mod repo, public serverlist and remote media fetching via http
|
||||
ENABLE_CURSES=ON - Build with (n)curses; Enables a server side terminal (command line option: --terminal)
|
||||
ENABLE_GETTEXT=ON - Build with Gettext; Allows using translations
|
||||
|
@ -39,10 +40,15 @@ General options and their default values:
|
|||
ENABLE_UPDATE_CHECKER=TRUE - Whether to enable update checks by default
|
||||
INSTALL_DEVTEST=FALSE - Whether the Development Test game should be installed alongside Minetest
|
||||
USE_GPROF=FALSE - Enable profiling using GProf
|
||||
BUILD_WITH_TRACY=FALSE - Fetch and build with the Tracy profiler client
|
||||
FETCH_TRACY_GIT_TAG=master - Git tag for fetching Tracy client. Match with your server (gui) version
|
||||
VERSION_EXTRA= - Text to append to version (e.g. VERSION_EXTRA=foobar -> Minetest 0.4.9-foobar)
|
||||
|
||||
Library specific options:
|
||||
|
||||
SDL2_DLL - Only if building with SDL2 on Windows; path to libSDL2.dll
|
||||
SDL2_INCLUDE_DIRS - Only if building with SDL2; directory where SDL.h is located
|
||||
SDL2_LIBRARIES - Only if building with SDL2; path to libSDL2.a/libSDL2.so/libSDL2.lib
|
||||
CURL_DLL - Only if building with cURL on Windows; path to libcurl.dll
|
||||
CURL_INCLUDE_DIR - Only if building with cURL; directory where curl.h is located
|
||||
CURL_LIBRARY - Only if building with cURL; path to libcurl.a/libcurl.so/libcurl.lib
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Miscellaneous
|
||||
|
||||
## Profiling Minetest on Linux
|
||||
## Profiling Minetest on Linux with perf
|
||||
|
||||
We will be using a tool called "perf", which you can get by installing `perf` or `linux-perf` or `linux-tools-common`.
|
||||
|
||||
|
@ -36,3 +36,54 @@ Give both files to the developer and also provide:
|
|||
* commit the source was built from and/or modified source code (if applicable)
|
||||
|
||||
Hotspot will resolve symbols correctly when pointing the sysroot option at the collected libs.
|
||||
|
||||
|
||||
## Profiling with Tracy
|
||||
|
||||
[Tracy](https://github.com/wolfpld/tracy) is
|
||||
> A real time, nanosecond resolution, remote telemetry, hybrid frame and sampling
|
||||
> profiler for games and other applications.
|
||||
|
||||
It allows one to annotate important functions and generate traces, where one can
|
||||
see when each individual function call happened, and how long it took.
|
||||
|
||||
Tracy can also record when frames, e.g. server step, start and end, and inspect
|
||||
frames that took longer than usual. Minetest already contains annotations for
|
||||
its frames.
|
||||
|
||||
See also [Tracy's official documentation](https://github.com/wolfpld/tracy/releases/latest/download/tracy.pdf).
|
||||
|
||||
### Installing
|
||||
|
||||
Tracy consists of a client (Minetest) and a server (the gui).
|
||||
|
||||
Install the server, e.g. using your package manager.
|
||||
|
||||
### Building
|
||||
|
||||
Build Minetest with `-DDBUILD_WITH_TRACY=1`, this will fetch Tracy for building
|
||||
the Tracy client. And use `FETCH_TRACY_GIT_TAG` to get a version matching your
|
||||
Tracy server, e.g. `-DFETCH_TRACY_GIT_TAG=v0.11.0` if it's `0.11.0`.
|
||||
|
||||
To actually use Tracy, you also have to enable it with Tracy's build options:
|
||||
```
|
||||
-DTRACY_ENABLE=1 -DTRACY_ONLY_LOCALHOST=1
|
||||
```
|
||||
|
||||
See Tracy's documentation for more build options.
|
||||
|
||||
### Using in C++
|
||||
|
||||
Start the Tracy server and Minetest. You should see Minetest in the menu.
|
||||
|
||||
To actually get useful traces, you have to annotate functions with `ZoneScoped`
|
||||
macros and recompile. Please refer to Tracy's official documentation.
|
||||
|
||||
### Using in Lua
|
||||
|
||||
Tracy also supports Lua.
|
||||
If built with Tracy, Minetest loads its API in the global `tracy` table.
|
||||
See Tracy's official documentation for more information.
|
||||
|
||||
Note: The whole Tracy Lua API is accessible to all mods. And we don't check if it
|
||||
is or becomes insecure. Run untrusted mods at your own risk.
|
||||
|
|
|
@ -1470,7 +1470,8 @@ Look for examples in `games/devtest` or `games/minetest_game`.
|
|||
'Connected Glass'.
|
||||
* `allfaces`
|
||||
* Often used for partially-transparent nodes.
|
||||
* External and internal sides of textures are visible.
|
||||
* External sides of textures, and unlike other drawtypes, the external sides
|
||||
of other blocks, are visible from the inside.
|
||||
* `allfaces_optional`
|
||||
* Often used for leaves nodes.
|
||||
* This switches between `normal`, `glasslike` and `allfaces` according to
|
||||
|
@ -5522,6 +5523,10 @@ Utilities
|
|||
override_item_remove_fields = true,
|
||||
-- The predefined hotbar is a Lua HUD element of type `hotbar` (5.10.0)
|
||||
hotbar_hud_element = true,
|
||||
-- Bulk LBM support (5.10.0)
|
||||
bulk_lbms = true,
|
||||
-- ABM supports field without_neighbors (5.10.0)
|
||||
abm_without_neighbors = true,
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -5580,8 +5585,8 @@ Utilities
|
|||
},
|
||||
|
||||
-- Estimated maximum formspec size before Minetest will start shrinking the
|
||||
-- formspec to fit. For a fullscreen formspec, use a size 10-20% larger than
|
||||
-- this and `padding[-0.01,-0.01]`.
|
||||
-- formspec to fit. For a fullscreen formspec, use this formspec size and
|
||||
-- `padding[0,0]`. `bgcolor[;true]` is also recommended.
|
||||
max_formspec_size = {
|
||||
x = 20,
|
||||
y = 11.25
|
||||
|
@ -5655,6 +5660,13 @@ Utilities
|
|||
* `minetest.colorspec_to_bytes(colorspec)`: Converts a ColorSpec to a raw
|
||||
string of four bytes in an RGBA layout, returned as a string.
|
||||
* `colorspec`: The ColorSpec to convert
|
||||
* `minetest.colorspec_to_table(colorspec)`: Converts a ColorSpec into RGBA table
|
||||
form. If the ColorSpec is invalid, returns `nil`. You can use this to parse
|
||||
ColorStrings.
|
||||
* `colorspec`: The ColorSpec to convert
|
||||
* `minetest.time_to_day_night_ratio(time_of_day)`: Returns a "day-night ratio" value
|
||||
(as accepted by `ObjectRef:override_day_night_ratio`) that is equivalent to
|
||||
the given "time of day" value (as returned by `minetest.get_timeofday`).
|
||||
* `minetest.encode_png(width, height, data, [compression])`: Encode a PNG
|
||||
image and return it in string form.
|
||||
* `width`: Width of the image
|
||||
|
@ -5838,8 +5850,13 @@ Call these functions only at load time!
|
|||
* `clicker`: ObjectRef - Object that acted upon `player`, may or may not be a player
|
||||
* `minetest.register_on_player_hpchange(function(player, hp_change, reason), modifier)`
|
||||
* Called when the player gets damaged or healed
|
||||
* When `hp == 0`, damage doesn't trigger this callback.
|
||||
* When `hp == hp_max`, healing does still trigger this callback.
|
||||
* `player`: ObjectRef of the player
|
||||
* `hp_change`: the amount of change. Negative when it is damage.
|
||||
* Historically, the new HP value was clamped to [0, 65535] before
|
||||
calculating the HP change. This clamping has been removed as of
|
||||
Minetest 5.10.0
|
||||
* `reason`: a PlayerHPChangeReason table.
|
||||
* The `type` field will have one of the following values:
|
||||
* `set_hp`: A mod or the engine called `set_hp` without
|
||||
|
@ -5860,6 +5877,7 @@ Call these functions only at load time!
|
|||
* `minetest.register_on_dieplayer(function(ObjectRef, reason))`
|
||||
* Called when a player dies
|
||||
* `reason`: a PlayerHPChangeReason table, see register_on_player_hpchange
|
||||
* For customizing the death screen, see `minetest.show_death_screen`.
|
||||
* `minetest.register_on_respawnplayer(function(ObjectRef))`
|
||||
* Called when player is to be respawned
|
||||
* Called _before_ repositioning of player occurs
|
||||
|
@ -6136,6 +6154,8 @@ Environment access
|
|||
* `minetest.swap_node(pos, node)`
|
||||
* Swap node at position with another.
|
||||
* This keeps the metadata intact and will not run con-/destructor callbacks.
|
||||
* `minetest.bulk_swap_node({pos1, pos2, pos3, ...}, node)`
|
||||
* Equivalent to `minetest.swap_node` but in bulk.
|
||||
* `minetest.remove_node(pos)`: Remove a node
|
||||
* Equivalent to `minetest.set_node(pos, {name="air"})`, but a bit faster.
|
||||
* `minetest.get_node(pos)`
|
||||
|
@ -6562,6 +6582,13 @@ Formspec
|
|||
* `"INV"`: something failed
|
||||
* `"CHG"`: has been changed
|
||||
* `"VAL"`: not changed
|
||||
* `minetest.show_death_screen(player, reason)`
|
||||
* Called when the death screen should be shown.
|
||||
* `player` is an ObjectRef, `reason` is a PlayerHPChangeReason table or nil.
|
||||
* By default, this shows a simple formspec with the option to respawn.
|
||||
Respawning is done via `ObjectRef:respawn`.
|
||||
* You can override this to show a custom death screen.
|
||||
* For general death handling, use `minetest.register_on_dieplayer` instead.
|
||||
|
||||
Item handling
|
||||
-------------
|
||||
|
@ -6999,10 +7026,11 @@ Bans
|
|||
* Returns boolean indicating success
|
||||
* `minetest.unban_player_or_ip(ip_or_name)`: remove ban record matching
|
||||
IP address or name
|
||||
* `minetest.kick_player(name, [reason])`: disconnect a player with an optional
|
||||
* `minetest.kick_player(name[, reason[, reconnect]])`: disconnect a player with an optional
|
||||
reason.
|
||||
* Returns boolean indicating success (false if player nonexistent)
|
||||
* `minetest.disconnect_player(name, [reason])`: disconnect a player with an
|
||||
* If `reconnect` is true, allow the user to reconnect.
|
||||
* `minetest.disconnect_player(name[, reason[, reconnect]])`: disconnect a player with an
|
||||
optional reason, this will not prefix with 'Kicked: ' like kick_player.
|
||||
If no reason is given, it will default to 'Disconnected.'
|
||||
* Returns boolean indicating success (false if player nonexistent)
|
||||
|
@ -8508,12 +8536,15 @@ child will follow movement and rotation of that bone.
|
|||
if set to zero the clouds are rendered flat.
|
||||
* `speed`: 2D cloud speed + direction in nodes per second
|
||||
(default `{x=0, z=-2}`).
|
||||
* `shadow`: shadow color, applied to the base of the cloud
|
||||
(default `#cccccc`).
|
||||
* `get_clouds()`: returns a table with the current cloud parameters as in
|
||||
`set_clouds`.
|
||||
* `override_day_night_ratio(ratio or nil)`
|
||||
* `0`...`1`: Overrides day-night ratio, controlling sunlight to a specific
|
||||
amount.
|
||||
* Passing no arguments disables override, defaulting to sunlight based on day-night cycle
|
||||
* See also `minetest.time_to_day_night_ratio`,
|
||||
* `get_day_night_ratio()`: returns the ratio or nil if it isn't overridden
|
||||
* `set_local_animation(idle, walk, dig, walk_while_dig, frame_speed)`:
|
||||
set animation for player model in third person view.
|
||||
|
@ -8540,11 +8571,23 @@ child will follow movement and rotation of that bone.
|
|||
* Passing no arguments resets lighting to its default values.
|
||||
* `light_definition` is a table with the following optional fields:
|
||||
* `saturation` sets the saturation (vividness; default: `1.0`).
|
||||
* values > 1 increase the saturation
|
||||
* values in [0,1] decrease the saturation
|
||||
* It is applied according to the function `result = b*(1-s) + c*s`, where:
|
||||
* `c` is the original color
|
||||
* `b` is the greyscale version of the color with the same luma
|
||||
* `s` is the saturation set here
|
||||
* The resulting color always has the same luma (perceived brightness) as the original.
|
||||
* This means that:
|
||||
* values > 1 oversaturate
|
||||
* values < 1 down to 0 desaturate, 0 being entirely greyscale
|
||||
* values < 0 cause an effect similar to inversion,
|
||||
but keeping original luma and being symmetrical in terms of saturation
|
||||
(eg. -1 and 1 is the same saturation and luma, but different hues)
|
||||
* `shadows` is a table that controls ambient shadows
|
||||
* `intensity` sets the intensity of the shadows from 0 (no shadows, default) to 1 (blackness)
|
||||
* This value has no effect on clients who have the "Dynamic Shadows" shader disabled.
|
||||
* `tint` tints the shadows with the provided color, with RGB values ranging from 0 to 255.
|
||||
(default `{r=0, g=0, b=0}`)
|
||||
* This value has no effect on clients who have the "Dynamic Shadows" shader disabled.
|
||||
* `exposure` is a table that controls automatic exposure.
|
||||
The basic exposure factor equation is `e = 2^exposure_correction / clamp(luminance, 2^luminance_min, 2^luminance_max)`
|
||||
* `luminance_min` set the lower luminance boundary to use in the calculation (default: `-3.0`)
|
||||
|
@ -9071,6 +9114,11 @@ Used by `minetest.register_abm`.
|
|||
-- If left out or empty, any neighbor will do.
|
||||
-- `group:groupname` can also be used here.
|
||||
|
||||
without_neighbors = {"default:lava_source", "default:lava_flowing"},
|
||||
-- Only apply `action` to nodes that have no one of these neighbors.
|
||||
-- If left out or empty, it has no effect.
|
||||
-- `group:groupname` can also be used here.
|
||||
|
||||
interval = 10.0,
|
||||
-- Operation interval in seconds
|
||||
|
||||
|
@ -9106,7 +9154,12 @@ Used by `minetest.register_lbm`.
|
|||
|
||||
A loading block modifier (LBM) is used to define a function that is called for
|
||||
specific nodes (defined by `nodenames`) when a mapblock which contains such nodes
|
||||
gets activated (not loaded!)
|
||||
gets activated (not loaded!).
|
||||
|
||||
Note: LBMs operate on a "snapshot" of node positions taken once before they are triggered.
|
||||
That means if an LBM callback adds a node, it won't be taken into account.
|
||||
However the engine guarantees that when the callback is called that all given position(s)
|
||||
contain a matching node.
|
||||
|
||||
```lua
|
||||
{
|
||||
|
@ -9130,7 +9183,13 @@ gets activated (not loaded!)
|
|||
action = function(pos, node, dtime_s) end,
|
||||
-- Function triggered for each qualifying node.
|
||||
-- `dtime_s` is the in-game time (in seconds) elapsed since the block
|
||||
-- was last active
|
||||
-- was last active.
|
||||
|
||||
bulk_action = function(pos_list, dtime_s) end,
|
||||
-- Function triggered with a list of all applicable node positions at once.
|
||||
-- This can be provided as an alternative to `action` (not both).
|
||||
-- Available since `minetest.features.bulk_lbms` (5.10.0)
|
||||
-- `dtime_s`: as above
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -9337,9 +9396,17 @@ Used by `minetest.register_node`, `minetest.register_craftitem`, and
|
|||
-- If specified as a table, the field to be used is selected according to
|
||||
-- the current `pointed_thing`.
|
||||
-- There are three possible TouchInteractionMode values:
|
||||
-- * "user" (meaning depends on client-side settings)
|
||||
-- * "long_dig_short_place" (long tap = dig, short tap = place)
|
||||
-- * "short_dig_long_place" (short tap = dig, long tap = place)
|
||||
-- * "user":
|
||||
-- * For `pointed_object`: Equivalent to "short_dig_long_place" if the
|
||||
-- client-side setting "touch_punch_gesture" is "short_tap" (the
|
||||
-- default value) and the item is able to punch (i.e. has no on_use
|
||||
-- callback defined).
|
||||
-- Equivalent to "long_dig_short_place" otherwise.
|
||||
-- * For `pointed_node` and `pointed_nothing`:
|
||||
-- Equivalent to "long_dig_short_place".
|
||||
-- * The behavior of "user" may change in the future.
|
||||
-- The default value is "user".
|
||||
|
||||
sound = {
|
||||
|
@ -11368,6 +11435,16 @@ Functions: bit.tobit, bit.tohex, bit.bnot, bit.band, bit.bor, bit.bxor, bit.lshi
|
|||
|
||||
See http://bitop.luajit.org/ for advanced information.
|
||||
|
||||
Tracy Profiler
|
||||
--------------
|
||||
|
||||
Minetest can be built with support for the Tracy profiler, which can also be
|
||||
useful for profiling mods and is exposed to Lua as the global `tracy`.
|
||||
|
||||
See doc/developing/misc.md for details.
|
||||
|
||||
Note: This is a development feature and not covered by compatibility promises.
|
||||
|
||||
Error Handling
|
||||
--------------
|
||||
|
||||
|
|
|
@ -253,8 +253,8 @@ GUI
|
|||
},
|
||||
|
||||
-- Estimated maximum formspec size before Minetest will start shrinking the
|
||||
-- formspec to fit. For a fullscreen formspec, use a size 10-20% larger than
|
||||
-- this and `padding[-0.01,-0.01]`.
|
||||
-- formspec to fit. For a fullscreen formspec, use this formspec size and
|
||||
-- `padding[0,0]`. `bgcolor[;true]` is also recommended.
|
||||
max_formspec_size = {
|
||||
x = 20,
|
||||
y = 11.25
|
||||
|
|
|
@ -154,3 +154,36 @@ minetest.register_chatcommand("bench_bulk_get_node", {
|
|||
return true, msg
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand("bench_bulk_swap_node", {
|
||||
params = "",
|
||||
description = "Benchmark: Bulk-swap 99×99×99 stone nodes",
|
||||
func = function(name, param)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if not player then
|
||||
return false, "No player."
|
||||
end
|
||||
local pos_list = get_positions_cube(player:get_pos())
|
||||
|
||||
minetest.chat_send_player(name, "Benchmarking minetest.bulk_swap_node. Warming up ...")
|
||||
|
||||
-- warm up because first execution otherwise becomes
|
||||
-- significantly slower
|
||||
minetest.bulk_swap_node(pos_list, {name = "mapgen_stone"})
|
||||
|
||||
minetest.chat_send_player(name, "Warming up finished, now benchmarking ...")
|
||||
|
||||
local start_time = minetest.get_us_time()
|
||||
for i=1,#pos_list do
|
||||
minetest.swap_node(pos_list[i], {name = "mapgen_stone"})
|
||||
end
|
||||
local middle_time = minetest.get_us_time()
|
||||
minetest.bulk_swap_node(pos_list, {name = "mapgen_stone"})
|
||||
local end_time = minetest.get_us_time()
|
||||
local msg = string.format("Benchmark results: minetest.swap_node loop: %.2f ms; minetest.bulk_swap_node: %.2f ms",
|
||||
((middle_time - start_time)) / 1000,
|
||||
((end_time - middle_time)) / 1000
|
||||
)
|
||||
return true, msg
|
||||
end,
|
||||
})
|
||||
|
|
6
games/devtest/mods/testabms/README.md
Normal file
6
games/devtest/mods/testabms/README.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
# Test ABMs
|
||||
|
||||
This mod contains a nodes and related ABM actions.
|
||||
By placing these nodes, you can test basic ABM behaviours.
|
||||
|
||||
There are separate tests for ABM `chance`, `interval`, `min_y`, `max_y`, `neighbor` and `without_neighbor` fields.
|
12
games/devtest/mods/testabms/after_node.lua
Normal file
12
games/devtest/mods/testabms/after_node.lua
Normal file
|
@ -0,0 +1,12 @@
|
|||
|
||||
local S = minetest.get_translator("testnodes")
|
||||
|
||||
-- After ABM node
|
||||
minetest.register_node("testabms:after_abm", {
|
||||
description = S("After ABM processed node."),
|
||||
drawtype = "normal",
|
||||
tiles = { "testabms_after_node.png" },
|
||||
|
||||
groups = { dig_immediate = 3 },
|
||||
})
|
||||
|
56
games/devtest/mods/testabms/chances.lua
Normal file
56
games/devtest/mods/testabms/chances.lua
Normal file
|
@ -0,0 +1,56 @@
|
|||
-- test ABMs with different chances
|
||||
|
||||
local S = minetest.get_translator("testnodes")
|
||||
|
||||
-- ABM chance 5 node
|
||||
minetest.register_node("testabms:chance_5", {
|
||||
description = S("Node for test ABM chance_5"),
|
||||
drawtype = "normal",
|
||||
tiles = { "testabms_wait_node.png" },
|
||||
|
||||
groups = { dig_immediate = 3 },
|
||||
|
||||
on_construct = function (pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", "Waiting for ABM testabms:chance_5")
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_abm({
|
||||
label = "testabms:chance_5",
|
||||
nodenames = "testabms:chance_5",
|
||||
interval = 10,
|
||||
chance = 5,
|
||||
action = function (pos)
|
||||
minetest.swap_node(pos, {name="testabms:after_abm"})
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", "ABM testabsm:chance_5 changed this node.")
|
||||
end
|
||||
})
|
||||
|
||||
-- ABM chance 20 node
|
||||
minetest.register_node("testabms:chance_20", {
|
||||
description = S("Node for test ABM chance_20"),
|
||||
drawtype = "normal",
|
||||
tiles = { "testabms_wait_node.png" },
|
||||
|
||||
groups = { dig_immediate = 3 },
|
||||
|
||||
on_construct = function (pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", "Waiting for ABM testabms:chance_20")
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_abm({
|
||||
label = "testabms:chance_20",
|
||||
nodenames = "testabms:chance_20",
|
||||
interval = 10,
|
||||
chance = 20,
|
||||
action = function (pos)
|
||||
minetest.swap_node(pos, {name="testabms:after_abm"})
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", "ABM testabsm:chance_20 changed this node.")
|
||||
end
|
||||
})
|
||||
|
7
games/devtest/mods/testabms/init.lua
Normal file
7
games/devtest/mods/testabms/init.lua
Normal file
|
@ -0,0 +1,7 @@
|
|||
local path = minetest.get_modpath(minetest.get_current_modname())
|
||||
|
||||
dofile(path.."/after_node.lua")
|
||||
dofile(path.."/chances.lua")
|
||||
dofile(path.."/intervals.lua")
|
||||
dofile(path.."/min_max.lua")
|
||||
dofile(path.."/neighbors.lua")
|
56
games/devtest/mods/testabms/intervals.lua
Normal file
56
games/devtest/mods/testabms/intervals.lua
Normal file
|
@ -0,0 +1,56 @@
|
|||
-- test ABMs with different interval
|
||||
|
||||
local S = minetest.get_translator("testnodes")
|
||||
|
||||
-- ABM inteval 1 node
|
||||
minetest.register_node("testabms:interval_1", {
|
||||
description = S("Node for test ABM interval_1"),
|
||||
drawtype = "normal",
|
||||
tiles = { "testabms_wait_node.png" },
|
||||
|
||||
groups = { dig_immediate = 3 },
|
||||
|
||||
on_construct = function (pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", "Waiting for ABM testabms:interval_1")
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_abm({
|
||||
label = "testabms:interval_1",
|
||||
nodenames = "testabms:interval_1",
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
action = function (pos)
|
||||
minetest.swap_node(pos, {name="testabms:after_abm"})
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", "ABM testabsm:interval_1 changed this node.")
|
||||
end
|
||||
})
|
||||
|
||||
-- ABM interval 60 node
|
||||
minetest.register_node("testabms:interval_60", {
|
||||
description = S("Node for test ABM interval_60"),
|
||||
drawtype = "normal",
|
||||
tiles = { "testabms_wait_node.png" },
|
||||
|
||||
groups = { dig_immediate = 3 },
|
||||
|
||||
on_construct = function (pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", "Waiting for ABM testabms:interval_60")
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_abm({
|
||||
label = "testabms:interval_60",
|
||||
nodenames = "testabms:interval_60",
|
||||
interval = 60,
|
||||
chance = 1,
|
||||
action = function (pos)
|
||||
minetest.swap_node(pos, {name="testabms:after_abm"})
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", "ABM testabsm:interval_60 changed this node.")
|
||||
end
|
||||
})
|
||||
|
58
games/devtest/mods/testabms/min_max.lua
Normal file
58
games/devtest/mods/testabms/min_max.lua
Normal file
|
@ -0,0 +1,58 @@
|
|||
-- test ABMs with min_y and max_y
|
||||
|
||||
local S = minetest.get_translator("testnodes")
|
||||
|
||||
-- ABM min_y node
|
||||
minetest.register_node("testabms:min_y", {
|
||||
description = S("Node for test ABM min_y."),
|
||||
drawtype = "normal",
|
||||
tiles = { "testabms_wait_node.png" },
|
||||
|
||||
groups = { dig_immediate = 3 },
|
||||
|
||||
on_construct = function (pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", "Waiting for ABM testabms:min_y at y "..pos.y.." with min_y = 0")
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_abm({
|
||||
label = "testabms:min_y",
|
||||
nodenames = "testabms:min_y",
|
||||
interval = 10,
|
||||
chance = 1,
|
||||
min_y = 0,
|
||||
action = function (pos)
|
||||
minetest.swap_node(pos, {name="testabms:after_abm"})
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", "ABM testabsm:min_y changed this node.")
|
||||
end
|
||||
})
|
||||
|
||||
-- ABM max_y node
|
||||
minetest.register_node("testabms:max_y", {
|
||||
description = S("Node for test ABM max_y."),
|
||||
drawtype = "normal",
|
||||
tiles = { "testabms_wait_node.png" },
|
||||
|
||||
groups = { dig_immediate = 3 },
|
||||
|
||||
on_construct = function (pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", "Waiting for ABM testabms:max_y at y "..pos.y.." with max_y = 0")
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_abm({
|
||||
label = "testabms:max_y",
|
||||
nodenames = "testabms:max_y",
|
||||
interval = 10,
|
||||
chance = 1,
|
||||
max_y = 0,
|
||||
action = function (pos)
|
||||
minetest.swap_node(pos, {name="testabms:after_abm"})
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext", "ABM testabsm:max_y changed this node.")
|
||||
end
|
||||
})
|
||||
|
2
games/devtest/mods/testabms/mod.conf
Normal file
2
games/devtest/mods/testabms/mod.conf
Normal file
|
@ -0,0 +1,2 @@
|
|||
name = testabms
|
||||
description = Contains some nodes for test ABMs.
|
99
games/devtest/mods/testabms/neighbors.lua
Normal file
99
games/devtest/mods/testabms/neighbors.lua
Normal file
|
@ -0,0 +1,99 @@
|
|||
-- test ABMs with neighbor and without_neighbor
|
||||
|
||||
local S = minetest.get_translator("testnodes")
|
||||
|
||||
-- ABM required neighbor
|
||||
minetest.register_node("testabms:required_neighbor", {
|
||||
description = S("Node for test ABM required_neighbor.") .. "\n"
|
||||
.. S("Sensitive neighbor node is testnodes:normal."),
|
||||
drawtype = "normal",
|
||||
tiles = { "testabms_wait_node.png" },
|
||||
|
||||
groups = { dig_immediate = 3 },
|
||||
|
||||
on_construct = function (pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext",
|
||||
"Waiting for ABM testabms:required_neighbor "
|
||||
.. "(normal drawtype testnode sensitive)")
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_abm({
|
||||
label = "testabms:required_neighbor",
|
||||
nodenames = "testabms:required_neighbor",
|
||||
neighbors = {"testnodes:normal"},
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
action = function (pos)
|
||||
minetest.swap_node(pos, {name="testabms:after_abm"})
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext",
|
||||
"ABM testabsm:required_neighbor changed this node.")
|
||||
end
|
||||
})
|
||||
|
||||
-- ABM missing neighbor node
|
||||
minetest.register_node("testabms:missing_neighbor", {
|
||||
description = S("Node for test ABM missing_neighbor.") .. "\n"
|
||||
.. S("Sensitive neighbor node is testnodes:normal."),
|
||||
drawtype = "normal",
|
||||
tiles = { "testabms_wait_node.png" },
|
||||
|
||||
groups = { dig_immediate = 3 },
|
||||
|
||||
on_construct = function (pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext",
|
||||
"Waiting for ABM testabms:missing_neighbor"
|
||||
.. " (normal drawtype testnode sensitive)")
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_abm({
|
||||
label = "testabms:missing_neighbor",
|
||||
nodenames = "testabms:missing_neighbor",
|
||||
without_neighbors = {"testnodes:normal"},
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
action = function (pos)
|
||||
minetest.swap_node(pos, {name="testabms:after_abm"})
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext",
|
||||
"ABM testabsm:missing_neighbor changed this node.")
|
||||
end
|
||||
})
|
||||
|
||||
-- ABM required and missing neighbor node
|
||||
minetest.register_node("testabms:required_missing_neighbor", {
|
||||
description = S("Node for test ABM required_missing_neighbor.") .. "\n"
|
||||
.. S("Sensitive neighbor nodes are testnodes:normal and testnodes:glasslike."),
|
||||
drawtype = "normal",
|
||||
tiles = { "testabms_wait_node.png" },
|
||||
|
||||
groups = { dig_immediate = 3 },
|
||||
|
||||
on_construct = function (pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext",
|
||||
"Waiting for ABM testabms:required_missing_neighbor"
|
||||
.. " (wint normal drawtype testnode and no glasslike"
|
||||
.. " drawtype testnode sensitive)")
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_abm({
|
||||
label = "testabms:required_missing_neighbor",
|
||||
nodenames = "testabms:required_missing_neighbor",
|
||||
neighbors = {"testnodes:normal"},
|
||||
without_neighbors = {"testnodes:glasslike"},
|
||||
interval = 1,
|
||||
chance = 1,
|
||||
action = function (pos)
|
||||
minetest.swap_node(pos, {name="testabms:after_abm"})
|
||||
local meta = minetest.get_meta(pos)
|
||||
meta:set_string("infotext",
|
||||
"ABM testabsm:required_missing_neighbor changed this node.")
|
||||
end
|
||||
})
|
||||
|
BIN
games/devtest/mods/testabms/textures/testabms_after_node.png
Normal file
BIN
games/devtest/mods/testabms/textures/testabms_after_node.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 179 B |
BIN
games/devtest/mods/testabms/textures/testabms_wait_node.png
Normal file
BIN
games/devtest/mods/testabms/textures/testabms_wait_node.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 183 B |
|
@ -66,7 +66,7 @@ local inv_style_fs = [[
|
|||
|
||||
-- Some textures from textures/base/pack and Devtest, with many different sizes
|
||||
-- and aspect ratios.
|
||||
local image_column = "image,0=logo.png,1=rare_controls.png,2=checkbox_16.png," ..
|
||||
local image_column = "image,0=logo.png,1=crack_anylength.png^[invert:rgb,2=checkbox_16.png," ..
|
||||
"3=checkbox_32.png,4=checkbox_64.png,5=default_lava.png," ..
|
||||
"6=progress_bar.png,7=progress_bar_bg.png"
|
||||
local words = {
|
||||
|
|
|
@ -1,18 +1,30 @@
|
|||
local function show_fullscreen_fs(name)
|
||||
local window = minetest.get_player_window_information(name)
|
||||
if not window then
|
||||
return false, "Unable to get window info"
|
||||
local function window_info_equal(a, b)
|
||||
return
|
||||
-- size
|
||||
a.size.x == b.size.x and a.size.y == b.size.y and
|
||||
-- real_gui_scaling, real_hud_scaling
|
||||
a.real_gui_scaling == b.real_gui_scaling and
|
||||
a.real_hud_scaling == b.real_hud_scaling and
|
||||
-- max_formspec_size
|
||||
a.max_formspec_size.x == b.max_formspec_size.x and
|
||||
a.max_formspec_size.y == b.max_formspec_size.y and
|
||||
-- touch_controls
|
||||
a.touch_controls == b.touch_controls
|
||||
end
|
||||
|
||||
local last_window_info = {}
|
||||
|
||||
local function show_fullscreen_fs(name, window)
|
||||
print(dump(window))
|
||||
|
||||
local size = { x = window.max_formspec_size.x * 1.1, y = window.max_formspec_size.y * 1.1 }
|
||||
local size = window.max_formspec_size
|
||||
local touch_text = window.touch_controls and "Touch controls enabled" or
|
||||
"Touch controls disabled"
|
||||
local fs = {
|
||||
"formspec_version[4]",
|
||||
("size[%f,%f]"):format(size.x, size.y),
|
||||
"padding[-0.01,-0.01]",
|
||||
"padding[0,0]",
|
||||
"bgcolor[;true]",
|
||||
("button[%f,%f;1,1;%s;%s]"):format(0, 0, "tl", "TL"),
|
||||
("button[%f,%f;1,1;%s;%s]"):format(size.x - 1, 0, "tr", "TR"),
|
||||
("button[%f,%f;1,1;%s;%s]"):format(size.x - 1, size.y - 1, "br", "BR"),
|
||||
|
@ -23,10 +35,37 @@ local function show_fullscreen_fs(name)
|
|||
}
|
||||
|
||||
minetest.show_formspec(name, "testfullscreenfs:fs", table.concat(fs))
|
||||
return true, ("Calculated size of %f, %f"):format(size.x, size.y)
|
||||
minetest.chat_send_player(name, ("Calculated size of %f, %f"):format(size.x, size.y))
|
||||
last_window_info[name] = window
|
||||
end
|
||||
|
||||
|
||||
minetest.register_chatcommand("testfullscreenfs", {
|
||||
func = show_fullscreen_fs,
|
||||
func = function(name)
|
||||
local window = minetest.get_player_window_information(name)
|
||||
if not window then
|
||||
return false, "Unable to get window info"
|
||||
end
|
||||
|
||||
show_fullscreen_fs(name, window)
|
||||
return true
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_globalstep(function()
|
||||
for name, last_window in pairs(last_window_info) do
|
||||
local window = minetest.get_player_window_information(name)
|
||||
if window and not window_info_equal(last_window, window) then
|
||||
show_fullscreen_fs(name, window)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname == "testfullscreenfs:fs" and fields.quit then
|
||||
last_window_info[player:get_player_name()] = nil
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
last_window_info[player:get_player_name()] = nil
|
||||
end)
|
||||
|
|
|
@ -98,6 +98,23 @@ minetest.register_node("testnodes:allfaces", {
|
|||
groups = { dig_immediate = 3 },
|
||||
})
|
||||
|
||||
minetest.register_node("testnodes:allfaces_6", {
|
||||
description = S("\"allfaces 6 Textures\" Drawtype Test Node").."\n"..
|
||||
S("Transparent node with visible internal backfaces"),
|
||||
drawtype = "allfaces",
|
||||
paramtype = "light",
|
||||
tiles = {
|
||||
"testnodes_allfaces.png^[colorize:red",
|
||||
"testnodes_allfaces.png^[colorize:orange",
|
||||
"testnodes_allfaces.png^[colorize:yellow",
|
||||
"testnodes_allfaces.png^[colorize:green",
|
||||
"testnodes_allfaces.png^[colorize:blue",
|
||||
"testnodes_allfaces.png^[colorize:purple"
|
||||
},
|
||||
|
||||
groups = { dig_immediate = 3 },
|
||||
})
|
||||
|
||||
local allfaces_optional_tooltip = ""..
|
||||
S("Rendering depends on 'leaves_style' setting:").."\n"..
|
||||
S("* 'fancy': transparent with visible internal backfaces").."\n"..
|
||||
|
|
17
games/devtest/mods/unittests/color.lua
Normal file
17
games/devtest/mods/unittests/color.lua
Normal file
|
@ -0,0 +1,17 @@
|
|||
local function assert_colors_equal(c1, c2)
|
||||
if type(c1) == "table" and type(c2) == "table" then
|
||||
assert(c1.r == c2.r and c1.g == c2.g and c1.b == c2.b and c1.a == c2.a)
|
||||
else
|
||||
assert(c1 == c2)
|
||||
end
|
||||
end
|
||||
|
||||
local function test_color_conversion()
|
||||
assert_colors_equal(core.colorspec_to_table("#fff"), {r = 255, g = 255, b = 255, a = 255})
|
||||
assert_colors_equal(core.colorspec_to_table(0xFF00FF00), {r = 0, g = 255, b = 0, a = 255})
|
||||
assert_colors_equal(core.colorspec_to_table("#00000000"), {r = 0, g = 0, b = 0, a = 0})
|
||||
assert_colors_equal(core.colorspec_to_table("green"), {r = 0, g = 128, b = 0, a = 255})
|
||||
assert_colors_equal(core.colorspec_to_table("gren"), nil)
|
||||
end
|
||||
|
||||
unittests.register("test_color_conversion", test_color_conversion)
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue