Initial commit
|
@ -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!
|
|
@ -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.
|
|
@ -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
|
||||
})
|
|
@ -0,0 +1,10 @@
|
|||
3d_armor?
|
||||
abriglass?
|
||||
areas
|
||||
default
|
||||
frame?
|
||||
maptools
|
||||
moreblocks?
|
||||
moreores?
|
||||
unified_inventory
|
||||
worldedit
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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"}
|
|
@ -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"}}
|
|
@ -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"}
|
|
@ -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"}}
|
|
@ -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
|
|
@ -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"}
|
|
@ -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"}}
|
|
@ -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
|
|
@ -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/
|
|
@ -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
|
|
@ -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
|
After Width: | Height: | Size: 379 B |
After Width: | Height: | Size: 360 B |
After Width: | Height: | Size: 574 B |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 7.0 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 596 B |
|
@ -0,0 +1 @@
|
|||
gamehub
|
|
@ -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
|
||||
})
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
gamehub mod (C) shivajiva101@hotmail.com 2019
|
||||
|
||||
|
||||
jail.mts by shivajiva. Licence: CC-BY-Attribution
|
|
@ -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/
|
|
@ -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
|
After Width: | Height: | Size: 96 B |
|
@ -0,0 +1,2 @@
|
|||
gamehub
|
||||
unified_inventory
|
|
@ -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")
|
|
@ -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/
|
|
@ -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/
|
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 16 KiB |
|
@ -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)
|
|
@ -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")
|