Initial commit

master
shivajiva101 2019-08-12 00:58:45 +01:00
commit 4be0a9b86d
51 changed files with 4002 additions and 0 deletions

124
ReadMe.md Normal file
View File

@ -0,0 +1,124 @@
## Gamehub Modpack
### for minetest by shivajiva101@hotmail.com
This mod provides a hub concept for sub games within a Minetest world.
Designed to handle privileges, inventory, transport and rewards.
Adding nodes for game stages and game completion, menus, commands,
shop and jail features. It uses and extends other mods API's to create a simple but powerful concept.
You *just* need to create the content! To help you start there are a few
example games in the /schems folder you can add. You have the ability to load, save and share the games you create! Easy player access to the menu and admin tools to simplify the game creation process.
Mod dependencies:
* default
* areas
* maptools
* unified inventory
* worldedit
Lua dependencies:
* lsqlite3 (http://lua.sqlite.org/)
I suggest you use luarocks (https://luarocks.org/) to install lsqlite3 with the command:
``sudo apt install luarocks``
then you can install lsqlite3 with the following command:
``luarocks install lsqlite3``
This mod should be added to secure.trusted in your minetest.conf before starting the server.
### Privileges
```
hub_admin -- games admin
hub_mod -- server moderator
```
### Admin Commands
```
/hub <option>
Options:
add -- display add game form
delete <area_id> [true] -- delete a game [remove]
edit <game> -- display form to edit game
load <name> [new_name] -- load a saved game [used to duplicate]
protect <area_id> [true] -- add pclip & kill nodes to an area [remove]
save <area_id> -- save a game
stage -- add a stage destination to a game
unstage <game> <num> -- remove a stage destination
```
### Moderator Commands
```
/info <player> -- display players current game
```
### Player Commands
```
/p -- display game menu to player
/q -- quit current game
/s -- display statistics
```
### Adding an example game
A few examples are provided in the mods /schems folder. A saved game consists of a set of 3 files with the same name but different extensions [hub, mts, we]. Check the folder to see the names available to use. Some games have dependencies on frame, signs_lib etc. You should check your server has them enabled before attempting to load them. See readme.md file in the schems folder for more info.
For example to add a game:
* choose a location, preferably above 1000 height
* type ``/hub load Barnyard`` or ``/hub load BunnyHop`` or ``/hub load X-men Rooms``
The game will be inserted into your world and appear as an entry in the players game menu. Yes you read that correctly...a single command will add a functional game!
### Creating a new game in your world
The basic steps to add a game are as follows;
* Choose a location to build the game, preferably away from players access
* Create an area large enough to hold the game using the name you have chosen for the game. This ensures it's protected during the build phase.
* Go to the place you want the player to start from
* Turn and face the direction you want the player to face on arrival and type ``/hub add``
* Fill in form details leaving active *unchecked* and press save
* Build your game using the single cloud node that appears
* Use stage pads if required for getting between different stages of your game (see section below)
* Place reward pad at finish point, right-click it and set the game name
* Type ``/hub protect <area_id>`` where area_id is the id of the area you created in step 2. This command will wrap the area in pclip and line the inside with kill nodes 2 deep.
* Type ``/hub edit <game>`` to modify any details, tick active checkbox and save
The game should now appear in the players game menu.
### Setting stages in your games
If you want multiple stages in your game, you can use stage pads. The mechanism is simple, go to the destination for the pad, look at the view you want a player to see when they arrive, then type ``/hub stage``
you should be informed the stage was added at the current vector. Now you can go back and place the pad, that's it! You have added your first stage.
If for any reason you need to remove a stage you can use ``/hub unstage <stage_number>`` where ``<index>`` refers to the table index, one less than the stage. You must be within the game area, do not execute this command anywhere else!
### Saving games
Use the area ID to save a game, remember it creates 3 files named the same as the area name,
so it's important to think about what you call the area, prior to building a game within it.
* type ``/hub save <area_id>``
3 files will be created in your worlds /schems folder which you can compress as a set to share with your friends and the community.
### Jail
A simple but powerful mechanism is used to jail players and disable their functionality. The jail building is inserted in the bowels of the world, a fitting place for a player finding themselves on the wrong side of the server management team. To jail a player use the command:
``/jail <player> <duration> <reason>``
where ``<player>`` is the players name, ``<duration>`` is the length of time in the same format as sban & xban. For example:
``/jail Steve 1w trolling a staff member ``
this would jail Steve for 1 week and will automatically expire. The hub_mod privilege is required before you can jail players.
To unjail a currently jailed player use the following command:
``/unjail <player>``
jail records are only kept for the duration of the jail sentence and can be viewed using the command:
``/jail_info``
this command also requires the hub_mod privilege so only the server staff have access to the information.
### Shop
The hub admin controls the shop, they have the necessary privilege to add items from the inventory, choosing a selling price, moq and buy back price if required for each item they wish to sell. It provides a method to spend the reward credits and earn more from mining and farming. The shop is accessed via Unified Inventory with the shop icon.
### Credits
See individual credit.txt in the respective folders for further information.
This modpack was inspired by running a Skyblock server and time spent playing with the code, friends who undoubtedly know who they are, plus all the Minetest developers & mod developers contributions that enabled it.
### Status
Functional, not fully tested
THIS MODPACK IS A WIP!

1
description.txt Normal file
View File

@ -0,0 +1 @@
Adds a games hub, jail and shop to your world. Load the examples or create your own mini games and share them with the community.

727
gamehub/commands.lua Normal file
View File

@ -0,0 +1,727 @@
--[[
gamehub mod (C) shivajiva101@hotmail.com 2019
This file is part of gamehub.
gamehub is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
gamehub 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with gamehub. If not, see <https://www.gnu.org/licenses/>.
]]
local ie = gamehub.ie
local MP = minetest.get_modpath(minetest.get_current_modname())
-----------------------
-- Helper Functions --
-----------------------
-- Grant command handler
-- @param caller: player executing the command
-- @param grant_name: player name receiving privs
-- @param grant_priv_str: privileges string
-- @return bool & message
local function handle_grant_command(caller, grant_name, grant_priv_str)
local caller_privs = minetest.get_player_privs(caller)
if not (caller_privs.privs or caller_privs.basic_privs) then
return false, "Your privileges are insufficient."
end
if not minetest.get_auth_handler().get_auth(grant_name) then
return false, "Player " .. grant_name .. " does not exist."
end
local grantprivs = minetest.string_to_privs(grant_priv_str)
local privs = minetest.get_player_privs(grant_name)
local privs_unknown = ""
local basic_privs = minetest.string_to_privs(
minetest.setting_get("basic_privs") or "interact,shout")
if grant_priv_str == "all" then
grantprivs = minetest.registered_privileges
end
for priv, _ in pairs(grantprivs) do
if not basic_privs[priv] and
not minetest.check_player_privs(caller, {privs=true}) then
return true, "Your privileges are insufficient."
end
if not minetest.registered_privileges[priv] then
privs_unknown = privs_unknown .. "Unknown privilege: " .. priv .. "\n"
end
privs[priv] = true
end
if privs_unknown ~= "" then
return false, privs_unknown
end
if not gamehub.player[grant_name] then
gamehub.load_player(grant_name)
if gamehub.player[grant_name] then
gamehub.update_player_field(grant_name, "privs", privs)
gamehub.player[grant_name] = nil
minetest.log("action", caller..
' granted ('..grant_priv_str..
') privileges to '..grant_name)
return true, "Privileges of " .. grant_name .. ": "
.. minetest.privs_to_string(privs, ', ')
else
return false, "No record for "..grant_name
end
end
gamehub.privs[grant_name] = privs
gamehub.update_player_field(grant_name, "privs") -- backup
if gamehub.player[grant_name].game == "world" then
minetest.set_player_privs(grant_name, privs) -- set the privileges
end
minetest.log("action", caller..
' granted ('..minetest.privs_to_string(grantprivs, ', ')..
') privileges to '..grant_name)
if grant_name ~= caller then
minetest.chat_send_player(grant_name, caller
.. " granted you privileges: "
.. minetest.privs_to_string(grantprivs, ' '))
end
return true, "Privileges of " .. grant_name .. ": "
.. minetest.privs_to_string(
minetest.get_player_privs(grant_name), ' ')
end
-- Revoke command handler
-- @param caller: player executing the command
-- @param revoke_name: player name losing privs
-- @param revoke_priv_str: privileges string
-- @return bool & message
local function handle_revoke_command(caller, revoke_name, revoke_priv_str)
local caller_privs = minetest.get_player_privs(caller)
if not (caller_privs.privs or caller_privs.basic_privs) then
return false, "Your privileges are insufficient."
end
if not minetest.get_auth_handler().get_auth(revoke_name) then
return false, "Player " .. revoke_name .. " does not exist."
end
local revoke_privs = minetest.string_to_privs(revoke_priv_str)
local privs = minetest.get_player_privs(revoke_name)
local basic_privs = minetest.string_to_privs(
minetest.setting_get("basic_privs") or "interact,shout")
for priv, _ in pairs(revoke_privs) do
if not basic_privs[priv] and
not minetest.check_player_privs(caller, {privs=true}) then
return true, "Your privileges are insufficient."
end
end
if revoke_priv_str == "all" then
privs = {}
else
for priv, _ in pairs(revoke_privs) do
privs[priv] = nil
end
end
minetest.set_player_privs(revoke_name, privs)
gamehub.privs[revoke_name] = privs
gamehub.update_player_field(revoke_name, "privs")
minetest.log("action", caller..' revoked ('
..minetest.privs_to_string(revoke_privs, ', ')
..') privileges from '..revoke_name)
if revoke_name ~= caller then
minetest.chat_send_player(revoke_name, caller
.. " revoked privileges from you: "
.. minetest.privs_to_string(revoke_privs, ' '))
end
return true, "Privileges of " .. revoke_name .. ": "
.. minetest.privs_to_string(
minetest.get_player_privs(revoke_name), ' ')
end
-- Check path for correct file presence
-- @param path: folder to check
-- @param name: filename without extension
-- @return truth table including count
local check_files = function(path, name)
local extension, file, err
local list = {}
list.n = 0
extension = {"mts", "we", "hub"}
for _, entry in ipairs(extension) do
local filename = path .. name .. "." .. entry
file, err = ie.io.open(filename, "rb")
if err then
list[entry] = false
else
file:close()
list[entry] = true
list.n = list.n + 1
end
end
return list
end
--------------------
-- Admin Commands --
--------------------
minetest.register_chatcommand("hub", {
description = 'gamehub management tool',
params = '{add|del|edit|load|protect|reset|save|stage|unstage} [name|id]',
func = function(name, param)
-- secure access
if not gamehub.privs[name].hub_admin then
return false, "Insufficient privs!"
end
local cmd, helper, list, param1, param2, player
helper = [[Usage:
/hub add
/hub delete <area_id> [true]
/hub edit <game>
/hub load <filename>
/hub protect <area_id> [true]
/hub save <area_id>
/hub stage
/hub unstage <stage_num>
]]
list = {}
player = minetest.get_player_by_name(name)
if not player then
return false, "You need to be playing to use this command!"
end
for word in param:gmatch("%S+") do
list[#list+1] = word
end
if #list < 1 then return false, helper end
cmd = list[1]
if #list == 1 then
if cmd == 'add' then
local area, ctr = gamehub.area_at_pos(player:get_pos())
if not area then
return false, "You must create an area first!"
elseif ctr > 1 then
return false, "Multiple areas detected. Unable to continue!"
else
minetest.show_formspec(name, "hub:add", gamehub.get_add_formspec(area.name))
end
elseif cmd == 'stage' then
local pos = vector.round(player:get_pos())
local facing = {
h = player:get_look_horizontal(),
v = player:get_look_vertical()
}
local area, ctr = gamehub.area_at_pos(pos)
if area and ctr == 1 then
local data = gamehub.game[area.name].data
local stages = data.stages or {}
local new_stage = {
stage = #stages + 1,
pos = {}, -- set on pad placement
dest = pos,
facing = facing
}
stages[#stages+1] = new_stage
data.stages = stages
gamehub.game[area.name].data = data -- update cache
gamehub.update_game_field(area.name, "data")
return true, "Stage " .. #stages + 1 .. " position added to " ..
area.name .. " data"
else
return false, "Multiple areas detected. Unable to continue!"
end
else
-- no matches
return false, helper
end
elseif #list >= 2 then
if cmd == 'delete' then
local id = tonumber(list[2])
if not areas.areas[id] then
return false, "area id " .. id .. " doesn't exist!"
end
local game = areas.areas[id].name
local msg = game .. " game removed!"
if list[3] == "true" then
-- delete area
local area = areas.areas[id]
worldedit.set(area.pos1, area.pos2, "air")
worldedit.clear_objects(area.pos1, area.pos2)
areas:remove(id, true)
areas:save()
msg = msg .. "\nbuild removed!"
end
-- remove from db
gamehub.delete_game(game)
return true, msg
elseif cmd == "edit" then
local game = list[2]
if #list > 2 then
game = table.concat(list, " ", 2)
end
if not gamehub.game[game] then
return false, game .. ' does not exist!'
end
minetest.show_formspec(name, "hub:edit",
gamehub.get_edit_formspec(game))
elseif cmd == 'load' then
-- flatten list values if reqd
local new_name
local old_name = list[2]
if #list > 2 then
old_name = table.concat(list, " ", 2)
end
if gamehub.game[old_name] then
for i=1,100 do
local exists = ([[%s %i]]):format(old_name, i)
if not gamehub.game[exists] then
new_name = exists
break
end
end
end
-- last entry takes precedence
local folders = {
MP .. "/schems/",
WP .. "/schems/"
}
local path, folder, file, err, msg
msg = {}
for i,v in ipairs(folders) do
local check = check_files(v, old_name)
if check.n == 3 then
folder = v
msg[#msg+1] = "file set found in " .. v
elseif check.n > 0 then
for k,val in pairs(check) do
if val then
msg[#msg+1] = v.."."..k.." found..."
else
msg[#msg+1] = v.."."..k.." missing!"
end
end
elseif check.n == 0 then
msg[#msg + 1] = "no files found in " .. v
end
minetest.chat_send_player(name, table.concat(msg, "\n"))
check.n = nil -- reset
end
if not folder then return end
path = folder .. old_name .. ".mts"
-- add mts using player current pos
local pos1 = vector.round(player:get_pos())
err = minetest.place_schematic(pos1, path, nil, nil, true)
if err == nil then
minetest.chat_send_player(name, "could not open file " .. path)
return
end
-- add nodes with metadata
path = folder .. old_name .. ".we"
file, err = ie.io.open(path, "rb")
if err then
minetest.chat_send_player(name, "could not open file "
.. old_name .. ".we")
return
end
local value = file:read("*a")
file:close()
local count = worldedit.deserialize(pos1, value)
minetest.chat_send_player(name, "replaced " .. count ..
" nodes...")
-- load game file
path = folder .. old_name .. ".hub"
file, err = ie.io.open(path, "rb")
if err then
minetest.chat_send_player(name, "could not open file "..
old_name..".hub")
return
end
value = file:read("*a")
file:close()
local game = minetest.deserialize(value)
-- add new area
-- use distance vector to calculate second position
local dist = vector.subtract(game.data.pos2, game.data.pos1)
local pos2 = vector.add(pos1, dist)
local game_name = new_name or game.name
areas:add(name, game_name, pos1, pos2, nil)
areas:save()
-- modify game data
-- stages
local stages = game.data.stages or {}
for i, stage in ipairs(stages) do
-- modify vectors
local pos
dist = vector.subtract(stage.pos, game.data.pos1)
pos = vector.add(pos1, dist)
stage.pos = pos
dist = vector.subtract(stage.dest, game.data.pos1)
pos = vector.add(pos1, dist)
stage.dest = pos
stages[i] = stage
minetest.get_node_timer(stage.pos):start(1.0) -- init
end
game.data.stages = stages
-- reward pad
if game.data.rpad and game.data.rpad.pos then
-- modify vector
dist = vector.subtract(game.data.rpad.pos, game.data.pos1)
game.data.rpad.pos = vector.add(pos1, dist)
minetest.get_node_timer(game.data.rpad.pos):start(1.0) -- init
end
if new_name then
-- change reward pad meta
local meta = minetest.get_meta(game.data.rpad.pos)
meta:set_string("game", game_name)
meta:set_string("infotext", "Step on pad to complete ".. game_name)
end
-- start vector
dist = vector.subtract(game.pos, game.data.pos1)
game.pos = vector.add(pos1, dist)
game.name = game_name
game.data.pos1 = pos1
game.data.pos2 = pos2
game.played = 0
game.completed = 0
-- create new record
gamehub.new_game(game)
elseif cmd == 'protect' then
local id = tonumber(list[2])
if not areas.areas[id] then
return false, "area id " .. id .. " doesn't exist!"
end
-- optional clear param
if #list == 3 then
-- convert to bool
param2 = list[3] == 'true'
end
local count, msg = gamehub.protect(id, param2)
return true, msg .. id .. "\nadded " .. count .. " nodes"
elseif cmd == 'save' then
local id = tonumber(list[2])
if not id or not areas.areas[id] then
return false, "area id " .. id .. " does not exist!"
end
local area = areas.areas[id]
-- serialize metadata
local result, count = gamehub.serialize_meta(area.pos1, area.pos2)
local path = minetest.get_worldpath() .. "/schems"
local filename = path .. "/" .. area.name .. ".we"
local file, err = ie.io.open(filename, "wb")
if err ~= nil then
minetest.log(name, "Could not save file to \"" .. filename .. "\"")
return
end
file:write(result)
file:flush()
file:close()
minetest.chat_send_player(name, "Saved " .. count ..
" nodes to \"" .. filename .. "\"")
-- create schematic
filename = path .. "/" .. area.name .. ".mts"
minetest.create_schematic(area.pos1, area.pos2, nil, filename)
minetest.chat_send_player(name, "Saved \"" .. filename .. "\"")
-- create serialized db entry file
local data = gamehub.game[area.name]
data = minetest.serialize(data)
filename = path .. "/" .. area.name .. ".hub"
file, err = io.open(filename, "wb")
if err ~= nil then
minetest.log(name, "Could not save file to \"" .. filename .. "\"")
return
end
file:write(data)
file:flush()
file:close()
minetest.chat_send_player(name, "Saved \"" .. filename .. "\"")
elseif cmd == 'unstage' then
local num = tonumber(list[2])
local stages, data, fresh, msg, game
local area, ctr = gamehub.area_at_pos(pos)
if area and ctr == 1 then
data = gamehub.game[area.name].data
stages = data.stages
fresh = {}
msg = "error: stage " .. num .. " doesn't exist"
for i,stage in ipairs(stages) do
-- rebuild table
if stage.stage ~= num then
table.insert(fresh, stage)
else
msg = ("stage %i removed!"):format(i)
end
end
data.stages = fresh
gamehub.game[area.name].data = data
gamehub.update_game_field(area.name, "data")
return true, msg
else
return true, "Multiple areas detected. Unable to continue!"
end
else
return true, helper
end
end
end,
})
------------------------
-- Moderator Commands --
------------------------
-- list player gamehub info
minetest.register_chatcommand("info", {
description = 'List players game (moderator only)',
params = "<name>",
func = function(name, param)
if not gamehub.privs[name].hub_mod then
return false, "Insufficient privs!"
end
-- use invoker for missing param
if param == "" then
param = name
end
local player_data = gamehub.player[param]
if player_data == nil then
-- try to load player from db
player_data = gamehub.load_player(param)
end
if player_data and player_data.game then
return true, param.." is playing "..player_data.game
else
return true, "player isn't registered!"
end
end,
})
-- replace default revoke/grant privileges commands
minetest.override_chatcommand("revoke", {
params = "<name> (<privilege> | all)",
description = "Remove privilege from player",
privs = {privs=true},
func = function(name, param)
local revoke_name, revoke_priv_str = string.match(param, "([^ ]+) (.+)")
if not revoke_name or not revoke_priv_str then
return true, "Invalid parameters (see /help revoke)"
elseif not minetest.get_auth_handler().get_auth(revoke_name) then
return true, "Player " .. revoke_name .. " does not exist."
end
return handle_revoke_command(name, revoke_name, revoke_priv_str)
end,
}
)
minetest.override_chatcommand("grant", {
params = "<name> (<privilege> | all)",
description = "Give privilege to player",
func = function(name, param)
local grant_name, grant_priv_str = string.match(param, "([^ ]+) (.+)")
if not grant_name or not grant_priv_str then
return false, "Invalid parameters (Usage: /hub_grant <player> <privs>)"
end
return handle_grant_command(name, grant_name, grant_priv_str)
end,
}
)
---------------------
-- Player Commands --
---------------------
-- show game menu command
minetest.register_chatcommand("p", {
description = 'Show game menu to player',
params = "<player>",
privs = {shout=true},
func = function(name, param)
if gamehub.jail[name] then
return true, "Access Denied!"
end
local privs = gamehub.privs[name]
local target = name
if privs.hub_mod and param ~= "" and gamehub.player[param] then
target = param -- reassign
end
-- show form
minetest.show_formspec(target, "hub:menu",
gamehub.get_menu_formspec(target))
end,
})
-- exit a subgame
minetest.register_chatcommand("q", {
description = 'quit current game',
params = "<player>",
privs = {shout=true},
func = function(name, param)
if gamehub.jail[name] then
return true, "Access Denied!"
end
local privs = gamehub.privs[name]
local target = name
if privs.hub_mod and param ~= "" then
target = param
end
if gamehub.player[target].game ~= "world" then
gamehub.enter_world(target)
return true, target .. " returned to the world"
end
end,
})
-- show league table
minetest.register_chatcommand("s", {
description = 'view fastest player ranks',
privs = {shout=true},
func = function(name, param)
if gamehub.jail[name] then
return true, "Access Denied!"
end
local privs = gamehub.privs[name]
local target = name
if privs.hub_mod and param ~= "" and gamehub.player[param] then
target = param -- reassign
end
minetest.show_formspec(target, "hub:stats",
gamehub.get_stats_formspec(target))
end
})

10
gamehub/depends.txt Normal file
View File

@ -0,0 +1,10 @@
3d_armor?
abriglass?
areas
default
frame?
maptools
moreblocks?
moreores?
unified_inventory
worldedit

218
gamehub/extender.lua Normal file
View File

@ -0,0 +1,218 @@
--[[
gamehub mod (C) shivajiva101@hotmail.com 2019
This file is part of gamehub.
gamehub is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
gamehub 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with gamehub. If not, see <https://www.gnu.org/licenses/>.
Some parts of the code in this file are modified or copied
from worldedit by Uberi https://github.com/Uberi/Minetest-WorldEdit
]]
local HEADER = 5 .. ":"
-- Serialise any meta nodes within a volume
-- @param pos1: first vector
-- @param pos2: second vector
-- @return serialised string, node count
function gamehub.serialise_meta(pos1, pos2)
pos1, pos2 = worldedit.sort_pos(pos1, pos2)
worldedit.keep_loaded(pos1, pos2)
local pos = {x=pos1.x, y=0, z=0}
local count = 0
local result = {}
local get_node, get_meta = minetest.get_node, minetest.get_meta
while pos.x <= pos2.x do
pos.y = pos1.y
while pos.y <= pos2.y do
pos.z = pos1.z
while pos.z <= pos2.z do
local node = get_node(pos)
if node.name ~= "air" and node.name ~= "ignore" then
local meta = get_meta(pos):to_table()
local meta_content
-- Convert metadata item stacks to item strings
for name, inventory in pairs(meta.inventory) do
for index, stack in ipairs(inventory) do
meta_content = true
inventory[index] = stack.to_string and stack:to_string() or stack
end
end
for name, field in pairs(meta.fields) do
meta_content = true
end
for k in pairs(meta) do
if k ~= "inventory" and k ~= "fields" then
meta_content = true
break
end
end
if meta_content then
count = count + 1
result[count] = {
x = pos.x - pos1.x,
y = pos.y - pos1.y,
z = pos.z - pos1.z,
name = node.name,
param1 = node.param1 ~= 0 and node.param1 or nil,
param2 = node.param2 ~= 0 and node.param2 or nil,
meta = meta_content and meta or nil,
}
end
end
pos.z = pos.z + 1
end
pos.y = pos.y + 1
end
pos.x = pos.x + 1
end
-- Serialise entries
return HEADER .. minetest.serialize(result), count
end
-- Adds a hollow cube of playerclip double lined with kill
-- designed for games created in the air
-- @param pos: base vector of cube (x=,y=,z=)
-- @param vol: volume (x=,y=,z=)
-- @param clear: replace shield with air (bool)
-- @return number of nodes added
local function wrapper(pos, vol, remove)
local function sort_pos(pos1, pos2)
if pos1.x > pos2.x then
pos2.x, pos1.x = pos1.x, pos2.x
end
if pos1.y > pos2.y then
pos2.y, pos1.y = pos1.y, pos2.y
end
if pos1.z > pos2.z then
pos2.z, pos1.z = pos1.z, pos2.z
end
return pos1, pos2
end
local function volume(pos1, pos2)
local p1, p2 = sort_pos(pos1, pos2)
return (p2.x - p1.x + 1) *
(p2.y - p1.y + 1) *
(p2.z - p1.z + 1)
end
local function get_empty_data(area)
local data = {}
local c_ignore = minetest.get_content_id("ignore")
for i = 1, volume(area.MinEdge, area.MaxEdge) do
data[i] = c_ignore
end
return data
end
local function init(pos1, pos2)
local manip = minetest.get_voxel_manip()
local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
return manip, area
end
local manip, area = init(pos, vector.add(pos, vol))
local data = get_empty_data(area)
local node_1, node_2, msg
if remove == true then
node_1 = minetest.get_content_id("air")
node_2 = node_1
msg = "Shield replaced with air on area id: "
else
node_1 = minetest.get_content_id("maptools:playerclip")
node_2 = minetest.get_content_id("maptools:kill")
msg = "Shield added to area id: "
end
local stride = {x=1, y=area.ystride, z=area.zstride}
local offset = vector.subtract(pos, area.MinEdge)
local count = 0
-- add the nodes
for z = 0, vol.z-1 do
local index_z = (offset.z + z) * stride.z + 1
for y = 0, vol.y-1 do
local index_y = index_z + (offset.y + y) * stride.y
for x = 0, vol.x-1 do
local is_clip = z == 0 or z == vol.z-1
or y == 0 or y == vol.y-1
or x == 0 or x == vol.x-1
local is_kill = z == 1 or z == vol.z-2 or z == vol.z-3
or y == 1 or y == 2 or y == vol.y-2 or y == vol.y-3
or x == 1 or x == 2 or x == vol.x-2 or x == vol.x-3
if is_clip then
local i = index_y + (offset.x + x)
data[i] = node_1
count = count + 1
elseif is_kill then
local i = index_y + (offset.x + x)
data[i] = node_2
count = count + 1
end
end
end
end
manip:set_data(data)
manip:write_to_map()
manip:update_map()
return count, msg
end
-- Adds a protective shield to an area id
-- @param id: area id to shield (int)
-- @param remover: replace shield with air (bool)
-- @return number of nodes added
gamehub.protect = function(id, remove)
local p1, p2, dims
local areas = areas.areas
-- using area vectors
p1 = areas[id].pos1
p2 = areas[id].pos2
-- sort if reqd
if p1.y > p2.y then
p2, p1 = p1, p2
end
-- volume vect
dims = {
x = p2.x - p1.x,
y = p2.y - p1.y,
z = p2.z - p1.z
}
-- unsign if reqd
for k,v in pairs(dims) do
if v < 0 then
dims[k] = (v*v)^0.5
end
end
-- execute, returning node count
return wrapper(p1, dims, remove)
end

1015
gamehub/functions.lua Normal file

File diff suppressed because it is too large Load Diff

72
gamehub/init.lua Normal file
View File

@ -0,0 +1,72 @@
--[[
gamehub mod (C) shivajiva101@hotmail.com 2019
This file is part of gamehub.
gamehub is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
gamehub 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with gamehub. If not, see <https://www.gnu.org/licenses/>.
]]
-- globals
gamehub = {}
gamehub.game = {} -- game cache
gamehub.privs = {} -- priv cache
gamehub.player = {} -- player cache
gamehub.shop = {} -- item cache
gamehub.settings = {} -- settings cache
gamehub.bank = {} -- bank accounts cache
gamehub.jail = {} -- jail API
gamehub.jail.roll = {} -- jailed player cache
gamehub.tmr = {}
-- request an insecure enviroment
local ie = minetest.request_insecure_environment()
-- catch inaccessible insecure environment
if not ie then
error("insecure environment inaccessible\n"..
" - make sure gamehub has been added to the conf file for this server!")
end
-- temp globals
gamehub.sql = ie.require("lsqlite3")
gamehub.ie = ie
-- privs registered by this mod
minetest.register_privilege("hub_mod", "Hub moderator")
minetest.register_privilege("hub_admin", "Hub administrator")
minetest.register_privilege("jailer", "Jail moderator")
local MP = minetest.get_modpath(minetest.get_current_modname())
-- Logo
print(' .__ ___. ')
print(' _________ _____ ____| |__ ___ _\\_ |__ ')
print(' / ___\\__ \\ / \\_/ __ \\ | \\ | \\ __ \\ ')
print(' / /_/ > __ \\_ Y Y \\ ___/ Y \\ | / \\_\\ \\')
print(' \\___ (____ /__|_| /\\___ >__| /____/| ___ /')
print('/_____/ \\/ \\/ \\/ \\/ \\/ ')
-- Process mods files
dofile(MP.."/sql.lua")
dofile(MP.."/functions.lua")
dofile(MP.."/nodes.lua")
dofile(MP.."/commands.lua")
dofile(MP.."/extender.lua")
-- remove temp globals
gamehub.sql = nil
gamehub.ie = nil
-- secure this instance of sqlite3
sqlite3 = nil -- luacheck: ignore sqlite3

317
gamehub/nodes.lua Normal file
View File

@ -0,0 +1,317 @@
--[[
gamehub mod (C) shivajiva101@hotmail.com 2019
This file is part of gamehub.
gamehub is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
gamehub 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with gamehub. If not, see <https://www.gnu.org/licenses/>.
]]
local function rpad_timer(pos, elapsed)
local meta = minetest.get_meta(pos)
local game = meta:get_string("game")
if game == "" then
return true
elseif not gamehub.game[game] then
return true
end
local data = gamehub.game[game].data.rpad
if not data then
minetest.log("error", "Warning: rpad data missing at " .. minetest.pos_to_string(pos))
return false
end
local objs = minetest.get_objects_inside_radius(pos, 1)
if #objs == 0 then return true end
if vector.equals(data.pos, pos) then
for i, obj in ipairs(objs) do
if obj:is_player() then
local name = obj:get_player_name()
if gamehub.player[name].game == game or
gamehub.privs[name].hub_admin then
gamehub.process_stats(name)
minetest.sound_play("pad_reward", {
to_player = name, gain = 1, loop = false})
gamehub.player_reward(name, game)
gamehub.enter_world(name)
obj:set_hp(20)
else
if not gamehub.privs[name].hub_mod then
minetest.log("action", name ..
" attempted to use the reward pad in "..
game ..
" whilst registerd to "..gamehub.player[name].game)
end
end
end
end
else
local msg = {}
msg[#msg+1] = 'rpad at '
msg[#msg+1] = minetest.pos_to_string(pos)
msg[#msg+1] = ' does not match db record '
msg[#msg+1] = minetest.pos_to_string(data.pos)
minetest.log("warning", msg:concat())
end
return true
end
local function gpad_timer(pos, elapsed)
local objs = minetest.get_objects_inside_radius(pos, 1)
if #objs == 0 then return true end
local meta = minetest.get_meta(pos)
local pad = tonumber(meta:get_string("pad"))
local area = gamehub.area_at_pos(pos)
local game = area.name
local stage = gamehub.game[game].data.stages[pad]
if vector.equals(pos, stage.pos) then
for i, obj in ipairs(objs) do
if obj:is_player() then
local name = obj:get_player_name()
if gamehub.privs[name].hub_admin or -- admin test access
gamehub.player[name].game == game then -- game players
obj:set_pos(stage.dest)
obj:set_look_horizontal(stage.facing.h)
obj:set_look_vertical(stage.facing.v)
end
end
end
else
local msg = {}
msg[#msg+1] = 'gpad at '
msg[#msg+1] = minetest.pos_to_string(pos)
msg[#msg+1] = ' does not match db record '
msg[#msg+1] = minetest.pos_to_string(stage.pos)
minetest.log("warning", msg:concat())
end
return true -- run again
end
-----------------------------
-- REGISTER NODES
-----------------------------
-- coord based teleport pad
minetest.register_node("gamehub:gpad", {
tiles = {"hub_gpad.png"},
drawtype = 'nodebox',
paramtype = "light",
paramtype2 = "wallmounted",
legacy_wallmounted = true,
walkable = true,
sunlight_propagates = true,
description = "Teleport pad to move player to the next stage in the game",
inventory_image = "hub_gpad.png",
wield_image = "hub_gpad.png",
light_source = 14,
groups = {unbreakable = 1, not_in_creative_inventory = 1},
node_box = {
type = "wallmounted",
wall_top = { - 0.5, 0.4375, - 0.5, 0.5, 0.5, 0.5},
wall_bottom = { - 0.5, - 0.5, - 0.5, 0.5, - 0.4375, 0.5},
wall_side = { - 0.5, - 0.5, - 0.5, - 0.4375, 0.5, 0.5},
},
selection_box = {type = "wallmounted"},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
local area, ctr = gamehub.area_at_pos(pos)
if area and ctr == 1 then
local game = area.name
local data = gamehub.game[game].data
local stages = data.stages or {}
for _, stage in ipairs(stages) do
if stage.pos == 0 then
stage.pos = pos
gamehub.game[game].data = data
gamehub.update_game_field(game, "data")
break
end
end
meta:set_string("infotext", "Stage " .. #stages+1)
meta:set_string("pad", #stages)
minetest.get_node_timer(pos):start(1.0)
end
end,
on_destruct = function(pos)
local area, _ = gamehub.area_at_pos(pos)
if area then
local game = area.name
local data = gamehub.game[game].data
local stages = data.stages
for i, stage in ipairs(stages) do
if vector.equals(stage.pos, vector.round(pos)) then
stage.pos = {}
break
end
end
gamehub.game[game].data = data
gamehub.update_game_field(game, "data")
end
end,
on_drop = function(itemstack, dropper, pos)
return
end,
on_timer = gpad_timer,
})
-- reward pad:
minetest.register_node("gamehub:rpad", {
tiles = {"hub_rpad.png"},
drawtype = 'nodebox',
paramtype = "light",
paramtype2 = "wallmounted",
legacy_wallmounted = true,
walkable = true,
sunlight_propagates = true,
description = "Reward Pad (place and right-click to set)",
inventory_image = "hub_rpad.png",
wield_image = "hub_rpad.png",
light_source = 14,
groups = {unbreakable = 1, not_in_creative_inventory = 1},
node_box = {
type = "wallmounted",
wall_top = { - 0.5, 0.4375, - 0.5, 0.5, 0.5, 0.5},
wall_bottom = { - 0.5, - 0.5, - 0.5, 0.5, - 0.4375, 0.5},
wall_side = { - 0.5, - 0.5, - 0.5, - 0.4375, 0.5, 0.5},
},
selection_box = {type = "wallmounted"},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
-- set formspec & info
meta:set_string("formspec", "size[3.2,2.5]"..
"field[0.5,0.75;2,0.25;game;Game;${game}]"..
"button_exit[0.6,1.75;2,0.2;quit;Save]")
meta:set_string("infotext", "Right-click to set")
minetest.get_node_timer(pos):start(1.0)
end,
on_destruct = function(pos)
local area, _ = gamehub.area_at_pos(pos)
if area then
local game = area.name
gamehub.game[game].data.rpad = nil
gamehub.update_game_field(game, "data")
end
end,
on_receive_fields = function(pos, formname, fields, sender)
if fields.quit then
if not fields.game then return end
local game = fields.game
local name = sender:get_player_name()
if not name then
return
elseif not gamehub.privs[name].hub_admin then
minetest.chat_send_player(name, "permission denied!")
return
elseif not gamehub.game[game] then
minetest.chat_send_player(name, game .. " doesn't exist!")
return
end
-- set pad meta
local meta = minetest.get_meta(pos)
meta:set_string("game", game)
meta:set_string("formspec", "")
meta:set_string("infotext", "Step on pad to complete ".. game)
-- store data
gamehub.game[game].data.rpad = {pos = vector.round(pos)}
gamehub.update_game_field(game, "data")
end
end,
on_drop = function(itemstack, dropper, pos)
return
end,
on_timer = rpad_timer,
})
----------------------
-- EXTRAS
----------------------
minetest.register_node("gamehub:egg", {
description = "Easter Egg",
drawtype = "plantlike",
tiles = {"hub_egg.png"},
paramtype = "light",
paramtype2 = "facedir",
is_ground_content = false,
groups = {crumbly = 1, not_in_creative_inventory = 1},
drop = {},
sounds = default.node_sound_stone_defaults,
})
if minetest.get_modpath("moreblocks") then
-- Add support for moreores mod
stairsplus:register_all("moreores", "mithril_block", "moreores:mithril_block", {
description = "Mithril",
tiles = {"moreores_mithril_block.png"},
groups = {snappy = 1, bendy = 2, cracky = 1, melty = 2, level= 2},
sounds = default.node_sound_stone_defaults(),
})
stairsplus:register_all("moreores", "silver_block", "moreores:silver_block", {
description = "Silver",
tiles = {"moreores_silver_block.png"},
groups = {snappy = 1, bendy = 2, cracky = 1, melty = 2, level= 2},
sounds = default.node_sound_stone_defaults(),
})
-- Add snow and ice
stairsplus:register_all("moreblocks", "snowblock", "default:snowblock", {
description = "Snow Block",
tiles = {"default_snow.png"},
groups = {crumbly = 3, cools_lava = 1, snowy = 1},
sounds = default.node_sound_snow_defaults(),
})
stairsplus:register_all("moreblocks", "ice", "default:ice", {
description = "Ice",
tiles = {"default_ice.png"},
is_ground_content = false,
paramtype = "light",
groups = {cracky = 3, cools_lava = 1, slippery = 3},
sounds = default.node_sound_glass_defaults(),
})
end
-- Add cleanup for rogue entities from signs_lib
if not signs_lib then
minetest.register_entity(":signs:text", {
on_activate = function(self)
self.object:remove()
end
})
end

View File

@ -0,0 +1 @@
return {["data"] = {["pos2"] = {["y"] = 1137, ["x"] = 49, ["z"] = 43}, ["pos1"] = {["y"] = 982, ["x"] = -21, ["z"] = -9}, ["rpad"] = {["pos"] = {["y"] = 998, ["x"] = 21, ["z"] = 19}}}, ["active"] = true, ["items"] = "", ["author"] = "dman", ["facing"] = {["v"] = 0, ["h"] = 4.6731195449829}, ["credits"] = "X-men - team builder", ["description"] = "Drop through a barnyard, avoiding the obstacles, to the water pocket to survive the fall and collect your reward. With 3 entry points you can even choose the difficulty!", ["privs"] = {["shout"] = true}, ["created"] = 1557172378, ["pos"] = {["y"] = 1078, ["x"] = 20, ["z"] = 20}, ["played"] = 79, ["completed"] = 36, ["type"] = "dropper", ["cap"] = 6, ["name"] = "Barnyard", ["reward"] = "25"}

BIN
gamehub/schems/Barnyard.mts Normal file

Binary file not shown.

View File

@ -0,0 +1,4 @@
5:return {{["x"] = 37, ["meta"] = {["fields"] = {["formspec"] = "size[8,8.5]list[context;src;2.75,0.5;1,1;]list[context;fuel;2.75,2.5;1,1;]image[2.75,1.5;1,1;default_furnace_fire_bg.png^[lowpart:97:default_furnace_fire_fg.png]image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[lowpart:0:gui_furnace_arrow_fg.png^[transformR270]list[context;dst;4.75,0.96;2,2;]list[current_player;main;0,4.25;8,1;]list[current_player;main;0,5.5;8,3;8]listring[context;dst]listring[current_player;main]listring[context;src]listring[current_player;main]listring[context;fuel]listring[current_player;main]image[0,4.25;1,1;gui_hb_bg.png]image[1,4.25;1,1;gui_hb_bg.png]image[2,4.25;1,1;gui_hb_bg.png]image[3,4.25;1,1;gui_hb_bg.png]image[4,4.25;1,1;gui_hb_bg.png]image[5,4.25;1,1;gui_hb_bg.png]image[6,4.25;1,1;gui_hb_bg.png]image[7,4.25;1,1;gui_hb_bg.png]", ["infotext"] = "Furnace active\
(Item: Empty; Fuel: 3%)", ["fuel_totaltime"] = "1e+09", ["src_time"] = "0", ["fuel_time"] = "3.7212e+07"}, ["inventory"] = {["fuel"] = {""}, ["dst"] = {"", "", "", ""}, ["src"] = {""}}}, ["param2"] = 7, ["y"] = 39, ["z"] = 21, ["name"] = "default:furnace_active"}, {["x"] = 37, ["meta"] = {["fields"] = {["infotext"] = "Chest"}, ["inventory"] = {["main"] = {"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}}}, ["param2"] = 7, ["y"] = 40, ["param1"] = 221, ["z"] = 21, ["name"] = "default:chest"}, {["x"] = 39, ["meta"] = {["fields"] = {["owner"] = "dman", ["formspec"] = "size[11,10]bgcolor[#080808BB;true]background[5,5;1,1;gui_formbg.png;true]listcolors[#00000069;#5A5A5A;#141318;#30434C;#FFF]label[0,0;Input\
material]list[current_name;input;1.5,0;1,1;]label[0,1;Left-over]list[current_name;micro;1.5,1;1,1;]label[0,2;Recycle\
output]list[current_name;recycle;1.5,2;1,1;]field[0.3,3.5;1,1;max_offered;Max:;${max_offered}]button[1,3.2;1,1;Set;Set]list[current_name;output;2.8,0;8,6;]list[current_player;main;1.5,6.25;8,4;]", ["infotext"] = "Circular Saw is empty (owned by dman)", ["anz"] = "0", ["max_offered"] = "99"}, ["inventory"] = {["input"] = {""}, ["micro"] = {""}, ["recycle"] = {""}, ["output"] = {"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""}}}, ["param2"] = 4, ["y"] = 40, ["param1"] = 221, ["z"] = 21, ["name"] = "moreblocks:circular_saw"}, {["x"] = 42, ["meta"] = {["fields"] = {["infotext"] = "Step on pad to complete Barnyard", ["game"] = "Barnyard"}, ["inventory"] = {}}, ["param2"] = 1, ["y"] = 16, ["param1"] = 238, ["z"] = 28, ["name"] = "gamehub:rpad"}}

View File

@ -0,0 +1,2 @@
return {["data"] = {["pos2"] = {["y"] = 1359, ["x"] = 515, ["z"] = 634}, ["stages"] = {{["facing"] = {["h"] = 4.6727700233459, ["v"] = 0.17261306941509}, ["pos"] = {["y"] = 1224, ["x"] = 395, ["z"] = 594}, ["stage"] = 1, ["dest"] = {["y"] = 1327, ["x"] = 397, ["z"] = 594}}}, ["pos1"] = {["y"] = 1201, ["x"] = 261, ["z"] = 553}, ["rpad"] = {["pos"] = {["y"] = 1345, ["x"] = 468, ["z"] = 577}}}, ["active"] = true, ["items"] = "", ["author"] = "evilbunny", ["facing"] = {["h"] = 2.7668707370758, ["v"] = 0.15847590565681}, ["credits"] = "skyblock server", ["description"] = "3 stage parcour with a nice theme.\
Difficulty: Hard", ["privs"] = {["interact"] = true, ["shout"] = true}, ["created"] = 1563404163, ["pos"] = {["y"] = 1210, ["x"] = 300, ["z"] = 593}, ["played"] = 0, ["completed"] = 1, ["type"] = "parkour", ["cap"] = 1, ["name"] = "BunnyHop", ["reward"] = "1000"}

BIN
gamehub/schems/BunnyHop.mts Normal file

Binary file not shown.

View File

@ -0,0 +1,21 @@
5:return {{["x"] = 30, ["meta"] = {["fields"] = {["infotext"] = "\"Told ya!\"", ["formspec"] = "field[text;;${text}]", ["text"] = "Told ya!"}, ["inventory"] = {}}, ["y"] = 87, ["param1"] = 15, ["z"] = 78, ["name"] = "maptools:kill"}, {["x"] = 36, ["meta"] = {["fields"] = {["formspec"] = "size[8,8.5]bgcolor[#080808BB;true]background[5,5;1,1;gui_formbg.png;true]listcolors[#00000069;#5A5A5A;#141318;#30434C;#FFF]list[current_name;src;2.75,0.5;1,1;]list[current_name;fuel;2.75,2.5;1,1;]image[2.75,1.5;1,1;default_furnace_fire_bg.png]image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[transformR270]list[current_name;dst;4.75,0.96;2,2;]list[current_player;main;0,4.25;8,1;]list[current_player;main;0,5.5;8,3;8]listring[current_name;dst]listring[current_player;main]listring[current_name;src]listring[current_player;main]listring[current_name;fuel]listring[current_player;main]image[0,4.25;1,1;gui_hb_bg.png]image[1,4.25;1,1;gui_hb_bg.png]image[2,4.25;1,1;gui_hb_bg.png]image[3,4.25;1,1;gui_hb_bg.png]image[4,4.25;1,1;gui_hb_bg.png]image[5,4.25;1,1;gui_hb_bg.png]image[6,4.25;1,1;gui_hb_bg.png]image[7,4.25;1,1;gui_hb_bg.png]"}, ["inventory"] = {["fuel"] = {""}, ["dst"] = {"", "", "", ""}, ["src"] = {""}}}, ["y"] = 2, ["param1"] = 15, ["z"] = 46, ["name"] = "maptools:kill"}, {["x"] = 38, ["meta"] = {["fields"] = {["state"] = "0"}, ["inventory"] = {}}, ["y"] = 2, ["param1"] = 15, ["z"] = 44, ["name"] = "maptools:kill"}, {["x"] = 38, ["meta"] = {["fields"] = {["infotext"] = "\"Welcome to\
Bunny hop\"", ["formspec"] = "field[text;;${text}]", ["text"] = "Welcome to\
Bunny hop"}, ["inventory"] = {}}, ["param2"] = 5, ["y"] = 10, ["param1"] = 187, ["z"] = 38, ["name"] = "default:sign_wall_steel"}, {["x"] = 39, ["meta"] = {["fields"] = {["infotext"] = "\"Parcour with 3 Stages\
1. Prolog\
2. Meet the Bunny\
3. Egg run\"", ["formspec"] = "field[text;;${text}]", ["text"] = "Parcour with 3 Stages\
1. Prolog\
2. Meet the Bunny\
3. Egg run"}, ["inventory"] = {}}, ["param2"] = 5, ["y"] = 10, ["param1"] = 187, ["z"] = 38, ["name"] = "default:sign_wall_steel"}, {["x"] = 44, ["meta"] = {["fields"] = {["formspec"] = "size[8,8.5]bgcolor[#080808BB;true]background[5,5;1,1;gui_formbg.png;true]listcolors[#00000069;#5A5A5A;#141318;#30434C;#FFF]list[current_name;src;2.75,0.5;1,1;]list[current_name;fuel;2.75,2.5;1,1;]image[2.75,1.5;1,1;default_furnace_fire_bg.png]image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[transformR270]list[current_name;dst;4.75,0.96;2,2;]list[current_player;main;0,4.25;8,1;]list[current_player;main;0,5.5;8,3;8]listring[current_name;dst]listring[current_player;main]listring[current_name;src]listring[current_player;main]listring[current_name;fuel]listring[current_player;main]image[0,4.25;1,1;gui_hb_bg.png]image[1,4.25;1,1;gui_hb_bg.png]image[2,4.25;1,1;gui_hb_bg.png]image[3,4.25;1,1;gui_hb_bg.png]image[4,4.25;1,1;gui_hb_bg.png]image[5,4.25;1,1;gui_hb_bg.png]image[6,4.25;1,1;gui_hb_bg.png]image[7,4.25;1,1;gui_hb_bg.png]"}, ["inventory"] = {["fuel"] = {""}, ["dst"] = {"", "", "", ""}, ["src"] = {""}}}, ["param2"] = 13, ["y"] = 8, ["z"] = 46, ["name"] = "default:furnace"}, {["x"] = 46, ["meta"] = {["fields"] = {["state"] = "0"}, ["inventory"] = {}}, ["y"] = 8, ["param1"] = 153, ["z"] = 44, ["name"] = "doors:door_wood_a"}, {["x"] = 46, ["meta"] = {["fields"] = {["infotext"] = "\"WC\"", ["formspec"] = "field[text;;${text}]", ["text"] = "WC"}, ["inventory"] = {}}, ["param2"] = 4, ["y"] = 10, ["param1"] = 187, ["z"] = 43, ["name"] = "default:sign_wall_steel"}, {["x"] = 47, ["meta"] = {["fields"] = {["infotext"] = "\"Last chance\"", ["formspec"] = "field[text;;${text}]", ["text"] = "Last chance"}, ["inventory"] = {}}, ["param2"] = 4, ["y"] = 9, ["param1"] = 170, ["z"] = 43, ["name"] = "default:sign_wall_steel"}, {["x"] = 52, ["meta"] = {["fields"] = {["infotext"] = "\"Prolog: to warm up\
(Stage 1)\"", ["formspec"] = "field[text;;${text}]", ["text"] = "Prolog: to warm up\
(Stage 1)"}, ["inventory"] = {}}, ["param2"] = 2, ["y"] = 10, ["param1"] = 221, ["z"] = 39, ["name"] = "default:sign_wall_steel"}, {["x"] = 54, ["meta"] = {["fields"] = {["infotext"] = "\"Sokomines place\
\"", ["formspec"] = "field[text;;${text}]", ["text"] = "Sokomines place\
"}, ["inventory"] = {}}, ["param2"] = 3, ["y"] = 10, ["param1"] = 190, ["z"] = 38, ["name"] = "default:sign_wall_steel"}, {["x"] = 133, ["meta"] = {["fields"] = {["infotext"] = "\"Well done :-)\"", ["formspec"] = "field[text;;${text}]", ["text"] = "Well done :-)"}, ["inventory"] = {}}, ["param2"] = 4, ["y"] = 24, ["param1"] = 188, ["z"] = 42, ["name"] = "default:sign_wall_steel"}, {["x"] = 134, ["meta"] = {["fields"] = {["infotext"] = "Stage 2", ["pad"] = "1"}, ["inventory"] = {}}, ["param2"] = 1, ["y"] = 23, ["param1"] = 238, ["z"] = 41, ["name"] = "gamehub:gpad"}, {["x"] = 135, ["meta"] = {["fields"] = {["infotext"] = "\"Step on the pad to proceed\"", ["formspec"] = "field[text;;${text}]", ["text"] = "Step on the pad to proceed"}, ["inventory"] = {}}, ["param2"] = 2, ["y"] = 24, ["param1"] = 204, ["z"] = 41, ["name"] = "default:sign_wall_steel"}, {["x"] = 137, ["meta"] = {["fields"] = {["infotext"] = "\"Stage 2\
Meet the Bunny\"", ["formspec"] = "field[text;;${text}]", ["text"] = "Stage 2\
Meet the Bunny"}, ["inventory"] = {}}, ["param2"] = 2, ["y"] = 127, ["param1"] = 204, ["z"] = 42, ["name"] = "default:sign_wall_steel"}, {["x"] = 152, ["meta"] = {["fields"] = {["wear"] = "0"}, ["inventory"] = {}}, ["param2"] = 2, ["y"] = 129, ["param1"] = 207, ["z"] = 39, ["name"] = "frame:default_coal_lump"}, {["x"] = 152, ["meta"] = {["fields"] = {["wear"] = "0"}, ["inventory"] = {}}, ["param2"] = 2, ["y"] = 129, ["param1"] = 207, ["z"] = 41, ["name"] = "frame:default_coal_lump"}, {["x"] = 154, ["meta"] = {["fields"] = {["state"] = "1"}, ["inventory"] = {}}, ["param2"] = 3, ["y"] = 120, ["param1"] = 157, ["z"] = 43, ["name"] = "doors:door_wood_b"}, {["x"] = 167, ["meta"] = {["fields"] = {["infotext"] = "Owned by evilbunny", ["owner"] = "evilbunny"}, ["inventory"] = {}}, ["param2"] = 2, ["y"] = 135, ["param1"] = 62, ["z"] = 40, ["name"] = "doors:trapdoor_steel_open"}, {["x"] = 184, ["meta"] = {["fields"] = {["infotext"] = "\"do not jump on the Cactus or you will die\"", ["formspec"] = "field[text;;${text}]", ["text"] = "do not jump on the Cactus or you will die"}, ["inventory"] = {}}, ["param2"] = 2, ["y"] = 146, ["param1"] = 207, ["z"] = 49, ["name"] = "default:sign_wall_steel"}, {["x"] = 184, ["meta"] = {["fields"] = {["infotext"] = "\"Jump down\
right into the light\
\"", ["formspec"] = "field[text;;${text}]", ["text"] = "Jump down\
right into the light\
"}, ["inventory"] = {}}, ["param2"] = 2, ["y"] = 147, ["param1"] = 191, ["z"] = 49, ["name"] = "default:sign_wall_steel"}, {["x"] = 185, ["meta"] = {["fields"] = {["infotext"] = "\"Not on the Cactus! Random do not even think of!!!\"", ["formspec"] = "field[text;;${text}]", ["text"] = "Not on the Cactus! Random do not even think of!!!"}, ["inventory"] = {}}, ["param2"] = 1, ["y"] = 146, ["param1"] = 175, ["z"] = 50, ["name"] = "default:sign_wall_steel"}, {["x"] = 187, ["meta"] = {["fields"] = {["infotext"] = "Stage 3\
Egg run ", ["__signslib_new_format"] = "1", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]", ["text"] = "Stage 3\
Egg run"}, ["inventory"] = {}}, ["param2"] = 2, ["y"] = 117, ["param1"] = 223, ["z"] = 50, ["name"] = "default:sign_wall_wood"}, {["x"] = 188, ["meta"] = {["fields"] = {["infotext"] = "\"Told ya!\"", ["formspec"] = "field[text;;${text}]", ["text"] = "Told ya!"}, ["inventory"] = {}}, ["param2"] = 4, ["y"] = 118, ["param1"] = 175, ["z"] = 58, ["name"] = "default:sign_wall_steel"}, {["x"] = 207, ["meta"] = {["fields"] = {["infotext"] = "Step on pad to complete BunnyHop", ["game"] = "BunnyHop"}, ["inventory"] = {}}, ["param2"] = 1, ["y"] = 144, ["param1"] = 239, ["z"] = 24, ["name"] = "gamehub:rpad"}, {["x"] = 207, ["meta"] = {["fields"] = {["infotext"] = "WoolyMint ", ["__signslib_new_format"] = "1", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]", ["text"] = "WoolyMint"}, ["inventory"] = {}}, ["param2"] = 5, ["y"] = 144, ["param1"] = 207, ["z"] = 30, ["name"] = "default:sign_wall_wood"}, {["x"] = 210, ["meta"] = {["fields"] = {["infotext"] = "\"The floor is lethal!\"", ["formspec"] = "field[text;;${text}]", ["text"] = "The floor is lethal!"}, ["inventory"] = {}}, ["param2"] = 5, ["y"] = 125, ["param1"] = 156, ["z"] = 54, ["name"] = "default:sign_wall_steel"}, {["x"] = 213, ["meta"] = {["fields"] = {["infotext"] = "\"Find the way to the Top\"", ["formspec"] = "field[text;;${text}]", ["text"] = "Find the way to the Top"}, ["inventory"] = {}}, ["param2"] = 4, ["y"] = 125, ["param1"] = 204, ["z"] = 54, ["name"] = "default:sign_wall_steel"}}

23
gamehub/schems/ReadMe.md Normal file
View File

@ -0,0 +1,23 @@
## Example game mod dependencies
### Barnyard by dman
* default
* gamehub
* maptools
* moreblocks
### Bunny Hop by evilbunny
* abriglass
* default
* frame
* gamehub
* maptools
* moreblocks
* moreores
### X-men Rooms by X-men
* abriglass
* default
* gamehub
* maptools
* moreblocks

View File

@ -0,0 +1 @@
return {["data"] = {["pos2"] = {["y"] = 1583, ["x"] = 305, ["z"] = 706}, ["pos1"] = {["y"] = 1503, ["x"] = 216, ["z"] = 321}, ["rpad"] = {["pos"] = {["y"] = 1521, ["x"] = 240, ["z"] = 366}}}, ["active"] = true, ["items"] = "", ["author"] = "X-men", ["facing"] = {["h"] = 4.7216396331787, ["v"] = -0.22165682911873}, ["credits"] = "shivajiva", ["description"] = "This game is a multi map parkour. Can you make it all the way to the end without dying?", ["privs"] = {["interact"] = true, ["shout"] = true}, ["created"] = 1565379453, ["pos"] = {["y"] = 1520, ["x"] = 249, ["z"] = 640}, ["played"] = 0, ["completed"] = 0, ["type"] = "parkour", ["cap"] = 3, ["name"] = "X-men Rooms", ["reward"] = "100"}

Binary file not shown.

View File

@ -0,0 +1,34 @@
5:return {{["x"] = 23, ["meta"] = {["fields"] = {["infotext"] = "lvl.5\
Jump and Don't Die! ", ["__signslib_new_format"] = "1", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]", ["text"] = "#4lvl.5\
#4Jump and Don't Die! "}, ["inventory"] = {}}, ["param2"] = 5, ["y"] = 28, ["param1"] = 174, ["z"] = 221, ["name"] = "default:sign_wall_wood"}, {["x"] = 24, ["meta"] = {["fields"] = {["infotext"] = "Step on pad to complete X-men Rooms", ["game"] = "X-men Rooms"}, ["inventory"] = {}}, ["param2"] = 1, ["y"] = 18, ["param1"] = 238, ["z"] = 45, ["name"] = "gamehub:rpad"}, {["x"] = 24, ["meta"] = {["fields"] = {["infotext"] = "CONGRATULATIONS!\
CONRATULAZIONI! ", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]", ["__signslib_new_format"] = "1", ["text"] = "CONGRATULATIONS!\
CONRATULAZIONI!"}, ["inventory"] = {}}, ["param2"] = 3, ["y"] = 19, ["param1"] = 222, ["z"] = 45, ["name"] = "default:sign_wall_steel"}, {["x"] = 24, ["meta"] = {["fields"] = {["infotext"] = "lvl.7\
Underwater Maze ", ["text"] = "#1lvl.7\
#9Underwater Maze", ["__signslib_new_format"] = "1", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]"}, ["inventory"] = {}}, ["param2"] = 5, ["y"] = 28, ["param1"] = 174, ["z"] = 197, ["name"] = "default:sign_wall_wood"}, {["x"] = 25, ["meta"] = {["fields"] = {["infotext"] = "lvl. 2\
Anti-Gravity Hills ", ["__signslib_new_format"] = "1", ["text"] = "#8lvl. 2\
#9Anti-Gravity Hills", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]"}, ["inventory"] = {}}, ["param2"] = 1, ["y"] = 24, ["param1"] = 222, ["z"] = 293, ["name"] = "default:sign_wall_steel"}, {["x"] = 27, ["meta"] = {["fields"] = {["infotext"] = "lvl.9\
Ninja Training ", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]", ["__signslib_new_format"] = "1", ["text"] = "#elvl.9\
#eNinja Training"}, ["inventory"] = {}}, ["param2"] = 1, ["y"] = 17, ["param1"] = 222, ["z"] = 127, ["name"] = "default:sign_wall_steel"}, {["x"] = 27, ["meta"] = {["fields"] = {["infotext"] = "lvl.8\
Space Zone ", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]", ["__signslib_new_format"] = "1", ["text"] = "#8lvl.8\
Space Zone"}, ["inventory"] = {}}, ["param2"] = 5, ["y"] = 20, ["param1"] = 221, ["z"] = 170, ["name"] = "default:sign_wall_steel"}, {["x"] = 28, ["meta"] = {["fields"] = {["infotext"] = "lvl.4\
Desert Parkour ", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]", ["__signslib_new_format"] = "1", ["text"] = "#elvl.4\
#e Desert Parkour"}, ["inventory"] = {}}, ["param2"] = 5, ["y"] = 18, ["param1"] = 175, ["z"] = 246, ["name"] = "default:sign_wall_steel"}, {["x"] = 29, ["meta"] = {["fields"] = {["infotext"] = "Start!\
Inizia! ", ["__signslib_new_format"] = "1", ["text"] = "Start!\
Inizia!", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]"}, ["inventory"] = {}}, ["param2"] = 5, ["y"] = 19, ["param1"] = 175, ["z"] = 313, ["name"] = "default:sign_wall_steel"}, {["x"] = 31, ["meta"] = {["fields"] = {["infotext"] = "lvl.3\
Cacti Maze and Desert Pyramid ", ["__signslib_new_format"] = "1", ["text"] = "#alvl.3\
#2 Cacti Maze and #eDesert Pyramid", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]"}, ["inventory"] = {}}, ["param2"] = 5, ["y"] = 18, ["param1"] = 221, ["z"] = 268, ["name"] = "default:sign_wall_steel"}, {["x"] = 31, ["meta"] = {["fields"] = {["infotext"] = "lvl. 1\
Green Hills! ", ["__signslib_new_format"] = "1", ["text"] = "lvl. 1\
Green Hills!", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]"}, ["inventory"] = {}}, ["param2"] = 3, ["y"] = 18, ["param1"] = 174, ["z"] = 306, ["name"] = "default:sign_wall_steel"}, {["x"] = 31, ["meta"] = {["fields"] = {["infotext"] = "Heh , wrong way! ", ["text"] = "#3Heh , wrong way!", ["__signslib_new_format"] = "1", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]"}, ["inventory"] = {}}, ["param2"] = 4, ["y"] = 23, ["param1"] = 190, ["z"] = 198, ["name"] = "default:sign_wall_wood"}, {["x"] = 31, ["meta"] = {["fields"] = {["infotext"] = "Final level!\
Lava Castle ", ["__signslib_new_format"] = "1", ["text"] = "#4Final level!\
#4 Lava Castle", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]"}, ["inventory"] = {}}, ["param2"] = 4, ["y"] = 26, ["param1"] = 172, ["z"] = 85, ["name"] = "default:sign_wall_steel"}, {["x"] = 31, ["meta"] = {["fields"] = {["infotext"] = "lvl.6\
Underwater Zone ", ["text"] = "#3lvl.6\
#bUnderwater Zone\
", ["__signslib_new_format"] = "1", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]"}, ["inventory"] = {}}, ["param2"] = 3, ["y"] = 30, ["param1"] = 206, ["z"] = 206, ["name"] = "default:sign_wall_wood"}, {["x"] = 32, ["meta"] = {["fields"] = {["infotext"] = "Not Bad ", ["text"] = "#3Not Bad", ["__signslib_new_format"] = "1", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]"}, ["inventory"] = {}}, ["param2"] = 2, ["y"] = 22, ["param1"] = 170, ["z"] = 181, ["name"] = "default:sign_wall_wood"}, {["x"] = 32, ["meta"] = {["fields"] = {["infotext"] = "GG ", ["text"] = "#bGG", ["__signslib_new_format"] = "1", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]"}, ["inventory"] = {}}, ["param2"] = 2, ["y"] = 22, ["param1"] = 187, ["z"] = 182, ["name"] = "default:sign_wall_wood"}, {["x"] = 34, ["meta"] = {["fields"] = {["infotext"] = "EN: Remember to have fun!\
IT: Ricordati di divertirti! ", ["__signslib_new_format"] = "1", ["text"] = "EN: Remember to have fun!\
IT: Ricordati di divertirti!", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]"}, ["inventory"] = {}}, ["param2"] = 2, ["y"] = 18, ["param1"] = 206, ["z"] = 318, ["name"] = "default:sign_wall_steel"}, {["x"] = 34, ["meta"] = {["fields"] = {["infotext"] = "EN: You die if you go in a place you aren't supposed to be , so don't make bad moves if you wish to live.\
IT: Qui , muori se vai in un posto in cui non dovresti , quindi non fare mosse azzardate se desideri vivere. ", ["__signslib_new_format"] = "1", ["text"] = "EN: You die if you go in a place you aren't supposed to be , so don't make bad moves if you wish to live.\
IT: Qui , muori se vai in un posto in cui non dovresti , quindi non fare mosse azzardate se desideri vivere.", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]"}, ["inventory"] = {}}, ["param2"] = 2, ["y"] = 18, ["param1"] = 190, ["z"] = 319, ["name"] = "default:sign_wall_steel"}, {["x"] = 34, ["meta"] = {["fields"] = {["infotext"] = "EN: This game is made out of different parkour maps , let's see if you can make it out without dying!\
IT: Questo gioco composto da varie mappe di parkour , vediamo se riesci a completare il gioco senza morire! ", ["__signslib_new_format"] = "1", ["text"] = "EN: This game is made out of different parkour maps , let's see if you can make it out without dying!\
IT: Questo gioco composto da varie mappe di parkour , vediamo se riesci a completare il gioco senza morire!", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]"}, ["inventory"] = {}}, ["param2"] = 2, ["y"] = 18, ["param1"] = 175, ["z"] = 320, ["name"] = "default:sign_wall_steel"}, {["x"] = 34, ["meta"] = {["fields"] = {["infotext"] = "EN: Welcome to X-men's Rooms!\
IT: Benvenuto nel minigioco Rooms di X-men ", ["__signslib_new_format"] = "1", ["text"] = "EN: Welcome to X-men's Rooms!\
IT: Benvenuto nel minigioco Rooms di X-men", ["formspec"] = "size[6,4]textarea[0,-0.3;6.5,3;text;;${text}]button_exit[2,3.4;2,1;ok;Write]background[-0.5,-0.5;7,5;bg_signs_lib.jpg]"}, ["inventory"] = {}}, ["param2"] = 2, ["y"] = 19, ["param1"] = 174, ["z"] = 319, ["name"] = "default:sign_wall_steel"}}

View File

@ -0,0 +1,11 @@
gamehub mod (C) shivajiva101@hotmail.com 2019
This file is part of gamehub mod.
The example schematics were created in my skyblocks server and
are provided under CC ATTRIBUTION 3.0
Barnyard created by dman
BunnyHop created by evilbunny
X-Men Rooms created by X-men

View File

@ -0,0 +1,6 @@
gamehub mod (C) shivajiva101@hotmail.com 2019
This file is part of gamehub mod.
pad_reward.ogg by syseQ CC0-ATTRIBUTION https://freesound.org/s/267528/
pad_teleport.ogg by DWOBoyle CC-BY-ATTRIBUTION 3.0 https://freesound.org/s/474180/

Binary file not shown.

Binary file not shown.

668
gamehub/sql.lua Normal file
View File

@ -0,0 +1,668 @@
--[[
gamehub mod (C) shivajiva101@hotmail.com 2019
This file is part of gamehub.
gamehub is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
gamehub 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with gamehub. If not, see <https://www.gnu.org/licenses/>.
]]
-- localise access to the db handler
local _sql = gamehub.sql
-- localise db
local db = _sql.open(minetest.get_worldpath().."/gamehub.sqlite") -- connection
-- Create db:exec wrapper for error reporting
-- @param stmt: sql statement to execute
-- @return nothing
local function db_exec(stmt)
if db:exec(stmt) ~= _sql.OK then
minetest.log("error", "[Gamehub] Sqlite ERROR: " .. db:errcode() ..
" " .. db:errmsg())
end
end
---------------------
--- DB TABLES ---
---------------------
local create_db = [[
CREATE TABLE IF NOT EXISTS game (
name VARCHAR PRIMARY KEY,
type INTEGER,
pos VARCHAR,
facing VARCHAR,
reward VARCHAR,
cap INTEGER,
privs VARCHAR,
author VARCHAR,
credits VARCHAR,
description VARCHAR,
created INTEGER,
played INTEGER,
completed INTEGER,
items VARCHAR,
active BOOLEAN DEFAULT (0),
data VARCHAR DEFAULT ('return = {}')
);
CREATE TABLE IF NOT EXISTS player (
name VARCHAR PRIMARY KEY,
game INTEGER,
privs VARCHAR,
pos VARCHAR,
facing VARCHAR,
counters VARCHAR DEFAULT ('return = {}'),
data VARCHAR DEFAULT ('return = {}'),
created INTEGER
);
CREATE TABLE IF NOT EXISTS bank (
name VARCHAR PRIMARY KEY,
coins INTEGER,
created INTEGER
);
CREATE TABLE IF NOT EXISTS shop (
item VARCHAR PRIMARY KEY,
moq INTEGER,
buy INTEGER,
sell INTEGER,
created INTEGER
);
CREATE TABLE IF NOT EXISTS jail (
name VARCHAR PRIMARY KEY,
reason VARCHAR,
source VARCHAR,
created INTEGER,
expires INTEGER
);
CREATE TABLE IF NOT EXISTS settings (
data VARCHAR
);
CREATE TABLE IF NOT EXISTS stats (
data VARCHAR
);
]]
--create tables if reqd
db_exec(create_db)
----------------
-- QUERIES ---
----------------
-- Loads games into gamehub.game table
-- @return nothing
local function load_games()
local q = "SELECT * FROM game;"
for row in db:nrows(q) do
row.pos = minetest.string_to_pos(row.pos)
row.facing = minetest.deserialize(row.facing)
row.privs = minetest.string_to_privs(row.privs)
row.active = row.active == 1
row.data = minetest.deserialize(row.data)
gamehub.game[row.name] = row
end
end
load_games()
-- Loads shop items into gamehub.shop table
-- @return nothing
local function load_shop()
local q = "SELECT * FROM shop;"
for row in db:nrows(q) do
gamehub.shop[row.item] = row
end
end
load_shop()
-- Loads jailed players into gamehub.jail.roll table
-- @return nothing
local function load_jail()
local q = "SELECT * FROM jail;"
for row in db:nrows(q) do
gamehub.jail.roll[row.name] = row
end
end
load_jail()
-- Loads internal settings into gamehub.settings table
-- @return nothing
local function load_settings()
local q = "SELECT * FROM settings;"
local it, state = db:nrows(q)
local row = it(state)
if row then
gamehub.settings = minetest.deserialize(row.data)
end
end
load_settings()
-- Load a players data unpacking as necessary
-- @param name: playes name
-- @return data as table
gamehub.load_player = function(name)
local q = ([[
SELECT * from player WHERE name = '%s' LIMIT 1;
]]):format(name)
local it, state = db:nrows(q)
local row = it(state)
if row then
-- unpack
row.pos = minetest.string_to_pos(row.pos)
row.facing = minetest.deserialize(row.facing)
row.privs = minetest.string_to_privs(row.privs)
row.counters = minetest.deserialize(row.counters)
row.data = minetest.deserialize(row.data)
return row
end
end
-- Load a players money into gamehub.bank table
-- @param name: players name
-- @return nothing
gamehub.load_bank_account = function(name)
local q = ([[
SELECT * from bank WHERE name = '%s' LIMIT 1;
]]):format(name)
local it, state = db:nrows(q)
local row = it(state)
if row then
gamehub.bank[name] = row
end
end
-- Loads internal settings into gamehub.settings table
-- @return nothing
local function load_stats()
local q = "SELECT * FROM stats;"
local it, state = db:nrows(q)
local row = it(state)
if row then
gamehub.stats = minetest.deserialize(row.data)
end
end
load_stats()
-------------------
--- INSERTS ---
-------------------
-- Create & cache a new game record
-- @param data: table of params
-- @return nothing
gamehub.new_game = function(data)
-- prepare data
local pos_string = minetest.pos_to_string(vector.round(data.pos))
local facing = minetest.serialize(data.facing)
local priv_string = minetest.privs_to_string(data.privs)
local active = 0
local data_string = minetest.serialize(data.data)
if data.active then active = 1 end
local stmt = ([[
INSERT INTO game (
name,
type,
pos,
facing,
reward,
cap,
privs,
author,
credits,
description,
created,
played,
completed,
items,
active,
data
) VALUES ('%s','%s','%s','%s',%i,%i,'%s','%s','%s','%s',
%i,%i,%i,'%s',%i,'%s');]]):format(data.name,data.type,
pos_string,facing,data.reward,data.cap,priv_string,data.author,
data.credits,data.description,data.created,data.played,
data.completed,data.items,active,data_string)
db_exec(stmt)
-- cache
gamehub.game[data.name] = data
end
-- Create & cache a new shop stock item record
-- @param item: item string
-- @param buy: price the shop pays for the item
-- @param sell: price the shop sells the item for
-- @param moq: minimum qty the player can buy
-- @return nothing
gamehub.new_shop_item = function(item, buy, sell, moq)
local ts = os.time()
local stmt = ([[
INSERT INTO shop (
item,
moq,
buy,
sell,
created
) VALUES ('%s',%i,%i,%i,%i);
]]):format(item, moq, buy, sell, ts)
db_exec(stmt)
-- cache
gamehub.shop[item] = {
item = item,
moq = moq,
buy = buy,
sell = sell,
created = ts
}
end
-- Create & cache a new player record
-- @param name: players name
-- @return nothing
gamehub.new_player = function(name)
local ts = os.time()
local game = "world"
local privs = minetest.get_player_privs(name)
local privS = minetest.privs_to_string(privs)
local player = minetest.get_player_by_name(name)
local pos = player:get_pos()
local poS = minetest.pos_to_string(vector.round(pos))
local facing = {
h = player:get_look_horizontal(), v = player:get_look_vertical()
}
local facinG = minetest.serialize(facing)
local counters = minetest.serialize({})
local data = minetest.serialize({})
local stmt = ([[
INSERT INTO player (
name,
game,
privs,
pos,
facing,
counters,
data,
created
) VALUES ('%s','%s','%s','%s','%s','%s','%s',%i);
]]):format(name, game, privS, poS, facinG, counters, data, ts)
db_exec(stmt)
-- cache
gamehub.player[name] = {
name = name,
game = game,
pos = pos,
facing = facing,
counters = {},
data = {},
created = ts
}
gamehub.privs[name] = privs
end
-- Create & cache a new jail record
-- @param name: jailed player name string
-- @param reason: reason string
-- @param source: name string of player creating the record
-- @param expires: expiry time as utc integer
-- @return nothing
gamehub.jail.new_record = function(name, reason, source, expires)
local ts = os.time()
local stmt = ([[
INSERT INTO jail VALUES ('%s','%s','%s',%i,%i)
]]):format(name, reason, source, ts, expires)
db_exec(stmt)
gamehub.jail[name] = {
name = name,
reason = reason,
source = source,
created = ts,
expires = expires
}
end
-- Create & cache a new bank account record
-- @param name: players name
-- @return nothing
gamehub.new_bank_account = function(name)
local ts = os.time()
local stmt = ([[
INSERT INTO bank VALUES ('%s',%i,%i)
]]):format(name, 100, ts)
db_exec(stmt)
gamehub.bank[name] = {
name=name,
coins=100,
created=ts
}
end
-- Create new settings record
-- @return nothing
gamehub.new_settings_data = function()
local data = minetest.serialize(gamehub.settings)
local stmt = ([[
INSERT INTO settings VALUES ('%s');
]]):format(data)
db_exec(stmt)
end
-- Create new stats record
-- @return nothing
gamehub.new_stats_data = function()
local data = minetest.serialize(gamehub.stats)
local stmt = ([[
INSERT INTO stats VALUES ('%s');
]]):format(data)
db_exec(stmt)
end
-------------------
--- UPDATES ---
-------------------
-- Updates a game record field
-- @param name: game name string
-- @param field: field name string
-- @param value: new value
-- @return nothing
gamehub.update_game_field = function(name, field)
local value = gamehub.game[name][field]
-- format
if field == "pos" then
value = minetest.pos_to_string(vector.round(value))
elseif field == "privs" then
value = minetest.privs_to_string(value)
elseif field == "data" or field == "facing" then
value = minetest.serialize(value)
elseif field == "active" and value then
value = 1
end
-- db
local stmt
if type(value) == "string" then
stmt = ([[
UPDATE game SET %s = '%s' WHERE name = '%s' LIMIT 1;
]]):format(field, value, name)
else
stmt = ([[
UPDATE game SET %s = %i WHERE name = '%s' LIMIT 1;
]]):format(field, value, name)
end
db_exec(stmt)
end
-- Updates & caches game information in the record
-- @param data: table of game fields
-- @return nothing
gamehub.update_game_form = function(game)
local active = 0
if game.active then active = 1 end
local data = minetest.serialize(game.data)
local stmt = ([[
UPDATE game SET
type = '%s',
privs = '%s',
author = '%s',
credits = '%s',
description = '%s',
reward = %i,
cap = %i,
items = '%s',
active = %i,
data = '%s'
WHERE name = '%s' LIMIT 1;
]]):format(game.type, game.privs, game.author, game.credits,
game.description, game.reward, game.cap, game.items, active,
data, game.name)
db_exec(stmt)
-- cache
gamehub.game[game.name].type = game.type
gamehub.game[game.name].privs = minetest.string_to_privs(game.privs)
gamehub.game[game.name].author = game.author
gamehub.game[game.name].credits = game.credits
gamehub.game[game.name].description = game.description
gamehub.game[game.name].items = game.items
gamehub.game[game.name].reward = game.reward
gamehub.game[game.name].cap = game.cap
gamehub.game[game.name].active = game.active
gamehub.game[game.name].data = game.data
end
-- Updates game record play count
-- @param game: game name string
-- @return nothing
gamehub.update_game_played = function(game)
local stmt = ([[
UPDATE game SET played = %i WHERE name = '%s' LIMIT 1;
]]):format(gamehub.game[game].played, game)
db_exec(stmt)
end
-- Updates game record completed count
-- @param game: game name string
-- @return nothing
gamehub.update_game_completed = function(game)
local stmt = ([[
UPDATE game SET completed = %i WHERE name = '%s';
]]):format(gamehub.game[game].completed, game)
db_exec(stmt)
end
-- Update stats record
-- @return nothing
gamehub.update_stats = function()
local data = minetest.serialize(gamehub.stats)
local stmt = ([[
UPDATE stats SET data = '%s'
]]):format(data)
db_exec(stmt)
end
-- Updates player record on departure
-- @param player: player object
-- @return nothing
gamehub.update_on_leaveplayer = function(player)
local name = player:get_player_name()
local game = gamehub.player[name].game
local counters = minetest.serialize(gamehub.player[name].counters)
local data = minetest.serialize(gamehub.player[name].data)
-- default sql string for a subgame
local stmt = ([[
UPDATE player SET
game = '%s',
counters = '%s',
data = '%s'
WHERE name = '%s' LIMIT 1;
]]):format(game,counters,data,name)
if game == "world" then
local pos = minetest.pos_to_string(vector.round(player:get_pos()))
local facing = minetest.serialize({
h = player:get_look_horizontal(),
v = player:get_look_vertical()
})
-- replace
stmt = ([[
UPDATE player SET
game = '%s',
pos = '%s',
facing = '%s',
counters = '%s',
data = '%s'
WHERE name = '%s' LIMIT 1;
]]):format(game,pos,facing,counters,data,name)
end
db_exec(stmt)
end
-- Updates player position in record
-- @param name: player name string
-- @return nothing
gamehub.update_player_pos = function(name)
local pos, facing, stmt
pos = minetest.pos_to_string(gamehub.player[name].pos)
facing = minetest.serialize(gamehub.player[name].facing)
stmt = ([[
UPDATE player SET
pos = '%s',
facing = '%s'
WHERE name = '%s' LIMIT 1;
]]):format(pos, facing, name)
db_exec(stmt)
end
-- Updates a player record field
-- @param name: player name string
-- @param field: field name string
-- @return nothing
gamehub.update_player_field = function(name, field)
local value = gamehub.player[name][field]
if field == "counters" or field == "data" then
value = minetest.serialize(value)
elseif field == "privs" then
value = minetest.privs_to_string(gamehub.privs[name])
end
local stmt
if type(value) == "string" then
stmt = ([[
UPDATE player SET %s = '%s' WHERE name = '%s' LIMIT 1;
]]):format(field, value, name)
else
stmt = ([[
UPDATE player SET %s = %i WHERE name = '%s' LIMIT 1;
]]):format(field, value, name)
end
db_exec(stmt)
end
-- Updates shop item record
-- @param item: item name string
-- @param buy: price the shop pays
-- @param sell: price the buyer pays
-- @param moq: minimum order quantity
-- @return nothing
gamehub.update_shop_item = function(item, buy, sell, moq)
-- cache
gamehub.shop[item].moq = moq
gamehub.shop[item].buy = buy
gamehub.shop[item].sell = sell
-- db
local stmt = ([[
UPDATE shop SET moq = %i, buy = %i, sell = %i
WHERE name = '%s' LIMIT 1;
]]):format(moq, buy, sell, item)
db_exec(stmt)
end
-- Update game record play count
-- @param name: player name string
-- @return nothing
gamehub.update_bank_account = function(name)
local balance = gamehub.bank[name].coins
local stmt = ([[
UPDATE bank SET coins = %i WHERE name = '%s' LIMIT 1;
]]):format(balance, name)
db_exec(stmt)
end
-- Updates data in settings record
-- @return nothing
gamehub.update_setting_data = function()
local data = minetest.serialize(gamehub.settings)
local stmt = ([[
UPDATE settings SET data = '%s';
]]):format(data)
db_exec(stmt)
end
-------------------
--- DELETES ---
-------------------
-- Deletes a game record
-- @param name: game name string
-- @return nothing
gamehub.delete_game = function(name)
local stmt = ([[
DELETE FROM game WHERE name = '%s' LIMIT 1;
]]):format(name)
db_exec(stmt)
gamehub.game[name] = nil -- update cache
end
-- Deletes a player record
-- @param name: player name string
-- @return nothing
gamehub.delete_player = function(name)
local stmt = ([[
DELETE FROM player WHERE name = '%s'
]]):format(name)
db_exec(stmt)
gamehub.player[name] = nil -- update cache
--gamehub.delete_account(name)
end
-- Deletes a jail record
-- @param name: player name string
-- @return nothing
gamehub.jail.delete_record = function(name)
local stmt = ([[
DELETE FROM jail WHERE name = '%s';
]]):format(name)
db_exec(stmt)
gamehub.jail[name] = nil -- update cache
end
-- Deletes a shop item record
-- @param item: item name string
-- @return nothing
gamehub.delete_shop_item = function(item)
local stmt = ([[
DELETE FROM shop WHERE item = '%s'
]]):format(item)
db_exec(stmt)
gamehub.shop[item] = nil -- update cache
end
-- Deletes players bank account record
-- @param name: player name string
-- @return nothing
gamehub.delete_bank_account = function(name)
local stmt = ([[
DELETE FROM bank WHERE name = '%s';
]]):format(name)
db_exec(stmt)
gamehub.bank[name] = nil
end

View File

@ -0,0 +1,10 @@
gamehub mod (C) shivajiva101@hotmail.com 2019
This file is part of gamehub mod.
hub_gpad.png by shivajiva CC Attribution 3.0
hub_rpad.png by shivajiva CC Attribution 3.0
hub_bg.png by shivajiva CC Attribution 3.0
hub_bg2.png by shivajiva CC Attribution 3.0
hub_egg.png by X-men CC Attribution 3.0
hub_left_icon.png / hub_right_icon.png http://commons.wikimedia.org/wiki/File:Media-playback-start.svg

BIN
gamehub/textures/hub_bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 596 B

1
jail/depends.txt Normal file
View File

@ -0,0 +1 @@
gamehub

346
jail/init.lua Normal file
View File

@ -0,0 +1,346 @@
--[[
jail mod (C) shivajiva101@hotmail.com 2019
This file is part of gamehub.
gamehub is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
gamehub 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with gamehub. If not, see <https://www.gnu.org/licenses/>.
]]
local target, mode
local filename = minetest.get_modpath("jail") .. "/schems/jail.mts"
local t_units = {
s = 1, S=1, m = 60, h = 3600, H = 3600,
d = 86400, D = 86400, w = 604800, W = 604800,
M = 2592000, y = 31104000, Y = 31104000, [""] = 1
}
jail = {}
-- Insert physical jail if not present
if not gamehub.settings.jail then
minetest.after(5, function()
local pos = minetest.setting_get_pos("jail") or {x=0,y=-1000,z=0}
minetest.place_schematic(pos, filename, nil, nil, true)
gamehub.settings.jail = {x=7,y=-998,z=7}
gamehub.new_settings_data()
end)
end
-- Jailer entity registration
minetest.register_entity("jail:jailer", {
physical = true,
collisionbox = {-0.01,-0.01,-0.01, 0.01,0.01,0.01},
visual = "sprite",
visual_size = {x=0, y=0},
textures = {"jailer.png"},
is_visible = false,
makes_footstep_sound = false,
on_activate = function(self, staticdata)
self.object:set_armor_groups({immortal = 1})
if not target or not mode or self.trapped then return end
local prisoner = minetest.get_player_by_name(target)
if not prisoner then return end
if mode == "attach" then
prisoner:set_attach(self.object, "", {x=0,y=0,z=0}, {x=0,y=0,z=0})
self.trapped = target
minetest.sound_play("jail_door", {
to_player = target,
gain = 0.2,
loop = false
})
target, mode = nil, nil
end
end,
on_step = function(self,dtime)
if not target or not mode then return end
if mode == "detach" and target == self.trapped then
local player = minetest.get_player_by_name(target)
if not player then return end
player:set_detach()
gamehub.jail.delete_record(target)
minetest.log("action", target.." released from jail!")
minetest.chat_send_all("NEWSFLASH..." .. target ..
" has been released from jail!")
-- initiate action before removing object
minetest.after(0.2, gamehub.enter_world, target)
target, mode = nil, nil
self.object:remove()
end
end,
})
--[[
-----------------------------
Internal Functions
-----------------------------
]]
-- Initialises player target
-- @param name: player name string
-- @param mode: attach or detach string
local function target_player(name, mode_string)
target = name
mode = mode_string
end
-- Convert UTC to a readable format
-- @param t: UTC integer
-- @return formatted string
local function hrdf(t)
if type(t) == "number" then
return (t and os.date("%c", t))
end
end
-- Parse duration string converting to seconds
-- @param str: duration string
-- @return seconds integer
local parse_time = function(str)
local s = 0
for n, u in str:gmatch("(%d+)([smhdwyDMY]?)") do
s = s + (tonumber(n) * (t_units[u] or 1))
end
return s
end
-- Preprocess attachment event
-- @param name: player name
-- @return nothing
local attach = function(name)
minetest.set_player_privs(name, {})
target_player(name, "attach")
local player = minetest.get_player_by_name(name)
-- minimise stacking
local adj = math.random(-2,2)
local pos = gamehub.settings.jail
pos.x = pos.x + adj
pos.z = pos.z + adj
pos.y = pos.y + 0.5
player:set_pos(pos)
minetest.add_entity(pos, "jail:jailer")
end
-- Preprocess detachment event
-- @param name: player name
-- @return nothing
local detach = function(name)
target_player(name, "detach")
end
-- Expiry timer
-- @return nothing
local function tmr()
local ts = os.time()
for name,v in pairs(gamehub.jail.roll) do
if ts >= v.expires then
local player = minetest.get_player_by_name(name)
if player then
detach(name)
else
gamehub.jail.delete_record(name)
minetest.chat_send_all("Notice: " .. name ..
" was released from jail!")
end
end
end
minetest.after(60, tmr)
end
tmr() -- start
-----------------------------
--- API Functions ---
-----------------------------
jail.jail = function(caller, name, duration, reason)
if not (caller and name and duration and reason) then
return false, 'missing paramter...'
elseif gamehub.jail.roll[name] then
return false, name .. 'is already in jail!'
elseif name == owner then
return false, 'Insufficient privileges!'
end
duration = parse_time(duration)
if duration < 60 then
return false, 'You must jail for > 60 seconds'
end
local expires = os.time() + duration
gamehub.jail.new_record(name, reason, caller, expires)
if minetest.get_player_by_name(name) then
attach(name)
end
minetest.log('info', name .. ' was jailed by ' .. caller .. ' for '..reason)
return true, name .. ' was jailed by '..caller..' until ' .. hrdf(expires)
end
jail.unjail = function(caller, name)
if not gamehub.jail.roll[name] then
return false, name .. " isn't in jail!"
end
local player = minetest.get_player_by_name(name)
if player then
detach(name)
else
gamehub.jail.delete_record(target)
minetest.log("action", target.." released from jail by " .. caller)
end
return true, name .. ' released from jail'
end
------------------------------
-- Register Callbacks --
------------------------------
minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
if gamehub.jail.roll[name] then
if os.time() > gamehub.jail.roll[name].expires then
gamehub.jail.delete_record(name)
else
minetest.after(1, attach, name)
end
end
end)
minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
if gamehub.jail.roll[name] then
detach(name)
end
end)
-- respawn
minetest.register_on_respawnplayer(function(player)
if not player then return true end
local name = player:get_player_name()
if gamehub.jail.roll[name] then
return true -- return as handled
end
end)
------------------------------
-- Register Commands --
------------------------------
minetest.register_chatcommand('jail', {
description = 'jail player',
params = '<name> <duration> <reason>',
func = function(name, param)
-- secure
if not gamehub.privs[name].hub_mod then
return false, "Insufficient privs!"
end
local pname, duration, reason = param:match("(%S+)%s+(%S+)%s+(.+)")
if not (pname and duration and reason) then
return false, "Usage: /jail <player> <time> <reason>"
elseif gamehub.jail.roll[pname] then
return false, pname .. " is already in jail!"
elseif pname == owner then
-- protect owner account
return false, "Insufficient privileges!"
end
duration = parse_time(duration)
if duration < 3600 then
return false, "You must jail for > 60 mins"
end
local expires = os.time() + duration
gamehub.jail.new_record(pname, reason, name, expires)
if minetest.get_player_by_name(name) then
attach(pname)
end
return true, pname .. " was jailed until " .. hrdf(expires)
end
})
minetest.register_chatcommand('unjail', {
params = '<player>',
description = 'release player from jail',
func = function(name, param)
if not gamehub.privs[name].hub_mod then
return false, 'Insufficient privs!'
end
if not param then
return false, 'Usage: /unjail <player>'
end
if not gamehub.jail.roll[param] then
return false, param .. "isn't in jail!"
end
detach(param)
return true, param .. ' released from jail'
end,
})
minetest.register_chatcommand('jail_info', {
description = 'view jail records',
func = function(name)
-- secure
if not gamehub.privs[name].hub_mod then
return false, 'Insufficient privs!'
end
local info = {}
for k,v in pairs(gamehub.jail.roll) do
info[#info+1] =('%s jailed by %s on %s for %s until %s'):format(
k,v.source,hrdf(v.created),v.reason,hrdf(v.expires))
end
if #info == 0 then
info[#info+1] = 'No jail records found...'
end
return true, table.concat(info,"\n")
end
})
minetest.register_chatcommand('jail_visit', {
description = 'visit jail',
func = function(name)
-- secure
if not gamehub.privs[name].hub_mod then
return false, 'Insufficient privs!'
end
local player = minetest.get_player_by_name(name)
player:set_pos(gamehub.settings.jail)
return true
end
})

5
jail/schems/credits.txt Normal file
View File

@ -0,0 +1,5 @@
gamehub mod (C) shivajiva101@hotmail.com 2019
jail.mts by shivajiva. Licence: CC-BY-Attribution

BIN
jail/schems/jail.mts Normal file

Binary file not shown.

5
jail/sounds/credits.txt Normal file
View File

@ -0,0 +1,5 @@
gamehub mod (C) shivajiva101@hotmail.com 2019
This file is part of gamehub mod.
jail_door.ogg by TurtleLG CC0 ATTRIBUTION https://freesound.org/s/80449/

BIN
jail/sounds/jail_door.ogg Normal file

Binary file not shown.

19
jail/textures/credits.txt Normal file
View File

@ -0,0 +1,19 @@
gamehub mod (C) shivajiva101@hotmail.com 2019
This file is part of gamehub.
gamehub is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
gamehub 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with gamehub. If not, see <https://www.gnu.org/licenses/>.
jailer.png by shivajiva CC0 v1.0

BIN
jail/textures/jailer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 B

0
modpack.txt Normal file
View File

2
shop/depends.txt Normal file
View File

@ -0,0 +1,2 @@
gamehub
unified_inventory

24
shop/init.lua Normal file
View File

@ -0,0 +1,24 @@
--[[
shop mod (C) shivajiva101@hotmail.com 2019
This file is part of gamehub.
gamehub is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
gamehub 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with gamehub. If not, see <https://www.gnu.org/licenses/>.
]]
local MP = minetest.get_modpath("shop")
dofile(MP.."/ui_extender.lua")
dofile(MP.."/ui_shop.lua")

6
shop/sounds/credits.txt Normal file
View File

@ -0,0 +1,6 @@
gamehub mod (C) shivajiva101@hotmail.com 2019
This file is part of gamehub mod.
shop_pay.ogg by Butilko CC0-ATTRIBUTION https://freesound.org/s/169146/
shop_register.ogg by deleted_user_96253 CC0-ATTRIBUTION https://freesound.org/s/351304/

BIN
shop/sounds/shop_pay.ogg Normal file

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,7 @@
gamehub mod (C) shivajiva101@hotmail.com 2019
This file is part of gamehub.
shop_button.png CC0 https://www.kisscc0.com/clipart/computer-icons-download-kiosk-document-shop-front-rvaes5/
shop_treasure.png CC0 https://www.kisscc0.com/clipart/coin-philippine-peso-money-bag-treasure-money-pot-lqs0nw/
shop_delete.png CC0 https://www.kisscc0.com/clipart/computer-icons-error-message-download-http-404-red-9pr99c/

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

50
shop/ui_extender.lua Normal file
View File

@ -0,0 +1,50 @@
--[[
shop mod (C) shivajiva101@hotmail.com 2019
This file is part of gamehub.
gamehub is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
gamehub 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with gamehub. If not, see <https://www.gnu.org/licenses/>.
]]
-- Extend Unified Inventory functionality to track
-- item button clicks on pages registered by this mod.
gamehub.page_click_tracking = {}
function gamehub.register_click_tracking(name)
gamehub.page_click_tracking[name] = true
end
-- register callback to track clicks
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "" then return end
local player_name = player:get_player_name()
local page = unified_inventory.current_page[player_name]
if gamehub.page_click_tracking[page] then
local item
for name, value in pairs(fields) do
if string.sub(name, 1, 12) == "item_button_" then
local _, mangled_item = string.match(name, "^item_button_([a-z]+)_(.*)$")
item = unified_inventory.demangle_for_formspec(mangled_item)
break
end
end
if item then
unified_inventory.current_item[player_name] = item
unified_inventory.set_inventory_formspec(player, page)
return true -- no further handling
end
end
end)

272
shop/ui_shop.lua Normal file
View File

@ -0,0 +1,272 @@
--[[
shop mod (C) shivajiva101@hotmail.com 2019
This file is part of gamehub.
gamehub is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
gamehub 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with gamehub. If not, see <https://www.gnu.org/licenses/>.
]]
local function get_name(item)
if type(item) == "table" then
return item.name
end
return item
end
-- display info and handle buying & selling items
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "" then return end
local name = player:get_player_name()
local item = get_name(unified_inventory.current_item[name])
-- catch events
if fields.shop_admin and gamehub.privs[name].server then
unified_inventory.set_inventory_formspec(player, "shop_manager")
elseif fields.shop_buy then
local p_inv = player:get_inventory()
local qty = tonumber(fields.shop_qty) or 1
local moq = gamehub.shop[item].moq
if qty < moq then
minetest.chat_send_player(name,"minimum qty: "..moq)
return
end
local total = tonumber(gamehub.shop[item].sell) * tonumber(qty)
-- funds and inventory space check
if gamehub.bank[name].coins >= total then
local item_stack = ItemStack(item .. " " .. qty)
if p_inv:room_for_item("main", item_stack) then
total = total - (2 * total)
gamehub.bank[name].coins = gamehub.bank[name].coins + total
gamehub.update_bank_account(name)
p_inv:add_item("main", item_stack)
minetest.sound_play("shop_register", {
to_player = name,
gain = 0.1,
loop = false
})
minetest.log("info",
name.." bought "..qty.." of "..item.."from the shop")
else
minetest.chat_send_player(name,
"insufficient space in your inventory!")
end
unified_inventory.set_inventory_formspec(player, "shop_player") -- refresh
else
minetest.chat_send_player(name,"insufficient funds!")
end
elseif fields.shop_remove then
gamehub.delete_shop_item(item)
unified_inventory.set_inventory_formspec(player, "shop_manager")
elseif fields.shop_add and gamehub.privs[name].server then
if not gamehub.shop[item] and tonumber(fields.shop_selling) > 0 then -- new
gamehub.new_shop_item(item, tonumber(fields.shop_buying),
tonumber(fields.shop_selling), tonumber(fields.shop_moq))
elseif gamehub.shop[item] then -- update
gamehub.update_shop_item(item, tonumber(fields.shop_buying),
tonumber(fields.shop_selling), tonumber(fields.shop_moq))
end
unified_inventory.set_inventory_formspec(player, "shop_manager") -- refresh
end
end)
-- Initialise shop drop slot
minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
-- create single slot inventory
local shop_inv = minetest.create_detached_inventory(name.."_shop_inv",{
allow_put = function(inv, listname, index, stack)
local item = get_name(unified_inventory.current_item[name])
if string.find(stack:get_name(), item) == nil then return 0 end
return stack:get_count()
end,
on_put = function(inv, listname, index, stack, p)
local n = p:get_player_name()
local item = get_name(unified_inventory.current_item[n])
local payment = stack:get_count() * gamehub.shop[item].buy
inv:remove_item(listname, stack)
gamehub.bank[n].coins = gamehub.bank[n].coins + payment
gamehub.update_bank_account(n)
minetest.sound_play("shop_pay", {
to_player = n,
gain = 1,
loop = false
})
minetest.log("info",
name .. " balance is now " .. gamehub.bank[n].coins .. " coins")
unified_inventory.set_inventory_formspec(p, "shop_player")
end
}, name)
shop_inv:set_size("shop", 1)
end)
-- Register button
unified_inventory.register_button("shop_player", {
type = "image",
image = "shop_button.png",
tooltip = "Shop",
})
-- Register UI pages
unified_inventory.register_page("shop_player", {
get_formspec = function(player, perplayer_formspec)
local name = player:get_player_name()
local fy = perplayer_formspec.formspec_y
local fhy = perplayer_formspec.form_header_y
local item = get_name(unified_inventory.current_item[name])
local def = minetest.registered_items[item]
local description
if def and def.description then
description = def.description
else
description = item
end
local fs = {}
fs[#fs+1] = "background[0,"
fs[#fs+1] = (fy + 3.5)
fs[#fs+1] = ";8,4;ui_main_inventory.png]"
fs[#fs+1] = "label[0,"
fs[#fs+1] = fhy
fs[#fs+1] = ";Server Shop]"
fs[#fs+1] = "size[8,8.6]"
fs[#fs+1] = "image[5,1;1,1;shop_treasure.png]"
fs[#fs+1] = "label[6,1.4;"
fs[#fs+1] = gamehub.bank[name].coins
fs[#fs+1] = "]"
-- admin?
if gamehub.privs[name].server then
fs[#fs+1] = "image_button[7.5,4;0.5,0.5;ui_craft_icon.png;shop_admin;]"
end
if not item then
fs[#fs+1] = "label[1,1;Select an item...]"
return {formspec=table.concat(fs)}
end
if gamehub.shop[item] then
fs[#fs+1] = "item_image_button[1,1;2,2;"
fs[#fs+1] = item
fs[#fs+1] = ";shop_buy;]"
fs[#fs+1] = "tooltip[shop_buy;Press to buy "
fs[#fs+1] = description
fs[#fs+1] = "]"
fs[#fs+1] = "label[1,3.2;Price: "
fs[#fs+1] = gamehub.shop[item].sell
fs[#fs+1] = "]"
if def.type ~= "tool" then
fs[#fs+1] = "field[3.6,1.5;1,0.5;shop_qty;Qty;"
fs[#fs+1] = gamehub.shop[item].moq
fs[#fs+1] = "]"
end
if tonumber(gamehub.shop[item].buy) > 0 then
fs[#fs+1] = "background[5,"
fs[#fs+1] = (fy + 1.5)
fs[#fs+1] = ";1,1;ui_single_slot.png]"
fs[#fs+1] = "list[detached:"
fs[#fs+1] = name
fs[#fs+1] = "_shop_inv;shop;5,2.5;1,1]"
fs[#fs+1] = "label[5,3.5;Pays: "
fs[#fs+1] = gamehub.shop[item].buy
fs[#fs+1] = "]"
end
else
fs[#fs+1] = "image[1.1,1;2,2;ui_no.png]"
end
return {formspec=table.concat(fs)}
end,
})
unified_inventory.register_page("shop_manager", {
get_formspec = function(player, perplayer_formspec)
local name = player:get_player_name()
local fy = perplayer_formspec.formspec_y
local fhy = perplayer_formspec.form_header_y
local item = get_name(unified_inventory.current_item[name])
local def = minetest.registered_items[item]
local description
if def and def.description then
description = def.description
else
description = item
end
local fs = {}
fs[#fs+1] = "background[0,"
fs[#fs+1] = (fy + 3.5)
fs[#fs+1] = ";8,4;ui_main_inventory.png]"
fs[#fs+1] = "label[0,"
fs[#fs+1] = fhy
fs[#fs+1] = ";Shop Management]"
if not item then
fs[#fs+1] = "label[1,1;Select an item...]"
return {formspec=table.concat(fs)}
end
local sell,buy,moq = "0","0","1"
if gamehub.shop[item] then
buy = gamehub.shop[item].buy
sell = gamehub.shop[item].sell
moq = gamehub.shop[item].moq
end
fs[#fs+1] = "item_image_button[1,1;2,2;"
fs[#fs+1] = item
fs[#fs+1] = ";shop_add;]"
fs[#fs+1] = "label[1,3.2;Item: "
fs[#fs+1] = description
fs[#fs+1] = "]"
fs[#fs+1] = "field[3.8,1.5;1,0.5;shop_selling;sell:;"
fs[#fs+1] = sell
fs[#fs+1] = "]"
fs[#fs+1] = "field[3.8,2.7;1,0.5;shop_buying;buy:;"
fs[#fs+1] = buy
fs[#fs+1] = "]"
fs[#fs+1] = "field[5,2.7;1,0.5;shop_moq;moq:;"
fs[#fs+1] = moq
fs[#fs+1] = "]"
fs[#fs+1] = "tooltip[shop_selling;selling price]"
fs[#fs+1] = "tooltip[shop_buying;purchase price]"
if gamehub.shop[item] then
fs[#fs+1] = "tooltip[shop_add;press to update item]"
else
fs[#fs+1] = "tooltip[shop_add;press to add item]"
end
fs[#fs+1] = "tooltip[shop_moq;minimum order quantity]"
if gamehub.shop[item] then
fs[#fs+1] = "image_button[7.2,1;0.5,0.5;shop_delete.png;shop_remove;]"
fs[#fs+1] = "tooltip[shop_remove;Press to remove item from shop]"
end
return {formspec=table.concat(fs)}
end,
})
-- register pages for item button click tracking
gamehub.register_click_tracking("shop_player")
gamehub.register_click_tracking("shop_manager")