Merge branch 'master' of https://github.com/minetest/minetest
commit
b11c0a6721
|
@ -8,8 +8,8 @@ assignees: ''
|
||||||
|
|
||||||
##### Minetest version
|
##### Minetest version
|
||||||
<!--
|
<!--
|
||||||
Paste Minetest version between quotes below
|
Paste Minetest version between quotes below.
|
||||||
If you are on a devel version, please add git commit hash
|
If you are on a devel version, please add git commit hash.
|
||||||
You can use `minetest --version` to find it.
|
You can use `minetest --version` to find it.
|
||||||
-->
|
-->
|
||||||
```
|
```
|
||||||
|
@ -29,4 +29,4 @@ OpenGL version:
|
||||||
<!-- Describe your problem here -->
|
<!-- Describe your problem here -->
|
||||||
|
|
||||||
##### Steps to reproduce
|
##### Steps to reproduce
|
||||||
<!-- For bug reports or build issues, explain how the problem happened -->
|
<!-- Explain how the problem has happened, providing a minimal test (i.e. a code snippet reduced to the bone) where possible -->
|
||||||
|
|
|
@ -67,6 +67,12 @@ appgurueu:
|
||||||
erlehmann, Warr1024, rollerozxa:
|
erlehmann, Warr1024, rollerozxa:
|
||||||
textures/base/pack/no_screenshot.png
|
textures/base/pack/no_screenshot.png
|
||||||
|
|
||||||
|
kilbith:
|
||||||
|
textures/base/pack/server_favorite.png
|
||||||
|
|
||||||
|
SmallJoker
|
||||||
|
textures/base/pack/server_favorite_delete.png (based on server_favorite.png)
|
||||||
|
|
||||||
License of Minetest source code
|
License of Minetest source code
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,17 @@
|
||||||
android:name=".UnzipService"
|
android:name=".UnzipService"
|
||||||
android:enabled="true"
|
android:enabled="true"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
</application>
|
|
||||||
|
<provider
|
||||||
|
android:name="androidx.core.content.FileProvider"
|
||||||
|
android:authorities="net.minetest.minetest.fileprovider"
|
||||||
|
android:grantUriPermissions="true"
|
||||||
|
android:exported="false">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
|
android:resource="@xml/filepaths" />
|
||||||
|
</provider>
|
||||||
|
|
||||||
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -26,6 +26,7 @@ import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
|
@ -36,7 +37,9 @@ import android.widget.LinearLayout;
|
||||||
|
|
||||||
import androidx.annotation.Keep;
|
import androidx.annotation.Keep;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.core.content.FileProvider;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
// Native code finds these methods by name (see porting_android.cpp).
|
// Native code finds these methods by name (see porting_android.cpp).
|
||||||
|
@ -183,4 +186,22 @@ public class GameActivity extends NativeActivity {
|
||||||
public String getCachePath() {
|
public String getCachePath() {
|
||||||
return Utils.getCacheDirectory(this).getAbsolutePath();
|
return Utils.getCacheDirectory(this).getAbsolutePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void shareFile(String path) {
|
||||||
|
File file = new File(path);
|
||||||
|
if (!file.exists()) {
|
||||||
|
Log.e("GameActivity", "File " + file.getAbsolutePath() + " doesn't exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uri fileUri = FileProvider.getUriForFile(this, "net.minetest.minetest.fileprovider", file);
|
||||||
|
|
||||||
|
Intent intent = new Intent(Intent.ACTION_SEND, fileUri);
|
||||||
|
intent.setDataAndType(fileUri, getContentResolver().getType(fileUri));
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
intent.putExtra(Intent.EXTRA_STREAM, fileUri);
|
||||||
|
|
||||||
|
Intent shareIntent = Intent.createChooser(intent, null);
|
||||||
|
startActivity(shareIntent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
<paths>
|
||||||
|
<external-files-path path="Minetest/" name="minetest" />
|
||||||
|
</paths>
|
|
@ -254,7 +254,7 @@ local formspec_escapes = {
|
||||||
}
|
}
|
||||||
function core.formspec_escape(text)
|
function core.formspec_escape(text)
|
||||||
-- Use explicit character set instead of dot here because it doubles the performance
|
-- Use explicit character set instead of dot here because it doubles the performance
|
||||||
return text and text:gsub("[\\%[%];,]", formspec_escapes)
|
return text and string.gsub(text, "[\\%[%];,]", formspec_escapes)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -242,3 +242,11 @@ function menu_worldmt_legacy(selected)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function confirmation_formspec(message, confirm_id, confirm_label, cancel_id, cancel_label)
|
||||||
|
return "size[10,2.5,true]" ..
|
||||||
|
"label[0.5,0.5;" .. message .. "]" ..
|
||||||
|
"style[" .. confirm_id .. ";bgcolor=red]" ..
|
||||||
|
"button[0.5,1.5;2.5,0.5;" .. confirm_id .. ";" .. confirm_label .. "]" ..
|
||||||
|
"button[7.0,1.5;2.5,0.5;" .. cancel_id .. ";" .. cancel_label .. "]"
|
||||||
|
end
|
||||||
|
|
|
@ -488,12 +488,10 @@ local confirm_overwrite = {}
|
||||||
function confirm_overwrite.get_formspec()
|
function confirm_overwrite.get_formspec()
|
||||||
local package = confirm_overwrite.package
|
local package = confirm_overwrite.package
|
||||||
|
|
||||||
return "size[11.5,4.5,true]" ..
|
return confirmation_formspec(
|
||||||
"label[2,2;" ..
|
fgettext("\"$1\" already exists. Would you like to overwrite it?", package.name),
|
||||||
fgettext("\"$1\" already exists. Would you like to overwrite it?", package.name) .. "]"..
|
'install', fgettext("Overwrite"),
|
||||||
"style[install;bgcolor=red]" ..
|
'cancel', fgettext("Cancel"))
|
||||||
"button[3.25,3.5;2.5,0.5;install;" .. fgettext("Overwrite") .. "]" ..
|
|
||||||
"button[5.75,3.5;2.5,0.5;cancel;" .. fgettext("Cancel") .. "]"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function confirm_overwrite.handle_submit(this, fields)
|
function confirm_overwrite.handle_submit(this, fields)
|
||||||
|
|
|
@ -18,15 +18,10 @@
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
local function delete_content_formspec(dialogdata)
|
local function delete_content_formspec(dialogdata)
|
||||||
local retval =
|
return confirmation_formspec(
|
||||||
"size[11.5,4.5,true]" ..
|
fgettext("Are you sure you want to delete \"$1\"?", dialogdata.content.name),
|
||||||
"label[2,2;" ..
|
'dlg_delete_content_confirm', fgettext("Delete"),
|
||||||
fgettext("Are you sure you want to delete \"$1\"?", dialogdata.content.name) .. "]"..
|
'dlg_delete_content_cancel', fgettext("Cancel"))
|
||||||
"style[dlg_delete_content_confirm;bgcolor=red]" ..
|
|
||||||
"button[3.25,3.5;2.5,0.5;dlg_delete_content_confirm;" .. fgettext("Delete") .. "]" ..
|
|
||||||
"button[5.75,3.5;2.5,0.5;dlg_delete_content_cancel;" .. fgettext("Cancel") .. "]"
|
|
||||||
|
|
||||||
return retval
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
|
@ -17,14 +17,10 @@
|
||||||
|
|
||||||
|
|
||||||
local function delete_world_formspec(dialogdata)
|
local function delete_world_formspec(dialogdata)
|
||||||
local retval =
|
return confirmation_formspec(
|
||||||
"size[10,2.5,true]" ..
|
fgettext("Delete World \"$1\"?", dialogdata.delete_name),
|
||||||
"label[0.5,0.5;" ..
|
'world_delete_confirm', fgettext("Delete"),
|
||||||
fgettext("Delete World \"$1\"?", dialogdata.delete_name) .. "]" ..
|
'world_delete_cancel', fgettext("Cancel"))
|
||||||
"style[world_delete_confirm;bgcolor=red]" ..
|
|
||||||
"button[0.5,1.5;2.5,0.5;world_delete_confirm;" .. fgettext("Delete") .. "]" ..
|
|
||||||
"button[7.0,1.5;2.5,0.5;world_delete_cancel;" .. fgettext("Cancel") .. "]"
|
|
||||||
return retval
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function delete_world_buttonhandler(this, fields)
|
local function delete_world_buttonhandler(this, fields)
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
--Minetest
|
||||||
|
--Copyright (C) 2022 rubenwardy
|
||||||
|
--
|
||||||
|
--This program is free software; you can redistribute it and/or modify
|
||||||
|
--it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
--the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
--(at your option) any later version.
|
||||||
|
--
|
||||||
|
--This program is distributed in the hope that it will be useful,
|
||||||
|
--but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
--GNU Lesser General Public License for more details.
|
||||||
|
--
|
||||||
|
--You should have received a copy of the GNU Lesser General Public License along
|
||||||
|
--with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local function register_formspec(dialogdata)
|
||||||
|
local title = fgettext("Joining $1", dialogdata.server and dialogdata.server.name or dialogdata.address)
|
||||||
|
local buttons_y = 4 + 1.3
|
||||||
|
if dialogdata.error then
|
||||||
|
buttons_y = buttons_y + 0.8
|
||||||
|
end
|
||||||
|
|
||||||
|
local retval = {
|
||||||
|
"formspec_version[4]",
|
||||||
|
"size[8,", tostring(buttons_y + 1.175), "]",
|
||||||
|
"set_focus[", (dialogdata.name ~= "" and "password" or "name"), "]",
|
||||||
|
"label[0.375,0.8;", title, "]",
|
||||||
|
"field[0.375,1.575;7.25,0.8;name;", core.formspec_escape(fgettext("Name")), ";",
|
||||||
|
core.formspec_escape(dialogdata.name), "]",
|
||||||
|
"pwdfield[0.375,2.875;7.25,0.8;password;", core.formspec_escape(fgettext("Password")), "]",
|
||||||
|
"pwdfield[0.375,4.175;7.25,0.8;password_2;", core.formspec_escape(fgettext("Confirm Password")), "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
if dialogdata.error then
|
||||||
|
table.insert_all(retval, {
|
||||||
|
"box[0.375,", tostring(buttons_y - 0.9), ";7.25,0.6;darkred]",
|
||||||
|
"label[0.625,", tostring(buttons_y - 0.6), ";", core.formspec_escape(dialogdata.error), "]",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert_all(retval, {
|
||||||
|
"container[0.375,", tostring(buttons_y), "]",
|
||||||
|
"button[0,0;2.5,0.8;dlg_register_confirm;", fgettext("Register"), "]",
|
||||||
|
"button[4.75,0;2.5,0.8;dlg_register_cancel;", fgettext("Cancel"), "]",
|
||||||
|
"container_end[]",
|
||||||
|
})
|
||||||
|
|
||||||
|
return table.concat(retval, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
local function register_buttonhandler(this, fields)
|
||||||
|
this.data.name = fields.name
|
||||||
|
this.data.error = nil
|
||||||
|
|
||||||
|
if fields.dlg_register_confirm or fields.key_enter then
|
||||||
|
if fields.name == "" then
|
||||||
|
this.data.error = fgettext("Missing name")
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
if fields.password ~= fields.password_2 then
|
||||||
|
this.data.error = fgettext("Passwords do not match")
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
gamedata.playername = fields.name
|
||||||
|
gamedata.password = fields.password
|
||||||
|
gamedata.address = this.data.address
|
||||||
|
gamedata.port = this.data.port
|
||||||
|
gamedata.allow_login_or_register = "register"
|
||||||
|
gamedata.selected_world = 0
|
||||||
|
|
||||||
|
assert(gamedata.address and gamedata.port)
|
||||||
|
|
||||||
|
local server = this.data.server
|
||||||
|
if server then
|
||||||
|
serverlistmgr.add_favorite(server)
|
||||||
|
gamedata.servername = server.name
|
||||||
|
gamedata.serverdescription = server.description
|
||||||
|
else
|
||||||
|
gamedata.servername = ""
|
||||||
|
gamedata.serverdescription = ""
|
||||||
|
|
||||||
|
serverlistmgr.add_favorite({
|
||||||
|
address = gamedata.address,
|
||||||
|
port = gamedata.port,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
core.settings:set("name", fields.name)
|
||||||
|
core.settings:set("address", gamedata.address)
|
||||||
|
core.settings:set("remote_port", gamedata.port)
|
||||||
|
|
||||||
|
core.start()
|
||||||
|
end
|
||||||
|
|
||||||
|
if fields["dlg_register_cancel"] then
|
||||||
|
this:delete()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
function create_register_dialog(address, port, server)
|
||||||
|
assert(address)
|
||||||
|
assert(type(port) == "number")
|
||||||
|
|
||||||
|
local retval = dialog_create("dlg_register",
|
||||||
|
register_formspec,
|
||||||
|
register_buttonhandler,
|
||||||
|
nil)
|
||||||
|
retval.data.address = address
|
||||||
|
retval.data.port = port
|
||||||
|
retval.data.server = server
|
||||||
|
retval.data.name = core.settings:get("name") or ""
|
||||||
|
return retval
|
||||||
|
end
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
mt_color_grey = "#AAAAAA"
|
mt_color_grey = "#AAAAAA"
|
||||||
mt_color_blue = "#6389FF"
|
mt_color_blue = "#6389FF"
|
||||||
|
mt_color_lightblue = "#99CCFF"
|
||||||
mt_color_green = "#72FF63"
|
mt_color_green = "#72FF63"
|
||||||
mt_color_dark_green = "#25C191"
|
mt_color_dark_green = "#25C191"
|
||||||
mt_color_orange = "#FF8800"
|
mt_color_orange = "#FF8800"
|
||||||
|
@ -43,6 +44,7 @@ dofile(menupath .. DIR_DELIM .. "dlg_contentstore.lua")
|
||||||
dofile(menupath .. DIR_DELIM .. "dlg_create_world.lua")
|
dofile(menupath .. DIR_DELIM .. "dlg_create_world.lua")
|
||||||
dofile(menupath .. DIR_DELIM .. "dlg_delete_content.lua")
|
dofile(menupath .. DIR_DELIM .. "dlg_delete_content.lua")
|
||||||
dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua")
|
dofile(menupath .. DIR_DELIM .. "dlg_delete_world.lua")
|
||||||
|
dofile(menupath .. DIR_DELIM .. "dlg_register.lua")
|
||||||
dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua")
|
dofile(menupath .. DIR_DELIM .. "dlg_rename_modpack.lua")
|
||||||
|
|
||||||
local tabs = {}
|
local tabs = {}
|
||||||
|
|
|
@ -140,7 +140,9 @@ return {
|
||||||
fgettext("Active renderer:") .. "\n" ..
|
fgettext("Active renderer:") .. "\n" ..
|
||||||
core.formspec_escape(core.get_screen_info().render_info) .. "]"
|
core.formspec_escape(core.get_screen_info().render_info) .. "]"
|
||||||
|
|
||||||
if PLATFORM ~= "Android" then
|
if PLATFORM == "Android" then
|
||||||
|
fs = fs .. "button[0,4;3.5,1;share_debug;" .. fgettext("Share debug log") .. "]"
|
||||||
|
else
|
||||||
fs = fs .. "tooltip[userdata;" ..
|
fs = fs .. "tooltip[userdata;" ..
|
||||||
fgettext("Opens the directory that contains user-provided worlds, games, mods,\n" ..
|
fgettext("Opens the directory that contains user-provided worlds, games, mods,\n" ..
|
||||||
"and texture packs in a file manager / explorer.") .. "]"
|
"and texture packs in a file manager / explorer.") .. "]"
|
||||||
|
@ -154,6 +156,11 @@ return {
|
||||||
core.open_url("https://www.minetest.net")
|
core.open_url("https://www.minetest.net")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if fields.share_debug then
|
||||||
|
local path = core.get_user_path() .. DIR_DELIM .. "debug.txt"
|
||||||
|
core.share_file(path)
|
||||||
|
end
|
||||||
|
|
||||||
if fields.userdata then
|
if fields.userdata then
|
||||||
core.open_dir(core.get_user_path())
|
core.open_dir(core.get_user_path())
|
||||||
end
|
end
|
||||||
|
|
|
@ -87,27 +87,34 @@ local function get_formspec(tabview, name, tabdata)
|
||||||
"field[4.25,0.5;1.25,0.75;te_port;;" ..
|
"field[4.25,0.5;1.25,0.75;te_port;;" ..
|
||||||
core.formspec_escape(core.settings:get("remote_port")) .. "]" ..
|
core.formspec_escape(core.settings:get("remote_port")) .. "]" ..
|
||||||
|
|
||||||
-- Name / Password
|
|
||||||
"label[0.25,1.55;" .. fgettext("Name") .. "]" ..
|
|
||||||
"label[3,1.55;" .. fgettext("Password") .. "]" ..
|
|
||||||
"field[0.25,1.75;2.75,0.75;te_name;;" ..
|
|
||||||
core.formspec_escape(core.settings:get("name")) .. "]" ..
|
|
||||||
"pwdfield[3,1.75;2.5,0.75;te_pwd;]" ..
|
|
||||||
|
|
||||||
-- Description Background
|
-- Description Background
|
||||||
"label[0.25,2.75;" .. fgettext("Server Description") .. "]" ..
|
"label[0.25,1.6;" .. fgettext("Server Description") .. "]" ..
|
||||||
"box[0.25,3;5.25,2.75;#999999]"..
|
"box[0.25,1.85;5.25,2.7;#999999]"..
|
||||||
|
|
||||||
|
-- Name / Password
|
||||||
|
"container[0,4.8]" ..
|
||||||
|
"label[0.25,0;" .. fgettext("Name") .. "]" ..
|
||||||
|
"label[3,0;" .. fgettext("Password") .. "]" ..
|
||||||
|
"field[0.25,0.2;2.625,0.75;te_name;;" .. core.formspec_escape(core.settings:get("name")) .. "]" ..
|
||||||
|
"pwdfield[2.875,0.2;2.625,0.75;te_pwd;]" ..
|
||||||
|
"container_end[]" ..
|
||||||
|
|
||||||
-- Connect
|
-- Connect
|
||||||
"button[3,6;2.5,0.75;btn_mp_connect;" .. fgettext("Connect") .. "]"
|
"button[3,6;2.5,0.75;btn_mp_login;" .. fgettext("Login") .. "]"
|
||||||
|
|
||||||
|
if core.settings:get_bool("enable_split_login_register") then
|
||||||
|
retval = retval .. "button[0.25,6;2.5,0.75;btn_mp_register;" .. fgettext("Register") .. "]"
|
||||||
|
end
|
||||||
|
|
||||||
if tabdata.selected then
|
if tabdata.selected then
|
||||||
if gamedata.fav then
|
if gamedata.fav then
|
||||||
retval = retval .. "button[0.25,6;2.5,0.75;btn_delete_favorite;" ..
|
retval = retval .. "tooltip[btn_delete_favorite;" .. fgettext("Remove favorite") .. "]"
|
||||||
fgettext("Del. Favorite") .. "]"
|
retval = retval .. "style[btn_delete_favorite;padding=6]"
|
||||||
|
retval = retval .. "image_button[5,1.3;0.5,0.5;" .. defaulttexturedir ..
|
||||||
|
"server_favorite_delete.png;btn_delete_favorite;]"
|
||||||
end
|
end
|
||||||
if gamedata.serverdescription then
|
if gamedata.serverdescription then
|
||||||
retval = retval .. "textarea[0.25,3;5.25,2.75;;;" ..
|
retval = retval .. "textarea[0.25,1.85;5.2,2.75;;;" ..
|
||||||
core.formspec_escape(gamedata.serverdescription) .. "]"
|
core.formspec_escape(gamedata.serverdescription) .. "]"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -339,12 +346,15 @@ local function main_button_handler(tabview, fields, name, tabdata)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if (fields.btn_mp_connect or fields.key_enter)
|
if (fields.btn_mp_login or fields.key_enter)
|
||||||
and fields.te_address ~= "" and fields.te_port then
|
and fields.te_address ~= "" and fields.te_port then
|
||||||
gamedata.playername = fields.te_name
|
gamedata.playername = fields.te_name
|
||||||
gamedata.password = fields.te_pwd
|
gamedata.password = fields.te_pwd
|
||||||
gamedata.address = fields.te_address
|
gamedata.address = fields.te_address
|
||||||
gamedata.port = tonumber(fields.te_port)
|
gamedata.port = tonumber(fields.te_port)
|
||||||
|
|
||||||
|
local enable_split_login_register = core.settings:get_bool("enable_split_login_register")
|
||||||
|
gamedata.allow_login_or_register = enable_split_login_register and "login" or "any"
|
||||||
gamedata.selected_world = 0
|
gamedata.selected_world = 0
|
||||||
|
|
||||||
local idx = core.get_table_index("servers")
|
local idx = core.get_table_index("servers")
|
||||||
|
@ -381,6 +391,25 @@ local function main_button_handler(tabview, fields, name, tabdata)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if fields.btn_mp_register and fields.te_address ~= "" and fields.te_port then
|
||||||
|
local idx = core.get_table_index("servers")
|
||||||
|
local server = idx and tabdata.lookup[idx]
|
||||||
|
if server and (server.address ~= fields.te_address or server.port ~= tonumber(fields.te_port)) then
|
||||||
|
server = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if server and not is_server_protocol_compat_or_error(
|
||||||
|
server.proto_min, server.proto_max) then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local dlg = create_register_dialog(fields.te_address, tonumber(fields.te_port), server)
|
||||||
|
dlg:set_parent(tabview)
|
||||||
|
tabview:hide()
|
||||||
|
dlg:show()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -160,7 +160,7 @@ local function formspec(tabview, name, tabdata)
|
||||||
.. getSettingIndex.NodeHighlighting() .. "]" ..
|
.. getSettingIndex.NodeHighlighting() .. "]" ..
|
||||||
"dropdown[0.25,3.6;3.5;dd_leaves_style;" .. dd_options.leaves[1] .. ";"
|
"dropdown[0.25,3.6;3.5;dd_leaves_style;" .. dd_options.leaves[1] .. ";"
|
||||||
.. getSettingIndex.Leaves() .. "]" ..
|
.. getSettingIndex.Leaves() .. "]" ..
|
||||||
"box[4,0;3.75,4.5;#999999]" ..
|
"box[4,0;3.75,4.9;#999999]" ..
|
||||||
"label[4.25,0.1;" .. fgettext("Texturing:") .. "]" ..
|
"label[4.25,0.1;" .. fgettext("Texturing:") .. "]" ..
|
||||||
"dropdown[4.25,0.55;3.5;dd_filters;" .. dd_options.filters[1] .. ";"
|
"dropdown[4.25,0.55;3.5;dd_filters;" .. dd_options.filters[1] .. ";"
|
||||||
.. getSettingIndex.Filter() .. "]" ..
|
.. getSettingIndex.Filter() .. "]" ..
|
||||||
|
@ -169,9 +169,6 @@ local function formspec(tabview, name, tabdata)
|
||||||
"label[4.25,2.15;" .. fgettext("Antialiasing:") .. "]" ..
|
"label[4.25,2.15;" .. fgettext("Antialiasing:") .. "]" ..
|
||||||
"dropdown[4.25,2.6;3.5;dd_antialiasing;" .. dd_options.antialiasing[1] .. ";"
|
"dropdown[4.25,2.6;3.5;dd_antialiasing;" .. dd_options.antialiasing[1] .. ";"
|
||||||
.. getSettingIndex.Antialiasing() .. "]" ..
|
.. getSettingIndex.Antialiasing() .. "]" ..
|
||||||
"label[4.25,3.45;" .. fgettext("Screen:") .. "]" ..
|
|
||||||
"checkbox[4.25,3.6;cb_autosave_screensize;" .. fgettext("Autosave Screen Size") .. ";"
|
|
||||||
.. dump(core.settings:get_bool("autosave_screensize")) .. "]" ..
|
|
||||||
"box[8,0;3.75,4.5;#999999]"
|
"box[8,0;3.75,4.5;#999999]"
|
||||||
|
|
||||||
local video_driver = core.settings:get("video_driver")
|
local video_driver = core.settings:get("video_driver")
|
||||||
|
@ -203,10 +200,15 @@ local function formspec(tabview, name, tabdata)
|
||||||
|
|
||||||
if core.settings:get("touchscreen_threshold") ~= nil then
|
if core.settings:get("touchscreen_threshold") ~= nil then
|
||||||
tab_string = tab_string ..
|
tab_string = tab_string ..
|
||||||
"label[4.3,4.2;" .. fgettext("Touchthreshold: (px)") .. "]" ..
|
"label[4.25,3.5;" .. fgettext("Touch threshold (px):") .. "]" ..
|
||||||
"dropdown[4.25,4.65;3.5;dd_touchthreshold;0,10,20,30,40,50;" ..
|
"dropdown[4.25,3.95;3.5;dd_touchthreshold;0,10,20,30,40,50;" ..
|
||||||
((tonumber(core.settings:get("touchscreen_threshold")) / 10) + 1) ..
|
((tonumber(core.settings:get("touchscreen_threshold")) / 10) + 1) ..
|
||||||
"]box[4.0,4.5;3.75,1.0;#999999]"
|
"]"
|
||||||
|
else
|
||||||
|
tab_string = tab_string ..
|
||||||
|
"label[4.25,3.65;" .. fgettext("Screen:") .. "]" ..
|
||||||
|
"checkbox[4.25,3.9;cb_autosave_screensize;" .. fgettext("Autosave Screen Size") .. ";"
|
||||||
|
.. dump(core.settings:get_bool("autosave_screensize")) .. "]"
|
||||||
end
|
end
|
||||||
|
|
||||||
if shaders_enabled then
|
if shaders_enabled then
|
||||||
|
|
|
@ -1045,9 +1045,9 @@ serverlist_file (Serverlist file) string favoriteservers.json
|
||||||
# 0 to disable queueing and -1 to make the queue size unlimited.
|
# 0 to disable queueing and -1 to make the queue size unlimited.
|
||||||
max_out_chat_queue_size (Maximum size of the out chat queue) int 20
|
max_out_chat_queue_size (Maximum size of the out chat queue) int 20
|
||||||
|
|
||||||
# Enable register confirmation when connecting to server.
|
# If enabled, account registration is separate from login in the UI.
|
||||||
# If disabled, new account will be registered automatically.
|
# If disabled, new accounts will be registered automatically when logging in.
|
||||||
enable_register_confirmation (Enable register confirmation) bool true
|
enable_split_login_register (Enable split login/register) bool true
|
||||||
|
|
||||||
[*Advanced]
|
[*Advanced]
|
||||||
|
|
||||||
|
|
|
@ -1673,10 +1673,16 @@ these formats.
|
||||||
### Serialized
|
### Serialized
|
||||||
|
|
||||||
This is called "stackstring" or "itemstring". It is a simple string with
|
This is called "stackstring" or "itemstring". It is a simple string with
|
||||||
1-3 components: the full item identifier, an optional amount and an optional
|
1-4 components:
|
||||||
wear value. Syntax:
|
|
||||||
|
|
||||||
<identifier> [<amount>[ <wear>]]
|
1. Full item identifier ("item name")
|
||||||
|
2. Optional amount
|
||||||
|
3. Optional wear value
|
||||||
|
4. Optional item metadata
|
||||||
|
|
||||||
|
Syntax:
|
||||||
|
|
||||||
|
<identifier> [<amount>[ <wear>[ <metadata>]]]
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
|
@ -1684,6 +1690,26 @@ Examples:
|
||||||
* `"default:dirt 5"`: 5 dirt
|
* `"default:dirt 5"`: 5 dirt
|
||||||
* `"default:pick_stone"`: a new stone pickaxe
|
* `"default:pick_stone"`: a new stone pickaxe
|
||||||
* `"default:pick_wood 1 21323"`: a wooden pickaxe, ca. 1/3 worn out
|
* `"default:pick_wood 1 21323"`: a wooden pickaxe, ca. 1/3 worn out
|
||||||
|
* `[[default:pick_wood 1 21323 "\u0001description\u0002My worn out pick\u0003"]]`:
|
||||||
|
* a wooden pickaxe from the `default` mod,
|
||||||
|
* amount must be 1 (pickaxe is a tool), ca. 1/3 worn out (it's a tool),
|
||||||
|
* with the `description` field set to `"My worn out pick"` in its metadata
|
||||||
|
* `[[default:dirt 5 0 "\u0001description\u0002Special dirt\u0003"]]`:
|
||||||
|
* analogeous to the above example
|
||||||
|
* note how the wear is set to `0` as dirt is not a tool
|
||||||
|
|
||||||
|
You should ideally use the `ItemStack` format to build complex item strings
|
||||||
|
(especially if they use item metadata)
|
||||||
|
without relying on the serialization format. Example:
|
||||||
|
|
||||||
|
local stack = ItemStack("default:pick_wood")
|
||||||
|
stack:set_wear(21323)
|
||||||
|
stack:get_meta():set_string("description", "My worn out pick")
|
||||||
|
local itemstring = stack:to_string()
|
||||||
|
|
||||||
|
Additionally the methods `minetest.itemstring_with_palette(item, palette_index)`
|
||||||
|
and `minetest.itemstring_with_color(item, colorstring)` may be used to create
|
||||||
|
item strings encoding color information in their metadata.
|
||||||
|
|
||||||
### Table format
|
### Table format
|
||||||
|
|
||||||
|
@ -1779,7 +1805,6 @@ An example: Make meat soup from any meat, any water and any bowl:
|
||||||
{"group:water"},
|
{"group:water"},
|
||||||
{"group:bowl"},
|
{"group:bowl"},
|
||||||
},
|
},
|
||||||
-- preserve = {"group:bowl"}, -- Not implemented yet (TODO)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Another example: Make red wool from white wool and red dye:
|
Another example: Make red wool from white wool and red dye:
|
||||||
|
@ -3593,6 +3618,12 @@ Helper functions
|
||||||
* `minetest.pointed_thing_to_face_pos(placer, pointed_thing)`: returns a
|
* `minetest.pointed_thing_to_face_pos(placer, pointed_thing)`: returns a
|
||||||
position.
|
position.
|
||||||
* returns the exact position on the surface of a pointed node
|
* returns the exact position on the surface of a pointed node
|
||||||
|
* `minetest.get_tool_wear_after_use(uses [, initial_wear])`
|
||||||
|
* Simulates a tool being used once and returns the added wear,
|
||||||
|
such that, if only this function is used to calculate wear,
|
||||||
|
the tool will break exactly after `uses` times of uses
|
||||||
|
* `uses`: Number of times the tool can be used
|
||||||
|
* `initial_wear`: The initial wear the tool starts with (default: 0)
|
||||||
* `minetest.get_dig_params(groups, tool_capabilities [, wear])`:
|
* `minetest.get_dig_params(groups, tool_capabilities [, wear])`:
|
||||||
Simulates an item that digs a node.
|
Simulates an item that digs a node.
|
||||||
Returns a table with the following fields:
|
Returns a table with the following fields:
|
||||||
|
@ -6528,7 +6559,13 @@ an itemstring, a table or `nil`.
|
||||||
or those of the hand if none are defined for this item type
|
or those of the hand if none are defined for this item type
|
||||||
* `add_wear(amount)`
|
* `add_wear(amount)`
|
||||||
* Increases wear by `amount` if the item is a tool, otherwise does nothing
|
* Increases wear by `amount` if the item is a tool, otherwise does nothing
|
||||||
|
* Valid `amount` range is [0,65536]
|
||||||
* `amount`: number, integer
|
* `amount`: number, integer
|
||||||
|
* `add_wear_by_uses(max_uses)`
|
||||||
|
* Increases wear in such a way that, if only this function is called,
|
||||||
|
the item breaks after `max_uses` times
|
||||||
|
* Valid `max_uses` range is [0,65536]
|
||||||
|
* Does nothing if item is not a tool or if `max_uses` is 0
|
||||||
* `add_item(item)`: returns leftover `ItemStack`
|
* `add_item(item)`: returns leftover `ItemStack`
|
||||||
* Put some item or stack onto this stack
|
* Put some item or stack onto this stack
|
||||||
* `item_fits(item)`: returns `true` if item or stack can be fully added to
|
* `item_fits(item)`: returns `true` if item or stack can be fully added to
|
||||||
|
|
|
@ -46,6 +46,8 @@ core.open_url(url)
|
||||||
core.open_dir(path)
|
core.open_dir(path)
|
||||||
^ opens the path in the system file browser/explorer, returns false on failure.
|
^ opens the path in the system file browser/explorer, returns false on failure.
|
||||||
^ Must be an existing directory.
|
^ Must be an existing directory.
|
||||||
|
core.share_file(path)
|
||||||
|
^ Android only. Shares file using the share popup
|
||||||
core.get_version() (possible in async calls)
|
core.get_version() (possible in async calls)
|
||||||
^ returns current core version
|
^ returns current core version
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,8 @@ Client::Client(
|
||||||
MtEventManager *event,
|
MtEventManager *event,
|
||||||
RenderingEngine *rendering_engine,
|
RenderingEngine *rendering_engine,
|
||||||
bool ipv6,
|
bool ipv6,
|
||||||
GameUI *game_ui
|
GameUI *game_ui,
|
||||||
|
ELoginRegister allow_login_or_register
|
||||||
):
|
):
|
||||||
m_mesh_update_thread(this),
|
m_mesh_update_thread(this),
|
||||||
m_tsrc(tsrc),
|
m_tsrc(tsrc),
|
||||||
|
@ -125,7 +126,8 @@ Client::Client(
|
||||||
m_media_downloader(new ClientMediaDownloader()),
|
m_media_downloader(new ClientMediaDownloader()),
|
||||||
m_state(LC_Created),
|
m_state(LC_Created),
|
||||||
m_game_ui(game_ui),
|
m_game_ui(game_ui),
|
||||||
m_modchannel_mgr(new ModChannelMgr())
|
m_modchannel_mgr(new ModChannelMgr()),
|
||||||
|
m_allow_login_or_register(allow_login_or_register)
|
||||||
{
|
{
|
||||||
// Add local player
|
// Add local player
|
||||||
m_env.setLocalPlayer(new LocalPlayer(this, playername));
|
m_env.setLocalPlayer(new LocalPlayer(this, playername));
|
||||||
|
@ -399,10 +401,6 @@ void Client::step(float dtime)
|
||||||
initial_step = false;
|
initial_step = false;
|
||||||
}
|
}
|
||||||
else if(m_state == LC_Created) {
|
else if(m_state == LC_Created) {
|
||||||
if (m_is_registration_confirmation_state) {
|
|
||||||
// Waiting confirmation
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
float &counter = m_connection_reinit_timer;
|
float &counter = m_connection_reinit_timer;
|
||||||
counter -= dtime;
|
counter -= dtime;
|
||||||
if(counter <= 0.0) {
|
if(counter <= 0.0) {
|
||||||
|
@ -1081,18 +1079,6 @@ void Client::sendInit(const std::string &playerName)
|
||||||
Send(&pkt);
|
Send(&pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::promptConfirmRegistration(AuthMechanism chosen_auth_mechanism)
|
|
||||||
{
|
|
||||||
m_chosen_auth_mech = chosen_auth_mechanism;
|
|
||||||
m_is_registration_confirmation_state = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::confirmRegistration()
|
|
||||||
{
|
|
||||||
m_is_registration_confirmation_state = false;
|
|
||||||
startAuth(m_chosen_auth_mech);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Client::startAuth(AuthMechanism chosen_auth_mechanism)
|
void Client::startAuth(AuthMechanism chosen_auth_mechanism)
|
||||||
{
|
{
|
||||||
m_chosen_auth_mech = chosen_auth_mechanism;
|
m_chosen_auth_mech = chosen_auth_mechanism;
|
||||||
|
|
|
@ -37,6 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "mesh_generator_thread.h"
|
#include "mesh_generator_thread.h"
|
||||||
#include "network/address.h"
|
#include "network/address.h"
|
||||||
#include "network/peerhandler.h"
|
#include "network/peerhandler.h"
|
||||||
|
#include "gameparams.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
#define CLIENT_CHAT_MESSAGE_LIMIT_PER_10S 10.0f
|
#define CLIENT_CHAT_MESSAGE_LIMIT_PER_10S 10.0f
|
||||||
|
@ -126,7 +127,8 @@ public:
|
||||||
MtEventManager *event,
|
MtEventManager *event,
|
||||||
RenderingEngine *rendering_engine,
|
RenderingEngine *rendering_engine,
|
||||||
bool ipv6,
|
bool ipv6,
|
||||||
GameUI *game_ui
|
GameUI *game_ui,
|
||||||
|
ELoginRegister allow_login_or_register
|
||||||
);
|
);
|
||||||
|
|
||||||
~Client();
|
~Client();
|
||||||
|
@ -348,8 +350,7 @@ public:
|
||||||
u16 getProtoVersion()
|
u16 getProtoVersion()
|
||||||
{ return m_proto_ver; }
|
{ return m_proto_ver; }
|
||||||
|
|
||||||
void confirmRegistration();
|
ELoginRegister m_allow_login_or_register = ELoginRegister::Any;
|
||||||
bool m_is_registration_confirmation_state = false;
|
|
||||||
bool m_simple_singleplayer_mode;
|
bool m_simple_singleplayer_mode;
|
||||||
|
|
||||||
float mediaReceiveProgress();
|
float mediaReceiveProgress();
|
||||||
|
@ -467,7 +468,6 @@ private:
|
||||||
static AuthMechanism choseAuthMech(const u32 mechs);
|
static AuthMechanism choseAuthMech(const u32 mechs);
|
||||||
|
|
||||||
void sendInit(const std::string &playerName);
|
void sendInit(const std::string &playerName);
|
||||||
void promptConfirmRegistration(AuthMechanism chosen_auth_mechanism);
|
|
||||||
void startAuth(AuthMechanism chosen_auth_mechanism);
|
void startAuth(AuthMechanism chosen_auth_mechanism);
|
||||||
void sendDeletedBlocks(std::vector<v3s16> &blocks);
|
void sendDeletedBlocks(std::vector<v3s16> &blocks);
|
||||||
void sendGotBlocks(const std::vector<v3s16> &blocks);
|
void sendGotBlocks(const std::vector<v3s16> &blocks);
|
||||||
|
|
|
@ -451,6 +451,7 @@ bool ClientLauncher::launch_game(std::string &error_message,
|
||||||
start_data.name = menudata.name;
|
start_data.name = menudata.name;
|
||||||
start_data.password = menudata.password;
|
start_data.password = menudata.password;
|
||||||
start_data.address = std::move(menudata.address);
|
start_data.address = std::move(menudata.address);
|
||||||
|
start_data.allow_login_or_register = menudata.allow_login_or_register;
|
||||||
server_name = menudata.servername;
|
server_name = menudata.servername;
|
||||||
server_description = menudata.serverdescription;
|
server_description = menudata.serverdescription;
|
||||||
|
|
||||||
|
|
|
@ -219,13 +219,11 @@ void ClientMap::updateDrawList()
|
||||||
// Number of blocks occlusion culled
|
// Number of blocks occlusion culled
|
||||||
u32 blocks_occlusion_culled = 0;
|
u32 blocks_occlusion_culled = 0;
|
||||||
|
|
||||||
// No occlusion culling when free_move is on and camera is
|
// No occlusion culling when free_move is on and camera is inside ground
|
||||||
// inside ground
|
|
||||||
bool occlusion_culling_enabled = true;
|
bool occlusion_culling_enabled = true;
|
||||||
if ((g_settings->getBool("free_move") && g_settings->getBool("noclip")) || g_settings->getBool("freecam")) {
|
if (m_control.allow_noclip || g_settings->getBool("freecam")) {
|
||||||
MapNode n = getNode(cam_pos_nodes);
|
MapNode n = getNode(cam_pos_nodes);
|
||||||
if (n.getContent() == CONTENT_IGNORE ||
|
if (n.getContent() == CONTENT_IGNORE || m_nodedef->get(n).solidness == 2)
|
||||||
m_nodedef->get(n).solidness == 2)
|
|
||||||
occlusion_culling_enabled = false;
|
occlusion_culling_enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,19 +676,17 @@ void ClientMap::renderPostFx(CameraMode cam_mode)
|
||||||
|
|
||||||
MapNode n = getNode(floatToInt(m_camera_position, BS));
|
MapNode n = getNode(floatToInt(m_camera_position, BS));
|
||||||
|
|
||||||
// - If the player is in a solid node, make everything black.
|
|
||||||
// - If the player is in liquid, draw a semi-transparent overlay.
|
|
||||||
// - Do not if player is in third person mode
|
|
||||||
const ContentFeatures& features = m_nodedef->get(n);
|
const ContentFeatures& features = m_nodedef->get(n);
|
||||||
video::SColor post_effect_color = features.post_effect_color;
|
video::SColor post_effect_color = features.post_effect_color;
|
||||||
if(features.solidness == 2 && !((g_settings->getBool("noclip") || g_settings->getBool("freecam")) &&
|
|
||||||
(m_client->checkLocalPrivilege("noclip") || g_settings->getBool("freecam"))) &&
|
// If the camera is in a solid node, make everything black.
|
||||||
cam_mode == CAMERA_MODE_FIRST)
|
// (first person mode only)
|
||||||
{
|
if (features.solidness == 2 && cam_mode == CAMERA_MODE_FIRST &&
|
||||||
|
!(m_control.allow_noclip || g_settings->getBool("freecam"))) {
|
||||||
post_effect_color = video::SColor(255, 0, 0, 0);
|
post_effect_color = video::SColor(255, 0, 0, 0);
|
||||||
}
|
}
|
||||||
if (post_effect_color.getAlpha() != 0)
|
|
||||||
{
|
if (post_effect_color.getAlpha() != 0) {
|
||||||
// Draw a full-screen rectangle
|
// Draw a full-screen rectangle
|
||||||
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
video::IVideoDriver* driver = SceneManager->getVideoDriver();
|
||||||
v2u32 ss = driver->getScreenSize();
|
v2u32 ss = driver->getScreenSize();
|
||||||
|
|
|
@ -27,10 +27,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
struct MapDrawControl
|
struct MapDrawControl
|
||||||
{
|
{
|
||||||
// Overrides limits by drawing everything
|
|
||||||
bool range_all = false;
|
|
||||||
// Wanted drawing range
|
// Wanted drawing range
|
||||||
float wanted_range = 0.0f;
|
float wanted_range = 0.0f;
|
||||||
|
// Overrides limits by drawing everything
|
||||||
|
bool range_all = false;
|
||||||
|
// Allow rendering out of bounds
|
||||||
|
bool allow_noclip = false;
|
||||||
// show a wire frame for debugging
|
// show a wire frame for debugging
|
||||||
bool show_wireframe = false;
|
bool show_wireframe = false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -43,7 +43,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "gameparams.h"
|
#include "gameparams.h"
|
||||||
#include "gettext.h"
|
#include "gettext.h"
|
||||||
#include "gui/guiChatConsole.h"
|
#include "gui/guiChatConsole.h"
|
||||||
#include "gui/guiConfirmRegistration.h"
|
|
||||||
#include "gui/guiFormSpecMenu.h"
|
#include "gui/guiFormSpecMenu.h"
|
||||||
#include "gui/guiKeyChangeMenu.h"
|
#include "gui/guiKeyChangeMenu.h"
|
||||||
#include "gui/guiPasswordChange.h"
|
#include "gui/guiPasswordChange.h"
|
||||||
|
@ -675,7 +674,8 @@ bool Game::connectToServer(const GameStartData &start_data,
|
||||||
start_data.password, start_data.address,
|
start_data.password, start_data.address,
|
||||||
*draw_control, texture_src, shader_src,
|
*draw_control, texture_src, shader_src,
|
||||||
itemdef_manager, nodedef_manager, sound, eventmgr,
|
itemdef_manager, nodedef_manager, sound, eventmgr,
|
||||||
m_rendering_engine, connect_address.isIPv6(), m_game_ui.get());
|
m_rendering_engine, connect_address.isIPv6(), m_game_ui.get(),
|
||||||
|
start_data.allow_login_or_register);
|
||||||
client->migrateModStorage();
|
client->migrateModStorage();
|
||||||
} catch (const BaseException &e) {
|
} catch (const BaseException &e) {
|
||||||
*error_message = fmtgettext("Error creating client: %s", e.what());
|
*error_message = fmtgettext("Error creating client: %s", e.what());
|
||||||
|
@ -738,28 +738,16 @@ bool Game::connectToServer(const GameStartData &start_data,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client->m_is_registration_confirmation_state) {
|
wait_time += dtime;
|
||||||
if (registration_confirmation_shown) {
|
// Only time out if we aren't waiting for the server we started
|
||||||
// Keep drawing the GUI
|
if (!start_data.address.empty() && wait_time > 10) {
|
||||||
m_rendering_engine->draw_menu_scene(guienv, dtime, true);
|
*error_message = gettext("Connection timed out.");
|
||||||
} else {
|
errorstream << *error_message << std::endl;
|
||||||
registration_confirmation_shown = true;
|
break;
|
||||||
(new GUIConfirmRegistration(guienv, guienv->getRootGUIElement(), -1,
|
|
||||||
&g_menumgr, client, start_data.name, start_data.password,
|
|
||||||
connection_aborted, texture_src))->drop();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
wait_time += dtime;
|
|
||||||
// Only time out if we aren't waiting for the server we started
|
|
||||||
if (!start_data.address.empty() && wait_time > 10) {
|
|
||||||
*error_message = gettext("Connection timed out.");
|
|
||||||
errorstream << *error_message << std::endl;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update status
|
|
||||||
showOverlayMessage(N_("Connecting to server..."), dtime, 20);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update status
|
||||||
|
showOverlayMessage(N_("Connecting to server..."), dtime, 20);
|
||||||
}
|
}
|
||||||
} catch (con::PeerNotFoundException &e) {
|
} catch (con::PeerNotFoundException &e) {
|
||||||
// TODO: Should something be done here? At least an info/error
|
// TODO: Should something be done here? At least an info/error
|
||||||
|
@ -938,6 +926,8 @@ void Game::processQueues()
|
||||||
void Game::updateDebugState()
|
void Game::updateDebugState()
|
||||||
{
|
{
|
||||||
LocalPlayer *player = client->getEnv().getLocalPlayer();
|
LocalPlayer *player = client->getEnv().getLocalPlayer();
|
||||||
|
|
||||||
|
// debug UI and wireframe
|
||||||
bool has_debug = client->checkPrivilege("debug");
|
bool has_debug = client->checkPrivilege("debug");
|
||||||
bool has_basic_debug = has_debug || (player->hud_flags & HUD_FLAG_BASIC_DEBUG);
|
bool has_basic_debug = has_debug || (player->hud_flags & HUD_FLAG_BASIC_DEBUG);
|
||||||
|
|
||||||
|
@ -952,6 +942,9 @@ void Game::updateDebugState()
|
||||||
hud->disableBlockBounds();
|
hud->disableBlockBounds();
|
||||||
if (!has_debug)
|
if (!has_debug)
|
||||||
draw_control->show_wireframe = false;
|
draw_control->show_wireframe = false;
|
||||||
|
|
||||||
|
// noclip
|
||||||
|
draw_control->allow_noclip = m_cache_enable_noclip && client->checkPrivilege("noclip");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::updateProfilers(const RunStats &stats, const FpsControl &draw_times,
|
void Game::updateProfilers(const RunStats &stats, const FpsControl &draw_times,
|
||||||
|
@ -3047,7 +3040,10 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
|
||||||
float direct_brightness;
|
float direct_brightness;
|
||||||
bool sunlight_seen;
|
bool sunlight_seen;
|
||||||
|
|
||||||
if ((m_cache_enable_noclip && m_cache_enable_free_move) || g_settings->getBool("freecam")) {
|
// When in noclip mode force same sky brightness as above ground so you
|
||||||
|
// can see properly
|
||||||
|
if ((draw_control->allow_noclip && m_cache_enable_free_move &&
|
||||||
|
client->checkPrivilege("fly")) || g_settings->getBool("freecam")) {
|
||||||
direct_brightness = time_brightness;
|
direct_brightness = time_brightness;
|
||||||
sunlight_seen = true;
|
sunlight_seen = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -450,16 +450,6 @@ void LocalPlayer::move(f32 dtime, Environment *env, f32 pos_max_d,
|
||||||
camera_impact = getSpeed().Y * -1;
|
camera_impact = getSpeed().Y * -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
camera_barely_in_ceiling = false;
|
|
||||||
v3s16 camera_np = floatToInt(getEyePosition(), BS);
|
|
||||||
MapNode n = map->getNode(camera_np);
|
|
||||||
if (n.getContent() != CONTENT_IGNORE) {
|
|
||||||
if (nodemgr->get(n).walkable && nodemgr->get(n).solidness == 2)
|
|
||||||
camera_barely_in_ceiling = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check properties of the node on which the player is standing
|
Check properties of the node on which the player is standing
|
||||||
*/
|
*/
|
||||||
|
@ -730,8 +720,7 @@ v3f LocalPlayer::getSendSpeed()
|
||||||
|
|
||||||
v3f LocalPlayer::getEyeOffset() const
|
v3f LocalPlayer::getEyeOffset() const
|
||||||
{
|
{
|
||||||
float eye_height = camera_barely_in_ceiling ? m_eye_height - 0.125f : m_eye_height;
|
return v3f(0.0f, BS * m_eye_height, 0.0f);
|
||||||
return v3f(0.0f, BS * eye_height, 0.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientActiveObject *LocalPlayer::getParent() const
|
ClientActiveObject *LocalPlayer::getParent() const
|
||||||
|
@ -1071,16 +1060,6 @@ void LocalPlayer::old_move(f32 dtime, Environment *env, f32 pos_max_d,
|
||||||
camera_impact = getSpeed().Y * -1.0f;
|
camera_impact = getSpeed().Y * -1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
camera_barely_in_ceiling = false;
|
|
||||||
v3s16 camera_np = floatToInt(getEyePosition(), BS);
|
|
||||||
MapNode n = map->getNode(camera_np);
|
|
||||||
if (n.getContent() != CONTENT_IGNORE) {
|
|
||||||
if (nodemgr->get(n).walkable && nodemgr->get(n).solidness == 2)
|
|
||||||
camera_barely_in_ceiling = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Update the node last under the player
|
Update the node last under the player
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -237,7 +237,6 @@ private:
|
||||||
u16 m_breath = PLAYER_MAX_BREATH_DEFAULT;
|
u16 m_breath = PLAYER_MAX_BREATH_DEFAULT;
|
||||||
f32 m_yaw = 0.0f;
|
f32 m_yaw = 0.0f;
|
||||||
f32 m_pitch = 0.0f;
|
f32 m_pitch = 0.0f;
|
||||||
bool camera_barely_in_ceiling = false;
|
|
||||||
aabb3f m_collisionbox = aabb3f(-BS * 0.30f, 0.0f, -BS * 0.30f, BS * 0.30f,
|
aabb3f m_collisionbox = aabb3f(-BS * 0.30f, 0.0f, -BS * 0.30f, BS * 0.30f,
|
||||||
BS * 1.75f, BS * 0.30f);
|
BS * 1.75f, BS * 0.30f);
|
||||||
float m_eye_height = 1.625f;
|
float m_eye_height = 1.625f;
|
||||||
|
|
|
@ -64,7 +64,7 @@ void set_default_settings()
|
||||||
settings->setDefault("enable_client_modding", "true");
|
settings->setDefault("enable_client_modding", "true");
|
||||||
settings->setDefault("max_out_chat_queue_size", "20");
|
settings->setDefault("max_out_chat_queue_size", "20");
|
||||||
settings->setDefault("pause_on_lost_focus", "false");
|
settings->setDefault("pause_on_lost_focus", "false");
|
||||||
settings->setDefault("enable_register_confirmation", "true");
|
settings->setDefault("enable_split_login_register", "true");
|
||||||
settings->setDefault("chat_weblink_color", "#8888FF");
|
settings->setDefault("chat_weblink_color", "#8888FF");
|
||||||
|
|
||||||
// Cheat Menu
|
// Cheat Menu
|
||||||
|
@ -526,7 +526,6 @@ void set_default_settings()
|
||||||
// Altered settings for macOS
|
// Altered settings for macOS
|
||||||
#if defined(__MACH__) && defined(__APPLE__)
|
#if defined(__MACH__) && defined(__APPLE__)
|
||||||
settings->setDefault("keymap_sneak", "KEY_SHIFT");
|
settings->setDefault("keymap_sneak", "KEY_SHIFT");
|
||||||
settings->setDefault("fps_max", "0");
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_TOUCHSCREENGUI
|
#ifdef HAVE_TOUCHSCREENGUI
|
||||||
|
|
|
@ -20,8 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "irrlichttypes.h"
|
#include "irrlichttypes.h"
|
||||||
|
#include "content/subgames.h"
|
||||||
struct SubgameSpec;
|
|
||||||
|
|
||||||
// Information provided from "main"
|
// Information provided from "main"
|
||||||
struct GameParams
|
struct GameParams
|
||||||
|
@ -34,6 +33,12 @@ struct GameParams
|
||||||
bool is_dedicated_server;
|
bool is_dedicated_server;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ELoginRegister {
|
||||||
|
Any = 0,
|
||||||
|
Login,
|
||||||
|
Register
|
||||||
|
};
|
||||||
|
|
||||||
// Information processed by main menu
|
// Information processed by main menu
|
||||||
struct GameStartData : GameParams
|
struct GameStartData : GameParams
|
||||||
{
|
{
|
||||||
|
@ -46,6 +51,8 @@ struct GameStartData : GameParams
|
||||||
std::string address;
|
std::string address;
|
||||||
bool local_server;
|
bool local_server;
|
||||||
|
|
||||||
|
ELoginRegister allow_login_or_register = ELoginRegister::Any;
|
||||||
|
|
||||||
// "world_path" must be kept in sync!
|
// "world_path" must be kept in sync!
|
||||||
WorldSpec world_spec;
|
WorldSpec world_spec;
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,7 +12,6 @@ set(gui_SRCS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/guiButtonImage.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/guiButtonImage.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/guiButtonItemImage.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/guiButtonItemImage.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/guiChatConsole.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/guiChatConsole.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/guiConfirmRegistration.cpp
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/guiEditBox.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/guiEditBox.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/guiEditBoxWithScrollbar.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/guiEditBoxWithScrollbar.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/guiEngine.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/guiEngine.cpp
|
||||||
|
|
|
@ -1,266 +0,0 @@
|
||||||
/*
|
|
||||||
Minetest
|
|
||||||
Copyright (C) 2018 srifqi, Muhammad Rifqi Priyo Susanto
|
|
||||||
<muhammadrifqipriyosusanto@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2.1 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "guiConfirmRegistration.h"
|
|
||||||
#include "client/client.h"
|
|
||||||
#include "guiButton.h"
|
|
||||||
#include <IGUICheckBox.h>
|
|
||||||
#include <IGUIButton.h>
|
|
||||||
#include <IGUIStaticText.h>
|
|
||||||
#include <IGUIFont.h>
|
|
||||||
#include "guiEditBoxWithScrollbar.h"
|
|
||||||
#include "porting.h"
|
|
||||||
|
|
||||||
#ifdef HAVE_TOUCHSCREENGUI
|
|
||||||
#include "client/renderingengine.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "gettext.h"
|
|
||||||
|
|
||||||
// Continuing from guiPasswordChange.cpp
|
|
||||||
const int ID_confirmPassword = 262;
|
|
||||||
const int ID_confirm = 263;
|
|
||||||
const int ID_intotext = 264;
|
|
||||||
const int ID_cancel = 265;
|
|
||||||
const int ID_message = 266;
|
|
||||||
|
|
||||||
GUIConfirmRegistration::GUIConfirmRegistration(gui::IGUIEnvironment *env,
|
|
||||||
gui::IGUIElement *parent, s32 id, IMenuManager *menumgr, Client *client,
|
|
||||||
const std::string &playername, const std::string &password,
|
|
||||||
bool *aborted, ISimpleTextureSource *tsrc) :
|
|
||||||
GUIModalMenu(env, parent, id, menumgr),
|
|
||||||
m_client(client), m_playername(playername), m_password(password),
|
|
||||||
m_aborted(aborted), m_tsrc(tsrc)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_TOUCHSCREENGUI
|
|
||||||
m_touchscreen_visible = false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUIConfirmRegistration::regenerateGui(v2u32 screensize)
|
|
||||||
{
|
|
||||||
acceptInput();
|
|
||||||
removeAllChildren();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Calculate new sizes and positions
|
|
||||||
*/
|
|
||||||
#ifdef HAVE_TOUCHSCREENGUI
|
|
||||||
const float s = m_gui_scale * RenderingEngine::getDisplayDensity() / 2;
|
|
||||||
#else
|
|
||||||
const float s = m_gui_scale;
|
|
||||||
#endif
|
|
||||||
DesiredRect = core::rect<s32>(
|
|
||||||
screensize.X / 2 - 600 * s / 2,
|
|
||||||
screensize.Y / 2 - 360 * s / 2,
|
|
||||||
screensize.X / 2 + 600 * s / 2,
|
|
||||||
screensize.Y / 2 + 360 * s / 2
|
|
||||||
);
|
|
||||||
recalculateAbsolutePosition(false);
|
|
||||||
|
|
||||||
v2s32 size = DesiredRect.getSize();
|
|
||||||
v2s32 topleft_client(0, 0);
|
|
||||||
|
|
||||||
const wchar_t *text;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Add stuff
|
|
||||||
*/
|
|
||||||
s32 ypos = 30 * s;
|
|
||||||
{
|
|
||||||
core::rect<s32> rect2(0, 0, 540 * s, 180 * s);
|
|
||||||
rect2 += topleft_client + v2s32(30 * s, ypos);
|
|
||||||
static const std::string info_text_template = strgettext(
|
|
||||||
"You are about to join this server with the name \"%s\" for the "
|
|
||||||
"first time.\n"
|
|
||||||
"If you proceed, a new account using your credentials will be "
|
|
||||||
"created on this server.\n"
|
|
||||||
"Please retype your password and click 'Register and Join' to "
|
|
||||||
"confirm account creation, or click 'Cancel' to abort.");
|
|
||||||
char info_text_buf[1024];
|
|
||||||
porting::mt_snprintf(info_text_buf, sizeof(info_text_buf),
|
|
||||||
info_text_template.c_str(), m_playername.c_str());
|
|
||||||
|
|
||||||
std::wstring info_text_w = utf8_to_wide(info_text_buf);
|
|
||||||
gui::IGUIEditBox *e = new GUIEditBoxWithScrollBar(info_text_w.c_str(),
|
|
||||||
true, Environment, this, ID_intotext, rect2, false, true);
|
|
||||||
e->drop();
|
|
||||||
e->setMultiLine(true);
|
|
||||||
e->setWordWrap(true);
|
|
||||||
e->setTextAlignment(gui::EGUIA_UPPERLEFT, gui::EGUIA_CENTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
ypos += 200 * s;
|
|
||||||
{
|
|
||||||
core::rect<s32> rect2(0, 0, 540 * s, 30 * s);
|
|
||||||
rect2 += topleft_client + v2s32(30 * s, ypos);
|
|
||||||
gui::IGUIEditBox *e = Environment->addEditBox(m_pass_confirm.c_str(),
|
|
||||||
rect2, true, this, ID_confirmPassword);
|
|
||||||
e->setPasswordBox(true);
|
|
||||||
Environment->setFocus(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
ypos += 50 * s;
|
|
||||||
{
|
|
||||||
core::rect<s32> rect2(0, 0, 230 * s, 35 * s);
|
|
||||||
rect2 = rect2 + v2s32(size.X / 2 - 220 * s, ypos);
|
|
||||||
text = wgettext("Register and Join");
|
|
||||||
GUIButton::addButton(Environment, rect2, m_tsrc, this, ID_confirm, text);
|
|
||||||
delete[] text;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
core::rect<s32> rect2(0, 0, 120 * s, 35 * s);
|
|
||||||
rect2 = rect2 + v2s32(size.X / 2 + 70 * s, ypos);
|
|
||||||
text = wgettext("Cancel");
|
|
||||||
GUIButton::addButton(Environment, rect2, m_tsrc, this, ID_cancel, text);
|
|
||||||
delete[] text;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
core::rect<s32> rect2(0, 0, 500 * s, 40 * s);
|
|
||||||
rect2 += topleft_client + v2s32(30 * s, ypos + 40 * s);
|
|
||||||
text = wgettext("Passwords do not match!");
|
|
||||||
IGUIElement *e = Environment->addStaticText(
|
|
||||||
text, rect2, false, true, this, ID_message);
|
|
||||||
e->setVisible(false);
|
|
||||||
delete[] text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUIConfirmRegistration::drawMenu()
|
|
||||||
{
|
|
||||||
gui::IGUISkin *skin = Environment->getSkin();
|
|
||||||
if (!skin)
|
|
||||||
return;
|
|
||||||
video::IVideoDriver *driver = Environment->getVideoDriver();
|
|
||||||
|
|
||||||
video::SColor bgcolor(140, 0, 0, 0);
|
|
||||||
driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
|
|
||||||
|
|
||||||
gui::IGUIElement::draw();
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
getAndroidUIInput();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUIConfirmRegistration::closeMenu(bool goNext)
|
|
||||||
{
|
|
||||||
if (goNext) {
|
|
||||||
m_client->confirmRegistration();
|
|
||||||
} else {
|
|
||||||
*m_aborted = true;
|
|
||||||
infostream << "Connect aborted [Escape]" << std::endl;
|
|
||||||
}
|
|
||||||
quitMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GUIConfirmRegistration::acceptInput()
|
|
||||||
{
|
|
||||||
gui::IGUIElement *e;
|
|
||||||
e = getElementFromId(ID_confirmPassword);
|
|
||||||
if (e)
|
|
||||||
m_pass_confirm = e->getText();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GUIConfirmRegistration::processInput()
|
|
||||||
{
|
|
||||||
if (utf8_to_wide(m_password) != m_pass_confirm) {
|
|
||||||
gui::IGUIElement *e = getElementFromId(ID_message);
|
|
||||||
if (e)
|
|
||||||
e->setVisible(true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GUIConfirmRegistration::OnEvent(const SEvent &event)
|
|
||||||
{
|
|
||||||
if (event.EventType == EET_KEY_INPUT_EVENT) {
|
|
||||||
// clang-format off
|
|
||||||
if ((event.KeyInput.Key == KEY_ESCAPE ||
|
|
||||||
event.KeyInput.Key == KEY_CANCEL) &&
|
|
||||||
event.KeyInput.PressedDown) {
|
|
||||||
closeMenu(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// clang-format on
|
|
||||||
if (event.KeyInput.Key == KEY_RETURN && event.KeyInput.PressedDown) {
|
|
||||||
acceptInput();
|
|
||||||
if (processInput())
|
|
||||||
closeMenu(true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.EventType != EET_GUI_EVENT)
|
|
||||||
return Parent ? Parent->OnEvent(event) : false;
|
|
||||||
|
|
||||||
if (event.GUIEvent.EventType == gui::EGET_ELEMENT_FOCUS_LOST && isVisible()) {
|
|
||||||
if (!canTakeFocus(event.GUIEvent.Element)) {
|
|
||||||
infostream << "GUIConfirmRegistration: Not allowing focus change."
|
|
||||||
<< std::endl;
|
|
||||||
// Returning true disables focus change
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED) {
|
|
||||||
switch (event.GUIEvent.Caller->getID()) {
|
|
||||||
case ID_confirm:
|
|
||||||
acceptInput();
|
|
||||||
if (processInput())
|
|
||||||
closeMenu(true);
|
|
||||||
return true;
|
|
||||||
case ID_cancel:
|
|
||||||
closeMenu(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (event.GUIEvent.EventType == gui::EGET_EDITBOX_ENTER) {
|
|
||||||
switch (event.GUIEvent.Caller->getID()) {
|
|
||||||
case ID_confirmPassword:
|
|
||||||
acceptInput();
|
|
||||||
if (processInput())
|
|
||||||
closeMenu(true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
bool GUIConfirmRegistration::getAndroidUIInput()
|
|
||||||
{
|
|
||||||
if (!hasAndroidUIInput() || m_jni_field_name != "password")
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// still waiting
|
|
||||||
if (porting::getInputDialogState() == -1)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
m_jni_field_name.clear();
|
|
||||||
|
|
||||||
gui::IGUIElement *e = getElementFromId(ID_confirmPassword);
|
|
||||||
|
|
||||||
if (!e || e->getType() != irr::gui::EGUIET_EDIT_BOX)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
std::string text = porting::getInputDialogValue();
|
|
||||||
e->setText(utf8_to_wide(text).c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,65 +0,0 @@
|
||||||
/*
|
|
||||||
Minetest
|
|
||||||
Copyright (C) 2018 srifqi, Muhammad Rifqi Priyo Susanto
|
|
||||||
<muhammadrifqipriyosusanto@gmail.com>
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2.1 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Lesser General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License along
|
|
||||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "irrlichttypes_extrabloated.h"
|
|
||||||
#include "modalMenu.h"
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class Client;
|
|
||||||
class ISimpleTextureSource;
|
|
||||||
|
|
||||||
class GUIConfirmRegistration : public GUIModalMenu
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GUIConfirmRegistration(gui::IGUIEnvironment *env, gui::IGUIElement *parent,
|
|
||||||
s32 id, IMenuManager *menumgr, Client *client,
|
|
||||||
const std::string &playername, const std::string &password,
|
|
||||||
bool *aborted, ISimpleTextureSource *tsrc);
|
|
||||||
/*
|
|
||||||
Remove and re-add (or reposition) stuff
|
|
||||||
*/
|
|
||||||
void regenerateGui(v2u32 screensize);
|
|
||||||
|
|
||||||
void drawMenu();
|
|
||||||
|
|
||||||
void closeMenu(bool goNext);
|
|
||||||
|
|
||||||
void acceptInput();
|
|
||||||
|
|
||||||
bool processInput();
|
|
||||||
|
|
||||||
bool OnEvent(const SEvent &event);
|
|
||||||
#ifdef __ANDROID__
|
|
||||||
bool getAndroidUIInput();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::wstring getLabelByID(s32 id) { return L""; }
|
|
||||||
std::string getNameByID(s32 id) { return "password"; }
|
|
||||||
|
|
||||||
Client *m_client = nullptr;
|
|
||||||
const std::string &m_playername;
|
|
||||||
const std::string &m_password;
|
|
||||||
bool *m_aborted = nullptr;
|
|
||||||
std::wstring m_pass_confirm = L"";
|
|
||||||
ISimpleTextureSource *m_tsrc;
|
|
||||||
};
|
|
|
@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "irrlichttypes_extrabloated.h"
|
#include "irrlichttypes_extrabloated.h"
|
||||||
|
#include "gameparams.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
|
@ -50,5 +51,7 @@ struct MainMenuData {
|
||||||
// Data to be passed to the script
|
// Data to be passed to the script
|
||||||
MainMenuDataForScript script_data;
|
MainMenuDataForScript script_data;
|
||||||
|
|
||||||
|
ELoginRegister allow_login_or_register = ELoginRegister::Any;
|
||||||
|
|
||||||
MainMenuData() = default;
|
MainMenuData() = default;
|
||||||
};
|
};
|
||||||
|
|
|
@ -238,7 +238,8 @@ u32 Mapgen::getBlockSeed(v3s16 p, s32 seed)
|
||||||
|
|
||||||
u32 Mapgen::getBlockSeed2(v3s16 p, s32 seed)
|
u32 Mapgen::getBlockSeed2(v3s16 p, s32 seed)
|
||||||
{
|
{
|
||||||
u32 n = 1619 * p.X + 31337 * p.Y + 52591 * p.Z + 1013 * seed;
|
// Multiply by unsigned number to avoid signed overflow (UB)
|
||||||
|
u32 n = 1619U * p.X + 31337U * p.Y + 52591U * p.Z + 1013U * seed;
|
||||||
n = (n >> 13) ^ n;
|
n = (n >> 13) ^ n;
|
||||||
return (n * (n * n * 60493 + 19990303) + 1376312589);
|
return (n * (n * n * 60493 + 19990303) + 1376312589);
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,11 +103,20 @@ void Client::handleCommand_Hello(NetworkPacket* pkt)
|
||||||
|
|
||||||
// Authenticate using that method, or abort if there wasn't any method found
|
// Authenticate using that method, or abort if there wasn't any method found
|
||||||
if (chosen_auth_mechanism != AUTH_MECHANISM_NONE) {
|
if (chosen_auth_mechanism != AUTH_MECHANISM_NONE) {
|
||||||
if (chosen_auth_mechanism == AUTH_MECHANISM_FIRST_SRP &&
|
bool is_register = chosen_auth_mechanism == AUTH_MECHANISM_FIRST_SRP;
|
||||||
!m_simple_singleplayer_mode &&
|
ELoginRegister mode = is_register ? ELoginRegister::Register : ELoginRegister::Login;
|
||||||
!getServerAddress().isLocalhost() &&
|
if (m_allow_login_or_register != ELoginRegister::Any &&
|
||||||
g_settings->getBool("enable_register_confirmation")) {
|
m_allow_login_or_register != mode) {
|
||||||
promptConfirmRegistration(chosen_auth_mechanism);
|
m_chosen_auth_mech = AUTH_MECHANISM_NONE;
|
||||||
|
m_access_denied = true;
|
||||||
|
if (m_allow_login_or_register == ELoginRegister::Login) {
|
||||||
|
m_access_denied_reason =
|
||||||
|
gettext("Name is not registered. To create an account on this server, click 'Register'");
|
||||||
|
} else {
|
||||||
|
m_access_denied_reason =
|
||||||
|
gettext("Name is taken. Please choose another name");
|
||||||
|
}
|
||||||
|
m_con->Disconnect();
|
||||||
} else {
|
} else {
|
||||||
startAuth(chosen_auth_mechanism);
|
startAuth(chosen_auth_mechanism);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,8 @@
|
||||||
#define NOISE_MAGIC_X 1619
|
#define NOISE_MAGIC_X 1619
|
||||||
#define NOISE_MAGIC_Y 31337
|
#define NOISE_MAGIC_Y 31337
|
||||||
#define NOISE_MAGIC_Z 52591
|
#define NOISE_MAGIC_Z 52591
|
||||||
#define NOISE_MAGIC_SEED 1013
|
// Unsigned magic seed prevents undefined behavior.
|
||||||
|
#define NOISE_MAGIC_SEED 1013U
|
||||||
|
|
||||||
typedef float (*Interp2dFxn)(
|
typedef float (*Interp2dFxn)(
|
||||||
float v00, float v10, float v01, float v11,
|
float v00, float v10, float v01, float v11,
|
||||||
|
|
|
@ -213,6 +213,18 @@ void openURIAndroid(const std::string &url)
|
||||||
jnienv->CallVoidMethod(app_global->activity->clazz, url_open, jurl);
|
jnienv->CallVoidMethod(app_global->activity->clazz, url_open, jurl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void shareFileAndroid(const std::string &path)
|
||||||
|
{
|
||||||
|
jmethodID url_open = jnienv->GetMethodID(nativeActivity, "shareFile",
|
||||||
|
"(Ljava/lang/String;)V");
|
||||||
|
|
||||||
|
FATAL_ERROR_IF(url_open == nullptr,
|
||||||
|
"porting::shareFileAndroid unable to find java openURI method");
|
||||||
|
|
||||||
|
jstring jurl = jnienv->NewStringUTF(path.c_str());
|
||||||
|
jnienv->CallVoidMethod(app_global->activity->clazz, url_open, jurl);
|
||||||
|
}
|
||||||
|
|
||||||
int getInputDialogState()
|
int getInputDialogState()
|
||||||
{
|
{
|
||||||
jmethodID dialogstate = jnienv->GetMethodID(nativeActivity,
|
jmethodID dialogstate = jnienv->GetMethodID(nativeActivity,
|
||||||
|
|
|
@ -60,6 +60,13 @@ void showInputDialog(const std::string &acceptButton,
|
||||||
|
|
||||||
void openURIAndroid(const std::string &url);
|
void openURIAndroid(const std::string &url);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a share intent to the file at path
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
*/
|
||||||
|
void shareFileAndroid(const std::string &path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WORKAROUND for not working callbacks from java -> c++
|
* WORKAROUND for not working callbacks from java -> c++
|
||||||
* get current state of input dialog
|
* get current state of input dialog
|
||||||
|
|
|
@ -348,7 +348,7 @@ int LuaItemStack::l_get_tool_capabilities(lua_State *L)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add_wear(self, amount) -> true/false
|
// add_wear(self, amount) -> true/false
|
||||||
// The range for "amount" is [0,65535]. Wear is only added if the item
|
// The range for "amount" is [0,65536]. Wear is only added if the item
|
||||||
// is a tool. Adding wear might destroy the item.
|
// is a tool. Adding wear might destroy the item.
|
||||||
// Returns true if the item is (or was) a tool.
|
// Returns true if the item is (or was) a tool.
|
||||||
int LuaItemStack::l_add_wear(lua_State *L)
|
int LuaItemStack::l_add_wear(lua_State *L)
|
||||||
|
@ -362,6 +362,25 @@ int LuaItemStack::l_add_wear(lua_State *L)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add_wear_by_uses(self, max_uses) -> true/false
|
||||||
|
// The range for "max_uses" is [0,65536].
|
||||||
|
// Adds wear to the item in such a way that, if
|
||||||
|
// only this function is called to add wear, the item
|
||||||
|
// will be destroyed exactly after `max_uses` times of calling it.
|
||||||
|
// No-op if `max_uses` is 0 or item is not a tool.
|
||||||
|
// Returns true if the item is (or was) a tool.
|
||||||
|
int LuaItemStack::l_add_wear_by_uses(lua_State *L)
|
||||||
|
{
|
||||||
|
NO_MAP_LOCK_REQUIRED;
|
||||||
|
LuaItemStack *o = checkobject(L, 1);
|
||||||
|
ItemStack &item = o->m_stack;
|
||||||
|
u32 max_uses = readParam<int>(L, 2);
|
||||||
|
u32 add_wear = calculateResultWear(max_uses, item.wear);
|
||||||
|
bool result = item.addWear(add_wear, getGameDef(L)->idef());
|
||||||
|
lua_pushboolean(L, result);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// add_item(self, itemstack or itemstring or table or nil) -> itemstack
|
// add_item(self, itemstack or itemstring or table or nil) -> itemstack
|
||||||
// Returns leftover item stack
|
// Returns leftover item stack
|
||||||
int LuaItemStack::l_add_item(lua_State *L)
|
int LuaItemStack::l_add_item(lua_State *L)
|
||||||
|
@ -537,6 +556,7 @@ const luaL_Reg LuaItemStack::methods[] = {
|
||||||
luamethod(LuaItemStack, get_definition),
|
luamethod(LuaItemStack, get_definition),
|
||||||
luamethod(LuaItemStack, get_tool_capabilities),
|
luamethod(LuaItemStack, get_tool_capabilities),
|
||||||
luamethod(LuaItemStack, add_wear),
|
luamethod(LuaItemStack, add_wear),
|
||||||
|
luamethod(LuaItemStack, add_wear_by_uses),
|
||||||
luamethod(LuaItemStack, add_item),
|
luamethod(LuaItemStack, add_item),
|
||||||
luamethod(LuaItemStack, item_fits),
|
luamethod(LuaItemStack, item_fits),
|
||||||
luamethod(LuaItemStack, take_item),
|
luamethod(LuaItemStack, take_item),
|
||||||
|
|
|
@ -108,11 +108,20 @@ private:
|
||||||
static int l_get_tool_capabilities(lua_State *L);
|
static int l_get_tool_capabilities(lua_State *L);
|
||||||
|
|
||||||
// add_wear(self, amount) -> true/false
|
// add_wear(self, amount) -> true/false
|
||||||
// The range for "amount" is [0,65535]. Wear is only added if the item
|
// The range for "amount" is [0,65536]. Wear is only added if the item
|
||||||
// is a tool. Adding wear might destroy the item.
|
// is a tool. Adding wear might destroy the item.
|
||||||
// Returns true if the item is (or was) a tool.
|
// Returns true if the item is (or was) a tool.
|
||||||
static int l_add_wear(lua_State *L);
|
static int l_add_wear(lua_State *L);
|
||||||
|
|
||||||
|
// add_wear_by_uses(self, max_uses) -> true/false
|
||||||
|
// The range for "max_uses" is [0,65536].
|
||||||
|
// Adds wear to the item in such a way that, if
|
||||||
|
// only this function is called to add wear, the item
|
||||||
|
// will be destroyed exactly after `max_uses` times of calling it.
|
||||||
|
// No-op if `max_uses` is 0 or item is not a tool.
|
||||||
|
// Returns true if the item is (or was) a tool.
|
||||||
|
static int l_add_wear_by_uses(lua_State *L);
|
||||||
|
|
||||||
// add_item(self, itemstack or itemstring or table or nil) -> itemstack
|
// add_item(self, itemstack or itemstring or table or nil) -> itemstack
|
||||||
// Returns leftover item stack
|
// Returns leftover item stack
|
||||||
static int l_add_item(lua_State *L);
|
static int l_add_item(lua_State *L);
|
||||||
|
|
|
@ -139,6 +139,14 @@ int ModApiMainMenu::l_start(lua_State *L)
|
||||||
data->password = getTextData(L,"password");
|
data->password = getTextData(L,"password");
|
||||||
data->address = getTextData(L,"address");
|
data->address = getTextData(L,"address");
|
||||||
data->port = getTextData(L,"port");
|
data->port = getTextData(L,"port");
|
||||||
|
|
||||||
|
const auto val = getTextData(L, "allow_login_or_register");
|
||||||
|
if (val == "login")
|
||||||
|
data->allow_login_or_register = ELoginRegister::Login;
|
||||||
|
else if (val == "register")
|
||||||
|
data->allow_login_or_register = ELoginRegister::Register;
|
||||||
|
else
|
||||||
|
data->allow_login_or_register = ELoginRegister::Any;
|
||||||
}
|
}
|
||||||
data->serverdescription = getTextData(L,"serverdescription");
|
data->serverdescription = getTextData(L,"serverdescription");
|
||||||
data->servername = getTextData(L,"servername");
|
data->servername = getTextData(L,"servername");
|
||||||
|
@ -872,6 +880,19 @@ int ModApiMainMenu::l_open_dir(lua_State *L)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
int ModApiMainMenu::l_share_file(lua_State *L)
|
||||||
|
{
|
||||||
|
#ifdef __ANDROID__
|
||||||
|
std::string path = luaL_checkstring(L, 1);
|
||||||
|
porting::shareFileAndroid(path);
|
||||||
|
lua_pushboolean(L, true);
|
||||||
|
#else
|
||||||
|
lua_pushboolean(L, false);
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
int ModApiMainMenu::l_do_async_callback(lua_State *L)
|
int ModApiMainMenu::l_do_async_callback(lua_State *L)
|
||||||
{
|
{
|
||||||
|
@ -937,6 +958,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top)
|
||||||
API_FCT(get_max_supp_proto);
|
API_FCT(get_max_supp_proto);
|
||||||
API_FCT(open_url);
|
API_FCT(open_url);
|
||||||
API_FCT(open_dir);
|
API_FCT(open_dir);
|
||||||
|
API_FCT(share_file);
|
||||||
API_FCT(do_async_callback);
|
API_FCT(do_async_callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,6 +152,8 @@ private:
|
||||||
|
|
||||||
static int l_open_dir(lua_State *L);
|
static int l_open_dir(lua_State *L);
|
||||||
|
|
||||||
|
static int l_share_file(lua_State *L);
|
||||||
|
|
||||||
|
|
||||||
// async
|
// async
|
||||||
static int l_do_async_callback(lua_State *L);
|
static int l_do_async_callback(lua_State *L);
|
||||||
|
|
|
@ -159,6 +159,17 @@ int ModApiUtil::l_write_json(lua_State *L)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get_tool_wear_after_use(uses[, initial_wear])
|
||||||
|
int ModApiUtil::l_get_tool_wear_after_use(lua_State *L)
|
||||||
|
{
|
||||||
|
NO_MAP_LOCK_REQUIRED;
|
||||||
|
u32 uses = readParam<int>(L, 1);
|
||||||
|
u16 initial_wear = readParam<int>(L, 2, 0);
|
||||||
|
u16 wear = calculateResultWear(uses, initial_wear);
|
||||||
|
lua_pushnumber(L, wear);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// get_dig_params(groups, tool_capabilities[, wear])
|
// get_dig_params(groups, tool_capabilities[, wear])
|
||||||
int ModApiUtil::l_get_dig_params(lua_State *L)
|
int ModApiUtil::l_get_dig_params(lua_State *L)
|
||||||
{
|
{
|
||||||
|
@ -586,6 +597,7 @@ void ModApiUtil::Initialize(lua_State *L, int top)
|
||||||
API_FCT(parse_json);
|
API_FCT(parse_json);
|
||||||
API_FCT(write_json);
|
API_FCT(write_json);
|
||||||
|
|
||||||
|
API_FCT(get_tool_wear_after_use);
|
||||||
API_FCT(get_dig_params);
|
API_FCT(get_dig_params);
|
||||||
API_FCT(get_hit_params);
|
API_FCT(get_hit_params);
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,9 @@ private:
|
||||||
// write_json(data[, styled])
|
// write_json(data[, styled])
|
||||||
static int l_write_json(lua_State *L);
|
static int l_write_json(lua_State *L);
|
||||||
|
|
||||||
|
// get_tool_wear_after_use(uses[, initial_wear])
|
||||||
|
static int l_get_tool_wear_after_use(lua_State *L);
|
||||||
|
|
||||||
// get_dig_params(groups, tool_capabilities[, wear])
|
// get_dig_params(groups, tool_capabilities[, wear])
|
||||||
static int l_get_dig_params(lua_State *L);
|
static int l_get_dig_params(lua_State *L);
|
||||||
|
|
||||||
|
|
|
@ -258,23 +258,23 @@ void LBMManager::applyLBMs(ServerEnvironment *env, MapBlock *block, u32 stamp)
|
||||||
v3s16 pos;
|
v3s16 pos;
|
||||||
MapNode n;
|
MapNode n;
|
||||||
content_t c;
|
content_t c;
|
||||||
lbm_lookup_map::const_iterator it = getLBMsIntroducedAfter(stamp);
|
bool pos_valid; // dummy, we know it's valid
|
||||||
|
auto it = getLBMsIntroducedAfter(stamp);
|
||||||
for (; it != m_lbm_lookup.end(); ++it) {
|
for (; it != m_lbm_lookup.end(); ++it) {
|
||||||
// Cache previous version to speedup lookup which has a very high performance
|
// Cache previous version to speedup lookup which has a very high performance
|
||||||
// penalty on each call
|
// penalty on each call
|
||||||
content_t previous_c{};
|
content_t previous_c = CONTENT_IGNORE;
|
||||||
std::vector<LoadingBlockModifierDef *> *lbm_list = nullptr;
|
const std::vector<LoadingBlockModifierDef *> *lbm_list = nullptr;
|
||||||
|
|
||||||
for (pos.X = 0; pos.X < MAP_BLOCKSIZE; pos.X++)
|
for (pos.X = 0; pos.X < MAP_BLOCKSIZE; pos.X++)
|
||||||
for (pos.Y = 0; pos.Y < MAP_BLOCKSIZE; pos.Y++)
|
for (pos.Y = 0; pos.Y < MAP_BLOCKSIZE; pos.Y++)
|
||||||
for (pos.Z = 0; pos.Z < MAP_BLOCKSIZE; pos.Z++) {
|
for (pos.Z = 0; pos.Z < MAP_BLOCKSIZE; pos.Z++) {
|
||||||
n = block->getNodeNoEx(pos);
|
n = block->getNodeNoCheck(pos, &pos_valid);
|
||||||
c = n.getContent();
|
c = n.getContent();
|
||||||
|
|
||||||
// If content_t are not matching perform an LBM lookup
|
// If content_t are not matching perform an LBM lookup
|
||||||
if (previous_c != c) {
|
if (previous_c != c) {
|
||||||
lbm_list = (std::vector<LoadingBlockModifierDef *> *)
|
lbm_list = it->second.lookup(c);
|
||||||
it->second.lookup(c);
|
|
||||||
previous_c = c;
|
previous_c = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -183,7 +183,7 @@ void ToolCapabilities::deserializeJson(std::istream &is)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 calculateResultWear(const u32 uses, const u16 initial_wear)
|
u32 calculateResultWear(const u32 uses, const u16 initial_wear)
|
||||||
{
|
{
|
||||||
if (uses == 0) {
|
if (uses == 0) {
|
||||||
// Trivial case: Infinite uses
|
// Trivial case: Infinite uses
|
||||||
|
|
|
@ -142,4 +142,5 @@ PunchDamageResult getPunchDamage(
|
||||||
u16 initial_wear = 0
|
u16 initial_wear = 0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
u32 calculateResultWear(const u32 uses, const u16 initial_wear);
|
||||||
f32 getToolRange(const ItemDefinition &def_selected, const ItemDefinition &def_hand);
|
f32 getToolRange(const ItemDefinition &def_selected, const ItemDefinition &def_hand);
|
||||||
|
|
|
@ -30,8 +30,14 @@ public:
|
||||||
|
|
||||||
void runTests(IGameDef *gamedef);
|
void runTests(IGameDef *gamedef);
|
||||||
|
|
||||||
|
void testNoise2dAtOriginWithZeroSeed();
|
||||||
|
void testNoise2dWithMaxSeed();
|
||||||
|
void testNoise2dWithFunPrimes();
|
||||||
void testNoise2dPoint();
|
void testNoise2dPoint();
|
||||||
void testNoise2dBulk();
|
void testNoise2dBulk();
|
||||||
|
void testNoise3dAtOriginWithZeroSeed();
|
||||||
|
void testNoise3dWithMaxSeed();
|
||||||
|
void testNoise3dWithFunPrimes();
|
||||||
void testNoise3dPoint();
|
void testNoise3dPoint();
|
||||||
void testNoise3dBulk();
|
void testNoise3dBulk();
|
||||||
void testNoiseInvalidParams();
|
void testNoiseInvalidParams();
|
||||||
|
@ -44,8 +50,14 @@ static TestNoise g_test_instance;
|
||||||
|
|
||||||
void TestNoise::runTests(IGameDef *gamedef)
|
void TestNoise::runTests(IGameDef *gamedef)
|
||||||
{
|
{
|
||||||
|
TEST(testNoise2dAtOriginWithZeroSeed);
|
||||||
|
TEST(testNoise2dWithMaxSeed);
|
||||||
|
TEST(testNoise2dWithFunPrimes);
|
||||||
TEST(testNoise2dPoint);
|
TEST(testNoise2dPoint);
|
||||||
TEST(testNoise2dBulk);
|
TEST(testNoise2dBulk);
|
||||||
|
TEST(testNoise3dAtOriginWithZeroSeed);
|
||||||
|
TEST(testNoise3dWithMaxSeed);
|
||||||
|
TEST(testNoise3dWithFunPrimes);
|
||||||
TEST(testNoise3dPoint);
|
TEST(testNoise3dPoint);
|
||||||
TEST(testNoise3dBulk);
|
TEST(testNoise3dBulk);
|
||||||
TEST(testNoiseInvalidParams);
|
TEST(testNoiseInvalidParams);
|
||||||
|
@ -53,6 +65,27 @@ void TestNoise::runTests(IGameDef *gamedef)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void TestNoise::testNoise2dAtOriginWithZeroSeed()
|
||||||
|
{
|
||||||
|
float actual{ noise2d(0, 0, 0) };
|
||||||
|
constexpr float expected{ -0.281791f };
|
||||||
|
UASSERT(std::fabs(actual - expected) <= 0.00001);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestNoise::testNoise2dWithMaxSeed()
|
||||||
|
{
|
||||||
|
float actual{ noise2d(4096, 4096, 2147483647) };
|
||||||
|
constexpr float expected{ 0.950606f };
|
||||||
|
UASSERT(std::fabs(actual - expected) <= 0.00001);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestNoise::testNoise2dWithFunPrimes()
|
||||||
|
{
|
||||||
|
float actual{ noise2d(-3947, -2333, 7027) };
|
||||||
|
constexpr float expected{ -0.294907f };
|
||||||
|
UASSERT(std::fabs(actual - expected) <= 0.00001);
|
||||||
|
}
|
||||||
|
|
||||||
void TestNoise::testNoise2dPoint()
|
void TestNoise::testNoise2dPoint()
|
||||||
{
|
{
|
||||||
NoiseParams np_normal(20, 40, v3f(50, 50, 50), 9, 5, 0.6, 2.0);
|
NoiseParams np_normal(20, 40, v3f(50, 50, 50), 9, 5, 0.6, 2.0);
|
||||||
|
@ -79,6 +112,27 @@ void TestNoise::testNoise2dBulk()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestNoise::testNoise3dAtOriginWithZeroSeed()
|
||||||
|
{
|
||||||
|
float actual{ noise2d(0, 0, 0) };
|
||||||
|
constexpr float expected{ -0.281791f };
|
||||||
|
UASSERT(std::fabs(actual - expected) <= 0.00001);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestNoise::testNoise3dWithMaxSeed()
|
||||||
|
{
|
||||||
|
float actual{ noise3d(4096, 4096, 4096, 2147483647) };
|
||||||
|
constexpr float expected{ -0.775243f };
|
||||||
|
UASSERT(std::fabs(actual - expected) <= 0.00001);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestNoise::testNoise3dWithFunPrimes()
|
||||||
|
{
|
||||||
|
float actual{ noise2d(3903, -1723, 7411) };
|
||||||
|
constexpr float expected{ 0.989124f };
|
||||||
|
UASSERT(std::fabs(actual - expected) <= 0.00001);
|
||||||
|
}
|
||||||
|
|
||||||
void TestNoise::testNoise3dPoint()
|
void TestNoise::testNoise3dPoint()
|
||||||
{
|
{
|
||||||
NoiseParams np_normal(20, 40, v3f(50, 50, 50), 9, 5, 0.6, 2.0);
|
NoiseParams np_normal(20, 40, v3f(50, 50, 50), 9, 5, 0.6, 2.0);
|
||||||
|
|
|
@ -39,16 +39,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __NetBSD__
|
|
||||||
#include <sys/param.h>
|
|
||||||
#if __NetBSD_Version__ <= 999001500
|
|
||||||
#define BSD_ICONV_USED
|
|
||||||
#endif
|
|
||||||
#elif defined(_ICONV_H_) && (defined(__FreeBSD__) || defined(__OpenBSD__) || \
|
|
||||||
defined(__DragonFly__))
|
|
||||||
#define BSD_ICONV_USED
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
|
||||||
static bool convert(const char *to, const char *from, char *outbuf,
|
static bool convert(const char *to, const char *from, char *outbuf,
|
||||||
|
@ -56,11 +46,7 @@ static bool convert(const char *to, const char *from, char *outbuf,
|
||||||
{
|
{
|
||||||
iconv_t cd = iconv_open(to, from);
|
iconv_t cd = iconv_open(to, from);
|
||||||
|
|
||||||
#ifdef BSD_ICONV_USED
|
|
||||||
const char *inbuf_ptr = inbuf;
|
|
||||||
#else
|
|
||||||
char *inbuf_ptr = inbuf;
|
char *inbuf_ptr = inbuf;
|
||||||
#endif
|
|
||||||
char *outbuf_ptr = outbuf;
|
char *outbuf_ptr = outbuf;
|
||||||
|
|
||||||
size_t *inbuf_left_ptr = &inbuf_size;
|
size_t *inbuf_left_ptr = &inbuf_size;
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 748 B |
Loading…
Reference in New Issue