This commit is contained in:
Milan2018 2024-11-10 14:47:55 +01:00
parent 623ef197f6
commit d6cb0dc610
111 changed files with 8499 additions and 0 deletions

2
hbhunger/.mailmap Normal file
View file

@ -0,0 +1,2 @@
Wuzzy <Wuzzy@disroot.org> <Wuzzy2@mail.ru>
Wuzzy <Wuzzy@disroot.org> <almikes@aol.com>

96
hbhunger/README.md Normal file
View file

@ -0,0 +1,96 @@
# Hunger with HUD Bar [`hbhunger`]
* Version: 1.1.6
## Using the mod
This mod adds a mechanic for hunger.
This mod depends on the HUD bars mod [`hudbars`], version 1.4.1 or any later version
starting with “1.” or “2.”.
## About hunger
This mod adds a hunger mechanic to the game. Players get a new attribute called “satiation”:
* A new player starts with 20 satiation points out of 30
* Actions like digging, placing and walking cause exhaustion, which lower the satiation
* Every 800 seconds you lose 1 satiation point without doing anything
* At 1 or 0 satiation you will suffer damage and die in case you don't eat something
* If your satiation is 16 or higher, you will slowly regenerate health points
* Eating food will increase your satiation (Duh!)
Important: Eating food will not directly increase your health anymore, as long as the food
item is supported by this mod (see below).
Careful! Some foods may be poisoned. If you eat a poisoned item, you may still get a satiation
boost, but for a brief period you lose health points because of food poisoning. However,
food poisoning can never kill you.
## Statbar mode
If you use the statbar mode of the HUD Bars mod, these things are important to know:
As with all mods using HUD Bars, the bread statbar symbols represent the rough percentage
out of 30 satiation points, in steps of 5%, so the symbols give you an estimate of your
satiation. This is different from the hunger mod by BlockMen.
You gain health at 5.5 symbols or more, as 5.5 symbols correspond to 16 satiation points.
You *may* lose health at exactly 0.5 symbols, as 0.5 symbols correspond to 1-2 satiation points.
## Supported food
All mods which add food through standard measures (`minetest.item_eat`) are already
supported automatically. Poisoned food needs special support.
### Known supported food mods
* Apple and Blueberries from Minetest Game [`default`]
* Red and brown mushroom from Minetest Game [`flowers`]
* Bread from Minetest Game [`farming`]
* [`animalmaterials`] (Mob Framework (`mobf` modpack))
* Bushes [`bushes`]
* [`bushes_classic`]
* Creatures [`creatures`]
* [`dwarves`] (beer and such)
* Docfarming [`docfarming`]
* Ethereal / Ethereal NG [`ethereal`]
* Farming Redo [`farming`] by TenPlus1
* Farming plus [`farming_plus`]
* Ferns [`ferns`]
* Fishing [`fishing`]
* [`fruit`]
* Glooptest [`glooptest`]
* JKMod ([`jkanimals`], [`jkfarming`], [`jkwine`])
* [`kpgmobs`]
* [`mobfcooking`]
* [`mooretrees`]
* [`mtfoods`]
* [`mushroom`]
* [`mush45`]
* Seaplants [`sea`]
* Simple mobs [`mobs`]
* Pizza [`pizza`]
* Not So Simple Mobs [`nssm`]
### Supported mods without optional dependency (mods provide their own support)
* Food ([`food`], [`food_basic`])
* Sweet Foods [`food_sweet`]
### Example
* Eating an apple (from Minetest Game) increases your satiation by 2;
## Licensing
This mod is free software.
### Source code
* License: [LGPL v2.1](https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html)
* Author: by Wuzzy (2015-2016)
* Forked from the “Better HUD (and hunger)” mod by BlockMen (2013-2015),
most code comes from this mod.
### Textures
* `hbhunger_icon.png`—PilzAdam ([MIT License](https://opensource.org/licenses/MIT)), modified by BlockMen
* `hbhunger_bgicon.png`—PilzAdam (MIT License), modified by BlockMen
* `hbhunger_bar.png`—Wuzzy (MIT License)
* `hbhunger_icon_health_poison.png`—celeron55 ([CC BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/)), modified by BlockMen, modified again by Wuzzy
* Everything else: MIT License, by BlockMen and Wuzzy

168
hbhunger/hunger.lua Normal file
View file

@ -0,0 +1,168 @@
-- Keep these for backwards compatibility
function hbhunger.save_hunger(player)
hbhunger.set_hunger_raw(player)
end
function hbhunger.load_hunger(player)
hbhunger.get_hunger_raw(player)
end
-- HACK: We register our on_item_eat handler after the other mods have loaded
-- so their on_item_eat handlers run first. This is because Minetest refuses
-- to run ANY further on_item_eat handler once one of the callback functions
-- has returned an itemstack. (as of Minetest 5.8.0)
-- FIXME: Remove the register_on_mods_loaded as soon Minetest handles
-- on_item_eat events in a less weird manner.
minetest.register_on_mods_loaded(function()
minetest.register_on_item_eat(function(hp_change, replace_with_item, itemstack, user, pointed_thing)
-- Our own item eat handler
return hbhunger.eat(hp_change, replace_with_item, ItemStack(itemstack), user, pointed_thing)
end)
end)
-- food functions
local food = hbhunger.food
function hbhunger.register_food(name, hunger_change, replace_with_item, poisen, heal, sound)
food[name] = {}
food[name].saturation = hunger_change -- hunger points added
food[name].replace = replace_with_item -- what item is given back after eating
food[name].poisen = poisen -- time its poisening
food[name].healing = heal -- amount of HP
food[name].sound = sound -- special sound that is played when eating
end
function hbhunger.eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
local item = itemstack:get_name()
local def = food[item]
if not def then
def = {}
if type(hp_change) ~= "number" then
hp_change = 1
minetest.log("error", "Wrong on_use() definition for item '" .. item .. "'")
end
def.saturation = hp_change * 1.3
def.replace = replace_with_item
end
local func = hbhunger.item_eat(def.saturation, def.replace, def.poisen, def.healing, def.sound)
return func(itemstack, user, pointed_thing)
end
-- Poison player
local function poisenp(tick, time, time_left, player)
-- First check if player is still there
if not player:is_player() then
return
end
time_left = time_left + tick
if time_left < time then
minetest.after(tick, poisenp, tick, time, time_left, player)
else
hbhunger.poisonings[player:get_player_name()] = hbhunger.poisonings[player:get_player_name()] - 1
if hbhunger.poisonings[player:get_player_name()] <= 0 then
-- Reset HUD bar color
hb.change_hudbar(player, "health", nil, nil, "hudbars_icon_health.png", nil, "hudbars_bar_health.png")
end
end
if player:get_hp()-1 > 0 then
player:set_hp(player:get_hp()-1)
end
end
function hbhunger.item_eat(hunger_change, replace_with_item, poisen, heal, sound)
return function(itemstack, user, pointed_thing)
if itemstack:take_item() ~= nil and user ~= nil then
local name = user:get_player_name()
local h = tonumber(hbhunger.hunger[name])
local hp = user:get_hp()
if h == nil or hp == nil then
return
end
if user:is_player() then
local object, object_pos
-- Check if user is a "fake player" (unofficial imitation of a the player data structure)
if type(user) == "userdata" then
object = user
else
object_pos = user:get_pos()
end
minetest.sound_play(
{name = sound or "hbhunger_eat_generic",
gain = 1},
{object=object,
pos=object_pos,
max_hear_distance = 16,
pitch = 1 + math.random(-10, 10)*0.005,},
true
)
end
-- Saturation
if h < hbhunger.SAT_MAX and hunger_change then
h = h + hunger_change
if h > hbhunger.SAT_MAX then h = hbhunger.SAT_MAX end
hbhunger.hunger[name] = h
hbhunger.set_hunger_raw(user)
end
-- Healing
local hp_max = user:get_properties().hp_max or minetest.PLAYER_MAX_HP_DEFAULT or 20
if hp < hp_max and heal then
hp = hp + heal
if hp > hp_max then hp = hp_max end
user:set_hp(hp)
end
-- Poison
if poisen then
-- Set poison bar
hb.change_hudbar(user, "health", nil, nil, "hbhunger_icon_health_poison.png", nil, "hbhunger_bar_health_poison.png")
hbhunger.poisonings[name] = hbhunger.poisonings[name] + 1
poisenp(1, poisen, 0, user)
end
if itemstack:get_count() == 0 then
itemstack:add_item(replace_with_item)
else
local inv = user:get_inventory()
if inv:room_for_item("main", replace_with_item) then
inv:add_item("main", replace_with_item)
else
minetest.add_item(user:get_pos(), replace_with_item)
end
end
end
return itemstack
end
end
-- player-action based hunger changes
function hbhunger.handle_node_actions(pos, oldnode, player, ext)
-- is_fake_player comes from the pipeworks, we are not interested in those
if not player or not player:is_player() or player.is_fake_player == true then
return
end
local name = player:get_player_name()
local exhaus = hbhunger.exhaustion[name]
if exhaus == nil then return end
local new = hbhunger.EXHAUST_PLACE
-- placenode event
if not ext then
new = hbhunger.EXHAUST_DIG
end
-- assume its send by main timer when movement detected
if not pos and not oldnode then
new = hbhunger.EXHAUST_MOVE
end
exhaus = exhaus + new
if exhaus > hbhunger.EXHAUST_LVL then
exhaus = 0
local h = tonumber(hbhunger.hunger[name])
h = h - 1
if h < 0 then h = 0 end
hbhunger.hunger[name] = h
hbhunger.set_hunger_raw(player)
end
hbhunger.exhaustion[name] = exhaus
end
minetest.register_on_placenode(hbhunger.handle_node_actions)
minetest.register_on_dignode(hbhunger.handle_node_actions)

188
hbhunger/init.lua Normal file
View file

@ -0,0 +1,188 @@
local S = minetest.get_translator("hbhunger")
if minetest.settings:get_bool("enable_damage") then
hbhunger = {}
hbhunger.food = {}
-- HUD statbar values
hbhunger.hunger = {}
hbhunger.hunger_out = {}
-- Count number of poisonings a player has at once
hbhunger.poisonings = {}
-- HUD item ids
local hunger_hud = {}
hbhunger.HUD_TICK = 0.1
--Some hunger settings
hbhunger.exhaustion = {} -- Exhaustion is experimental!
hbhunger.HUNGER_TICK = 800 -- time in seconds after that 1 hunger point is taken
hbhunger.EXHAUST_DIG = 3 -- exhaustion increased this value after digged node
hbhunger.EXHAUST_PLACE = 1 -- exhaustion increased this value after placed
hbhunger.EXHAUST_MOVE = 0.3 -- exhaustion increased this value if player movement detected
hbhunger.EXHAUST_LVL = 160 -- at what exhaustion player satiation gets lowerd
hbhunger.SAT_MAX = 30 -- maximum satiation points
hbhunger.SAT_INIT = 20 -- initial satiation points
hbhunger.SAT_HEAL = 15 -- required satiation points to start healing
--load custom settings
local set = io.open(minetest.get_modpath("hbhunger").."/hbhunger.conf", "r")
if set then
dofile(minetest.get_modpath("hbhunger").."/hbhunger.conf")
set:close()
end
local function custom_hud(player)
hb.init_hudbar(player, "satiation", hbhunger.get_hunger_raw(player))
end
dofile(minetest.get_modpath("hbhunger").."/hunger.lua")
dofile(minetest.get_modpath("hbhunger").."/register_foods.lua")
-- register satiation hudbar
hb.register_hudbar("satiation", 0xFFFFFF, S("Satiation"), { icon = "hbhunger_icon.png", bgicon = "hbhunger_bgicon.png", bar = "hbhunger_bar.png" }, hbhunger.SAT_INIT, hbhunger.SAT_MAX, false, nil, { format_value = "%.1f", format_max_value = "%d" })
-- update hud elemtens if value has changed
local function update_hud(player)
local name = player:get_player_name()
--hunger
local h_out = tonumber(hbhunger.hunger_out[name])
local h = tonumber(hbhunger.hunger[name])
if h_out ~= h then
hbhunger.hunger_out[name] = h
hb.change_hudbar(player, "satiation", h)
end
end
hbhunger.get_hunger_raw = function(player)
local inv = player:get_inventory()
if not inv then return nil end
local hgp = inv:get_stack("hunger", 1):get_count()
if hgp == 0 then
hgp = 21
inv:set_stack("hunger", 1, ItemStack({name=":", count=hgp}))
else
hgp = hgp
end
return hgp-1
end
hbhunger.set_hunger_raw = function(player)
local inv = player:get_inventory()
local name = player:get_player_name()
local value = hbhunger.hunger[name]
if not inv or not value then return nil end
if value > hbhunger.SAT_MAX then value = hbhunger.SAT_MAX end
if value < 0 then value = 0 end
inv:set_stack("hunger", 1, ItemStack({name=":", count=value+1}))
return true
end
minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
local inv = player:get_inventory()
inv:set_size("hunger",1)
hbhunger.hunger[name] = hbhunger.get_hunger_raw(player)
hbhunger.hunger_out[name] = hbhunger.hunger[name]
hbhunger.exhaustion[name] = 0
hbhunger.poisonings[name] = 0
custom_hud(player)
hbhunger.set_hunger_raw(player)
end)
minetest.register_on_respawnplayer(function(player)
-- reset hunger (and save)
local name = player:get_player_name()
hbhunger.hunger[name] = hbhunger.SAT_INIT
hbhunger.set_hunger_raw(player)
hbhunger.exhaustion[name] = 0
end)
local main_timer = 0
local timer = 0
local timer2 = 0
minetest.register_globalstep(function(dtime)
main_timer = main_timer + dtime
timer = timer + dtime
timer2 = timer2 + dtime
if main_timer > hbhunger.HUD_TICK or timer > 4 or timer2 > hbhunger.HUNGER_TICK then
if main_timer > hbhunger.HUD_TICK then main_timer = 0 end
for _,player in ipairs(minetest.get_connected_players()) do
local name = player:get_player_name()
local h = tonumber(hbhunger.hunger[name])
local hp = player:get_hp()
if timer > 4 then
-- heal player by 1 hp if not dead and satiation is > hbhunger.SAT_HEAL
if h > hbhunger.SAT_HEAL and hp > 0 and player:get_breath() > 0 then
player:set_hp(hp+1)
-- or damage player by 1 hp if satiation is < 2
elseif h <= 1 then
if hp-1 >= 0 then player:set_hp(hp-1) end
end
end
-- lower satiation by 1 point after xx seconds
if timer2 > hbhunger.HUNGER_TICK then
if h > 0 then
h = h-1
hbhunger.hunger[name] = h
hbhunger.set_hunger_raw(player)
end
end
-- update all hud elements
update_hud(player)
local controls = player:get_player_control()
-- Determine if the player is walking
if controls.up or controls.down or controls.left or controls.right then
hbhunger.handle_node_actions(nil, nil, player)
end
end
end
if timer > 4 then timer = 0 end
if timer2 > hbhunger.HUNGER_TICK then timer2 = 0 end
end)
minetest.register_chatcommand("satiation", {
privs = {["server"]=true},
params = S("[<player>] <satiation>"),
description = S("Set satiation of player or yourself"),
func = function(name, param)
if minetest.settings:get_bool("enable_damage") == false then
return false, S("Not possible, damage is disabled.")
end
local targetname, satiation = string.match(param, "(%S+) (%S+)")
if not targetname then
satiation = param
end
satiation = tonumber(satiation)
if not satiation then
return false, S("Invalid satiation!")
end
if not targetname then
targetname = name
end
local target = minetest.get_player_by_name(targetname)
if target == nil then
return false, S("Player @1 does not exist.", targetname)
end
if satiation > hbhunger.SAT_MAX then
satiation = hbhunger.SAT_MAX
elseif satiation < 0 then
satiation = 0
end
hbhunger.hunger[targetname] = satiation
hbhunger.set_hunger_raw(target)
return true
end,
})
end

View file

@ -0,0 +1,9 @@
# textdomain:hbhunger
Hunger with HUD Bar=Hunger mit HUD-Leiste
Adds a simple hunger meachanic with satiation, food poisoning and different healing.=Fügt ein einfaches Hungersystem hinzu, mit Sättigung, Lebensmittelvergiftung und anderer Heilung.
Satiation=Sättigung
[<player>] <satiation>=[<Spieler>] <Sättigung>
Set satiation of player or yourself=Sättigung von Spieler oder Ihnen selbst setzen
Not possible, damage is disabled.=Nicht möglich, Schaden ist deaktiviert.
Invalid satiation!=Ungültige Sättigung!
Player @1 does not exist.=Spieler @1 existiert nicht.

View file

@ -0,0 +1,9 @@
# textdomain:hbhunger
Hunger with HUD Bar=
Adds a simple hunger meachanic with satiation, food poisoning and different healing.=
Satiation=Satiété
[<player>] <satiation>=
Set satiation of player or yourself=
Not possible, damage is disabled.=
Invalid satiation!=
Player @1 does not exist.=

View file

@ -0,0 +1,9 @@
# textdomain:hbhunger
Hunger with HUD Bar=
Adds a simple hunger meachanic with satiation, food poisoning and different healing.=
Satiation=Sazietà
[<player>] <satiation>=
Set satiation of player or yourself=
Not possible, damage is disabled.=
Invalid satiation!=
Player @1 does not exist.=

View file

@ -0,0 +1,9 @@
# textdomain:hbhunger
Hunger with HUD Bar=
Adds a simple hunger meachanic with satiation, food poisoning and different healing.=
Satiation=Kekenyangan
[<player>] <satiation>=
Set satiation of player or yourself=
Not possible, damage is disabled.=
Invalid satiation!=
Player @1 does not exist.=

View file

@ -0,0 +1,9 @@
# textdomain:hbhunger
Hunger with HUD Bar=
Adds a simple hunger meachanic with satiation, food poisoning and different healing.=
Satiation=Saciedade
[<player>] <satiation>=
Set satiation of player or yourself=
Not possible, damage is disabled.=
Invalid satiation!=
Player @1 does not exist.=

View file

@ -0,0 +1,9 @@
# textdomain:hbhunger
Hunger with HUD Bar=
Adds a simple hunger meachanic with satiation, food poisoning and different healing.=
Satiation=голод
[<player>] <satiation>=
Set satiation of player or yourself=
Not possible, damage is disabled.=
Invalid satiation!=
Player @1 does not exist.=

View file

@ -0,0 +1,9 @@
# textdomain:hbhunger
Hunger with HUD Bar=
Adds a simple hunger meachanic with satiation, food poisoning and different healing.=
Satiation=
[<player>] <satiation>=
Set satiation of player or yourself=
Not possible, damage is disabled.=
Invalid satiation!=
Player @1 does not exist.=

7
hbhunger/mod.conf Normal file
View file

@ -0,0 +1,7 @@
name = hbhunger
title = Hunger with HUD Bar
description = Adds a simple hunger meachanic with satiation, food poisoning and different healing.
depends = hudbars
optional_depends = default, flowers, animalmaterials, bucket, bushes, bushes_classic, cooking, creatures, docfarming, dwarves, ethereal, farming, farming_plus, ferns, fishing, fruit, glooptest, jkanimals, jkfarming, jkwine, kpgmobs, mobfcooking, mobs, moretrees, mtfoods, mush45, mushroom, seaplants, pizza, nssm
release = 26108
author = Wuzzy

331
hbhunger/register_foods.lua Normal file
View file

@ -0,0 +1,331 @@
if minetest.get_modpath("default") ~= nil then
hbhunger.register_food("default:apple", 2)
hbhunger.register_food("default:blueberries", 2)
end
if minetest.get_modpath("flowers") ~= nil then
hbhunger.register_food("flowers:mushroom_brown", 1)
hbhunger.register_food("flowers:mushroom_red", 1, "", 3)
end
if minetest.get_modpath("farming") ~= nil then
hbhunger.register_food("farming:bread", 5)
end
if minetest.get_modpath("mobs") ~= nil then
if mobs.mod ~= nil and mobs.mod == "redo" then
hbhunger.register_food("mobs:cheese", 4)
hbhunger.register_food("mobs:meat", 8)
hbhunger.register_food("mobs:meat_raw", 4)
hbhunger.register_food("mobs:rat_cooked", 4)
hbhunger.register_food("mobs:honey", 2)
hbhunger.register_food("mobs:pork_raw", 3, "", 3)
hbhunger.register_food("mobs:pork_cooked", 8)
hbhunger.register_food("mobs:chicken_cooked", 6)
hbhunger.register_food("mobs:chicken_raw", 2, "", 3)
hbhunger.register_food("mobs:chicken_egg_fried", 2)
if minetest.get_modpath("bucket") then
hbhunger.register_food("mobs:bucket_milk", 3, "bucket:bucket_empty")
end
else
hbhunger.register_food("mobs:meat", 6)
hbhunger.register_food("mobs:meat_raw", 3)
hbhunger.register_food("mobs:rat_cooked", 5)
end
end
if minetest.get_modpath("moretrees") ~= nil then
hbhunger.register_food("moretrees:coconut_milk", 1)
hbhunger.register_food("moretrees:raw_coconut", 2)
hbhunger.register_food("moretrees:acorn_muffin", 3)
hbhunger.register_food("moretrees:spruce_nuts", 1)
hbhunger.register_food("moretrees:pine_nuts", 1)
hbhunger.register_food("moretrees:fir_nuts", 1)
end
if minetest.get_modpath("dwarves") ~= nil then
hbhunger.register_food("dwarves:beer", 2)
hbhunger.register_food("dwarves:apple_cider", 1)
hbhunger.register_food("dwarves:midus", 2)
hbhunger.register_food("dwarves:tequila", 2)
hbhunger.register_food("dwarves:tequila_with_lime", 2)
hbhunger.register_food("dwarves:sake", 2)
end
if minetest.get_modpath("animalmaterials") ~= nil then
hbhunger.register_food("animalmaterials:milk", 2)
hbhunger.register_food("animalmaterials:meat_raw", 3)
hbhunger.register_food("animalmaterials:meat_pork", 3)
hbhunger.register_food("animalmaterials:meat_beef", 3)
hbhunger.register_food("animalmaterials:meat_chicken", 3)
hbhunger.register_food("animalmaterials:meat_lamb", 3)
hbhunger.register_food("animalmaterials:meat_venison", 3)
hbhunger.register_food("animalmaterials:meat_undead", 3, "", 3)
hbhunger.register_food("animalmaterials:meat_toxic", 3, "", 5)
hbhunger.register_food("animalmaterials:meat_ostrich", 3)
hbhunger.register_food("animalmaterials:fish_bluewhite", 2)
hbhunger.register_food("animalmaterials:fish_clownfish", 2)
end
if minetest.get_modpath("fishing") ~= nil then
hbhunger.register_food("fishing:fish_raw", 2)
hbhunger.register_food("fishing:fish_cooked", 5)
hbhunger.register_food("fishing:sushi", 6)
hbhunger.register_food("fishing:shark", 4)
hbhunger.register_food("fishing:shark_cooked", 8)
hbhunger.register_food("fishing:pike", 4)
hbhunger.register_food("fishing:pike_cooked", 8)
end
if minetest.get_modpath("glooptest") ~= nil then
hbhunger.register_food("glooptest:kalite_lump", 1)
end
if minetest.get_modpath("bushes") ~= nil then
hbhunger.register_food("bushes:sugar", 1)
hbhunger.register_food("bushes:strawberry", 2)
hbhunger.register_food("bushes:berry_pie_raw", 3)
hbhunger.register_food("bushes:berry_pie_cooked", 4)
hbhunger.register_food("bushes:basket_pies", 15)
end
if minetest.get_modpath("bushes_classic") then
-- bushes_classic mod, as found in the plantlife modpack
local berries = {
"strawberry",
"blackberry",
"blueberry",
"raspberry",
"gooseberry",
"mixed_berry"}
for _, berry in ipairs(berries) do
if berry ~= "mixed_berry" then
hbhunger.register_food("bushes:"..berry, 1)
end
hbhunger.register_food("bushes:"..berry.."_pie_raw", 2)
hbhunger.register_food("bushes:"..berry.."_pie_cooked", 5)
hbhunger.register_food("bushes:basket_"..berry, 15)
end
end
if minetest.get_modpath("mushroom") ~= nil then
hbhunger.register_food("mushroom:brown", 1)
hbhunger.register_food("mushroom:red", 1, "", 3)
-- mushroom potions: red = strong poison, brown = light restorative
if minetest.get_modpath("vessels") then
hbhunger.register_food("mushroom:brown_essence", 1, "vessels:glass_bottle", nil, 4)
hbhunger.register_food("mushroom:poison", 1, "vessels:glass_bottle", 10)
end
end
if minetest.get_modpath("docfarming") ~= nil then
hbhunger.register_food("docfarming:carrot", 3)
hbhunger.register_food("docfarming:cucumber", 2)
hbhunger.register_food("docfarming:corn", 3)
hbhunger.register_food("docfarming:potato", 4)
hbhunger.register_food("docfarming:bakedpotato", 5)
hbhunger.register_food("docfarming:raspberry", 3)
end
if minetest.get_modpath("farming_plus") ~= nil then
hbhunger.register_food("farming_plus:carrot_item", 3)
hbhunger.register_food("farming_plus:banana", 2)
hbhunger.register_food("farming_plus:orange_item", 2)
hbhunger.register_food("farming:pumpkin_bread", 4)
hbhunger.register_food("farming_plus:strawberry_item", 2)
hbhunger.register_food("farming_plus:tomato_item", 2)
hbhunger.register_food("farming_plus:potato_item", 4)
hbhunger.register_food("farming_plus:rhubarb_item", 2)
end
if minetest.get_modpath("mtfoods") ~= nil then
hbhunger.register_food("mtfoods:dandelion_milk", 1)
hbhunger.register_food("mtfoods:sugar", 1)
hbhunger.register_food("mtfoods:short_bread", 4)
hbhunger.register_food("mtfoods:cream", 1)
hbhunger.register_food("mtfoods:chocolate", 2)
hbhunger.register_food("mtfoods:cupcake", 2)
hbhunger.register_food("mtfoods:strawberry_shortcake", 2)
hbhunger.register_food("mtfoods:cake", 3)
hbhunger.register_food("mtfoods:chocolate_cake", 3)
hbhunger.register_food("mtfoods:carrot_cake", 3)
hbhunger.register_food("mtfoods:pie_crust", 3)
hbhunger.register_food("mtfoods:apple_pie", 3)
hbhunger.register_food("mtfoods:rhubarb_pie", 2)
hbhunger.register_food("mtfoods:banana_pie", 3)
hbhunger.register_food("mtfoods:pumpkin_pie", 3)
hbhunger.register_food("mtfoods:cookies", 2)
hbhunger.register_food("mtfoods:mlt_burger", 5)
hbhunger.register_food("mtfoods:potato_slices", 2)
hbhunger.register_food("mtfoods:potato_chips", 3)
--mtfoods:medicine
hbhunger.register_food("mtfoods:casserole", 3)
hbhunger.register_food("mtfoods:glass_flute", 2)
hbhunger.register_food("mtfoods:orange_juice", 2)
hbhunger.register_food("mtfoods:apple_juice", 2)
hbhunger.register_food("mtfoods:apple_cider", 2)
hbhunger.register_food("mtfoods:cider_rack", 2)
end
if minetest.get_modpath("fruit") ~= nil then
hbhunger.register_food("fruit:apple", 2)
hbhunger.register_food("fruit:pear", 2)
hbhunger.register_food("fruit:bananna", 3)
hbhunger.register_food("fruit:orange", 2)
end
if minetest.get_modpath("mush45") ~= nil then
hbhunger.register_food("mush45:meal", 4)
end
if minetest.get_modpath("seaplants") ~= nil then
hbhunger.register_food("seaplants:kelpgreen", 1)
hbhunger.register_food("seaplants:kelpbrown", 1)
hbhunger.register_food("seaplants:seagrassgreen", 1)
hbhunger.register_food("seaplants:seagrassred", 1)
hbhunger.register_food("seaplants:seasaladmix", 6)
hbhunger.register_food("seaplants:kelpgreensalad", 1)
hbhunger.register_food("seaplants:kelpbrownsalad", 1)
hbhunger.register_food("seaplants:seagrassgreensalad", 1)
hbhunger.register_food("seaplants:seagrassgreensalad", 1)
end
if minetest.get_modpath("mobfcooking") ~= nil then
hbhunger.register_food("mobfcooking:cooked_pork", 6)
hbhunger.register_food("mobfcooking:cooked_ostrich", 6)
hbhunger.register_food("mobfcooking:cooked_beef", 6)
hbhunger.register_food("mobfcooking:cooked_chicken", 6)
hbhunger.register_food("mobfcooking:cooked_lamb", 6)
hbhunger.register_food("mobfcooking:cooked_venison", 6)
hbhunger.register_food("mobfcooking:cooked_fish", 6)
end
if minetest.get_modpath("creatures") ~= nil then
hbhunger.register_food("creatures:meat", 6)
hbhunger.register_food("creatures:flesh", 3)
hbhunger.register_food("creatures:rotten_flesh", 3, "", 3)
end
if minetest.get_modpath("ethereal") then
hbhunger.register_food("ethereal:strawberry", 1)
hbhunger.register_food("ethereal:banana", 4)
hbhunger.register_food("ethereal:pine_nuts", 1)
hbhunger.register_food("ethereal:bamboo_sprout", 0, "", 3)
hbhunger.register_food("ethereal:fern_tubers", 1)
hbhunger.register_food("ethereal:banana_bread", 7)
hbhunger.register_food("ethereal:mushroom_plant", 2)
hbhunger.register_food("ethereal:coconut_slice", 2)
hbhunger.register_food("ethereal:golden_apple", 4, "", nil, 10)
hbhunger.register_food("ethereal:wild_onion_plant", 2)
hbhunger.register_food("ethereal:mushroom_soup", 4, "ethereal:bowl")
hbhunger.register_food("ethereal:mushroom_soup_cooked", 6, "ethereal:bowl")
hbhunger.register_food("ethereal:hearty_stew", 6, "ethereal:bowl")
hbhunger.register_food("ethereal:hearty_stew_cooked", 10, "ethereal:bowl")
if minetest.get_modpath("bucket") then
hbhunger.register_food("ethereal:bucket_cactus", 2, "bucket:bucket_empty")
end
hbhunger.register_food("ethereal:fish_raw", 2)
hbhunger.register_food("ethereal:fish_cooked", 5)
hbhunger.register_food("ethereal:seaweed", 1)
hbhunger.register_food("ethereal:yellowleaves", 1, "", nil, 1)
hbhunger.register_food("ethereal:sashimi", 4)
hbhunger.register_food("ethereal:orange", 2)
end
if minetest.get_modpath("farming") and farming.mod == "redo" then
hbhunger.register_food("farming:bread", 6)
hbhunger.register_food("farming:potato", 1)
hbhunger.register_food("farming:baked_potato", 6)
hbhunger.register_food("farming:cucumber", 4)
hbhunger.register_food("farming:tomato", 4)
hbhunger.register_food("farming:carrot", 3)
hbhunger.register_food("farming:carrot_gold", 6, "", nil, 8)
hbhunger.register_food("farming:corn", 3)
hbhunger.register_food("farming:corn_cob", 5)
hbhunger.register_food("farming:melon_slice", 2)
hbhunger.register_food("farming:pumpkin_slice", 1)
hbhunger.register_food("farming:pumpkin_bread", 9)
hbhunger.register_food("farming:coffee_cup", 2, "farming:drinking_cup")
hbhunger.register_food("farming:coffee_cup_hot", 3, "farming:drinking_cup", nil, 2)
hbhunger.register_food("farming:cookie", 2)
hbhunger.register_food("farming:chocolate_dark", 3)
hbhunger.register_food("farming:donut", 4)
hbhunger.register_food("farming:donut_chocolate", 6)
hbhunger.register_food("farming:donut_apple", 6)
hbhunger.register_food("farming:raspberries", 1)
hbhunger.register_food("farming:blueberries", 1)
hbhunger.register_food("farming:muffin_blueberry", 4)
if minetest.get_modpath("vessels") then
hbhunger.register_food("farming:smoothie_raspberry", 2, "vessels:drinking_glass")
end
hbhunger.register_food("farming:rhubarb", 1)
hbhunger.register_food("farming:rhubarb_pie", 6)
hbhunger.register_food("farming:beans", 1)
end
if minetest.get_modpath("kpgmobs") ~= nil then
hbhunger.register_food("kpgmobs:uley", 3)
hbhunger.register_food("kpgmobs:meat", 6)
hbhunger.register_food("kpgmobs:rat_cooked", 5)
hbhunger.register_food("kpgmobs:med_cooked", 4)
if minetest.get_modpath("bucket") then
hbhunger.register_food("kpgmobs:bucket_milk", 4, "bucket:bucket_empty")
end
end
if minetest.get_modpath("jkfarming") ~= nil then
hbhunger.register_food("jkfarming:carrot", 3)
hbhunger.register_food("jkfarming:corn", 3)
hbhunger.register_food("jkfarming:melon_part", 2)
hbhunger.register_food("jkfarming:cake", 3)
end
if minetest.get_modpath("jkanimals") ~= nil then
hbhunger.register_food("jkanimals:meat", 6)
end
if minetest.get_modpath("jkwine") ~= nil then
hbhunger.register_food("jkwine:grapes", 2)
hbhunger.register_food("jkwine:winebottle", 1)
end
if minetest.get_modpath("cooking") ~= nil then
hbhunger.register_food("cooking:meat_beef_cooked", 4)
hbhunger.register_food("cooking:fish_bluewhite_cooked", 3)
hbhunger.register_food("cooking:fish_clownfish_cooked", 1)
hbhunger.register_food("cooking:meat_chicken_cooked", 2)
hbhunger.register_food("cooking:meat_cooked", 2)
hbhunger.register_food("cooking:meat_pork_cooked", 3)
hbhunger.register_food("cooking:meat_toxic_cooked", -3)
hbhunger.register_food("cooking:meat_venison_cooked", 3)
hbhunger.register_food("cooking:meat_undead_cooked", 1)
end
-- ferns mod of plantlife_modpack
if minetest.get_modpath("ferns") ~= nil then
hbhunger.register_food("ferns:fiddlehead", 1, "", 1)
hbhunger.register_food("ferns:fiddlehead_roasted", 3)
hbhunger.register_food("ferns:ferntuber_roasted", 3)
hbhunger.register_food("ferns:horsetail_01", 1)
end
if minetest.get_modpath("pizza") ~= nil then
hbhunger.register_food("pizza:pizza", 30, "", nil, 30)
hbhunger.register_food("pizza:pizzaslice", 5, "", nil, 5)
end
if minetest.get_modpath("nssm") then
hbhunger.register_food("nssm:werewolf_leg", 3)
hbhunger.register_food("nssm:heron_leg", 2)
hbhunger.register_food("nssm:chichibios_heron_leg", 4)
hbhunger.register_food("nssm:crocodile_tail", 3)
hbhunger.register_food("nssm:duck_legs", 1)
hbhunger.register_food("nssm:ant_leg", 1)
hbhunger.register_food("nssm:spider_leg", 1)
hbhunger.register_food("nssm:tentacle", 2)
hbhunger.register_food("nssm:worm_flesh", 2, "", 2) -- poisonous
hbhunger.register_food("nssm:amphibian_heart", 1)
hbhunger.register_food("nssm:raw_scrausics_wing", 1)
-- superfoods
hbhunger.register_food("nssm:phoenix_nuggets", 20, "", nil, 20)
hbhunger.register_food("nssm:phoenix_tear", 20, "", nil, 20)
end

BIN
hbhunger/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 417 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 B

11
hbsprint/.github/workflows/build.yml vendored Normal file
View file

@ -0,0 +1,11 @@
on: [push, pull_request]
name: build
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: lint
uses: Roang-zero1/factorio-mod-luacheck@master
with:
luacheckrc_url: ""

19
hbsprint/.luacheckrc Normal file
View file

@ -0,0 +1,19 @@
allow_defined_top = true
unused_args = false
max_line_length = false
read_globals = {
string = {fields = {"split", "trim"}},
table = {fields = {"copy", "getn"}},
"player_monoids",
"playerphysics",
"hb",
"vector",
"hunger_ng",
}
globals = {
"minetest",
"hbhunger"
}

504
hbsprint/LICENSE Normal file
View file

@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
(This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.)
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
{description}
Copyright (C) {year} {fullname}
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random
Hacker.
{signature of Ty Coon}, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

39
hbsprint/README.md Normal file
View file

@ -0,0 +1,39 @@
# hbSprint
## Description
A flexible sprint mod supporting stamina, hunger and coexistance with other physics altering mods.
## Licensing
- LGPLv2.1/CC BY-SA 3.0. Particle code: copyright (c) 2017 Elijah Duffy.
- sprint_stamina_\*icon textures:
- CC0
- Created by Jordan Irwin (AntumDeluge)
- Based on [Running man icon by manio1](https://openclipart.org/detail/254287)
## Notes
hbSprint can be played with Minetest 0.4.16 or above.
It has no dependencies, but supports [hudbars](https://repo.or.cz/minetest_hudbars.git) and [player_monoids](https://github.com/minetest-mods/player_monoids).
Compatible hunger mods: [hbhunger](https://repo.or.cz/minetest_hbhunger.git) or [hunger_ng](https://gitlab.com/4w/hunger_ng).
## List of features
- Displays and drains stamina (by default, if hudbars is present). Hides stamina bar if full.
- Displays and drains satiation (by default, if compatible hunger mod found)
- Drains air faster while sprinting on walkable ground but in water (by default)
- Requires only forward key to be pressed, not left and right (by default)
- Requires walkable ground (no water surface sprinting)
- Particle spawning based on ground type (Thanks to [octacian](https://github.com/octacian/sprint/))
- All variables customizable in Advanced settings or directly in minetest.conf
## Known issues
- Forward double tap support not implemented
## Bug reports and suggestions
You can report bugs or suggest ideas by [filing an issue](http://github.com/tacotexmex/hbsprint/issues/new).
## Links
* [Download ZIP](https://github.com/minetest-mods/hbsprint/archive/master.zip)
* [Source](https://github.com/minetest-mods/hbsprint)
* [Forum thread](https://forum.minetest.net/viewtopic.php?f=9&t=18069&p=282981)

261
hbsprint/init.lua Normal file
View file

@ -0,0 +1,261 @@
-- Vars
local function setting_get(name, default)
return minetest.settings:get(name) or default
end
local speed = tonumber(setting_get("sprint_speed", "1.3"))
local jump = tonumber(setting_get("sprint_jump", "1.1"))
local dir = minetest.is_yes(setting_get("sprint_forward_only", "false"))
local particles = tonumber(setting_get("sprint_particles", "2"))
local stamina = minetest.is_yes(setting_get("sprint_stamina", "true"))
local stamina_drain = tonumber(setting_get("sprint_stamina_drain", "2"))
local stamina_heal = tonumber(setting_get("sprint_stamina_heal", "2"))
local standing = tonumber(setting_get("sprint_stamina_standing", "2.5"))
local replenish = tonumber(setting_get("sprint_stamina_replenish", "2"))
local starve = minetest.is_yes(setting_get("sprint_starve", "true"))
local starve_drain = tonumber(setting_get("sprint_starve_drain", "0.5"))
local starve_limit = tonumber(setting_get("sprint_starve_limit", "6"))
local breath = minetest.is_yes(setting_get("sprint_breath", "true"))
local breath_drain = tonumber(setting_get("sprint_breath_drain", "1"))
local autohide = minetest.is_yes(setting_get("hudbars_autohide_stamina", "true"))
local sprint_timer_step = 0.5
local sprint_timer = 0
local sprinting = {}
local stamina_timer = {}
local breath_timer = {}
local mod_hudbars = minetest.get_modpath("hudbars") ~= nil
local mod_player_monoids = minetest.get_modpath("player_monoids") ~= nil
local mod_playerphysics = minetest.get_modpath("playerphysics") ~= nil
if starve then
if minetest.get_modpath("hbhunger") then
starve = "hbhunger"
elseif minetest.get_modpath("hunger_ng") then
starve = "hunger_ng"
else
starve = false
end
end
if minetest.settings:get_bool("creative_mode") then
starve = false
end
-- Functions
local function start_sprint(player)
local name = player:get_player_name()
if not sprinting[name] then
if mod_player_monoids then
player_monoids.speed:add_change(player, speed, "hbsprint:speed")
player_monoids.jump:add_change(player, jump, "hbsprint:jump")
elseif mod_playerphysics then
playerphysics.add_physics_factor(player, "speed", "hbsprint:speed", speed)
playerphysics.add_physics_factor(player, "jump", "hbsprint:jump", jump)
else
player:set_physics_override({speed = speed, jump = jump})
end
sprinting[name] = true
end
end
local function stop_sprint(player)
local name = player:get_player_name()
if sprinting[name] then
if mod_player_monoids then
player_monoids.speed:del_change(player, "hbsprint:speed")
player_monoids.jump:del_change(player, "hbsprint:jump")
elseif mod_playerphysics then
playerphysics.remove_physics_factor(player, "speed", "hbsprint:speed")
playerphysics.remove_physics_factor(player, "jump", "hbsprint:jump")
else
player:set_physics_override({speed = 1, jump = 1})
end
sprinting[name] = false
end
end
local function drain_stamina(player)
local player_stamina = player:get_meta():get_float("hbsprint:stamina")
if player_stamina > 0 then
player_stamina = math.max(0, player_stamina - stamina_drain)
player:get_meta():set_float("hbsprint:stamina", player_stamina)
end
if mod_hudbars then
if autohide and player_stamina < 20 then hb.unhide_hudbar(player, "stamina") end
hb.change_hudbar(player, "stamina", player_stamina)
end
end
local function replenish_stamina(player)
local player_stamina = player:get_meta():get_float("hbsprint:stamina")
local ctrl = player:get_player_control()
if player_stamina < 20 and not ctrl.jump then
if not ctrl.right and not ctrl.left and not ctrl.down and not ctrl.up and not ctrl.LMB and not ctrl.RMB then
player_stamina = math.min(20, player_stamina + standing)
else
player_stamina = math.min(20, player_stamina + stamina_heal)
end
player:get_meta():set_float("hbsprint:stamina", player_stamina)
end
if mod_hudbars then
hb.change_hudbar(player, "stamina", player_stamina)
if autohide and player_stamina >= 20 then hb.hide_hudbar(player, "stamina") end
end
end
local function drain_hunger(player, name)
if starve == "hbhunger" then
local hunger = tonumber(hbhunger.hunger[name]) - starve_drain
hbhunger.hunger[name] = math.max(0, hunger)
hbhunger.set_hunger_raw(player)
elseif starve == "hunger_ng" then
hunger_ng.alter_hunger(name, -starve_drain, "Sprinting")
end
end
local function drain_breath(player)
local player_breath = player:get_breath()
if player_breath < player:get_properties().breath_max then
player_breath = math.max(0, player_breath - breath_drain)
player:set_breath(player_breath)
end
end
local function is_walkable(ground)
local ground_def = minetest.registered_nodes[ground.name]
return ground_def and (ground_def.walkable and ground_def.liquidtype == "none")
end
local function create_particles(player, name, ground)
local def = minetest.registered_nodes[ground.name] or {}
local tile = def.tiles and def.tiles[1] or def.inventory_image
if type(tile) == "table" then
tile = tile.name
end
if not tile then
return
end
local pos = player:get_pos()
local rand = function() return math.random(-1,1) * math.random() / 2 end
for i = 1, particles do
minetest.add_particle({
pos = {x = pos.x + rand(), y = pos.y + 0.1, z = pos.z + rand()},
velocity = {x = 0, y = 5, z = 0},
acceleration = {x = 0, y = -13, z = 0},
expirationtime = math.random(),
size = math.random() + 0.5,
vertical = false,
texture = tile,
})
end
end
-- Registrations
if mod_hudbars and stamina then
hb.register_hudbar(
"stamina",
0xFFFFFF,
"Stamina",
{
bar = "sprint_stamina_bar.png",
icon = "sprint_stamina_icon.png",
bgicon = "sprint_stamina_bgicon.png"
},
20,
20,
autohide)
end
minetest.register_on_joinplayer(function(player)
if stamina then
if mod_hudbars then
hb.init_hudbar(player, "stamina", 20, 20, autohide)
end
player:get_meta():set_float("hbsprint:stamina", 20)
end
end)
local function sprint_step(player, dtime)
local name = player:get_player_name()
local fast = minetest.get_player_privs(name).fast
if not fast then
if stamina then
stamina_timer[name] = (stamina_timer[name] or 0) + dtime
end
if breath then
breath_timer[name] = (breath_timer[name] or 0) + dtime
end
end
local ctrl = player:get_player_control()
local key_press
if dir then
key_press = ctrl.aux1 and ctrl.up and not ctrl.left and not ctrl.right
else
key_press = ctrl.aux1 and (ctrl.up or ctrl.left or ctrl.right or ctrl.down)
end
if not key_press then
stop_sprint(player)
if stamina and not fast and stamina_timer[name] >= replenish then
replenish_stamina(player)
stamina_timer[name] = 0
end
return
end
local ground_pos = player:get_pos()
ground_pos.y = math.floor(ground_pos.y)
-- check if player is reasonably near a walkable node
local ground
for _, y_off in ipairs({0, -1, -2}) do
local testpos = vector.add(ground_pos, {x=0, y=y_off, z=0})
local testnode = minetest.get_node_or_nil(testpos)
if testnode ~= nil and is_walkable(testnode) then
ground = testnode
break
end
end
local player_stamina = 1
if stamina then
player_stamina = player:get_meta():get_float("hbsprint:stamina")
end
local hunger = 30
if starve == "hbhunger" then
hunger = tonumber(hbhunger.hunger[name])
elseif starve == "hunger_ng" then
hunger = hunger_ng.get_hunger_information(name).hunger.exact
end
if (player_stamina > 0 and hunger > starve_limit and ground) or fast then
start_sprint(player)
if stamina and not fast then drain_stamina(player) end
if starve and not fast then drain_hunger(player, name) end
if breath and not fast and breath_timer[name] >= 2 then
drain_breath(player)
breath_timer[name] = 0
end
if particles and ground then
create_particles(player, name, ground)
end
else
stop_sprint(player)
end
end
minetest.register_globalstep(function(dtime)
sprint_timer = sprint_timer + dtime
if sprint_timer >= sprint_timer_step then
for _, player in ipairs(minetest.get_connected_players()) do
sprint_step(player, sprint_timer)
end
sprint_timer = 0
end
end)

6
hbsprint/mod.conf Normal file
View file

@ -0,0 +1,6 @@
name = hbsprint
optional_depends = player_monoids, hudbars, hbhunger, hunger_ng
description = A flexible sprint mod supporting stamina, hunger and monoids.
release = 16568
author = texmex
title = Hbsprint

42
hbsprint/settingtypes.txt Normal file
View file

@ -0,0 +1,42 @@
#Sprint speed multiplier
sprint_speed (Sprint speed multiplier) float 1.3
#Sprint jump multiplier
sprint_jump (Sprint jump multiplier) float 1.1
#Require player to move forward only to be able to sprint
sprint_forward_only (Sprint forward only) bool true
#The amount of particles to spawn behind a sprinting player
sprint_particles (Particles) float 2
#Drain stamina while sprinting
sprint_stamina (Stamina) bool true
#The amount of stamina to drain while sprinting
sprint_stamina_drain (Stamina drain) float 2
#The amount of stamina to heal while not sprinting
sprint_stamina_heal (Stamina heal) float 2
#The amount of stamina to heal while not moving or taking any actions
sprint_stamina_standing (Stamina heal) float 2.5
#The amount of seconds before starting to replenish stamina
sprint_stamina_replenish (Stamina replenish) float 2
#Drain satiation while sprinting
sprint_starve (Starve) bool true
#The amount of satiation to drain while sprinting
sprint_starve_drain (Starve drain) float 0.5
#Drain air while sprinting under water
sprint_breath (Breath) bool true
#The amount of air to drain while sprinting under water
sprint_breath_drain (Breath drain) float 1
#If enabled (default), the stamina indicators in the HUD will be automatically hidden shortly
#after stamina has filled up. Otherwise, stamina will always be displayed.
hudbars_autohide_stamina (Automatically hide staminal indicator) bool true

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

2
hudbars/.mailmap Normal file
View file

@ -0,0 +1,2 @@
Wuzzy <Wuzzy@disroot.org> <Wuzzy2@mail.ru>
Wuzzy <Wuzzy@disroot.org> <almikes@aol.com>

210
hudbars/API.md Normal file
View file

@ -0,0 +1,210 @@
API documentation for the HUD bars mod
======================================
## Introduction
This API allows you to add, change, hide and unhide custom HUD bars for this mod.
## Overview
To give you a *very* brief overview over this API, here is the basic workflow on how to add your own custom HUD bar:
* Create images for your HUD bar
* Call `hb.register_hudbar` to make the definition of the HUD bar known to this mod
* Call `hb.init_hudbar` for each player for which you want to use previously defined HUD bar
* Use `hb.change_hudbar` whenever you need to change the values of a HUD bar of a certain player
* If you need it: Use `hb.hide_hudbar` and `hb.unhide_hudbar` to hide or unhide HUD bars of a certain player
## The basic rules
In order to use this API, you should be aware of a few basic rules in order to understand it:
* A HUD bar is an approximate graphical representation of the ratio of a current value and a maximum value, i.e. current health of 15 and maximum health of 20. A full HUD bar represents 100%, an empty HUD bar represents 0%.
* The current value must always be equal to or smaller then the maximum
* Both current value and maximum must not be smaller than 0
* Both current value and maximum must be real numbers. So no NaN, infinity, etc.
* The HUD bar will be hidden if the maximum equals 0. This is intentional.
* The health and breath HUD bars are hardcoded.
These are soft rules, the HUD bars mod will not enforce all of these.
But this mod has been programmed under the assumption that these rules are followed, for integrity.
## Adding a HUD bar
To make a new HUD bar known to this mod, you need …
* … an image of size 2×16 for the bar
* … an icon of size 16×16 (optional)
* … to register it with `hb.register_hudbar`
### Bar image
The image for the bar will be repeated horizontally to denote the “value” of the HUD bar.
It **must** be of size 2×16.
If neccessary, the image will be split vertically in half, and only the left half of the image
is displayed. So the final HUD bar will always be displayed on a per-pixel basis.
The default bar images are single-colored, but you can use other styles as well, for instance,
a vertical gradient.
### Icon
A 16×16 image shown left of the HUD bar. This is optional.
### `hb.register_hudbar(identifier, text_color, label, textures, default_start_value, default_start_max, default_start_hidden, format_string, format_string_config)`
This function registers a new custom HUD bar definition to the HUD bars mod, so it can be later used to be displayed, changed, hidden
and unhidden on a per-player basis.
Note this does not yet display the HUD bar.
The HUD bars will be displayed in a “first come, first serve” order. This API does not allow fow a custom order or a way to set it
manually in a reliable way. However, you can use the setting `hudbars_sorting` for this. See the advanced setting menu in Minetest
for more information.
#### Parameters
* `identifier`: A globally unique internal name for the HUD bar, will be used later to refer to it. Please only rely on alphanumeric characters for now. The identifiers “`health`” and “`breath`” are used internally for the built-in health and breath bar, respectively. Please do not use these names.
* `text_color`: A 3-octet number defining the color of the text. The octets denote, in this order red, green and blue and range from `0x00` (complete lack of this component) to `0xFF` (full intensity of this component). Example: `0xFFFFFF` for white.
* `label`: A string which is displayed on the HUD bar itself to describe the HUD bar. Try to keep this string short.
* `textures`: A table with the following fields:
* `bar`: The file name of the bar image (as string). This is only used for the `progress_bar` bar type (see `README.txt`, settings section).
* `icon`: The file name of the icon, as string. For the `progress_bar` type, it is shown as single image left of the bar, for the two statbar bar types, it is used as the statbar icon and will be repeated. This field can be `nil`, in which case no icon will be used, but this is not recommended, because the HUD bar will be invisible if the one of the statbar bar types is used.
* `bgicon`: The file name of the background icon, it is used as the background for the modern statbar mode only. This field can be `nil`, in which case no background icon will be displayed in this mode.
* `default_start_value`: If this HUD bar is added to a player, and no initial value is specified, this value will be used as initial current value
* `default_max_value`: If this HUD bar is added to a player, and no initial maximum value is specified, this value will be used as initial maximum value
* `default_start_hidden`: The HUD bar will be initially start hidden by default when added to a player. Use `hb.unhide_hudbar` to unhide it.
* `format_string`: Optional; You can specify an alternative format string to use for the final text on the HUD bar. The default format string is “`@1: @2/@3`” (The “@” numbers are placeholders that have a meaning in this order: @1 = Label, @2 = current value, @3 = maximum value). Do *not* use minetest.translator on this string, the string will be translated by `hudbars`, but you still must put this string into the translation catalogue file.
* `format_string_config`: Required if `format_string` is set. This allows to change which parameters to use in the format string. It's a table with these fields:
* `textdomain`: Text domain of the format string, used by `minetest.translate` if missing or set to `nil` will use `minetest.get_translator`
* `order`: Table that contains the order of the placeholders. It's also possible to remove placeholders. Default order: `{ "label", "value", "max_value" }`
* `format_value`: Format string to apply when displaying `value`. Syntax is same as in `string.format`. Default: `"%d"`
* `format_max_value`: Same as `format_value` but is applied to `max_value`
#### Example
Example (mostly) from `hbarmor` mod:
```
hb.register_hudbar("armor", 0xFFFFFF, minetest.translator("hbarmor", "Armor"), { icon = "hbarmor_icon.png", bgicon = "hbarmor_bgicon.png", bar = "hbarmor_bar.png" }, 0, 100, hbarmor.autohide, N("@1: @2%"), { order = { "label", "value" }, textdomain = "hbarmor" } )
```
Displays an armor HUD bar with a label of the form „Armor: 53%“. (`N` is a dummy function that returns its argument, used to make the string visible for translator scripts.)
#### Return value
Always `nil`.
## Displaying a HUD bar
After a HUD bar has been registered, they are not yet displayed yet for any player. HUD bars must be
explicitly initialized on a per-player basis.
You probably want to do this in the `minetest.register_on_joinplayer`.
### `hb.init_hudbar(player, identifier, start_value, start_max, start_hidden)`
This function initialzes and activates a previously registered HUD bar and assigns it to a
certain client/player. This has only to be done once per player and after that, you can change
the values using `hb.change_hudbar`.
However, if `start_hidden` was set to `true` for the HUD bar (in `hb.register_hudbar`), the HUD bar
will initially be hidden, but the HUD elements are still sent to the client. Otherwise,
the HUD bar will be initially be shown to the player.
#### Parameters
* `player`: `ObjectRef` of the player to which the new HUD bar should be displayed to.
* `identifier`: The identifier of the HUD bar type, as specified in `hb.register_hudbar`.
* `start_value`: The initial current value of the HUD bar. This is optional, `default_start_value` of the registration function will be used, if this is `nil`.
* `start_max`: The initial maximum value of the HUD bar. This is optional, `default_start_max` of the registration function will be used, if this is `nil`
* `start_hidden`: Whether the HUD bar is initially hidden. This is optional, `default_start_hidden` of the registration function will be used as default
#### Return value
`true` on success, `false` otherwise.
## Modifying a HUD bar
After a HUD bar has been added, you can change the current and maximum value and other attributes on a per-player basis.
You use the function `hb.change_hudbar` for this.
### `hb.change_hudbar(player, identifier, new_value, new_max_value, new_icon, new_bgicon, new_bar, new_label, new_text_color)`
Changes the values and the appearance of an initialized HUD bar for a certain player. `new_value`
and `new_max_value` are the most important parameters as they specify the new current and maximum new values, you do not need
to worry too much about the other parameters.
The following parameters are less important and provided for styling the HUD bar after registration (if
this is desired). The “styling” parameters parallel the parameters of `hb.register_hudbar`. It is
recommended to not change the style of a HUD bar too often as this can be distracting or confusing
for players.
`new_value`, `new_max_value` `new_icon`, `new_bgicon`, `new_bar`, `new_label` and `new_text_color` can be
`nil`; if one of them is `nil`, that means the value is unchanged. If all those values are `nil`, this
function is a no-op.
This function tries to minimize the amount of calls to `hud_change` of the Minetest Lua API
(and thus, network traffic), when you only change the value and/or maximum value. In this case,
`hud_change` is only called if it is actually needed, e.g. when the actual length of the bar
or the displayed string changed, so you do not have to worry about it. There is, however, no
such network optimization for the “styling” parameters, so keep this in mind.
#### Parameters
* `player`: `ObjectRef` of the player to which the HUD bar belongs to
* `identifier`: The identifier of the HUD bar type to change, as specified in `hb.register_hudbar`.
* `new_value`: The new current value of the HUD bar
* `new_max_value`: The new maximum value of the HUD bar
* `new_icon`: File name of the new icon
* `new_bgicon`: File name of the new background icon for the modern-style statbar
* `new_bar`: File name of the new bar segment image
* `new_label`: A new text label of the HUD bar. Note the format string still applies
* `new_text_color`: A 3-octet number defining the new color of the text.
#### Return value
`true` on success, `false` otherwise.
## Hiding and unhiding a HUD bar
You can also hide custom HUD bars, meaning they will not be displayed for a certain player. You can still
use `hb.change_hudbar` on a hidden HUD bar, the new values will be correctly displayed after the HUD bar
has been unhidden. Both functions will only call `hud_change` if there has been an actual change to avoid
unneccessary traffic.
Note that the hidden state of a HUD bar will *not* be saved by this mod on server shutdown, so you may need
to write your own routines for this or by setting the correct value for `start_hidden` when calling
`hb.init_hudbar`.
### `hb.hide_hudbar(player, identifier)`
Hides the specified HUD bar from the screen of the specified player.
#### Parameters
* `player`: `ObjectRef` of the player to which the HUD bar belongs to
* `identifier`: The identifier of the HUD bar type to hide, as specified in `hb.register_hudbar`.
#### Return value
`true` on success, `false` otherwise.
### `hb.unhide_hudbar(player, identifier)`
Makes a previously hidden HUD bar visible again to a player.
#### Parameters
* `player`: `ObjectRef` of the player to which the HUD bar belongs to
* `identifier`: The identifier of the HUD bar type to unhide, as specified in `hb.register_hudbar`.
#### Return value
`true` on success, `false` otherwise.
## Reading HUD bar information
It is also possible to read information about existing HUD bars.
### `hb.get_hudbar_state(player, identifier)`
Returns the current state of the active player's HUD bar. Will return `nil` if the hudbar is not initialized.
#### Parameters
* `player`: `ObjectRef` of the player to which the HUD bar belongs to
* `identifier`: The identifier of the HUD bar type to hide, as specified in `hb.register_hudbar`.
#### Return value
On success, returns a table which holds information on the current state of the HUD bar. Note
the table is a deep copy of the internal HUD bar state, it is *not* a reference; the information
hold by the table is only true for the moment you called this function. The fields of this table are:
* `value`: Current value of HUD bar.
* `max`: Current maximum value of HUD bar.
* `hidden`: Boolean denoting whether the HUD bar is hidden.
* `barlength`: The length of the HUD bar in pixels. This field is meaningless if the HUD bar is currently hidden.
* `text`: The text shown on the HUD bar. This fiels is meaningless if the HUD bar is currently hidden.
If the player does not exist, returns `nil` instead.
### `hb.get_hudbar_identifiers()`
Returns a table of all currently registered HUD bar identifiers.

63
hudbars/README.md Normal file
View file

@ -0,0 +1,63 @@
# HUD Bars
## Description
This mod changes the HUD of Minetest. It replaces the default health and breath
symbols by horizontal colored bars with text showing the number.
Furthermore, it enables other mods to add their own custom bars to the HUD,
this mod will place them accordingly.
**Important**: Keep in mind if running a server with this mod, that the custom
position should be displayed correctly on every screen size.
## Current version
The current version is 2.3.6.
It works for Minetest 5.3.0 or later.
This software uses [semantic versioning](http://semver.org), as defined by version 2.0.0 of the SemVer
standard.
## Settings
This mod can be configured quite a bit. You can change HUD bar appearance, offsets, ordering, and more.
Use the advanced settings menu in Minetest for detailed configuration.
## API
The API is used to add your own custom HUD bars.
Documentation for the API of this mod can be found in `API.md`.
## Legal
### License of source code
Author: Wuzzy (2015)
Also: This mod was forked from the “Better HUD” [hud] mod by BlockMen.
Translations:
* German: Wuzzy
* Portuguese: BrunoMine
* Turkish: admicos
* Dutch: kingoscargames
* Italian: Hamlet
* Malay: muhdnurhidayat
* Russian: Imk
* Spanish: wuniversales
* French: syl
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the MIT License.
### Licenses of textures
* `hudbars_icon_health.png`—celeron55 (CC BY-SA 3.0), modified by BlockMen
* `hudbars_bgicon_health.png`—celeron55 (CC BY-SA 3.0), modified by BlockMen
* `hudbars_icon_breath.png`—kaeza (MIT License), modified by BlockMen, modified again by Wuzzy
* `hudbars_bgicon_breath.png`—based on previous image, edited by Wuzzy (MIT License)
* `hudbars_bar_health.png`—Wuzzy (MIT License)
* `hudbars_bar_breath.png`—Wuzzy (MIT License)
* `hudbars_bar_background.png`—Wuzzy (MIT License)
### License references
* [CC-BY-SA 3.0](https://creativecommons.org/licenses/by-sa/3.0/)
* [MIT License](https://opensource.org/licenses/MIT)

View file

@ -0,0 +1,49 @@
-- (Hardcoded) default settings
hb.settings.max_bar_length = 160
hb.settings.statbar_length = 20
-- Statbar positions
hb.settings.pos_left = {}
hb.settings.pos_right = {}
hb.settings.start_offset_left = {}
hb.settings.start_offset_right= {}
hb.settings.pos_left.x = hb.load_setting("hudbars_pos_left_x", "number", 0.5)
hb.settings.pos_left.y = hb.load_setting("hudbars_pos_left_y", "number", 1)
hb.settings.pos_right.x = hb.load_setting("hudbars_pos_right_x", "number", 0.5)
hb.settings.pos_right.y = hb.load_setting("hudbars_pos_right_y", "number", 1)
hb.settings.bar_type = hb.load_setting("hudbars_bar_type", "string", "progress_bar", {"progress_bar", "statbar_classic", "statbar_modern"})
if hb.settings.bar_type == "progress_bar" then
hb.settings.start_offset_left.x = hb.load_setting("hudbars_start_offset_left_x", "number", -175)
hb.settings.start_offset_left.y = hb.load_setting("hudbars_start_offset_left_y", "number", -86)
hb.settings.start_offset_right.x = hb.load_setting("hudbars_start_offset_right_x", "number", 15)
hb.settings.start_offset_right.y = hb.load_setting("hudbars_start_offset_right_y", "number", -86)
else
hb.settings.start_offset_left.x = hb.load_setting("hudbars_start_statbar_offset_left_x", "number", -265)
hb.settings.start_offset_left.y = hb.load_setting("hudbars_start_statbar_offset_left_y", "number", -90)
hb.settings.start_offset_right.x = hb.load_setting("hudbars_start_statbar_offset_right_x", "number", 25)
hb.settings.start_offset_right.y = hb.load_setting("hudbars_start_statbar_offset_right_y", "number", -90)
end
hb.settings.vmargin = hb.load_setting("hudbars_vmargin", "number", 24)
hb.settings.tick = hb.load_setting("hudbars_tick", "number", 0.1)
-- Experimental setting: Changing this setting is not officially supported, do NOT rely on it!
hb.settings.forceload_default_hudbars = hb.load_setting("hudbars_forceload_default_hudbars", "bool", true)
-- Misc. settings
hb.settings.alignment_pattern = hb.load_setting("hudbars_alignment_pattern", "string", "zigzag", {"zigzag", "stack_up", "stack_down"})
hb.settings.autohide_breath = hb.load_setting("hudbars_autohide_breath", "bool", true)
hb.settings.hide_labels = hb.load_setting("hudbars_hide_labels", "bool", false)
local sorting = minetest.settings:get("hudbars_sorting")
if sorting ~= nil then
hb.settings.sorting = {}
hb.settings.sorting_reverse = {}
for k,v in string.gmatch(sorting, "(%w+)=(%w+)") do
hb.settings.sorting[k] = tonumber(v)
hb.settings.sorting_reverse[tonumber(v)] = k
end
else
hb.settings.sorting = { ["health"] = 0, ["breath"] = 1 }
hb.settings.sorting_reverse = { [0] = "health", [1] = "breath" }
end

583
hudbars/init.lua Normal file
View file

@ -0,0 +1,583 @@
local S = minetest.get_translator("hudbars")
local NS = function(s) return s end
-- Boilerplate for compatibiliity with pre-5.9.0
-- versions of minetest
local hud_def_type_field
if minetest.features.hud_def_type_field then
hud_def_type_field = "type"
else
hud_def_type_field = "hud_elem_type"
end
hb = {}
hb.hudtables = {}
-- number of registered HUD bars
hb.hudbars_count = 0
-- table which records which HUD bar slots have been “registered” so far; used for automatic positioning
hb.registered_slots = {}
hb.settings = {}
function hb.load_setting(sname, stype, defaultval, valid_values)
local sval
if stype == "string" then
sval = minetest.settings:get(sname)
elseif stype == "bool" then
sval = minetest.settings:get_bool(sname)
elseif stype == "number" then
sval = tonumber(minetest.settings:get(sname))
end
if sval ~= nil then
if valid_values ~= nil then
local valid = false
for i=1,#valid_values do
if sval == valid_values[i] then
valid = true
end
end
if not valid then
minetest.log("error", "[hudbars] Invalid value for "..sname.."! Using default value ("..tostring(defaultval)..").")
return defaultval
else
return sval
end
else
return sval
end
else
return defaultval
end
end
-- Load default settings
dofile(minetest.get_modpath("hudbars").."/default_settings.lua")
local function player_exists(player)
return player ~= nil and player:is_player()
end
local function make_label(format_string, format_string_config, label, start_value, max_value)
if hb.settings.hide_labels then
return ""
end
local params = {}
local order = format_string_config.order
for o=1, #order do
if order[o] == "label" then
table.insert(params, label)
elseif order[o] == "value" then
if format_string_config.format_value then
table.insert(params, string.format(format_string_config.format_value, start_value))
else
table.insert(params, start_value)
end
elseif order[o] == "max_value" then
if format_string_config.format_max_value then
table.insert(params, string.format(format_string_config.format_max_value, max_value))
else
table.insert(params, max_value)
end
end
end
local ret
if format_string_config.textdomain and minetest.translate then
ret = minetest.translate(format_string_config.textdomain, format_string, unpack(params))
else
ret = S(format_string, unpack(params))
end
return ret
end
-- Table which contains all players with active default HUD bars (only for internal use)
hb.players = {}
function hb.value_to_barlength(value, max)
if max == 0 then
return 0
else
if hb.settings.bar_type == "progress_bar" then
local x
if value < 0 then x=-0.5 else x = 0.5 end
local ret = math.modf((value/max) * hb.settings.max_bar_length + x)
return ret
else
local x
if value < 0 then x=-0.5 else x = 0.5 end
local ret = math.modf((value/max) * hb.settings.statbar_length + x)
return ret
end
end
end
function hb.get_hudtable(identifier)
return hb.hudtables[identifier]
end
function hb.get_hudbar_position_index(identifier)
if hb.settings.sorting[identifier] ~= nil then
return hb.settings.sorting[identifier]
else
local i = 0
while true do
if hb.registered_slots[i] ~= true and hb.settings.sorting_reverse[i] == nil then
return i
end
i = i + 1
end
end
end
function hb.register_hudbar(identifier, text_color, label, textures, default_start_value, default_start_max, default_start_hidden, format_string, format_string_config)
minetest.log("action", "hb.register_hudbar: "..tostring(identifier))
local hudtable = {}
local pos, offset
local index = math.floor(hb.get_hudbar_position_index(identifier))
hb.registered_slots[index] = true
if hb.settings.alignment_pattern == "stack_up" then
pos = hb.settings.pos_left
offset = {
x = hb.settings.start_offset_left.x,
y = hb.settings.start_offset_left.y - hb.settings.vmargin * index
}
elseif hb.settings.alignment_pattern == "stack_down" then
pos = hb.settings.pos_left
offset = {
x = hb.settings.start_offset_left.x,
y = hb.settings.start_offset_left.y + hb.settings.vmargin * index
}
else
if index % 2 == 0 then
pos = hb.settings.pos_left
offset = {
x = hb.settings.start_offset_left.x,
y = hb.settings.start_offset_left.y - hb.settings.vmargin * (index/2)
}
else
pos = hb.settings.pos_right
offset = {
x = hb.settings.start_offset_right.x,
y = hb.settings.start_offset_right.y - hb.settings.vmargin * ((index-1)/2)
}
end
end
if format_string == nil then
format_string = NS("@1: @2/@3")
end
if format_string_config == nil then
format_string_config = {}
end
if format_string_config.order == nil then
format_string_config.order = { "label", "value", "max_value" }
end
if format_string_config.format_value == nil then
format_string_config.format_value = "%d"
end
if format_string_config.format_max_value == nil then
format_string_config.format_max_value = "%d"
end
hudtable.add_all = function(player, hudtable, start_value, start_max, start_hidden)
if start_value == nil then start_value = hudtable.default_start_value end
if start_max == nil then start_max = hudtable.default_start_max end
if start_hidden == nil then start_hidden = hudtable.default_start_hidden end
local ids = {}
local state = {}
local name = player:get_player_name()
local bgscale, iconscale, text, barnumber, bgiconnumber
if start_max == 0 or start_hidden then
bgscale = { x=0, y=0 }
else
bgscale = { x=1, y=1 }
end
if start_hidden then
iconscale = { x=0, y=0 }
barnumber = 0
bgiconnumber = 0
text = ""
else
iconscale = { x=1, y=1 }
barnumber = hb.value_to_barlength(start_value, start_max)
bgiconnumber = hb.settings.statbar_length
text = make_label(format_string, format_string_config, label, start_value, start_max)
end
if hb.settings.bar_type == "progress_bar" then
ids.bg = player:hud_add({
[hud_def_type_field] = "image",
position = pos,
scale = bgscale,
text = "hudbars_bar_background.png",
alignment = {x=1,y=1},
offset = { x = offset.x - 1, y = offset.y - 1 },
z_index = 0,
})
if textures.icon ~= nil then
ids.icon = player:hud_add({
[hud_def_type_field] = "image",
position = pos,
scale = iconscale,
text = textures.icon,
alignment = {x=-1,y=1},
offset = { x = offset.x - 3, y = offset.y },
z_index = 1,
})
end
end
local bar_image, bgicon, bar_size
if hb.settings.bar_type == "progress_bar" then
bar_image = textures.bar
-- NOTE: Intentionally set to nil. For some reason, on some systems,
-- the progress bar is displaced when the bar_size is set explicitly here.
-- On the other hand, setting this to nil is deprecated in MT 5.0.0 due to
-- a debug log warning, but nothing is explained in lua_api.txt.
-- This section is a potential bug magnet, please watch with care!
-- The size of the bar image is expected to be exactly 2×16 pixels.
bar_size = nil
elseif hb.settings.bar_type == "statbar_classic" or hb.settings.bar_type == "statbar_modern" then
bar_image = textures.icon
bgicon = textures.bgicon
bar_size = {x=24, y=24}
end
ids.bar = player:hud_add({
[hud_def_type_field] = "statbar",
position = pos,
text = bar_image,
text2 = bgicon,
number = barnumber,
item = bgiconnumber,
alignment = {x=-1,y=-1},
offset = offset,
direction = 0,
size = bar_size,
z_index = 1,
})
if hb.settings.bar_type == "progress_bar" then
ids.text = player:hud_add({
[hud_def_type_field] = "text",
position = pos,
text = text,
alignment = {x=1,y=1},
number = text_color,
direction = 0,
offset = { x = offset.x + 2, y = offset.y - 1},
z_index = 2,
})
end
-- Do not forget to update hb.get_hudbar_state if you add new fields to the state table
state.hidden = start_hidden
state.value = start_value
state.max = start_max
state.text = text
state.barlength = hb.value_to_barlength(start_value, start_max)
local main_error_text =
"[hudbars] Bad initial values of HUD bar identifier “"..tostring(identifier).."” for player "..name..". "
if start_max < start_value then
minetest.log("error", main_error_text.."start_max ("..start_max..") is smaller than start_value ("..start_value..")!")
end
if start_max < 0 then
minetest.log("error", main_error_text.."start_max ("..start_max..") is smaller than 0!")
end
if start_value < 0 then
minetest.log("error", main_error_text.."start_value ("..start_value..") is smaller than 0!")
end
hb.hudtables[identifier].hudids[name] = ids
hb.hudtables[identifier].hudstate[name] = state
end
hudtable.identifier = identifier
hudtable.format_string = format_string
hudtable.format_string_config = format_string_config
hudtable.label = label
hudtable.hudids = {}
hudtable.hudstate = {}
hudtable.default_start_hidden = default_start_hidden
hudtable.default_start_value = default_start_value
hudtable.default_start_max = default_start_max
hb.hudbars_count= hb.hudbars_count + 1
hb.hudtables[identifier] = hudtable
end
function hb.init_hudbar(player, identifier, start_value, start_max, start_hidden)
if not player_exists(player) then return false end
local hudtable = hb.get_hudtable(identifier)
hb.hudtables[identifier].add_all(player, hudtable, start_value, start_max, start_hidden)
return true
end
function hb.change_hudbar(player, identifier, new_value, new_max_value, new_icon, new_bgicon, new_bar, new_label, new_text_color)
if new_value == nil and new_max_value == nil and new_icon == nil and new_bgicon == nil and new_bar == nil and new_label == nil and new_text_color == nil then
return true
end
if not player_exists(player) then
return false
end
local name = player:get_player_name()
local hudtable = hb.get_hudtable(identifier)
if not hudtable.hudstate[name] then
return false
end
local value_changed, max_changed = false, false
if new_value ~= nil then
if new_value ~= hudtable.hudstate[name].value then
hudtable.hudstate[name].value = new_value
value_changed = true
end
else
new_value = hudtable.hudstate[name].value
end
if new_max_value ~= nil then
if new_max_value ~= hudtable.hudstate[name].max then
hudtable.hudstate[name].max = new_max_value
max_changed = true
end
else
new_max_value = hudtable.hudstate[name].max
end
if hb.settings.bar_type == "progress_bar" then
if new_icon ~= nil and hudtable.hudids[name].icon ~= nil then
player:hud_change(hudtable.hudids[name].icon, "text", new_icon)
end
if new_bgicon ~= nil and hudtable.hudids[name].bgicon ~= nil then
player:hud_change(hudtable.hudids[name].bgicon, "text", new_bgicon)
end
if new_bar ~= nil then
player:hud_change(hudtable.hudids[name].bar , "text", new_bar)
end
if new_label ~= nil then
hudtable.label = new_label
local new_text = make_label(hudtable.format_string, hudtable.format_string_config, new_label, hudtable.hudstate[name].value, hudtable.hudstate[name].max)
player:hud_change(hudtable.hudids[name].text, "text", new_text)
end
if new_text_color ~= nil then
player:hud_change(hudtable.hudids[name].text, "number", new_text_color)
end
else
if new_icon ~= nil and hudtable.hudids[name].bar ~= nil then
player:hud_change(hudtable.hudids[name].bar, "text", new_icon)
end
if new_bgicon ~= nil and hudtable.hudids[name].bg ~= nil then
player:hud_change(hudtable.hudids[name].bg, "text", new_bgicon)
end
end
local main_error_text =
"[hudbars] Bad call to hb.change_hudbar, identifier: “"..tostring(identifier).."”, player name: “"..name.."”. "
if new_max_value < new_value then
minetest.log("error", main_error_text.."new_max_value ("..new_max_value..") is smaller than new_value ("..new_value..")!")
end
if new_max_value < 0 then
minetest.log("error", main_error_text.."new_max_value ("..new_max_value..") is smaller than 0!")
end
if new_value < 0 then
minetest.log("error", main_error_text.."new_value ("..new_value..") is smaller than 0!")
end
if hudtable.hudstate[name].hidden == false then
if max_changed and hb.settings.bar_type == "progress_bar" then
if hudtable.hudstate[name].max == 0 then
player:hud_change(hudtable.hudids[name].bg, "scale", {x=0,y=0})
else
player:hud_change(hudtable.hudids[name].bg, "scale", {x=1,y=1})
end
end
if value_changed or max_changed then
local new_barlength = hb.value_to_barlength(new_value, new_max_value)
if new_barlength ~= hudtable.hudstate[name].barlength then
player:hud_change(hudtable.hudids[name].bar, "number", hb.value_to_barlength(new_value, new_max_value))
hudtable.hudstate[name].barlength = new_barlength
end
if hb.settings.bar_type == "progress_bar" then
local new_text = make_label(hudtable.format_string, hudtable.format_string_config, hudtable.label, new_value, new_max_value)
if new_text ~= hudtable.hudstate[name].text then
player:hud_change(hudtable.hudids[name].text, "text", new_text)
hudtable.hudstate[name].text = new_text
end
end
end
end
return true
end
function hb.hide_hudbar(player, identifier)
if not player_exists(player) then return false end
local name = player:get_player_name()
local hudtable = hb.get_hudtable(identifier)
if hudtable == nil then return false end
if hudtable.hudstate[name].hidden == true then return true end
if hb.settings.bar_type == "progress_bar" then
if hudtable.hudids[name].icon ~= nil then
player:hud_change(hudtable.hudids[name].icon, "scale", {x=0,y=0})
end
player:hud_change(hudtable.hudids[name].bg, "scale", {x=0,y=0})
player:hud_change(hudtable.hudids[name].text, "text", "")
end
player:hud_change(hudtable.hudids[name].bar, "number", 0)
player:hud_change(hudtable.hudids[name].bar, "item", 0)
hudtable.hudstate[name].hidden = true
return true
end
function hb.unhide_hudbar(player, identifier)
if not player_exists(player) then return false end
local name = player:get_player_name()
local hudtable = hb.get_hudtable(identifier)
if hudtable == nil then return false end
if hudtable.hudstate[name].hidden == false then return true end
local value = hudtable.hudstate[name].value
local max = hudtable.hudstate[name].max
if hb.settings.bar_type == "progress_bar" then
if hudtable.hudids[name].icon ~= nil then
player:hud_change(hudtable.hudids[name].icon, "scale", {x=1,y=1})
end
if hudtable.hudstate[name].max ~= 0 then
player:hud_change(hudtable.hudids[name].bg, "scale", {x=1,y=1})
end
player:hud_change(hudtable.hudids[name].text, "text", make_label(hudtable.format_string, hudtable.format_string_config, hudtable.label, value, max))
elseif hb.settings.bar_type == "statbar_modern" then
player:hud_change(hudtable.hudids[name].bar, "scale", {x=1,y=1})
end
player:hud_change(hudtable.hudids[name].bar, "number", hb.value_to_barlength(value, max))
player:hud_change(hudtable.hudids[name].bar, "item", hb.value_to_barlength(max, max))
hudtable.hudstate[name].hidden = false
return true
end
function hb.get_hudbar_state(player, identifier)
if not player_exists(player) then return nil end
local ref = hb.get_hudtable(identifier).hudstate[player:get_player_name()]
if not ref then return nil end
-- Do not forget to update this chunk of code in case the state changes
local copy = {
hidden = ref.hidden,
value = ref.value,
max = ref.max,
text = ref.text,
barlength = ref.barlength,
}
return copy
end
function hb.get_hudbar_identifiers()
local ids = {}
for id, _ in pairs(hb.hudtables) do
table.insert(ids, id)
end
return ids
end
--register built-in HUD bars
if minetest.settings:get_bool("enable_damage") or hb.settings.forceload_default_hudbars then
hb.register_hudbar("health", 0xFFFFFF, S("Health"), { bar = "hudbars_bar_health.png", icon = "hudbars_icon_health.png", bgicon = "hudbars_bgicon_health.png" }, 20, 20, false)
hb.register_hudbar("breath", 0xFFFFFF, S("Breath"), { bar = "hudbars_bar_breath.png", icon = "hudbars_icon_breath.png", bgicon = "hudbars_bgicon_breath.png" }, 10, 10, true)
end
local function hide_builtin(player)
local flags = player:hud_get_flags()
flags.healthbar = false
flags.breathbar = false
player:hud_set_flags(flags)
end
local function custom_hud(player)
if minetest.settings:get_bool("enable_damage") or hb.settings.forceload_default_hudbars then
local hide
if minetest.settings:get_bool("enable_damage") then
hide = false
else
hide = true
end
local hp = player:get_hp()
local hp_max = player:get_properties().hp_max
hb.init_hudbar(player, "health", math.min(hp, hp_max), hp_max, hide)
local breath = player:get_breath()
local breath_max = player:get_properties().breath_max
local hide_breath
if breath >= breath_max and hb.settings.autohide_breath == true then hide_breath = true else hide_breath = false end
hb.init_hudbar(player, "breath", math.min(breath, breath_max), breath_max, hide_breath or hide)
end
end
local function update_health(player)
local hp_max = player:get_properties().hp_max
local hp = math.min(player:get_hp(), hp_max)
hb.change_hudbar(player, "health", hp, hp_max)
end
-- update built-in HUD bars
local function update_hud(player)
if not player_exists(player) then return end
if minetest.settings:get_bool("enable_damage") then
if hb.settings.forceload_default_hudbars then
hb.unhide_hudbar(player, "health")
end
--air
local breath_max = player:get_properties().breath_max
local breath = player:get_breath()
if breath >= breath_max and hb.settings.autohide_breath == true then
hb.hide_hudbar(player, "breath")
else
hb.unhide_hudbar(player, "breath")
hb.change_hudbar(player, "breath", math.min(breath, breath_max), breath_max)
end
--health
update_health(player)
elseif hb.settings.forceload_default_hudbars then
hb.hide_hudbar(player, "health")
hb.hide_hudbar(player, "breath")
end
end
minetest.register_on_player_hpchange(function(player)
if hb.players[player:get_player_name()] ~= nil then
update_health(player)
end
end)
minetest.register_on_respawnplayer(function(player)
update_health(player)
hb.hide_hudbar(player, "breath")
end)
minetest.register_on_joinplayer(function(player)
hide_builtin(player)
custom_hud(player)
hb.players[player:get_player_name()] = player
end)
minetest.register_on_leaveplayer(function(player)
hb.players[player:get_player_name()] = nil
end)
local main_timer = 0
local timer = 0
minetest.register_globalstep(function(dtime)
main_timer = main_timer + dtime
timer = timer + dtime
if main_timer > hb.settings.tick or timer > 4 then
if main_timer > hb.settings.tick then main_timer = 0 end
-- only proceed if damage is enabled
if minetest.settings:get_bool("enable_damage") or hb.settings.forceload_default_hudbars then
for _, player in pairs(hb.players) do
-- update all hud elements
update_hud(player)
end
end
end
if timer > 4 then timer = 0 end
end)

View file

@ -0,0 +1,4 @@
# textdomain: hudbars
Health=Leben
Breath=Atem
@1: @2/@3=@1: @2/@3

View file

@ -0,0 +1,4 @@
# textdomain: hudbars
Health=Salud
Breath=Aliento
@1: @2/@3=@1: @2/@3

View file

@ -0,0 +1,4 @@
# textdomain: hudbars
Health=Santé
Breath=Respiration
@1: @2/@3=@1 : @2/@3

View file

@ -0,0 +1,6 @@
# textdomain: hudbars
Health=Salute
Breath=Ossigeno
# Default format string for progress bar-style HUD bars, e.g. “Health 5/20”
@1: @2/@3=@1: @2/@3

View file

@ -0,0 +1,4 @@
# textdomain: hudbars
Health=Kesihatan
Breath=Nafas
@1: @2/@3=@1: @2/@3

View file

@ -0,0 +1,6 @@
# textdomain: hudbars
Health=Gezondheid
Breath=Adem
# Default format string for progress bar-style HUD bars, e.g. “Health 5/20”
@1: @2/@3=@1: @2/@3

View file

@ -0,0 +1,6 @@
# textdomain: hudbars
Health=Saude
Breath=Folego
# Formato de string padrão para progresso bar-style de barras do HUD, por exemplo “Saude 5/20”
@1: @2/@3=@1: @2/@3

View file

@ -0,0 +1,4 @@
# textdomain: hudbars
Health=HP
Breath=дыхание
@1: @2/@3=@1: @2/@3

View file

@ -0,0 +1,4 @@
# textdomain: hudbars
Health=Can
Breath=Nefes
@1: @2/@3=@1: @2/@3

View file

@ -0,0 +1,6 @@
# textdomain: hudbars
Health=
Breath=
# Default format string for progress bar-style HUD bars, e.g. “Health: 5/20”
@1: @2/@3=

5
hudbars/mod.conf Normal file
View file

@ -0,0 +1,5 @@
name = hudbars
title = HUD Bars
description = Replaces the health and breath symbols in the HUD by “progress bars” and shows exact values. Other mods can add more progress bars for custom player stats.
release = 27446
author = Wuzzy

BIN
hudbars/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

122
hudbars/settingtypes.txt Normal file
View file

@ -0,0 +1,122 @@
[Appearance]
# Specifies how the value indicators (i.e. health, breah, etc.) look. There are 3 styles
# available. You can choose between the default progress-bar-like bars and the good
# old statbars like you know from vanilla Minetest.
# These values are possible:
# - progress_bar: A horizontal progress-bar-like bar with a label, showing numerical value
# (current, maximum), and an icon. These bars usually convey the most
# information. This is the default and recommended value.
# - statbar_classic: Classic statbar, like in vanilla Minetest. Made out of up to 20
# half-symbols. Those bars represent the vague ratio between
# the current value and the maximum value. 1 half-symbol stands for
# approximately 5% of the maximum value.
# - statbar_modern: Like the classic statbar, but also supports background images, this
# kind of statbar may be considered to be more user-friendly than the
# classic statbar. This bar type closely resembles the mod
# “Better HUD” [hud] by BlockMen.
hudbars_bar_type (HUD bars style) enum progress_bar progress_bar,statbar_classic,statbar_modern
# If enabled (default), the breath indicators in the HUD will be automatically hidden shortly
# after the breath has been filled up. Otherwise, the breath will always be displayed.
hudbars_autohide_breath (Automatically hide breath indicators) bool true
# This setting changes the way the HUD bars are ordered on the display. You can choose
# between a zig-zag pattern (default) or a vertically stacked pattern.
# The following values are allowed:
# - zigzag: Starting from the left bottom, the next is right from the first,
# the next is above the first, the next is right of the third, etc.
# - stack_up: The HUD bars are stacked vertically, going upwards.
# - stack_down: The HUD bars are stacked vertically, going downwards.
hudbars_alignment_pattern (HUD bars alignment pattern) enum zigzag zigzag,stack_up,stack_down
# This setting allows you to specify the order of the HUD bars explicitly. If left empty
# (the default), the health and breath indicators come first, additional indicators
# may appear in any order. This setting is quite technical and normal users probably do not
# need to worry about it.
#
# Syntax:
# The setting has to be specified as a comma-seperated list of key=value pairs, where a key
# refers to the identifier of a HUD bar and the value refers to the slot number of where the
# HUD bar should be placed. The slot number must be an integer greater of equal to 0. Where
# the HUD bars will be displayed exactly depends on the alignment pattern being used.
# All HUD bars to which no order value has been applied will fill in all slots which have
# not been occupied by the HUD bars specified in this setting, the slots will be filled in
# from the lowest slot number.
# Note that the order of those remaining HUD bars is not fixed, it basically just boils
# down on which mod “came” first. Don't worry, the mod will still work perfectly fine, this
# setting is entirely optional.
# The identifier for the health bar is “health” and the identifier for the breath bar is
# “breath”. For other HUD bars, you have to learn it from the mod which is supplying them.
#
# Be careful not to use slot indices twice, or else different HUD bars will be drawn over
# each other!
#
# Example: “breath=0, health=1”
# This makes the breath bar first and the health bar second, which is the opposite order
# of the default one.
hudbars_sorting (HUD bars order) string
# If enabled, hide the labels over the bars
hudbars_hide_labels (Hide bar labels) bool false
[Positions and offsets]
# Horizontal (x) main position of the HUD bars over the entire screen.
# 0.0 is left-most, 1.0 is right-most.
# For the zig-zag alignment pattern, this is for the left HUD bars.
hudbars_pos_left_x (Left HUD bar screen x position) float 0.5 0.0 1.0
# Vertical (y) main position of the HUD bars over the entire screen.
# 0.0 is top, 1.0 is bottom.
# For the zig-zag alignment pattern, this is for the left HUD bars.
hudbars_pos_left_y (Left HUD bar screen y position) float 1.0 0.0 1.0
# Horizontal (x) main position of the right HUD bars over the entire screen.
# 0.0 is left-most, 1.0 is right-most.
# Only used for the zig-zag alignment pattern.
hudbars_pos_right_x (Right HUD bar screen x position) float 0.5 0.0 1.0
# Vertical main position (y) of the right HUD bars over the entire screen.
# 0.0 is top, 1.0 is bottom.
# Only used for the zig-zag alignment pattern.
hudbars_pos_right_y (Right HUD bar screen y position) float 1.0 0.0 1.0
# Precise x offset in pixels from the basic screen x position of the HUD bars.
# For the zig-zag alignment pattern, this is for the left HUD bars.
# This setting is used for the progress bar HUD bar style.
hudbars_start_offset_left_x (Left HUD bar x offset) int -175
# Precise y offset in pixels from the basic screen y position of the HUD bars.
# For the zig-zag alignment pattern, this is for the left HUD bars.
# This setting is used for the progress bar HUD bar style.
hudbars_start_offset_left_y (Left HUD bar y offset) int -86
# Precise x offset in pixels from the basic screen x position of the right HUD bars.
# Only used for the zig-zag alignment pattern.
# This setting is used for the progress bar HUD bar style.
hudbars_start_offset_right_x (Right HUD bar x offset) int 15
# Precise y offset in pixels from the basic screen y position of the right HUD bars.
# Only used for the zig-zag alignment pattern.
# This setting is used for the progress bar HUD bar style.
hudbars_start_offset_right_y (Right HUD bar y offset) int -86
# Precise x offset in pixels from the basic screen x position of the HUD statbars.
# For the zig-zag alignment pattern, this is for the left HUD statbars.
# This setting is used for the classic and modern statbar styles.
hudbars_start_statbar_offset_left_x (Left HUD statbar x offset) int -265
# Precise y offset in pixels from the basic screen y position of the HUD statbars.
# For the zig-zag alignment pattern, this is for the left HUD statbars.
# This setting is used for the classic and modern statbar styles.
hudbars_start_statbar_offset_left_y (Left HUD statbar y offset) int -90
# Precise x offset in pixels from the basic screen x position of the right HUD statbars.
# Only used for the zig-zag alignment pattern.
# This setting is used for the classic and modern statbar styles.
hudbars_start_statbar_offset_right_x (Right HUD statbar x offset) int 25
# Precise y offset in pixels from the basic screen y position of the right HUD statbars.
# Only used for the zig-zag alignment pattern.
# This setting is used for the classic and modern statbar styles.
hudbars_start_statbar_offset_right_y (Right HUD statbar y offset) int -90
# The vertical distance between two HUD bars, in pixels.
hudbars_vmargin (Vertical distance between HUD bars) int 24 0
[Performance]
# The of seconds which need to pass before the server updates the default HUD bars
# (health and breath). Increase this number if you have a slow server or a slow network
# connection and experience performance problems.
hudbars_tick (Default HUD bars update interval) float 0.1 0.0 4.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 811 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 818 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

505
thirsty/LICENSE Normal file
View file

@ -0,0 +1,505 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
(This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.)
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
{description}
Copyright (C) {year} {fullname}
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random
Hacker.
{signature of Ty Coon}, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

349
thirsty/README.md Normal file
View file

@ -0,0 +1,349 @@
# Thirsty [thirsty]
A Minetest mod that adds a "thirst" mechanic.
Version: 0.10.2
## *License*
**Code**
LGPL 2.1 (see included LICENSE file)
**Textures**
vessels_glass_bottle_full_cc_by_sa_3.png
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
modified from vessels_glass_bottle.png
Copyright (C) 2012-2016 Vanessa Ezekowitz
Copyright (C) 2016 Thomas-S
thirsty_drop_100_24_cc0.png +.xcf
thirsty_drop_100_16_cc0.png
thirsty_wooden_bowl_cc0.png +.xcf
thirsty_bronze_canteen_cc0.png +.xcf
thirsty_steel_canteen_cc0.png
thirsty_amulet_moisture_cc0.png +.xcf
thirsty_amulet_hydration_cc0.png +.xcf
Public Domain CC0 1.0 Universal
Sirrobzeroone
All other Images CC BY-SA 4.0
(see http://creativecommons.org/licenses/by-sa/4.0/)
**Sounds**
thirsty_breviceps_drink-drinking-liquid.ogg
https://freesound.org/people/Breviceps/sounds/445970/
Public Domain CC0 1.0 Universal
Report bugs or request help on the forum topic.
# Description
This is a mod for MineTest. It adds a thirst mechanic to the
game, similar to many hunger mods (but independent of them).
Players will slowly get thirstier over time, and will need to
drink or suffer damage.
The point of this mod is not to make the game more realistic,
or harder. The point is to have another mechanic that rewards
preparation and infrastructure. Players will now have an incentive
to build their base next to water (or add some water to their base),
and/or take some water with them when mining or travelling.
# Terminology: "Thirst" vs. "hydration"
"Thirst" is the absence of "hydration" (a term suggested by
everamzah on the Minetest forums, thanks!). The overall mechanic
is still called "thirst", but the visible bar is that of
"hydration", meaning a full bar represents full hydration, not full
thirst. Players lose hydration (or "hydro points") over time, and
gain hydration when drinking.
# Current behavior
## *Tier 0*
stand in water (running or standing) to slowly drink.
You may not move during drinking (or you could cross an ocean without
getting thirsty).
To register additional drinkable nodes use the function:
**thirsty.register_hydrate_node(node_name,also_drinkable_with_cup,regen_rate_per_second)**
**"node_name"** - registered node name
**"also_drinkable_with_cup"** - optional will default to true, if true
registers as per thirsty.register_drinkable_node() with max_hydration
equal to thirsty.config.start (default 20)
**"regen_rate_per_second"** - optional will default to 0.5 hydration
points per second standing still in the liquid.
**Example**
thirsty.register_hydrate_node("default:water_source")
## *Tier 1*
Use a container (e.g. from `vessels`) on water to instantly
fill your hydration. Craftable wooden bowl included.
**NODES**
Configure nodes that can be drunk from using a cup/glass etc assuming this was
not done as part of Tier 0 or if you wish to override max_hydration to be more
than the default value (normally 20):
**thirsty.register_drinkable_node(node_name,max_hydration)**
**"item_name"** registered node name
**"max_hydration"** optional will default to thirsty.config.start (default 20)
max hydration can be set above 20 to encourage use of drinking fountains or
hydration/drinking infrastructure.
**Example**
thirsty.register_drinkable_node("thirsty:drinking_fountain",30)
**ITEMS**
Configure cups/glasses/bowls etc that can be used to scoop up water and then
drink from:
**thirsty.augment_item_for_drinking(item_name, max_hydration)**
**"item_name"** registered item name
**"max_hydration"** optional will default to thirsty.config.start (default 20)
max hydration can be set above 20 to encourage use of items to drink with.
This will overide/replace any existing code the item may have in it's
item_name.on_use. So not recommended for items with custom on_use
code already.
**Example**
thirsty.augment_item_for_drinking('vessels:drinking_glass', 20)
**Integrate thirsty into item custom on_use code**
thirsty.on_use()
**Example**
minetest.register_craftitem("mod_name:empty_cup", {
description = S("Empty Cup"),
inventory_image = "mod_name_empty_cup.png",
liquids_pointable = true,
on_use = function(itemstack,player,pointed_thing)
local pos = pointed_thing.under
local node_name
if pointed_thing.type == "node" then
local node = minetest.get_node(pos)
node_name = node.name
end
if thirsty.config.node_drinkable[node_name] then
thirsty.on_use()
else
-- do something else
end
end,
})*
## *Tier 2*
Pre-made drinks and craftable canteens
**PREMADE DRINKS**
Pre-made drinks can include anything the player may have had to craft
or cook and you wish the player to restore some hydration on_use:
**thirsty.drink(player, amount, max_hydration, empty_vessel)**
**"player"** player object see minetest player object
**"amount"** number of hydration points to restore
**"max hydration"** - optional will default to thirsty.config.start (default 20)
max hydration can be set above 20 to encourage use of items to drink with.
**"empty_vessel"** - optional empty vessel or item to return to player.
**Example**
minetest.register_craftitem("mod_name:cup_of_soup", {
description = S("Cup of Soup"),
inventory_image = "mod_name_cup_of_soup.png",
on_use = function(itemstack,player,pointed_thing)
thirsty.drink(player, 2, 20, "mod_name:empty_cup")
itemstack:take_item()
return itemstack
end,
})
**CANTEENS, FLASKS or BOTTLES**
Craftable items that you may wish to configure to hold a certain amount of
liquid hydration points. If used these items are converted to registered tools
rather than straight regsitered items with stack maximum of 1 so that current
full/empty value is displayed to the player (using wear). Thirsty includes a
Steel canteen with 40 hydration point capacity and a Bronze canteen with 60
hydration point capacity. These can be refilled by clicking on any thirsty
registered hydrate_node.
**thirsty.register_canteen(item_name,hydrate_capacity,max_hydration,on_use)**
**"item_name"** Registered item name to convert to canteen type container
**"hydrate_capacity"** How many hydration points the container holds 1 full bar = 20
**"max hydration"** Optional will default to thirsty.config.start (default 20)
max hydration can be set above 20 to encourage use of items to drink with.
**"on_use"** Optional default is true. Will set item.on_use function to; thirsty.on_use(), however if set to false on_use wont be over written. Mod registering item will need to manually include "thirsty.on_use()" inside its on_use item definition or canteen will not work note see Tier 1 - thirsty.on_use()
**Example**
thirsty.register_canteen("thirsty:bronze_canteen",60,25)
**COMPLEX CANTEENS, FLASKS or BOTTLES**
Using the above will mean items can no longer be stacked most importantly when they are empty. The below function will overcome this as it will register a full version
of the empty vessel as a tool. Naturally if you do not wish or need the empty containers to stack just use thirsty.register_canteen. Once a container is empty it will be replaced with the empty version.
**thirsty.register_canteen_complex(item/node_name,hydrate_capacity,max_hydration,full_image)**
**"item_name" or "node_name"** Registered item name to convert to canteen type tool container
**"hydrate_capacity"** How many hydration points the container holds 1 full bar = 20
**"max hydration"** Optional will default to thirsty.config.start (default 20)
max hydration can be set above 20 to encourage use of items to drink with.
**"full_image"** The full image of the empty item used for inventory image and wield image
**Example**
thirsty.register_canteen_complex("vessels:glass_bottle",10,22,"vessels_glass_bottle_full.png")
## *Tier 3*
Placeable drinking fountain / wash basin node: instantly
fills your hydration when used.
Add the below to the on_rightclick function inside your node definition,
you'll also need to register the node as a drinkable node so you'll need
to also run - thirsty.register_drinkable_node(node_name). Recommended that
the node.drop for your node dosen't equal itself otherwise players will simply
use these as endless canteens/bottles.
**thirsty.on_rightclick()**
minetest.register_node('thirsty:drinking_fountain', {
description = 'Drinking fountain',
....
def info
....
drop = "default:stone 4",
on_rightclick = thirsty.on_rightclick(),
})
minetest.register_craft({
output = "thirsty:drinking_fountain",
recipe = {
{ "default:stone", "bucket:bucket_water", "default:stone"},
{ "" , "default:stone" , ""},
{ "" , "default:stone" , ""}
},
replacements = {
{"bucket:bucket_water", "bucket:bucket_empty"}
}
})
thirsty.register_drinkable_node("thirsty:drinking_fountain",30)
## *Tier 4*
Placeable fountain node(s) to fill the hydration of all
players within range. Placing more nodes increases the range.
**thirsty.register_water_fountain(node_name)**
**Example**
thirsty.register_water_fountain("thirsty:water_fountain")
**HOW TO USE WATER FOUNTAINS** *(Taken from forum posts)*
Water fountains are placeable, but these are not usable. Instead,
they constantly fill the hydration of all players within a 5 node
radius, as if they were standing in water. Water fountains need
actual water (source or flowing) near them to work.
You can extend the radius of water fountains with "water extenders",
placeable nodes without any function of their own.
Specifically, a water fountain will check all the nodes in a
5-node-high pyramid starting one node above itself. It will count all
water nodes (source or flowing), and count all water fountains /
water extenders. The smaller of these numbers is the "level" of the fountain,
up to 20 (in other words, you need an equal amount of water and fountain blocks).
Each level adds 5 more nodes to the working radius. A large fountain
should cover a city block or two.
I'd recommend placing one water source above the "fountain" node, and
arranging extenders under it, but the plan is to allow many working designs.
## *Tier 5*
Craftable trinkets/gadgets/amulets that constantly keep your
hydration filled when in your inventory, solving your thirst problem
once and for all.
**thirsty.register_amulet_extractor(item_name,value)**
**"item_name"** Registered item name
**"value"** Number of Hydration points extracted per half second (thirsty.config.tick_time)
*Note: Container must be avaliable in Inventory with avaliable space to add hydration points to.*
**Example**
thirsty.register_amulet_extractor("thirsty:amulet_of_moisture", 0.6)
**Amulet of Moisture** - Absorbs moisture from the surronding environment places it into a canteen or other water holding item. Must be held in Inventory.
**thirsty.register_amulet_supplier(item_name,value)**
**"item_name"** Registered item name
**"value"** Number of Hydration points supplied to player per half second.(thirsty.config.tick_time)
*Note: Container must be avaliable in Inventory with avaliable space to add hydration points to.*
**Example**
thirsty.register_amulet_supplier("thirsty:amulet_of_hydration", 0.5)
**Amulet of Hydration** - Feeds water from a Canteen or other water holding
item directly into the player to keep them always hydrated. Must be held in Inventory.
The above two Amulets can be used in combination with each other plus a
canteen. However this does permenantly fill 3 inventory slots the delibrate
downside to offset the significant bonus.
**Amulets of Thirst** - Three versions lesser,normal and greater each will slower the rate at which
a player becomes thirsty. Normal thirst factor is 1, however a "cursed" version could be created
which makes a player become thirsty faster.
thirsty.register_amulet_thirst(item_name, thirst_factor)
**"item_name"** Registered item name
**"thirst_factor"** Float value that represents the speed at which a player uses hydration points
**Example**
minetest.register_craftitem("thirsty:greater_amulet_thirst", {
description = "Greater Amulet of Thirst",
inventory_image = "thirsty_amulet_of_thirst_greater_cc0.png",
})
thirsty.register_amulet_thirst("thirsty:lesser_amulet_thirst",0.85)
*Note: Included Amulets of Thirst have no craft recipes and are only avaliable as
*dungeon loot with more powerful versions only found in deeper dungeons.
## *Additional Functions*
*thirsty.get_hydro(player) : returns the current hydration of a player*
"player" refers to a player object, i.e. with a get_player_name() method.
Future plans
------------
Continued tidy and updating
Dependencies
------------
* default (optional but needed for included components)
* bucket (optional but needed for some included components)
* hudbars (optional): https://forum.minetest.net/viewtopic.php?f=11&t=11153
* vessels (optional): https://forum.minetest.net/viewtopic.php?id=2574

324
thirsty/components.lua Normal file
View file

@ -0,0 +1,324 @@
------------------------------------------------------------
-- _____ _ _ _ --
-- |_ _| |_ (_)_ _ __| |_ _ _ --
-- | | | ' \| | '_(_-< _| || | --
-- |_| |_||_|_|_| /__/\__|\_, | --
-- |__/ --
------------------------------------------------------------
-- Thirsty mod [components] --
------------------------------------------------------------
-- See init.lua for license --
------------------------------------------------------------
local E = thirsty.ext_nodes_items
--------------------------
-- Tier 0 Hydrate Nodes --
--------------------------
if minetest.registered_items[E.water_source] then
thirsty.register_hydrate_node(E.water_source)
end
if minetest.registered_items[E.water_source_f] then
thirsty.register_hydrate_node(E.water_source_f)
end
if minetest.registered_items[E.water_source_riv] then
thirsty.register_hydrate_node(E.water_source_riv)
end
if minetest.registered_items[E.water_source_riv_f] then
thirsty.register_hydrate_node(E.water_source_riv_f)
end
-------------------------------------------
-- Tier 1 Drink from nodes using cup etc --
-------------------------------------------
-- Nodes --
-- see drinking fountain
-- Items --
if minetest.registered_items[E.drinking_glass] and thirsty.config.register_vessels then
-- add "drinking" to vessels
thirsty.augment_item_for_drinking(E.drinking_glass, 20)
end
if thirsty.config.register_bowl and not minetest.registered_items[E.wood_bowl] then
-- our own simple wooden bowl
minetest.register_craftitem('thirsty:wooden_bowl', {
description = "Wooden bowl",
inventory_image = "thirsty_bowl_cc0.png",
liquids_pointable = true,
})
minetest.register_craft({
output = "thirsty:wooden_bowl",
recipe = {
{E.group_wood, "", E.group_wood},
{ "",E.group_wood, ""}
}
})
thirsty.augment_item_for_drinking("thirsty:wooden_bowl", 22)
-- modify farming redo wooden bowl to be usable.
elseif thirsty.config.register_bowl and minetest.registered_items[E.wood_bowl] then
thirsty.augment_item_for_drinking(E.wood_bowl, 22)
end
--[[
Tier 2 Hydro Containers
Defines canteens (currently two types, with different capacities),
tools which store hydro. They use wear to show their content
level in their durability bar; they do not disappear when used up.
Wear corresponds to hydro level as follows:
- a wear of 0 shows no durability bar -> empty (initial state)
- a wear of 1 shows a full durability bar -> full
- a wear of 65535 shows an empty durability bar -> empty
]]
if thirsty.config.register_vessels and minetest.registered_items[E.glass_bottle] then
thirsty.register_canteen_complex(E.glass_bottle,10,22,E.glass_bottle_f)
end
if thirsty.config.register_vessels and minetest.registered_items[E.steel_bottle] then
thirsty.register_canteen_complex(E.steel_bottle,20,24)
end
if thirsty.config.register_canteens and
minetest.registered_items[E.steel_ingot] and
minetest.registered_items[E.bronze_ingot] then
minetest.register_craftitem('thirsty:steel_canteen', {
description = 'Steel canteen',
inventory_image = "thirsty_steel_canteen_cc0.png",
})
minetest.register_craftitem("thirsty:bronze_canteen", {
description = "Bronze canteen",
inventory_image = "thirsty_bronze_canteen_cc0.png",
})
thirsty.register_canteen("thirsty:steel_canteen",40,25)
thirsty.register_canteen("thirsty:bronze_canteen",60,25)
minetest.register_craft({
output = "thirsty:steel_canteen",
recipe = {
{E.group_wood, ""},
{E.steel_ingot,E.steel_ingot},
{E.steel_ingot,E.steel_ingot}
}
})
minetest.register_craft({
output = "thirsty:bronze_canteen",
recipe = {
{E.group_wood, ""},
{E.bronze_ingot,E.bronze_ingot},
{E.bronze_ingot,E.bronze_ingot}
}
})
end
-------------------------------
-- Tier 3 Drinking Fountain --
-------------------------------
if thirsty.config.register_drinking_fountain and
minetest.registered_items[E.stone] and
minetest.registered_items[E.bucket_water]then
minetest.register_node('thirsty:drinking_fountain', {
description = 'Drinking fountain',
drawtype = 'nodebox',
drop = E.stone.." 4",
tiles = {
-- top, bottom, right, left, front, back
'thirsty_drinkfount_top.png',
'thirsty_drinkfount_bottom.png',
'thirsty_drinkfount_side.png',
'thirsty_drinkfount_side.png',
'thirsty_drinkfount_side.png',
'thirsty_drinkfount_side.png',
},
paramtype = 'light',
groups = { cracky = 2 },
node_box = {
type = "fixed",
fixed = {
{ -3/16, -8/16, -3/16, 3/16, 3/16, 3/16 },
{ -8/16, 3/16, -8/16, 8/16, 6/16, 8/16 },
{ -8/16, 6/16, -8/16, 8/16, 8/16, -6/16 },
{ -8/16, 6/16, 6/16, 8/16, 8/16, 8/16 },
{ -8/16, 6/16, -6/16, -6/16, 8/16, 6/16 },
{ 6/16, 6/16, -6/16, 8/16, 8/16, 6/16 },
},
},
selection_box = {
type = "regular",
},
collision_box = {
type = "regular",
},
on_rightclick = thirsty.on_rightclick(nil),
})
minetest.register_craft({
output = "thirsty:drinking_fountain",
recipe = {
{E.stone,E.bucket_water,E.stone},
{ "" ,E.stone , ""},
{ "" ,E.stone , ""}
},
replacements = {
{E.bucket_water,E.bucket_empty}
}
})
thirsty.register_drinkable_node("thirsty:drinking_fountain",30)
end
----------------------------------------------
-- Tier 4: Water fountains, Water extenders --
----------------------------------------------
if thirsty.config.register_fountains and
minetest.registered_items[E.copper_ingot] and
minetest.registered_items[E.mese_crystal] and
minetest.registered_items[E.bucket_water] then
minetest.register_node('thirsty:water_fountain', {
description = 'Water fountain',
tiles = {
-- top, bottom, right, left, front, back
'thirsty_waterfountain_top.png',
'thirsty_waterfountain_top.png',
'thirsty_waterfountain_side.png',
'thirsty_waterfountain_side.png',
'thirsty_waterfountain_side.png',
'thirsty_waterfountain_side.png',
},
paramtype = 'light',
groups = { cracky = 2 },
})
minetest.register_node('thirsty:water_extender', {
description = 'Water fountain extender',
tiles = {
'thirsty_waterextender_top.png',
'thirsty_waterextender_top.png',
'thirsty_waterextender_side.png',
'thirsty_waterextender_side.png',
'thirsty_waterextender_side.png',
'thirsty_waterextender_side.png',
},
paramtype = 'light',
groups = { cracky = 2 },
})
minetest.register_craft({
output = "thirsty:water_fountain",
recipe = {
{E.copper_ingot,E.bucket_water,E.copper_ingot},
{"" ,E.copper_ingot, ""},
{E.copper_ingot,E.mese_crystal,E.copper_ingot}
}
})
minetest.register_craft({
output = "thirsty:water_extender",
recipe = {
{ "" ,E.bucket_water, ""},
{ "" ,E.copper_ingot, ""},
{E.copper_ingot,E.mese_crystal,E.copper_ingot}
}
})
thirsty.register_water_fountain("thirsty:water_fountain")
thirsty.register_water_fountain("thirsty:water_extender")
minetest.register_abm({
nodenames = {"thirsty:water_fountain"},
interval = 2,
chance = 5,
action = thirsty.fountain_abm,
})
end
--[[
Tier 5
These amulets don't do much; the actual code is above, where
they are searched for in player's inventories
]]
if thirsty.config.register_amulets and
minetest.registered_items[E.diamond] and
minetest.registered_items[E.mese_crystal] and
minetest.registered_items[E.bucket_water] then
minetest.register_craftitem("thirsty:amulet_of_hydration", {
description = "Amulet of Hydration",
inventory_image = "thirsty_amulet_hydration_cc0.png",
})
minetest.register_craft({
output = "thirsty:amulet_of_hydration",
recipe = {
{E.diamond ,E.mese_crystal,E.diamond},
{E.mese_crystal,E.bucket_water,E.mese_crystal},
{E.diamond ,E.mese_crystal,E.diamond}
}
})
thirsty.register_amulet_supplier("thirsty:amulet_of_hydration", 0.5)
minetest.register_craftitem("thirsty:amulet_of_moisture", {
description = "Amulet of Moisture",
inventory_image = "thirsty_amulet_moisture_cc0.png",
})
minetest.register_craft({
output = "thirsty:amulet_of_moisture",
recipe = {
{E.mese_crystal,E.diamond ,E.mese_crystal},
{E.diamond ,E.bucket_water,E.diamond },
{E.mese_crystal,E.diamond ,E.mese_crystal}
}
})
thirsty.register_amulet_extractor("thirsty:amulet_of_moisture", 0.6)
minetest.register_craftitem("thirsty:lesser_amulet_thirst", {
description = "Lesser Amulet of Thirst",
inventory_image = "thirsty_amulet_of_thirst_lesser_cc0.png",
})
minetest.register_craftitem("thirsty:amulet_thirst", {
description = "Amulet of Thirst",
inventory_image = "thirsty_amulet_of_thirst_cc0.png",
})
minetest.register_craftitem("thirsty:greater_amulet_thirst", {
description = "Greater Amulet of Thirst",
inventory_image = "thirsty_amulet_of_thirst_greater_cc0.png",
})
thirsty.register_amulet_thirst("thirsty:lesser_amulet_thirst",0.85)
thirsty.register_amulet_thirst("thirsty:amulet_thirst",0.70)
thirsty.register_amulet_thirst("thirsty:greater_amulet_thirst",0.55)
end

View file

@ -0,0 +1,49 @@
------------------------------------------------------------
-- _____ _ _ _ --
-- |_ _| |_ (_)_ _ __| |_ _ _ --
-- | | | ' \| | '_(_-< _| || | --
-- |_| |_||_|_|_| /__/\__|\_, | --
-- |__/ --
------------------------------------------------------------
-- Thirsty mod external nodes items --
------------------------------------------------------------
-- See init.lua for license --
------------------------------------------------------------
--[[
These are nodes and items required to make canteens and
fountains. Simply change the name here to change the reference
across the whole mod.
]]--
local E = thirsty.ext_nodes_items
-- item and node mod aliases, change these as needed.
-- if item dosen't exist as either Ingredient or Augumented
-- item it wont register.
-- Basic Water, change here or register
-- using thirsty.register_hydrate_node()
-- and leave these unchanged.
E.water_source = "default:water_source"
E.water_source_f = "default:water_flowing"
E.water_source_riv = "default:river_water_source"
E.water_source_riv_f = "default:river_water_flowing"
-- Ingredients
E.group_wood = "group:wood"
E.stone = "default:stone"
E.steel_ingot = "default:steel_ingot"
E.bronze_ingot = "default:bronze_ingot"
E.copper_ingot = "default:copper_ingot"
E.mese_crystal = "default:mese_crystal"
E.diamond = "default:diamond"
E.bucket_water = "bucket:bucket_water"
E.bucket_empty = "bucket:bucket_empty"
-- Augumented Items
E.drinking_glass = "vessels:drinking_glass"
E.glass_bottle = "vessels:glass_bottle" -- looks like glass potion bottle
E.glass_bottle_f = "vessels_glass_bottle_full_cc_by_sa_3.png" -- image for registering full version of above
E.steel_bottle = "vessels:steel_bottle"
E.wood_bowl = "farming:bowl"
E.glass_milk = "mobs:glass_milk" -- note needs E.drinking_glass for empty return item

583
thirsty/functions.lua Normal file
View file

@ -0,0 +1,583 @@
------------------------------------------------------------
-- _____ _ _ _ --
-- |_ _| |_ (_)_ _ __| |_ _ _ --
-- | | | ' \| | '_(_-< _| || | --
-- |_| |_||_|_|_| /__/\__|\_, | --
-- |__/ --
------------------------------------------------------------
-- Thirsty mod [functions] --
------------------------------------------------------------
-- See init.lua for license --
------------------------------------------------------------
--------------------------
-- Tier 0 API Functions --
--------------------------
-- regen_from_node is a table defining, for each node type, the
-- amount of hydro per second a player drinks by standing in it.
-- Default is 0.5 of a hydration per second
function thirsty.register_hydrate_node(node_name,drink_cup,regen)
local drink_cup = drink_cup or true
local regen = regen or 0.5
thirsty.config.regen_from_node[node_name] = regen
thirsty.config.fountain_type[node_name] = "w"
if drink_cup then
thirsty.register_drinkable_node(node_name)
end
end
--------------------------
-- Tier 1 API Functions --
--------------------------
-- node_drinkable: which nodes can we drink from, given a
-- container (a cup, a bowl etc.)
function thirsty.register_drinkable_node(node_name,max_hydrate)
local max_hydrate = max_hydrate or nil
thirsty.config.node_drinkable[node_name] = true
if max_hydrate then
thirsty.config.drink_from_node[node_name] = max_hydrate
end
end
function thirsty.on_use( old_on_use )
return function(itemstack, player, pointed_thing)
local node = nil
if pointed_thing and pointed_thing.type == 'node' then
node = minetest.get_node(pointed_thing.under)
end
thirsty.drink_handler(player, itemstack, node)
-- call original on_use, if provided
if old_on_use ~= nil then
return old_on_use(itemstack, player, pointed_thing)
else
return itemstack
end
end
end
function thirsty.augment_item_for_drinking( itemname, level )
local new_definition = {}
local level = level or thirsty.config.start
-- we need to be able to point at the water
new_definition.liquids_pointable = true
-- call closure generator with original on_use handler
new_definition.on_use = thirsty.on_use(
minetest.registered_items[itemname].on_use
)
-- overwrite the node definition with almost the original
minetest.override_item(itemname, new_definition)
-- add configuration settings
thirsty.config.drink_from_container[itemname] = level
end
--------------------------
-- Tier 2 API Functions --
--------------------------
function thirsty.drink(player, value, max_hyd, empty_vessel)
local max_hyd = max_hyd or 20
local value = value or 2
local pmeta = player:get_meta()
local hydro = pmeta:get_float("thirsty_hydro")
-- test whether we're not *above* max_hyd;
-- this function should not remove any overhydration
if hydro < max_hyd then
hydro = math.min(hydro + value, max_hyd)
--print("Drinking by "..value.." to "..hydro)
pmeta:set_float("thirsty_hydro", hydro)
minetest.sound_play("thirsty_breviceps_drink-drinking-liquid", { to_player = player:get_player_name(), gain = 2.0, })
if empty_vessel then
player:get_inventory():add_item("main", empty_vessel.." 1")
end
return true
end
return false
end
function thirsty.register_canteen(item_name,hydrate_capacity,max_hydrate,on_use)
local on_use = on_use or true
local max_hydrate = max_hydrate or thirsty.config.start
thirsty.config.container_capacity[item_name] = hydrate_capacity
thirsty.config.drink_from_container[item_name] = max_hydrate
local def = table.copy(minetest.registered_items[item_name])
def.liquids_pointable = true
def.stack_max = 1
def.type = "tool"
if on_use then
def.on_use = thirsty.on_use(nil)
end
minetest.register_tool(":"..item_name, def)
end
function thirsty.register_canteen_complex(item_name,hydrate_capacity,max_hydrate,full_image)
local full_item_name = item_name.."_full"
local max_hydrate = max_hydrate or thirsty.config.start
-- register new full version of item into thirsty tables and as tool.
thirsty.config.container_capacity[full_item_name] = hydrate_capacity
thirsty.config.drink_from_container[full_item_name] = max_hydrate
local def_f = table.copy(minetest.registered_items[item_name])
def_f.inventory_image = full_image or def_f.inventory_image
def_f.wield_image = full_image or def_f.inventory_image
def_f.liquids_pointable = true
def_f.stack_max = 1
def_f.type = "tool"
def_f.description = "Full "..def_f.description
def_f.on_use = thirsty.on_use(nil)
def_f.thirsty_empty = item_name
minetest.register_tool(":"..full_item_name, def_f)
-- modify empty_vessel registration
local def_e = table.copy(minetest.registered_items[item_name])
def_e.on_use = thirsty.on_use_empty()
def_e.liquids_pointable = true
def_e.name = nil
def_e.type = nil
minetest.override_item(item_name, def_e)
end
-- note not offically exposed to API yet, use with caution may change
function thirsty.on_use_empty()
return function(itemstack, player, pointed_thing)
local node = nil
if pointed_thing and pointed_thing.type == 'node' then
node = minetest.get_node(pointed_thing.under)
end
if node and thirsty.config.node_drinkable[node.name] then
local new_stack = {name = itemstack:get_name().."_full", count=1, wear=1, metadata=""}
player:get_inventory():add_item("main", new_stack)
itemstack:take_item()
return itemstack
end
end
end
--------------------------
-- Tier 3 API Functions --
--------------------------
function thirsty.on_rightclick( old_on_rightclick )
return function(pos, node, player, itemstack, pointed_thing)
thirsty.drink_handler(player, itemstack, node)
-- call original on_rightclick, if provided
if old_on_rightclick ~= nil then
return old_on_rightclick(pos, node, player, itemstack, pointed_thing)
else
return itemstack
end
end
end
--------------------------
-- Tier 4 API Functions --
--------------------------
function thirsty.register_water_fountain(node_name)
thirsty.config.fountain_type[node_name] = "f"
end
--------------------------
-- Tier 5 API Functions --
--------------------------
function thirsty.register_amulet_extractor(item_name,value)
thirsty.config.extraction_for_item[item_name] = value
end
function thirsty.register_amulet_supplier(item_name,value)
thirsty.config.injection_for_item[item_name] = value
end
function thirsty.register_amulet_thirst(item_name,value)
thirsty.config.thirst_adjust_item[item_name] = value
end
function thirsty.get_thirst_factor(player)
local name = player:get_player_name()
local pmeta = player:get_meta()
local pl = minetest.deserialize(pmeta:get_string("thirsty_values"))
return pl.thirst_factor
end
function thirsty.set_thirst_factor(player, factor)
local name = player:get_player_name()
local pmeta = player:get_meta()
local pl = minetest.deserialize(pmeta:get_string("thirsty_values"))
pl.thirst_factor = factor
pmeta:set_string("thirsty_values",minetest.serialize(pl))
end
-------------------------
-- Other API Functions --
-------------------------
function thirsty.get_hydro(player)
local pmeta = player:get_meta()
local hydro = pmeta:get_float("thirsty_hydro")
return hydro
end
----------------------------
-- Mod Internal Functions --
----------------------------
local damage_enabled = minetest.settings:get_bool("enable_damage")
function thirsty.on_joinplayer(player)
local name = player:get_player_name()
local pmeta = player:get_meta()
-- setup initial thirst player meta value if not present
if pmeta:get_float("thirsty_hydro") == 0 then
pmeta:set_float("thirsty_hydro", thirsty.config.start)
end
-- default entry for joining players
if pmeta:get_string("thirsty_values") == "" then
local pos = player:get_pos()
pmeta:set_string("thirsty_values", minetest.serialize({
last_pos = math.floor(pos.x) .. ':' .. math.floor(pos.z),
time_in_pos = 0.0,
pending_dmg = 0.0,
thirst_factor = 1.0
}))
end
thirsty.hud_init(player)
end
function thirsty.on_dieplayer(player)
local name = player:get_player_name()
local pos = player:get_pos()
local pmeta = player:get_meta()
pmeta:set_float("thirsty_hydro", thirsty.config.start)
pmeta:set_string("thirsty_values", minetest.serialize({
last_pos = math.floor(pos.x) .. ':' .. math.floor(pos.z),
time_in_pos = 0.0,
pending_dmg = 0.0,
thirst_factor = 1.0
}))
end
function thirsty.main_loop(dtime)
-- get thirsty
thirsty.time_next_tick = thirsty.time_next_tick - dtime
while thirsty.time_next_tick < 0.0 do
-- time for thirst
thirsty.time_next_tick = thirsty.time_next_tick + thirsty.config.tick_time
for _,player in ipairs(minetest.get_connected_players()) do
-- dead players don't get thirsty, or full for that matter :-P
if player:get_hp() <= 0 then
break
end
local name = player:get_player_name()
local pos = player:get_pos()
local pmeta = player:get_meta()
local hydro = pmeta:get_float("thirsty_hydro")
local pl = minetest.deserialize(pmeta:get_string("thirsty_values"))
-- how long have we been standing "here"?
-- (the node coordinates in X and Z should be enough)
local pos_hash = math.floor(pos.x) .. ':' .. math.floor(pos.z)
if pl.last_pos == pos_hash then
pl.time_in_pos = pl.time_in_pos + thirsty.config.tick_time
else
-- you moved!
pl.last_pos = pos_hash
pl.time_in_pos = 0.0
end
local pl_standing = pl.time_in_pos > thirsty.config.stand_still_for_drink
local pl_afk = pl.time_in_pos > thirsty.config.stand_still_for_afk
--print("Standing: " .. (pl_standing and 'true' or 'false' ) .. ", AFK: " .. (pl_afk and 'true' or 'false'))
pos.y = pos.y + 0.1
local node = minetest.get_node(pos)
local drink_per_second = thirsty.config.regen_from_node[node.name] or 0
-- fountaining (uses pos, slight changes ok)
for k, fountain in pairs(thirsty.fountains) do
local dx = fountain.pos.x - pos.x
local dy = fountain.pos.y - pos.y
local dz = fountain.pos.z - pos.z
local dist2 = dx * dx + dy * dy + dz * dz
local fdist = fountain.level * thirsty.config.fountain_distance_per_level -- max 100 nodes radius
--print (string.format("Distance from %s (%d): %f out of %f", k, fountain.level, math.sqrt(dist2), fdist ))
if dist2 < fdist * fdist then
-- in range, drink as if standing (still) in water
drink_per_second = math.max(thirsty.config.regen_from_fountain or 0, drink_per_second)
pl_standing = true
break -- no need to check the other fountains
end
end
-- amulets
-- TODO: I *guess* we need to optimize this, but I haven't
-- measured it yet. No premature optimizations!
local pl_inv = player:get_inventory()
local extractor_max = 0.0
local injector_max = 0.0
local amulet_thirst = false
local container_not_full = nil
local container_not_empty = nil
local inv_main = player:get_inventory():get_list('main')
for i, itemstack in ipairs(inv_main) do
local name = itemstack:get_name()
-- Amulets Hydration/Moisture
local injector_this = thirsty.config.injection_for_item[name]
if injector_this and injector_this > injector_max then
injector_max = injector_this
end
local extractor_this = thirsty.config.extraction_for_item[name]
if extractor_this and extractor_this > extractor_max then
extractor_max = extractor_this
end
if thirsty.config.container_capacity[name] then
local wear = itemstack:get_wear()
-- can be both!
if wear == 0 or wear > 1 then
container_not_full = { i, itemstack }
end
if wear > 0 and wear < 65534 then
container_not_empty = { i, itemstack }
end
end
-- Amulets of Thirst
local is_thirst_amulet = thirsty.config.thirst_adjust_item[name]
if is_thirst_amulet then
amulet_thirst = true
pl.thirst_factor = thirsty.config.thirst_adjust_item[name]
end
end
if amulet_thirst ~= true and pl.thirst_factor ~= 1.0 then
pl.thirst_factor = 1.0
end
if extractor_max > 0.0 and container_not_full then
local i = container_not_full[1]
local itemstack = container_not_full[2]
local capacity = thirsty.config.container_capacity[itemstack:get_name()]
local wear = itemstack:get_wear()
if wear == 0 then wear = 65535.0 end
local drink = extractor_max * thirsty.config.tick_time
local drinkwear = drink / capacity * 65535.0
wear = wear - drinkwear
if wear < 1 then wear = 1 end
itemstack:set_wear(wear)
player:get_inventory():set_stack("main", i, itemstack)
end
if injector_max > 0.0 and container_not_empty then
local i = container_not_empty[1]
local itemstack = container_not_empty[2]
local capacity = thirsty.config.container_capacity[itemstack:get_name()]
local wear = itemstack:get_wear()
if wear == 0 then wear = 65535.0 end
local drink = injector_max * thirsty.config.tick_time
local drink_missing = 20 - hydro
drink = math.max(math.min(drink, drink_missing), 0)
local drinkwear = drink / capacity * 65535.0
wear = wear + drinkwear
if wear > 65534 then wear = 65534 end
itemstack:set_wear(wear)
thirsty.drink(player, drink, 20)
hydro = pmeta:get_float("thirsty_hydro")
player:get_inventory():set_stack("main", i, itemstack)
end
if drink_per_second > 0 and pl_standing then
-- Drinking from the ground won't give you more than max
thirsty.drink(player, (drink_per_second * thirsty.config.tick_time)*2, 20)
pl.time_in_pos = 0.0
--print("Raising hydration by "..(drink_per_second*thirsty.config.tick_time).." to "..PPA.get_value(player, 'thirsty_hydro'))
else
if not pl_afk then
-- only get thirsty if not AFK
local amount = thirsty.config.thirst_per_second * thirsty.config.tick_time * pl.thirst_factor
pmeta:set_float("thirsty_hydro",(hydro - amount))
hydro = pmeta:get_float("thirsty_hydro")
--print("Lowering hydration by "..amount.." to "..hydro)
end
end
-- should we only update the hud on an actual change?
-- minetest.debug(player:get_player_name().." "..hydro)
thirsty.hud_update(player, hydro)
-- damage, if enabled
if damage_enabled then
-- maybe not the best way to do this, but it does mean
-- we can do anything with one tick loop
if hydro <= 0.0 and not pl_afk then
pl.pending_dmg = pl.pending_dmg + thirsty.config.damage_per_second * thirsty.config.tick_time
--print("Pending damage at " .. pl.pending_dmg)
if pl.pending_dmg > 1.0 then
local dmg = math.floor(pl.pending_dmg)
pl.pending_dmg = pl.pending_dmg - dmg
player:set_hp( player:get_hp() - dmg )
end
else
-- forget any pending damage when not thirsty
pl.pending_dmg = 0.0
end
end
pmeta:set_string("thirsty_values",minetest.serialize(pl))
end -- for players
-- check fountains for expiration
for k, fountain in pairs(thirsty.fountains) do
fountain.time_until_check = fountain.time_until_check - thirsty.config.tick_time
if fountain.time_until_check <= 0 then
-- remove fountain, the abm will set it again
--print("Removing fountain at " .. k)
thirsty.fountains[k] = nil
end
end
end
end
function thirsty.drink_handler(player, itemstack, node)
local pmeta = player:get_meta()
local hydro = pmeta:get_float("thirsty_hydro")
local pl = minetest.deserialize(pmeta:get_string("thirsty_values"))
local old_hydro = hydro
-- selectors, always true, to make the following code easier
local item_name = itemstack and itemstack:get_name() or ':'
local node_name = node and node.name or ':'
if thirsty.config.node_drinkable[node_name] then
-- we found something to drink!
local cont_level = thirsty.config.drink_from_container[item_name] or 0
local node_level = thirsty.config.drink_from_node[node_name] or 0
-- drink until level
local level = math.max(cont_level, node_level)
--print("Drinking to level " .. level)
thirsty.drink(player, level, level)
-- fill container, if applicable
if thirsty.config.container_capacity[item_name] then
--print("Filling a " .. item_name .. " to " .. thirsty.config.container_capacity[item_name])
itemstack:set_wear(1) -- "looks full"
end
elseif thirsty.config.container_capacity[item_name] then
-- drinking from a container
if itemstack:get_wear() ~= 0 then
local capacity = thirsty.config.container_capacity[item_name]
local hydro_missing = 20 - hydro;
if hydro_missing > 0 then
local wear_missing = hydro_missing / capacity * 65535.0;
local wear = itemstack:get_wear()
local new_wear = math.ceil(math.max(wear + wear_missing, 1))
if (new_wear > 65534) then
wear_missing = 65534 - wear
new_wear = 65534
end
-- deal with full/empty vessels, when empty remove
-- tool version and supply empty name to thirsty.drink
-- so player recieves empty version back
local empty_vessel_name
if new_wear >= 65534 then
if minetest.registered_items[item_name].thirsty_empty then
itemstack:take_item(1)
empty_vessel_name = minetest.registered_items[item_name].thirsty_empty
else
itemstack:set_wear(new_wear)
end
-- end full/empty vessel code block
else
itemstack:set_wear(new_wear)
end
if wear_missing > 0 then -- rounding glitches?
thirsty.drink(player, wear_missing * capacity / 65535.0, 20, empty_vessel_name)
hydro = pmeta:get_float("thirsty_hydro")
end
end
end
end
-- update HUD if value changed
if hydro ~= old_hydro then
thirsty.hud_update(player, hydro)
end
end
function thirsty.fountain_abm(pos, node)
local fountain_count = 0
local water_count = 0
local total_count = 0
for y = 0, thirsty.config.fountain_height do
for x = -y, y do
for z = -y, y do
local n = minetest.get_node({
x = pos.x + x,
y = pos.y - y + 1, -- start one *above* the fountain
z = pos.z + z
})
if n then
--print(string.format("%s at %d:%d:%d", n.name, pos.x+x, pos.y-y+1, pos.z+z))
total_count = total_count + 1
local type = thirsty.config.fountain_type[n.name] or ''
if type == 'f' then
fountain_count = fountain_count + 1
elseif type == 'w' then
water_count = water_count + 1
end
end
end
end
end
local level = math.min(thirsty.config.fountain_max_level, math.min(fountain_count, water_count))
--print(string.format("Fountain (%d): %d + %d / %d", level, fountain_count, water_count, total_count))
thirsty.fountains[string.format("%d:%d:%d", pos.x, pos.y, pos.z)] = {
pos = { x=pos.x, y=pos.y, z=pos.z },
level = level,
-- time until check is 20 seconds, or twice the average
-- time until the abm ticks again. Should be enough.
time_until_check = 20,
}
end

75
thirsty/hud.lua Normal file
View file

@ -0,0 +1,75 @@
------------------------------------------------------------
-- _____ _ _ _ --
-- |_ _| |_ (_)_ _ __| |_ _ _ --
-- | | | ' \| | '_(_-< _| || | --
-- |_| |_||_|_|_| /__/\__|\_, | --
-- |__/ --
------------------------------------------------------------
-- HUD definitions for Thirsty --
------------------------------------------------------------
-- See init.lua for license --
------------------------------------------------------------
--[[
Optionally from one of the supported mods
Any hud needs to define the following functions:
- thirsty.hud_init(player)
Initialize the HUD for a new player.
- thirsty.hud_update(player, value)
Display the new value "value" for the given player. "value" is
a floating point number, not necessarily bounded. You can use the
"thirsty.hud_clamp(value)" function to get an integer between 0
and 20.
]]--
function thirsty.hud_clamp(value)
if value < 0 then
return 0
elseif value > 20 then
return 20
else
return math.ceil(value)
end
end
if minetest.get_modpath("hudbars") then
hb.register_hudbar('thirst', 0xffffff, "Hydration", {
bar = 'thirsty_hudbars_bar.png',
icon = 'thirsty_drop_100_24_cc0.png'
}, 20, 20, false)
function thirsty.hud_init(player)
local pmeta = player:get_meta()
hb.init_hudbar(player, 'thirst',
thirsty.hud_clamp(pmeta:get_float("thirsty_hydro")),
20, false)
end
function thirsty.hud_update(player, value)
hb.change_hudbar(player, 'thirst', thirsty.hud_clamp(value), 20)
end
else
-- 'builtin' hud
function thirsty.hud_init(player)
-- above breath bar, for now
local name = player:get_player_name()
local pmeta = player:get_meta()
thirsty_hud = player:hud_add({
hud_elem_type = "statbar",
position = { x=0.5, y=1 },
text = "thirsty_drop_100_24_cc0.png",
number = thirsty.hud_clamp(pmeta:get_float("thirsty_hydro")),
direction = 0,
size = { x=24, y=24 },
offset = { x=25, y=-(48+24+16+32)},
})
end
function thirsty.hud_update(player, value)
local name = player:get_player_name()
local hud_id = thirsty_hud
player:hud_change(hud_id, 'number', thirsty.hud_clamp(value))
end
end

168
thirsty/init.lua Normal file
View file

@ -0,0 +1,168 @@
------------------------------------------------------------
-- _____ _ _ _ --
-- |_ _| |_ (_)_ _ __| |_ _ _ --
-- | | | ' \| | '_(_-< _| || | --
-- |_| |_||_|_|_| /__/\__|\_, | --
-- |__/ --
------------------------------------------------------------
-- Thirsty mod [thirsty] --
------------------------------------------------------------
-- A mod that adds a "thirst" mechanic, similar to hunger --
-- Copyright (C) 2015 Ben Deutsch <ben@bendeutsch.de> --
------------------------------------------------------------
-- name idea thirsty_revive or thirsty_renew
---------------
--[[ License --
---------------
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
USA
--Media/Images--
See Readme.MD - Mix of:
CC BY-SA 3.0
CC BY-SA 4.0
CC0 1.0 Universal
-------------------------------------------
-- Terminology: "Thirst" vs. "hydration" --
-------------------------------------------
"Thirst" is the absence of "hydration" (a term suggested by
everamzah on the Minetest forums, thanks!). The overall mechanic
is still called "thirst", but the visible bar is that of
"hydration", filled with "hydro points".
]]--
thirsty = {}
thirsty.version = 0.103
-- simple toboolean function that handles nil
thirsty.tobool = function(value)
if value == nil then
return nil
elseif value == "true" or value == 1 then
return true
else
return false
end
end
-- Configuration variables
thirsty.config = {
-- configuration in Settings>>Mods>>Thirsty
-- Best to not change defaults here
-- [General]
tick_time = minetest.settings:get("thirsty_tick_time") or 0.5,
start = minetest.settings:get("thirsty_starting_value") or 20,
thirst_per_second = minetest.settings:get("thirst_per_second") or 1.0 / 30,
damage_per_second = minetest.settings:get("damage_per_second") or 1.0 / 10.0,
stand_still_for_drink = minetest.settings:get("stand_still_for_drink") or 1.0,
stand_still_for_afk = minetest.settings:get("stand_still_for_afk") or 120.0,
-- [Water Fountain]
regen_from_fountain = minetest.settings:get("regen_from_fountain") or 0.5,
fountain_height = minetest.settings:get("fountain_height") or 4,
fountain_max_level = minetest.settings:get("fountain_max_level") or 20,
fountain_distance_per_level = minetest.settings:get("fountain_distance_per_level") or 5,
-- [Thirsty Mod Items]
register_bowl = thirsty.tobool(minetest.settings:get("register_bowl")) or true,
register_canteens = thirsty.tobool(minetest.settings:get("register_canteens")) or true,
register_drinking_fountain = thirsty.tobool(minetest.settings:get("register_drinking")) or true,
register_fountains = thirsty.tobool(minetest.settings:get("register_fountains")) or true,
register_amulets = thirsty.tobool(minetest.settings:get("register_amulets")) or true,
-- [Other Mods]
register_vessels = thirsty.tobool(minetest.settings:get("register_vessels")) or true,
-- [Node/Item Tables] Do not change names without code updates.
-- Use API functions to register to these tables
regen_from_node = {},
node_drinkable = {},
drink_from_container = {},
container_capacity = {},
drink_from_node = {},
fountain_type = {},
extraction_for_item = {},
injection_for_item = {},
thirst_adjust_item = {}
}
-- water fountains
thirsty.fountains = {
--[[
x:y:z = {
pos = { x=x, y=y, z=z },
level = 4,
time_until_check = 20,
-- something about times
}
]]
}
thirsty.ext_nodes_items = {
--[[ acts as an internal
mod aliasing for ingredients
used in Canteen/Fountain recipes.
to change edit:
components_external_nodes_items.lua
steel_ingot = default:steel_ingot
]]
}
-- general settings
thirsty.time_next_tick = 0.0
local M = thirsty
local C = M.config
local modpath = minetest.get_modpath("thirsty")
thirsty.time_next_tick = thirsty.config.tick_time
dofile(modpath..'/hud.lua')
dofile(modpath..'/functions.lua')
minetest.register_on_joinplayer(thirsty.on_joinplayer)
minetest.register_on_dieplayer(thirsty.on_dieplayer)
minetest.register_globalstep(thirsty.main_loop)
dofile(modpath..'/components_external_nodes_items.lua')
dofile(modpath..'/components.lua')
dofile(modpath..'/interop_a_functions.lua')
-- dungeon_loot for Aumlets of Thirst
if minetest.get_modpath("dungeon_loot") then
dofile(modpath..'/interop_dungeon_loot.lua')
end
-- mobs_animal specific config
if minetest.get_modpath("mobs_animal") then
dofile(modpath..'/interop_mobs_animal.lua')
end
-- farming(redo) specific config
if minetest.get_modpath("farming") and
farming.mod == "redo" then
dofile(modpath..'/interop_farming_redo.lua')
end
-- ethereal specific config
if minetest.get_modpath("ethereal") then
dofile(modpath..'/interop_ethereal.lua')
end

View file

@ -0,0 +1,56 @@
------------------------------------------------------------
-- _____ _ _ _ --
-- |_ _| |_ (_)_ _ __| |_ _ _ --
-- | | | ' \| | '_(_-< _| || | --
-- |_| |_||_|_|_| /__/\__|\_, | --
-- |__/ --
------------------------------------------------------------
-- Thirsty mod [interoperability function] --
------------------------------------------------------------
-- because I'm lazy and like small code blocks --
------------------------------------------------------------
thirsty.register_food_drink = function (item_name,satiate_value,heal_value,hyd_value,hyd_max,rtn_item_name)
local is_hunger_ng = false
local is_hbhunger = false
if minetest.get_modpath("hunger_ng") then is_hunger_ng = true end
if minetest.get_modpath("hbhunger") then is_hbhunger = true end
if is_hunger_ng then
hunger_ng.add_hunger_data(item_name,{
satiates = satiate_value,
heals = heal_value,
returns = nil,
timeout = nil
})
end
if is_hbhunger then
hbhunger.register_food(item_name, satiate_value)
end
local def = table.copy(minetest.registered_items[item_name])
def.on_use = function(itemstack,player,pointed_thing)
thirsty.drink(player,hyd_value,hyd_max,rtn_item_name)
if minetest.registered_items[item_name]._hunger_ng then
minetest.sound_play("hunger_ng_eat", {to_player = player:get_player_name(), gain = 2.0 })
hunger_ng.alter_hunger(player:get_player_name(), satiate_value, "from:thirsty-"..item_name)
player:set_hp(player:get_hp()+heal_value)
itemstack:take_item()
return itemstack
else
minetest.do_item_eat(satiate_value,nil, itemstack:take_item(), player, pointed_thing)
return itemstack
end
end
if def.type == "node" then
minetest.register_node(":"..item_name, def)
else
minetest.register_craftitem(":"..item_name, def)
end
end

View file

@ -0,0 +1,20 @@
------------------------------------------------------------
-- _____ _ _ _ --
-- |_ _| |_ (_)_ _ __| |_ _ _ --
-- | | | ' \| | '_(_-< _| || | --
-- |_| |_||_|_|_| /__/\__|\_, | --
-- |__/ --
------------------------------------------------------------
-- Thirsty mod [interop_ethereal] --
------------------------------------------------------------
-- Settings to support Dungeon Loot --
------------------------------------------------------------
if thirsty.config.register_amulets == true then
dungeon_loot.register({name = "thirsty:lesser_amulet_thirst", chance = 0.1, count = {1,1}})
dungeon_loot.register({name = "thirsty:amulet_thirst", chance = 0.05, count = {1,1}, y = {-100, 32768}})
dungeon_loot.register({name = "thirsty:greater_amulet_thirst", chance = 0.05, count = {1,1}, y = {-200, 32768}})
end

View file

@ -0,0 +1,20 @@
------------------------------------------------------------
-- _____ _ _ _ --
-- |_ _| |_ (_)_ _ __| |_ _ _ --
-- | | | ' \| | '_(_-< _| || | --
-- |_| |_||_|_|_| /__/\__|\_, | --
-- |__/ --
------------------------------------------------------------
-- Thirsty mod [interop_ethereal] --
------------------------------------------------------------
-- Settings to support Ethereal --
------------------------------------------------------------
local E = thirsty.ext_nodes_items
----------------------------
-- Hydrate and Food Items --
----------------------------
thirsty.register_food_drink("ethereal:firethorn_jelly" ,1,0,1,20,E.glass_bottle)
thirsty.register_food_drink("ethereal:mushroom_soup" ,2.5,0,2,20,"ethereal:bowl")
thirsty.register_food_drink("ethereal:hearty_stew" ,7.0,0,1,20,"ethereal:bowl")
thirsty.register_food_drink("ethereal:golden_apple" ,10,10,10,30,nil)

View file

@ -0,0 +1,71 @@
------------------------------------------------------------
-- _____ _ _ _ --
-- |_ _| |_ (_)_ _ __| |_ _ _ --
-- | | | ' \| | '_(_-< _| || | --
-- |_| |_||_|_|_| /__/\__|\_, | --
-- |__/ --
------------------------------------------------------------
-- Thirsty mod [interop_farming(redo)] --
------------------------------------------------------------
-- Settings to support farming redo --
------------------------------------------------------------
local E = thirsty.ext_nodes_items
--------------------
-- Hydrate only --
--------------------
local def = table.copy(minetest.registered_items["farming:glass_water"])
def.on_use = function(itemstack,player,pointed_thing)
thirsty.drink(player,2,20,E.drinking_glass)
itemstack:take_item()
return itemstack
end
minetest.register_craftitem(":farming:glass_water", def)
local def = table.copy(minetest.registered_items["farming:rose_water"])
def.on_use = function(itemstack,player,pointed_thing)
thirsty.drink(player,12,24,E.glass_bottle)
itemstack:take_item()
return itemstack
end
minetest.register_craftitem(":farming:rose_water", def)
----------------------------
-- Hydrate and Food Items --
----------------------------
thirsty.register_food_drink("farming:soy_milk" ,1,0,4,22,E.drinking_glass)
thirsty.register_food_drink("farming:pineapple_juice" ,1,0,4,22,E.drinking_glass)
thirsty.register_food_drink("farming:carrot_juice" ,1,0,4,22,E.drinking_glass)
thirsty.register_food_drink("farming:smoothie_berry" ,2,0,4,23,E.drinking_glass)
thirsty.register_food_drink("farming:smoothie_raspberry",2,0,4,23,E.drinking_glass)
thirsty.register_food_drink("farming:mint_tea" ,2,0,4,24,E.drinking_glass)
thirsty.register_food_drink("farming:coffee_cup" ,2,0,4,22,E.drinking_glass)
thirsty.register_food_drink("farming:beetroot_soup" ,4,0,2,20,E.wood_bowl)
thirsty.register_food_drink("farming:onion_soup" ,5,0,2,20,E.wood_bowl)
thirsty.register_food_drink("farming:pea_soup" ,6,0,2,20,E.wood_bowl)
thirsty.register_food_drink("farming:tomato_soup" ,7,0,2,20,E.wood_bowl)
thirsty.register_food_drink("farming:chili_bowl" ,7,0,-2,20,E.wood_bowl)
thirsty.register_food_drink("farming:chili_pepper" ,1,-1,-5,40,nil)
--------------------
-- Complex/Custom --
--------------------
local def = table.copy(minetest.registered_items["farming:cactus_juice"])
def.on_use = function(itemstack, player, pointed_thing)
if player then
if math.random(5) == 1 then
thirsty.drink(player,-2,20,E.drinking_glass)
itemstack:take_item()
return itemstack
else
thirsty.drink(player,6,20,E.drinking_glass)
itemstack:take_item()
return itemstack
end
end
end
minetest.register_craftitem(":farming:cactus_juice", def)

View file

@ -0,0 +1,19 @@
------------------------------------------------------------
-- _____ _ _ _ --
-- |_ _| |_ (_)_ _ __| |_ _ _ --
-- | | | ' \| | '_(_-< _| || | --
-- |_| |_||_|_|_| /__/\__|\_, | --
-- |__/ --
------------------------------------------------------------
-- Thirsty mod [interop_mobs_animal] --
------------------------------------------------------------
-- Settings to support mobs_animal --
------------------------------------------------------------
local E = thirsty.ext_nodes_items
----------------------------
-- Hydrate and Food Items --
----------------------------
thirsty.register_food_drink("mobs:glass_milk",1,0,4,22,E.drinking_glass)
thirsty.register_food_drink("mobs:honey" ,2,0,1,20,nil)

4
thirsty/mod.conf Normal file
View file

@ -0,0 +1,4 @@
name = thirsty
description = A mod that adds a "thirst" mechanic, similar to hunger.
depends =
optional_depends = default, bucket, hudbars, vessels, farming, mobs_animal, hunger_ng, hbhunger, dungeon_loot, ethereal

60
thirsty/settingtypes.txt Normal file
View file

@ -0,0 +1,60 @@
[*General]
# Hudbar/player max value for hydration
thirsty_starting_value (Thirst Max Value) int 20
# The period, in seconds, in which this mod updates values.
# Changing this will not directly affect other values, but
# may change computation load or accuracy.
thirsty_tick_time (Thirst Tick Time) float 0.5
# Thirst per second (full hydration is 20 hydro points)
# Basic Calc 1/30 = 0.033
thirst_per_second (Thirst Per Second) float 0.033
# Damage per second if completely thirsty / out of hydration.
# Basic Calc 1/10 = 0.1
damage_per_second (Damage Per Second) float 0.1
# How long in seconds you have to remain still to drink from standing in water.
stand_still_for_drink (Stand Still to Drink) float 1.0
# How long in seconds of not moving before a player is deemed
# AFK (away from keyboard), such players no longer get thirsty
# or damaged.
stand_still_for_afk (AFK Time Seconds) int 120
[*Water Fountain]
# Regeneration from being within a fountain's radius.
# (it's as if you're standing in water)
regen_from_fountain (Regen from Fountains) float 0.5
# How far should the fountain scanning pyramid go?
fountain_height (Fountain Height) int 4
# The max level of a fountain
fountain_max_level (Fountain Max Level) int 20
# How many nodes away can you still benefit from a fountain, per fountain level
fountain_distance_per_level (Fountain Distance Per Level) int 5
[*Thirsty Mod Items]
# Add the wooden bowl and crafting recipe?
# Will Augument Farming Redo Wooden Bowl if set to true
# and Farming redo is being used
register_bowl (Simple Wooden Bowl) bool true
# Add the canteens and crafting recipes?
register_canteens (Steel/Bronze Canteens) bool true
# Add the drinking fountain and crafting recipes?
register_drinking_fountain (Drinking Fountains) bool true
# Add the fountain and extenders and crafting recipes?
register_fountains (Water Fountains) bool true
# Add the amulets (extractor / injector) and crafting recipes?
register_amulets (Amulets) bool true
[*Other Mods]
# Should we augment the vessels from the "vessels" mod?
register_vessels (Vessels Mod) bool true

View file

@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="bowl.svg"
inkscape:export-filename="/home/ben/progs/minetest/minetest-thirsty/textures/thirsty_bowl_32.png"
inkscape:export-xdpi="180"
inkscape:export-ydpi="180">
<defs
id="defs4">
<inkscape:path-effect
effect="spiro"
id="path-effect3824"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3820"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761-8"
is_visible="true" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#838181"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="6.537478"
inkscape:cy="7.4852095"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1366"
inkscape:window-height="744"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:snap-global="false">
<inkscape:grid
type="xygrid"
id="grid3755"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<path
sodipodi:type="arc"
style="fill:#8e5700;fill-opacity:1;stroke:none"
id="path3757-8"
sodipodi:cx="340"
sodipodi:cy="252.36218"
sodipodi:rx="180"
sodipodi:ry="60"
d="m 520,252.36218 c 0,33.13709 -80.58875,60 -180,60 -99.41125,0 -180,-26.86291 -180,-60 0,0 0,0 0,0"
transform="matrix(0.0331251,0,0,0.09946417,-3.2760155,1018.2645)"
sodipodi:start="0"
sodipodi:end="3.1415927"
sodipodi:open="true" />
<path
sodipodi:type="arc"
style="fill:#b36e00;fill-opacity:1;stroke:none"
id="path3757-8-9"
sodipodi:cx="340"
sodipodi:cy="252.36218"
sodipodi:rx="180"
sodipodi:ry="60"
d="m 520,252.36218 c 0,33.02374 -80.05876,59.83946 -179.1288,59.9993 L 340,252.36218 z"
transform="matrix(0.01804296,0,0,0.09946417,1.8203443,1018.2479)"
sodipodi:start="0"
sodipodi:end="1.5659563" />
<path
sodipodi:type="arc"
style="fill:#b36e00;fill-opacity:1;stroke:none"
id="path3757-8-7"
sodipodi:cx="340"
sodipodi:cy="252.36218"
sodipodi:rx="180"
sodipodi:ry="60"
d="m 340.89962,312.36143 c -99.41001,0.16562 -180.40052,-26.5627 -180.89737,-59.69937 -7.6e-4,-0.0508 -0.001,-0.1017 -0.002,-0.15255 L 340,252.36218 z"
transform="matrix(0.0331251,0,0,0.09946417,-3.3075828,1018.2795)"
sodipodi:start="1.5657984"
sodipodi:end="3.1391372" />
<path
sodipodi:type="arc"
style="fill:#563500;fill-opacity:1;stroke:none"
id="path3757"
sodipodi:cx="340"
sodipodi:cy="252.36218"
sodipodi:rx="180"
sodipodi:ry="60"
d="m 520,252.36218 c 0,33.13709 -80.58875,60 -180,60 -99.41125,0 -180,-26.86291 -180,-60 0,-33.13708 80.58875,-60 180,-60 99.41125,0 180,26.86292 180,60 z"
transform="matrix(0.0331251,0,0,0.0326468,-3.2695864,1035.128)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="canteen.svg"
inkscape:export-filename="/home/ben/progs/minetest/minetest-thirsty/textures/thirsty_bowl_16.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4">
<inkscape:path-effect
effect="spiro"
id="path-effect3824"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3820"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761-8"
is_visible="true" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#838181"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="7.6921211"
inkscape:cy="7.4852095"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1366"
inkscape:window-height="744"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:snap-global="false">
<inkscape:grid
type="xygrid"
id="grid3755"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<g
id="g3784"
style="fill:#e28b1a;fill-opacity:1">
<path
transform="translate(0,1037.3408)"
d="m 13.005714,8.0134811 a 5.0034118,4.987628 0 1 1 -10.0068236,0 5.0034118,4.987628 0 1 1 10.0068236,0 z"
sodipodi:ry="4.987628"
sodipodi:rx="5.0034118"
sodipodi:cy="8.0134811"
sodipodi:cx="8.0023022"
id="path3010"
style="fill:#e28b1a;fill-opacity:1;stroke:none"
sodipodi:type="arc" />
<rect
transform="translate(0,1036.3622)"
y="2.0157008"
x="5.9977808"
height="1.0101526"
width="4.0090427"
id="rect3780"
style="fill:#e28b1a;fill-opacity:1;stroke:none" />
<rect
transform="translate(0,1036.3622)"
y="3.0258534"
x="6.976366"
height="1.9887378"
width="2.0518723"
id="rect3782"
style="fill:#e28b1a;fill-opacity:1;stroke:none" />
</g>
<rect
style="fill:#000000;fill-opacity:1;stroke:none"
id="rect3789"
width="2.0203052"
height="0.97858524"
x="7.0079331"
y="1.0371156"
transform="translate(0,1036.3622)" />
<rect
style="fill:#562f00;fill-opacity:1;stroke:none"
id="rect3791"
width="11.016976"
height="2.0203052"
x="562.01971"
y="876.90887"
transform="matrix(0.84395175,0.53641909,-0.53641909,0.84395175,0,0)" />
<rect
style="fill:#562f00;fill-opacity:1;stroke:none"
id="rect3791-4"
width="11.016976"
height="2.0203052"
x="548.4823"
y="885.47589"
transform="matrix(-0.84395175,0.53641909,0.53641909,0.84395175,0,0)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4 KiB

View file

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="cup_0.svg"
inkscape:export-filename="/home/ben/progs/minetest/minetest-thirsty/textures/thirsty_cup_50_32.png"
inkscape:export-xdpi="180"
inkscape:export-ydpi="180">
<defs
id="defs4">
<inkscape:path-effect
effect="spiro"
id="path-effect3824"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3820"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761-8"
is_visible="true" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#838181"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="5.2747873"
inkscape:cy="10.523682"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1366"
inkscape:window-height="744"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:snap-global="false">
<inkscape:grid
type="xygrid"
id="grid3755"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<g
id="g3901"
transform="translate(-0.06313453,-0.2841054)">
<path
transform="matrix(0.02586702,0,0,0.02586702,-0.759071,1034.7695)"
d="m 520,252.36218 c 0,33.13709 -80.58875,60 -180,60 -99.41125,0 -180,-26.86291 -180,-60 0,-33.13708 80.58875,-60 180,-60 99.41125,0 180,26.86292 180,60 z"
sodipodi:ry="60"
sodipodi:rx="180"
sodipodi:cy="252.36218"
sodipodi:cx="340"
id="path3757-7"
style="fill:none;stroke:#000000;stroke-width:38.65926743;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
sodipodi:type="arc" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
inkscape:original-d="m 3.379651,1041.2974 2.0693612,8.7948 m 5.1734018,0 2.069363,-8.7948"
inkscape:path-effect="#path-effect3761-8"
id="path3759-1"
d="m 3.379651,1041.2974 2.0693612,8.7948 m 5.1734018,0 2.069363,-8.7948"
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
sodipodi:end="12.190499"
sodipodi:start="6.1411257"
d="m 518.18677,243.86725 c 14.07487,32.80327 -54.29213,63.1989 -152.70196,67.89052 -98.40984,4.69163 -189.59671,-18.09737 -203.67158,-50.90065 -14.07487,-32.80328 54.29213,-63.1989 152.70196,-67.89053 82.50666,-3.93345 162.32363,11.52802 192.91865,37.37059"
sodipodi:ry="60"
sodipodi:rx="180"
sodipodi:cy="252.36218"
sodipodi:cx="340"
id="path3757-2-9"
style="fill:none;stroke:#000000;stroke-width:69.22486115;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
sodipodi:type="arc"
transform="matrix(0.0143204,0,0,0.01457205,3.175878,1046.32)"
sodipodi:open="true" />
</g>
<path
sodipodi:type="arc"
style="fill:none;stroke:#ffffff;stroke-width:38.65926743;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="path3757"
sodipodi:cx="340"
sodipodi:cy="252.36218"
sodipodi:rx="180"
sodipodi:ry="60"
d="m 520,252.36218 c 0,33.13709 -80.58875,60 -180,60 -99.41125,0 -180,-26.86291 -180,-60 0,-33.13708 80.58875,-60 180,-60 99.41125,0 180,26.86292 180,60 z"
transform="matrix(0.02586702,0,0,0.02586702,-1.6068063,1033.8716)" />
<path
style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 2.5319162,1040.3995 2.0693612,8.7948 m 5.1734015,0 2.0693631,-8.7948"
id="path3759"
inkscape:path-effect="#path-effect3761"
inkscape:original-d="m 2.5319162,1040.3995 2.0693612,8.7948 m 5.1734015,0 2.0693631,-8.7948"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
transform="matrix(0.0143204,0,0,0.01457205,2.3281432,1045.4221)"
sodipodi:type="arc"
style="fill:none;stroke:#ffffff;stroke-width:69.22486115;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="path3757-2"
sodipodi:cx="340"
sodipodi:cy="252.36218"
sodipodi:rx="180"
sodipodi:ry="60"
d="m 519.45086,257.04536 c -7.75934,33.03599 -94.39241,57.72022 -193.50038,55.13378 -99.10797,-2.58645 -173.16068,-31.46414 -165.40134,-64.50013 7.75934,-33.03599 94.39241,-57.72023 193.50038,-55.13378 91.69188,2.39291 163.2237,27.44217 165.87564,58.08691"
sodipodi:start="0.07813237"
sodipodi:end="6.2543473"
sodipodi:open="true" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6 KiB

View file

@ -0,0 +1,167 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="cup.svg"
inkscape:export-filename="/home/ben/progs/minetest/minetest-thirsty/textures/thirsty_cup_100_16.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4">
<inkscape:path-effect
effect="spiro"
id="path-effect3824"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3820"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761-8"
is_visible="true" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#838181"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="5.2747873"
inkscape:cy="10.523682"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1366"
inkscape:window-height="744"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:snap-global="false">
<inkscape:grid
type="xygrid"
id="grid3755"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<g
id="g3901"
transform="translate(-0.06313453,-0.2841054)">
<path
transform="matrix(0.02586702,0,0,0.02586702,-0.759071,1034.7695)"
d="m 520,252.36218 c 0,33.13709 -80.58875,60 -180,60 -99.41125,0 -180,-26.86291 -180,-60 0,-33.13708 80.58875,-60 180,-60 99.41125,0 180,26.86292 180,60 z"
sodipodi:ry="60"
sodipodi:rx="180"
sodipodi:cy="252.36218"
sodipodi:cx="340"
id="path3757-7"
style="fill:none;stroke:#000000;stroke-width:38.65926743;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
sodipodi:type="arc" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
inkscape:original-d="m 3.379651,1041.2974 2.0693612,8.7948 m 5.1734018,0 2.069363,-8.7948"
inkscape:path-effect="#path-effect3761-8"
id="path3759-1"
d="m 3.379651,1041.2974 2.0693612,8.7948 m 5.1734018,0 2.069363,-8.7948"
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
sodipodi:open="true"
sodipodi:end="3.1415927"
sodipodi:start="0"
d="m 520,252.36218 c 0,33.13709 -80.58875,60 -180,60 -99.41125,0 -180,-26.86291 -180,-60 0,0 0,0 0,0"
sodipodi:ry="60"
sodipodi:rx="180"
sodipodi:cy="252.36218"
sodipodi:cx="340"
id="path3757-2-9"
style="fill:none;stroke:#000000;stroke-width:69.22486115;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
sodipodi:type="arc"
transform="matrix(0.0143204,0,0,0.01457205,3.175878,1046.32)" />
</g>
<path
style="fill:#0000ff;fill-opacity:1;stroke:none"
d="m 3.1527235,1042.7275 c 0,0 1.0346817,4.1388 1.5520204,6.4668 1.3456112,1.113 3.7701452,1.0024 5.173404,0 0.5173421,-2.328 1.5520201,-6.4668 1.5520201,-6.4668"
id="path3822"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
transform="matrix(0.02383471,0,0,0.02383471,-0.81511342,1036.4749)"
sodipodi:type="arc"
style="fill:#0080ff;fill-opacity:1;stroke:none"
id="path3757-25"
sodipodi:cx="340"
sodipodi:cy="252.36218"
sodipodi:rx="180"
sodipodi:ry="60"
d="m 520,252.36218 a 180,60 0 1 1 -360,0 180,60 0 1 1 360,0 z" />
<path
sodipodi:type="arc"
style="fill:none;stroke:#ffffff;stroke-width:38.65926743;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="path3757"
sodipodi:cx="340"
sodipodi:cy="252.36218"
sodipodi:rx="180"
sodipodi:ry="60"
d="m 520,252.36218 a 180,60 0 1 1 -360,0 180,60 0 1 1 360,0 z"
transform="matrix(0.02586702,0,0,0.02586702,-1.6068063,1033.8716)" />
<path
style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 2.5319162,1040.3995 2.0693612,8.7948 m 5.1734015,0 2.0693631,-8.7948"
id="path3759"
inkscape:path-effect="#path-effect3761"
inkscape:original-d="m 2.5319162,1040.3995 2.0693612,8.7948 m 5.1734015,0 2.0693631,-8.7948"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
transform="matrix(0.0143204,0,0,0.01457205,2.3281432,1045.4221)"
sodipodi:type="arc"
style="fill:none;stroke:#ffffff;stroke-width:69.22486115;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="path3757-2"
sodipodi:cx="340"
sodipodi:cy="252.36218"
sodipodi:rx="180"
sodipodi:ry="60"
d="m 520,252.36218 a 180,60 0 1 1 -360,0"
sodipodi:start="0"
sodipodi:end="3.1415927"
sodipodi:open="true" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

View file

@ -0,0 +1,167 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="cup_100.svg"
inkscape:export-filename="/home/ben/progs/minetest/minetest-thirsty/textures/thirsty_cup_100_16.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4">
<inkscape:path-effect
effect="spiro"
id="path-effect3824"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3820"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761-8"
is_visible="true" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#838181"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="5.2747873"
inkscape:cy="10.523682"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1366"
inkscape:window-height="744"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:snap-global="false">
<inkscape:grid
type="xygrid"
id="grid3755"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<g
id="g3901"
transform="translate(-0.06313453,-0.2841054)">
<path
transform="matrix(0.02586702,0,0,0.02586702,-0.759071,1034.7695)"
d="m 520,252.36218 c 0,33.13709 -80.58875,60 -180,60 -99.41125,0 -180,-26.86291 -180,-60 0,-33.13708 80.58875,-60 180,-60 99.41125,0 180,26.86292 180,60 z"
sodipodi:ry="60"
sodipodi:rx="180"
sodipodi:cy="252.36218"
sodipodi:cx="340"
id="path3757-7"
style="fill:none;stroke:#000000;stroke-width:38.65926743;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
sodipodi:type="arc" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
inkscape:original-d="m 3.379651,1041.2974 2.0693612,8.7948 m 5.1734018,0 2.069363,-8.7948"
inkscape:path-effect="#path-effect3761-8"
id="path3759-1"
d="m 3.379651,1041.2974 2.0693612,8.7948 m 5.1734018,0 2.069363,-8.7948"
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
sodipodi:open="true"
sodipodi:end="3.1415927"
sodipodi:start="0"
d="m 520,252.36218 c 0,33.13709 -80.58875,60 -180,60 -99.41125,0 -180,-26.86291 -180,-60 0,0 0,0 0,0"
sodipodi:ry="60"
sodipodi:rx="180"
sodipodi:cy="252.36218"
sodipodi:cx="340"
id="path3757-2-9"
style="fill:none;stroke:#000000;stroke-width:69.22486115;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
sodipodi:type="arc"
transform="matrix(0.0143204,0,0,0.01457205,3.175878,1046.32)" />
</g>
<path
style="fill:#0000ff;fill-opacity:1;stroke:none"
d="m 3.689367,1045.095 c 0,0 0.4980382,1.7713 1.0153769,4.0993 1.3456112,1.113 3.7701452,1.0024 5.173404,0 0.5173421,-2.328 0.8891071,-3.973 0.8891071,-3.973"
id="path3822"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
transform="matrix(0.01909962,0,0,0.01909962,0.73168267,1040.2584)"
sodipodi:type="arc"
style="fill:#0080ff;fill-opacity:1;stroke:none"
id="path3757-25"
sodipodi:cx="340"
sodipodi:cy="252.36218"
sodipodi:rx="180"
sodipodi:ry="60"
d="m 520,252.36218 a 180,60 0 1 1 -360,0 180,60 0 1 1 360,0 z" />
<path
sodipodi:type="arc"
style="fill:none;stroke:#ffffff;stroke-width:38.65926743;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="path3757"
sodipodi:cx="340"
sodipodi:cy="252.36218"
sodipodi:rx="180"
sodipodi:ry="60"
d="m 520,252.36218 a 180,60 0 1 1 -360,0 180,60 0 1 1 360,0 z"
transform="matrix(0.02586702,0,0,0.02586702,-1.6068063,1033.8716)" />
<path
style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 2.5319162,1040.3995 2.0693612,8.7948 m 5.1734015,0 2.0693631,-8.7948"
id="path3759"
inkscape:path-effect="#path-effect3761"
inkscape:original-d="m 2.5319162,1040.3995 2.0693612,8.7948 m 5.1734015,0 2.0693631,-8.7948"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
transform="matrix(0.0143204,0,0,0.01457205,2.3281432,1045.4221)"
sodipodi:type="arc"
style="fill:none;stroke:#ffffff;stroke-width:69.22486115;stroke-linecap:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
id="path3757-2"
sodipodi:cx="340"
sodipodi:cy="252.36218"
sodipodi:rx="180"
sodipodi:ry="60"
d="m 520,252.36218 a 180,60 0 1 1 -360,0"
sodipodi:start="0"
sodipodi:end="3.1415927"
sodipodi:open="true" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.2 KiB

View file

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="birdbath_side.svg"
inkscape:export-filename="/home/ben/progs/minetest/minetest-thirsty/textures/thirsty_birdbath_side.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4">
<inkscape:path-effect
effect="spiro"
id="path-effect3824"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3820"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761-8"
is_visible="true" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#838181"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="9.7439934"
inkscape:cy="7.3273732"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1366"
inkscape:window-height="744"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:snap-global="true"
inkscape:snap-bbox="true">
<inkscape:grid
type="xygrid"
id="grid3755"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<rect
style="fill:#b9b9b9;fill-opacity:1;stroke:none"
id="rect3861-5"
width="16"
height="15.999983"
x="0"
y="1036.3622" />
<rect
style="fill:#878787;fill-opacity:1;stroke:none"
id="rect3861-5-7"
width="14"
height="14.000017"
x="1"
y="1037.3622" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="drinkfount_side.svg"
inkscape:export-filename="/home/ben/progs/minetest/minetest-thirsty/textures/thirsty_drinkfount_side.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4">
<inkscape:path-effect
effect="spiro"
id="path-effect3824"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3820"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761-8"
is_visible="true" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#838181"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="9.7124262"
inkscape:cy="9.316111"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1366"
inkscape:window-height="744"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:snap-global="true"
inkscape:snap-bbox="true">
<inkscape:grid
type="xygrid"
id="grid3755"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none"
id="rect3015"
width="16"
height="16"
x="0"
y="0"
transform="translate(0,1036.3622)" />
<rect
style="fill:#b9b9b9;fill-opacity:1;stroke:none"
id="rect3861"
width="16"
height="1.0000174"
x="0"
y="1040.3622" />
<rect
style="fill:#b9b9b9;fill-opacity:1;stroke:none"
id="rect3861-5-5"
width="1"
height="11.000017"
x="6"
y="1041.3622" />
<rect
style="fill:#b9b9b9;fill-opacity:1;stroke:none"
id="rect3861-5-5-0"
width="1"
height="11.000017"
x="9"
y="1041.3622" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="birdbath_top.svg"
inkscape:export-filename="/home/ben/progs/minetest/minetest-thirsty/textures/thirsty_birdbath_top.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4">
<inkscape:path-effect
effect="spiro"
id="path-effect3824"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3820"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761-8"
is_visible="true" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#838181"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="7.3448812"
inkscape:cy="8.5584966"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1366"
inkscape:window-height="744"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid3755"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none"
id="rect3015"
width="16"
height="16"
x="0"
y="0"
transform="translate(0,1036.3622)" />
<rect
style="fill:#c5c5c5;fill-opacity:1;stroke:none"
id="rect3785-8"
width="13.988738"
height="13.95717"
x="1"
y="1037.3723" />
<rect
style="fill:#0063c8;fill-opacity:1;stroke:none"
id="rect3785"
width="12"
height="12"
x="2.0315673"
y="1038.3622" />
<rect
style="fill:#0681ff;fill-opacity:1;stroke:none"
id="rect3785-9"
width="10.04283"
height="10.04283"
x="2.9988904"
y="1039.3081" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="extractor.svg"
inkscape:export-filename="/home/ben/progs/minetest/minetest-thirsty/textures/thirsty_birdbath_top.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4">
<inkscape:path-effect
effect="spiro"
id="path-effect3012"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3824"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3820"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761-8"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3012-7"
is_visible="true" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#838181"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="5.9243542"
inkscape:cy="7.3905077"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1366"
inkscape:window-height="744"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:snap-global="true"
inkscape:snap-bbox="true"
inkscape:snap-bbox-midpoints="false">
<inkscape:grid
type="xygrid"
id="grid3755"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<path
style="fill:#ffff03;fill-opacity:1;stroke:none"
d="m 6,1038.3622 -4,4 0,4 4,4 3.9999999,0 4.0000001,-4 0,-4 -4.0000001,-4 -3.9999999,0"
id="path3010-8"
inkscape:path-effect="#path-effect3012-7"
inkscape:original-d="m 6,1038.3622 -4,4 0,4 4,4 3.9999999,0 4.0000001,-4 0,-4 -4.0000001,-4 z"
inkscape:connector-curvature="0" />
<g
id="g3859">
<path
transform="translate(0,1036.3622)"
inkscape:connector-curvature="0"
id="path3803"
d="M 6,2 8,8 10,2 z"
style="fill:#00ffff;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3803-7"
d="m 2,1046.3622 6,-2 -6,-2 z"
style="fill:#00ffff;fill-opacity:1;stroke:none" />
<path
inkscape:connector-curvature="0"
id="path3803-7-4"
d="m 10,1050.3622 -2,-6 -2,6 z"
style="fill:#00ffff;fill-opacity:1;stroke:none" />
<path
inkscape:connector-curvature="0"
id="path3803-7-4-9"
d="m 14,1042.3622 -6,2 6,2 z"
style="fill:#00ffff;fill-opacity:1;stroke:none" />
</g>
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 6,2 -4,4 0,4 4,4 4,0 4,-4 0,-4 -4,-4 -4,0"
id="path3010"
inkscape:path-effect="#path-effect3012"
inkscape:original-d="m 6,2 -4,4 0,4 4,4 4,0 4,-4 0,-4 -4,-4 z"
inkscape:connector-curvature="0"
transform="translate(0,1036.3622)" />
<path
style="fill:#0000ff;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
d="M 7,6 6,7 6,9 7,10 9,10 10,9 10,7 9,6 z"
id="path3865"
inkscape:connector-curvature="0"
transform="translate(0,1036.3622)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

View file

@ -0,0 +1,141 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="extractor.svg"
inkscape:export-filename="/home/ben/progs/minetest/minetest-thirsty/textures/thirsty_extractor.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4">
<inkscape:path-effect
effect="spiro"
id="path-effect3012"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3824"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3820"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761-8"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3012-7"
is_visible="true" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#838181"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="5.9243542"
inkscape:cy="7.3905077"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1366"
inkscape:window-height="744"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:snap-global="true"
inkscape:snap-bbox="true"
inkscape:snap-bbox-midpoints="false">
<inkscape:grid
type="xygrid"
id="grid3755"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<path
style="fill:#00ffff;fill-opacity:1;stroke:none"
d="m 6,1038.3622 -4,4 0,4 4,4 3.9999999,0 4.0000001,-4 0,-4 -4.0000001,-4 -3.9999999,0"
id="path3010-8"
inkscape:path-effect="#path-effect3012-7"
inkscape:original-d="m 6,1038.3622 -4,4 0,4 4,4 3.9999999,0 4.0000001,-4 0,-4 -4.0000001,-4 z"
inkscape:connector-curvature="0" />
<g
id="g3859"
style="fill:#ffff00;fill-opacity:1">
<path
transform="translate(0,1036.3622)"
inkscape:connector-curvature="0"
id="path3803"
d="M 6,2 8,8 10,2 z"
style="fill:#ffff00;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" />
<path
inkscape:connector-curvature="0"
id="path3803-7"
d="m 2,1046.3622 6,-2 -6,-2 z"
style="fill:#ffff00;fill-opacity:1;stroke:none" />
<path
inkscape:connector-curvature="0"
id="path3803-7-4"
d="m 10,1050.3622 -2,-6 -2,6 z"
style="fill:#ffff00;fill-opacity:1;stroke:none" />
<path
inkscape:connector-curvature="0"
id="path3803-7-4-9"
d="m 14,1042.3622 -6,2 6,2 z"
style="fill:#ffff00;fill-opacity:1;stroke:none" />
</g>
<path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 6,2 -4,4 0,4 4,4 4,0 4,-4 0,-4 -4,-4 -4,0"
id="path3010"
inkscape:path-effect="#path-effect3012"
inkscape:original-d="m 6,2 -4,4 0,4 4,4 4,0 4,-4 0,-4 -4,-4 z"
inkscape:connector-curvature="0"
transform="translate(0,1036.3622)" />
<path
style="fill:#0000ff;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
d="M 7,6 6,7 6,9 7,10 9,10 10,9 10,7 9,6 z"
id="path3865"
inkscape:connector-curvature="0"
transform="translate(0,1036.3622)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View file

@ -0,0 +1,139 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="bronze_canteen.svg"
inkscape:export-filename="/home/ben/progs/minetest/minetest-thirsty/textures/thirsty_bowl_16.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4">
<inkscape:path-effect
effect="spiro"
id="path-effect3824"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3820"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761-8"
is_visible="true" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#838181"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="7.6921211"
inkscape:cy="7.4852095"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1366"
inkscape:window-height="744"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:snap-global="false">
<inkscape:grid
type="xygrid"
id="grid3755"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<g
id="g3784"
style="fill:#949494;fill-opacity:1">
<path
transform="translate(0,1037.3408)"
d="m 13.005714,8.0134811 a 5.0034118,4.987628 0 1 1 -10.0068236,0 5.0034118,4.987628 0 1 1 10.0068236,0 z"
sodipodi:ry="4.987628"
sodipodi:rx="5.0034118"
sodipodi:cy="8.0134811"
sodipodi:cx="8.0023022"
id="path3010"
style="fill:#949494;fill-opacity:1;stroke:none"
sodipodi:type="arc" />
<rect
transform="translate(0,1036.3622)"
y="2.0157008"
x="5.9977808"
height="1.0101526"
width="4.0090427"
id="rect3780"
style="fill:#949494;fill-opacity:1;stroke:none" />
<rect
transform="translate(0,1036.3622)"
y="3.0258534"
x="6.976366"
height="1.9887378"
width="2.0518723"
id="rect3782"
style="fill:#949494;fill-opacity:1;stroke:none" />
</g>
<rect
style="fill:#000000;fill-opacity:1;stroke:none"
id="rect3789"
width="2.0203052"
height="0.97858524"
x="7.0079331"
y="1.0371156"
transform="translate(0,1036.3622)" />
<rect
style="fill:#562f00;fill-opacity:1;stroke:none"
id="rect3791"
width="11.016976"
height="2.0203052"
x="562.01971"
y="876.90887"
transform="matrix(0.84395175,0.53641909,-0.53641909,0.84395175,0,0)" />
<rect
style="fill:#562f00;fill-opacity:1;stroke:none"
id="rect3791-4"
width="11.016976"
height="2.0203052"
x="548.4823"
y="885.47589"
transform="matrix(-0.84395175,0.53641909,0.53641909,0.84395175,0,0)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,244 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="waterextender_top.svg"
inkscape:export-filename="/home/ben/progs/minetest/minetest-thirsty/textures/thirsty_birdbath_top.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4">
<linearGradient
id="linearGradient3761">
<stop
style="stop-color:#aa4400;stop-opacity:1;"
offset="0"
id="stop3763" />
<stop
style="stop-color:#ffda2f;stop-opacity:1;"
offset="1"
id="stop3765" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect3824"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3820"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761-8"
is_visible="true" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3761"
id="linearGradient3767"
x1="7"
y1="8"
x2="9"
y2="8"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3761-6"
id="linearGradient3767-4"
x1="7"
y1="8"
x2="9"
y2="8"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3761-6">
<stop
style="stop-color:#aa4400;stop-opacity:1;"
offset="0"
id="stop3763-2" />
<stop
style="stop-color:#ffda2f;stop-opacity:1;"
offset="1"
id="stop3765-8" />
</linearGradient>
<linearGradient
gradientTransform="matrix(1,0,0,0.56397713,-4.9876282,1036.3611)"
y2="8"
x2="9"
y1="8"
x1="7"
gradientUnits="userSpaceOnUse"
id="linearGradient3809-6"
xlink:href="#linearGradient3761-6-2"
inkscape:collect="always" />
<linearGradient
id="linearGradient3761-6-2">
<stop
style="stop-color:#aa4400;stop-opacity:1;"
offset="0"
id="stop3763-2-2" />
<stop
style="stop-color:#ffda2f;stop-opacity:1;"
offset="1"
id="stop3765-8-9" />
</linearGradient>
<linearGradient
gradientTransform="matrix(1,0,0,0.56397713,-4.9876282,1036.3611)"
y2="8"
x2="9"
y1="8"
x1="7"
gradientUnits="userSpaceOnUse"
id="linearGradient3809-63"
xlink:href="#linearGradient3761-6-28"
inkscape:collect="always" />
<linearGradient
id="linearGradient3761-6-28">
<stop
style="stop-color:#aa4400;stop-opacity:1;"
offset="0"
id="stop3763-2-4" />
<stop
style="stop-color:#ffda2f;stop-opacity:1;"
offset="1"
id="stop3765-8-0" />
</linearGradient>
<linearGradient
y2="8"
x2="9"
y1="8"
x1="7"
gradientTransform="matrix(9.0998777e-4,-0.99999959,0.5639769,5.1321229e-4,2.2813658,1052.4044)"
gradientUnits="userSpaceOnUse"
id="linearGradient3878"
xlink:href="#linearGradient3761-6-28"
inkscape:collect="always" />
<linearGradient
y2="8"
x2="9"
y1="8"
x1="7"
gradientTransform="matrix(9.0998777e-4,-0.99999959,0.5639769,5.1321229e-4,2.2813658,1052.4044)"
gradientUnits="userSpaceOnUse"
id="linearGradient3878-5"
xlink:href="#linearGradient3761-6-28-1"
inkscape:collect="always" />
<linearGradient
id="linearGradient3761-6-28-1">
<stop
style="stop-color:#aa4400;stop-opacity:1;"
offset="0"
id="stop3763-2-4-7" />
<stop
style="stop-color:#ffda2f;stop-opacity:1;"
offset="1"
id="stop3765-8-0-4" />
</linearGradient>
<linearGradient
y2="8"
x2="9"
y1="8"
x1="7"
gradientTransform="matrix(-9.0998777e-4,-0.99999959,-0.5639769,5.1321229e-4,13.707372,1052.3728)"
gradientUnits="userSpaceOnUse"
id="linearGradient3912"
xlink:href="#linearGradient3761-6-28-1"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3761-6-28-1-0"
id="linearGradient3958-0"
x1="1"
y1="13"
x2="5"
y2="13"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3761-6-28-1-0">
<stop
style="stop-color:#aa4400;stop-opacity:1;"
offset="0"
id="stop3763-2-4-7-4" />
<stop
style="stop-color:#ffda2f;stop-opacity:1;"
offset="1"
id="stop3765-8-0-4-5" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#838181"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="8.1024956"
inkscape:cy="8.1165549"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1366"
inkscape:window-height="744"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid3755"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<rect
style="fill:#6a5f55;fill-opacity:1;stroke:none"
id="rect3015"
width="16"
height="16.000017"
x="0"
y="1036.3622" />
<rect
style="fill:url(#linearGradient3767);fill-opacity:1;stroke:none"
id="rect3759"
width="2"
height="16"
x="7"
y="0"
transform="translate(0,1036.3622)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.8 KiB

View file

@ -0,0 +1,309 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="waterfountain_top.svg"
inkscape:export-filename="/home/ben/progs/minetest/minetest-thirsty/textures/thirsty_birdbath_top.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4">
<linearGradient
id="linearGradient3761">
<stop
style="stop-color:#aa4400;stop-opacity:1;"
offset="0"
id="stop3763" />
<stop
style="stop-color:#ffda2f;stop-opacity:1;"
offset="1"
id="stop3765" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect3824"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3820"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761-8"
is_visible="true" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3761"
id="linearGradient3767"
x1="7"
y1="8"
x2="9"
y2="8"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3761-6"
id="linearGradient3767-4"
x1="7"
y1="8"
x2="9"
y2="8"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3761-6">
<stop
style="stop-color:#aa4400;stop-opacity:1;"
offset="0"
id="stop3763-2" />
<stop
style="stop-color:#ffda2f;stop-opacity:1;"
offset="1"
id="stop3765-8" />
</linearGradient>
<linearGradient
gradientTransform="matrix(1,0,0,0.56397713,-4.9876282,1036.3611)"
y2="8"
x2="9"
y1="8"
x1="7"
gradientUnits="userSpaceOnUse"
id="linearGradient3809"
xlink:href="#linearGradient3761-6"
inkscape:collect="always" />
<linearGradient
gradientTransform="matrix(1,0,0,0.56397713,-4.9876282,1036.3611)"
y2="8"
x2="9"
y1="8"
x1="7"
gradientUnits="userSpaceOnUse"
id="linearGradient3809-6"
xlink:href="#linearGradient3761-6-2"
inkscape:collect="always" />
<linearGradient
id="linearGradient3761-6-2">
<stop
style="stop-color:#aa4400;stop-opacity:1;"
offset="0"
id="stop3763-2-2" />
<stop
style="stop-color:#ffda2f;stop-opacity:1;"
offset="1"
id="stop3765-8-9" />
</linearGradient>
<linearGradient
y2="8"
x2="9"
y1="8"
x1="7"
gradientTransform="matrix(1,0,0,0.56397713,4.9977807,1036.3498)"
gradientUnits="userSpaceOnUse"
id="linearGradient3844"
xlink:href="#linearGradient3761-6-2"
inkscape:collect="always" />
<linearGradient
gradientTransform="matrix(1,0,0,0.56397713,-4.9876282,1036.3611)"
y2="8"
x2="9"
y1="8"
x1="7"
gradientUnits="userSpaceOnUse"
id="linearGradient3809-63"
xlink:href="#linearGradient3761-6-28"
inkscape:collect="always" />
<linearGradient
id="linearGradient3761-6-28">
<stop
style="stop-color:#aa4400;stop-opacity:1;"
offset="0"
id="stop3763-2-4" />
<stop
style="stop-color:#ffda2f;stop-opacity:1;"
offset="1"
id="stop3765-8-0" />
</linearGradient>
<linearGradient
y2="8"
x2="9"
y1="8"
x1="7"
gradientTransform="matrix(9.0998777e-4,-0.99999959,0.5639769,5.1321229e-4,2.2813658,1052.4044)"
gradientUnits="userSpaceOnUse"
id="linearGradient3878"
xlink:href="#linearGradient3761-6-28"
inkscape:collect="always" />
<linearGradient
y2="8"
x2="9"
y1="8"
x1="7"
gradientTransform="matrix(9.0998777e-4,-0.99999959,0.5639769,5.1321229e-4,2.2813658,1052.4044)"
gradientUnits="userSpaceOnUse"
id="linearGradient3878-5"
xlink:href="#linearGradient3761-6-28-1"
inkscape:collect="always" />
<linearGradient
id="linearGradient3761-6-28-1">
<stop
style="stop-color:#aa4400;stop-opacity:1;"
offset="0"
id="stop3763-2-4-7" />
<stop
style="stop-color:#ffda2f;stop-opacity:1;"
offset="1"
id="stop3765-8-0-4" />
</linearGradient>
<linearGradient
y2="8"
x2="9"
y1="8"
x1="7"
gradientTransform="matrix(-9.0998777e-4,-0.99999959,-0.5639769,5.1321229e-4,13.707372,1052.3728)"
gradientUnits="userSpaceOnUse"
id="linearGradient3912"
xlink:href="#linearGradient3761-6-28-1"
inkscape:collect="always" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3761-6-28-1"
id="linearGradient3958"
x1="1"
y1="13"
x2="5"
y2="13"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3761-6-28-1-0"
id="linearGradient3958-0"
x1="1"
y1="13"
x2="5"
y2="13"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3761-6-28-1-0">
<stop
style="stop-color:#aa4400;stop-opacity:1;"
offset="0"
id="stop3763-2-4-7-4" />
<stop
style="stop-color:#ffda2f;stop-opacity:1;"
offset="1"
id="stop3765-8-0-4-5" />
</linearGradient>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#838181"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="8.1024956"
inkscape:cy="8.1165549"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1366"
inkscape:window-height="744"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid3755"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<rect
style="fill:#6a5f55;fill-opacity:1;stroke:none"
id="rect3015"
width="16"
height="16.000017"
x="0"
y="1036.3622" />
<rect
style="fill:url(#linearGradient3767);fill-opacity:1;stroke:none"
id="rect3759"
width="2"
height="16"
x="7"
y="0"
transform="translate(0,1036.3622)" />
<path
style="fill:url(#linearGradient3878);fill-opacity:1;stroke:none"
d="m 0,1045.3622 0,-2 7,0 0,2 z"
id="rect3759-4-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="fill:url(#linearGradient3912);fill-opacity:1;stroke:none"
d="m 16,1045.3622 0,-2 -7.0112622,-0.032 0,2 z"
id="rect3759-4-5-0"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<g
transform="translate(4.9988903,-5.0090429)"
id="g3996">
<path
transform="translate(0,1036.3622)"
d="m 5,13 c 0,1.104569 -0.8954305,2 -2,2 -1.1045695,0 -2,-0.895431 -2,-2 0,-1.104569 0.8954305,-2 2,-2 1.1045695,0 2,0.895431 2,2 z"
sodipodi:ry="2"
sodipodi:rx="2"
sodipodi:cy="13"
sodipodi:cx="3"
id="path3950"
style="fill:url(#linearGradient3958-0);fill-opacity:1;stroke:none"
sodipodi:type="arc" />
<path
transform="translate(0,1036.3622)"
d="m 4,13 c 0,0.552285 -0.4477153,1 -1,1 -0.5522847,0 -1,-0.447715 -1,-1 0,-0.552285 0.4477153,-1 1,-1 0.5522847,0 1,0.447715 1,1 z"
sodipodi:ry="1"
sodipodi:rx="1"
sodipodi:cy="13"
sodipodi:cx="3"
id="path3960"
style="fill:#000000;fill-opacity:1;stroke:none"
sodipodi:type="arc" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9 KiB

View file

@ -0,0 +1,268 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="16"
height="16"
id="svg2"
version="1.1"
inkscape:version="0.48.4 r9939"
sodipodi:docname="waterfountain.svg"
inkscape:export-filename="/home/ben/progs/minetest/minetest-thirsty/textures/thirsty_birdbath_top.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4">
<linearGradient
id="linearGradient3761">
<stop
style="stop-color:#aa4400;stop-opacity:1;"
offset="0"
id="stop3763" />
<stop
style="stop-color:#ffda2f;stop-opacity:1;"
offset="1"
id="stop3765" />
</linearGradient>
<inkscape:path-effect
effect="spiro"
id="path-effect3824"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3820"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761"
is_visible="true" />
<inkscape:path-effect
effect="spiro"
id="path-effect3761-8"
is_visible="true" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3761"
id="linearGradient3767"
x1="7"
y1="8"
x2="9"
y2="8"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3761-6"
id="linearGradient3767-4"
x1="7"
y1="8"
x2="9"
y2="8"
gradientUnits="userSpaceOnUse" />
<linearGradient
id="linearGradient3761-6">
<stop
style="stop-color:#aa4400;stop-opacity:1;"
offset="0"
id="stop3763-2" />
<stop
style="stop-color:#ffda2f;stop-opacity:1;"
offset="1"
id="stop3765-8" />
</linearGradient>
<linearGradient
gradientTransform="matrix(1,0,0,0.56397713,-4.9876282,1036.3611)"
y2="8"
x2="9"
y1="8"
x1="7"
gradientUnits="userSpaceOnUse"
id="linearGradient3809"
xlink:href="#linearGradient3761-6"
inkscape:collect="always" />
<linearGradient
gradientTransform="matrix(1,0,0,0.56397713,-4.9876282,1036.3611)"
y2="8"
x2="9"
y1="8"
x1="7"
gradientUnits="userSpaceOnUse"
id="linearGradient3809-6"
xlink:href="#linearGradient3761-6-2"
inkscape:collect="always" />
<linearGradient
id="linearGradient3761-6-2">
<stop
style="stop-color:#aa4400;stop-opacity:1;"
offset="0"
id="stop3763-2-2" />
<stop
style="stop-color:#ffda2f;stop-opacity:1;"
offset="1"
id="stop3765-8-9" />
</linearGradient>
<linearGradient
y2="8"
x2="9"
y1="8"
x1="7"
gradientTransform="matrix(1,0,0,0.56397713,4.9977807,1036.3498)"
gradientUnits="userSpaceOnUse"
id="linearGradient3844"
xlink:href="#linearGradient3761-6-2"
inkscape:collect="always" />
<linearGradient
gradientTransform="matrix(1,0,0,0.56397713,-4.9876282,1036.3611)"
y2="8"
x2="9"
y1="8"
x1="7"
gradientUnits="userSpaceOnUse"
id="linearGradient3809-63"
xlink:href="#linearGradient3761-6-28"
inkscape:collect="always" />
<linearGradient
id="linearGradient3761-6-28">
<stop
style="stop-color:#aa4400;stop-opacity:1;"
offset="0"
id="stop3763-2-4" />
<stop
style="stop-color:#ffda2f;stop-opacity:1;"
offset="1"
id="stop3765-8-0" />
</linearGradient>
<linearGradient
y2="8"
x2="9"
y1="8"
x1="7"
gradientTransform="matrix(9.0998777e-4,-0.99999959,0.5639769,5.1321229e-4,2.2813658,1052.4044)"
gradientUnits="userSpaceOnUse"
id="linearGradient3878"
xlink:href="#linearGradient3761-6-28"
inkscape:collect="always" />
<linearGradient
y2="8"
x2="9"
y1="8"
x1="7"
gradientTransform="matrix(9.0998777e-4,-0.99999959,0.5639769,5.1321229e-4,2.2813658,1052.4044)"
gradientUnits="userSpaceOnUse"
id="linearGradient3878-5"
xlink:href="#linearGradient3761-6-28-1"
inkscape:collect="always" />
<linearGradient
id="linearGradient3761-6-28-1">
<stop
style="stop-color:#aa4400;stop-opacity:1;"
offset="0"
id="stop3763-2-4-7" />
<stop
style="stop-color:#ffda2f;stop-opacity:1;"
offset="1"
id="stop3765-8-0-4" />
</linearGradient>
<linearGradient
y2="8"
x2="9"
y1="8"
x1="7"
gradientTransform="matrix(-9.0998777e-4,-0.99999959,-0.5639769,5.1321229e-4,13.707372,1052.3728)"
gradientUnits="userSpaceOnUse"
id="linearGradient3912"
xlink:href="#linearGradient3761-6-28-1"
inkscape:collect="always" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#838181"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="31.678384"
inkscape:cx="8.1024956"
inkscape:cy="8.1165549"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1366"
inkscape:window-height="744"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:snap-global="true">
<inkscape:grid
type="xygrid"
id="grid3755"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true" />
</sodipodi:namedview>
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-1036.3622)">
<rect
style="fill:#6a5f55;fill-opacity:1;stroke:none"
id="rect3015"
width="16"
height="16.000017"
x="0"
y="1036.3622" />
<rect
style="fill:url(#linearGradient3767);fill-opacity:1;stroke:none"
id="rect3759"
width="2"
height="16"
x="7"
y="0"
transform="translate(0,1036.3622)" />
<path
style="fill:url(#linearGradient3809);fill-opacity:1;stroke:none"
d="m 2.0123718,1036.3611 2,0 L 4,1043.3622 l -1.9876282,2.0225 z"
id="rect3759-4"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="fill:url(#linearGradient3844);fill-opacity:1;stroke:none"
d="m 12,1036.3622 2,0 0,9 -2,-2 z"
id="rect3759-4-4"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="fill:url(#linearGradient3878);fill-opacity:1;stroke:none"
d="m 2,1045.3622 2,-2 3,0 0,2 z"
id="rect3759-4-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
<path
style="fill:url(#linearGradient3912);fill-opacity:1;stroke:none"
d="m 13.988738,1045.3306 -2,-2 -3.0000002,0 0,2 z"
id="rect3759-4-5-0"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.7 KiB

File diff suppressed because it is too large Load diff

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

Some files were not shown because too many files have changed in this diff Show more