From 309d71d72dd2749609bc35faca562c74b671876b Mon Sep 17 00:00:00 2001 From: Robert Zenz Date: Thu, 23 Jul 2015 19:47:37 +0200 Subject: [PATCH] Initial commit. --- .gitmodules | 3 + LICENSE | 24 ++ Makefile | 11 + README | 11 + README.md | 1 + deps/utils | 1 + doc/files/mods/spawn_usher/init.html | 94 +++++++ doc/files/mods/spawn_usher/spawnusher.html | 261 +++++++++++++++++++ doc/index.html | 94 +++++++ doc/luadoc.css | 286 +++++++++++++++++++++ mods/spawn_usher/depends.txt | 1 + mods/spawn_usher/init.lua | 32 +++ mods/spawn_usher/spawnusher.lua | 189 ++++++++++++++ mods/utils | 1 + 14 files changed, 1009 insertions(+) create mode 100644 .gitmodules create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 README create mode 120000 README.md create mode 160000 deps/utils create mode 100644 doc/files/mods/spawn_usher/init.html create mode 100644 doc/files/mods/spawn_usher/spawnusher.html create mode 100644 doc/index.html create mode 100644 doc/luadoc.css create mode 100644 mods/spawn_usher/depends.txt create mode 100644 mods/spawn_usher/init.lua create mode 100644 mods/spawn_usher/spawnusher.lua create mode 120000 mods/utils diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..125a12e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "deps/utils"] + path = deps/utils + url = https://github.com/RobertZenz/minetest-australopithecus-utils.git diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1c53c0e --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2014, Robert 'Bobby' Zenz +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c417d70 --- /dev/null +++ b/Makefile @@ -0,0 +1,11 @@ +doc := doc + +all: doc + +clean: + $(RM) -R $(doc) + +.PHONY: doc +doc: + luadoc -d $(doc) mods/spawn_usher + diff --git a/README b/README new file mode 100644 index 0000000..d4a53db --- /dev/null +++ b/README @@ -0,0 +1,11 @@ +minetest-australopithecus-spawn-usher +===================================== + +A simple system that corrects the spawn of players without knowing anything +about the mapgen that is used. + +To activate the system, add it to your `depends.txt` and call this in your +`init.lua.` + + spawnusher.activate() + diff --git a/README.md b/README.md new file mode 120000 index 0000000..100b938 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +README \ No newline at end of file diff --git a/deps/utils b/deps/utils new file mode 160000 index 0000000..2ae4c72 --- /dev/null +++ b/deps/utils @@ -0,0 +1 @@ +Subproject commit 2ae4c72b3d14d74c7b6ac9e919c02164f521b745 diff --git a/doc/files/mods/spawn_usher/init.html b/doc/files/mods/spawn_usher/init.html new file mode 100644 index 0000000..2143f12 --- /dev/null +++ b/doc/files/mods/spawn_usher/init.html @@ -0,0 +1,94 @@ + + + + + Luadocs for mods/spawn_usher/init.lua + + + + + +
+ +
+ +
+
+
+ +
+ + + +
+ +

File mods/spawn_usher/init.lua

+ + + + + + + + + + + + +
+
+ + + + + + + + + + +
+ +
+ +
+

Valid XHTML 1.0!

+
+ +
+ + diff --git a/doc/files/mods/spawn_usher/spawnusher.html b/doc/files/mods/spawn_usher/spawnusher.html new file mode 100644 index 0000000..605e91c --- /dev/null +++ b/doc/files/mods/spawn_usher/spawnusher.html @@ -0,0 +1,261 @@ + + + + + Luadocs for mods/spawn_usher/spawnusher.lua + + + + + +
+ +
+ +
+
+
+ +
+ + + +
+ +

File mods/spawn_usher/spawnusher.lua

+ + + + + + + +

Functions

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
spawnusher.activate (require_air_bubble_size, retry_time)Activates the spawn usher system.
spawnusher.is_air_bubble (start_pos)Tests if the given position is an air bubble big enough.
spawnusher.move_later (player, current_pos)Schedules the player to be moved later.
spawnusher.move_player (player)Moves the player to a safe location.
spawnusher.move_players ()Move all players that could not be placed so far.
+ + + + + + +
+
+ + + + +

Functions

+
+ + + +
spawnusher.activate (require_air_bubble_size, retry_time)
+
+Activates the spawn usher system. + + +

Parameters

+
    + +
  • + require_air_bubble_size: Optional. The size/height of the bubble of air that is required for the player to spawn. Defaults to 2. +
  • + +
  • + retry_time: Optional. This is the time that passes between tries to place to the player. +
  • + +
+ + + + + + + + +
+ + + + +
spawnusher.is_air_bubble (start_pos)
+
+Tests if the given position is an air bubble big enough. + + +

Parameters

+
    + +
  • + start_pos: The position at which to check. +
  • + +
+ + + + + + +

Return value:

+true if at the given position is an air bubble big enough. + + + +
+ + + + +
spawnusher.move_later (player, current_pos)
+
+Schedules the player to be moved later. Also moves the player to the given position. + + +

Parameters

+
    + +
  • + player: The player object. +
  • + +
  • + current_pos: The current position to which the player will be moved. +
  • + +
+ + + + + + + + +
+ + + + +
spawnusher.move_player (player)
+
+Moves the player to a safe location. + + +

Parameters

+
    + +
  • + player: The player object. +
  • + +
+ + + + + + + + +
+ + + + +
spawnusher.move_players ()
+
+Move all players that could not be placed so far. + + + + + + + + + +
+ + +
+ + + + + + + +
+ +
+ +
+

Valid XHTML 1.0!

+
+ +
+ + diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 0000000..20f3df3 --- /dev/null +++ b/doc/index.html @@ -0,0 +1,94 @@ + + + + + Luadocs Index + + + + + +
+ +
+ +
+
+
+ +
+ + + +
+ + + + + + + +

Files

+ + + + + + + + + + + + + +
mods/spawn_usher/init.lua
mods/spawn_usher/spawnusher.lua
+ + +
+ +
+ +
+

Valid XHTML 1.0!

+
+ +
+ + diff --git a/doc/luadoc.css b/doc/luadoc.css new file mode 100644 index 0000000..bc0f98a --- /dev/null +++ b/doc/luadoc.css @@ -0,0 +1,286 @@ +body { + margin-left: 1em; + margin-right: 1em; + font-family: arial, helvetica, geneva, sans-serif; + background-color:#ffffff; margin:0px; +} + +code { + font-family: "Andale Mono", monospace; +} + +tt { + font-family: "Andale Mono", monospace; +} + +body, td, th { font-size: 11pt; } + +h1, h2, h3, h4 { margin-left: 0em; } + +textarea, pre, tt { font-size:10pt; } +body, td, th { color:#000000; } +small { font-size:0.85em; } +h1 { font-size:1.5em; } +h2 { font-size:1.25em; } +h3 { font-size:1.15em; } +h4 { font-size:1.06em; } + +a:link { font-weight:bold; color: #004080; text-decoration: none; } +a:visited { font-weight:bold; color: #006699; text-decoration: none; } +a:link:hover { text-decoration:underline; } +hr { color:#cccccc } +img { border-width: 0px; } + + +h3 { padding-top: 1em; } + +p { margin-left: 1em; } + +p.name { + font-family: "Andale Mono", monospace; + padding-top: 1em; + margin-left: 0em; +} + +blockquote { margin-left: 3em; } + +pre.example { + background-color: rgb(245, 245, 245); + border-top-width: 1px; + border-right-width: 1px; + border-bottom-width: 1px; + border-left-width: 1px; + border-top-style: solid; + border-right-style: solid; + border-bottom-style: solid; + border-left-style: solid; + border-top-color: silver; + border-right-color: silver; + border-bottom-color: silver; + border-left-color: silver; + padding: 1em; + margin-left: 1em; + margin-right: 1em; + font-family: "Andale Mono", monospace; + font-size: smaller; +} + + +hr { + margin-left: 0em; + background: #00007f; + border: 0px; + height: 1px; +} + +ul { list-style-type: disc; } + +table.index { border: 1px #00007f; } +table.index td { text-align: left; vertical-align: top; } +table.index ul { padding-top: 0em; margin-top: 0em; } + +table { + border: 1px solid black; + border-collapse: collapse; + margin-left: auto; + margin-right: auto; +} +th { + border: 1px solid black; + padding: 0.5em; +} +td { + border: 1px solid black; + padding: 0.5em; +} +div.header, div.footer { margin-left: 0em; } + +#container +{ + margin-left: 1em; + margin-right: 1em; + background-color: #f0f0f0; +} + +#product +{ + text-align: center; + border-bottom: 1px solid #cccccc; + background-color: #ffffff; +} + +#product big { + font-size: 2em; +} + +#product_logo +{ +} + +#product_name +{ +} + +#product_description +{ +} + +#main +{ + background-color: #f0f0f0; + border-left: 2px solid #cccccc; +} + +#navigation +{ + float: left; + width: 18em; + margin: 0; + vertical-align: top; + background-color: #f0f0f0; + overflow:visible; +} + +#navigation h1 { + background-color:#e7e7e7; + font-size:1.1em; + color:#000000; + text-align:left; + margin:0px; + padding:0.2em; + border-top:1px solid #dddddd; + border-bottom:1px solid #dddddd; +} + +#navigation ul +{ + font-size:1em; + list-style-type: none; + padding: 0; + margin: 1px; +} + +#navigation li +{ + text-indent: -1em; + margin: 0em 0em 0em 0.5em; + display: block; + padding: 3px 0px 0px 12px; +} + +#navigation li li a +{ + padding: 0px 3px 0px -1em; +} + +#content +{ + margin-left: 18em; + padding: 1em; + border-left: 2px solid #cccccc; + border-right: 2px solid #cccccc; + background-color: #ffffff; +} + +#about +{ + clear: both; + margin: 0; + padding: 5px; + border-top: 2px solid #cccccc; + background-color: #ffffff; +} + +@media print { + body { + font: 12pt "Times New Roman", "TimeNR", Times, serif; + } + a { font-weight:bold; color: #004080; text-decoration: underline; } + + #main { background-color: #ffffff; border-left: 0px; } + #container { margin-left: 2%; margin-right: 2%; background-color: #ffffff; } + + #content { margin-left: 0px; padding: 1em; border-left: 0px; border-right: 0px; background-color: #ffffff; } + + #navigation { display: none; + } + pre.example { + font-family: "Andale Mono", monospace; + font-size: 10pt; + page-break-inside: avoid; + } +} + +table.module_list td +{ + border-width: 1px; + padding: 3px; + border-style: solid; + border-color: #cccccc; +} +table.module_list td.name { background-color: #f0f0f0; } +table.module_list td.summary { width: 100%; } + +table.file_list +{ + border-width: 1px; + border-style: solid; + border-color: #cccccc; + border-collapse: collapse; +} +table.file_list td +{ + border-width: 1px; + padding: 3px; + border-style: solid; + border-color: #cccccc; +} +table.file_list td.name { background-color: #f0f0f0; } +table.file_list td.summary { width: 100%; } + + +table.function_list +{ + border-width: 1px; + border-style: solid; + border-color: #cccccc; + border-collapse: collapse; +} +table.function_list td +{ + border-width: 1px; + padding: 3px; + border-style: solid; + border-color: #cccccc; +} +table.function_list td.name { background-color: #f0f0f0; } +table.function_list td.summary { width: 100%; } + + +table.table_list +{ + border-width: 1px; + border-style: solid; + border-color: #cccccc; + border-collapse: collapse; +} +table.table_list td +{ + border-width: 1px; + padding: 3px; + border-style: solid; + border-color: #cccccc; +} +table.table_list td.name { background-color: #f0f0f0; } +table.table_list td.summary { width: 100%; } + +dl.function dt {border-top: 1px solid #ccc; padding-top: 1em;} +dl.function dd {padding-bottom: 1em;} +dl.function h3 {padding: 0; margin: 0; font-size: medium;} + +dl.table dt {border-top: 1px solid #ccc; padding-top: 1em;} +dl.table dd {padding-bottom: 1em;} +dl.table h3 {padding: 0; margin: 0; font-size: medium;} + +#TODO: make module_list, file_list, function_list, table_list inherit from a list + diff --git a/mods/spawn_usher/depends.txt b/mods/spawn_usher/depends.txt new file mode 100644 index 0000000..9487075 --- /dev/null +++ b/mods/spawn_usher/depends.txt @@ -0,0 +1 @@ +utils diff --git a/mods/spawn_usher/init.lua b/mods/spawn_usher/init.lua new file mode 100644 index 0000000..50351f5 --- /dev/null +++ b/mods/spawn_usher/init.lua @@ -0,0 +1,32 @@ +--[[ +Copyright (c) 2015, Robert 'Bobby' Zenz +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--]] + + +-- Get the base path. +local base_path = minetest.get_modpath(minetest.get_current_modname()) + +dofile(base_path .. "/spawnusher.lua") + diff --git a/mods/spawn_usher/spawnusher.lua b/mods/spawn_usher/spawnusher.lua new file mode 100644 index 0000000..5dcd92d --- /dev/null +++ b/mods/spawn_usher/spawnusher.lua @@ -0,0 +1,189 @@ +--[[ +Copyright (c) 2015, Robert 'Bobby' Zenz +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +--]] + + +--- Spawn usher is a system that allows to correct the spawn position of players +-- without knowing anything about the mapgen. +-- +-- The system will register callbacks for newplayer and respawnplayer and will +-- try to find an air bubble, either upwards or downwards, which the player can +-- fit into. If an air bubble is found, the player will be moved there. If +-- the block is not loaded, it will be tried again after a certain amount of +-- time. +-- +-- The only function that should be called from clients is activate. +spawnusher = { + players = List:new(), + required_bubble_size = 2, + retry_time = 0.5, + scheduled = false +} + + +--- Activates the spawn usher system. +-- +-- @param require_air_bubble_size Optional. The size/height of the bubble of air +-- that is required for the player to spawn. +-- Defaults to 2. +-- @param retry_time Optional. This is the time that passes between tries to +-- place to the player. +function spawnusher.activate(require_air_bubble_size, retry_time) + minetest.register_on_newplayer(spawnusher.move_player) + minetest.register_on_respawnplayer(spawnusher.move_player) +end + +--- Tests if the given position is an air bubble big enough. +-- +-- @param start_pos The position at which to check. +-- @return true if at the given position is an air bubble big enough. +function spawnusher.is_air_bubble(start_pos) + local pos = { + x = start_pos.x, + y = start_pos.y, + z = start_pos.z + } + + for counter = 1, spawnusher.required_bubble_size, 1 do + pos.y = pos.y + 1 + + if minetest.get_node(pos).name ~= "air" then + return false + end + end + + return true +end + +--- Schedules the player to be moved later. Also moves the player to the given +-- position. +-- +-- @param player The player object. +-- @param current_pos The current position to which the player will be moved. +function spawnusher.move_later(player, current_pos) + player:setpos(current_pos) + + spawnusher.players:add(player) + + -- Override the physics of the player to make sure that the player does + -- not fall while we wait. + player:set_physics_override({ + speed = 0, + jump = 0, + gravity = 0, + sneak = false, + sneak_glitch = false + }) + + if not spawnusher.scheduled then + spawnusher.scheduled = true + + minetest.after(spawnusher.retry_time, spawnusher.move_players) + end +end + +--- Moves the player to a safe location. +-- +-- @param player The player object. +function spawnusher.move_player(player) + local pos = player:getpos() + + -- Could be while true, but at least this is halfway sane. + while mathutil.in_range(pos.y, -31000, 31000) do + local current = minetest.get_node(pos).name + + if current ~= "air" and current ~= "ignore" then + -- The current node is neither air nor ignore, that means it + -- is "solid", so we walk upwards looking for air. + pos.y = pos.y + 1 + elseif current == "air" then + -- The current node is air, now we will check if the node below it + -- is also air, if yes we will move downwards, if not we will check + -- if here is an air bubble. + local beneath_pos = { + x = pos.x, + y = pos.y - 1, + z = pos.z + } + + local beneath_node = minetest.get_node(beneath_pos).name + + if beneath_node == "air" then + -- The node below is air, move two downwards looking for + -- a "solid" node. + pos.y = pos.y - 2 + elseif beneath_node == "ignore" then + -- The node below is ignore, means we will have to try again + -- later. + spawnusher.move_later(player, pos) + return + elseif spawnusher.is_air_bubble(pos) then + -- Awesome! Place the user here. + player:setpos(pos) + + -- Reset the physics override. + player:set_physics_override({ + speed = 1, + jump = 1, + gravity = 1, + sneak = true, + sneak_glitch = true + }) + + return + else + -- The node beneath is neither air nor ignore and there is no + -- air bubble big enough, lets go upwards and see if that + -- helps. + pos.y = pos.y + 2 + end + elseif current == "ignore" then + -- The current node is ignore, which means we need to retry later. + spawnusher.move_later(player, pos) + return + end + end +end + +--- Move all players that could not be placed so far. +function spawnusher.move_players() + -- Copy the list to make sure that no one adds a player while we iterate + -- over it. Though, I'm not sure if that is actually possible, but the Java + -- programmer does not stop to scream "race condition" without this. + local to_move_players = spawnusher.players + spawnusher.players = List:new() + + to_move_players:foreach(function(player, index) + spawnusher.move_player(player) + end) + + -- If there are still players that could not be placed, schedule it again. + if spawnusher.players:size() > 0 then + minetest.after(spawnusher.retry_time, spawnusher.move_players) + else + spawnusher.scheduled = false + end +end + diff --git a/mods/utils b/mods/utils new file mode 120000 index 0000000..4c431f4 --- /dev/null +++ b/mods/utils @@ -0,0 +1 @@ +../deps/utils/utils \ No newline at end of file