Initial checkin.

This commit is contained in:
Auke Kok 2017-01-25 23:06:00 -08:00
commit 475ce277fd
41 changed files with 675 additions and 0 deletions

1
game.conf Normal file
View File

@ -0,0 +1 @@
name = Inside The Box

22
license.md Normal file
View File

@ -0,0 +1,22 @@
(C) 2016 Auke Kok <sofar@foo-projects.org>
Licensing Terms and Conditions
==============================
ATWT is licensed permissively, generally under the MIT-feh license
(https://spdx.org/licenses/MIT-feh.html) for all ATWT code
components. Artwork is generally CC-BY-4.0.
ATWT contains code and artwork that is borrowed from other mods and may
be licensed under different license terms. You should confirm that your
use of the code and artwork is compatible with these licenses. These
licenses are stated in the subfolders and files of these components
where relevant.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

90
mods/db/init.lua Normal file
View File

@ -0,0 +1,90 @@
--[[
sqlite backend for insidethebox
This backend stores various persistent world data bits that are
not properly stored by the minetest engine. This mod provides both
persistent and performant data storage for the itb game until a
better solution exists.
Major data storage parts in this db:
- players, player scores
No player metadata storage exists currently. Only HP and air
are stored in player data. We lack storage for things like
skin choice, stamina, RPG points and skills, etc.
- box data
--]]
local world_path = minetest.get_worldpath()
local sqlite3 = require("lsqlite3")
local itb_db = sqlite3.open(world_path .. "/itb.sqlite")
if not itb_db then
assert("lsqlite3 not available or non-functional. Please use e.g. luarocks to install lsqlite3")
end
-- we require these tables to exist:
assert(itb_db:exec[[
CREATE TABLE box (id INTEGER PRIMARY KEY, data BLOB);
CREATE TABLE series (id INTEGER PRIMARY KEY, name TEXT, meta BLOB);
CREATE TABLE series_box (series_id INTEGER, box_id INTEGER);
CREATE TABLE player (id INTEGER PRIMARY KEY, name TEXT, meta BLOB);
CREATE TABLE points (player_id INTEGER, score REAL, type TEXT, box_id INTEGER);
]])
-- table structure and content
--[[
box table: Contain the storage of the box content (not metadata) so all blocks. (one-to-one)
- id: box identifier
- data: box contents (nodes)
series: Contains existing series
- id: series ID
- name: name of the series
- meta: misc data
series_box: maps boxes into series (many-to-many)
- series_id: series ID
- box_id: box ID
player: player info
- id: player number
- name: player name
- meta: random player data bits
score: player and box score data
- player_id: player id
- score: score value
- type: score type (e.g. reviewed a box)
- box: associated box ID
--]]
db = {}
function db.player_get_meta(name)
for row in itb_db:nrows("SELECT meta FROM player WHERE name = '" .. name .. "';") do
return minetest.parse_json(row.meta)
end
print("no such player in db", name)
return nil
end
function db.player_put_meta(name, meta)
local r = itb_db:exec("REPLACE INTO player_meta (name, meta) VALUES ('" .. name .. "', '" ..
minetest.write_json(meta) .. "');")
if not r then
print("error writing")
return false
else
return true
end
end
minetest.register_on_shutdown(function()
itb_db:close()
end)

11
mods/mg/init.lua Normal file
View File

@ -0,0 +1,11 @@
--[[
mapgen - none!
--]]
-- disable all mapgens
minetest.register_on_mapgen_init(function(parms)
minetest.set_mapgen_params({mgname = "singlenode", flags = "nolight", flagmask = "nolight"})
end)

83
mods/nodes/init.lua Normal file
View File

@ -0,0 +1,83 @@
--[[
nodes.lua - basic node blocks for Inside The Box
]]--
-- table format:
-- [1] name, also used for texture
-- [2] true for stair/slab
-- [3] tool if diggable version needs to be added
-- [4] color versions?
local nodes = {
{"bricks_clay", true, "pickaxe"},
{"bricks_limestone", true, "pickaxe"},
{"bricks_marble", true, "pickaxe"},
{"bricks_sandstone", true, "pickaxe"},
{"bricks_stone", true, "pickaxe"},
{"cobble", true, "pickaxe"},
{"cobble_moss", true, "pickaxe"},
{"limestone", true, "pickaxe"},
{"marble", true, "pickaxe"},
{"sandstone", true, "pickaxe"},
{"stone", true, "pickaxe"},
{"stone_moss", true, "pickaxe"},
{"glass", false, "pickaxe"},
{"bronze", false, "pickaxe"},
{"gold", false, "pickaxe"},
{"iron", false, "pickaxe"},
{"clay", false, "shovel"},
{"dirt", false, "shovel"},
{"gravel", false, "shovel"},
{"sand", false, "shovel"},
{"trunk_light", false, "axe"},
{"trunk_medium", false, "axe"},
{"trunk_dark", false, "axe"},
{"leaves_light", false, "axe"},
{"leaves_medium", false, "axe"},
{"leaves_dark", false, "axe"},
{"wood_dark", true, "axe"},
{"wood_light", true, "axe"},
{"wood_medium", true, "axe"},
{"grass", false, false},
{"wool_*", false, false},
}
for _, v in pairs(nodes) do
local groups = {}
if v[3] then
groups = {[v[3]] = 3}
end
minetest.register_node(":a:" .. v[1], {
Description = v[1],
tiles = {v[1] .. ".png"},
groups = groups,
})
end
-- diggable stuff
-- panes
-- iron_pane
-- glass_pane
-- walls
-- cobble_wall
-- cobble_moss_wall
-- special nodes
-- water
-- lava
-- tnt
-- fire
-- fire_permanent
-- chests:
-- empty (fake) chest
-- chest-with-key
-- chest-with-tool

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 629 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 773 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 919 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 572 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 471 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 506 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 724 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 711 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 503 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 622 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 B

48
mods/tools/init.lua Normal file
View File

@ -0,0 +1,48 @@
-- hand tool
minetest.register_item(":", {
type = "none",
tool_capabilities = {
-- can't pick up any node by hand
groupcaps = {},
},
})
-- node tools
minetest.register_tool(":a:shovel", {
description = "A Shovel",
inventory_image = "shovel.png",
tool_capabilities = {
groupcaps = {
shovel = {
times = {[1] = 3, [2] = 3, [3] = 3},
},
},
},
})
minetest.register_tool(":a:axe", {
description = "An Axe",
inventory_image = "axe.png",
tool_capabilities = {
groupcaps = {
axe = {
times = {[1] = 3, [2] = 3, [3] = 3},
},
},
},
})
minetest.register_tool(":a:pickaxe", {
description = "A Pickaxe",
inventory_image = "pickaxe.png",
tool_capabilities = {
groupcaps = {
pickaxe = {
times = {[1] = 3, [2] = 3, [3] = 3},
},
},
},
})
minetest.register_tool(":a:sword", {})
minetest.register_tool(":a:flint", {})

BIN
mods/tools/textures/axe.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 255 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

107
mods/torches/init.lua Normal file
View File

@ -0,0 +1,107 @@
--[[
Torch mod - formerly mod "Torches"
======================
(c) Copyright BlockMen (2013-2015)
(C) Copyright sofar <sofar@foo-projects.org> (2016)
This mod changes the default torch drawtype from "torchlike" to "mesh",
giving the torch a three dimensional appearance. The mesh contains the
proper pixel mapping to make the animation appear as a particle above
the torch, while in fact the animation is just the texture of the mesh.
License:
~~~~~~~~
(c) Copyright BlockMen (2013-2015)
Textures and Meshes/Models:
CC-BY 3.0 BlockMen
Note that the models were entirely done from scratch by sofar.
Code:
Licensed under the GNU LGPL version 2.1 or higher.
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;
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
See LICENSE.txt and http://www.gnu.org/licenses/lgpl-2.1.txt
--]]
minetest.register_node("torches:torch", {
description = "Torch",
drawtype = "mesh",
mesh = "torch_floor.obj",
inventory_image = "default_torch_on_floor.png",
wield_image = "default_torch_on_floor.png",
tiles = {{
name = "default_torch_on_floor_animated.png",
animation = {type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 3.3}
}},
paramtype = "light",
paramtype2 = "wallmounted",
sunlight_propagates = true,
walkable = false,
liquids_pointable = false,
light_source = 13,
groups = {choppy=2, dig_immediate=3, flammable=1, attached_node=1, torch=1},
drop = "torches:torch",
selection_box = {
type = "wallmounted",
wall_bottom = {-1/8, -1/2, -1/8, 1/8, 2/16, 1/8},
},
on_place = function(itemstack, placer, pointed_thing)
local under = pointed_thing.under
local node = minetest.get_node(under)
local def = minetest.registered_nodes[node.name]
if def and def.on_rightclick and
((not placer) or (placer and not placer:get_player_control().sneak)) then
return def.on_rightclick(under, node, placer, itemstack,
pointed_thing) or itemstack
end
local above = pointed_thing.above
local wdir = minetest.dir_to_wallmounted(vector.subtract(under, above))
local fakestack = itemstack
if wdir == 0 then
return itemstack
elseif wdir == 1 then
fakestack:set_name("torches:torch")
else
fakestack:set_name("torches:torch_wall")
end
itemstack = minetest.item_place(fakestack, placer, pointed_thing, wdir)
itemstack:set_name("torches:torch")
return itemstack
end
})
minetest.register_node("torches:torch_wall", {
drawtype = "mesh",
mesh = "torch_wall.obj",
tiles = {{
name = "default_torch_on_floor_animated.png",
animation = {type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 3.3}
}},
paramtype = "light",
paramtype2 = "wallmounted",
sunlight_propagates = true,
walkable = false,
light_source = 13,
groups = {choppy=2, dig_immediate=3, flammable=1, not_in_creative_inventory=1, attached_node=1, torch=1},
drop = "torches:torch",
selection_box = {
type = "wallmounted",
wall_side = {-1/2, -1/2, -1/8, -1/8, 1/8, 1/8},
},
})

View File

@ -0,0 +1,50 @@
# Blender v2.76 (sub 11) OBJ File: 'torch_floor.blend'
# www.blender.org
mtllib torch_floor.mtl
o Cube_Cube.001
v 0.062500 0.062500 -0.062500
v 0.062500 -0.500000 -0.062500
v 0.062500 0.062500 0.062500
v 0.062500 -0.500000 0.062500
v -0.062500 0.062500 -0.062500
v -0.062500 -0.500000 -0.062500
v -0.062500 0.062500 0.062500
v -0.062500 -0.500000 0.062500
v -0.353553 -0.500000 0.353553
v -0.353553 0.500000 0.353553
v 0.353553 -0.500000 -0.353553
v 0.353553 0.500000 -0.353553
v -0.353553 -0.500000 -0.353553
v 0.353553 -0.500000 0.353553
v -0.353553 0.500000 -0.353553
v 0.353553 0.500000 0.353553
vt 0.562500 0.500000
vt 0.562500 0.625000
vt 0.437500 0.625000
vt 0.437500 0.500000
vt 0.437500 0.000000
vt 0.562500 0.000000
vt 0.562500 0.125000
vt 0.437500 0.125000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 0.000000 -1.000000
vn 1.000000 0.000000 0.000000
vn -0.707100 0.000000 -0.707100
vn -0.707100 -0.000000 0.707100
g Cube_Cube.001_Cube_Cube.001_Material.001
usemtl Material.001
s off
f 3/1/1 1/2/1 5/3/1 7/4/1
f 8/5/1 4/6/1 2/7/1 6/8/1
f 3/2/2 4/6/2 8/5/2 7/3/2
f 1/3/3 3/2/3 4/6/3 2/5/3
f 5/2/2 1/3/2 2/5/2 6/6/2
f 7/3/3 8/5/3 6/6/3 5/2/3
g Cube_Cube.001_Cube_Cube.001_Material.002
usemtl Material.002
f 9/9/4 10/10/4 12/11/4 11/12/4
f 13/12/5 14/9/5 16/10/5 15/11/5

View File

@ -0,0 +1,64 @@
# Blender v2.76 (sub 11) OBJ File: 'torch_wall.blend'
# www.blender.org
mtllib torch_wall.mtl
o Cube_Cube.001
v 0.062469 -0.195248 0.023570
v 0.062469 -0.476498 -0.463570
v 0.062469 -0.303502 0.086070
v 0.062469 -0.584752 -0.401070
v -0.062531 -0.195248 0.023570
v -0.062531 -0.476498 -0.463570
v -0.062531 -0.303502 0.086070
v -0.062531 -0.584752 -0.401070
v -0.353584 -0.613553 0.022500
v -0.353584 -0.613553 0.460000
v 0.353522 0.093553 0.022500
v 0.353522 0.093553 0.460000
v -0.353584 0.093553 0.022500
v 0.353522 -0.613553 0.022500
v -0.353584 0.093553 0.460000
v 0.353522 -0.613553 0.460000
v 0.353553 0.056811 -0.121957
v 0.353553 -0.224439 -0.609096
v -0.353553 -0.555561 0.231596
v -0.353553 -0.836811 -0.255543
v -0.353553 0.056811 -0.121957
v -0.353553 -0.224439 -0.609096
v 0.353553 -0.555561 0.231596
v 0.353553 -0.836811 -0.255543
vt 0.562500 0.500000
vt 0.562500 0.625000
vt 0.437500 0.625000
vt 0.437500 0.500000
vt 0.437500 0.000000
vt 0.562500 0.000000
vt 0.562500 0.125000
vt 0.437500 0.125000
vt 0.000000 0.562500
vt 0.000000 -0.000000
vt 1.000000 0.000000
vt 1.000000 0.562500
vt 1.000000 1.000000
vt 0.000000 1.000000
vn -0.000000 0.500000 0.866000
vn -0.000000 0.866000 -0.500000
vn 1.000000 0.000000 0.000000
vn -0.707100 0.612400 -0.353600
vn -0.707100 -0.612400 0.353600
vn -0.707100 0.707100 -0.000000
vn -0.707100 -0.707100 -0.000000
g Cube_Cube.001_Cube_Cube.001_Material.001
usemtl Material.001
s off
f 3/1/1 1/2/1 5/3/1 7/4/1
f 8/5/1 4/6/1 2/7/1 6/8/1
f 3/2/2 4/6/2 8/5/2 7/3/2
f 1/3/3 3/2/3 4/6/3 2/5/3
f 5/2/2 1/3/2 2/5/2 6/6/2
f 7/3/3 8/5/3 6/6/3 5/2/3
f 17/9/4 18/10/4 20/11/4 19/12/4
f 21/9/5 22/10/5 24/11/5 23/12/5
g Cube_Cube.001_Cube_Cube.001_Material.002
usemtl Material.002
f 9/12/6 10/13/6 12/14/6 11/9/6
f 13/9/7 14/12/7 16/13/7 15/14/7

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 B

199
readme.md Normal file
View File

@ -0,0 +1,199 @@
Inside The Box
==============
A multi-player puzzle solving and creation game for minetest.
The game is meant to be run as a multiplayer puzzle-creating server.
Players can connect and either play boxes, or create new ones.
The basic concept of the game is boxes. This is an area in which the
player needs to find one or more objectives (keys). The player then
needs to bring these objectives to a slot (keyhole). Once all the
secrets have been found and returned, an exit opens that allows the
player out, completing the puzzle box.
This minetest game is strongly inspired by the "parcels" MC player
map. I did not want to replicate the map itself, even though the
conversion tools exist to mostly do this, but more because giving
it a multiplayer spin sounds much more appealing, and a far better
tribute to the map itself. The possibility of having hundreds of
puzzle boxes created also sounds much more appealing.
## Playing
A player can choose to play available boxes. Selecting an available
level to play will create a private copy of the level box and teleport
the player to the starting point of the level. The starting point is
in a hallway or entry room. There can be some clues left, and there
should be some information of the builder, and perhaps difficulty,
time spent by players in the level, popularity, rating information.
From the hallway the player should have some visual on the inside of
the box. This will help players recognize boxes easier so they can
skip ones they have played before, or gauge difficulty, etc..
The player moves through a door to the level. This may trigger a
teleport to a starting location, or not. On the side of the wall
somewhere is displayed a large number corresponding with the box ID.
In the box there is a collection area. In the collection area there
are 1 or more collection slots. The slots all require to be filled
with a "key" item. These items are found anywhere in the level. The
player picks up the item and brings them to the collection slots.
The box largely contains unbreakable nodes. The box may contain certain
digging tools to break nodes in the box (e.g. an axe to break certain
wood blocks, a pickaxe to break stone blocks, or a shovel to dig
sand blocks). The player may be forced to use these tools to reach
new areas in the box, or to create bridges or ladders to climb up.
The player can not physically exit the box. The box is surrounded by
unbreakable blocks uncluding invisible ceilings where needed. The
player has an "escape" button that, when used, removes the player
from the game and returns the player to the general lobby.
The player may take damage in the box through falling or lava
or cacti, or other methods. The player recovers lost health somewhat
quickly, but some errors may be deadly.
Once the player collects all the needed items, an exit doorway opens
or becomes reachable. The player moves through the exit doorway and
ends in an exit lobby/hallway.
In the exit lobby/hallway, the player can leave feedback or ranking
votes for the level. Last, there is a method for the player to return
to the general lobby. The player also receives a ranking/score
about their performance in the box itself, but only on the first
attempt. The performance includes time spent in the box, times died,
and damage taken.
## Constructing
Players can construct new boxes. They do this by entering a pristine
box that is created on the fly for them. In this box, the player
receives full editing privileges. The player can construct and modify
the collection point, place the secrets, place any node or liquid,
fire, TNT or other element provided to them.
The entry hallway has a spot for a sign hint that the constructor can
modify. It also has an interface for modifying the box parameters,
such as name and size, and variations such as entry/exit gate locations
and collection point stations.
## Points
Points act as a measure of commitment. The more actions a player does
that are in the interest of the community, the more points a player
gains. These points can be exchanged for privileges.
For each level played and rated the player earns points.
A player may lose points for dying a lot in boxes, or dying a lot
in boxes in general. A player may also lose points for other actions,
such as going idle in a box, never rating boxes or always rating
boxes the same level of hearts. This lowers the input their
actions they have into the system. E.g. if a player continuously
dies many times in a few boxes, their scoring values are reduced
in the averages by a factor, reducing their impact on ratings.
Privileges that can be reached through gaining points are:
- ability to create new boxes
- ability to submit more boxes for trials
- ability to choose larger level boxes
- moderation of boxes that are eligible for moderation
- moderation of other players with a lower point level
## Ranking/Rating
Boxes are rated/ranked per players. Good boxes are promoted to box
series that can be accessed from the main lobby easily ("play this
months' top boxes") and ultimately make it in to a list of ultimate
box boxes. This level series of boxes will only ever grow, and the
player can track his progress through these series and continue at
any point left.
A Random box can be chosen from the lobby.
A player can test trial boxes. Trial boxes are not yet finished
but submitted by the creator for review. The player can rate and
provide comments ("can't continue", "fell and stuck in a hole",
"too easy") to the creator so they may modify the box.
Points are scored for time spent. More time equals more points, except
when players are leaving before finishing, which subtracts points.
Points are scored for player rating. 0-5 hearts can be given.
Points are scored for damage taken by players, but subtracted for
multiple deaths of the same player. In general, a player dying once
in a level is OK, as long as it is instructional to the player and
they understand afterwards how to overcome an obstacle. Subsequent
deaths of a player may subtract points (note: need to account for
trolling here).
## Series
Series are curated boxes that can be played in succession. A
series of boxes grows one box at a time (interval to be
determined) and the newest box is always the top ranked box that is
not yet in that series. It may be that a fixed amount of scoring points
needs to be gained before a box can be promoted to a series.
- Master Series: A series of best rated boxes over time. These are
boxes that have exceeded a certain amount of points. They are
permanently added to the master series forever.
- The trial Series: Unranked and unfinished boxes. These are marked
"can be played" but "review requested". Players can recieve extra
points when they play and rank these.
- The Newest Series: Best ranked boxes in a certain time frame. These
are up and coming boxes that are relatively new, but have been past
review already (no longer "review requested"). Players are encouraged
to play these boxes every week and rate.
## Other box choices
These are suggested game play modes to vary game play a bit.
- Random rated or Random unrated box: Play a random box.
- Box Race: Several players each attempt the same box separately.
- Coop: Try boxes together with another player.
## Roles
- Admin: reserved role for a player that can always moderate players
and/or boxes, ban/kick players, edit all boxes, remove boxes.
- Moderator: may suspend players, may suspend boxes.
- Player: no privileges.
## Technology
Inside The Box uses lsqlite3 to store player, box, series and score
data. This assures that large amounts of data can be stored easily
with reasonably good performance and reliability.
For creation and playing of maps, a virtual `plot` is reserved per
player in a random location on the map away from the static lobby. This
reservation is destroyed when the box is no longer needed.
The box contents are stored in the sqlite database and restored for
each player that attempts to play the box. This assures that multiple
players can separately try the same box without conflicts.
The sqlite backend also allows efficient storing and retrieval of
scores for players or boxes and creating ranks, modifying or inspecting
state of boxes or players.
Placement of boxes will use VoxelManips as well as additional metadata
where needed to connect dynamic elements inside the box. These are
subsequently connected to assure proper functioning of the box.