Towny Economy Setup
This commit is contained in:
parent
01aefb5094
commit
d6a158a6e7
@ -1,2 +1,3 @@
|
||||
areas?
|
||||
protector?
|
||||
currency?
|
||||
|
@ -1,8 +1,6 @@
|
||||
-- A township system for Minetest servers.
|
||||
-- The MIT License - 2019 Evert "Diamond" Prants <evert@lunasqu.ee>
|
||||
|
||||
-- TODO: Protection on HUD
|
||||
-- TODO: Nations
|
||||
-- TODO: Economy
|
||||
|
||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
|
@ -1,3 +1,3 @@
|
||||
name = towny
|
||||
description = A township system for Minetest servers.
|
||||
optional_depends = areas,protector
|
||||
optional_depends = areas,protector,currency
|
||||
|
@ -1,13 +1,11 @@
|
||||
|
||||
# General
|
||||
##########
|
||||
[General]
|
||||
|
||||
# Town metadata and region storage engine
|
||||
# Recommended to keep as modstorage.
|
||||
towny_storage_engine (Storage engine) enum modstorage modstorage,flatfile
|
||||
|
||||
# Claims settings
|
||||
##################
|
||||
[Claims]
|
||||
|
||||
# Towny claim diameter
|
||||
towny_claim_size (Claim size) int 16
|
||||
@ -27,19 +25,7 @@ towny_distance (Max town claims) int 80
|
||||
# Recommended to be kept as true, may cause issues with claims otherwise
|
||||
towny_prevent_protector (Prevent protectors from being placed in a town) bool true
|
||||
|
||||
# Command settings
|
||||
###################
|
||||
[Command]
|
||||
|
||||
# If true, players must be invited into towns (No direct joining)
|
||||
towny_invite (Invite-based membership) bool true
|
||||
|
||||
# Economy settings
|
||||
###################
|
||||
|
||||
towny_eco (Enable economy) bool false
|
||||
towny_tax (Allow taxation) bool true
|
||||
|
||||
# Units depend on economy mod used in server
|
||||
towny_create_cost (Town creation cost) int 10000
|
||||
towny_claim_cost (Town claim block cost) int 1000
|
||||
towny_upkeep_cost (Town daily upkeep cost, multiplied by member count) int 0
|
||||
|
19
towny_eco/api.lua
Normal file
19
towny_eco/api.lua
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
--------------
|
||||
-- Abstract --
|
||||
--------------
|
||||
|
||||
-- Get currency name/description
|
||||
function towny.eco.get_currency() return "" end
|
||||
|
||||
-- Format the number appropriately
|
||||
function towny.eco.format_number(number) return number end
|
||||
|
||||
-- Get player's balance
|
||||
function towny.eco.get_player_balance(player) return 0 end
|
||||
|
||||
-- Charge a player
|
||||
function towny.eco.charge_player(player, amount) return 0 end
|
||||
|
||||
-- Pay a player
|
||||
function towny.eco.pay_player(player, amount) return false end
|
2
towny_eco/depends.txt
Normal file
2
towny_eco/depends.txt
Normal file
@ -0,0 +1,2 @@
|
||||
towny
|
||||
currency?
|
1
towny_eco/description.txt
Normal file
1
towny_eco/description.txt
Normal file
@ -0,0 +1 @@
|
||||
Towny Economy support
|
18
towny_eco/init.lua
Normal file
18
towny_eco/init.lua
Normal file
@ -0,0 +1,18 @@
|
||||
-- A township system for Minetest servers.
|
||||
-- The MIT License - 2019 Evert "Diamond" Prants <evert@lunasqu.ee>
|
||||
|
||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
|
||||
towny.eco = {
|
||||
enabled = false,
|
||||
create_cost = tonumber(minetest.settings:get("towny_create_cost")) or 10000,
|
||||
claim_cost = tonumber(minetest.settings:get("towny_claim_cost")) or 1000,
|
||||
upkeep_cost = tonumber(minetest.settings:get("towny_upkeep_cost")) or 0,
|
||||
taxable = minetest.settings:get_bool("towny_tax", true)
|
||||
}
|
||||
|
||||
dofile(modpath.."/api.lua")
|
||||
|
||||
if minetest.get_modpath("currency") ~= nil then
|
||||
dofile(modpath.."/mods/currency.lua")
|
||||
end
|
4
towny_eco/mod.conf
Normal file
4
towny_eco/mod.conf
Normal file
@ -0,0 +1,4 @@
|
||||
name = towny_eco
|
||||
description = Towny Economy support
|
||||
depends = towny
|
||||
optional_depends = currency
|
289
towny_eco/mods/currency.lua
Normal file
289
towny_eco/mods/currency.lua
Normal file
@ -0,0 +1,289 @@
|
||||
-- Simple "currency" mod API
|
||||
|
||||
local denoms = {
|
||||
["currency:minegeld_cent_5"] = 0.05,
|
||||
["currency:minegeld_cent_10"] = 0.10,
|
||||
["currency:minegeld_cent_25"] = 0.25,
|
||||
["currency:minegeld"] = 1,
|
||||
["currency:minegeld_5"] = 5,
|
||||
["currency:minegeld_10"] = 10,
|
||||
["currency:minegeld_50"] = 50,
|
||||
["currency:minegeld_100"] = 100,
|
||||
}
|
||||
|
||||
function towny.eco.get_currency()
|
||||
return "Minegeld"
|
||||
end
|
||||
|
||||
function towny.eco.format_number(number)
|
||||
return ("%.2f MG$"):format(number)
|
||||
end
|
||||
|
||||
local function round(num, numDecimalPlaces)
|
||||
local mult = 10^(numDecimalPlaces or 0)
|
||||
return math.floor(num * mult + 0.5) / mult
|
||||
end
|
||||
|
||||
-- Item-based functions
|
||||
|
||||
local function to_stacks(items)
|
||||
local counted = {}
|
||||
for _,i in pairs(items) do
|
||||
if counted[i] then
|
||||
counted[i] = counted[i] + 1
|
||||
else
|
||||
counted[i] = 1
|
||||
end
|
||||
end
|
||||
|
||||
local stacks = {}
|
||||
for itm,cnt in pairs(counted) do
|
||||
table.insert(stacks, ItemStack(itm .. " " .. cnt))
|
||||
end
|
||||
|
||||
return stacks
|
||||
end
|
||||
|
||||
local function get_closest_note(amount, notes)
|
||||
local t = nil
|
||||
local a = 0
|
||||
for itm,val in pairs(denoms) do
|
||||
local b = (notes == nil)
|
||||
if notes and notes[itm] ~= nil and notes[itm] > 0 then
|
||||
b = true
|
||||
end
|
||||
if val <= amount and a <= val and b then
|
||||
t = itm
|
||||
a = val
|
||||
end
|
||||
end
|
||||
return a, t
|
||||
end
|
||||
|
||||
local function denominate(amount)
|
||||
local items = {}
|
||||
local tc = amount
|
||||
|
||||
while tc > 0 do
|
||||
local amount,item = get_closest_note(tc)
|
||||
if amount == 0 then break end
|
||||
tc = tc - amount
|
||||
table.insert(items, item)
|
||||
end
|
||||
|
||||
return to_stacks(items)
|
||||
end
|
||||
|
||||
local function notes_inv(inventory)
|
||||
local total = 0
|
||||
for _,stack in pairs(inventory:get_list("main")) do
|
||||
local value = denoms[stack:get_name()]
|
||||
if value then
|
||||
total = total + (value * stack:get_count())
|
||||
end
|
||||
end
|
||||
return total
|
||||
end
|
||||
|
||||
local function highest_note(notes, amount)
|
||||
local result = nil
|
||||
local tmount = 0
|
||||
for note,cnt in pairs(notes) do
|
||||
local nt = denoms[note]
|
||||
if nt > amount and cnt > 0 then
|
||||
result = note
|
||||
tmount = nt
|
||||
end
|
||||
end
|
||||
return tmount, result
|
||||
end
|
||||
|
||||
local function take_notes(inventory, total)
|
||||
-- Take an audit of all the notes in the inventory
|
||||
local notes = {}
|
||||
for _,stack in pairs(inventory:get_list("main")) do
|
||||
local name = stack:get_name()
|
||||
if denoms[name] then
|
||||
if notes[name] then
|
||||
notes[name] = notes[name] + stack:get_count()
|
||||
else
|
||||
notes[name] = stack:get_count()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local original = table.copy(notes)
|
||||
|
||||
-- Loop through, getting the highest notes first
|
||||
while total > 0 do
|
||||
local amount,item = get_closest_note(total,notes)
|
||||
if amount == 0 then break end
|
||||
if notes[item] then
|
||||
notes[item] = notes[item] - 1
|
||||
end
|
||||
total = total - amount
|
||||
end
|
||||
|
||||
-- If the total was not reached, try to get the next highest note
|
||||
local give = 0
|
||||
if total > 0 then
|
||||
local nxam,note = highest_note(notes, total)
|
||||
if nxam > total then
|
||||
notes[note] = notes[note] - 1
|
||||
give = nxam - total
|
||||
total = 0
|
||||
end
|
||||
end
|
||||
|
||||
-- Couldn't take total balance
|
||||
if total > 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Take from inventory
|
||||
for note,count in pairs(notes) do
|
||||
if original[note] then
|
||||
local taken = original[note] - count
|
||||
if taken > 0 then
|
||||
inventory:remove_item("main", ItemStack(note .. " " .. taken))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if give > 0 then
|
||||
local stacks = denominate(give)
|
||||
for _,stack in pairs(stacks) do
|
||||
inventory:add_item("main", stack)
|
||||
end
|
||||
end
|
||||
|
||||
return total
|
||||
end
|
||||
|
||||
-- Public functions
|
||||
|
||||
function towny.eco.get_player_balance(player)
|
||||
if type(player) == "string" then
|
||||
player = minetest.get_player_by_name(player)
|
||||
end
|
||||
if not player then return 0 end
|
||||
if towny.eco.type == "item" then
|
||||
return notes_inv(player:get_inventory())
|
||||
else
|
||||
local meta = player:get_meta()
|
||||
return meta:get_float("money")
|
||||
end
|
||||
end
|
||||
|
||||
function towny.eco.charge_player(player, amount)
|
||||
if type(player) == "string" then
|
||||
player = minetest.get_player_by_name(player)
|
||||
end
|
||||
if not player then return false end
|
||||
if towny.eco.type == "item" then
|
||||
return take_notes(player:get_inventory(), amount)
|
||||
else
|
||||
local meta = player:get_meta()
|
||||
local money = meta:get_float("money")
|
||||
if money < amount then
|
||||
return false
|
||||
end
|
||||
meta:set_float(money - amount)
|
||||
return amount
|
||||
end
|
||||
end
|
||||
|
||||
function towny.eco.pay_player(player, amount)
|
||||
if type(player) == "string" then
|
||||
player = minetest.get_player_by_name(player)
|
||||
end
|
||||
if not player then return false end
|
||||
if towny.eco.type == "item" then
|
||||
local inventory = player:get_inventory()
|
||||
local stacks = denominate(amount)
|
||||
for _,stack in pairs(stacks) do
|
||||
inventory:add_item("main", stack)
|
||||
end
|
||||
else
|
||||
local meta = player:get_meta()
|
||||
local money = meta:get_float("money")
|
||||
meta:set_float(money + amount)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local requests = {}
|
||||
|
||||
local function c(msg)
|
||||
return minetest.colorize("#09b700",msg)
|
||||
end
|
||||
|
||||
local function b(msg)
|
||||
return minetest.colorize("#078c00",msg)
|
||||
end
|
||||
|
||||
local function msg(name,msg)
|
||||
minetest.chat_send_player(name,msg)
|
||||
return true
|
||||
end
|
||||
|
||||
local function fm(amount)
|
||||
return towny.eco.format_number(amount)
|
||||
end
|
||||
|
||||
local function help()
|
||||
return minetest.colorize("#e5b002", "Command usage:") .. "\n" ..
|
||||
b("/money") .. c(" - Check your balance") .. "\n" ..
|
||||
b("/money transfer") .. c(" <player> <amount> - Give money to a player") .. "\n" ..
|
||||
b("/money request") .. c(" <player> <amount> - Request money from a player") .. "\n"
|
||||
end
|
||||
|
||||
local function money_command(name, param)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if not player then
|
||||
return false, "Only an online player can run this command."
|
||||
end
|
||||
|
||||
if param == "" then
|
||||
return true, b("Balance: ") .. c(fm(towny.eco.get_player_balance(player)))
|
||||
end
|
||||
|
||||
local command,target,amount = param:match("^(%a+) ([%a%d_-]+) ([%d.]+)$")
|
||||
local target_player = minetest.get_player_by_name(target or "")
|
||||
if command and not target then
|
||||
return false, "The target player doesn't exist."
|
||||
end
|
||||
|
||||
amount = tonumber(amount)
|
||||
|
||||
if command == "transfer" or command == "pay" or command == "give" then
|
||||
local taken = towny.eco.charge_player(player, amount)
|
||||
if not taken then
|
||||
return false, "You do not have enough money."
|
||||
end
|
||||
|
||||
towny.eco.pay_player(target_player, amount)
|
||||
minetest.chat_send_player(target, c("Player %s has paid you %s!"):format(name, fm(amount)))
|
||||
return true, c("Successfully given %s to %s."):format(fm(amount), target)
|
||||
elseif command == "request" then
|
||||
if requests[name.."-"..target] then
|
||||
return false, "You have already requested money from that player."
|
||||
end
|
||||
requests[name.."-"..target] = true
|
||||
|
||||
minetest.chat_send_player(target, c("Player %s requested a total of %s from you. Run '/money pay %s %d' to pay them.")
|
||||
:format(name, fm(amount), name, amount))
|
||||
return true, c("Request sent.")
|
||||
end
|
||||
|
||||
return false, help()
|
||||
end
|
||||
|
||||
minetest.register_chatcommand("money", {
|
||||
description = "View and transfer your money",
|
||||
privs = {interact = true},
|
||||
func = money_command
|
||||
})
|
||||
|
||||
towny.eco.type = "item"
|
||||
towny.eco.enabled = true
|
6
towny_eco/settingtypes.txt
Normal file
6
towny_eco/settingtypes.txt
Normal file
@ -0,0 +1,6 @@
|
||||
towny_tax (Allow taxation) bool true
|
||||
|
||||
# Units depend on economy mod used in server
|
||||
towny_create_cost (Town creation cost) int 10000
|
||||
towny_claim_cost (Town claim block cost) int 1000
|
||||
towny_upkeep_cost (Town daily upkeep cost, multiplied by member count) int 0
|
Loading…
Reference in New Issue
Block a user