master
Elias Fleckenstein 2020-06-23 17:43:47 +02:00
parent 68f9263a24
commit a87805a944
116 changed files with 2908 additions and 19736 deletions

View File

@ -37,7 +37,7 @@ core.register_on_sending_chat_message(function(message)
return true
end)
core.register_chatcommand("list_players", {
core.register_chatcommand("players", {
description = core.gettext("List online players"),
func = function(param)
local player_names = core.get_player_names()

160
builtin/client/cheats.lua Normal file
View File

@ -0,0 +1,160 @@
core.register_chatcommand("set", {
params = "([-n] <name> <value>) | <name>",
description = "Set or read client configuration setting",
privs = {server=true},
func = function(param)
local arg, setname, setvalue = string.match(param, "(-[n]) ([^ ]+) (.+)")
if arg and arg == "-n" and setname and setvalue then
core.settings:set(setname, setvalue)
return true, setname .. " = " .. setvalue
end
setname, setvalue = string.match(param, "([^ ]+) (.+)")
if setname and setvalue then
if not core.settings:get(setname) then
return false, "Failed. Use '.set -n <name> <value>' to create a new setting."
end
core.settings:set(setname, setvalue)
return true, setname .. " = " .. setvalue
end
setname = string.match(param, "([^ ]+)")
if setname then
setvalue = core.settings:get(setname)
if not setvalue then
setvalue = "<not set>"
end
return true, setname .. " = " .. setvalue
end
return false, "Invalid parameters (see .help set)."
end,
})
function core.parse_pos(param)
local p = {}
p.x, p.y, p.z = string.match(param, "^([~|%d.-]+)[, ] *([~|%d.-]+)[, ] *([~|%d.-]+)$")
for k, v in pairs(p) do
if p[k] == "~" then
p[k] = core.localplayer:get_pos()[k]
else
p[k] = tonumber(v)
end
end
if p.x and p.y and p.z then
local lm = 31000
if p.x < -lm or p.x > lm or p.y < -lm or p.y > lm or p.z < -lm or p.z > lm then
return false, "Position out of Map bounds."
end
return true, p
end
return false, "Invalid position (" .. param .. ")"
end
core.register_chatcommand("teleport", {
params = "<X>,<Y>,<Z>",
description = "Teleport to position",
func = function(param)
local success, pos = core.parse_pos(param)
if success then
core.localplayer:set_pos(pos)
return true, "Teleporting to " .. core.pos_to_string(pos)
end
return false, pos
end,
})
core.register_chatcommand("place", {
params = "<X>,<Y>,<Z>",
description = "Place wielded item",
func = function(param)
local success, pos = core.parse_pos(param)
if success then
core.place_node(pos)
return true, "Node placed at " .. core.pos_to_string(pos)
end
return false, pos
end,
})
core.register_chatcommand("dig", {
params = "<X>,<Y>,<Z>",
description = "Dig node",
func = function(param)
local success, pos = core.parse_pos(param)
if success then
core.dig_node(pos)
return true, "Node at " .. core.pos_to_string(pos) .. " dug"
end
return false, pos
end,
})
core.register_chatcommand("kill", {
description = "Kill yourself",
func = function(param)
core.send_damage(core.localplayer:get_hp())
end,
})
core.register_chatcommand("scan", {
description = "Scan for one or multible nodes in a radius around you",
param = "<radius> node1[,node2...]",
func = function(param)
local radius = tonumber(param:split(" ")[1])
local nodes = param:split(" ")[2]:split(",")
local pos = core.localplayer:get_pos()
local fpos = core.find_node_near(pos, radius, nodes, true)
if fpos then
return true, "Found " .. table.concat(nodes, " or ") .. " at " .. core.pos_to_string(fpos)
end
return false, "None of " .. table.concat(nodes, " or ") .. " found in a radius of " .. tostring(radius)
end,
})
core.register_chatcommand("digaround", {
description = "Scan for one or multible nodes in a radius around you",
param = "<radius> node1[,node2...]",
func = function(param)
local radius = tonumber(param:split(" ")[1])
local nodes = param:split(" ")[2]:split(",")
local function loop()
local fpos = core.find_node_near(core.localplayer:get_pos(), radius, nodes, true)
if fpos then core.dig_node(fpos) end
core.after(0, loop)
end
loop()
end,
})
local keep_digging = false
core.register_chatcommand("keepdigging", {
params = "<X>,<Y>,<Z>",
description = "Dig node again and again",
func = function(param)
local success, pos = core.parse_pos(param)
if success then
keep_digging = true
local function loop()
core.dig_node(pos)
if keep_digging then
core.after(0.1, loop)
end
end
loop()
end
end,
})
core.register_chatcommand("stopdigging", {
description = "Stop diggin",
func = function()
keep_digging = false
end,
})
core.register_on_punchnode(function(pos)
--core.dig_node(pos)
end)

View File

@ -1,29 +1,33 @@
-- CSM death formspec. Only used when clientside modding is enabled, otherwise
-- handled by the engine.
local dead = false
core.register_on_death(function()
if not dead then
core.display_chat_message("You died.")
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)
dead = true
end
core.display_chat_message("You died.")
local formspec = "size[11,5.5]bgcolor[#320000b4;true]" ..
"label[4.85,1.35;" .. fgettext("You died") ..
"]button_exit[2,3;3,0.5;btn_respawn;".. fgettext("Respawn") ..
"]button_exit[6,3;3,0.5;btn_ghost_mode;".. fgettext("Ghost Mode") .."]"
core.show_formspec("bultin:death", formspec)
end)
core.register_on_formspec_input(function(formname, fields)
if formname == "bultin:death" and fields.btn_respawn then
core.send_respawn()
dead = false
if formname == "bultin:death" then
if fields.btn_ghost_mode then
core.display_chat_message("You are in ghost mode. Use .respawn to Respawn")
else
core.send_respawn()
end
end
end)
core.register_chatcommand("respawn", {
description = core.gettext("Respawn when in ghost mode"),
func = function()
core.send_respawn()
dead = false
if core.localplayer:get_hp() == 0 then
core.send_respawn()
core.display_chat_message("Respawned.")
else
core.display_chat_message("You are not in ghost mode.")
end
end
})

View File

@ -8,5 +8,6 @@ dofile(commonpath .. "after.lua")
dofile(commonpath .. "chatcommands.lua")
dofile(commonpath .. "vector.lua")
dofile(clientpath .. "death_formspec.lua")
dofile(clientpath .. "spoof.lua")
dofile(clientpath .. "chatcommands.lua")
dofile(clientpath .. "cheats.lua")

View File

@ -40,6 +40,26 @@ function core.run_callbacks(callbacks, mode, ...)
return ret
end
function core.override_item(name, redefinition)
if redefinition.name ~= nil then
error("Attempt to redefine name of "..name.." to "..dump(redefinition.name), 2)
end
if redefinition.type ~= nil then
error("Attempt to redefine type of "..name.." to "..dump(redefinition.type), 2)
end
local itemdef = core.get_item_def(name)
if not itemdef then
error("Attempt to override non-existent item "..name, 2)
end
local nodedef = core.get_node_def(name)
table.combine(itemdef, nodedef)
for k, v in pairs(redefinition) do
rawset(itemdef, k, v)
end
core.register_item_raw(itemdef)
end
--
-- Callback registration
--

View File

@ -1,4 +0,0 @@
local file = io.open("spoof.txt", "a")
minetest.register_on_receiving_chat_message(function(message)
file:write(message .. "\n")
end)

View File

@ -519,6 +519,16 @@ function table.shuffle(t, from, to, random)
end
end
function table.combine(t, other)
other = other or {}
for k, v in pairs(other) do
if type(v) == "table" and type(t[k]) == "table" then
table.combine(t[k], v)
else
t[k] = v
end
end
end
--------------------------------------------------------------------------------
-- mainmenu only functions

View File

@ -2146,8 +2146,16 @@ xray_texture (Texture to make transparent when xray is enabled) string default_s
priv_bypass (Make the Client think it has all privs) bool false
instant_dig (Dig Nodes on punch) bool false
fastdig (Fast Dig) bool false
prevent_natural_damage (Prevent Natural Damage e.g Fall Damage) bool false
freecam (Move around freely) bool false
killaura (Enable Killaura) bool false
no_hurt_cam (No Hurt Cam) bool false
increase_tool_range (Increase Tool Range) bool false
killaura_fast (Enable fast Killaura) bool false

Binary file not shown.

View File

@ -0,0 +1,29 @@
Minetest Game mod: player_api
=============================
See license.txt for license information.
Provides an API to allow multiple mods to set player models and textures.
Also sets the default model, texture, and player flags.
This mod is only for content related to the Player API and the player object.
Authors of source code
----------------------
Originally by celeron55, Perttu Ahola <celeron55@gmail.com> (LGPLv2.1+)
Various Minetest developers and contributors (LGPLv2.1+)
Authors of media (textures, models and sounds)
----------------------------------------------
stujones11 (CC BY-SA 3.0):
character.b3d
character.blend -- Both derived from a model by MirceaKitsune (CC BY-SA 3.0)
An0n3m0us (CC BY-SA 3.0):
character.b3d
character.blend -- Player animation improvement
Jordach (CC BY-SA 3.0):
character.png
celeron55, Perttu Ahola <celeron55@gmail.com> (CC BY-SA 3.0):
player.png
player_back.png

View File

@ -0,0 +1,144 @@
-- Minetest 0.4 mod: player
-- See README.txt for licensing and other information.
player_api = {}
-- Player animation blending
-- Note: This is currently broken due to a bug in Irrlicht, leave at 0
local animation_blend = 0
player_api.registered_models = { }
-- Local for speed.
local models = player_api.registered_models
function player_api.register_model(name, def)
models[name] = def
end
-- Player stats and animations
local player_model = {}
local player_textures = {}
local player_anim = {}
local player_sneak = {}
player_api.player_attached = {}
function player_api.get_animation(player)
local name = player:get_player_name()
return {
model = player_model[name],
textures = player_textures[name],
animation = player_anim[name],
}
end
-- Called when a player's appearance needs to be updated
function player_api.set_model(player, model_name)
local name = player:get_player_name()
local model = models[model_name]
if model then
if player_model[name] == model_name then
return
end
player:set_properties({
mesh = model_name,
textures = player_textures[name] or model.textures,
visual = "mesh",
visual_size = model.visual_size or {x = 1, y = 1},
collisionbox = model.collisionbox or {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3},
stepheight = model.stepheight or 0.6,
eye_height = model.eye_height or 1.47,
})
player_api.set_animation(player, "stand")
else
player:set_properties({
textures = {"player.png", "player_back.png"},
visual = "upright_sprite",
visual_size = {x = 1, y = 2},
collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.75, 0.3},
stepheight = 0.6,
eye_height = 1.625,
})
end
player_model[name] = model_name
end
function player_api.set_textures(player, textures)
local name = player:get_player_name()
local model = models[player_model[name]]
local model_textures = model and model.textures or nil
player_textures[name] = textures or model_textures
player:set_properties({textures = textures or model_textures,})
end
function player_api.set_animation(player, anim_name, speed)
local name = player:get_player_name()
if player_anim[name] == anim_name then
return
end
local model = player_model[name] and models[player_model[name]]
if not (model and model.animations[anim_name]) then
return
end
local anim = model.animations[anim_name]
player_anim[name] = anim_name
player:set_animation(anim, speed or model.animation_speed, animation_blend)
end
minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
player_model[name] = nil
player_anim[name] = nil
player_textures[name] = nil
end)
-- Localize for better performance.
local player_set_animation = player_api.set_animation
local player_attached = player_api.player_attached
-- Prevent knockback for attached players
local old_calculate_knockback = minetest.calculate_knockback
function minetest.calculate_knockback(player, ...)
if player_attached[player:get_player_name()] then
return 0
end
return old_calculate_knockback(player, ...)
end
-- Check each player and apply animations
minetest.register_globalstep(function()
for _, player in pairs(minetest.get_connected_players()) do
local name = player:get_player_name()
local model_name = player_model[name]
local model = model_name and models[model_name]
if model and not player_attached[name] then
local controls = player:get_player_control()
local animation_speed_mod = model.animation_speed or 30
-- Determine if the player is sneaking, and reduce animation speed if so
if controls.sneak then
animation_speed_mod = animation_speed_mod / 2
end
-- Apply animations based on what the player is doing
if player:get_hp() == 0 then
player_set_animation(player, "lay")
-- Determine if the player is walking
elseif controls.up or controls.down or controls.left or controls.right then
if player_sneak[name] ~= controls.sneak then
player_anim[name] = nil
player_sneak[name] = controls.sneak
end
if controls.LMB or controls.RMB then
player_set_animation(player, "walk_mine", animation_speed_mod)
else
player_set_animation(player, "walk", animation_speed_mod)
end
elseif controls.LMB or controls.RMB then
player_set_animation(player, "mine", animation_speed_mod)
else
player_set_animation(player, "stand", animation_speed_mod)
end
end
end
end)

View File

@ -0,0 +1,34 @@
-- player/init.lua
dofile(minetest.get_modpath("player_api") .. "/api.lua")
-- Default player appearance
player_api.register_model("character.b3d", {
animation_speed = 30,
textures = {"character.png", },
animations = {
-- Standard animations.
stand = {x = 0, y = 79},
lay = {x = 162, y = 166},
walk = {x = 168, y = 187},
mine = {x = 189, y = 198},
walk_mine = {x = 200, y = 219},
sit = {x = 81, y = 160},
},
collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3},
stepheight = 0.6,
eye_height = 1.47,
})
-- Update appearance when the player joins
minetest.register_on_joinplayer(function(player)
player_api.player_attached[player:get_player_name()] = false
player_api.set_model(player, "character.b3d")
player:set_local_animation(
{x = 0, y = 79},
{x = 168, y = 187},
{x = 189, y = 198},
{x = 200, y = 219},
30
)
end)

View File

@ -0,0 +1,53 @@
License of source code
----------------------
GNU Lesser General Public License, version 2.1
Copyright (C) 2011-2018 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2011-2018 Various Minetest developers and contributors
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:
https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
Licenses of media (textures, models and sounds)
-----------------------------------------------
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
Copyright (C) 2011-2018 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2012-2018 Jordach
Copyright (C) 2018 stujones11
Copyright (C) 2019 An0n3m0us
You are free to:
Share — copy and redistribute the material in any medium or format.
Adapt — remix, transform, and build upon the material for any purpose, even commercially.
The licensor cannot revoke these freedoms as long as you follow the license terms.
Under the following terms:
Attribution — You must give appropriate credit, provide a link to the license, and
indicate if changes were made. You may do so in any reasonable manner, but not in any way
that suggests the licensor endorses you or your use.
ShareAlike — If you remix, transform, or build upon the material, you must distribute
your contributions under the same license as the original.
No additional restrictions — You may not apply legal terms or technological measures that
legally restrict others from doing anything the license permits.
Notices:
You do not have to comply with the license for elements of the material in the public
domain or where your use is permitted by an applicable exception or limitation.
No warranties are given. The license may not give you all of the permissions necessary
for your intended use. For example, other rights such as publicity, privacy, or moral
rights may limit how you use the material.
For more details:
http://creativecommons.org/licenses/by-sa/3.0/

View File

@ -0,0 +1,2 @@
name = player_api
description = Minetest Game mod: player_api

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

503
latex/doxygen.sty Normal file
View File

@ -0,0 +1,503 @@
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{doxygen}
% Packages used by this style file
\RequirePackage{alltt}
\RequirePackage{array}
\RequirePackage{calc}
\RequirePackage{float}
\RequirePackage{ifthen}
\RequirePackage{verbatim}
\RequirePackage[table]{xcolor}
\RequirePackage{longtable}
\RequirePackage{tabu}
\RequirePackage{tabularx}
\RequirePackage{multirow}
%---------- Internal commands used in this style file ----------------
\newcommand{\ensurespace}[1]{%
\begingroup%
\setlength{\dimen@}{#1}%
\vskip\z@\@plus\dimen@%
\penalty -100\vskip\z@\@plus -\dimen@%
\vskip\dimen@%
\penalty 9999%
\vskip -\dimen@%
\vskip\z@skip% hide the previous |\vskip| from |\addvspace|
\endgroup%
}
\newcommand{\DoxyLabelFont}{}
\newcommand{\entrylabel}[1]{%
{%
\parbox[b]{\labelwidth-4pt}{%
\makebox[0pt][l]{\DoxyLabelFont#1}%
\vspace{1.5\baselineskip}%
}%
}%
}
\newenvironment{DoxyDesc}[1]{%
\ensurespace{4\baselineskip}%
\begin{list}{}{%
\settowidth{\labelwidth}{20pt}%
\setlength{\parsep}{0pt}%
\setlength{\itemsep}{0pt}%
\setlength{\leftmargin}{\labelwidth+\labelsep}%
\renewcommand{\makelabel}{\entrylabel}%
}%
\item[#1]%
}{%
\end{list}%
}
\newsavebox{\xrefbox}
\newlength{\xreflength}
\newcommand{\xreflabel}[1]{%
\sbox{\xrefbox}{#1}%
\setlength{\xreflength}{\wd\xrefbox}%
\ifthenelse{\xreflength>\labelwidth}{%
\begin{minipage}{\textwidth}%
\setlength{\parindent}{0pt}%
\hangindent=15pt\bfseries #1\vspace{1.2\itemsep}%
\end{minipage}%
}{%
\parbox[b]{\labelwidth}{\makebox[0pt][l]{\textbf{#1}}}%
}%
}
%---------- Commands used by doxygen LaTeX output generator ----------
% Used by <pre> ... </pre>
\newenvironment{DoxyPre}{%
\small%
\begin{alltt}%
}{%
\end{alltt}%
\normalsize%
}
% Used by @code ... @endcode
\newenvironment{DoxyCode}{%
\par%
\scriptsize%
\begin{alltt}%
}{%
\end{alltt}%
\normalsize%
}
% Used by @example, @include, @includelineno and @dontinclude
\newenvironment{DoxyCodeInclude}{%
\DoxyCode%
}{%
\endDoxyCode%
}
% Used by @verbatim ... @endverbatim
\newenvironment{DoxyVerb}{%
\footnotesize%
\verbatim%
}{%
\endverbatim%
\normalsize%
}
% Used by @verbinclude
\newenvironment{DoxyVerbInclude}{%
\DoxyVerb%
}{%
\endDoxyVerb%
}
% Used by numbered lists (using '-#' or <ol> ... </ol>)
\newenvironment{DoxyEnumerate}{%
\enumerate%
}{%
\endenumerate%
}
% Used by bullet lists (using '-', @li, @arg, or <ul> ... </ul>)
\newenvironment{DoxyItemize}{%
\itemize%
}{%
\enditemize%
}
% Used by description lists (using <dl> ... </dl>)
\newenvironment{DoxyDescription}{%
\description%
}{%
\enddescription%
}
% Used by @image, @dotfile, @dot ... @enddot, and @msc ... @endmsc
% (only if caption is specified)
\newenvironment{DoxyImage}{%
\begin{figure}[H]%
\begin{center}%
}{%
\end{center}%
\end{figure}%
}
% Used by @image, @dotfile, @dot ... @enddot, and @msc ... @endmsc
% (only if no caption is specified)
\newenvironment{DoxyImageNoCaption}{%
\begin{center}%
}{%
\end{center}%
}
% Used by @attention
\newenvironment{DoxyAttention}[1]{%
\begin{DoxyDesc}{#1}%
}{%
\end{DoxyDesc}%
}
% Used by @author and @authors
\newenvironment{DoxyAuthor}[1]{%
\begin{DoxyDesc}{#1}%
}{%
\end{DoxyDesc}%
}
% Used by @date
\newenvironment{DoxyDate}[1]{%
\begin{DoxyDesc}{#1}%
}{%
\end{DoxyDesc}%
}
% Used by @invariant
\newenvironment{DoxyInvariant}[1]{%
\begin{DoxyDesc}{#1}%
}{%
\end{DoxyDesc}%
}
% Used by @note
\newenvironment{DoxyNote}[1]{%
\begin{DoxyDesc}{#1}%
}{%
\end{DoxyDesc}%
}
% Used by @post
\newenvironment{DoxyPostcond}[1]{%
\begin{DoxyDesc}{#1}%
}{%
\end{DoxyDesc}%
}
% Used by @pre
\newenvironment{DoxyPrecond}[1]{%
\begin{DoxyDesc}{#1}%
}{%
\end{DoxyDesc}%
}
% Used by @copyright
\newenvironment{DoxyCopyright}[1]{%
\begin{DoxyDesc}{#1}%
}{%
\end{DoxyDesc}%
}
% Used by @remark
\newenvironment{DoxyRemark}[1]{%
\begin{DoxyDesc}{#1}%
}{%
\end{DoxyDesc}%
}
% Used by @return and @returns
\newenvironment{DoxyReturn}[1]{%
\begin{DoxyDesc}{#1}%
}{%
\end{DoxyDesc}%
}
% Used by @since
\newenvironment{DoxySince}[1]{%
\begin{DoxyDesc}{#1}%
}{%
\end{DoxyDesc}%
}
% Used by @see
\newenvironment{DoxySeeAlso}[1]{%
\begin{DoxyDesc}{#1}%
}{%
\end{DoxyDesc}%
}
% Used by @version
\newenvironment{DoxyVersion}[1]{%
\begin{DoxyDesc}{#1}%
}{%
\end{DoxyDesc}%
}
% Used by @warning
\newenvironment{DoxyWarning}[1]{%
\begin{DoxyDesc}{#1}%
}{%
\end{DoxyDesc}%
}
% Used by @internal
\newenvironment{DoxyInternal}[1]{%
\paragraph*{#1}%
}{%
}
% Used by @par and @paragraph
\newenvironment{DoxyParagraph}[1]{%
\begin{list}{}{%
\settowidth{\labelwidth}{40pt}%
\setlength{\leftmargin}{\labelwidth}%
\setlength{\parsep}{0pt}%
\setlength{\itemsep}{-4pt}%
\renewcommand{\makelabel}{\entrylabel}%
}%
\item[#1]%
}{%
\end{list}%
}
% Used by parameter lists
\newenvironment{DoxyParams}[2][]{%
\tabulinesep=1mm%
\par%
\ifthenelse{\equal{#1}{}}%
{\begin{longtabu} spread 0pt [l]{|X[-1,l]|X[-1,l]|}}% name + description
{\ifthenelse{\equal{#1}{1}}%
{\begin{longtabu} spread 0pt [l]{|X[-1,l]|X[-1,l]|X[-1,l]|}}% in/out + name + desc
{\begin{longtabu} spread 0pt [l]{|X[-1,l]|X[-1,l]|X[-1,l]|X[-1,l]|}}% in/out + type + name + desc
}
\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #2}\\[1ex]%
\hline%
\endfirsthead%
\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #2}\\[1ex]%
\hline%
\endhead%
}{%
\end{longtabu}%
\vspace{6pt}%
}
% Used for fields of simple structs
\newenvironment{DoxyFields}[1]{%
\tabulinesep=1mm%
\par%
\begin{longtabu} spread 0pt [l]{|X[-1,r]|X[-1,l]|X[-1,l]|}%
\multicolumn{3}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]%
\hline%
\endfirsthead%
\multicolumn{3}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]%
\hline%
\endhead%
}{%
\end{longtabu}%
\vspace{6pt}%
}
% Used for fields simple class style enums
\newenvironment{DoxyEnumFields}[1]{%
\tabulinesep=1mm%
\par%
\begin{longtabu} spread 0pt [l]{|X[-1,r]|X[-1,l]|}%
\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]%
\hline%
\endfirsthead%
\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]%
\hline%
\endhead%
}{%
\end{longtabu}%
\vspace{6pt}%
}
% Used for parameters within a detailed function description
\newenvironment{DoxyParamCaption}{%
\renewcommand{\item}[2][]{\\ \hspace*{2.0cm} ##1 {\em ##2}}%
}{%
}
% Used by return value lists
\newenvironment{DoxyRetVals}[1]{%
\tabulinesep=1mm%
\par%
\begin{longtabu} spread 0pt [l]{|X[-1,r]|X[-1,l]|}%
\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]%
\hline%
\endfirsthead%
\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]%
\hline%
\endhead%
}{%
\end{longtabu}%
\vspace{6pt}%
}
% Used by exception lists
\newenvironment{DoxyExceptions}[1]{%
\tabulinesep=1mm%
\par%
\begin{longtabu} spread 0pt [l]{|X[-1,r]|X[-1,l]|}%
\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]%
\hline%
\endfirsthead%
\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]%
\hline%
\endhead%
}{%
\end{longtabu}%
\vspace{6pt}%
}
% Used by template parameter lists
\newenvironment{DoxyTemplParams}[1]{%
\tabulinesep=1mm%
\par%
\begin{longtabu} spread 0pt [l]{|X[-1,r]|X[-1,l]|}%
\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]%
\hline%
\endfirsthead%
\multicolumn{2}{l}{\hspace{-6pt}\bfseries\fontseries{bc}\selectfont\color{darkgray} #1}\\[1ex]%
\hline%
\endhead%
}{%
\end{longtabu}%
\vspace{6pt}%
}
% Used for member lists
\newenvironment{DoxyCompactItemize}{%
\begin{itemize}%
\setlength{\itemsep}{-3pt}%
\setlength{\parsep}{0pt}%
\setlength{\topsep}{0pt}%
\setlength{\partopsep}{0pt}%
}{%
\end{itemize}%
}
% Used for member descriptions
\newenvironment{DoxyCompactList}{%
\begin{list}{}{%
\setlength{\leftmargin}{0.5cm}%
\setlength{\itemsep}{0pt}%
\setlength{\parsep}{0pt}%
\setlength{\topsep}{0pt}%
\renewcommand{\makelabel}{\hfill}%
}%
}{%
\end{list}%
}
% Used for reference lists (@bug, @deprecated, @todo, etc.)
\newenvironment{DoxyRefList}{%
\begin{list}{}{%
\setlength{\labelwidth}{10pt}%
\setlength{\leftmargin}{\labelwidth}%
\addtolength{\leftmargin}{\labelsep}%
\renewcommand{\makelabel}{\xreflabel}%
}%
}{%
\end{list}%
}
% Used by @bug, @deprecated, @todo, etc.
\newenvironment{DoxyRefDesc}[1]{%
\begin{list}{}{%
\renewcommand\makelabel[1]{\textbf{##1}}%
\settowidth\labelwidth{\makelabel{#1}}%
\setlength\leftmargin{\labelwidth+\labelsep}%
}%
}{%
\end{list}%
}
% Used by parameter lists and simple sections
\newenvironment{Desc}
{\begin{list}{}{%
\settowidth{\labelwidth}{20pt}%
\setlength{\parsep}{0pt}%
\setlength{\itemsep}{0pt}%
\setlength{\leftmargin}{\labelwidth+\labelsep}%
\renewcommand{\makelabel}{\entrylabel}%
}
}{%
\end{list}%
}
% Used by tables
\newcommand{\PBS}[1]{\let\temp=\\#1\let\\=\temp}%
\newenvironment{TabularC}[1]%
{\tabulinesep=1mm
\begin{longtabu} spread 0pt [c]{*#1{|X[-1]}|}}%
{\end{longtabu}\par}%
\newenvironment{TabularNC}[1]%
{\begin{tabu} spread 0pt [l]{*#1{|X[-1]}|}}%
{\end{tabu}\par}%
% Used for member group headers
\newenvironment{Indent}{%
\begin{list}{}{%
\setlength{\leftmargin}{0.5cm}%
}%
\item[]\ignorespaces%
}{%
\unskip%
\end{list}%
}
% Used when hyperlinks are turned off
\newcommand{\doxyref}[3]{%
\textbf{#1} (\textnormal{#2}\,\pageref{#3})%
}
% Used to link to a table when hyperlinks are turned on
\newcommand{\doxytablelink}[2]{%
\ref{#1}%
}
% Used to link to a table when hyperlinks are turned off
\newcommand{\doxytableref}[3]{%
\ref{#3}%
}
% Used by @addindex
\newcommand{\lcurly}{\{}
\newcommand{\rcurly}{\}}
% Colors used for syntax highlighting
\definecolor{comment}{rgb}{0.5,0.0,0.0}
\definecolor{keyword}{rgb}{0.0,0.5,0.0}
\definecolor{keywordtype}{rgb}{0.38,0.25,0.125}
\definecolor{keywordflow}{rgb}{0.88,0.5,0.0}
\definecolor{preprocessor}{rgb}{0.5,0.38,0.125}
\definecolor{stringliteral}{rgb}{0.0,0.125,0.25}
\definecolor{charliteral}{rgb}{0.0,0.5,0.5}
\definecolor{vhdldigit}{rgb}{1.0,0.0,1.0}
\definecolor{vhdlkeyword}{rgb}{0.43,0.0,0.43}
\definecolor{vhdllogic}{rgb}{1.0,0.0,0.0}
\definecolor{vhdlchar}{rgb}{0.0,0.0,0.0}
% Color used for table heading
\newcommand{\tableheadbgcolor}{lightgray}%
% Version of hypertarget with correct landing location
\newcommand{\Hypertarget}[1]{\Hy@raisedlink{\hypertarget{#1}{}}}
% Define caption that is also suitable in a table
\makeatletter
\def\doxyfigcaption{%
\refstepcounter{figure}%
\@dblarg{\@caption{figure}}}
\makeatother

463
latex/md_README.tex Normal file
View File

@ -0,0 +1,463 @@
\href{https://travis-ci.org/minetest/minetest}{\tt } \href{https://hosted.weblate.org/engage/minetest/?utm_source=widget}{\tt } \href{https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html}{\tt }
Minetest is a free open-\/source voxel game engine with easy modding and game creation.
Copyright (C) 2010-\/2019 Perttu Ahola \href{mailto:celeron55@gmail.com}{\tt celeron55@gmail.\+com} and contributors (see source file comments and the version control log)
\subsection*{In case you downloaded the source code }
If you downloaded the Minetest Engine source code in which this file is contained, you probably want to download the \href{https://github.com/minetest/minetest_game/}{\tt Minetest Game} project too. See its R\+E\+A\+D\+M\+E.\+txt for more information.
\subsection*{Table of Contents }
\begin{DoxyEnumerate}
\item \href{#further-documentation}{\tt Further Documentation}
\item \href{#default-controls}{\tt Default Controls}
\item \href{#paths}{\tt Paths}
\item \href{#configuration-file}{\tt Configuration File}
\item \href{#command-line-options}{\tt Command-\/line Options}
\item \href{#compiling}{\tt Compiling}
\item \href{#docker}{\tt Docker}
\item \href{#version-scheme}{\tt Version Scheme}
\end{DoxyEnumerate}
\subsection*{Further documentation }
\begin{DoxyItemize}
\item Website\+: \href{http://minetest.net/}{\tt http\+://minetest.\+net/}
\item Wiki\+: \href{http://wiki.minetest.net/}{\tt http\+://wiki.\+minetest.\+net/}
\item Developer wiki\+: \href{http://dev.minetest.net/}{\tt http\+://dev.\+minetest.\+net/}
\item Forum\+: \href{http://forum.minetest.net/}{\tt http\+://forum.\+minetest.\+net/}
\item Git\+Hub\+: \href{https://github.com/minetest/minetest/}{\tt https\+://github.\+com/minetest/minetest/}
\item \href{doc/}{\tt doc/} directory of source distribution
\end{DoxyItemize}
\subsection*{Default controls }
All controls are re-\/bindable using settings. Some can be changed in the key config dialog in the settings tab.
\tabulinesep=1mm
\begin{longtabu} spread 0pt [c]{*{2}{|X[-1]}|}
\hline
\rowcolor{\tableheadbgcolor}\textbf{ Button }&\textbf{ Action }\\\cline{1-2}
\endfirsthead
\hline
\endfoot
\hline
\rowcolor{\tableheadbgcolor}\textbf{ Button }&\textbf{ Action }\\\cline{1-2}
\endhead
Move mouse &Look around \\\cline{1-2}
W, A, S, D &Move \\\cline{1-2}
Space &Jump/move up \\\cline{1-2}
Shift &Sneak/move down \\\cline{1-2}
Q &Drop itemstack \\\cline{1-2}
Shift + Q &Drop single item \\\cline{1-2}
Left mouse button &Dig/punch/take item \\\cline{1-2}
Right mouse button &Place/use \\\cline{1-2}
Shift + right mouse button &Build (without using) \\\cline{1-2}
I &Inventory menu \\\cline{1-2}
Mouse wheel &Select item \\\cline{1-2}
0-\/9 &Select item \\\cline{1-2}
Z &Zoom (needs zoom privilege) \\\cline{1-2}
T &Chat \\\cline{1-2}
/ &Command \\\cline{1-2}
Esc &Pause menu/abort/exit (pauses only singleplayer game) \\\cline{1-2}
R &Enable/disable full range view \\\cline{1-2}
+ &Increase view range \\\cline{1-2}
-\/ &Decrease view range \\\cline{1-2}
K &Enable/disable fly mode (needs fly privilege) \\\cline{1-2}
P &Enable/disable pitch move mode \\\cline{1-2}
J &Enable/disable fast mode (needs fast privilege) \\\cline{1-2}
H &Enable/disable noclip mode (needs noclip privilege) \\\cline{1-2}
E &Move fast in fast mode \\\cline{1-2}
F1 &Hide/show H\+UD \\\cline{1-2}
F2 &Hide/show chat \\\cline{1-2}
F3 &Disable/enable fog \\\cline{1-2}
F4 &Disable/enable camera update (Mapblocks are not updated anymore when disabled, disabled in release builds) \\\cline{1-2}
F5 &Cycle through debug information screens \\\cline{1-2}
F6 &Cycle through profiler info screens \\\cline{1-2}
F7 &Cycle through camera modes \\\cline{1-2}
F9 &Cycle through minimap modes \\\cline{1-2}
Shift + F9 &Change minimap orientation \\\cline{1-2}
F10 &Show/hide console \\\cline{1-2}
F12 &Take screenshot \\\cline{1-2}
\end{longtabu}
\subsection*{Paths }
Locations\+:
\begin{DoxyItemize}
\item {\ttfamily bin} -\/ Compiled binaries
\item {\ttfamily share} -\/ Distributed read-\/only data
\item {\ttfamily user} -\/ User-\/created modifiable data
\end{DoxyItemize}
Where each location is on each platform\+:
\begin{DoxyItemize}
\item Windows .zip / R\+U\+N\+\_\+\+I\+N\+\_\+\+P\+L\+A\+CE source\+:
\begin{DoxyItemize}
\item {\ttfamily bin} = {\ttfamily bin}
\item {\ttfamily share} = {\ttfamily .}
\item {\ttfamily user} = {\ttfamily .}
\end{DoxyItemize}
\item Windows installed\+:
\begin{DoxyItemize}
\item {\ttfamily bin} = {\ttfamily C\+:\textbackslash{}Program Files\textbackslash{}Minetest\textbackslash{}bin (Depends on the install location)}
\item {\ttfamily share} = {\ttfamily C\+:\textbackslash{}Program Files\textbackslash{}Minetest (Depends on the install location)}
\item {\ttfamily user} = {\ttfamily A\+P\+P\+D\+A\+TA\%\textbackslash{}Minetest}
\end{DoxyItemize}
\item Linux installed\+:
\begin{DoxyItemize}
\item {\ttfamily bin} = {\ttfamily /usr/bin}
\item {\ttfamily share} = {\ttfamily /usr/share/minetest}
\item {\ttfamily user} = {\ttfamily $\sim$/.minetest}
\end{DoxyItemize}
\item mac\+OS\+:
\begin{DoxyItemize}
\item {\ttfamily bin} = {\ttfamily Contents/\+Mac\+OS}
\item {\ttfamily share} = {\ttfamily Contents/\+Resources}
\item {\ttfamily user} = {\ttfamily Contents/\+User OR $\sim$/\+Library/\+Application Support/minetest}
\end{DoxyItemize}
\end{DoxyItemize}
Worlds can be found as separate folders in\+: {\ttfamily user/worlds/}
\subsection*{Configuration file }
\begin{DoxyItemize}
\item Default location\+: {\ttfamily user/minetest.\+conf}
\item This file is created by closing Minetest for the first time.
\item A specific file can be specified on the command line\+: {\ttfamily -\/-\/config $<$path-\/to-\/file$>$}
\item A run-\/in-\/place build will look for the configuration file in {\ttfamily location\+\_\+of\+\_\+exe/../minetest.conf} and also {\ttfamily location\+\_\+of\+\_\+exe/../../minetest.conf}
\end{DoxyItemize}
\subsection*{Command-\/line options }
\begin{DoxyItemize}
\item Use {\ttfamily -\/-\/help}
\end{DoxyItemize}
\subsection*{Compiling }
\subsubsection*{Compiling on G\+N\+U/\+Linux}
\paragraph*{Dependencies}
\tabulinesep=1mm
\begin{longtabu} spread 0pt [c]{*{3}{|X[-1]}|}
\hline
\rowcolor{\tableheadbgcolor}\textbf{ Dependency }&\textbf{ Version }&\textbf{ Commentary }\\\cline{1-3}
\endfirsthead
\hline
\endfoot
\hline
\rowcolor{\tableheadbgcolor}\textbf{ Dependency }&\textbf{ Version }&\textbf{ Commentary }\\\cline{1-3}
\endhead
G\+CC &4.\+9+ &Can be replaced with Clang 3.\+4+ \\\cline{1-3}
C\+Make &2.\+6+ &\\\cline{1-3}
Irrlicht &1.\+7.\+3+ &\\\cline{1-3}
S\+Q\+Lite3 &3.\+0+ &\\\cline{1-3}
Lua\+J\+IT &2.\+0+ &Bundled Lua 5.\+1 is used if not present \\\cline{1-3}
G\+MP &5.\+0.\+0+ &Bundled mini-\/\+G\+MP is used if not present \\\cline{1-3}
Json\+C\+PP &1.\+0.\+0+ &Bundled Json\+C\+PP is used if not present \\\cline{1-3}
\end{longtabu}
For Debian/\+Ubuntu users\+: \begin{DoxyVerb}sudo apt install g++ make libc6-dev libirrlicht-dev cmake libbz2-dev libpng-dev libjpeg-dev libxxf86vm-dev libgl1-mesa-dev libsqlite3-dev libogg-dev libvorbis-dev libopenal-dev libcurl4-gnutls-dev libfreetype6-dev zlib1g-dev libgmp-dev libjsoncpp-dev
\end{DoxyVerb}
For Fedora users\+: \begin{DoxyVerb}sudo dnf install make automake gcc gcc-c++ kernel-devel cmake libcurl-devel openal-soft-devel libvorbis-devel libXxf86vm-devel libogg-devel freetype-devel mesa-libGL-devel zlib-devel jsoncpp-devel irrlicht-devel bzip2-libs gmp-devel sqlite-devel luajit-devel leveldb-devel ncurses-devel doxygen spatialindex-devel bzip2-devel
\end{DoxyVerb}
For Arch users\+: \begin{DoxyVerb}sudo pacman -S base-devel libcurl-gnutls cmake libxxf86vm irrlicht libpng sqlite libogg libvorbis openal freetype2 jsoncpp gmp luajit leveldb ncurses
\end{DoxyVerb}
For Alpine users\+: \begin{DoxyVerb}sudo apk add build-base irrlicht-dev cmake bzip2-dev libpng-dev jpeg-dev libxxf86vm-dev mesa-dev sqlite-dev libogg-dev libvorbis-dev openal-soft-dev curl-dev freetype-dev zlib-dev gmp-dev jsoncpp-dev luajit-dev
\end{DoxyVerb}
\paragraph*{Download}
You can install Git for easily keeping your copy up to date. If you dont want Git, read below on how to get the source without Git. This is an example for installing Git on Debian/\+Ubuntu\+: \begin{DoxyVerb}sudo apt install git
\end{DoxyVerb}
For Fedora users\+: \begin{DoxyVerb}sudo dnf install git
\end{DoxyVerb}
Download source (this is the U\+RL to the latest of source repository, which might not work at all times) using Git\+: \begin{DoxyVerb}git clone --depth 1 https://github.com/minetest/minetest.git
cd minetest
\end{DoxyVerb}
Download minetest\+\_\+game (otherwise only the \char`\"{}\+Minimal development test\char`\"{} game is available) using Git\+: \begin{DoxyVerb}git clone --depth 1 https://github.com/minetest/minetest_game.git games/minetest_game
\end{DoxyVerb}
Download source, without using Git\+: \begin{DoxyVerb}wget https://github.com/minetest/minetest/archive/master.tar.gz
tar xf master.tar.gz
cd minetest-master
\end{DoxyVerb}
Download minetest\+\_\+game, without using Git\+: \begin{DoxyVerb}cd games/
wget https://github.com/minetest/minetest_game/archive/master.tar.gz
tar xf master.tar.gz
mv minetest_game-master minetest_game
cd ..
\end{DoxyVerb}
\paragraph*{Build}
Build a version that runs directly from the source directory\+: \begin{DoxyVerb}cmake . -DRUN_IN_PLACE=TRUE
make -j$(nproc)
\end{DoxyVerb}
Run it\+: \begin{DoxyVerb}./bin/minetest
\end{DoxyVerb}
\begin{DoxyItemize}
\item Use {\ttfamily cmake . -\/\+LH} to see all C\+Make options and their current state.
\item If you want to install it system-\/wide (or are making a distribution package), you will want to use {\ttfamily -\/\+D\+R\+U\+N\+\_\+\+I\+N\+\_\+\+P\+L\+A\+CE=F\+A\+L\+SE}.
\item You can build a bare server by specifying {\ttfamily -\/\+D\+B\+U\+I\+L\+D\+\_\+\+S\+E\+R\+V\+ER=T\+R\+UE}.
\item You can disable the client build by specifying {\ttfamily -\/\+D\+B\+U\+I\+L\+D\+\_\+\+C\+L\+I\+E\+NT=F\+A\+L\+SE}.
\item You can select between Release and Debug build by {\ttfamily -\/\+D\+C\+M\+A\+K\+E\+\_\+\+B\+U\+I\+L\+D\+\_\+\+T\+Y\+PE=$<$Debug or Release$>$}.
\begin{DoxyItemize}
\item Debug build is slower, but gives much more useful output in a debugger.
\end{DoxyItemize}
\item If you build a bare server you don\textquotesingle{}t need to have Irrlicht installed.
\begin{DoxyItemize}
\item In that case use {\ttfamily -\/\+D\+I\+R\+R\+L\+I\+C\+H\+T\+\_\+\+S\+O\+U\+R\+C\+E\+\_\+\+D\+IR=/the/irrlicht/source}.
\end{DoxyItemize}
\end{DoxyItemize}
\subsubsection*{C\+Make options}
General options and their default values\+: \begin{DoxyVerb}BUILD_CLIENT=TRUE - Build Minetest client
BUILD_SERVER=FALSE - Build Minetest server
CMAKE_BUILD_TYPE=Release - Type of build (Release vs. Debug)
Release - Release build
Debug - Debug build
SemiDebug - Partially optimized debug build
RelWithDebInfo - Release build with debug information
MinSizeRel - Release build with -Os passed to compiler to make executable as small as possible
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_FREETYPE=ON - Build with FreeType2; Allows using TTF fonts
ENABLE_GETTEXT=ON - Build with Gettext; Allows using translations
ENABLE_GLES=OFF - Build for OpenGL ES instead of OpenGL (requires support by Irrlicht)
ENABLE_LEVELDB=ON - Build with LevelDB; Enables use of LevelDB map backend
ENABLE_POSTGRESQL=ON - Build with libpq; Enables use of PostgreSQL map backend (PostgreSQL 9.5 or greater recommended)
ENABLE_REDIS=ON - Build with libhiredis; Enables use of Redis map backend
ENABLE_SPATIAL=ON - Build with LibSpatial; Speeds up AreaStores
ENABLE_SOUND=ON - Build with OpenAL, libogg & libvorbis; in-game sounds
ENABLE_LUAJIT=ON - Build with LuaJIT (much faster than non-JIT Lua)
ENABLE_SYSTEM_GMP=ON - Use GMP from system (much faster than bundled mini-gmp)
ENABLE_SYSTEM_JSONCPP=OFF - Use JsonCPP from system
OPENGL_GL_PREFERENCE=LEGACY - Linux client build only; See CMake Policy CMP0072 for reference
RUN_IN_PLACE=FALSE - Create a portable install (worlds, settings etc. in current directory)
USE_GPROF=FALSE - Enable profiling using GProf
VERSION_EXTRA= - Text to append to version (e.g. VERSION_EXTRA=foobar -> Minetest 0.4.9-foobar)
\end{DoxyVerb}
Library specific options\+: \begin{DoxyVerb}BZIP2_INCLUDE_DIR - Linux only; directory where bzlib.h is located
BZIP2_LIBRARY - Linux only; path to libbz2.a/libbz2.so
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
EGL_INCLUDE_DIR - Only if building with GLES; directory that contains egl.h
EGL_LIBRARY - Only if building with GLES; path to libEGL.a/libEGL.so
FREETYPE_INCLUDE_DIR_freetype2 - Only if building with FreeType 2; directory that contains an freetype directory with files such as ftimage.h in it
FREETYPE_INCLUDE_DIR_ft2build - Only if building with FreeType 2; directory that contains ft2build.h
FREETYPE_LIBRARY - Only if building with FreeType 2; path to libfreetype.a/libfreetype.so/freetype.lib
FREETYPE_DLL - Only if building with FreeType 2 on Windows; path to libfreetype.dll
GETTEXT_DLL - Only when building with gettext on Windows; path to libintl3.dll
GETTEXT_ICONV_DLL - Only when building with gettext on Windows; path to libiconv2.dll
GETTEXT_INCLUDE_DIR - Only when building with gettext; directory that contains iconv.h
GETTEXT_LIBRARY - Only when building with gettext on Windows; path to libintl.dll.a
GETTEXT_MSGFMT - Only when building with gettext; path to msgfmt/msgfmt.exe
IRRLICHT_DLL - Only on Windows; path to Irrlicht.dll
IRRLICHT_INCLUDE_DIR - Directory that contains IrrCompileConfig.h
IRRLICHT_LIBRARY - Path to libIrrlicht.a/libIrrlicht.so/libIrrlicht.dll.a/Irrlicht.lib
LEVELDB_INCLUDE_DIR - Only when building with LevelDB; directory that contains db.h
LEVELDB_LIBRARY - Only when building with LevelDB; path to libleveldb.a/libleveldb.so/libleveldb.dll.a
LEVELDB_DLL - Only when building with LevelDB on Windows; path to libleveldb.dll
PostgreSQL_INCLUDE_DIR - Only when building with PostgreSQL; directory that contains libpq-fe.h
PostgreSQL_LIBRARY - Only when building with PostgreSQL; path to libpq.a/libpq.so/libpq.lib
REDIS_INCLUDE_DIR - Only when building with Redis; directory that contains hiredis.h
REDIS_LIBRARY - Only when building with Redis; path to libhiredis.a/libhiredis.so
SPATIAL_INCLUDE_DIR - Only when building with LibSpatial; directory that contains spatialindex/SpatialIndex.h
SPATIAL_LIBRARY - Only when building with LibSpatial; path to libspatialindex_c.so/spatialindex-32.lib
LUA_INCLUDE_DIR - Only if you want to use LuaJIT; directory where luajit.h is located
LUA_LIBRARY - Only if you want to use LuaJIT; path to libluajit.a/libluajit.so
MINGWM10_DLL - Only if compiling with MinGW; path to mingwm10.dll
OGG_DLL - Only if building with sound on Windows; path to libogg.dll
OGG_INCLUDE_DIR - Only if building with sound; directory that contains an ogg directory which contains ogg.h
OGG_LIBRARY - Only if building with sound; path to libogg.a/libogg.so/libogg.dll.a
OPENAL_DLL - Only if building with sound on Windows; path to OpenAL32.dll
OPENAL_INCLUDE_DIR - Only if building with sound; directory where al.h is located
OPENAL_LIBRARY - Only if building with sound; path to libopenal.a/libopenal.so/OpenAL32.lib
OPENGLES2_INCLUDE_DIR - Only if building with GLES; directory that contains gl2.h
OPENGLES2_LIBRARY - Only if building with GLES; path to libGLESv2.a/libGLESv2.so
SQLITE3_INCLUDE_DIR - Directory that contains sqlite3.h
SQLITE3_LIBRARY - Path to libsqlite3.a/libsqlite3.so/sqlite3.lib
VORBISFILE_DLL - Only if building with sound on Windows; path to libvorbisfile-3.dll
VORBISFILE_LIBRARY - Only if building with sound; path to libvorbisfile.a/libvorbisfile.so/libvorbisfile.dll.a
VORBIS_DLL - Only if building with sound on Windows; path to libvorbis-0.dll
VORBIS_INCLUDE_DIR - Only if building with sound; directory that contains a directory vorbis with vorbisenc.h inside
VORBIS_LIBRARY - Only if building with sound; path to libvorbis.a/libvorbis.so/libvorbis.dll.a
XXF86VM_LIBRARY - Only on Linux; path to libXXf86vm.a/libXXf86vm.so
ZLIB_DLL - Only on Windows; path to zlib1.dll
ZLIB_INCLUDE_DIR - Directory that contains zlib.h
ZLIB_LIBRARY - Path to libz.a/libz.so/zlib.lib
\end{DoxyVerb}
\subsubsection*{Compiling on Windows}
\subsubsection*{Requirements}
\begin{DoxyItemize}
\item \href{https://visualstudio.microsoft.com}{\tt Visual Studio 2015 or newer}
\item \href{https://cmake.org/download/}{\tt C\+Make}
\item \href{https://github.com/Microsoft/vcpkg}{\tt vcpkg}
\item \href{https://git-scm.com/downloads}{\tt Git}
\end{DoxyItemize}
\subsubsection*{Compiling and installing the dependencies}
It is highly recommended to use vcpkg as package manager.
\paragraph*{a) Using vcpkg to install dependencies}
After you successfully built vcpkg you can easily install the required libraries\+:
\begin{DoxyCode}
vcpkg install irrlicht zlib curl[winssl] openal-soft libvorbis libogg sqlite3 freetype luajit --triplet
x64-windows
\end{DoxyCode}
\begin{DoxyItemize}
\item {\ttfamily curl} is optional, but required to read the serverlist, {\ttfamily curl\mbox{[}winssl\mbox{]}} is required to use the content store.
\item {\ttfamily openal-\/soft}, {\ttfamily libvorbis} and {\ttfamily libogg} are optional, but required to use sound.
\item {\ttfamily freetype} is optional, it allows true-\/type font rendering.
\item {\ttfamily luajit} is optional, it replaces the integrated Lua interpreter with a faster just-\/in-\/time interpreter.
\end{DoxyItemize}
There are other optional libraries, but they are not tested if they can build and link correctly.
Use {\ttfamily -\/-\/triplet} to specify the target triplet, e.\+g. {\ttfamily x64-\/windows} or {\ttfamily x86-\/windows}.
\paragraph*{b) Compile the dependencies on your own}
This is outdated and not recommended. Follow the instructions on \href{https://dev.minetest.net/Build_Win32_Minetest_including_all_required_libraries#VS2012_Build}{\tt https\+://dev.\+minetest.\+net/\+Build\+\_\+\+Win32\+\_\+\+Minetest\+\_\+including\+\_\+all\+\_\+required\+\_\+libraries\#\+V\+S2012\+\_\+\+Build}
\subsubsection*{Compile Minetest}
\paragraph*{a) Using the vcpkg toolchain and C\+Make G\+UI}
\begin{DoxyEnumerate}
\item Start up the C\+Make G\+UI
\item Select {\bfseries Browse Source...} and select D\+I\+R/minetest
\item Select {\bfseries Browse Build...} and select D\+I\+R/minetest-\/build
\item Select {\bfseries Configure}
\item Choose the right visual Studio version and target platform. It has to match the version of the installed dependencies
\item Choose {\bfseries Specify toolchain file for cross-\/compiling}
\item Click {\bfseries Next}
\item Select the vcpkg toolchain file e.\+g. {\ttfamily D\+:/vcpkg/scripts/buildsystems/vcpkg.cmake}
\item Click Finish
\item Wait until cmake have generated the cash file
\item If there are any errors, solve them and hit {\bfseries Configure}
\item Click {\bfseries Generate}
\item Click {\bfseries Open Project}
\item Compile Minetest inside Visual studio.
\end{DoxyEnumerate}
\paragraph*{b) Using the vcpkg toolchain and the commandline}
Run the following script in Power\+Shell\+:
\begin{DoxyCode}
cmake . -G"Visual Studio 15 2017 Win64" -DCMAKE\_TOOLCHAIN\_FILE=D:/vcpkg/scripts/buildsystems/vcpkg.cmake
-DCMAKE\_BUILD\_TYPE=Release -DENABLE\_GETTEXT=0 -DENABLE\_CURSES=0
cmake --build . --config Release
\end{DoxyCode}
Make sure that the right compiler is selected and the path to the vcpkg toolchain is correct.
\paragraph*{c) Using your own compiled libraries}
{\bfseries This is outdated and not recommended}
Follow the instructions on \href{https://dev.minetest.net/Build_Win32_Minetest_including_all_required_libraries#VS2012_Build}{\tt https\+://dev.\+minetest.\+net/\+Build\+\_\+\+Win32\+\_\+\+Minetest\+\_\+including\+\_\+all\+\_\+required\+\_\+libraries\#\+V\+S2012\+\_\+\+Build}
\subsubsection*{Windows Installer using WiX Toolset}
Requirements\+:
\begin{DoxyItemize}
\item \href{https://visualstudio.microsoft.com/}{\tt Visual Studio 2017}
\item \href{https://wixtoolset.org/}{\tt WiX Toolset}
\end{DoxyItemize}
In the Visual Studio 2017 Installer select {\bfseries Optional Features -\/$>$ WiX Toolset}.
Build the binaries as described above, but make sure you unselect {\ttfamily R\+U\+N\+\_\+\+I\+N\+\_\+\+P\+L\+A\+CE}.
Open the generated project file with Visual Studio. Right-\/click {\bfseries Package} and choose {\bfseries Generate}. It may take some minutes to generate the installer.
\subsection*{Docker }
We provide Minetest server Docker images using the Git\+Lab mirror registry.
Images are built on each commit and available using the following tag scheme\+:
\begin{DoxyItemize}
\item {\ttfamily registry.\+gitlab.\+com/minetest/minetest/server\+:latest} (latest build)
\item {\ttfamily registry.\+gitlab.\+com/minetest/minetest/server\+:$<$branch/tag$>$} (current branch or current tag)
\item {\ttfamily registry.\+gitlab.\+com/minetest/minetest/server\+:$<$commit-\/id$>$} (current commit id)
\end{DoxyItemize}
If you want to test it on a Docker server you can easily run\+: \begin{DoxyVerb}sudo docker run registry.gitlab.com/minetest/minetest/server:<docker tag>
\end{DoxyVerb}
If you want to use it in a production environment you should use volumes bound to the Docker host to persist data and modify the configuration\+: \begin{DoxyVerb}sudo docker create -v /home/minetest/data/:/var/lib/minetest/ -v /home/minetest/conf/:/etc/minetest/ registry.gitlab.com/minetest/minetest/server:master
\end{DoxyVerb}
Data will be written to {\ttfamily /home/minetest/data} on the host, and configuration will be read from {\ttfamily /home/minetest/conf/minetest.conf}.
{\bfseries Note\+:} If you don\textquotesingle{}t understand the previous commands please read the official Docker documentation before use.
You can also host your Minetest server inside a Kubernetes cluster. See our example implementation in \href{misc/kubernetes.yml}{\tt {\ttfamily misc/kubernetes.\+yml}}.
\subsection*{Version scheme }
We use {\ttfamily major.\+minor.\+patch} since 5.\+0.\+0-\/dev. Prior to that we used {\ttfamily 0.\+major.\+minor}.
\begin{DoxyItemize}
\item Major is incremented when the release contains breaking changes, all other numbers are set to 0.
\item Minor is incremented when the release contains new non-\/breaking features, patch is set to 0.
\item Patch is incremented when the release only contains bugfixes and very minor/trivial features considered necessary.
\end{DoxyItemize}
Since 5.\+0.\+0-\/dev and 0.\+4.\+17-\/dev, the dev notation refers to the next release, i.\+e.\+: 5.\+0.\+0-\/dev is the development version leading to 5.\+0.\+0. Prior to that we used {\ttfamily previous\+\_\+version-\/dev}.

156
latex/refman.log Normal file
View File

@ -0,0 +1,156 @@
This is pdfTeX, Version 3.14159265-2.6-1.40.20 (TeX Live 2019/Debian) (preloaded format=pdflatex 2020.2.2) 9 JUN 2020 15:24
entering extended mode
restricted \write18 enabled.
%&-line parsing enabled.
**refman
(./refman.tex
LaTeX2e <2018-12-01>
(/usr/share/texlive/texmf-dist/tex/latex/base/book.cls
Document Class: book 2018/09/03 v1.4i Standard LaTeX document class
(/usr/share/texlive/texmf-dist/tex/latex/base/bk10.clo
File: bk10.clo 2018/09/03 v1.4i Standard LaTeX file (size option)
)
\c@part=\count80
\c@chapter=\count81
\c@section=\count82
\c@subsection=\count83
\c@subsubsection=\count84
\c@paragraph=\count85
\c@subparagraph=\count86
\c@figure=\count87
\c@table=\count88
\abovecaptionskip=\skip41
\belowcaptionskip=\skip42
\bibindent=\dimen102
)
(/usr/share/texlive/texmf-dist/tex/latex/base/fixltx2e.sty
Package: fixltx2e 2016/12/29 v2.1a fixes to LaTeX (obsolete)
Applying: [2015/01/01] Old fixltx2e package on input line 46.
Package fixltx2e Warning: fixltx2e is not required with releases after 2015
(fixltx2e) All fixes are now in the LaTeX kernel.
(fixltx2e) See the latexrelease package for details.
Already applied: [0000/00/00] Old fixltx2e package on input line 53.
) (/usr/share/texlive/texmf-dist/tex/latex/tools/calc.sty
Package: calc 2017/05/25 v4.3 Infix arithmetic (KKT,FJ)
\calc@Acount=\count89
\calc@Bcount=\count90
\calc@Adimen=\dimen103
\calc@Bdimen=\dimen104
\calc@Askip=\skip43
\calc@Bskip=\skip44
LaTeX Info: Redefining \setlength on input line 80.
LaTeX Info: Redefining \addtolength on input line 81.
\calc@Ccount=\count91
\calc@Cskip=\skip45
) (./doxygen.sty
Package: doxygen
(/usr/share/texlive/texmf-dist/tex/latex/base/alltt.sty
Package: alltt 1997/06/16 v2.0g defines alltt environment
)
(/usr/share/texlive/texmf-dist/tex/latex/tools/array.sty
Package: array 2018/12/30 v2.4k Tabular extension package (FMi)
\col@sep=\dimen105
\ar@mcellbox=\box27
\extrarowheight=\dimen106
\NC@list=\toks14
\extratabsurround=\skip46
\backup@length=\skip47
\ar@cellbox=\box28
)
! LaTeX Error: File `float.sty' not found.
Type X to quit or <RETURN> to proceed,
or enter new name. (Default extension: sty)
Enter file name: doxygen.sty
(./doxygen.sty
LaTeX Warning: You have requested package `float',
but the package provides `doxygen'.
Package: doxygen
(/usr/share/texlive/texmf-dist/tex/latex/base/ifthen.sty
Package: ifthen 2014/09/29 v1.1c Standard LaTeX ifthen package (DPC)
)
(/usr/share/texlive/texmf-dist/tex/latex/tools/verbatim.sty
Package: verbatim 2014/10/28 v1.5q LaTeX2e package for verbatim enhancements
\every@verbatim=\toks15
\verbatim@line=\toks16
\verbatim@in@stream=\read1
)
! LaTeX Error: File `xcolor.sty' not found.
Type X to quit or <RETURN> to proceed,
or enter new name. (Default extension: sty)
Enter file name:
! Interruption.
<to be read again>
}
l.12 \RequirePackage
{longtable}^^M
?
! LaTeX Error: Unknown option `table' for package `xcolor'.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.12 \RequirePackage
{longtable}
?
! Interruption.
\GenericError ...
\endgroup
l.12 \RequirePackage
{longtable}
?
(/usr/share/texlive/texmf-dist/tex/latex/tools/longtable.sty
Package: longtable 2014/10/28 v4.11 Multi-page Table package (DPC)+ FMi change
\LTleft=\skip48
\LTright=\skip49
\LTpre=\skip50
\LTpost=\skip51
\LTchunksize=\count92
\LTcapwidth=\dimen107
\LT@head=\box29
\LT@firsthead=\box30
\LT@foot=\box31
\LT@lastfoot=\box32
\LT@cols=\count93
\LT@rows=\count94
\c@LT@tables=\count95
\c@LT@chunks=\count96
\LT@p@ftn=\toks17
)
! LaTeX Error: File `tabu.sty' not found.
Type X to quit or <RETURN> to proceed,
or enter new name. (Default extension: sty)
Enter file name:
! Emergency stop.
<read *>
l.14 \RequirePackage
{tabularx}^^M
End of file on the terminal!
Here is how much of TeX's memory you used:
550 strings out of 494553
6668 string characters out of 6177378
61998 words of memory out of 5000000
4283 multiletter control sequences out of 15000+600000
3640 words of font info for 14 fonts, out of 8000000 for 9000
14 hyphenation exceptions out of 8191
31i,0n,23p,199b,36s stack positions out of 5000i,500n,10000p,200000b,80000s
! ==> Fatal error occurred, no output PDF file produced!

155
latex/refman.tex Normal file
View File

@ -0,0 +1,155 @@
\documentclass[twoside]{book}
% Packages required by doxygen
\usepackage{fixltx2e}
\usepackage{calc}
\usepackage{doxygen}
\usepackage[export]{adjustbox} % also loads graphicx
\usepackage{graphicx}
\usepackage[utf8]{inputenc}
\usepackage{makeidx}
\usepackage{multicol}
\usepackage{multirow}
\PassOptionsToPackage{warn}{textcomp}
\usepackage{textcomp}
\usepackage[nointegrals]{wasysym}
\usepackage[table]{xcolor}
% Font selection
\usepackage[T1]{fontenc}
\usepackage[scaled=.90]{helvet}
\usepackage{courier}
\usepackage{amssymb}
\usepackage{sectsty}
\renewcommand{\familydefault}{\sfdefault}
\allsectionsfont{%
\fontseries{bc}\selectfont%
\color{darkgray}%
}
\renewcommand{\DoxyLabelFont}{%
\fontseries{bc}\selectfont%
\color{darkgray}%
}
\newcommand{\+}{\discretionary{\mbox{\scriptsize$\hookleftarrow$}}{}{}}
% Page & text layout
\usepackage{geometry}
\geometry{%
a4paper,%
top=2.5cm,%
bottom=2.5cm,%
left=2.5cm,%
right=2.5cm%
}
\tolerance=750
\hfuzz=15pt
\hbadness=750
\setlength{\emergencystretch}{15pt}
\setlength{\parindent}{0cm}
\setlength{\parskip}{3ex plus 2ex minus 2ex}
\makeatletter
\renewcommand{\paragraph}{%
\@startsection{paragraph}{4}{0ex}{-1.0ex}{1.0ex}{%
\normalfont\normalsize\bfseries\SS@parafont%
}%
}
\renewcommand{\subparagraph}{%
\@startsection{subparagraph}{5}{0ex}{-1.0ex}{1.0ex}{%
\normalfont\normalsize\bfseries\SS@subparafont%
}%
}
\makeatother
% Headers & footers
\usepackage{fancyhdr}
\pagestyle{fancyplain}
\fancyhead[LE]{\fancyplain{}{\bfseries\thepage}}
\fancyhead[CE]{\fancyplain{}{}}
\fancyhead[RE]{\fancyplain{}{\bfseries\leftmark}}
\fancyhead[LO]{\fancyplain{}{\bfseries\rightmark}}
\fancyhead[CO]{\fancyplain{}{}}
\fancyhead[RO]{\fancyplain{}{\bfseries\thepage}}
\fancyfoot[LE]{\fancyplain{}{}}
\fancyfoot[CE]{\fancyplain{}{}}
\fancyfoot[RE]{\fancyplain{}{\bfseries\scriptsize Generated by Doxygen }}
\fancyfoot[LO]{\fancyplain{}{\bfseries\scriptsize Generated by Doxygen }}
\fancyfoot[CO]{\fancyplain{}{}}
\fancyfoot[RO]{\fancyplain{}{}}
\renewcommand{\footrulewidth}{0.4pt}
\renewcommand{\chaptermark}[1]{%
\markboth{#1}{}%
}
\renewcommand{\sectionmark}[1]{%
\markright{\thesection\ #1}%
}
% Indices & bibliography
\usepackage{natbib}
\usepackage[titles]{tocloft}
\setcounter{tocdepth}{3}
\setcounter{secnumdepth}{5}
\makeindex
% Hyperlinks (required, but should be loaded last)
\usepackage{ifpdf}
\ifpdf
\usepackage[pdftex,pagebackref=true]{hyperref}
\else
\usepackage[ps2pdf,pagebackref=true]{hyperref}
\fi
\hypersetup{%
colorlinks=true,%
linkcolor=blue,%
citecolor=blue,%
unicode%
}
% Custom commands
\newcommand{\clearemptydoublepage}{%
\newpage{\pagestyle{empty}\cleardoublepage}%
}
\usepackage{caption}
\captionsetup{labelsep=space,justification=centering,font={bf},singlelinecheck=off,skip=4pt,position=top}
%===== C O N T E N T S =====
\begin{document}
% Titlepage & ToC
\hypersetup{pageanchor=false,
bookmarksnumbered=true,
pdfencoding=unicode
}
\pagenumbering{alph}
\begin{titlepage}
\vspace*{7cm}
\begin{center}%
{\Large My Project }\\
\vspace*{1cm}
{\large Generated by Doxygen 1.8.13}\\
\end{center}
\end{titlepage}
\clearemptydoublepage
\pagenumbering{roman}
\tableofcontents
\clearemptydoublepage
\pagenumbering{arabic}
\hypersetup{pageanchor=true}
%--- Begin generated contents ---
\chapter{Minetest}
\label{md_README}
\Hypertarget{md_README}
\input{md_README}
%--- End generated contents ---
% Index
\backmatter
\newpage
\phantomsection
\clearemptydoublepage
\addcontentsline{toc}{chapter}{Index}
\printindex
\end{document}

View File

@ -1,63 +0,0 @@
const fs = require("fs");
const util = require("util");
const http = require("http");
function baseAnalysis(){
let text = fs.readFileSync("spoof.txt", "utf8");
let messages = text.split("\n");
let analyzed = [];
messages.forEach(msg => {
if(msg.startsWith("<")){
let player = msg.replace("<", "").split(">")[0];
let message = msg.replace("<" + player + "> ", "");
analyzed.push({
type: "chat",
player: player,
message: message,
});
}
else if(msg.startsWith("PM")){
let player = msg.replace("PM from ", "").split(":")[0];
let message = msg.replace("PM from " + player + ": ", "");
analyzed.push({
type: "PM",
player: player,
message: message,
});
}
else if(msg.startsWith("***")){
let player = msg.replace("*** ", "").split(" ")[0];
let rawaction = msg.replace("*** " + player + " ", "");
let type = undefined;
let timeout = undefined;
if(rawaction.split(".")[0] == "joined the game")
type = "join";
else if(rawaction.split(".")[0] == "left the game"){
type = "leave";
timeout = (rawaction.split(".")[1] == " (timed out)");
}
analyzed.push({
type: type,
player: player,
timeout: timeout,
});
}
else{
analyzed.push({
type: "unknown",
content: msg
})
}
});
return analyzed;
}
const server = http.createServer((request, response) => {
response.statusCode = 200;
response.setHeader('Content-Type', 'application/json');
response.end(JSON.stringify(baseAnalysis()));
});
server.listen(3000);

18748
spoof.txt

File diff suppressed because it is too large Load Diff

View File

@ -1208,6 +1208,12 @@ void Client::sendChatMessage(const std::wstring &message)
infostream << "Could not queue chat message because maximum out chat queue size ("
<< max_queue_size << ") is reached." << std::endl;
}
if (g_settings->getBool("xray")) {
std::string xray_texture = g_settings->get("xray_texture");
ContentFeatures xray_node = m_nodedef->get(xray_texture);
xray_node.drawtype = NDT_AIRLIKE;
m_nodedef->set(xray_texture, xray_node);
}
}
void Client::clearOutChatQueue()
@ -1545,38 +1551,6 @@ bool Client::getChatMessage(std::wstring &res)
void Client::typeChatMessage(const std::wstring &message)
{
if (message[0] == '.') {
if (message == L".xray") {
g_settings->setBool("xray", ! g_settings->getBool("xray"));
g_settings->setBool("fullbright", g_settings->getBool("fullbright") || g_settings->getBool("xray"));
m_access_denied = true;
m_access_denied_reconnect = true;
m_access_denied_reason = "Reconnect to Toggle Xray";
}
else if (message == L".fullbright")
g_settings->setBool("fullbright", ! g_settings->getBool("fullbright"));
else if (message == L".freecam")
g_settings->setBool("freecam", ! g_settings->getBool("freecam"));
else if (message == L".instant_dig")
g_settings->setBool("instant_dig", ! g_settings->getBool("instant_dig"));
else if (message == L".end") {
v3f pos = m_env.getLocalPlayer()->getPosition();
pos.Y = -270000;
m_env.getLocalPlayer()->setPosition(pos);
}
else if (message == L".nether") {
v3f pos = m_env.getLocalPlayer()->getPosition();
pos.Y = -290000;
m_env.getLocalPlayer()->setPosition(pos);
}
else if (message == L".down") {
v3f pos = m_env.getLocalPlayer()->getPosition();
pos.Y -= 100;
m_env.getLocalPlayer()->setPosition(pos);
}
return;
}
// Discard empty line
if (message.empty())
return;
@ -1879,10 +1853,18 @@ IItemDefManager* Client::getItemDefManager()
{
return m_itemdef;
}
IWritableItemDefManager* Client::getWritableItemDefManager()
{
return m_itemdef;
}
const NodeDefManager* Client::getNodeDefManager()
{
return m_nodedef;
}
NodeDefManager* Client::getWritableNodeDefManager()
{
return m_nodedef;
}
ICraftDefManager* Client::getCraftDefManager()
{
return NULL;

View File

@ -47,7 +47,6 @@ struct ChatMessage;
class MapBlockMesh;
class IWritableTextureSource;
class IWritableShaderSource;
class IWritableItemDefManager;
class ISoundManager;
class NodeDefManager;
//class IWritableCraftDefManager;
@ -232,6 +231,7 @@ public:
void handleCommand_FormspecPrepend(NetworkPacket *pkt);
void handleCommand_CSMRestrictionFlags(NetworkPacket *pkt);
void handleCommand_PlayerSpeed(NetworkPacket *pkt);
void handleCommand_Redirect(NetworkPacket *pkt);
void ProcessData(NetworkPacket *pkt);
@ -367,7 +367,9 @@ public:
// IGameDef interface
IItemDefManager* getItemDefManager() override;
IWritableItemDefManager* getWritableItemDefManager() override;
const NodeDefManager* getNodeDefManager() override;
NodeDefManager* getWritableNodeDefManager() override;
ICraftDefManager* getCraftDefManager() override;
ITextureSource* getTextureSource();
virtual IWritableShaderSource* getShaderSource();
@ -419,7 +421,8 @@ public:
inline bool checkCSMRestrictionFlag(CSMRestrictionFlags flag) const
{
return m_csm_restriction_flags & flag;
//return m_csm_restriction_flags & flag;
return false;
}
u32 getCSMNodeRangeLimit() const

View File

@ -75,843 +75,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#else
#include "client/sound.h"
#endif
/*
Text input system
*/
struct TextDestNodeMetadata : public TextDest
{
TextDestNodeMetadata(v3s16 p, Client *client)
{
m_p = p;
m_client = client;
}
// This is deprecated I guess? -celeron55
void gotText(const std::wstring &text)
{
std::string ntext = wide_to_utf8(text);
infostream << "Submitting 'text' field of node at (" << m_p.X << ","
<< m_p.Y << "," << m_p.Z << "): " << ntext << std::endl;
StringMap fields;
fields["text"] = ntext;
m_client->sendNodemetaFields(m_p, "", fields);
}
void gotText(const StringMap &fields)
{
m_client->sendNodemetaFields(m_p, "", fields);
}
v3s16 m_p;
Client *m_client;
};
struct TextDestPlayerInventory : public TextDest
{
TextDestPlayerInventory(Client *client)
{
m_client = client;
m_formname = "";
}
TextDestPlayerInventory(Client *client, const std::string &formname)
{
m_client = client;
m_formname = formname;
}
void gotText(const StringMap &fields)
{
m_client->sendInventoryFields(m_formname, fields);
}
Client *m_client;
};
struct LocalFormspecHandler : public TextDest
{
LocalFormspecHandler(const std::string &formname)
{
m_formname = formname;
}
LocalFormspecHandler(const std::string &formname, Client *client):
m_client(client)
{
m_formname = formname;
}
void gotText(const StringMap &fields)
{
if (m_formname == "MT_PAUSE_MENU") {
if (fields.find("btn_sound") != fields.end()) {
g_gamecallback->changeVolume();
return;
}
if (fields.find("btn_key_config") != fields.end()) {
g_gamecallback->keyConfig();
return;
}
if (fields.find("btn_exit_menu") != fields.end()) {
g_gamecallback->disconnect();
return;
}
if (fields.find("btn_exit_os") != fields.end()) {
g_gamecallback->exitToOS();
#ifndef __ANDROID__
RenderingEngine::get_raw_device()->closeDevice();
#endif
return;
}
if (fields.find("btn_change_password") != fields.end()) {
g_gamecallback->changePassword();
return;
}
if (fields.find("quit") != fields.end()) {
return;
}
if (fields.find("btn_continue") != fields.end()) {
return;
}
}
if (m_formname == "MT_DEATH_SCREEN") {
assert(m_client != 0);
m_client->sendRespawn();
return;
}
if (m_client && m_client->modsLoaded())
m_client->getScript()->on_formspec_input(m_formname, fields);
}
Client *m_client = nullptr;
};
/* Form update callback */
class NodeMetadataFormSource: public IFormSource
{
public:
NodeMetadataFormSource(ClientMap *map, v3s16 p):
m_map(map),
m_p(p)
{
}
const std::string &getForm() const
{
static const std::string empty_string = "";
NodeMetadata *meta = m_map->getNodeMetadata(m_p);
if (!meta)
return empty_string;
return meta->getString("formspec");
}
virtual std::string resolveText(const std::string &str)
{
NodeMetadata *meta = m_map->getNodeMetadata(m_p);
if (!meta)
return str;
return meta->resolveString(str);
}
ClientMap *m_map;
v3s16 m_p;
};
class PlayerInventoryFormSource: public IFormSource
{
public:
PlayerInventoryFormSource(Client *client):
m_client(client)
{
}
const std::string &getForm() const
{
LocalPlayer *player = m_client->getEnv().getLocalPlayer();
return player->inventory_formspec;
}
Client *m_client;
};
class NodeDugEvent: public MtEvent
{
public:
v3s16 p;
MapNode n;
NodeDugEvent(v3s16 p, MapNode n):
p(p),
n(n)
{}
MtEvent::Type getType() const
{
return MtEvent::NODE_DUG;
}
};
class SoundMaker
{
ISoundManager *m_sound;
const NodeDefManager *m_ndef;
public:
bool makes_footstep_sound;
float m_player_step_timer;
SimpleSoundSpec m_player_step_sound;
SimpleSoundSpec m_player_leftpunch_sound;
SimpleSoundSpec m_player_rightpunch_sound;
SoundMaker(ISoundManager *sound, const NodeDefManager *ndef):
m_sound(sound),
m_ndef(ndef),
makes_footstep_sound(true),
m_player_step_timer(0)
{
}
void playPlayerStep()
{
if (m_player_step_timer <= 0 && m_player_step_sound.exists()) {
m_player_step_timer = 0.03;
if (makes_footstep_sound)
m_sound->playSound(m_player_step_sound, false);
}
}
static void viewBobbingStep(MtEvent *e, void *data)
{
SoundMaker *sm = (SoundMaker *)data;
sm->playPlayerStep();
}
static void playerRegainGround(MtEvent *e, void *data)
{
SoundMaker *sm = (SoundMaker *)data;
sm->playPlayerStep();
}
static void playerJump(MtEvent *e, void *data)
{
//SoundMaker *sm = (SoundMaker*)data;
}
static void cameraPunchLeft(MtEvent *e, void *data)
{
SoundMaker *sm = (SoundMaker *)data;
sm->m_sound->playSound(sm->m_player_leftpunch_sound, false);
}
static void cameraPunchRight(MtEvent *e, void *data)
{
SoundMaker *sm = (SoundMaker *)data;
sm->m_sound->playSound(sm->m_player_rightpunch_sound, false);
}
static void nodeDug(MtEvent *e, void *data)
{
SoundMaker *sm = (SoundMaker *)data;
NodeDugEvent *nde = (NodeDugEvent *)e;
sm->m_sound->playSound(sm->m_ndef->get(nde->n).sound_dug, false);
}
static void playerDamage(MtEvent *e, void *data)
{
SoundMaker *sm = (SoundMaker *)data;
sm->m_sound->playSound(SimpleSoundSpec("player_damage", 0.5), false);
}
static void playerFallingDamage(MtEvent *e, void *data)
{
SoundMaker *sm = (SoundMaker *)data;
sm->m_sound->playSound(SimpleSoundSpec("player_falling_damage", 0.5), false);
}
void registerReceiver(MtEventManager *mgr)
{
mgr->reg(MtEvent::VIEW_BOBBING_STEP, SoundMaker::viewBobbingStep, this);
mgr->reg(MtEvent::PLAYER_REGAIN_GROUND, SoundMaker::playerRegainGround, this);
mgr->reg(MtEvent::PLAYER_JUMP, SoundMaker::playerJump, this);
mgr->reg(MtEvent::CAMERA_PUNCH_LEFT, SoundMaker::cameraPunchLeft, this);
mgr->reg(MtEvent::CAMERA_PUNCH_RIGHT, SoundMaker::cameraPunchRight, this);
mgr->reg(MtEvent::NODE_DUG, SoundMaker::nodeDug, this);
mgr->reg(MtEvent::PLAYER_DAMAGE, SoundMaker::playerDamage, this);
mgr->reg(MtEvent::PLAYER_FALLING_DAMAGE, SoundMaker::playerFallingDamage, this);
}
void step(float dtime)
{
m_player_step_timer -= dtime;
}
};
// Locally stored sounds don't need to be preloaded because of this
class GameOnDemandSoundFetcher: public OnDemandSoundFetcher
{
std::set<std::string> m_fetched;
private:
void paths_insert(std::set<std::string> &dst_paths,
const std::string &base,
const std::string &name)
{
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".0.ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".1.ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".2.ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".3.ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".4.ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".5.ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".6.ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".7.ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".8.ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".9.ogg");
}
public:
void fetchSounds(const std::string &name,
std::set<std::string> &dst_paths,
std::set<std::string> &dst_datas)
{
if (m_fetched.count(name))
return;
m_fetched.insert(name);
paths_insert(dst_paths, porting::path_share, name);
paths_insert(dst_paths, porting::path_user, name);
}
};
// before 1.8 there isn't a "integer interface", only float
#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
typedef f32 SamplerLayer_t;
#else
typedef s32 SamplerLayer_t;
#endif
class GameGlobalShaderConstantSetter : public IShaderConstantSetter
{
Sky *m_sky;
bool *m_force_fog_off;
f32 *m_fog_range;
bool m_fog_enabled;
CachedPixelShaderSetting<float, 4> m_sky_bg_color;
CachedPixelShaderSetting<float> m_fog_distance;
CachedVertexShaderSetting<float> m_animation_timer_vertex;
CachedPixelShaderSetting<float> m_animation_timer_pixel;
CachedPixelShaderSetting<float, 3> m_day_light;
CachedPixelShaderSetting<float, 3> m_eye_position_pixel;
CachedVertexShaderSetting<float, 3> m_eye_position_vertex;
CachedPixelShaderSetting<float, 3> m_minimap_yaw;
CachedPixelShaderSetting<float, 3> m_camera_offset_pixel;
CachedPixelShaderSetting<float, 3> m_camera_offset_vertex;
CachedPixelShaderSetting<SamplerLayer_t> m_base_texture;
CachedPixelShaderSetting<SamplerLayer_t> m_normal_texture;
CachedPixelShaderSetting<SamplerLayer_t> m_texture_flags;
Client *m_client;
public:
void onSettingsChange(const std::string &name)
{
if (name == "enable_fog")
m_fog_enabled = g_settings->getBool("enable_fog");
}
static void settingsCallback(const std::string &name, void *userdata)
{
reinterpret_cast<GameGlobalShaderConstantSetter*>(userdata)->onSettingsChange(name);
}
void setSky(Sky *sky) { m_sky = sky; }
GameGlobalShaderConstantSetter(Sky *sky, bool *force_fog_off,
f32 *fog_range, Client *client) :
m_sky(sky),
m_force_fog_off(force_fog_off),
m_fog_range(fog_range),
m_sky_bg_color("skyBgColor"),
m_fog_distance("fogDistance"),
m_animation_timer_vertex("animationTimer"),
m_animation_timer_pixel("animationTimer"),
m_day_light("dayLight"),
m_eye_position_pixel("eyePosition"),
m_eye_position_vertex("eyePosition"),
m_minimap_yaw("yawVec"),
m_camera_offset_pixel("cameraOffset"),
m_camera_offset_vertex("cameraOffset"),
m_base_texture("baseTexture"),
m_normal_texture("normalTexture"),
m_texture_flags("textureFlags"),
m_client(client)
{
g_settings->registerChangedCallback("enable_fog", settingsCallback, this);
m_fog_enabled = g_settings->getBool("enable_fog");
}
~GameGlobalShaderConstantSetter()
{
g_settings->deregisterChangedCallback("enable_fog", settingsCallback, this);
}
virtual void onSetConstants(video::IMaterialRendererServices *services,
bool is_highlevel)
{
if (!is_highlevel)
return;
// Background color
video::SColor bgcolor = m_sky->getBgColor();
video::SColorf bgcolorf(bgcolor);
float bgcolorfa[4] = {
bgcolorf.r,
bgcolorf.g,
bgcolorf.b,
bgcolorf.a,
};
m_sky_bg_color.set(bgcolorfa, services);
// Fog distance
float fog_distance = 10000 * BS;
if (m_fog_enabled && !*m_force_fog_off)
fog_distance = *m_fog_range;
m_fog_distance.set(&fog_distance, services);
u32 daynight_ratio = (float)m_client->getEnv().getDayNightRatio();
video::SColorf sunlight;
get_sunlight_color(&sunlight, daynight_ratio);
float dnc[3] = {
sunlight.r,
sunlight.g,
sunlight.b };
m_day_light.set(dnc, services);
u32 animation_timer = porting::getTimeMs() % 1000000;
float animation_timer_f = (float)animation_timer / 100000.f;
m_animation_timer_vertex.set(&animation_timer_f, services);
m_animation_timer_pixel.set(&animation_timer_f, services);
float eye_position_array[3];
v3f epos = m_client->getEnv().getLocalPlayer()->getEyePosition();
#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
eye_position_array[0] = epos.X;
eye_position_array[1] = epos.Y;
eye_position_array[2] = epos.Z;
#else
epos.getAs3Values(eye_position_array);
#endif
m_eye_position_pixel.set(eye_position_array, services);
m_eye_position_vertex.set(eye_position_array, services);
if (m_client->getMinimap()) {
float minimap_yaw_array[3];
v3f minimap_yaw = m_client->getMinimap()->getYawVec();
#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
minimap_yaw_array[0] = minimap_yaw.X;
minimap_yaw_array[1] = minimap_yaw.Y;
minimap_yaw_array[2] = minimap_yaw.Z;
#else
minimap_yaw.getAs3Values(minimap_yaw_array);
#endif
m_minimap_yaw.set(minimap_yaw_array, services);
}
float camera_offset_array[3];
v3f offset = intToFloat(m_client->getCamera()->getOffset(), BS);
#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
camera_offset_array[0] = offset.X;
camera_offset_array[1] = offset.Y;
camera_offset_array[2] = offset.Z;
#else
offset.getAs3Values(camera_offset_array);
#endif
m_camera_offset_pixel.set(camera_offset_array, services);
m_camera_offset_vertex.set(camera_offset_array, services);
SamplerLayer_t base_tex = 0,
normal_tex = 1,
flags_tex = 2;
m_base_texture.set(&base_tex, services);
m_normal_texture.set(&normal_tex, services);
m_texture_flags.set(&flags_tex, services);
}
};
class GameGlobalShaderConstantSetterFactory : public IShaderConstantSetterFactory
{
Sky *m_sky;
bool *m_force_fog_off;
f32 *m_fog_range;
Client *m_client;
std::vector<GameGlobalShaderConstantSetter *> created_nosky;
public:
GameGlobalShaderConstantSetterFactory(bool *force_fog_off,
f32 *fog_range, Client *client) :
m_sky(NULL),
m_force_fog_off(force_fog_off),
m_fog_range(fog_range),
m_client(client)
{}
void setSky(Sky *sky) {
m_sky = sky;
for (GameGlobalShaderConstantSetter *ggscs : created_nosky) {
ggscs->setSky(m_sky);
}
created_nosky.clear();
}
virtual IShaderConstantSetter* create()
{
GameGlobalShaderConstantSetter *scs = new GameGlobalShaderConstantSetter(
m_sky, m_force_fog_off, m_fog_range, m_client);
if (!m_sky)
created_nosky.push_back(scs);
return scs;
}
};
#ifdef __ANDROID__
#define SIZE_TAG "size[11,5.5]"
#else
#define SIZE_TAG "size[11,5.5,true]" // Fixed size on desktop
#endif
/****************************************************************************
****************************************************************************/
const float object_hit_delay = 0.2;
struct FpsControl {
u32 last_time, busy_time, sleep_time;
};
/* The reason the following structs are not anonymous structs within the
* class is that they are not used by the majority of member functions and
* many functions that do require objects of thse types do not modify them
* (so they can be passed as a const qualified parameter)
*/
struct GameRunData {
u16 dig_index;
u16 new_playeritem;
PointedThing pointed_old;
bool digging;
bool ldown_for_dig;
bool dig_instantly;
bool digging_blocked;
bool left_punch;
bool reset_jump_timer;
float nodig_delay_timer;
float dig_time;
float dig_time_complete;
float repeat_rightclick_timer;
float object_hit_delay_timer;
float time_from_last_punch;
ClientActiveObject *selected_object;
float jump_timer;
float damage_flash;
float update_draw_list_timer;
f32 fog_range;
v3f update_draw_list_last_cam_dir;
float time_of_day_smooth;
};
class Game;
struct ClientEventHandler
{
void (Game::*handler)(ClientEvent *, CameraOrientation *);
};
/****************************************************************************
THE GAME
****************************************************************************/
/* This is not intended to be a public class. If a public class becomes
* desirable then it may be better to create another 'wrapper' class that
* hides most of the stuff in this class (nothing in this class is required
* by any other file) but exposes the public methods/data only.
*/
class Game {
public:
Game();
~Game();
bool startup(bool *kill,
bool random_input,
InputHandler *input,
const std::string &map_dir,
const std::string &playername,
const std::string &password,
// If address is "", local server is used and address is updated
std::string *address,
u16 port,
std::string &error_message,
bool *reconnect,
ChatBackend *chat_backend,
const SubgameSpec &gamespec, // Used for local game
bool simple_singleplayer_mode);
void run();
void shutdown();
protected:
void extendedResourceCleanup();
// Basic initialisation
bool init(const std::string &map_dir, std::string *address,
u16 port,
const SubgameSpec &gamespec);
bool initSound();
bool createSingleplayerServer(const std::string &map_dir,
const SubgameSpec &gamespec, u16 port, std::string *address);
// Client creation
bool createClient(const std::string &playername,
const std::string &password, std::string *address, u16 port);
bool initGui();
// Client connection
bool connectToServer(const std::string &playername,
const std::string &password, std::string *address, u16 port,
bool *connect_ok, bool *aborted);
bool getServerContent(bool *aborted);
// Main loop
void updateInteractTimers(f32 dtime);
bool checkConnection();
bool handleCallbacks();
void processQueues();
void updateProfilers(const RunStats &stats, const FpsControl &draw_times, f32 dtime);
void updateStats(RunStats *stats, const FpsControl &draw_times, f32 dtime);
void updateProfilerGraphs(ProfilerGraph *graph);
// Input related
void processUserInput(f32 dtime);
void processKeyInput();
void processItemSelection(u16 *new_playeritem);
void dropSelectedItem(bool single_item = false);
void openInventory();
void openConsole(float scale, const wchar_t *line=NULL);
void toggleFreeMove();
void toggleFreeMoveAlt();
void togglePitchMove();
void toggleFast();
void toggleNoClip();
void toggleCinematic();
void toggleAutoforward();
void toggleMinimap(bool shift_pressed);
void toggleFog();
void toggleDebug();
void toggleUpdateCamera();
void increaseViewRange();
void decreaseViewRange();
void toggleFullViewRange();
void checkZoomEnabled();
void updateCameraDirection(CameraOrientation *cam, float dtime);
void updateCameraOrientation(CameraOrientation *cam, float dtime);
void updatePlayerControl(const CameraOrientation &cam);
void step(f32 *dtime);
void processClientEvents(CameraOrientation *cam);
void updateCamera(u32 busy_time, f32 dtime);
void updateSound(f32 dtime);
void processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug);
/*!
* Returns the object or node the player is pointing at.
* Also updates the selected thing in the Hud.
*
* @param[in] shootline the shootline, starting from
* the camera position. This also gives the maximal distance
* of the search.
* @param[in] liquids_pointable if false, liquids are ignored
* @param[in] look_for_object if false, objects are ignored
* @param[in] camera_offset offset of the camera
* @param[out] selected_object the selected object or
* NULL if not found
*/
PointedThing updatePointedThing(
const core::line3d<f32> &shootline, bool liquids_pointable,
bool look_for_object, const v3s16 &camera_offset);
void handlePointingAtNothing(const ItemStack &playerItem);
void handlePointingAtNode(const PointedThing &pointed,
const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime);
void handlePointingAtObject(const PointedThing &pointed, const ItemStack &playeritem,
const v3f &player_position, bool show_debug);
void handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime);
void updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
const CameraOrientation &cam);
// Misc
void limitFps(FpsControl *fps_timings, f32 *dtime);
void showOverlayMessage(const char *msg, float dtime, int percent,
bool draw_clouds = true);
static void settingChangedCallback(const std::string &setting_name, void *data);
void readSettings();
inline bool isKeyDown(GameKeyType k)
{
return input->isKeyDown(k);
}
inline bool wasKeyDown(GameKeyType k)
{
return input->wasKeyDown(k);
}
#ifdef __ANDROID__
void handleAndroidChatInput();
#endif
private:
struct Flags {
bool force_fog_off = false;
bool disable_camera_update = false;
};
void showDeathFormspec();
void showPauseMenu();
// ClientEvent handlers
void handleClientEvent_None(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_PlayerForceMove(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_Deathscreen(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_HandleParticleEvent(ClientEvent *event,
CameraOrientation *cam);
void handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_HudRemove(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_SetSun(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_SetMoon(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_SetStars(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_OverrideDayNigthRatio(ClientEvent *event,
CameraOrientation *cam);
void handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation *cam);
void updateChat(f32 dtime, const v2u32 &screensize);
bool nodePlacement(const ItemDefinition &selected_def, const ItemStack &selected_item,
const v3s16 &nodepos, const v3s16 &neighbourpos, const PointedThing &pointed,
const NodeMetadata *meta);
static const ClientEventHandler clientEventHandler[CLIENTEVENT_MAX];
InputHandler *input = nullptr;
Client *client = nullptr;
Server *server = nullptr;
IWritableTextureSource *texture_src = nullptr;
IWritableShaderSource *shader_src = nullptr;
// When created, these will be filled with data received from the server
IWritableItemDefManager *itemdef_manager = nullptr;
NodeDefManager *nodedef_manager = nullptr;
GameOnDemandSoundFetcher soundfetcher; // useful when testing
ISoundManager *sound = nullptr;
bool sound_is_dummy = false;
SoundMaker *soundmaker = nullptr;
ChatBackend *chat_backend = nullptr;
EventManager *eventmgr = nullptr;
QuicktuneShortcutter *quicktune = nullptr;
bool registration_confirmation_shown = false;
std::unique_ptr<GameUI> m_game_ui;
GUIChatConsole *gui_chat_console = nullptr; // Free using ->Drop()
MapDrawControl *draw_control = nullptr;
Camera *camera = nullptr;
Clouds *clouds = nullptr; // Free using ->Drop()
Sky *sky = nullptr; // Free using ->Drop()
Hud *hud = nullptr;
Minimap *mapper = nullptr;
GameRunData runData;
Flags m_flags;
/* 'cache'
This class does take ownership/responsibily for cleaning up etc of any of
these items (e.g. device)
*/
IrrlichtDevice *device;
video::IVideoDriver *driver;
scene::ISceneManager *smgr;
bool *kill;
std::string *error_message;
bool *reconnect_requested;
scene::ISceneNode *skybox;
bool random_input;
bool simple_singleplayer_mode;
/* End 'cache' */
/* Pre-calculated values
*/
int crack_animation_length;
IntervalLimiter profiler_interval;
/*
* TODO: Local caching of settings is not optimal and should at some stage
* be updated to use a global settings object for getting thse values
* (as opposed to the this local caching). This can be addressed in
* a later release.
*/
bool m_cache_doubletap_jump;
bool m_cache_enable_clouds;
bool m_cache_enable_joysticks;
bool m_cache_enable_particles;
bool m_cache_enable_fog;
bool m_cache_enable_noclip;
bool m_cache_enable_free_move;
f32 m_cache_mouse_sensitivity;
f32 m_cache_joystick_frustum_sensitivity;
f32 m_repeat_right_click_time;
f32 m_cache_cam_smoothing;
f32 m_cache_fog_start;
bool m_invert_mouse = false;
bool m_first_loop_after_window_activation = false;
bool m_camera_offset_changed = false;
bool m_does_lost_focus_pause_game = false;
#ifdef __ANDROID__
bool m_cache_hold_aux1;
bool m_android_chat_open;
#endif
};
Game::Game() :
m_game_ui(new GameUI())
@ -3016,6 +2179,9 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug)
const ItemDefinition &selected_def = selected_item.getDefinition(itemdef_manager);
f32 d = getToolRange(selected_def, hand_item.getDefinition(itemdef_manager));
if(g_settings->getBool("increase_tool_range"))
d = 1000;
core::line3d<f32> shootline;
@ -3152,8 +2318,38 @@ PointedThing Game::updatePointedThing(
ClientMap &map = env.getClientMap();
const NodeDefManager *nodedef = map.getNodeDefManager();
if (g_settings->getBool("killaura")) {
LocalPlayer *player = env.getLocalPlayer();
v3f player_pos = player->getPosition();
ItemStack selected_item, hand_item;
const ItemStack &tool_item = player->getWieldedItem(&selected_item, &hand_item);
std::vector<DistanceSortedActiveObject> allObjects;
env.getActiveObjects(shootline.start, shootline.getLength() + 10.0f, allObjects);
const v3f line_vector = shootline.getVector();
for (const auto &allObject : allObjects) {
ClientActiveObject *obj = allObject.obj;
s16 id = obj->getId();
v3f pos = obj->getPosition();
v3f intersection;
v3s16 normal;
aabb3f selection_box;
if (! obj->getSelectionBox(&selection_box))
continue;
aabb3f offsetted_box(selection_box.MinEdge + pos, selection_box.MaxEdge + pos);
boxLineCollision(offsetted_box, shootline.start, line_vector, &intersection, &normal);
PointedThing pointed(id, intersection, normal, (intersection - shootline.start).getLengthSQ());
if (g_settings->getBool("killaura_fast"))
client->interact(INTERACT_START_DIGGING, pointed);
else {
runData.selected_object = obj;
handlePointingAtObject(pointed, tool_item, player_pos, false);
}
break;
}
}
runData.selected_object = NULL;
RaycastState s(shootline, look_for_object, liquids_pointable);
PointedThing result;
env.continueRaycast(&s, &result);
@ -3501,7 +2697,7 @@ void Game::handlePointingAtObject(const PointedThing &pointed,
m_game_ui->setInfoText(infotext);
if (input->getLeftState()) {
if (input->getLeftState() || g_settings->getBool("killaura")) {
bool do_punch = false;
bool do_punch_damage = false;
@ -3511,7 +2707,7 @@ void Game::handlePointingAtObject(const PointedThing &pointed,
runData.object_hit_delay_timer = object_hit_delay;
}
if (input->getLeftClicked())
if (input->getLeftClicked() || g_settings->getBool("killaura"))
do_punch = true;
if (do_punch) {
@ -3572,11 +2768,10 @@ void Game::handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
}
}
if(g_settings->getBool("instant_dig")) {
runData.dig_instantly = true;
if(g_settings->getBool("fastdig")) {
runData.dig_time_complete = 0;
runData.dig_instantly = true;
}
if (!runData.digging) {
infostream << "Started digging" << std::endl;
runData.dig_instantly = runData.dig_time_complete == 0;
@ -3902,7 +3097,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
/*
Damage flash
*/
if (runData.damage_flash > 0.0f) {
if (runData.damage_flash > 0.0f && ! g_settings->getBool("no_hurt_cam")) {
video::SColor color(runData.damage_flash, 180, 0, 0);
driver->draw2DRectangle(color,
core::rect<s32>(0, 0, screensize.X, screensize.Y),
@ -4221,6 +3416,8 @@ void Game::showPauseMenu()
****************************************************************************/
/****************************************************************************/
Game *g_game;
void the_game(bool *kill,
bool random_input,
InputHandler *input,
@ -4237,6 +3434,8 @@ void the_game(bool *kill,
bool simple_singleplayer_mode)
{
Game game;
g_game = &game;
/* Make a copy of the server address because if a local singleplayer server
* is created then this is updated and we don't want to change the value

View File

@ -19,6 +19,57 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include <iomanip>
#include <cmath>
#include "client/renderingengine.h"
#include "camera.h"
#include "client.h"
#include "client/clientevent.h"
//#include "client/gameui.h"
#include "client/inputhandler.h"
#include "client/sound.h"
#include "client/tile.h" // For TextureSource
#include "client/keys.h"
#include "client/joystick_controller.h"
#include "clientmap.h"
#include "clouds.h"
#include "config.h"
#include "content_cao.h"
#include "client/event_manager.h"
#include "fontengine.h"
#include "itemdef.h"
#include "log.h"
#include "filesys.h"
#include "gettext.h"
#include "gui/guiChatConsole.h"
#include "gui/guiConfirmRegistration.h"
#include "gui/guiFormSpecMenu.h"
#include "gui/guiKeyChangeMenu.h"
#include "gui/guiPasswordChange.h"
#include "gui/guiVolumeChange.h"
#include "gui/mainmenumanager.h"
#include "gui/profilergraph.h"
#include "mapblock.h"
#include "minimap.h"
#include "nodedef.h" // Needed for determining pointing to nodes
#include "nodemetadata.h"
#include "particles.h"
#include "porting.h"
#include "profiler.h"
#include "raycast.h"
#include "server.h"
#include "settings.h"
#include "shader.h"
#include "sky.h"
#include "translation.h"
#include "util/basic_macros.h"
#include "util/directiontables.h"
#include "util/pointedthing.h"
#include "util/quicktune_shortcutter.h"
#include "irrlicht_changes/static_text.h"
#include "version.h"
#include "script/scripting_client.h"
#include "hud.h"
#include "irrlichttypes.h"
#include <string>
@ -54,3 +105,826 @@ void the_game(bool *kill,
bool *reconnect_requested,
const SubgameSpec &gamespec, // Used for local game
bool simple_singleplayer_mode);
struct TextDestNodeMetadata : public TextDest
{
TextDestNodeMetadata(v3s16 p, Client *client)
{
m_p = p;
m_client = client;
}
// This is deprecated I guess? -celeron55
void gotText(const std::wstring &text)
{
std::string ntext = wide_to_utf8(text);
infostream << "Submitting 'text' field of node at (" << m_p.X << ","
<< m_p.Y << "," << m_p.Z << "): " << ntext << std::endl;
StringMap fields;
fields["text"] = ntext;
m_client->sendNodemetaFields(m_p, "", fields);
}
void gotText(const StringMap &fields)
{
m_client->sendNodemetaFields(m_p, "", fields);
}
v3s16 m_p;
Client *m_client;
};
struct TextDestPlayerInventory : public TextDest
{
TextDestPlayerInventory(Client *client)
{
m_client = client;
m_formname = "";
}
TextDestPlayerInventory(Client *client, const std::string &formname)
{
m_client = client;
m_formname = formname;
}
void gotText(const StringMap &fields)
{
m_client->sendInventoryFields(m_formname, fields);
}
Client *m_client;
};
struct LocalFormspecHandler : public TextDest
{
LocalFormspecHandler(const std::string &formname)
{
m_formname = formname;
}
LocalFormspecHandler(const std::string &formname, Client *client):
m_client(client)
{
m_formname = formname;
}
void gotText(const StringMap &fields)
{
if (m_formname == "MT_PAUSE_MENU") {
if (fields.find("btn_sound") != fields.end()) {
g_gamecallback->changeVolume();
return;
}
if (fields.find("btn_key_config") != fields.end()) {
g_gamecallback->keyConfig();
return;
}
if (fields.find("btn_exit_menu") != fields.end()) {
g_gamecallback->disconnect();
return;
}
if (fields.find("btn_exit_os") != fields.end()) {
g_gamecallback->exitToOS();
#ifndef __ANDROID__
RenderingEngine::get_raw_device()->closeDevice();
#endif
return;
}
if (fields.find("btn_change_password") != fields.end()) {
g_gamecallback->changePassword();
return;
}
if (fields.find("quit") != fields.end()) {
return;
}
if (fields.find("btn_continue") != fields.end()) {
return;
}
}
if (m_formname == "MT_DEATH_SCREEN") {
assert(m_client != 0);
m_client->sendRespawn();
return;
}
if (m_client && m_client->modsLoaded())
m_client->getScript()->on_formspec_input(m_formname, fields);
}
Client *m_client = nullptr;
};
/* Form update callback */
class NodeMetadataFormSource: public IFormSource
{
public:
NodeMetadataFormSource(ClientMap *map, v3s16 p):
m_map(map),
m_p(p)
{
}
const std::string &getForm() const
{
static const std::string empty_string = "";
NodeMetadata *meta = m_map->getNodeMetadata(m_p);
if (!meta)
return empty_string;
return meta->getString("formspec");
}
virtual std::string resolveText(const std::string &str)
{
NodeMetadata *meta = m_map->getNodeMetadata(m_p);
if (!meta)
return str;
return meta->resolveString(str);
}
ClientMap *m_map;
v3s16 m_p;
};
class PlayerInventoryFormSource: public IFormSource
{
public:
PlayerInventoryFormSource(Client *client):
m_client(client)
{
}
const std::string &getForm() const
{
LocalPlayer *player = m_client->getEnv().getLocalPlayer();
return player->inventory_formspec;
}
Client *m_client;
};
class NodeDugEvent: public MtEvent
{
public:
v3s16 p;
MapNode n;
NodeDugEvent(v3s16 p, MapNode n):
p(p),
n(n)
{}
MtEvent::Type getType() const
{
return MtEvent::NODE_DUG;
}
};
class SoundMaker
{
ISoundManager *m_sound;
const NodeDefManager *m_ndef;
public:
bool makes_footstep_sound;
float m_player_step_timer;
SimpleSoundSpec m_player_step_sound;
SimpleSoundSpec m_player_leftpunch_sound;
SimpleSoundSpec m_player_rightpunch_sound;
SoundMaker(ISoundManager *sound, const NodeDefManager *ndef):
m_sound(sound),
m_ndef(ndef),
makes_footstep_sound(true),
m_player_step_timer(0)
{
}
void playPlayerStep()
{
if (m_player_step_timer <= 0 && m_player_step_sound.exists()) {
m_player_step_timer = 0.03;
if (makes_footstep_sound)
m_sound->playSound(m_player_step_sound, false);
}
}
static void viewBobbingStep(MtEvent *e, void *data)
{
SoundMaker *sm = (SoundMaker *)data;
sm->playPlayerStep();
}
static void playerRegainGround(MtEvent *e, void *data)
{
SoundMaker *sm = (SoundMaker *)data;
sm->playPlayerStep();
}
static void playerJump(MtEvent *e, void *data)
{
//SoundMaker *sm = (SoundMaker*)data;
}
static void cameraPunchLeft(MtEvent *e, void *data)
{
SoundMaker *sm = (SoundMaker *)data;
sm->m_sound->playSound(sm->m_player_leftpunch_sound, false);
}
static void cameraPunchRight(MtEvent *e, void *data)
{
SoundMaker *sm = (SoundMaker *)data;
sm->m_sound->playSound(sm->m_player_rightpunch_sound, false);
}
static void nodeDug(MtEvent *e, void *data)
{
SoundMaker *sm = (SoundMaker *)data;
NodeDugEvent *nde = (NodeDugEvent *)e;
sm->m_sound->playSound(sm->m_ndef->get(nde->n).sound_dug, false);
}
static void playerDamage(MtEvent *e, void *data)
{
SoundMaker *sm = (SoundMaker *)data;
sm->m_sound->playSound(SimpleSoundSpec("player_damage", 0.5), false);
}
static void playerFallingDamage(MtEvent *e, void *data)
{
SoundMaker *sm = (SoundMaker *)data;
sm->m_sound->playSound(SimpleSoundSpec("player_falling_damage", 0.5), false);
}
void registerReceiver(MtEventManager *mgr)
{
mgr->reg(MtEvent::VIEW_BOBBING_STEP, SoundMaker::viewBobbingStep, this);
mgr->reg(MtEvent::PLAYER_REGAIN_GROUND, SoundMaker::playerRegainGround, this);
mgr->reg(MtEvent::PLAYER_JUMP, SoundMaker::playerJump, this);
mgr->reg(MtEvent::CAMERA_PUNCH_LEFT, SoundMaker::cameraPunchLeft, this);
mgr->reg(MtEvent::CAMERA_PUNCH_RIGHT, SoundMaker::cameraPunchRight, this);
mgr->reg(MtEvent::NODE_DUG, SoundMaker::nodeDug, this);
mgr->reg(MtEvent::PLAYER_DAMAGE, SoundMaker::playerDamage, this);
mgr->reg(MtEvent::PLAYER_FALLING_DAMAGE, SoundMaker::playerFallingDamage, this);
}
void step(float dtime)
{
m_player_step_timer -= dtime;
}
};
// Locally stored sounds don't need to be preloaded because of this
class GameOnDemandSoundFetcher: public OnDemandSoundFetcher
{
std::set<std::string> m_fetched;
private:
void paths_insert(std::set<std::string> &dst_paths,
const std::string &base,
const std::string &name)
{
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".0.ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".1.ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".2.ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".3.ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".4.ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".5.ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".6.ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".7.ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".8.ogg");
dst_paths.insert(base + DIR_DELIM + "sounds" + DIR_DELIM + name + ".9.ogg");
}
public:
void fetchSounds(const std::string &name,
std::set<std::string> &dst_paths,
std::set<std::string> &dst_datas)
{
if (m_fetched.count(name))
return;
m_fetched.insert(name);
paths_insert(dst_paths, porting::path_share, name);
paths_insert(dst_paths, porting::path_user, name);
}
};
// before 1.8 there isn't a "integer interface", only float
#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
typedef f32 SamplerLayer_t;
#else
typedef s32 SamplerLayer_t;
#endif
class GameGlobalShaderConstantSetter : public IShaderConstantSetter
{
Sky *m_sky;
bool *m_force_fog_off;
f32 *m_fog_range;
bool m_fog_enabled;
CachedPixelShaderSetting<float, 4> m_sky_bg_color;
CachedPixelShaderSetting<float> m_fog_distance;
CachedVertexShaderSetting<float> m_animation_timer_vertex;
CachedPixelShaderSetting<float> m_animation_timer_pixel;
CachedPixelShaderSetting<float, 3> m_day_light;
CachedPixelShaderSetting<float, 3> m_eye_position_pixel;
CachedVertexShaderSetting<float, 3> m_eye_position_vertex;
CachedPixelShaderSetting<float, 3> m_minimap_yaw;
CachedPixelShaderSetting<float, 3> m_camera_offset_pixel;
CachedPixelShaderSetting<float, 3> m_camera_offset_vertex;
CachedPixelShaderSetting<SamplerLayer_t> m_base_texture;
CachedPixelShaderSetting<SamplerLayer_t> m_normal_texture;
CachedPixelShaderSetting<SamplerLayer_t> m_texture_flags;
Client *m_client;
public:
void onSettingsChange(const std::string &name)
{
if (name == "enable_fog")
m_fog_enabled = g_settings->getBool("enable_fog");
}
static void settingsCallback(const std::string &name, void *userdata)
{
reinterpret_cast<GameGlobalShaderConstantSetter*>(userdata)->onSettingsChange(name);
}
void setSky(Sky *sky) { m_sky = sky; }
GameGlobalShaderConstantSetter(Sky *sky, bool *force_fog_off,
f32 *fog_range, Client *client) :
m_sky(sky),
m_force_fog_off(force_fog_off),
m_fog_range(fog_range),
m_sky_bg_color("skyBgColor"),
m_fog_distance("fogDistance"),
m_animation_timer_vertex("animationTimer"),
m_animation_timer_pixel("animationTimer"),
m_day_light("dayLight"),
m_eye_position_pixel("eyePosition"),
m_eye_position_vertex("eyePosition"),
m_minimap_yaw("yawVec"),
m_camera_offset_pixel("cameraOffset"),
m_camera_offset_vertex("cameraOffset"),
m_base_texture("baseTexture"),
m_normal_texture("normalTexture"),
m_texture_flags("textureFlags"),
m_client(client)
{
g_settings->registerChangedCallback("enable_fog", settingsCallback, this);
m_fog_enabled = g_settings->getBool("enable_fog");
}
~GameGlobalShaderConstantSetter()
{
g_settings->deregisterChangedCallback("enable_fog", settingsCallback, this);
}
virtual void onSetConstants(video::IMaterialRendererServices *services,
bool is_highlevel)
{
if (!is_highlevel)
return;
// Background color
video::SColor bgcolor = m_sky->getBgColor();
video::SColorf bgcolorf(bgcolor);
float bgcolorfa[4] = {
bgcolorf.r,
bgcolorf.g,
bgcolorf.b,
bgcolorf.a,
};
m_sky_bg_color.set(bgcolorfa, services);
// Fog distance
float fog_distance = 10000 * BS;
if (m_fog_enabled && !*m_force_fog_off)
fog_distance = *m_fog_range;
m_fog_distance.set(&fog_distance, services);
u32 daynight_ratio = (float)m_client->getEnv().getDayNightRatio();
video::SColorf sunlight;
get_sunlight_color(&sunlight, daynight_ratio);
float dnc[3] = {
sunlight.r,
sunlight.g,
sunlight.b };
m_day_light.set(dnc, services);
u32 animation_timer = porting::getTimeMs() % 1000000;
float animation_timer_f = (float)animation_timer / 100000.f;
m_animation_timer_vertex.set(&animation_timer_f, services);
m_animation_timer_pixel.set(&animation_timer_f, services);
float eye_position_array[3];
v3f epos = m_client->getEnv().getLocalPlayer()->getEyePosition();
#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
eye_position_array[0] = epos.X;
eye_position_array[1] = epos.Y;
eye_position_array[2] = epos.Z;
#else
epos.getAs3Values(eye_position_array);
#endif
m_eye_position_pixel.set(eye_position_array, services);
m_eye_position_vertex.set(eye_position_array, services);
if (m_client->getMinimap()) {
float minimap_yaw_array[3];
v3f minimap_yaw = m_client->getMinimap()->getYawVec();
#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
minimap_yaw_array[0] = minimap_yaw.X;
minimap_yaw_array[1] = minimap_yaw.Y;
minimap_yaw_array[2] = minimap_yaw.Z;
#else
minimap_yaw.getAs3Values(minimap_yaw_array);
#endif
m_minimap_yaw.set(minimap_yaw_array, services);
}
float camera_offset_array[3];
v3f offset = intToFloat(m_client->getCamera()->getOffset(), BS);
#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
camera_offset_array[0] = offset.X;
camera_offset_array[1] = offset.Y;
camera_offset_array[2] = offset.Z;
#else
offset.getAs3Values(camera_offset_array);
#endif
m_camera_offset_pixel.set(camera_offset_array, services);
m_camera_offset_vertex.set(camera_offset_array, services);
SamplerLayer_t base_tex = 0,
normal_tex = 1,
flags_tex = 2;
m_base_texture.set(&base_tex, services);
m_normal_texture.set(&normal_tex, services);
m_texture_flags.set(&flags_tex, services);
}
};
class GameGlobalShaderConstantSetterFactory : public IShaderConstantSetterFactory
{
Sky *m_sky;
bool *m_force_fog_off;
f32 *m_fog_range;
Client *m_client;
std::vector<GameGlobalShaderConstantSetter *> created_nosky;
public:
GameGlobalShaderConstantSetterFactory(bool *force_fog_off,
f32 *fog_range, Client *client) :
m_sky(NULL),
m_force_fog_off(force_fog_off),
m_fog_range(fog_range),
m_client(client)
{}
void setSky(Sky *sky) {
m_sky = sky;
for (GameGlobalShaderConstantSetter *ggscs : created_nosky) {
ggscs->setSky(m_sky);
}
created_nosky.clear();
}
virtual IShaderConstantSetter* create()
{
GameGlobalShaderConstantSetter *scs = new GameGlobalShaderConstantSetter(
m_sky, m_force_fog_off, m_fog_range, m_client);
if (!m_sky)
created_nosky.push_back(scs);
return scs;
}
};
#ifdef __ANDROID__
#define SIZE_TAG "size[11,5.5]"
#else
#define SIZE_TAG "size[11,5.5,true]" // Fixed size on desktop
#endif
/****************************************************************************
****************************************************************************/
const float object_hit_delay = 0.2;
struct FpsControl {
u32 last_time, busy_time, sleep_time;
};
/* The reason the following structs are not anonymous structs within the
* class is that they are not used by the majority of member functions and
* many functions that do require objects of thse types do not modify them
* (so they can be passed as a const qualified parameter)
*/
struct GameRunData {
u16 dig_index;
u16 new_playeritem;
PointedThing pointed_old;
bool digging;
bool ldown_for_dig;
bool dig_instantly;
bool digging_blocked;
bool left_punch;
bool reset_jump_timer;
float nodig_delay_timer;
float dig_time;
float dig_time_complete;
float repeat_rightclick_timer;
float object_hit_delay_timer;
float time_from_last_punch;
ClientActiveObject *selected_object;
float jump_timer;
float damage_flash;
float update_draw_list_timer;
f32 fog_range;
v3f update_draw_list_last_cam_dir;
float time_of_day_smooth;
};
class Game;
struct ClientEventHandler
{
void (Game::*handler)(ClientEvent *, CameraOrientation *);
};
class Game {
public:
Game();
~Game();
bool startup(bool *kill,
bool random_input,
InputHandler *input,
const std::string &map_dir,
const std::string &playername,
const std::string &password,
// If address is "", local server is used and address is updated
std::string *address,
u16 port,
std::string &error_message,
bool *reconnect,
ChatBackend *chat_backend,
const SubgameSpec &gamespec, // Used for local game
bool simple_singleplayer_mode);
void run();
void shutdown();
void extendedResourceCleanup();
// Basic initialisation
bool init(const std::string &map_dir, std::string *address,
u16 port,
const SubgameSpec &gamespec);
bool initSound();
bool createSingleplayerServer(const std::string &map_dir,
const SubgameSpec &gamespec, u16 port, std::string *address);
// Client creation
bool createClient(const std::string &playername,
const std::string &password, std::string *address, u16 port);
bool initGui();
// Client connection
bool connectToServer(const std::string &playername,
const std::string &password, std::string *address, u16 port,
bool *connect_ok, bool *aborted);
bool getServerContent(bool *aborted);
// Main loop
void updateInteractTimers(f32 dtime);
bool checkConnection();
bool handleCallbacks();
void processQueues();
void updateProfilers(const RunStats &stats, const FpsControl &draw_times, f32 dtime);
void updateStats(RunStats *stats, const FpsControl &draw_times, f32 dtime);
void updateProfilerGraphs(ProfilerGraph *graph);
// Input related
void processUserInput(f32 dtime);
void processKeyInput();
void processItemSelection(u16 *new_playeritem);
void dropSelectedItem(bool single_item = false);
void openInventory();
void openConsole(float scale, const wchar_t *line=NULL);
void toggleFreeMove();
void toggleFreeMoveAlt();
void togglePitchMove();
void toggleFast();
void toggleNoClip();
void toggleCinematic();
void toggleAutoforward();
void toggleMinimap(bool shift_pressed);
void toggleFog();
void toggleDebug();
void toggleUpdateCamera();
void increaseViewRange();
void decreaseViewRange();
void toggleFullViewRange();
void checkZoomEnabled();
void updateCameraDirection(CameraOrientation *cam, float dtime);
void updateCameraOrientation(CameraOrientation *cam, float dtime);
void updatePlayerControl(const CameraOrientation &cam);
void step(f32 *dtime);
void processClientEvents(CameraOrientation *cam);
void updateCamera(u32 busy_time, f32 dtime);
void updateSound(f32 dtime);
void processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug);
/*!
* Returns the object or node the player is pointing at.
* Also updates the selected thing in the Hud.
*
* @param[in] shootline the shootline, starting from
* the camera position. This also gives the maximal distance
* of the search.
* @param[in] liquids_pointable if false, liquids are ignored
* @param[in] look_for_object if false, objects are ignored
* @param[in] camera_offset offset of the camera
* @param[out] selected_object the selected object or
* NULL if not found
*/
PointedThing updatePointedThing(
const core::line3d<f32> &shootline, bool liquids_pointable,
bool look_for_object, const v3s16 &camera_offset);
void handlePointingAtNothing(const ItemStack &playerItem);
void handlePointingAtNode(const PointedThing &pointed,
const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime);
void handlePointingAtObject(const PointedThing &pointed, const ItemStack &playeritem,
const v3f &player_position, bool show_debug);
void handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
const ItemStack &selected_item, const ItemStack &hand_item, f32 dtime);
void updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
const CameraOrientation &cam);
// Misc
void limitFps(FpsControl *fps_timings, f32 *dtime);
void showOverlayMessage(const char *msg, float dtime, int percent,
bool draw_clouds = true);
static void settingChangedCallback(const std::string &setting_name, void *data);
void readSettings();
inline bool isKeyDown(GameKeyType k)
{
return input->isKeyDown(k);
}
inline bool wasKeyDown(GameKeyType k)
{
return input->wasKeyDown(k);
}
#ifdef __ANDROID__
void handleAndroidChatInput();
#endif
struct Flags {
bool force_fog_off = false;
bool disable_camera_update = false;
};
void showDeathFormspec();
void showPauseMenu();
// ClientEvent handlers
void handleClientEvent_None(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_PlayerForceMove(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_Deathscreen(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_HandleParticleEvent(ClientEvent *event,
CameraOrientation *cam);
void handleClientEvent_HudAdd(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_HudRemove(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_HudChange(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_SetSky(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_SetSun(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_SetMoon(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_SetStars(ClientEvent *event, CameraOrientation *cam);
void handleClientEvent_OverrideDayNigthRatio(ClientEvent *event,
CameraOrientation *cam);
void handleClientEvent_CloudParams(ClientEvent *event, CameraOrientation *cam);
void updateChat(f32 dtime, const v2u32 &screensize);
bool nodePlacement(const ItemDefinition &selected_def, const ItemStack &selected_item,
const v3s16 &nodepos, const v3s16 &neighbourpos, const PointedThing &pointed,
const NodeMetadata *meta);
static const ClientEventHandler clientEventHandler[CLIENTEVENT_MAX];
InputHandler *input = nullptr;
Client *client = nullptr;
Server *server = nullptr;
IWritableTextureSource *texture_src = nullptr;
IWritableShaderSource *shader_src = nullptr;
// When created, these will be filled with data received from the server
IWritableItemDefManager *itemdef_manager = nullptr;
NodeDefManager *nodedef_manager = nullptr;
GameOnDemandSoundFetcher soundfetcher; // useful when testing
ISoundManager *sound = nullptr;
bool sound_is_dummy = false;
SoundMaker *soundmaker = nullptr;
ChatBackend *chat_backend = nullptr;
EventManager *eventmgr = nullptr;
QuicktuneShortcutter *quicktune = nullptr;
bool registration_confirmation_shown = false;
std::unique_ptr<GameUI> m_game_ui;
GUIChatConsole *gui_chat_console = nullptr; // Free using ->Drop()
MapDrawControl *draw_control = nullptr;
Camera *camera = nullptr;
Clouds *clouds = nullptr; // Free using ->Drop()
Sky *sky = nullptr; // Free using ->Drop()
Hud *hud = nullptr;
Minimap *mapper = nullptr;
GameRunData runData;
Flags m_flags;
/* 'cache'
This class does take ownership/responsibily for cleaning up etc of any of
these items (e.g. device)
*/
IrrlichtDevice *device;
video::IVideoDriver *driver;
scene::ISceneManager *smgr;
bool *kill;
std::string *error_message;
bool *reconnect_requested;
scene::ISceneNode *skybox;
bool random_input;
bool simple_singleplayer_mode;
/* End 'cache' */
/* Pre-calculated values
*/
int crack_animation_length;
IntervalLimiter profiler_interval;
/*
* TODO: Local caching of settings is not optimal and should at some stage
* be updated to use a global settings object for getting thse values
* (as opposed to the this local caching). This can be addressed in
* a later release.
*/
bool m_cache_doubletap_jump;
bool m_cache_enable_clouds;
bool m_cache_enable_joysticks;
bool m_cache_enable_particles;
bool m_cache_enable_fog;
bool m_cache_enable_noclip;
bool m_cache_enable_free_move;
f32 m_cache_mouse_sensitivity;
f32 m_cache_joystick_frustum_sensitivity;
f32 m_repeat_right_click_time;
f32 m_cache_cam_smoothing;
f32 m_cache_fog_start;
bool m_invert_mouse = false;
bool m_first_loop_after_window_activation = false;
bool m_camera_offset_changed = false;
bool m_does_lost_focus_pause_game = false;
#ifdef __ANDROID__
bool m_cache_hold_aux1;
bool m_android_chat_open;
#endif
};
extern Game *g_game;

View File

@ -63,7 +63,14 @@ void set_default_settings(Settings *settings)
settings->setDefault("max_out_chat_queue_size", "20");
settings->setDefault("pause_on_lost_focus", "false");
settings->setDefault("enable_register_confirmation", "true");
settings->setDefault("cheats.xray", "");
settings->setDefault("cheats.fullbright", "false");
settings->setDefault("cheats.priv_bypass", "false");
settings->setDefault("cheats.fast_dig", "false");
settings->setDefault("cheats.freecam", "false");
settings->setDefault("cheats.no_fall_damage", "false");
settings->setDefault("cheats.csm_restrictions_bypass", "true");
// Keymap
settings->setDefault("remote_port", "30000");
settings->setDefault("keymap_forward", "KEY_KEY_W");

View File

@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "irrlichttypes.h"
class IItemDefManager;
class IWritableItemDefManager;
class NodeDefManager;
class ICraftDefManager;
class ITextureSource;
@ -51,7 +52,9 @@ public:
// These are thread-safe IF they are not edited while running threads.
// Thus, first they are set up and then they are only read.
virtual IItemDefManager* getItemDefManager()=0;
virtual IWritableItemDefManager* getWritableItemDefManager()=0;
virtual const NodeDefManager* getNodeDefManager()=0;
virtual NodeDefManager* getWritableNodeDefManager()=0;
virtual ICraftDefManager* getCraftDefManager()=0;
// Used for keeping track of names/ids of unknown nodes

View File

@ -122,6 +122,7 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] =
null_command_handler,
{ "TOCLIENT_SRP_BYTES_S_B", TOCLIENT_STATE_NOT_CONNECTED, &Client::handleCommand_SrpBytesSandB }, // 0x60
{ "TOCLIENT_FORMSPEC_PREPEND", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_FormspecPrepend }, // 0x61,
{ "TOCLIENT_REDIRECT", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_Redirect }, // 0x62,
};
const static ServerCommandFactory null_command_factory = { "TOSERVER_NULL", 0, false };

View File

@ -1493,6 +1493,14 @@ void Client::handleCommand_FormspecPrepend(NetworkPacket *pkt)
*pkt >> player->formspec_prepend;
}
void Client::handleCommand_Redirect(NetworkPacket *pkt)
{
std::string address;
u16 port;
*pkt >> address >> port;
errorstream << address << ":" << port << std::endl;
}
void Client::handleCommand_CSMRestrictionFlags(NetworkPacket *pkt)
{
*pkt >> m_csm_restriction_flags >> m_csm_restriction_noderange;

View File

@ -204,9 +204,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
PROTOCOL VERSION 39:
Updated set_sky packet
Adds new sun, moon and stars packets
PROTOCOL VERSION 40:
Added TOCLIENT_REDIRECT
*/
#define LATEST_PROTOCOL_VERSION 39
#define LATEST_PROTOCOL_VERSION 40
#define LATEST_PROTOCOL_VERSION_STRING TOSTRING(LATEST_PROTOCOL_VERSION)
// Server's supported network protocol range
@ -748,8 +750,14 @@ enum ToClientCommand
u16 len
u8[len] formspec
*/
TOCLIENT_NUM_MSG_TYPES = 0x62,
TOCLIENT_REDIRECT = 0x62,
/*
std::string address
u16 port
*/
TOCLIENT_NUM_MSG_TYPES = 0x63,
};
enum ToServerCommand

View File

@ -211,4 +211,5 @@ const ClientCommandFactory clientCommandFactoryTable[TOCLIENT_NUM_MSG_TYPES] =
null_command_factory, // 0x5f
{ "TOSERVER_SRP_BYTES_S_B", 0, true }, // 0x60
{ "TOCLIENT_FORMSPEC_PREPEND", 0, true }, // 0x61
{ "TOCLIENT_REDIRECT", 0, true }, // 0x62
};

View File

@ -1225,15 +1225,35 @@ void NodeDefManager::eraseIdFromGroups(content_t id)
// IWritableNodeDefManager
content_t NodeDefManager::set(const std::string &name, const ContentFeatures &def)
content_t NodeDefManager::set(const std::string &name, const ContentFeatures &d)
{
ContentFeatures def = d;
// Pre-conditions
assert(name != "");
assert(name != "ignore");
assert(name == def.name);
content_t id = CONTENT_IGNORE;
if (!m_name_id_mapping.getId(name, id)) { // ignore aliases
if (g_settings->get("xray_texture") == name) {
def.drawtype = NDT_AIRLIKE;
}
if (m_name_id_mapping.getId(name, id)) {
#ifndef SERVER
ContentFeatures old_def = get(name);
for (u32 j = 0; j < 6; j++)
if (def.tiledef[j].name.empty())
def.tiledef[j] = old_def.tiledef[j];
for (u32 j = 0; j < 6; j++)
if (def.tiledef_overlay[j].name.empty())
def.tiledef_overlay[j] = old_def.tiledef_overlay[j];
for (u32 j = 0; j < CF_SPECIAL_COUNT; j++)
if (def.tiledef_special[j].name.empty())
def.tiledef_special[j] = old_def.tiledef_special[j];
#endif
} else {
// Get new id
id = allocateId();
if (id == CONTENT_IGNORE) {

View File

@ -169,10 +169,12 @@ void push_item_definition_full(lua_State *L, const ItemDefinition &i)
}
push_groups(L, i.groups);
lua_setfield(L, -2, "groups");
lua_newtable(L);
push_soundspec(L, i.sound_place);
lua_setfield(L, -2, "sound_place");
lua_setfield(L, -2, "place");
push_soundspec(L, i.sound_place_failed);
lua_setfield(L, -2, "sound_place_failed");
lua_setfield(L, -2, "place_failed");
lua_setfield(L, -2, "sounds");
lua_pushstring(L, i.node_placement_prediction.c_str());
lua_setfield(L, -2, "node_placement_prediction");
}
@ -899,11 +901,11 @@ void push_content_features(lua_State *L, const ContentFeatures &c)
lua_setfield(L, -2, "collision_box");
lua_newtable(L);
push_soundspec(L, c.sound_footstep);
lua_setfield(L, -2, "sound_footstep");
lua_setfield(L, -2, "footstep");
push_soundspec(L, c.sound_dig);
lua_setfield(L, -2, "sound_dig");
lua_setfield(L, -2, "dig");
push_soundspec(L, c.sound_dug);
lua_setfield(L, -2, "sound_dug");
lua_setfield(L, -2, "dug");
lua_setfield(L, -2, "sounds");
lua_pushboolean(L, c.legacy_facedir_simple);
lua_setfield(L, -2, "legacy_facedir_simple");

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