bump
commit
8aedbc35c3
|
@ -0,0 +1,10 @@
|
|||
# Mini-games
|
||||
|
||||
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=XPWULB42QVJCJ)
|
||||
|
||||
Automatic arenas and other. List:
|
||||
|
||||
* Spleef
|
||||
* PvP arena
|
||||
* TP Points
|
||||
* Give Cost
|
|
@ -0,0 +1,28 @@
|
|||
# give_cost
|
||||
|
||||
Give cost for:
|
||||
|
||||
* Crafting;
|
||||
* Digging;
|
||||
* Building;
|
||||
* Chat messages;
|
||||
* Per minute.
|
||||
|
||||
Config path: %worldpath%/configs/give_cost/settings.conf
|
||||
|
||||
Formula: setting number * booster
|
||||
|
||||
## Commands and privs
|
||||
|
||||
* **/gcreload** - reload settings (need *gcreload* priv)
|
||||
|
||||
## API
|
||||
|
||||
* *give_cost.set_boost(num)*
|
||||
* *give_cost.get_boost()*
|
||||
|
||||
## Depends
|
||||
|
||||
* mod_configs
|
||||
* coins
|
||||
* initlib?
|
|
@ -0,0 +1,3 @@
|
|||
mod_configs
|
||||
coins
|
||||
initlib?
|
|
@ -0,0 +1,78 @@
|
|||
give_cost = {}
|
||||
local settings = {}
|
||||
local boost = 1
|
||||
|
||||
-- INITLIB
|
||||
local S, NS
|
||||
if minetest.global_exists('intllib') then
|
||||
S, NS = intllib.make_gettext_pair(minetest.get_current_modname())
|
||||
else
|
||||
S = function(s) return s end
|
||||
NS = S
|
||||
end
|
||||
|
||||
-- API
|
||||
function give_cost.set_boost(num)
|
||||
boost = num
|
||||
end
|
||||
|
||||
function give_cost.get_boost()
|
||||
return boost
|
||||
end
|
||||
|
||||
-- LOCAL FUNCTIONS
|
||||
local function load_settings()
|
||||
settings = mod_configs.get_conf('give_cost', 'settings')
|
||||
if not settings then
|
||||
settings = {
|
||||
events = {
|
||||
craft = 0.05, dig = 0.01, place = 0.02, chat = 0.05, eat = 0.1, permin = 0.1
|
||||
}
|
||||
}
|
||||
mod_configs.save_conf('give_cost', 'settings', settings)
|
||||
end
|
||||
end
|
||||
load_settings()
|
||||
|
||||
local function tick()
|
||||
for _, player in ipairs(minetest.get_connected_players()) do
|
||||
coins.add_coins(player:get_player_name(), settings.events.permin * boost)
|
||||
end
|
||||
minetest.after(60, tick)
|
||||
end
|
||||
minetest.after(60, tick)
|
||||
|
||||
-- EVENTS
|
||||
minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv)
|
||||
coins.add_coins(player:get_player_name(), settings.events.craft * boost)
|
||||
end)
|
||||
|
||||
minetest.register_on_dignode(function(pos, oldnode, digger)
|
||||
coins.add_coins(digger:get_player_name(), settings.events.dig * boost)
|
||||
end)
|
||||
|
||||
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
|
||||
coins.add_coins(placer:get_player_name(), settings.events.place * boost)
|
||||
end)
|
||||
|
||||
minetest.register_on_chat_message(function(name, message)
|
||||
coins.add_coins(name, settings.events.chat * boost)
|
||||
end)
|
||||
|
||||
minetest.register_on_item_eat(function(hp_change, replace_with_item, itemstack, user, pointed_thing)
|
||||
coins.add_coins(user:get_player_name(), settings.events.eat * boost)
|
||||
end)
|
||||
|
||||
-- REGISTRATIONS
|
||||
minetest.register_privilege('gcreload', S('Can use /gcreload'))
|
||||
|
||||
-- COMMANDS
|
||||
minetest.register_chatcommand('gcreload', {
|
||||
params = 'none',
|
||||
description = S('reload give_cost settings'),
|
||||
privs = {gcreload = true},
|
||||
func = function(name, params)
|
||||
load_settings()
|
||||
return true, S('settings config reloaded')
|
||||
end,
|
||||
})
|
|
@ -0,0 +1,4 @@
|
|||
# init.lua
|
||||
Can use /gcreload = Для использования /gcreload
|
||||
reload give_cost settings = перезагрузить конфиг
|
||||
settings config reloaded = конфиг перезагружен
|
|
@ -0,0 +1,4 @@
|
|||
# init.lua
|
||||
Can use /gcreload =
|
||||
reload give_cost settings =
|
||||
settings config reloaded =
|
|
@ -0,0 +1 @@
|
|||
mod = give_cost
|
|
@ -0,0 +1,14 @@
|
|||
Copyright (C) 2017 InterVi
|
||||
|
||||
This program 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.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see [http://www.gnu.org/licenses/](http://www.gnu.org/licenses/).
|
|
@ -0,0 +1,86 @@
|
|||
# pvp_arena
|
||||
|
||||
PvP arena minigame for minetest. Protect arena, there are lobby and spectate. The distribution of the prize coins. Take into account the order of leave, number of hits, being in the region. Support **gui_menu**.
|
||||
|
||||
## How to working?
|
||||
|
||||
* Gamers joining to lobby, moving coins cost from balance to fond.
|
||||
* Gamers voting start.
|
||||
* Chat separate.
|
||||
* Gamers teleported to game point. Inventrory backup, give random kit.
|
||||
* Pause.
|
||||
* Start game.
|
||||
* Game...
|
||||
* End game, distribution of the prize coins, give coins. Formula: "fond / 2 * boost", "fond = fond / 2".
|
||||
|
||||
Commands:
|
||||
|
||||
* **/pa list** - show list available arenas
|
||||
* **/pa join <arena>** - join to lobby
|
||||
* **/pa spec <arena>** - watch
|
||||
* **/pa leave** - leaving, if game not started - return coins cost
|
||||
* **/pa start** - vote start
|
||||
|
||||
## How to create arena?
|
||||
|
||||
* **/pacreate <arena>**
|
||||
* Punch node (pos 1 arena region)
|
||||
* **/papos1**
|
||||
* Punch node (pos 2 arena region)
|
||||
* **/papos2**
|
||||
* Punch node (pvp zone pos 1)
|
||||
* **/pazpos1**
|
||||
* Punch node (pvp zone pos 2)
|
||||
* **/pazpos2**
|
||||
* Stand on the position.
|
||||
* **/palobby (save lobby position)**
|
||||
* Stand on the position.
|
||||
* **/paspec (save spectate position)**
|
||||
* Stand on the position.
|
||||
* **/pagame (save game position)**
|
||||
* **/pasettings <min_p> <max_p> <after> <max_time> <cost>**
|
||||
* **/pakit name (optional)** - add kit for random, you inventory
|
||||
* **/pakits** - show kit names
|
||||
* **/padone**
|
||||
|
||||
Done! Editing:
|
||||
|
||||
* **/paedit <arena>**
|
||||
* ... editing ... (read above)
|
||||
* **/padone**
|
||||
|
||||
For removing:
|
||||
|
||||
* **/paremove <arena>**
|
||||
|
||||
For reload config:
|
||||
|
||||
* **/pareload**
|
||||
|
||||
## Moder commands
|
||||
|
||||
* **/pakick <player>** - kick player from arena
|
||||
* **/pastop <arena>** - force stop game
|
||||
* **/pastart <arena>** - force start game
|
||||
|
||||
## Privs
|
||||
|
||||
* **pvpa** - for access game commands
|
||||
* **pvpamod** - for access moder commands
|
||||
* **pvpaadm** - for access admin commands (edit arenas)
|
||||
|
||||
## Depends
|
||||
|
||||
* cuboids_lib
|
||||
* coins
|
||||
* pvp_control?
|
||||
* gui_menu?
|
||||
* initlib?
|
||||
|
||||
## API
|
||||
|
||||
* **pvp_arena.get_arenas()** - get available arenas, return array
|
||||
* **pvp_arena.get_active_arenas()** - get started arenas, return table "{arena = #players + #spectators}"
|
||||
* **pvp_arena.get_wait_arenas()** - get waiting arenas (gamers in lobby), return table "{arena = #players + #spectators}"
|
||||
* **pvp_arena.set_boost(num)**
|
||||
* **pvp_arena.get_boost()**
|
|
@ -0,0 +1,5 @@
|
|||
cuboids_lib
|
||||
coins
|
||||
pvp_control?
|
||||
gui_menu?
|
||||
initlib?
|
|
@ -0,0 +1,981 @@
|
|||
pvp_arena = {}
|
||||
-- {arena {
|
||||
-- edit = true/false,
|
||||
-- lobby = {xyz},
|
||||
-- spec = {xyz},
|
||||
-- game = {xyz},
|
||||
-- y_level = number,
|
||||
-- max_time = number,
|
||||
-- after = number,
|
||||
-- reg = {pos1 = {xyz}, pos2 = {xyz}},
|
||||
-- zone = {pos1 = {xyz}, pos2 = {xyz}},
|
||||
-- minp = number,
|
||||
-- maxp = number,
|
||||
-- cost = number,
|
||||
-- kits = {name = inv table, ...} (optional)
|
||||
-- }, ...}
|
||||
local arenas = {}
|
||||
-- {arena {
|
||||
-- players = {array}, spectators = {array}, invs = {player_name = json string, ...}, locs = {player_name = {xyzpitchyaw}},
|
||||
-- leaves = {player_name = number, ...}, hits = {player_name = number, ...}, start = {array},
|
||||
-- channels = {player_name = channel, ...}, started = true/false, time = number (time start), fond = number (all money)
|
||||
-- }, ...}
|
||||
local games = {}
|
||||
-- arenas analog
|
||||
local sets = {}
|
||||
-- {
|
||||
-- player_name = {arena = arena name, spec = true/false}, ...
|
||||
-- }
|
||||
local gamers = {}
|
||||
-- {player_name = arena = string, pos1 = {xyz}, pos2 = {xyz}, fpos1 = {xyz}, fpos2 = {xyz}, pos = {xyz}}
|
||||
local editors = {}
|
||||
local boost = 1
|
||||
|
||||
-- INITLIB
|
||||
local S, NS
|
||||
if minetest.global_exists('intllib') then
|
||||
S, NS = intllib.make_gettext_pair(minetest.get_current_modname())
|
||||
else
|
||||
S = function(s) return s end
|
||||
NS = S
|
||||
end
|
||||
|
||||
-- API
|
||||
function pvp_arena.get_arenas()
|
||||
local result = {}
|
||||
for key, value in pairs(arenas) do
|
||||
if not value.edit then
|
||||
table.insert(result, key)
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function pvp_arena.get_active_arenas()
|
||||
local result = {}
|
||||
for key, value in pairs(games) do
|
||||
if value.started then
|
||||
result[key] = #value.players + #value.spectators
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function pvp_arena.get_wait_arenas()
|
||||
local result = {}
|
||||
for key, value in pairs(games) do
|
||||
if not value.started then
|
||||
result[key] = #value.players + #value.spectators
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function pvp_arena.set_boost(num)
|
||||
boost = num
|
||||
end
|
||||
|
||||
function pvp_arena.get_boost()
|
||||
return boost
|
||||
end
|
||||
|
||||
-- LOCAL FUNCTIONS
|
||||
local function load_file()
|
||||
arenas = mod_configs.load_json('pvp_arena', 'arenas')
|
||||
if not arenas then arenas = {} end
|
||||
end
|
||||
|
||||
local function load_cache()
|
||||
sets = mod_configs.load_json('pvp_arena', 'cache_sets')
|
||||
editors = mod_configs.load_json('pvp_arena', 'cache_editors')
|
||||
if not sets then sets = {} end
|
||||
if not editors then editors = {} end
|
||||
end
|
||||
|
||||
load_file()
|
||||
--load_cache()
|
||||
|
||||
local function tp_lobby(player, arena)
|
||||
games[arena].locs[player:get_player_name()] = player:getpos()
|
||||
games[arena].locs[player:get_player_name()].pitch = player:get_look_vertical()
|
||||
games[arena].locs[player:get_player_name()].yaw = player:get_look_horizontal()
|
||||
local pos = arenas[arena].lobby
|
||||
player:setpos(pos)
|
||||
player:set_look_vertical(pos.pitch)
|
||||
player:set_look_horizontal(pos.yaw)
|
||||
end
|
||||
|
||||
local function tp_spectate(player, arena)
|
||||
games[arena].locs[player:get_player_name()] = player:getpos()
|
||||
games[arena].locs[player:get_player_name()].pitch = player:get_look_vertical()
|
||||
games[arena].locs[player:get_player_name()].yaw = player:get_look_horizontal()
|
||||
local pos = arenas[arena].spec
|
||||
player:setpos(pos)
|
||||
player:set_look_vertical(pos.pitch)
|
||||
player:set_look_horizontal(pos.yaw)
|
||||
end
|
||||
|
||||
local function tp_game(player, arena)
|
||||
local pos = arenas[arena].game
|
||||
player:setpos(pos)
|
||||
player:set_look_vertical(pos.pitch)
|
||||
player:set_look_horizontal(pos.yaw)
|
||||
end
|
||||
|
||||
local function tp_back(player, arena)
|
||||
local pos = games[arena].locs[player:get_player_name()]
|
||||
player:setpos(pos)
|
||||
player:set_look_vertical(pos.pitch)
|
||||
player:set_look_horizontal(pos.yaw)
|
||||
end
|
||||
|
||||
local function create_game(arena)
|
||||
games[arena] = {
|
||||
players = {}, spectators = {}, invs = {}, locs = {}, leaves = {}, hits = {},
|
||||
start = {}, channels = {}, started = false, time = 0, fond = 0
|
||||
}
|
||||
superchat.add_channel('pvparena.' .. arena)
|
||||
end
|
||||
|
||||
local function get_inv(inv)
|
||||
local result = {}
|
||||
for key, value in pairs(inv:get_lists()) do
|
||||
local list = {}
|
||||
for k, v in pairs(value) do list[k] = v:to_table() end
|
||||
result[key] = list
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local function clear_inv(inv)
|
||||
for key, value in pairs(inv:get_lists()) do
|
||||
for k, v in pairs(value) do inv:remove_item(key, v) end
|
||||
end
|
||||
end
|
||||
|
||||
local function set_inv(inv, data)
|
||||
clear_inv(inv)
|
||||
for key, value in pairs(data) do
|
||||
for k, v in pairs(value) do inv:add_item(key, v) end
|
||||
end
|
||||
end
|
||||
|
||||
local function get_top(arena)
|
||||
local players = {}
|
||||
local hits = {}
|
||||
for key, value in pairs(games[arena].hits) do blocks[value] = key end
|
||||
local result = {}
|
||||
local i = 1
|
||||
for key, value in pairs(hits) do
|
||||
result[value] = i
|
||||
i = i + 1
|
||||
end
|
||||
local ys = {}
|
||||
for key, value in pairs(games[arena].players) do
|
||||
local y = minetest.get_player_by_name(value):getpos().y
|
||||
if not ys[y] then ys[y] = value end
|
||||
table.insert(players, value)
|
||||
end
|
||||
local result2 = {}
|
||||
i = 1
|
||||
for key, value in pairs(ys) do
|
||||
result2[value] = i
|
||||
i = i + 1
|
||||
end
|
||||
for key in pairs(games[arena].leaves) do table.insert(players, key) end
|
||||
local result3 = {}
|
||||
i = math.abs(#games[arena].players - #games[arena].leaves)
|
||||
for key, value in pairs(players) do
|
||||
if games[arena].leaves[value] then
|
||||
result3[games[arena].leaves[value]] = value
|
||||
elseif result2[value] then
|
||||
result3[result2[value]] = value
|
||||
elseif result[value] then
|
||||
local p = result[value]
|
||||
while result3[p] do p = p - 1 end
|
||||
result3[p] = value
|
||||
else
|
||||
while result3[i] do i = i - 1 end
|
||||
result3[i] = value
|
||||
i = i - 1
|
||||
end
|
||||
end
|
||||
return result3
|
||||
end
|
||||
|
||||
local function stop_game(arena)
|
||||
local fond = games[arena].fond
|
||||
local mess = ''
|
||||
local top = get_top(arena)
|
||||
for key, value in pairs(top) do
|
||||
local priz = 0
|
||||
if #top > 2 then priz = fond / 2 else priz = fond end
|
||||
if priz > 0 then
|
||||
coins.add_coins(value, priz * boost)
|
||||
minetest.chat_send_player(value, S('%dst, give %d coins'):format(key, priz * boost))
|
||||
end
|
||||
mess = mess .. S('%dst'):format(key) .. ': ' .. value
|
||||
fond = fond - priz
|
||||
end
|
||||
for _, name in pairs(games[arena].players) do
|
||||
local player = minetest.get_player_by_name(name)
|
||||
tp_back(player, arena)
|
||||
set_inv(player:get_inventory(), games[arena].invs[name])
|
||||
minetest.chat_send_player(name, mess)
|
||||
superchat.change_channel(name, games[arena].channels[name])
|
||||
gamers[name] = nil
|
||||
gui_menu.reset_formspec(name)
|
||||
end
|
||||
for _, name in pairs(games[arena].spectators) do
|
||||
local player = minetest.get_player_by_name(name)
|
||||
tp_back(player, arena)
|
||||
minetest.chat_send_player(name, mess)
|
||||
superchat.change_channel(name, games[arena].channels[name])
|
||||
superchat.del_channel('pvparena.' .. arena)
|
||||
gamers[name] = nil
|
||||
gui_menu.reset_formspec(name)
|
||||
end
|
||||
superchat.del_channel('superchat.' .. arena)
|
||||
games[arena] = nil
|
||||
end
|
||||
|
||||
local function leave(player_name)
|
||||
local arena = gamers[player_name].arena
|
||||
local player = minetest.get_player_by_name(player_name)
|
||||
tp_back(player, arena)
|
||||
if games[arena].invs[player_name] then
|
||||
set_inv(player:get_inventory(), games[arena].invs[player_name])
|
||||
end
|
||||
if games[arena].channels[player_name] then
|
||||
superchat.change_channel(player_name, games[arena].channels[player_name])
|
||||
end
|
||||
games[arena].channels[player_name] = nil
|
||||
games[arena].invs[player_name] = nil
|
||||
if games[arena].started then
|
||||
coins.add_coins(player_name, arenas[arena].cost)
|
||||
games[arena].fond = games[arena].fond - arenas[arena].cost
|
||||
end
|
||||
local i = 1
|
||||
if gamers[player_name].spec then
|
||||
for key, value in pairs(games[arena].spectators) do
|
||||
if value == player_name then
|
||||
table.remove(games[arena].spectators, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
if games[arena].started then games[arena].leaves[player_name] = #games[arena].players end
|
||||
for key, value in pairs(games[arena].players) do
|
||||
if value == player_name then
|
||||
table.remove(games[arena].players, i)
|
||||
break
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
gamers[player_name] = nil
|
||||
gui_menu.reset_formspec(player_name)
|
||||
if player:is_player_connected() then
|
||||
minetest.chat_send_player(player_name, S('You leaving from %s'):format(arena))
|
||||
end
|
||||
if not games[arena].players or #games[arena].players <= 1 then stop_game(arena) end
|
||||
end
|
||||
|
||||
local function is_in_arena(arena, pos)
|
||||
if not arenas[arena] or not arenas[arena].zone or not arenas[arena].zone.pos1 or not arenas[arena].zone.pos2 then
|
||||
return false
|
||||
end
|
||||
return cuboids_lib.contains(cuboids_lib.get_cube(arenas[arena].zone.pos1, arenas[arena].zone.pos2), pos)
|
||||
end
|
||||
|
||||
local function worker(arena)
|
||||
if not games[arena] then return end
|
||||
for _, name in ipairs(games[arena].players) do
|
||||
if not is_in_arena(arena, minetest.get_player_by_name(name):getpos()) then
|
||||
leave(name)
|
||||
end
|
||||
end
|
||||
if not games[arena] then return end
|
||||
if os.time() - games[arena].time >= arenas[arena].max_time then
|
||||
stop_game(arena)
|
||||
return
|
||||
end
|
||||
minetest.after(1, worker, arena)
|
||||
end
|
||||
|
||||
local function t_len(t)
|
||||
local result = 0
|
||||
for key in pairs(t) do result = result + 1 end
|
||||
return result
|
||||
end
|
||||
|
||||
local function start_game(arena)
|
||||
superchat.add_channel('pvparena.' .. arena)
|
||||
for _, name in ipairs(games[arena].players) do
|
||||
local inv = minetest.get_player_by_name(name):get_inventory()
|
||||
games[arena].invs[name] = get_inv(inv)
|
||||
if arenas[arena].kits then
|
||||
local n = math.random(t_len(arenas[arena].kits))
|
||||
local i = 1
|
||||
for key, value in pairs(arenas[arena].kits) do
|
||||
if i == n then
|
||||
set_inv(inv, value)
|
||||
minetest.chat_send_player(name, S('give %s kit'):format(key))
|
||||
break
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
games[arena].channels[name] = superchat.get_player_channel(name)
|
||||
superchat.change_channel(name, 'pvparena.' .. arena)
|
||||
tp_game(minetest.get_player_by_name(name), arena)
|
||||
gamers[name] = minetest.parse_json('{"arena":"' .. arena .. '","spec":false}')
|
||||
minetest.chat_send_player(name, S('============ PvP ARENA ============'))
|
||||
minetest.chat_send_player(name, S('-------> CHAT SEPARATE <-------'))
|
||||
minetest.chat_send_player(name, S('GAME WILL STARTING, PLEASE WAIT...'))
|
||||
minetest.chat_send_player(name, S('============ PvP ARENA ============'))
|
||||
end
|
||||
for _, name in ipairs(games[arena].spectators) do
|
||||
games[arena].channels[name] = superchat.get_player_channel(name)
|
||||
superchat.change_channel(name, 'pvparena.' .. arena)
|
||||
gamers[name] = minetest.parse_json('{"arena":' .. arena .. ',"spec":false}')
|
||||
minetest.chat_send_player(name, S('============ PvP ARENA ============'))
|
||||
minetest.chat_send_player(name, S('-------> CHAT SEPARATE <-------'))
|
||||
minetest.chat_send_player(name, S('GAME WILL STARTING, PLEASE WAIT...'))
|
||||
minetest.chat_send_player(name, S('============ PvP ARENA ============'))
|
||||
end
|
||||
minetest.after(arenas[arena].after, function(a)
|
||||
if not games[a] then return end
|
||||
games[a].time = os.time()
|
||||
games[a].started = true
|
||||
for _, name in ipairs(games[a].players) do
|
||||
minetest.chat_send_player(name, S('START GAME!!! RUN!'))
|
||||
end
|
||||
for _, name in ipairs(games[a].spectators) do
|
||||
minetest.chat_send_player(name, S('START GAME!!! SEE!'))
|
||||
end
|
||||
minetest.after(1, worker, arena)
|
||||
end, arena)
|
||||
games[arena].fond = #games[arena].players * arenas[arena].cost
|
||||
end
|
||||
|
||||
local function tfloor(pos)
|
||||
for key, value in pairs(pos) do pos[key] = math.floor(value) end
|
||||
return pos
|
||||
end
|
||||
|
||||
local function set_area(arena, pos1, pos2)
|
||||
sets[arena].reg = {tfloor(pos1), tfloor(pos2)}
|
||||
end
|
||||
|
||||
local function set_zone(arena, pos1, pos2)
|
||||
sets[arena].zone = {tfloor(pos1), tfloor(pos2)}
|
||||
end
|
||||
|
||||
local function set_settings(arena, min_p, max_p, after, max_time, cost)
|
||||
sets[arena].minp = min_p
|
||||
sets[arena].maxp = max_p
|
||||
sets[arena]['max_time'] = max_time
|
||||
sets[arena]['after'] = after
|
||||
sets[arena]['cost'] = cost
|
||||
end
|
||||
|
||||
local function save()
|
||||
mod_configs.save_json('pvp_arena', 'arenas', arenas)
|
||||
end
|
||||
|
||||
local function done(arena)
|
||||
arenas[arena] = sets[arena]
|
||||
arenas[arena].edit = false
|
||||
save()
|
||||
sets[arena] = nil
|
||||
if minetest.global_exists('pvp_control') then
|
||||
pvp_control.add_cuboid('pvparena.' .. arena, cuboids_lib.get_cube(arenas[arena].reg.pos1,
|
||||
arenas[arena].reg.pos2), false, true)
|
||||
end
|
||||
end
|
||||
|
||||
local function remove(arena)
|
||||
arenas[arena] = nil
|
||||
save()
|
||||
end
|
||||
|
||||
local function is_arena(pos)
|
||||
for key, value in pairs(arenas) do
|
||||
if cuboids_lib.contains(cuboids_lib.get_cube(value.reg.pos1, value.reg.pos2), pos) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function to_lobby(player, arena)
|
||||
local player_name = player:get_player_name()
|
||||
if not games[arena] then create_game(arena) end
|
||||
table.insert(games[arena].players, player_name)
|
||||
gamers[player_name] = minetest.parse_json('{"arena":"' .. arena .. '","spec":false}')
|
||||
coins.take_coins(player_name, arenas[arena].cost)
|
||||
tp_lobby(player, arena)
|
||||
end
|
||||
|
||||
local function to_spectate(player, arena)
|
||||
local player_name = player:get_player_name()
|
||||
table.insert(games[arena].spectators, player_name)
|
||||
gamers[player_name] = minetest.parse_json('{"arena":"' .. arena .. '","spec":true}')
|
||||
tp_spectate(player, arena)
|
||||
end
|
||||
|
||||
local function vote_start(arena, name)
|
||||
if games[arena].start then
|
||||
for key, value in pairs(games[arena].start) do
|
||||
if value == name then return false end
|
||||
end
|
||||
end
|
||||
table.insert(games[arena].start, name)
|
||||
if #games[arena].start == #games[arena].players and #games[arena].players >= arenas[arena].minp then
|
||||
start_game(arena)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- PVP CONTROL SUPPORT
|
||||
if minetest.global_exists('pvp_control') then
|
||||
for key, value in pairs(arenas) do
|
||||
pvp_control.add_cuboid('pvparena.' .. key, cuboids_lib.get_cube(arenas[key].reg.pos1,
|
||||
arenas[key].reg.pos2), false, true)
|
||||
end
|
||||
end
|
||||
|
||||
-- EVENTS
|
||||
minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, pos, damage)
|
||||
local pname = player:get_player_name()
|
||||
local hname = player:get_player_name()
|
||||
if gamers[pname] then
|
||||
local arena = gamers[pname].arena
|
||||
if not gamers[hname] or gamers[hname].spec then return true end
|
||||
if not games[arena].started then return true end
|
||||
if not cuboids_lib.contains(cuboibds_lib.get_cube(games[arena].zone.pos1, games[arena].zone.pos2), pos) then
|
||||
return true
|
||||
end
|
||||
if games[arena].hits[hname] then games[arena].hits[hname] = games[arena].hits[hname] + 1 else
|
||||
games[arena].hits[hname] = 1 end
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_dieplayer(function(player)
|
||||
local player_name = player:get_player_name()
|
||||
if gamers[player_name] then leave(player_name) end
|
||||
end)
|
||||
|
||||
minetest.register_on_respawnplayer(function(player)
|
||||
local player_name = player:get_player_name()
|
||||
if gamers[player_name] then leave(player_name) end
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local player_name = player:get_player_name()
|
||||
if gamers[player_name] then leave(player_name) end
|
||||
end)
|
||||
|
||||
minetest.register_on_shutdown(function()
|
||||
for key in pairs(games) do stop_game(key) end
|
||||
mod_configs.save_json('pvp_arena', 'chache_games', games)
|
||||
mod_configs.save_json('pvp_arena', 'chache_gamers', gamers)
|
||||
mod_configs.save_json('pvp_arena', 'chache_sets', sets)
|
||||
mod_configs.save_json('pvp_arena', 'cache_editors', editors)
|
||||
end)
|
||||
|
||||
minetest.register_on_dignode(function(pos, oldnode, digger)
|
||||
if is_arena(pos) then return true end
|
||||
end)
|
||||
|
||||
minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing)
|
||||
local player_name = puncher:get_player_name()
|
||||
if editors[player_name] then
|
||||
editors[player_name].pos = pos
|
||||
minetest.chat_send_player(player_name, S('Pos') .. ': ' .. minetest.pos_to_string(pos))
|
||||
end
|
||||
if is_arena(pos) then return true end
|
||||
end)
|
||||
|
||||
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
|
||||
if is_arena(pos) then return true end
|
||||
end)
|
||||
|
||||
local old_is_protected = minetest.is_protected
|
||||
function minetest.is_protected(pos, name)
|
||||
if is_arena(pos) then
|
||||
return true
|
||||
end
|
||||
return old_is_protected(pos, name)
|
||||
end
|
||||
|
||||
-- REGISTRATIONS
|
||||
minetest.register_privilege('pvpa', S('For using pvp arena'))
|
||||
minetest.register_privilege('pvpamod', S('For manage pvp games'))
|
||||
minetest.register_privilege('pvpaadm', S('For editing arenas'))
|
||||
|
||||
-- COMMANDS
|
||||
minetest.register_chatcommand('pacreate', {
|
||||
params = '<arena>',
|
||||
description = S('start creating pvp arena'),
|
||||
privs = {pvpaadm = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not arena') end
|
||||
if arenas[params] or sets[params] then
|
||||
return false, S('%s is found'):format(params)
|
||||
end
|
||||
sets[params] = minetest.parse_json('{"edit":false}')
|
||||
editors[name] = minetest.parse_json('{"arena":"' .. params .. '"}')
|
||||
return true, S('arena %s created'):format(params)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('paedit', {
|
||||
params = '<arena>',
|
||||
description = S('start editing pvp arena'),
|
||||
privs = {pvpaadm = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not arena') end
|
||||
if games[params] then return false, S('%s is started'):format(params) end
|
||||
if not arenas[params] then return false, S('%s not found') end
|
||||
sets[params] = arenas[params]
|
||||
arenas[params].edit = true
|
||||
editors[name] = minetest.parse_json('{"arena":"' .. params .. '"}')
|
||||
if minetest.global_exists('pvp_control') then
|
||||
pvp_control.del_cuboid('pvpcontrol.' .. params)
|
||||
end
|
||||
return true, S('%s edit mode on'):format(params)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('padone', {
|
||||
params = 'none',
|
||||
description = S('done editing'),
|
||||
privs = {pvpaadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
done(arena)
|
||||
editors[name] = nil
|
||||
return true, S('%s done editing'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('paremove', {
|
||||
params = '<arena>',
|
||||
description = S('remove arena'),
|
||||
privs = {pvpaadm = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not arena') end
|
||||
if not arenas[params] then return false, S('%s not found') end
|
||||
remove(params)
|
||||
return true, S('%s removed'):format(params)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('pareload', {
|
||||
params = 'none',
|
||||
description = S('reload arenas config'),
|
||||
privs = {pvpaadm = true},
|
||||
func = function(name, params)
|
||||
load_file()
|
||||
return true, S('settings reloaded')
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('papos1', {
|
||||
params = 'none',
|
||||
description = S('set pvp arena region pos1'),
|
||||
privs = {pvpaadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
if not editors[name].pos then return false, S('not selected point') end
|
||||
editors[name].pos1 = editors[name].pos
|
||||
if editors[name].pos2 then
|
||||
set_area(arena, editors[name].pos1, editors[name].pos2)
|
||||
end
|
||||
return true, S('pos1 for %s set'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('papos2', {
|
||||
params = '<arena>',
|
||||
description = S('set pvp arena region pos2'),
|
||||
privs = {pvpaadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
if not editors[name].pos then return false, S('not selected point') end
|
||||
editors[name].pos2 = editors[name].pos
|
||||
if editors[name].pos1 then
|
||||
set_area(arena, editors[name].pos1, editors[name].pos2)
|
||||
end
|
||||
return true, S('pos2 for %s set'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('pazpos1', {
|
||||
params = 'none',
|
||||
description = S('set pvp arena battle zone pos1'),
|
||||
privs = {pvpaadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
if not editors[name].pos then return false, S('not selected point') end
|
||||
editors[name].fpos1 = editors[name].pos
|
||||
if editors[name].fpos2 then
|
||||
set_zone(arena, editors[name].fpos1, editors[name].fpos2)
|
||||
end
|
||||
return true, S('zpos1 for %s set'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('pazpos2', {
|
||||
params = 'none',
|
||||
description = S('set pvp arena battle zone pos2'),
|
||||
privs = {pvpaadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
if not editors[name].pos then return false, S('not selected point') end
|
||||
editors[name].fpos2 = editors[name].pos
|
||||
if editors[name].fpos1 then
|
||||
set_floor(arena, editors[name].fpos1, editors[name].fpos2)
|
||||
end
|
||||
return true, S('zpos2 for %s set'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('pasettings', {
|
||||
params = '<min_p> <max_p> <after> <max_time> <cost>',
|
||||
description = S('set pvp arena settings'),
|
||||
privs = {pvpaadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not args') end
|
||||
local params = params:split(' ')
|
||||
if #params < 1 then return false, S('invalid command, not min_players') end
|
||||
if #params < 2 then return false, S('invalid command, not max_players') end
|
||||
if #params < 3 then return false, S('invalid command, not after') end
|
||||
if #params < 4 then return false, S('invalid command, not max_time') end
|
||||
if #params < 5 then return false, S('invalid command, not cost') end
|
||||
for i = 1, 5 do
|
||||
params[i] = params[i]:trim()
|
||||
if not params[i]:match('^[0-9]*$') then
|
||||
return false, S('incorrect number %s'):format(params[1])
|
||||
end
|
||||
end
|
||||
set_settings(
|
||||
arena, tonumber(params[1]), tonumber(params[2]),
|
||||
tonumber(params[3]), tonumber(params[4]), tonumber(params[5])
|
||||
)
|
||||
return true, S('%s settings set'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('palobby', {
|
||||
params = 'none',
|
||||
description = S('set pvp arena lobby point'),
|
||||
privs = {pvpaadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local pos = player:getpos()
|
||||
pos.pitch = player:get_look_vertical()
|
||||
pos.yaw = player:get_look_horizontal()
|
||||
sets[arena].lobby = pos
|
||||
return true, S('%s lobby point set'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('paspec', {
|
||||
params = 'none',
|
||||
description = S('set pvp arena spectate point'),
|
||||
privs = {pvpaadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local pos = player:getpos()
|
||||
pos.pitch = player:get_look_vertical()
|
||||
pos.yaw = player:get_look_horizontal()
|
||||
sets[arena].spec = pos
|
||||
return true, S('%s spectate point set'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('pagame', {
|
||||
params = 'none',
|
||||
description = S('set pvp arena game point'),
|
||||
privs = {pvpaadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local pos = player:getpos()
|
||||
pos.pitch = player:get_look_vertical()
|
||||
pos.yaw = player:get_look_horizontal()
|
||||
sets[arena].game = pos
|
||||
return true, S('%s game point set'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('pakit', {
|
||||
params = '<name>',
|
||||
description = S('add kit for pvp arena'),
|
||||
privs = {pvpaadm = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not kit name') end
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
if not sets[arena].kits then sets[arena].kits = {} end
|
||||
sets[arena].kits[params] = get_inv(minetest.get_player_by_name(name):get_inventory())
|
||||
return true, S('kit %s added'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('paremkit', {
|
||||
params = '<name>',
|
||||
description = S('delete kit for pvp arena'),
|
||||
privs = {pvpaadm = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not kit name') end
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
if not sets[arena].kits or not sets[arena].kits[params] then return false, S('kit %s not found') end
|
||||
sets[arena].kits[params] = nil
|
||||
return true, S('kit %s removed'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('pakits', {
|
||||
params = 'none',
|
||||
description = S('show kits in arena'),
|
||||
privs = {pvpaadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
if not arena[arena].kits then return false, S('not kits') end
|
||||
local result = ''
|
||||
for key in pairs(arena[arena].kits) do
|
||||
result = result .. key .. ', '
|
||||
end
|
||||
return true, S('Kits arena %s: %s'):format(arena, result:sub(0, result:len()-2))
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('pakick', {
|
||||
params = '<player>',
|
||||
description = S('kick player from pvp arena'),
|
||||
privs = {pvpamod = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not player name') end
|
||||
if not gamers[params] then return false, S('%s not in pvp arena'):format(params) end
|
||||
local arena = gamers[params].arena
|
||||
leave(params)
|
||||
minetest.chat_send_player(params, S('%s kicking you from pvp arena %s'):format(name, arena))
|
||||
return true, S('%s kicked from pvp arena %s'):format(params, arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('pastop', {
|
||||
params = '<arena>',
|
||||
description = S('stop pvp arena'),
|
||||
privs = {pvpamod = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not arena') end
|
||||
if not games[params] or not games[params].started then return false, S('%s not started'):format(params) end
|
||||
superchat.send(name, 'pvparena.' .. params, S('FORCE STOPPING GAME'))
|
||||
stop_game(params)
|
||||
return true, S('%s stopped'):format(params)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('pastart', {
|
||||
params = '<arena>',
|
||||
description = S('start pvp arena'),
|
||||
privs = {pvpamod = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not arena') end
|
||||
if not games[params] or not games[params].started then return false, S('%s not started'):format(params) end
|
||||
superchat.send(name, 'pvparena.' .. params, S('FORCE STARTING GAME'))
|
||||
start_game(params)
|
||||
return true, S('%s started'):format(params)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('pa', {
|
||||
params = '<list/join/spec/leave/start>',
|
||||
description = S('gamers commands'),
|
||||
privs = {pvpa = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not arg') end
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if params == 'list' then
|
||||
local str = ''
|
||||
for key, value in ipairs(pvp_arena.get_arenas()) do
|
||||
str = str .. value .. ', '
|
||||
end
|
||||
if str:len() > 0 then return true, S('Arenas') .. ': ' .. str:sub(0, str:len() - 2)
|
||||
else return false, S('not arenas') end
|
||||
elseif params:sub(0, 4) == 'join' then
|
||||
local params = params:split(' ')
|
||||
if #params < 2 then return false, S('invalid command, not arena') end
|
||||
local arena = params[2]
|
||||
if not arenas[arena] then return false, S('%s not found'):format(arena) end
|
||||
if games[arena] and games[arena].started then return false, S('%s is started'):format(arena) end
|
||||
if not coins.get_coins(name) or coins.get_coins(name) < arenas[arena].cost then
|
||||
return false, S('sorry, not %d coins in you balance'):format(arenas[arena].cost)
|
||||
end
|
||||
if games[arena] and #games[arena].players >= arenas[arena].maxp then
|
||||
return false, S('%s is full'):format(arena)
|
||||
end
|
||||
if gamers[name] then return false, S('You playing arena %s'):format(arena) end
|
||||
to_lobby(player, arena)
|
||||
return true, S('Joined %s arena, taking %d coins'):format(arena, arenas[arena].cost)
|
||||
elseif params:sub(0, 4) == 'spec' then
|
||||
local params = params:split(' ')
|
||||
if #params < 2 then return false, S('invalid command, not arena') end
|
||||
if not games[params[2]] then return false, S('%s not started'):format(params[2]) end
|
||||
if gamers[name] then return false, S('You playing arena %s'):format(arena) end
|
||||
to_spectate(player, params[2])
|
||||
return true, S('You spectate %s arena'):format(params[2])
|
||||
elseif params == 'leave' then
|
||||
if not gamers[name] then return false, S('you not in pvp arena') end
|
||||
local arena = gamers[name].arena
|
||||
leave(name)
|
||||
gui_menu.reset_formspec(name)
|
||||
return true, S('you leaving from %s arena'):format(arena)
|
||||
elseif params == 'start' then
|
||||
if not gamers[name] then return false, S('you not in pvp arena') end
|
||||
local arena = gamers[name].arena
|
||||
local v = vote_start(arena, name)
|
||||
if not v then return false, S('you have already voted') end
|
||||
return true, S('You vote start game')
|
||||
else
|
||||
return false, S('Using /pa list/join/spec/leave/start')
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- MENU SUPPORT
|
||||
if minetest.global_exists('gui_menu') then
|
||||
gui_menu.add_listener(function(player_name, cat, page, fields)
|
||||
local player = minetest.get_player_by_name(player_name)
|
||||
|
||||
local function ga()
|
||||
local add = pvp_arena.get_arenas()
|
||||
if add then
|
||||
local result = {}
|
||||
result[S('PvP arenas')] = {}
|
||||
for key, value in pairs(add) do
|
||||
result[S('PvP arenas')]['pvparena.' .. value] = {text = value}
|
||||
end
|
||||
return result
|
||||
end
|
||||
end
|
||||
|
||||
local ga2 = ga()
|
||||
if not ga2 then return nil end
|
||||
if not cat and not fields then
|
||||
return ga()
|
||||
elseif not fields then return nil
|
||||
elseif fields['gui_menu:cat.' .. S('PvP arenas')] then
|
||||
gui_menu.show_buttons(player_name, S('PvP arenas'), ga2[S('PvP arenas')], 1)
|
||||
elseif cat == S('PvP arenas') and fields['gui_menu:pgo'] then
|
||||
gui_menu.show_buttons(player_name, S('PvP arenas'), ga2[S('PvP arenas')], page + 1)
|
||||
elseif cat == S('PvP arenas') and fields['gui_menu:pback'] then
|
||||
gui_menu.show_buttons(player_name, S('PvP arenas'), ga2[S('PvP arenas')], page - 1)
|
||||
elseif cat == S('PvP arenas') and fields then
|
||||
local lstr = 'size[3,1]button[0,0;3,1;pvparena.leave;' .. S('Leave') .. ']'
|
||||
local sstr = 'size[6,1]button[0,0;3,1;pvparena.start;' .. S('Vote start') .. ']button[3,0;3,1;pvparena.leave;' .. S('Leave') .. ']'
|
||||
if fields['pvparena.leave'] then
|
||||
if not gamers[player_name] then
|
||||
minetest.chat_send_player(player_name, S('you not in pvp arena'))
|
||||
gui_menu.reset_formspec(player_name)
|
||||
gui_menu.show_cat(player_name, nil)
|
||||
return
|
||||
end
|
||||
leave(player_name)
|
||||
gui_menu.reset_formspec(player_name)
|
||||
gui_menu.show_cat(player_name, nil)
|
||||
return
|
||||
elseif fields['pvparena.close'] then
|
||||
gui_menu.show_cat(player_name, nil)
|
||||
return
|
||||
elseif fields['pvparena.start'] then
|
||||
if not gamers[player_name] then
|
||||
minetest.chat_send_player(player_name, S('you not in pvp arena'))
|
||||
gui_menu.set_formspec(player_name, lstr)
|
||||
minetest.show_formspec(player_name, 'gui_menu', lstr)
|
||||
return
|
||||
end
|
||||
local v = vote_start(gamers[player_name].arena, player_name)
|
||||
if not v then
|
||||
minetest.chat_send_player(player_name, S('you have already voted'))
|
||||
end
|
||||
minetest.chat_send_player(player_name, S('You vote start game'))
|
||||
gui_menu.set_formspec(player_name, lstr)
|
||||
minetest.show_formspec(player_name, 'gui_menu', lstr)
|
||||
return
|
||||
end
|
||||
|
||||
local function f(player, arena)
|
||||
local result = 'size[8,1]button[7,0;1,1;pvparena.close;X]'
|
||||
if games[arena] then
|
||||
result = result .. 'button[4,0;3,1;pvparena.' .. arena .. '.spec;' .. S('Spectate') .. ']'
|
||||
end
|
||||
if not games[arena] or not games[arena].started or #games[arena].players < arenas[arena].maxp then
|
||||
result = result .. 'button[0,0;3,1;pvparena.' .. arena .. '.join;' .. S('Join') .. ']'
|
||||
end
|
||||
minetest.show_formspec(player_name, 'gui_menu', result)
|
||||
end
|
||||
|
||||
local ar = pvp_arena.get_arenas()
|
||||
if not arenas then return nil end
|
||||
for key, value in pairs(ar) do
|
||||
if fields['pvparena.' .. value] then
|
||||
return {func = f, args = {value}}
|
||||
elseif fields['pvparena.' .. value .. '.join'] then
|
||||
if gamers[player_name] then
|
||||
minetest.chat_send_player(player_name, S('You playing arena %s'):format(value))
|
||||
return
|
||||
end
|
||||
if games[value] and games[value].started then
|
||||
minetest.chat_send_player(player_name, S('%s is started'):format(value))
|
||||
return
|
||||
end
|
||||
if not coins.get_coins(player_name) or coins.get_coins(player_name) < arenas[value].cost then
|
||||
minetest.chat_send_player(player_name, S('sorry, not %d coins in you balance'):format(arenas[value].cost))
|
||||
return
|
||||
end
|
||||
if games[value] and #games[value].players >= arenas[value].maxp then
|
||||
minetest.chat_send_player(player_name, S('%s is full'):format(value))
|
||||
return
|
||||
end
|
||||
to_lobby(player, value)
|
||||
minetest.chat_send_player(player_name, S('Joined %s arena, taking %d coins'):format(value, arenas[value].cost))
|
||||
gui_menu.set_formspec(player_name, sstr)
|
||||
minetest.show_formspec(player_name, 'gui_menu', sstr)
|
||||
elseif fields['pvparena.' .. value .. '.spec'] then
|
||||
if not games[value] then
|
||||
minetest.chat_send_player(player_name, S('%s not started'):format(value))
|
||||
return
|
||||
end
|
||||
if gamers[player_name] then
|
||||
minetest.chat_send_player(player_name, S('You playing arena %s'):format(value))
|
||||
return
|
||||
end
|
||||
to_spectate(player, value)
|
||||
minetest.chat_send_player(player_name, S('You spectate %s arena'):format(value))
|
||||
gui_menu.set_formspec(player_name, lstr)
|
||||
minetest.show_formspec(player_name, 'gui_menu', lstr)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
|
@ -0,0 +1,96 @@
|
|||
# init.lua
|
||||
%dst, give %d coins =
|
||||
%dst =
|
||||
You leaving from %s =
|
||||
give %s kit =
|
||||
'============ PvP ARENA ============' =
|
||||
-------> CHAT SEPARATE <------- =
|
||||
GAME WILL STARTING, PLEASE WAIT... =
|
||||
START GAME!!! RUN! =
|
||||
START GAME!!! SEE! =
|
||||
Pos =
|
||||
For using pvp arena =
|
||||
For manage pvp games =
|
||||
For editing arenas =
|
||||
start creating pvp arena =
|
||||
invalid command, not arena =
|
||||
%s is found =
|
||||
arena %s created =
|
||||
start editing pvp arena =
|
||||
%s is started =
|
||||
%s not found =
|
||||
%s edit mode on =
|
||||
done editing =
|
||||
need edit mode on =
|
||||
%s done editing =
|
||||
remove arena =
|
||||
%s removed =
|
||||
reload arenas config =
|
||||
settings reloaded =
|
||||
set pvp arena region pos1 =
|
||||
need edit mode on =
|
||||
not selected point =
|
||||
pos1 for %s set =
|
||||
set pvp arena region pos2 =
|
||||
pos2 for %s set =
|
||||
set pvp arena battle zone pos1 =
|
||||
zpos1 for %s set =
|
||||
set pvp arena battle zone pos2 =
|
||||
zpos2 for %s set =
|
||||
set pvp arena settings =
|
||||
invalid command, not args =
|
||||
invalid command, not min_players =
|
||||
invalid command, not max_players =
|
||||
invalid command, not after =
|
||||
invalid command, not max_time =
|
||||
invalid command, not cost =
|
||||
incorrect number %s =
|
||||
%s settings set =
|
||||
set pvp arena lobby point =
|
||||
%s lobby point set =
|
||||
set pvp arena spectate point =
|
||||
%s spectate point set =
|
||||
set pvp arena game point =
|
||||
%s game point set =
|
||||
add kit for pvp arena =
|
||||
invalid command, not kit name =
|
||||
kit %s added =
|
||||
delete kit for pvp arena =
|
||||
kit %s not found =
|
||||
kit %s removed =
|
||||
show kits in arena =
|
||||
not kits =
|
||||
Kits arena %s: %s =
|
||||
kick player from pvp arena =
|
||||
invalid command, not player name =
|
||||
%s not in pvp arena =
|
||||
%s kicking you from pvp arena %s =
|
||||
%s kicked from pvp arena %s =
|
||||
stop pvp arena =
|
||||
%s not started =
|
||||
FORCE STOPPING GAME =
|
||||
%s stopped =
|
||||
start pvp arena =
|
||||
FORCE STARTING GAME =
|
||||
%s started =
|
||||
gamers commands =
|
||||
invalid command, not arg =
|
||||
Arenas =
|
||||
not arenas =
|
||||
%s is started =
|
||||
sorry, not %d coins in you balance =
|
||||
%s is full =
|
||||
You playing arena %s =
|
||||
Joined %s arena, taking %d coins =
|
||||
You spectate %s arena =
|
||||
you not in pvp arena =
|
||||
you leaving from %s arena =
|
||||
you not in pvp arena =
|
||||
you have already voted =
|
||||
You vote start game =
|
||||
Using /pa list/join/spec/leave/start =
|
||||
PvP arenas =
|
||||
Leave =
|
||||
Vote start =
|
||||
Spectate =
|
||||
Join =
|
|
@ -0,0 +1 @@
|
|||
mod = pvp_arena
|
|
@ -0,0 +1,91 @@
|
|||
# spleef
|
||||
|
||||
Spleef minigame for minetest. Auto regen floor, protect arena, there are lobby and spectate. The distribution of the prize coins. Take into account the order of leave, number of broken blocks, the Y coordinate. Support **gui_menu**.
|
||||
|
||||
## How to working?
|
||||
|
||||
* Gamers joining to lobby, moving coins cost from balance to fond.
|
||||
* Gamers voting start.
|
||||
* Regenerate floor.
|
||||
* Chat separate.
|
||||
* Gamers teleported to game point. Inventrory backup, give tool.
|
||||
* Pause.
|
||||
* Start game.
|
||||
* Game... floor immediately disappears from punch.
|
||||
* End game, distribution of the prize coins, give coins. Formula: "fond / 2 * boost", "fond = fond / 2".
|
||||
|
||||
Commands:
|
||||
|
||||
* **/spleef list** - show list available arenas
|
||||
* **/spleef join <arena>** - join to lobby
|
||||
* **/spleef spec <arena>** - watch
|
||||
* **/spleef leave** - leaving, if game not started - return coins cost
|
||||
* **/spleef start** - vote start
|
||||
|
||||
## How to create arena?
|
||||
|
||||
* **/spcreate <arena>**
|
||||
* Punch node (pos 1 arena region)
|
||||
* **/sppos1**
|
||||
* Punch node (pos 2 arena region)
|
||||
* **/sppos2**
|
||||
* Punch node (floor pos 1)
|
||||
* **/spfpos1**
|
||||
* Punch node (floor pos 2)
|
||||
* **/spfpos2**
|
||||
* Stand on the position.
|
||||
* **/splobby (save lobby position)**
|
||||
* Stand on the position.
|
||||
* **/spspec (save spectate position)**
|
||||
* Stand on the position.
|
||||
* **/spgame (save game position)**
|
||||
* **/spsettings <min_p> <max_p> <after> <max_time> <cost>**
|
||||
* **/sptool itemstring (optional)**
|
||||
* **/spdone**
|
||||
|
||||
Done! Editing:
|
||||
|
||||
* **/spedit <arena>**
|
||||
* ... editing ... (read above)
|
||||
* **/spdone**
|
||||
|
||||
For removing:
|
||||
|
||||
* **/spremove <arena>**
|
||||
|
||||
For reload config:
|
||||
|
||||
* **/spreload**
|
||||
|
||||
## Moder commands
|
||||
|
||||
* **/spkick <player>** - kick player from arena
|
||||
* **/spstop <arena>** - force stop game
|
||||
* **/spstart <arena>** - force start game
|
||||
|
||||
## Privs
|
||||
|
||||
* **spleef** - for access game commands
|
||||
* **spleefmod** - for access moder commands
|
||||
* **spleefadm** - for access admin commands (edit arenas)
|
||||
|
||||
## Settings for minetest.conf
|
||||
|
||||
* **spleef.tool = <itemstring>** - default item (optional, defaut - diamond shovel)
|
||||
|
||||
## Depends
|
||||
|
||||
* mod_configs
|
||||
* superchat
|
||||
* coins
|
||||
* cuboids_lib
|
||||
* gui_menu?
|
||||
* initlib?
|
||||
|
||||
## API
|
||||
|
||||
* **spleef.get_arenas()** - get available arenas, return array
|
||||
* **spleef.get_active_arenas()** - get started arenas, return table "{arena = #players + #spectators}"
|
||||
* **spleef.get_wait_arenas()** - get waiting arenas (gamers in lobby), return table "{arena = #players + #spectators}"
|
||||
* **spleef.set_boost(num)**
|
||||
* **spleef.get_boost()**
|
|
@ -0,0 +1,6 @@
|
|||
mod_configs
|
||||
superchat
|
||||
coins
|
||||
cuboids_lib
|
||||
gui_menu?
|
||||
initlib?
|
|
@ -0,0 +1,949 @@
|
|||
spleef = {}
|
||||
-- {arena {
|
||||
-- edit = true/false,
|
||||
-- lobby = {xyz},
|
||||
-- spec = {xyz},
|
||||
-- game = {xyz},
|
||||
-- floor = {{xyz} = {node}, ...}
|
||||
-- y_level = number,
|
||||
-- max_time = number,
|
||||
-- after = number,
|
||||
-- reg = {pos1 = {xyz}, pos2 = {xyz}},
|
||||
-- minp = number,
|
||||
-- maxp = number,
|
||||
-- cost = number,
|
||||
-- tool = string (optional)
|
||||
-- }, ...}
|
||||
local arenas = {}
|
||||
-- {arena {
|
||||
-- players = {array}, spectators = {array}, invs = {player_name = json string, ...}, locs = {player_name = {xyzpitchyaw}},
|
||||
-- leaves = {player_name = number, ...}, blocks = {player_name = number, ...}, start = {array},
|
||||
-- channels = {player_name = channel, ...}, started = true/false, time = number (time start), fond = number (all money)
|
||||
-- }, ...}
|
||||
local games = {}
|
||||
-- arenas analog
|
||||
local sets = {}
|
||||
-- {
|
||||
-- player_name = {arena = arena name, spec = true/false}, ...
|
||||
-- }
|
||||
local gamers = {}
|
||||
-- {player_name = arena = string, pos1 = {xyz}, pos2 = {xyz}, fpos1 = {xyz}, fpos2 = {xyz}, pos = {xyz}}
|
||||
local editors = {}
|
||||
local boost = 1
|
||||
|
||||
-- INITLIB
|
||||
local S, NS
|
||||
if minetest.global_exists('intllib') then
|
||||
S, NS = intllib.make_gettext_pair(minetest.get_current_modname())
|
||||
else
|
||||
S = function(s) return s end
|
||||
NS = S
|
||||
end
|
||||
|
||||
-- API
|
||||
function spleef.get_arenas()
|
||||
local result = {}
|
||||
for key, value in pairs(arenas) do
|
||||
if not value.edit then
|
||||
table.insert(result, key)
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function spleef.get_active_arenas()
|
||||
local result = {}
|
||||
for key, value in pairs(games) do
|
||||
if value.started then
|
||||
result[key] = #value.players + #value.spectators
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function spleef.get_wait_arenas()
|
||||
local result = {}
|
||||
for key, value in pairs(games) do
|
||||
if not value.started then
|
||||
result[key] = #value.players + #value.spectators
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function spleef.set_boost(num)
|
||||
boost = num
|
||||
end
|
||||
|
||||
function spleef.get_boost()
|
||||
return boost
|
||||
end
|
||||
|
||||
-- LOCAL FUNCTIONS
|
||||
local function load_file()
|
||||
arenas = mod_configs.load_json('spleef', 'arenas')
|
||||
if not arenas then arenas = {} end
|
||||
end
|
||||
|
||||
local function load_cache()
|
||||
sets = mod_configs.load_json('spleef', 'cache_sets')
|
||||
editors = mod_configs.load_json('spleef', 'cache_editors')
|
||||
if not sets then sets = {} end
|
||||
if not editors then editors = {} end
|
||||
end
|
||||
|
||||
load_file()
|
||||
--load_cache()
|
||||
|
||||
local function tp_lobby(player, arena)
|
||||
games[arena].locs[player:get_player_name()] = player:getpos()
|
||||
games[arena].locs[player:get_player_name()].pitch = player:get_look_vertical()
|
||||
games[arena].locs[player:get_player_name()].yaw = player:get_look_horizontal()
|
||||
local pos = arenas[arena].lobby
|
||||
player:setpos(pos)
|
||||
player:set_look_vertical(pos.pitch)
|
||||
player:set_look_horizontal(pos.yaw)
|
||||
end
|
||||
|
||||
local function tp_spectate(player, arena)
|
||||
games[arena].locs[player:get_player_name()] = player:getpos()
|
||||
games[arena].locs[player:get_player_name()].pitch = player:get_look_vertical()
|
||||
games[arena].locs[player:get_player_name()].yaw = player:get_look_horizontal()
|
||||
local pos = arenas[arena].spec
|
||||
player:setpos(pos)
|
||||
player:set_look_vertical(pos.pitch)
|
||||
player:set_look_horizontal(pos.yaw)
|
||||
end
|
||||
|
||||
local function tp_game(player, arena)
|
||||
local pos = arenas[arena].game
|
||||
player:setpos(pos)
|
||||
player:set_look_vertical(pos.pitch)
|
||||
player:set_look_horizontal(pos.yaw)
|
||||
end
|
||||
|
||||
local function tp_back(player, arena)
|
||||
local pos = games[arena].locs[player:get_player_name()]
|
||||
player:setpos(pos)
|
||||
player:set_look_vertical(pos.pitch)
|
||||
player:set_look_horizontal(pos.yaw)
|
||||
end
|
||||
|
||||
local function create_game(arena)
|
||||
games[arena] = {
|
||||
players = {}, spectators = {}, invs = {}, locs = {}, leaves = {}, blocks = {},
|
||||
start = {}, channels = {}, started = false, time = 0, fond = 0
|
||||
}
|
||||
superchat.add_channel('spleef.' .. arena)
|
||||
end
|
||||
|
||||
local function regen_floors(arena)
|
||||
for pos, node in pairs(arenas[arena].floor) do
|
||||
minetest.set_node(minetest.parse_json(pos), node)
|
||||
end
|
||||
end
|
||||
|
||||
local function get_top(arena)
|
||||
local players = {}
|
||||
local blocks = {}
|
||||
for key, value in pairs(games[arena].blocks) do blocks[value] = key end
|
||||
local result = {}
|
||||
local i = 1
|
||||
for key, value in pairs(blocks) do
|
||||
result[value] = i
|
||||
i = i + 1
|
||||
end
|
||||
local ys = {}
|
||||
for key, value in pairs(games[arena].players) do
|
||||
local y = minetest.get_player_by_name(value):getpos().y
|
||||
if not ys[y] then ys[y] = value end
|
||||
table.insert(players, value)
|
||||
end
|
||||
local result2 = {}
|
||||
i = 1
|
||||
for key, value in pairs(ys) do
|
||||
result2[value] = i
|
||||
i = i + 1
|
||||
end
|
||||
for key in pairs(games[arena].leaves) do table.insert(players, key) end
|
||||
local result3 = {}
|
||||
i = math.abs(#games[arena].players - #games[arena].leaves)
|
||||
for key, value in pairs(players) do
|
||||
if games[arena].leaves[value] then
|
||||
result3[games[arena].leaves[value]] = value
|
||||
elseif result2[value] then
|
||||
result3[result2[value]] = value
|
||||
elseif result[value] then
|
||||
local p = result[value]
|
||||
while result3[p] do p = p - 1 end
|
||||
result3[p] = value
|
||||
else
|
||||
while result3[i] do i = i - 1 end
|
||||
result3[i] = value
|
||||
i = i - 1
|
||||
end
|
||||
end
|
||||
return result3
|
||||
end
|
||||
|
||||
local function get_inv(inv)
|
||||
local result = {}
|
||||
for key, value in pairs(inv:get_lists()) do
|
||||
local list = {}
|
||||
for k, v in pairs(value) do list[k] = v:to_table() end
|
||||
result[key] = list
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
local function clear_inv(inv)
|
||||
for key, value in pairs(inv:get_lists()) do
|
||||
for k, v in pairs(value) do inv:remove_item(key, v) end
|
||||
end
|
||||
end
|
||||
|
||||
local function set_inv(inv, data)
|
||||
clear_inv(inv)
|
||||
for key, value in pairs(data) do
|
||||
for k, v in pairs(value) do inv:add_item(key, v) end
|
||||
end
|
||||
end
|
||||
|
||||
local function stop_game(arena)
|
||||
local fond = games[arena].fond
|
||||
local mess = ''
|
||||
local top = get_top(arena)
|
||||
for key, value in pairs(top) do
|
||||
local priz = 0
|
||||
if #top > 2 then priz = fond / 2 else priz = fond end
|
||||
if priz > 0 then
|
||||
coins.add_coins(value, priz * boost)
|
||||
minetest.chat_send_player(value, S('%dst, give %d coins'):format(key, priz * boost))
|
||||
end
|
||||
mess = mess .. S('%dst'):format(key) .. ': ' .. value
|
||||
fond = fond - priz
|
||||
end
|
||||
for _, name in pairs(games[arena].players) do
|
||||
local player = minetest.get_player_by_name(name)
|
||||
tp_back(player, arena)
|
||||
set_inv(player:get_inventory(), games[arena].invs[name])
|
||||
minetest.chat_send_player(name, mess)
|
||||
superchat.change_channel(name, games[arena].channels[name])
|
||||
gamers[name] = nil
|
||||
gui_menu.reset_formspec(name)
|
||||
end
|
||||
for _, name in pairs(games[arena].spectators) do
|
||||
local player = minetest.get_player_by_name(name)
|
||||
tp_back(player, arena)
|
||||
minetest.chat_send_player(name, mess)
|
||||
superchat.change_channel(name, games[arena].channels[name])
|
||||
superchat.del_channel('spleef.' .. arena)
|
||||
gamers[name] = nil
|
||||
gui_menu.reset_formspec(name)
|
||||
end
|
||||
superchat.del_channel('superchat.' .. arena)
|
||||
games[arena] = nil
|
||||
end
|
||||
|
||||
local function leave(player_name)
|
||||
local arena = gamers[player_name].arena
|
||||
local player = minetest.get_player_by_name(player_name)
|
||||
tp_back(player, arena)
|
||||
if games[arena].invs[player_name] then
|
||||
set_inv(player:get_inventory(), games[arena].invs[player_name])
|
||||
end
|
||||
if games[arena].channels[player_name] then
|
||||
superchat.change_channel(player_name, games[arena].channels[player_name])
|
||||
end
|
||||
games[arena].channels[player_name] = nil
|
||||
games[arena].invs[player_name] = nil
|
||||
if games[arena].started then
|
||||
coins.add_coins(player_name, arenas[arena].cost)
|
||||
games[arena].fond = games[arena].fond - arenas[arena].cost
|
||||
end
|
||||
local i = 1
|
||||
if gamers[player_name].spec then
|
||||
for key, value in pairs(games[arena].spectators) do
|
||||
if value == player_name then
|
||||
table.remove(games[arena].spectators, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
if games[arena].started then games[arena].leaves[player_name] = #games[arena].players end
|
||||
for key, value in pairs(games[arena].players) do
|
||||
if value == player_name then
|
||||
table.remove(games[arena].players, i)
|
||||
break
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
gamers[player_name] = nil
|
||||
gui_menu.reset_formspec(player_name)
|
||||
if player:is_player_connected() then
|
||||
minetest.chat_send_player(player_name, S('You leaving from %s'):format(arena))
|
||||
end
|
||||
if not games[arena].players or #games[arena].players <= 1 then stop_game(arena) end
|
||||
end
|
||||
|
||||
local function worker(arena)
|
||||
if not games[arena] then return end
|
||||
for _, name in ipairs(games[arena].players) do
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local y = player:getpos().y
|
||||
if y < arenas[arena].y_level then
|
||||
leave(name)
|
||||
end
|
||||
end
|
||||
if not games[arena] then return end
|
||||
if os.time() - games[arena].time >= arenas[arena].max_time then
|
||||
stop_game(arena)
|
||||
return
|
||||
end
|
||||
minetest.after(1, worker, arena)
|
||||
end
|
||||
|
||||
local function start_game(arena)
|
||||
regen_floors(arena)
|
||||
superchat.add_channel('spleef.' .. arena)
|
||||
local tool = minetest.setting_get('spleef.tool')
|
||||
if not tool then tool = 'default:shovel_diamond' end
|
||||
if arenas.tool then tool = arenas.tool end
|
||||
for _, name in ipairs(games[arena].players) do
|
||||
local inv = minetest.get_player_by_name(name):get_inventory()
|
||||
games[arena].invs[name] = get_inv(inv)
|
||||
clear_inv(inv)
|
||||
inv:add_item('main', tool)
|
||||
games[arena].channels[name] = superchat.get_player_channel(name)
|
||||
superchat.change_channel(name, 'spleef.' .. arena)
|
||||
tp_game(minetest.get_player_by_name(name), arena)
|
||||
gamers[name] = minetest.parse_json('{"arena":"' .. arena .. '","spec":false}')
|
||||
minetest.chat_send_player(name, S('============ SPLEEF ============'))
|
||||
minetest.chat_send_player(name, S('-------> CHAT SEPARATE <-------'))
|
||||
minetest.chat_send_player(name, S('GAME WILL STARTING, PLEASE WAIT...'))
|
||||
minetest.chat_send_player(name, S('============ SPLEEF ============'))
|
||||
end
|
||||
for _, name in ipairs(games[arena].spectators) do
|
||||
games[arena].channels[name] = superchat.get_player_channel(name)
|
||||
superchat.change_channel(name, 'spleef.' .. arena)
|
||||
gamers[name] = minetest.parse_json('{"arena":' .. arena .. ',"spec":false}')
|
||||
minetest.chat_send_player(name, S('============ SPLEEF ============'))
|
||||
minetest.chat_send_player(name, S('-------> CHAT SEPARATE <-------'))
|
||||
minetest.chat_send_player(name, S('GAME WILL STARTING, PLEASE WAIT...'))
|
||||
minetest.chat_send_player(name, S('============ SPLEEF ============'))
|
||||
end
|
||||
minetest.after(arenas[arena].after, function(a)
|
||||
if not games[a] then return end
|
||||
games[a].time = os.time()
|
||||
games[a].started = true
|
||||
for _, name in ipairs(games[a].players) do
|
||||
minetest.chat_send_player(name, S('START GAME!!! RUN!'))
|
||||
end
|
||||
for _, name in ipairs(games[a].spectators) do
|
||||
minetest.chat_send_player(name, S('START GAME!!! SEE!'))
|
||||
end
|
||||
minetest.after(1, worker, arena)
|
||||
end, arena)
|
||||
games[arena].fond = #games[arena].players * arenas[arena].cost
|
||||
end
|
||||
|
||||
local function tfloor(pos)
|
||||
for key, value in pairs(pos) do pos[key] = math.floor(value) end
|
||||
return pos
|
||||
end
|
||||
|
||||
local function set_area(arena, pos1, pos2)
|
||||
sets[arena].reg = {tfloor(pos1), tfloor(pos2)}
|
||||
end
|
||||
|
||||
local function set_floor(arena, pos1, pos2)
|
||||
sets[arena].floor = {}
|
||||
pos1 = tfloor(pos1)
|
||||
pos2 = tfloor(pos2)
|
||||
for _, pos in ipairs(cuboids_lib.get_nodes(cuboids_lib.get_cube(pos1, pos2))) do
|
||||
sets[arena].floor[minetest.write_json(pos)] = minetest.get_node_or_nil(pos)
|
||||
end
|
||||
local y = 0
|
||||
if pos1.y <= pos2.y then y = pos1.y else y = pos2.y end
|
||||
if not sets[arena].y_level or y < sets[arena].y_level then sets[arena].y_level = y end
|
||||
end
|
||||
|
||||
local function set_settings(arena, min_p, max_p, after, max_time, cost)
|
||||
sets[arena].minp = min_p
|
||||
sets[arena].maxp = max_p
|
||||
sets[arena]['max_time'] = max_time
|
||||
sets[arena]['after'] = after
|
||||
sets[arena]['cost'] = cost
|
||||
end
|
||||
|
||||
local function save()
|
||||
mod_configs.save_json('spleef', 'arenas', arenas)
|
||||
end
|
||||
|
||||
local function done(arena)
|
||||
arenas[arena] = sets[arena]
|
||||
arenas[arena].edit = false
|
||||
save()
|
||||
sets[arena] = nil
|
||||
end
|
||||
|
||||
local function remove(arena)
|
||||
arenas[arena] = nil
|
||||
save()
|
||||
end
|
||||
|
||||
local function is_floor(arena, pos)
|
||||
if arenas[arena].floor[minetest.write_json(pos)] then return true end
|
||||
return false
|
||||
end
|
||||
|
||||
local function is_arena(arena, pos)
|
||||
if not arenas[arena] or not arenas[arena].reg or not arenas[arena].reg.pos1 or not arenas[arena].reg.pos2 then
|
||||
return false
|
||||
end
|
||||
return cuboids_lib.contains(cuboids_lib.get_cube(arenas[arena].reg.pos1, arenas[arena].reg.pos2), pos)
|
||||
end
|
||||
|
||||
local function can_break(player_name, pos)
|
||||
if editors[player_name] and is_arena(editors[player_name].arena, pos) then return true end
|
||||
if not gamers[player_name] then
|
||||
for key in pairs(arenas) do
|
||||
if is_arena(key, pos) then return false end
|
||||
end
|
||||
end
|
||||
if (gamers[player_name] and not gamers[player_name].spec and games[gamers[player_name].arena].started and
|
||||
is_floor(gamers[player_name].arena, pos)) then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function to_lobby(player, arena)
|
||||
local player_name = player:get_player_name()
|
||||
if not games[arena] then create_game(arena) end
|
||||
table.insert(games[arena].players, player_name)
|
||||
gamers[player_name] = minetest.parse_json('{"arena":"' .. arena .. '","spec":false}')
|
||||
coins.take_coins(player_name, arenas[arena].cost)
|
||||
tp_lobby(player, arena)
|
||||
end
|
||||
|
||||
local function to_spectate(player, arena)
|
||||
local player_name = player:get_player_name()
|
||||
table.insert(games[arena].spectators, player_name)
|
||||
gamers[player_name] = minetest.parse_json('{"arena":"' .. arena .. '","spec":true}')
|
||||
tp_spectate(player, arena)
|
||||
end
|
||||
|
||||
local function vote_start(arena, name)
|
||||
if games[arena].start then
|
||||
for key, value in pairs(games[arena].start) do
|
||||
if value == name then return false end
|
||||
end
|
||||
end
|
||||
table.insert(games[arena].start, name)
|
||||
if #games[arena].start == #games[arena].players and #games[arena].players >= arenas[arena].minp then
|
||||
start_game(arena)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- EVENTS
|
||||
minetest.register_on_player_hpchange(function(player, hp_change)
|
||||
if gamers[player:get_player_name()] then return true end
|
||||
end, nil)
|
||||
|
||||
minetest.register_on_respawnplayer(function(player)
|
||||
local player_name = player:get_player_name()
|
||||
if gamers[player_name] then leave(player_name) end
|
||||
end)
|
||||
|
||||
minetest.register_on_dignode(function(pos, oldnode, digger)
|
||||
if not can_break(digger:get_player_name(), pos) then return true end
|
||||
end)
|
||||
|
||||
minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing)
|
||||
local player_name = puncher:get_player_name()
|
||||
if editors[player_name] then
|
||||
editors[player_name].pos = pos
|
||||
minetest.chat_send_player(player_name, S('Pos') .. ': ' .. minetest.pos_to_string(pos))
|
||||
end
|
||||
if not can_break(player_name, pos) then return true
|
||||
elseif gamers[player_name] then
|
||||
minetest.remove_node(pos)
|
||||
local b = games[gamers[player_name].arena].blocks[player_name]
|
||||
if b then
|
||||
games[gamers[player_name].arena].blocks[player_name] = b + 1
|
||||
else
|
||||
games[gamers[player_name].arena].blocks[player_name] = 1
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_placenode(function(pos, newnode, placer, oldnode, itemstack, pointed_thing)
|
||||
local player_name = placer:get_player_name()
|
||||
if not editors[player_name] and gamers[player_name] then return true end
|
||||
end)
|
||||
|
||||
minetest.register_on_punchplayer(function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage)
|
||||
if gamers[player:get_player_name()] then return true end
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local player_name = player:get_player_name()
|
||||
if gamers[player_name] then leave(player_name) end
|
||||
end)
|
||||
|
||||
minetest.register_on_shutdown(function()
|
||||
for key in pairs(games) do stop_game(key) end
|
||||
mod_configs.save_json('spleef', 'chache_games', games)
|
||||
mod_configs.save_json('spleef', 'chache_gamers', gamers)
|
||||
mod_configs.save_json('spleef', 'chache_sets', sets)
|
||||
mod_configs.save_json('spleef', 'cache_editors', editors)
|
||||
end)
|
||||
|
||||
local old_is_protected = minetest.is_protected
|
||||
function minetest.is_protected(pos, name)
|
||||
if not can_break(name, pos) then
|
||||
return true
|
||||
end
|
||||
return old_is_protected(pos, name)
|
||||
end
|
||||
|
||||
-- REGISTRATIONS
|
||||
minetest.register_privilege('spleef', S('For using spleef'))
|
||||
minetest.register_privilege('spleefmod', S('For manage spleef games'))
|
||||
minetest.register_privilege('spleefadm', S('For editing arenas'))
|
||||
|
||||
-- COMMANDS
|
||||
minetest.register_chatcommand('spcreate', {
|
||||
params = '<arena>',
|
||||
description = S('start creating spleef arena'),
|
||||
privs = {spleefadm = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not arena') end
|
||||
if arenas[params] or sets[params] then
|
||||
return false, S('%s is found'):format(params)
|
||||
end
|
||||
sets[params] = minetest.parse_json('{"edit":false}')
|
||||
editors[name] = minetest.parse_json('{"arena":"' .. params .. '"}')
|
||||
return true, S('arena %s created'):format(params)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('spedit', {
|
||||
params = '<arena>',
|
||||
description = S('start editing spleef arena'),
|
||||
privs = {spleefadm = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not arena') end
|
||||
if games[params] then return false, S('%s is started'):format(params) end
|
||||
if not arenas[params] then return false, S('%s not found') end
|
||||
sets[params] = arenas[params]
|
||||
arenas[params].edit = true
|
||||
editors[name] = minetest.parse_json('{"arena":"' .. params .. '"}')
|
||||
return true, S('%s edit mode on'):format(params)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('spdone', {
|
||||
params = 'none',
|
||||
description = S('done editing'),
|
||||
privs = {spleefadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
done(arena)
|
||||
editors[name] = nil
|
||||
return true, S('%s done editing'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('spremove', {
|
||||
params = '<arena>',
|
||||
description = S('remove arena'),
|
||||
privs = {spleefadm = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not arena') end
|
||||
if not arenas[params] then return false, S('%s not found') end
|
||||
remove(params)
|
||||
return true, S('%s removed'):format(params)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('spreload', {
|
||||
params = 'none',
|
||||
description = S('reload arenas config'),
|
||||
privs = {spleefadm = true},
|
||||
func = function(name, params)
|
||||
load_file()
|
||||
return true, S('settings reloaded')
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('sppos1', {
|
||||
params = 'none',
|
||||
description = S('set spleef arena region pos1'),
|
||||
privs = {spleefadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
if not editors[name].pos then return false, S('not selected point') end
|
||||
editors[name].pos1 = editors[name].pos
|
||||
if editors[name].pos2 then
|
||||
set_area(arena, editors[name].pos1, editors[name].pos2)
|
||||
end
|
||||
return true, S('pos1 for %s set'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('sppos2', {
|
||||
params = '<arena>',
|
||||
description = S('set spleef arena region pos2'),
|
||||
privs = {spleefadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
if not editors[name].pos then return false, S('not selected point') end
|
||||
editors[name].pos2 = editors[name].pos
|
||||
if editors[name].pos1 then
|
||||
set_area(arena, editors[name].pos1, editors[name].pos2)
|
||||
end
|
||||
return true, S('pos2 for %s set'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('spfpos1', {
|
||||
params = 'none',
|
||||
description = S('set spleef arena floor pos1'),
|
||||
privs = {spleefadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
if not editors[name].pos then return false, S('not selected point') end
|
||||
editors[name].fpos1 = editors[name].pos
|
||||
if editors[name].fpos2 then
|
||||
set_floor(arena, editors[name].fpos1, editors[name].fpos2)
|
||||
end
|
||||
return true, S('fpos1 for %s set'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('spfpos2', {
|
||||
params = 'none',
|
||||
description = S('set spleef arena floor pos2'),
|
||||
privs = {spleefadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
if not editors[name].pos then return false, S('not selected point') end
|
||||
editors[name].fpos2 = editors[name].pos
|
||||
if editors[name].fpos1 then
|
||||
set_floor(arena, editors[name].fpos1, editors[name].fpos2)
|
||||
end
|
||||
return true, S('fpos2 for %s set'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('spsettings', {
|
||||
params = '<min_p> <max_p> <after> <max_time> <cost>',
|
||||
description = S('set spleef arena settings'),
|
||||
privs = {spleefadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not args') end
|
||||
local params = params:split(' ')
|
||||
if #params < 1 then return false, S('invalid command, not min_players') end
|
||||
if #params < 2 then return false, S('invalid command, not max_players') end
|
||||
if #params < 3 then return false, S('invalid command, not after') end
|
||||
if #params < 4 then return false, S('invalid command, not max_time') end
|
||||
if #params < 5 then return false, S('invalid command, not cost') end
|
||||
for i = 1, 5 do
|
||||
params[i] = params[i]:trim()
|
||||
if not params[i]:match('^[0-9]*$') then
|
||||
return false, S('incorrect number %s'):format(params[1])
|
||||
end
|
||||
end
|
||||
set_settings(
|
||||
arena, tonumber(params[1]), tonumber(params[2]),
|
||||
tonumber(params[3]), tonumber(params[4]), tonumber(params[5])
|
||||
)
|
||||
return true, S('%s settings set'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('splobby', {
|
||||
params = 'none',
|
||||
description = S('set spleef arena lobby point'),
|
||||
privs = {spleefadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local pos = player:getpos()
|
||||
pos.pitch = player:get_look_vertical()
|
||||
pos.yaw = player:get_look_horizontal()
|
||||
sets[arena].lobby = pos
|
||||
return true, S('%s lobby point set'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('spspec', {
|
||||
params = 'none',
|
||||
description = S('set spleef arena spectate point'),
|
||||
privs = {spleefadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local pos = player:getpos()
|
||||
pos.pitch = player:get_look_vertical()
|
||||
pos.yaw = player:get_look_horizontal()
|
||||
sets[arena].spec = pos
|
||||
return true, S('%s spectate point set'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('spgame', {
|
||||
params = 'none',
|
||||
description = S('set spleef arena game point'),
|
||||
privs = {spleefadm = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local pos = player:getpos()
|
||||
pos.pitch = player:get_look_vertical()
|
||||
pos.yaw = player:get_look_horizontal()
|
||||
sets[arena].game = pos
|
||||
return true, S('%s game point set'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('sptool', {
|
||||
params = '<itemstering>',
|
||||
description = S('set tool for spleef arena'),
|
||||
privs = {spleefadm = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not itemstring') end
|
||||
if not editors[name] then return false, S('need edit mode on') end
|
||||
local arena = editors[name].arena
|
||||
if not pcall(ItemStack(params)) then return false, S('invalid itemstring') end
|
||||
sets[arena].tool = params
|
||||
return true, S('%s tool set'):format(arena)
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
minetest.register_chatcommand('spkick', {
|
||||
params = '<player>',
|
||||
description = S('kick player from spleef arena'),
|
||||
privs = {spleefmod = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not player name') end
|
||||
if not gamers[params] then return false, S('%s not in spleef'):format(params) end
|
||||
local arena = gamers[params].arena
|
||||
leave(params)
|
||||
minetest.chat_send_player(params, S('%s kicking you from spleef arena %s'):format(name, arena))
|
||||
return true, S('%s kicked from spleef arena %s'):format(params, arena)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('spstop', {
|
||||
params = '<arena>',
|
||||
description = S('stop spleef arena'),
|
||||
privs = {spleefmod = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not arena') end
|
||||
if not games[params] or not games[params].started then return false, S('%s not started'):format(params) end
|
||||
superchat.send(name, 'spleef.' .. params, S('FORCE STOPPING GAME'))
|
||||
stop_game(params)
|
||||
return true, S('%s stopped'):format(params)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('spstart', {
|
||||
params = '<arena>',
|
||||
description = S('start spleef arena'),
|
||||
privs = {spleefmod = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not arena') end
|
||||
if not games[params] or not games[params].started then return false, S('%s not started'):format(params) end
|
||||
superchat.send(name, 'spleef.' .. params, S('FORCE STARTING GAME'))
|
||||
start_game(params)
|
||||
return true, S('%s started'):format(params)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('spleef', {
|
||||
params = '<list/join/spec/leave/start>',
|
||||
description = S('gamers commands'),
|
||||
privs = {spleef = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not arg') end
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if params == 'list' then
|
||||
local str = ''
|
||||
for key, value in ipairs(spleef.get_arenas()) do
|
||||
str = str .. value .. ', '
|
||||
end
|
||||
if str:len() > 0 then return true, S('Arenas') .. ': ' .. str:sub(0, str:len() - 2)
|
||||
else return false, S('not arenas') end
|
||||
elseif params:sub(0, 4) == 'join' then
|
||||
local params = params:split(' ')
|
||||
if #params < 2 then return false, S('invalid command, not arena') end
|
||||
local arena = params[2]
|
||||
if not arenas[arena] then return false, S('%s not found'):format(arena) end
|
||||
if games[arena] and games[arena].started then return false, S('%s is started'):format(arena) end
|
||||
if not coins.get_coins(name) or coins.get_coins(name) < arenas[arena].cost then
|
||||
return false, S('sorry, not %d coins in you balance'):format(arenas[arena].cost)
|
||||
end
|
||||
if games[arena] and #games[arena].players >= arenas[arena].maxp then
|
||||
return false, S('%s is full'):format(arena)
|
||||
end
|
||||
if gamers[name] then return false, S('You playing arena %s'):format(arena) end
|
||||
to_lobby(player, arena)
|
||||
return true, S('Joined %s arena, taking %d coins'):format(arena, arenas[arena].cost)
|
||||
elseif params:sub(0, 4) == 'spec' then
|
||||
local params = params:split(' ')
|
||||
if #params < 2 then return false, S('invalid command, not arena') end
|
||||
if not games[params[2]] then return false, S('%s not started'):format(params[2]) end
|
||||
if gamers[name] then return false, S('You playing arena %s'):format(arena) end
|
||||
to_spectate(player, params[2])
|
||||
return true, S('You spectate %s arena'):format(params[2])
|
||||
elseif params == 'leave' then
|
||||
if not gamers[name] then return false, S('you not in spleef arena') end
|
||||
local arena = gamers[name].arena
|
||||
leave(name)
|
||||
gui_menu.reset_formspec(name)
|
||||
return true, S('you leaving from %s arena'):format(arena)
|
||||
elseif params == 'start' then
|
||||
if not gamers[name] then return false, S('you not in spleef arena') end
|
||||
local arena = gamers[name].arena
|
||||
local v = vote_start(arena, name)
|
||||
if not v then return false, S('you have already voted') end
|
||||
return true, S('You vote start game')
|
||||
else
|
||||
return false, S('Using /spleef list/join/spec/leave/start')
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- MENU SUPPORT
|
||||
if minetest.global_exists('gui_menu') then
|
||||
gui_menu.add_listener(function(player_name, cat, page, fields)
|
||||
local player = minetest.get_player_by_name(player_name)
|
||||
|
||||
local function ga()
|
||||
local add = spleef.get_arenas()
|
||||
if add then
|
||||
local result = {}
|
||||
result[S('Spleef arenas')] = {}
|
||||
for key, value in pairs(add) do
|
||||
result[S('Spleef arenas')]['spleef.' .. value] = {text = value}
|
||||
end
|
||||
return result
|
||||
end
|
||||
end
|
||||
|
||||
local ga2 = ga()
|
||||
if not ga2 then return nil end
|
||||
if not cat and not fields then
|
||||
return ga()
|
||||
elseif not fields then return nil
|
||||
elseif fields['gui_menu:cat.' .. S('Spleef arenas')] then
|
||||
gui_menu.show_buttons(player_name, S('Spleef arenas'), ga2[S('Spleef arenas')], 1)
|
||||
elseif cat == S('Spleef arenas') and fields['gui_menu:pgo'] then
|
||||
gui_menu.show_buttons(player_name, S('Spleef arenas'), ga2[S('Spleef arenas')], page + 1)
|
||||
elseif cat == S('Spleef arenas') and fields['gui_menu:pback'] then
|
||||
gui_menu.show_buttons(player_name, S('Spleef arenas'), ga2[S('Spleef arenas')], page - 1)
|
||||
elseif cat == S('Spleef arenas') and fields then
|
||||
local lstr = 'size[3,1]button[0,0;3,1;spleef.leave;' .. S('Leave') .. ']'
|
||||
local sstr = 'size[6,1]button[0,0;3,1;spleef.start;' .. S('Vote start') .. ']button[3,0;3,1;spleef.leave;' .. S('Leave') .. ']'
|
||||
if fields['spleef.leave'] then
|
||||
if not gamers[player_name] then
|
||||
minetest.chat_send_player(player_name, S('you not in spleef arena'))
|
||||
gui_menu.reset_formspec(player_name)
|
||||
gui_menu.show_cat(player_name, nil)
|
||||
return
|
||||
end
|
||||
leave(player_name)
|
||||
gui_menu.reset_formspec(player_name)
|
||||
gui_menu.show_cat(player_name, nil)
|
||||
return
|
||||
elseif fields['spleef.close'] then
|
||||
gui_menu.show_cat(player_name, nil)
|
||||
return
|
||||
elseif fields['spleef.start'] then
|
||||
if not gamers[player_name] then
|
||||
minetest.chat_send_player(player_name, S('you not in spleef arena'))
|
||||
gui_menu.set_formspec(player_name, lstr)
|
||||
minetest.show_formspec(player_name, 'gui_menu', lstr)
|
||||
return
|
||||
end
|
||||
local v = vote_start(gamers[player_name].arena, player_name)
|
||||
if not v then
|
||||
minetest.chat_send_player(player_name, S('you have already voted'))
|
||||
end
|
||||
minetest.chat_send_player(player_name, S('You vote start game'))
|
||||
gui_menu.set_formspec(player_name, lstr)
|
||||
minetest.show_formspec(player_name, 'gui_menu', lstr)
|
||||
return
|
||||
end
|
||||
|
||||
local function f(player, arena)
|
||||
local result = 'size[8,1]button[7,0;1,1;spleef.close;X]'
|
||||
if games[arena] then
|
||||
result = result .. 'button[4,0;3,1;spleef.' .. arena .. '.spec;' .. S('Spectate') .. ']'
|
||||
end
|
||||
if not games[arena] or not games[arena].started or #games[arena].players < arenas[arena].maxp then
|
||||
result = result .. 'button[0,0;3,1;spleef.' .. arena .. '.join;' .. S('Join') .. ']'
|
||||
end
|
||||
minetest.show_formspec(player_name, 'gui_menu', result)
|
||||
end
|
||||
|
||||
local ar = spleef.get_arenas()
|
||||
if not arenas then return nil end
|
||||
for key, value in pairs(ar) do
|
||||
if fields['spleef.' .. value] then
|
||||
return {func = f, args = {value}}
|
||||
elseif fields['spleef.' .. value .. '.join'] then
|
||||
if gamers[player_name] then
|
||||
minetest.chat_send_player(player_name, S('You playing arena %s'):format(value))
|
||||
return
|
||||
end
|
||||
if games[value] and games[value].started then
|
||||
minetest.chat_send_player(player_name, S('%s is started'):format(value))
|
||||
return
|
||||
end
|
||||
if not coins.get_coins(player_name) or coins.get_coins(player_name) < arenas[value].cost then
|
||||
minetest.chat_send_player(player_name, S('sorry, not %d coins in you balance'):format(arenas[value].cost))
|
||||
return
|
||||
end
|
||||
if games[value] and #games[value].players >= arenas[value].maxp then
|
||||
minetest.chat_send_player(player_name, S('%s is full'):format(value))
|
||||
return
|
||||
end
|
||||
to_lobby(player, value)
|
||||
minetest.chat_send_player(player_name, S('Joined %s arena, taking %d coins'):format(value, arenas[value].cost))
|
||||
gui_menu.set_formspec(player_name, sstr)
|
||||
minetest.show_formspec(player_name, 'gui_menu', sstr)
|
||||
elseif fields['spleef.' .. value .. '.spec'] then
|
||||
if not games[value] then
|
||||
minetest.chat_send_player(player_name, S('%s not started'):format(value))
|
||||
return
|
||||
end
|
||||
if gamers[player_name] then
|
||||
minetest.chat_send_player(player_name, S('You playing arena %s'):format(value))
|
||||
return
|
||||
end
|
||||
to_spectate(player, value)
|
||||
minetest.chat_send_player(player_name, S('You spectate %s arena'):format(value))
|
||||
gui_menu.set_formspec(player_name, lstr)
|
||||
minetest.show_formspec(player_name, 'gui_menu', lstr)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
|
@ -0,0 +1,88 @@
|
|||
# init.lua
|
||||
%dst, give %d coins =
|
||||
%dst =
|
||||
You leaving from %s =
|
||||
'============ SPLEEF ============' =
|
||||
-------> CHAT SEPARATE <------- =
|
||||
GAME WILL STARTING, PLEASE WAIT... =
|
||||
START GAME!!! RUN! =
|
||||
START GAME!!! SEE! =
|
||||
Pos =
|
||||
For using spleef =
|
||||
For manage spleef games =
|
||||
For editing arenas =
|
||||
start creating spleef arena =
|
||||
invalid command, not arena =
|
||||
%s is found =
|
||||
arena %s created =
|
||||
start editing spleef arena =
|
||||
%s is started =
|
||||
%s not found =
|
||||
%s edit mode on =
|
||||
done editing =
|
||||
need edit mode on =
|
||||
%s done editing =
|
||||
remove arena =
|
||||
%s removed =
|
||||
reload arenas config =
|
||||
settings reloaded =
|
||||
set spleef arena region pos1 =
|
||||
not selected point =
|
||||
pos1 for %s set =
|
||||
set spleef arena region pos2 =
|
||||
pos2 for %s set =
|
||||
set spleef arena floor pos1 =
|
||||
fpos1 for %s set =
|
||||
set spleef arena floor pos2 =
|
||||
fpos2 for %s set =
|
||||
set spleef arena settings =
|
||||
invalid command, not args =
|
||||
invalid command, not min_players =
|
||||
invalid command, not max_players =
|
||||
invalid command, not after =
|
||||
invalid command, not max_time =
|
||||
invalid command, not cost =
|
||||
incorrect number %s =
|
||||
%s settings set =
|
||||
set spleef arena lobby point =
|
||||
%s lobby point set =
|
||||
set spleef arena spectate point =
|
||||
%s spectate point set =
|
||||
set spleef arena game point =
|
||||
%s game point set =
|
||||
set tool for spleef arena =
|
||||
invalid command, not itemstring =
|
||||
invalid itemstring =
|
||||
%s tool set =
|
||||
kick player from spleef arena =
|
||||
invalid command, not player name =
|
||||
%s kicking you from spleef arena %s =
|
||||
%s kicked from spleef arena %s =
|
||||
%s not in spleef =
|
||||
stop spleef arena =
|
||||
%s not started =
|
||||
FORCE STOPPING GAME =
|
||||
%s stopped =
|
||||
start spleef arena =
|
||||
FORCE STARTING GAME =
|
||||
%s started =
|
||||
gamers commands =
|
||||
invalid command, not arg =
|
||||
Arenas =
|
||||
not arenas =
|
||||
sorry, not %d coins in you balance =
|
||||
%s is full =
|
||||
You playing arena %s =
|
||||
Joined %s arena, taking %d coins =
|
||||
You playing arena %s =
|
||||
You spectate %s arena =
|
||||
you not in spleef arena =
|
||||
you leaving from %s arena =
|
||||
you have already voted =
|
||||
You vote start game =
|
||||
Using /spleef list/join/spec/leave/start =
|
||||
Spleef arenas =
|
||||
Leave =
|
||||
Vote start =
|
||||
Spectate =
|
||||
Join =
|
|
@ -0,0 +1 @@
|
|||
mod = spleef
|
|
@ -0,0 +1,39 @@
|
|||
# tp_point
|
||||
|
||||
Add teleport positions. Support give and take cost, sending message to player. Give cost formula: *setting numer + boost*.
|
||||
|
||||
## Create point
|
||||
|
||||
Need *tppoint* priv.
|
||||
|
||||
* **/tppcreate <name> <give> <take> <mess?>**
|
||||
* or **/tppedit <name>**
|
||||
* Punch node.
|
||||
* **/tppfrom** - add from position (teleport point)
|
||||
* Stand on the position.
|
||||
* **/tppto** - add to position
|
||||
* **/tppdone**
|
||||
|
||||
Other commands:
|
||||
|
||||
* **/tppdel <name>**
|
||||
* **/tppreload** - for reloading data from config file
|
||||
* **/tppoints** - show list names points
|
||||
|
||||
## Depends
|
||||
|
||||
* mod_configs
|
||||
*coins
|
||||
* essentials
|
||||
* initlib?
|
||||
|
||||
## API
|
||||
|
||||
* *tp_point.set_boost(num)*
|
||||
* *tp_point.get_boost()* - return number
|
||||
* *tp_point.get_all_points()* - return array
|
||||
* *tp_point.get_point(pos)* - return string name or nil, pos - table "{x = number, y = number, z = number}"
|
||||
* *tp_point.get_point_data(name)* - return table or nil, table - "{from = from_pos, to = to_pos, give = give_cost, take = take_cost}"
|
||||
* *tp_point.add_point(name, from_pos, to_pos, give_cost, take_cost, message)* - message optional (set nil)
|
||||
* *tp_point.del_point(name)*
|
||||
* *tp_point.is_exists(name)* - return bool, true if name is exists
|
|
@ -0,0 +1,4 @@
|
|||
mod_configs
|
||||
coins
|
||||
essentials
|
||||
initlib?
|
|
@ -0,0 +1,234 @@
|
|||
tp_point = {}
|
||||
local data = {}
|
||||
local editors = {}
|
||||
local boost = 1
|
||||
|
||||
-- INITLIB
|
||||
local S, NS
|
||||
if minetest.global_exists('intllib') then
|
||||
S, NS = intllib.make_gettext_pair(minetest.get_current_modname())
|
||||
else
|
||||
S = function(s) return s end
|
||||
NS = S
|
||||
end
|
||||
|
||||
-- API
|
||||
function tp_point.set_boost(num)
|
||||
boost = num
|
||||
end
|
||||
|
||||
function tp_point.get_boost()
|
||||
return boost
|
||||
end
|
||||
|
||||
function tp_point.get_all_points()
|
||||
local result = {}
|
||||
for key in pairs(data) do table.insert(result, key) end
|
||||
return result
|
||||
end
|
||||
|
||||
function tp_point.get_point(pos)
|
||||
pos = essentials.table_floor(pos)
|
||||
for key, value in pairs(data) do
|
||||
if essentials.table_equals(pos, value.from) then return key end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function tp_point.get_point_data(name)
|
||||
if not data[name] then return nil end
|
||||
return data[name]
|
||||
end
|
||||
|
||||
function tp_point.add_point(name, from_pos, to_pos, give_cost, take_cost, message)
|
||||
data[name] = {
|
||||
from = from_pos, to = to_pos, give = give_cost, take = take_cost
|
||||
}
|
||||
if message then data[name].mess = message end
|
||||
mod_configs.save_json('tp_point', 'points', data)
|
||||
end
|
||||
|
||||
function tp_point.del_point(name)
|
||||
data[name] = nil
|
||||
mod_configs.save_json('tp_point', 'points', data)
|
||||
end
|
||||
|
||||
function tp_point.is_exists(name)
|
||||
if data[name] then return true end
|
||||
return false
|
||||
end
|
||||
|
||||
-- LOCAL FUNCTIONS
|
||||
local function load_data()
|
||||
data = mod_configs.load_json('tp_point', 'points')
|
||||
if not data then data = {} end
|
||||
end
|
||||
load_data()
|
||||
|
||||
local function tp(point, player_name)
|
||||
if data[point].take > 0 and data[point].take >= coins.get_coins(player_name) then
|
||||
coins.take_coins(player_name, data[point].take)
|
||||
minetest.chat_send_player(player_name, S('take %d coins for teleport'):format(data[point].take))
|
||||
end
|
||||
essentials.set_full_pos(minetest.get_player_by_name(player_name), data[point].to)
|
||||
if data[point].give > 0 then
|
||||
coins.add_coins(player_name, data[point].give * boost)
|
||||
minetest.chat_send_player(player_name, S('give %d coins to you'):format(data[point].give))
|
||||
end
|
||||
if data[point].mess then minetest.chat_send_player(player_name, data[point].mess) end
|
||||
end
|
||||
|
||||
local function tick()
|
||||
for _, player in ipairs(minetest.get_connected_players()) do
|
||||
local point = tp_point.get_point(player:getpos())
|
||||
if point then tp(point, player:get_player_name()) end
|
||||
end
|
||||
minetest.after(0.5, tick)
|
||||
end
|
||||
minetest.after(0.5, tick)
|
||||
|
||||
local function edit(player_name, point)
|
||||
editors[player_name] = {}
|
||||
editors[player_name]['point'] = point
|
||||
editors[player_name].from = data[point].from
|
||||
editors[player_name].to = data[point].to
|
||||
editors[player_name].give = data[point].give
|
||||
editors[player_name].take = data[point].take
|
||||
if data[point].mess then editors[player_name].mess = data[point].mess end
|
||||
data[point] = nil
|
||||
end
|
||||
|
||||
local function done(player_name)
|
||||
data[editors[player_name].point] = {
|
||||
from = editors[player_name].from, to = editors[player_name].to,
|
||||
give = editors[player_name].give, take = editors[player_name].take
|
||||
}
|
||||
if editors[player_name].mess then data[editors[player_name].point].mess = editors[player_name].mess end
|
||||
mod_configs.save_json('tp_point', 'points', data)
|
||||
editors[player_name] = nil
|
||||
end
|
||||
|
||||
-- EVENTS
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
editors[player:get_player_name()] = nil
|
||||
end)
|
||||
|
||||
minetest.register_on_punchnode(function(pos, node, puncher, pointed_thing)
|
||||
local player_name = puncher:get_player_name()
|
||||
if editors[player_name] then
|
||||
pos.y = pos.y + 1
|
||||
editors[player_name].pos = pos
|
||||
minetest.chat_send_player(player_name, S('Pos') .. ': ' .. minetest.pos_to_string(pos))
|
||||
end
|
||||
end)
|
||||
|
||||
-- REGISTRATIONS
|
||||
minetest.register_privilege('tppoint', S('Access to admin commands tp_point'))
|
||||
|
||||
-- COMMANDS
|
||||
minetest.register_chatcommand('tppoints', {
|
||||
params = 'none',
|
||||
description = S('show points list'),
|
||||
privs = {tppoint = true},
|
||||
func = function(name, params)
|
||||
local str = ''
|
||||
for key in ipairs(data) do
|
||||
str = str .. key .. ', '
|
||||
end
|
||||
if str:len() > 0 then return true, S('Points') .. ': ' .. str:sub(0, str:len() - 2)
|
||||
else return false, S('no points') end
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('tppcreate', {
|
||||
params = '<name> <give> <take> <mess?>',
|
||||
description = S('create tp point'),
|
||||
privs = {tppoint = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not point name') end
|
||||
local params = params:split(' ')
|
||||
if #params < 1 then return false, S('invalid command, not point name') end
|
||||
if #params < 2 then return false, S('invalid command, not give cost') end
|
||||
if #params < 3 then return false, S('invalid command, not take cost') end
|
||||
if not params[2]:trim():match('^[0-9]*$') then return false, S('invalid number %s'):format(params[2]) end
|
||||
if not params[3]:trim():match('^[0-9]*$') then return false, S('invalid number %s'):format(params[3]) end
|
||||
if editors[name] then return false, S('you already editing %s'):format(editors[name].point) end
|
||||
editors[name] = {
|
||||
point = params[1]:trim(), give = tonumber(params[2]:trim()), take = tonumber(params[3]:trim())
|
||||
}
|
||||
if #params > 3 then
|
||||
local message = ''
|
||||
for i = 4, #params do message = message .. params[i]:trim() .. ' ' end
|
||||
editors[name].mess = message:sub(0, message:len()-1)
|
||||
end
|
||||
return true, S('%s point created'):format(params[1])
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('tppdone', {
|
||||
params = 'none',
|
||||
description = S('done editing tp point'),
|
||||
privs = {tppoint = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('you no edit mode') end
|
||||
done(name)
|
||||
return true, S('done, edit mode off')
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('tppedit', {
|
||||
params = '<name>',
|
||||
description = S('editing tp point'),
|
||||
privs = {tppoint = true},
|
||||
func = function(name, params)
|
||||
if not params or params:trim():len() == 0 then return false, S('invalid command, not point name') end
|
||||
if editors[name] then return false, S('you already editing %s'):format(editors[name].point) end
|
||||
if not data[name] then return false, S('%s not found'):format(params) end
|
||||
edit(name, params)
|
||||
return true, S('you editing %s, edit mode on'):format(params)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('tppfrom', {
|
||||
params = 'none',
|
||||
description = S('set from pos for tp point'),
|
||||
privs = {tppoint = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('you no edit mode') end
|
||||
if not editors[name].pos then return false, S('punch node for getting position') end
|
||||
editors[name].from = essentials.table_floor(editors[name].pos)
|
||||
return true, S('from pos for %s set'):format(editors[name].point)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('tppto', {
|
||||
params = 'none',
|
||||
description = S('set to pos for tp point'),
|
||||
privs = {tppoint = true},
|
||||
func = function(name, params)
|
||||
if not editors[name] then return false, S('you no edit mode') end
|
||||
editors[name].to = essentials.get_full_pos(minetest.get_player_by_name(name))
|
||||
return true, S('to pos for %s set'):format(editors[name].point)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('tppdel', {
|
||||
params = '<name>',
|
||||
description = S('remove tp point'),
|
||||
privs = {tppoint = true},
|
||||
func = function(name, params)
|
||||
if not data[params] then return false, S('point %s not found'):format(params) end
|
||||
tp_point.del_point(params)
|
||||
return true, S('point %s deleted'):format(params)
|
||||
end,
|
||||
})
|
||||
|
||||
minetest.register_chatcommand('tppreload', {
|
||||
params = 'none',
|
||||
description = S('reload data from json config'),
|
||||
privs = {tppoint = true},
|
||||
func = function(name, params)
|
||||
load_data()
|
||||
return true, S('config reloaded')
|
||||
end,
|
||||
})
|
|
@ -0,0 +1,31 @@
|
|||
# init.lua
|
||||
take %d coins for teleport =
|
||||
give %d coins to you =
|
||||
Access to admin commands tp_point =
|
||||
show points list =
|
||||
Points =
|
||||
no points =
|
||||
create tp point =
|
||||
invalid command, not point name =
|
||||
invalid command, not give cost =
|
||||
invalid command, not take cost =
|
||||
invalid number %s =
|
||||
you already editing %s =
|
||||
%s point created =
|
||||
done editing tp point =
|
||||
you no edit mode =
|
||||
done, edit mode off =
|
||||
editing tp point =
|
||||
%s not found =
|
||||
you editing %s, edit mode on =
|
||||
set from pos for tp point =
|
||||
from pos for %s set =
|
||||
set to pos for tp point =
|
||||
to pos for %s set =
|
||||
remove tp point =
|
||||
point %s not found =
|
||||
point %s deleted =
|
||||
reload data from json config =
|
||||
config reloaded =
|
||||
Pos =
|
||||
punch node for getting position =
|
|
@ -0,0 +1 @@
|
|||
mod = tp_point
|
Loading…
Reference in New Issue