Update to 0.4.16

master
maikerumine 2017-07-05 00:36:40 -04:00
parent b15d16a7ae
commit 3ea00f4e6f
241 changed files with 12841 additions and 4712 deletions

View File

@ -101,56 +101,6 @@ function hunger.handle_node_actions(pos, oldnode, player, ext)
hunger.players[name].exhaus = exhaus
end
-- sprint settings
local enable_sprint = minetest.setting_getbool("sprint") ~= false
local enable_sprint_particles = minetest.setting_getbool("sprint_particles") ~= false
-- 3d armor support
local armor_mod = minetest.get_modpath("3d_armor")
-- Sets the sprint state of a player (false = stopped, true = sprinting)
function set_sprinting(name, sprinting)
if not hunger.players[name] then
return false
end
local player = minetest.get_player_by_name(name)
-- is 3d_armor active, then set to armor defaults
local def = {}
if armor_mod and armor and armor.def[name] then
def = armor.def[name]
end
def.speed = def.speed or 1
def.jump = def.jump or 1
def.gravity = def.gravity or 1
if sprinting == true then
player:set_physics_override({
speed = def.speed + SPRINT_SPEED,
jump = def.jump + SPRINT_JUMP,
gravity = def.gravity
})
--print ("Speed:", def.speed + SPRINT_SPEED, "Jump:", def.jump + SPRINT_JUMP, "Gravity:", def.gravity)
else
player:set_physics_override({
speed = def.speed,
jump = def.jump,
gravity = def.gravity
})
--print ("Speed:", def.speed, "Jump:", def.jump, "Gravity:", def.gravity)
end
return true
end
-- Time based hunger functions
local hunger_timer = 0
@ -169,61 +119,6 @@ local function hunger_globaltimer(dtime)
if controls.up or controls.down or controls.left or controls.right then
hunger.handle_node_actions(nil, nil, player)
end
if enable_sprint then
local name = player:get_player_name()
-- check if player should be sprinting (hunger must be over 6 points)
if player
and controls.aux1
and controls.up
and not minetest.check_player_privs(name, {fast = true})
and hunger.players[name].lvl > 6 then
set_sprinting(name, true)
-- create particles behind player when sprinting
if enable_sprint_particles then
local pos = player:getpos()
local node = minetest.get_node({
x = pos.x,
y = pos.y - 1,
z = pos.z
})
if node.name ~= "air" then
minetest.add_particlespawner({
time = 0.01,
amount = 5,
minpos = {x = pos.x - 0.25, y = pos.y + 0.1, z = pos.z - 0.25},
maxpos = {x = pos.x + 0.25, y = pos.y + 0.1, z = pos.z + 0.25},
minvel = {x = -0.5, y = 1, z = -0.5},
maxvel = {x = 0.5, y = 2, z = 0.5},
minacc = {x = 0, y = -5, z = 0},
maxacc = {x = 0, y = -12, z = 0},
minexptime = 0.25,
maxexptime = 0.5,
minsize = 0.5,
maxsize = 1.0,
vertical = false,
collisiondetection = false,
texture = "default_dirt.png",
})
end
end
-- Lower the player's hunger
update_hunger(player,
hunger.players[name].lvl - (SPRINT_DRAIN * HUNGER_MOVE_TICK))
else
set_sprinting(name, false)
end
end
end
action_timer = 0
end
@ -268,7 +163,6 @@ local function hunger_globaltimer(dtime)
end
end
if minetest.setting_getbool("enable_damage") then
minetest.register_globalstep(hunger_globaltimer)
end

View File

@ -0,0 +1,386 @@
-- read/write
function hunger.read(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
if tonumber(hgp) > HUNGER_MAX + 1 then
hgp = HUNGER_MAX + 1
end
return hgp - 1
end
function hunger.save(player)
local inv = player:get_inventory()
local name = player:get_player_name()
local value = hunger.players[name].lvl
if not inv or not value then
return nil
end
if value > HUNGER_MAX then
value = HUNGER_MAX
end
if value < 0 then
value = 0
end
inv:set_stack("hunger", 1, ItemStack({name = ":", count = value + 1}))
return true
end
function hunger.update_hunger(player, new_lvl)
local name = player:get_player_name() or nil
if not name then
return false
end
if minetest.setting_getbool("enable_damage") == false then
hunger.players[name] = 20
return
end
local lvl = hunger.players[name].lvl
if new_lvl then
lvl = new_lvl
end
if lvl > HUNGER_MAX then
lvl = HUNGER_MAX
end
hunger.players[name].lvl = lvl
if lvl > 20 then
lvl = 20
end
hud.change_item(player, "hunger", {number = lvl})
hunger.save(player)
end
local update_hunger = hunger.update_hunger
-- player-action based hunger changes
function hunger.handle_node_actions(pos, oldnode, player, ext)
if not player or not player:is_player() then
return
end
local name = player:get_player_name()
if not name or not hunger.players[name] then
return
end
local exhaus = hunger.players[name].exhaus
if not exhaus then
hunger.players[name].exhaus = 0
--return
end
local new = HUNGER_EXHAUST_PLACE
-- placenode event
if not ext then
new = HUNGER_EXHAUST_DIG
end
-- assume its send by action_timer(globalstep)
if not pos and not oldnode then
new = HUNGER_EXHAUST_MOVE
end
exhaus = exhaus + new
if exhaus > HUNGER_EXHAUST_LVL then
exhaus = 0
local h = tonumber(hunger.players[name].lvl)
if h > 0 then
update_hunger(player, h - 1)
end
end
hunger.players[name].exhaus = exhaus
end
-- sprint settings
local enable_sprint = minetest.setting_getbool("sprint") ~= false
local enable_sprint_particles = minetest.setting_getbool("sprint_particles") ~= false
-- 3d armor support
local armor_mod = minetest.get_modpath("3d_armor")
-- Sets the sprint state of a player (false = stopped, true = sprinting)
function set_sprinting(name, sprinting)
if not hunger.players[name] then
return false
end
local player = minetest.get_player_by_name(name)
-- is 3d_armor active, then set to armor defaults
local def = {}
if armor_mod and armor and armor.def[name] then
def = armor.def[name]
end
def.speed = def.speed or 1
def.jump = def.jump or 1
def.gravity = def.gravity or 1
if sprinting == true then
player:set_physics_override({
speed = def.speed + SPRINT_SPEED,
jump = def.jump + SPRINT_JUMP,
gravity = def.gravity
})
--print ("Speed:", def.speed + SPRINT_SPEED, "Jump:", def.jump + SPRINT_JUMP, "Gravity:", def.gravity)
else
player:set_physics_override({
speed = def.speed,
jump = def.jump,
gravity = def.gravity
})
--print ("Speed:", def.speed, "Jump:", def.jump, "Gravity:", def.gravity)
end
return true
end
-- Time based hunger functions
local hunger_timer = 0
local health_timer = 0
local action_timer = 0
local function hunger_globaltimer(dtime)
hunger_timer = hunger_timer + dtime
health_timer = health_timer + dtime
action_timer = action_timer + dtime
if action_timer > HUNGER_MOVE_TICK then
for _,player in ipairs(minetest.get_connected_players()) do
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
hunger.handle_node_actions(nil, nil, player)
end
if enable_sprint then
local name = player:get_player_name()
-- check if player should be sprinting (hunger must be over 6 points)
if player
and controls.aux1
and controls.up
and not minetest.check_player_privs(name, {fast = true})
and hunger.players[name].lvl > 6 then
set_sprinting(name, true)
-- create particles behind player when sprinting
if enable_sprint_particles then
local pos = player:getpos()
local node = minetest.get_node({
x = pos.x,
y = pos.y - 1,
z = pos.z
})
if node.name ~= "air" then
minetest.add_particlespawner({
time = 0.01,
amount = 5,
minpos = {x = pos.x - 0.25, y = pos.y + 0.1, z = pos.z - 0.25},
maxpos = {x = pos.x + 0.25, y = pos.y + 0.1, z = pos.z + 0.25},
minvel = {x = -0.5, y = 1, z = -0.5},
maxvel = {x = 0.5, y = 2, z = 0.5},
minacc = {x = 0, y = -5, z = 0},
maxacc = {x = 0, y = -12, z = 0},
minexptime = 0.25,
maxexptime = 0.5,
minsize = 0.5,
maxsize = 1.0,
vertical = false,
collisiondetection = false,
texture = "default_dirt.png",
})
end
end
-- Lower the player's hunger
update_hunger(player,
hunger.players[name].lvl - (SPRINT_DRAIN * HUNGER_MOVE_TICK))
else
set_sprinting(name, false)
end
end
end
action_timer = 0
end
-- lower saturation by 1 point after <HUNGER_TICK> second(s)
if hunger_timer > HUNGER_TICK then
for _,player in ipairs(minetest.get_connected_players()) do
local name = player:get_player_name()
local tab = hunger.players[name]
if tab then
local hunger = tab.lvl
if hunger > 0 then
update_hunger(player, hunger - 1)
end
end
end
hunger_timer = 0
end
-- heal or damage player, depending on saturation
if health_timer > HUNGER_HEALTH_TICK then
for _,player in ipairs(minetest.get_connected_players()) do
local name = player:get_player_name()
local tab = hunger.players[name]
if tab then
local air = player:get_breath() or 0
local hp = player:get_hp()
-- heal player by 1 hp if not dead and saturation is > 15 (of 30) player is not drowning
if tonumber(tab.lvl) > HUNGER_HEAL_LVL and hp > 0 and air > 0 then
player:set_hp(hp + HUNGER_HEAL)
end
-- or damage player by 1 hp if saturation is < 2 (of 30)
if tonumber(tab.lvl) < HUNGER_STARVE_LVL then
player:set_hp(hp - HUNGER_STARVE)
end
end
end
health_timer = 0
end
end
if minetest.setting_getbool("enable_damage") then
minetest.register_globalstep(hunger_globaltimer)
end
-- food functions
local food = hunger.food
function hunger.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
-- Poison player
local function poisenp(tick, time, time_left, player)
time_left = time_left + tick
if time_left < time then
minetest.after(tick, poisenp, tick, time, time_left, player)
else
hud.change_item(player, "hunger", {text = "hud_hunger_fg.png"})
end
local hp = player:get_hp() -1 or 0
if hp > 0 then
player:set_hp(hp)
end
end
-- wrapper for minetest.item_eat (this way we make sure other mods can't break this one)
local org_eat = core.do_item_eat
core.do_item_eat = function(hp_change, replace_with_item, itemstack, user, pointed_thing)
local old_itemstack = itemstack
itemstack = hunger.eat(hp_change, replace_with_item, itemstack, user, pointed_thing)
for _, callback in pairs(core.registered_on_item_eats) do
local result = callback(hp_change, replace_with_item, itemstack, user, pointed_thing, old_itemstack)
if result then
return result
end
end
return itemstack
end
function hunger.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
core.log("error", "Wrong on_use() definition for item '" .. item .. "'")
end
def.saturation = hp_change * 1.3
def.replace = replace_with_item
end
local func = hunger.item_eat(def.saturation, def.replace, def.poisen, def.healing, def.sound)
return func(itemstack, user, pointed_thing)
end
function hunger.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
return itemstack
end
local name = user:get_player_name()
if not hunger.players[name] then
return itemstack
end
local sat = tonumber(hunger.players[name].lvl or 0)
local hp = user:get_hp()
-- Saturation
if sat < HUNGER_MAX and hunger_change then
sat = sat + hunger_change
hunger.update_hunger(user, sat)
end
-- Healing
if hp < 20 and heal then
hp = hp + heal
if hp > 20 then
hp = 20
end
user:set_hp(hp)
end
-- Poison
if poisen then
hud.change_item(user, "hunger", {text = "hunger_statbar_poisen.png"})
poisenp(1.0, poisen, 0, user)
end
-- eating sound
sound = sound or "hunger_eat"
minetest.sound_play(sound, {to_player = name, gain = 0.7})
if replace_with_item then
if itemstack:is_empty() then
itemstack:add_item(replace_with_item)
else
local inv = user:get_inventory()
if inv:room_for_item("main", {name = replace_with_item}) then
inv:add_item("main", replace_with_item)
else
local pos = user:getpos()
pos.y = math.floor(pos.y + 0.5)
core.add_item(pos, replace_with_item)
end
end
end
return itemstack
end
end

View File

@ -0,0 +1,21 @@
Simple Fast Inventory
====================
![SFINV Screeny](https://cdn.pbrd.co/images/1yQhd1TI.png)
A cleaner, simpler, solution to having an advanced inventory in Minetest.
Written by rubenwardy.
License: MIT
See game_api.txt for this mod's API
License of source code and media files:
---------------------------------------
Copyright (C) 2016 rubenwardy <rubenwardy@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,170 @@
sfinv = {
pages = {},
pages_unordered = {},
contexts = {},
enabled = true
}
function sfinv.register_page(name, def)
assert(name, "Invalid sfinv page. Requires a name")
assert(def, "Invalid sfinv page. Requires a def[inition] table")
assert(def.get, "Invalid sfinv page. Def requires a get function.")
assert(not sfinv.pages[name], "Attempt to register already registered sfinv page " .. dump(name))
sfinv.pages[name] = def
def.name = name
table.insert(sfinv.pages_unordered, def)
end
function sfinv.override_page(name, def)
assert(name, "Invalid sfinv page override. Requires a name")
assert(def, "Invalid sfinv page override. Requires a def[inition] table")
local page = sfinv.pages[name]
assert(page, "Attempt to override sfinv page " .. dump(name) .. " which does not exist.")
for key, value in pairs(def) do
page[key] = value
end
end
function sfinv.get_nav_fs(player, context, nav, current_idx)
-- Only show tabs if there is more than one page
if #nav > 1 then
return "tabheader[0,0;tabs;" .. table.concat(nav, ",") .. ";" .. current_idx .. ";true;false]"
else
return ""
end
end
local theme_main = "bgcolor[#080808BB;true]" .. default.gui_bg ..
default.gui_bg_img
local theme_inv = default.gui_slots .. [[
list[current_player;main;0,4.7;8,1;]
list[current_player;main;0,5.85;8,3;8]
]]
function sfinv.make_formspec(player, context, content, show_inv, size)
local tmp = {
size or "size[8,8.6]",
theme_main,
sfinv.get_nav_fs(player, context, context.nav_titles, context.nav_idx),
content
}
if show_inv then
tmp[#tmp + 1] = theme_inv
end
return table.concat(tmp, "")
end
function sfinv.get_homepage_name(player)
return "sfinv:crafting"
end
function sfinv.get_formspec(player, context)
-- Generate navigation tabs
local nav = {}
local nav_ids = {}
local current_idx = 1
for i, pdef in pairs(sfinv.pages_unordered) do
if not pdef.is_in_nav or pdef:is_in_nav(player, context) then
nav[#nav + 1] = pdef.title
nav_ids[#nav_ids + 1] = pdef.name
if pdef.name == context.page then
current_idx = #nav_ids
end
end
end
context.nav = nav_ids
context.nav_titles = nav
context.nav_idx = current_idx
-- Generate formspec
local page = sfinv.pages[context.page] or sfinv.pages["404"]
if page then
return page:get(player, context)
else
local old_page = context.page
context.page = sfinv.get_homepage_name(player)
assert(sfinv.pages[context.page], "[sfinv] Invalid homepage")
minetest.log("warning", "[sfinv] Couldn't find " .. dump(old_page) .. " so using switching to homepage")
return sfinv.get_formspec(player, context)
end
end
function sfinv.get_or_create_context(player)
local name = player:get_player_name()
local context = sfinv.contexts[name]
if not context then
context = {
page = sfinv.get_homepage_name(player)
}
sfinv.contexts[name] = context
end
return context
end
function sfinv.set_context(player, context)
sfinv.contexts[player:get_player_name()] = context
end
function sfinv.set_player_inventory_formspec(player, context)
local fs = sfinv.get_formspec(player,
context or sfinv.get_or_create_context(player))
player:set_inventory_formspec(fs)
end
function sfinv.set_page(player, pagename)
local context = sfinv.get_or_create_context(player)
local oldpage = sfinv.pages[context.page]
if oldpage and oldpage.on_leave then
oldpage:on_leave(player, context)
end
context.page = pagename
local page = sfinv.pages[pagename]
if page.on_enter then
page:on_enter(player, context)
end
sfinv.set_player_inventory_formspec(player, context)
end
minetest.register_on_joinplayer(function(player)
if sfinv.enabled then
sfinv.set_player_inventory_formspec(player)
end
end)
minetest.register_on_leaveplayer(function(player)
sfinv.contexts[player:get_player_name()] = nil
end)
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname ~= "" or not sfinv.enabled then
return false
end
-- Get Context
local name = player:get_player_name()
local context = sfinv.contexts[name]
if not context then
sfinv.set_player_inventory_formspec(player)
return false
end
-- Was a tab selected?
if fields.tabs and context.nav then
local tid = tonumber(fields.tabs)
if tid and tid > 0 then
local id = context.nav[tid]
local page = sfinv.pages[id]
if id and page then
sfinv.set_page(player, id)
end
end
else
-- Pass event to page
local page = sfinv.pages[context.page]
if page and page.on_player_receive_fields then
return page:on_player_receive_fields(player, context, fields)
end
end
end)

View File

@ -0,0 +1,22 @@
dofile(minetest.get_modpath("sfinv") .. "/api.lua")
sfinv.register_page("sfinv:crafting", {
title = "Crafting",
get = function(self, player, context)
return sfinv.make_formspec(player, context, [[
list[current_player;craft;1.75,0.5;3,3;]
list[current_player;craftpreview;5.75,1.5;1,1;]
image[4.75,1.5;1,1;gui_furnace_arrow_bg.png^[transformR270]
listring[current_player;main]
listring[current_player;craft]
image[0,4.75;1,1;gui_hb_bg.png]
image[1,4.75;1,1;gui_hb_bg.png]
image[2,4.75;1,1;gui_hb_bg.png]
image[3,4.75;1,1;gui_hb_bg.png]
image[4,4.75;1,1;gui_hb_bg.png]
image[5,4.75;1,1;gui_hb_bg.png]
image[6,4.75;1,1;gui_hb_bg.png]
image[7,4.75;1,1;gui_hb_bg.png]
]], true)
end
})

View File

@ -1,121 +0,0 @@
Creative Commons Legal Code
CC0 1.0 Universal
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
HEREUNDER.
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator
and subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for
the purpose of contributing to a commons of creative, cultural and
scientific works ("Commons") that the public can reliably and without fear
of later claims of infringement build upon, modify, incorporate in other
works, reuse and redistribute as freely as possible in any form whatsoever
and for any purposes, including without limitation commercial purposes.
These owners may contribute to the Commons to promote the ideal of a free
culture and the further production of creative, cultural and scientific
works, or to gain reputation or greater distribution for their Work in
part through the use and efforts of others.
For these and/or other purposes and motivations, and without any
expectation of additional consideration or compensation, the person
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
is an owner of Copyright and Related Rights in the Work, voluntarily
elects to apply CC0 to the Work and publicly distribute the Work under its
terms, with knowledge of his or her Copyright and Related Rights in the
Work and the meaning and intended legal effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not
limited to, the following:
i. the right to reproduce, adapt, distribute, perform, display,
communicate, and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or
likeness depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data
in a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation
thereof, including any amended or successor version of such
directive); and
vii. other similar, equivalent or corresponding rights throughout the
world based on applicable law or treaty, and any national
implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention
of, applicable law, Affirmer hereby overtly, fully, permanently,
irrevocably and unconditionally waives, abandons, and surrenders all of
Affirmer's Copyright and Related Rights and associated claims and causes
of action, whether now known or unknown (including existing as well as
future claims and causes of action), in the Work (i) in all territories
worldwide, (ii) for the maximum duration provided by applicable law or
treaty (including future time extensions), (iii) in any current or future
medium and for any number of copies, and (iv) for any purpose whatsoever,
including without limitation commercial, advertising or promotional
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
member of the public at large and to the detriment of Affirmer's heirs and
successors, fully intending that such Waiver shall not be subject to
revocation, rescission, cancellation, termination, or any other legal or
equitable action to disrupt the quiet enjoyment of the Work by the public
as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason
be judged legally invalid or ineffective under applicable law, then the
Waiver shall be preserved to the maximum extent permitted taking into
account Affirmer's express Statement of Purpose. In addition, to the
extent the Waiver is so judged Affirmer hereby grants to each affected
person a royalty-free, non transferable, non sublicensable, non exclusive,
irrevocable and unconditional license to exercise Affirmer's Copyright and
Related Rights in the Work (i) in all territories worldwide, (ii) for the
maximum duration provided by applicable law or treaty (including future
time extensions), (iii) in any current or future medium and for any number
of copies, and (iv) for any purpose whatsoever, including without
limitation commercial, advertising or promotional purposes (the
"License"). The License shall be deemed effective as of the date CC0 was
applied by Affirmer to the Work. Should any part of the License for any
reason be judged legally invalid or ineffective under applicable law, such
partial invalidity or ineffectiveness shall not invalidate the remainder
of the License, and in such case Affirmer hereby affirms that he or she
will not (i) exercise any of his or her remaining Copyright and Related
Rights in the Work or (ii) assert any associated claims and causes of
action with respect to the Work, in either case contrary to Affirmer's
express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or
warranties of any kind concerning the Work, express, implied,
statutory or otherwise, including without limitation warranties of
title, merchantability, fitness for a particular purpose, non
infringement, or the absence of latent or other defects, accuracy, or
the present or absence of errors, whether or not discoverable, all to
the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without
limitation any person's Copyright and Related Rights in the Work.
Further, Affirmer disclaims responsibility for obtaining any necessary
consents, permissions or other rights required for any use of the
Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to
this CC0 or use of the Work.

View File

@ -1,23 +0,0 @@
Afk Kick mod for Minetest by GunshipPenguin
Kicks players after they are Afk for an amount of time. By default,
players are kicked after five minutes, although this can be configured.
Licence: CC0 (see COPYING file)
This mod can be configured by changing the variables declared in the
start of init.lua. The following is a brief explanation of each one.
MAX_INACTIVE_TIME (default 300)
Maximum amount of time that a player may remain AFK (in seconds)
before being kicked.
CHECK_INTERVAL (default 1)
Time between checks for inactivity (In seconds)
WARN_TIME (default 20)
Number of seconds remaining before being kicked that a player will
start to be warned via chat message.

View File

@ -1,65 +0,0 @@
--[[
Afk Kick mod for Minetest by GunshipPenguin
To the extent possible under law, the author(s)
have dedicated all copyright and related and neighboring rights
to this software to the public domain worldwide. This software is
distributed without any warranty.
]]
local MAX_INACTIVE_TIME = 11200
local CHECK_INTERVAL = 1
local WARN_TIME = 20
local players = {}
local checkTimer = 0
minetest.register_on_joinplayer(function(player)
local playerName = player:get_player_name()
players[playerName] = {
lastAction = minetest.get_gametime()
}
end)
minetest.register_on_leaveplayer(function(player)
local playerName = player:get_player_name()
players[playerName] = nil
end)
minetest.register_on_chat_message(function(playerName, message)
players[playerName]["lastAction"] = minetest.get_gametime()
end)
minetest.register_globalstep(function(dtime)
local currGameTime = minetest.get_gametime()
--Loop through each player in players
for playerName,_ in pairs(players) do
local player = minetest.get_player_by_name(playerName)
if player then
--Check for inactivity once every CHECK_INTERVAL seconds
checkTimer = checkTimer + dtime
if checkTimer > CHECK_INTERVAL then
checkTimer = 0
--Kick player if he/she has been inactive for longer than MAX_INACTIVE_TIME seconds
if players[playerName]["lastAction"] + MAX_INACTIVE_TIME < currGameTime then
minetest.kick_player(playerName, "Kicked for inactivity")
end
--Warn player if he/she has less than WARN_TIME seconds to move or be kicked
if players[playerName]["lastAction"] + MAX_INACTIVE_TIME - WARN_TIME < currGameTime then
minetest.chat_send_player(playerName, "Warning, you have " .. tostring(players[playerName]["lastAction"] + MAX_INACTIVE_TIME - currGameTime) .. " seconds to move or be kicked")
end
end
--Check if this player is doing an action
for _,keyPressed in pairs(player:get_player_control()) do
if keyPressed then
players[playerName]["lastAction"] = currGameTime
end
end
end
end
end)

View File

@ -1,5 +0,0 @@
basic_vote - simple voting for minetest
Start vote simply with chatcommand "vote". for vote to suceed at least 50% of connected players must vote and there must be more yes votes than no votes. Player with kick privs has a lot of vote pover.
- add custom votes easily by defining vote types and what voting does

View File

@ -1 +0,0 @@
anticheat?

View File

@ -1,348 +0,0 @@
-- basic vote by rnd, 2015
local basic_vote = {};
-- SETTINGS ----------------------------------------------------------------------
-- DEFINE VOTE TYPES
basic_vote.types = { -- [type] = { description , votes_needed , timeout, command, help_description}
[1] = {"ban %s for 2 minutes" , -3 , 30, "ban", "Ban player for 2 minutes"}, -- -3 means strictly more than 3 players need to vote ( so 4 or more)
[2] = {"remove interact of %s" , 0.5, 120, "remove_interact", "Remove 'interact' privilege from player"}, -- 0.5 means at least 50% need to vote
[3] = {"give interact to %s" , 0.5 , 120, "give_interact", "Give 'interact' privilege to player"},
[4] = {"kill %s" , -3 , 30, "kill", "Kill player"},
[5] = {"poison %s" , -3 , 30, "poison", "Poison player"},
[6] = {"teleport %s to vote starter" , -3 , 30, "teleport", "Teleport player to you"},
[7] = {"change name color of %s",-2,30,"name color","Change name of player"},
[8] = {"mutelate %s",-2,30,"mutelate", "Mute and kill player when talking"},
[9] = {"unmutelate",-2,30,"unmutelate","Undo effects of mutelate"},
[10] = {"ask",1.0,30,"ask","put a question up for voting"}
};
basic_vote.modreq = 2; -- more that this number of moderators from "anticheat" mod must vote for mod to succeed
-- needed for poison vote
local vote_poison_state = {};
basic_vote_poison = function(name)
local player = minetest.get_player_by_name(name);
if not vote_poison_state[name] then
vote_poison_state[name] = 60;
end
vote_poison_state[name] = vote_poison_state[name] - 1;
if vote_poison_state[name]<=0 then
vote_poison_state[name] = nil; return;
end
if player then
if player:get_hp()>0 then
player:set_hp(player:get_hp()-4);
end
end
minetest.after(2, function() basic_vote_poison(name) end)
end
basic_vote.kicklist = {};
basic_vote.talklist = {};
basic_vote.huds = {};
-- for hud votes
local hud_definition =
{
hud_elem_type = "image",
scale = {x=-50,y=-50},
text = "default_stone.png",
size = { x=50, y=50 },
offset = { x=0, y=0},
}
-- DEFINE WHAT HAPPENS WHEN VOTE SUCCEEDS
basic_vote.execute = function(type, name, reason)
if type == 1 then
local ip = tostring(minetest.get_player_ip(name));
basic_vote.kicklist[ip] = minetest.get_gametime(); -- remembers start time
minetest.kick_player(name, reason)
elseif type == 2 then
local privs = core.get_player_privs(name);privs.interact = false
core.set_player_privs(name, privs); minetest.auth_reload()
elseif type == 3 then
local privs = core.get_player_privs(name);privs.interact = true;
core.set_player_privs(name, privs); minetest.auth_reload()
elseif type == 4 then
local player = minetest.get_player_by_name(name); if not player then return end
player:set_hp(0);
elseif type == 5 then
local player = minetest.get_player_by_name(name); if not player then return end
if not vote_poison_state[name] then
basic_vote_poison(name);
end
elseif type == 6 then
local player = minetest.get_player_by_name(name); if not player then return end
local vname = basic_vote.vote.voter; local vplayer = minetest.get_player_by_name(vname);
if not vplayer then return end
player:setpos(vplayer:getpos());
elseif type == 7 then
local player = minetest.get_player_by_name(name); if not player then return end
player:set_nametag_attributes({color = basic_vote.vote.reason});
elseif type == 8 then
local player = minetest.get_player_by_name(name); if not player then return end
basic_vote.talklist[name]=1;
elseif type == 9 then
local player = minetest.get_player_by_name(name); if not player then return end
basic_vote.talklist[name]=nil;
elseif type == 10 then
--basic_vote.huds[name]=player:hud_add(hud_definition);
end
end
-- for ban vote
minetest.register_on_prejoinplayer(
function(name, ip)
local name;
if basic_vote.kicklist[ip] then
local t = minetest.get_gametime();
t=t-basic_vote.kicklist[ip];
if t>120 then
basic_vote.kicklist[ip] = nil;
else
return "You have been temporarily banned from the server."
end
end
end
)
-- for talking votes
minetest.register_on_chat_message(
function(name, message)
if basic_vote.talklist[name] then
if basic_vote.talklist[name] == 1 then -- kill
local player = minetest.get_player_by_name(name);
if not player then return end
if not player:get_inventory():is_empty("main") then
local p = player:getpos();
p.x=math.floor(p.x);p.y=math.floor(p.y);p.z=math.floor(p.z);
minetest.chat_send_all("<" .. name .. "> please come get my bones at " .. minetest.pos_to_string(p))
end
player:set_hp(0);
return true
end
end
end
)
-- END OF SETTINGS ---------------------------------------------------------------
basic_vote.votes = 0; -- vote count
basic_vote.modscore = 0; -- how many moderators voted - need 3 for vote to succeed
basic_vote.voters = {}; -- who voted already
basic_vote.state = 0; -- 0 no vote, 1 vote in progress,2 timeout
basic_vote.vote = {time = 0,type = 0, name = "", reason = "", votes_needed = 0, timeout = 0, }; -- description of current vote
basic_vote.requirements = {[0]=0}
basic_vote.vote_desc=""
for i=1,#basic_vote.types do
basic_vote.vote_desc = basic_vote.vote_desc .. "Type " .. i .. " (" ..basic_vote.types[i][4].. "): ".. basic_vote.types[i][5].."\n"
end
local function get_description(vote)
local type_str = string.format(basic_vote.types[basic_vote.vote.type][1], basic_vote.vote.name)
local timeout = math.max(0, vote.timeout - os.difftime(os.time(), vote.time_start))
if vote.reason == nil or vote.reason == "" then
return string.format("## VOTE by %s to %s. Timeout in %ds.", vote.voter, type_str, timeout)
else
return string.format("## VOTE by %s to %s with reason: '%s'. Timeout in %ds.", vote.voter, type_str, vote.reason, timeout)
end
end
-- starts a new vote
minetest.register_chatcommand("vote", {
privs = {
interact = true
},
params = "[[<type> <name> [<reason>]] | types]",
description = "Start a vote. '/vote types' for a list of types, '/vote' without arguments to see current voting progress",
func = function(name, param)
if basic_vote.state~=0 then
minetest.chat_send_player(name,"Vote already in progress:")
minetest.chat_send_player(name,get_description(basic_vote.vote));
return
elseif param == "" then
minetest.chat_send_player(name,"No vote in progress.")
return
end
local player = minetest.get_player_by_name(name);
-- split string param into parameters
local paramt = string.split(param, " ")
for i = #paramt+1,3 do paramt[i]="" end
if paramt[1] == "types" then minetest.chat_send_player(name, basic_vote.vote_desc) return end
basic_vote.vote.time = minetest.get_gametime();
basic_vote.vote.type = tonumber(paramt[1]);
-- check for text-based types
-- if basic_vote.vote.type == nil then
-- for i=1,#basic_vote.types do
-- if paramt[1] == basic_vote.types[i][4] then
-- basic_vote.vote.type = i
-- end
-- end
-- end
if not basic_vote.types[basic_vote.vote.type] then
minetest.chat_send_player(name,"Error: Invalid syntax or type. Use '/help vote' for help.")
return
end
-- if not basic_vote.vote.type then minetest.chat_send_player(name,"Error: Invalid syntax or type. Use '/help vote' for help.") return end
basic_vote.vote.name=paramt[2] or "an unknown player";
basic_vote.vote.voter = name;
basic_vote.vote.reason = string.match(param, "%w+ [%w_-]+ (.+)")
basic_vote.vote.votes_needed = basic_vote.types[ basic_vote.vote.type ][2];
basic_vote.vote.timeout = basic_vote.types[ basic_vote.vote.type ][3];
basic_vote.vote.time_start = os.time();
--check if target valid player
if basic_vote.vote.name == "" then
minetest.chat_send_player(name,"Error: No player specified.")
return
elseif not minetest.get_player_by_name(basic_vote.vote.name) and basic_vote.vote.type~= 1 then
minetest.chat_send_player(name,"Error: The specified player is currently not connected.")
return
end
-- check anticheat db
local ip = tostring(minetest.get_player_ip(basic_vote.vote.name));
if anticheatdb and anticheatdb[ip] then -- #anticheat mod: makes detected cheater more succeptible to voting
if anticheatsettings.moderators[name] then -- moderator must call vote
basic_vote.vote.votes_needed=0; -- just need 1 vote
name = "an anonymous player"; -- so cheater does not see who voted - anonymous vote
end
end
basic_vote.votes = 0; basic_vote.modscore = 0; basic_vote.voters = {};
local type_str = string.format(basic_vote.types[basic_vote.vote.type][1], basic_vote.vote.name)
if basic_vote.vote.reason == nil or basic_vote.vote.reason == "" then
minetest.chat_send_all(string.format("## VOTE started (by %s to %s).\nSay '/y' to vote 'yes'. Timeout in %ds.", name, type_str, basic_vote.vote.timeout))
else
minetest.chat_send_all(string.format("## VOTE started (by %s to %s) with reason: '%s'.\nSay '/y' to vote 'yes'. Timeout in %ds.", name, type_str, basic_vote.vote.reason, basic_vote.vote.timeout))
end
basic_vote.state = 1; minetest.after(basic_vote.vote.timeout, function()
if basic_vote.state == 1 then basic_vote.state = 2;basic_vote.update(); end
end)
end
}
)
-- check if enough votes for vote to succeed or fail vote if timeout
basic_vote.update = function()
local players=minetest.get_connected_players();
local count = #players;
local votes_needed;
if basic_vote.vote.votes_needed>0 then
votes_needed = basic_vote.vote.votes_needed*count; -- percent of all players
if basic_vote.vote.votes_needed>=0.5 then -- more serious vote, to prevent ppl voting serious stuff with few players on server, at least 6 votes needed
if votes_needed<6 then votes_needed = 6 end
end
else
votes_needed = -basic_vote.vote.votes_needed; -- number instead
end
if basic_vote.state == 2 then -- timeout
minetest.chat_send_all("## VOTE failed. ".. basic_vote.votes .." voted (needed more than ".. votes_needed ..").");
basic_vote.state = 0;basic_vote.vote = {time = 0,type = 0, name = "", reason = ""}; return
end
if basic_vote.state~=1 then return end -- no vote in progress
-- check if enough votes
if basic_vote.modscore> basic_vote.modreq then -- enough moderators voted for vote to succeed
basic_vote.votes = votes_needed+1;
end
if basic_vote.votes>votes_needed then -- enough voters
minetest.chat_send_all("## VOTE succeded. "..basic_vote.votes .." voted.");
local type = basic_vote.vote.type;
basic_vote.execute(basic_vote.vote.type,basic_vote.vote.name, basic_vote.vote.reason)
basic_vote.state = 0;basic_vote.vote = {time = 0,type = 0, name = "", reason = ""};
end
end
local cast_vote = function (name,param)
if basic_vote.state~=1 then
-- vote not in progress
minetest.chat_send_player(name,"Error: No vote in progress.");
return
end
local ip = tostring(minetest.get_player_ip(name));
if basic_vote.voters[ip] then
minetest.chat_send_player(name,"Error: You already voted.");
return
else
-- mark as already voted
basic_vote.voters[ip]=true
end
basic_vote.votes = basic_vote.votes+1;
if anticheatsettings and anticheatsettings.moderators[name] then -- moderator from anticheat mod
basic_vote.modscore=basic_vote.modscore+1;
end
local privs = core.get_player_privs(name);if privs.kick then basic_vote.votes = 100; end
basic_vote.update(); minetest.chat_send_player(name,"Vote received.");
end
minetest.register_chatcommand("y", {
privs = {
interact = true
},
params = "",
description = "Vote 'Yes.' in the current vote (see vote command)",
func = function(name, param)
cast_vote(name,param)
end
}
)

View File

@ -65,7 +65,7 @@ messages.fire = {
" just got roasted, hotdog style.",
" got burned up. More light that way."
}
--[[
-- Other death messages
messages.other = {
" died.",
@ -77,7 +77,7 @@ messages.other = {
" is a rusher.",
" loves maikerumine's youtube channel!"
}
]]
function get_message(mtype)
if RANDOM_MESSAGES then
return messages[mtype][math.random(1, #messages[mtype])]
@ -107,7 +107,7 @@ minetest.register_on_dieplayer(function(player)
else
--minetest.chat_send_all(player_name .. get_message("other"))
end
player:setpos(death)
--player:setpos(death)
end)
--bigfoot code
-- bigfoot547's death messages

View File

@ -0,0 +1,21 @@
Lightning mod for minetest
Copyright (C) 2016 - Auke Kok <sofar@foo-projects.org>
"lightning" 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.
Textures: CC-BY-SA-4.0 by sofar
lightning_1.png
lightning_2.png
lightning_3.png
Sounds:
thunder.1.ogg - CC-BY-SA - hantorio - http://www.freesound.org/people/hantorio/sounds/121945/
thunder.2.ogg - CC-BY-SA - juskiddink - http://www.freesound.org/people/juskiddink/sounds/101948/
thunder.3.ogg - CC-BY-SA - IllusiaProductions - http://www.freesound.org/people/IllusiaProductions/sounds/249950/

View File

@ -0,0 +1,2 @@
default?
fire?

View File

@ -0,0 +1 @@
A mod that adds thunder and lightning effects.

View File

@ -0,0 +1,225 @@
--[[
Copyright (C) 2016 - Auke Kok <sofar@foo-projects.org>
"lightning" 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.
--]]
lightning = {}
lightning.interval_low = 17
lightning.interval_high = 503
lightning.range_h = 100
lightning.range_v = 50
lightning.size = 100
-- disable this to stop lightning mod from striking
lightning.auto = true
local rng = PcgRandom(32321123312123)
local ps = {}
local ttl = 1
local revertsky = function()
if ttl == 0 then
return
end
ttl = ttl - 1
if ttl > 0 then
return
end
for key, entry in pairs(ps) do
local sky = entry.sky
entry.p:set_sky(sky.bgcolor, sky.type, sky.textures)
end
ps = {}
end
minetest.register_globalstep(revertsky)
-- select a random strike point, midpoint
local function choose_pos(pos)
if not pos then
local playerlist = minetest.get_connected_players()
local playercount = table.getn(playerlist)
-- nobody on
if playercount == 0 then
return nil, nil
end
local r = rng:next(1, playercount)
local randomplayer = playerlist[r]
pos = randomplayer:getpos()
-- avoid striking underground
if pos.y < -20 then
return nil, nil
end
pos.x = math.floor(pos.x - (lightning.range_h / 2) + rng:next(1, lightning.range_h))
pos.y = pos.y + (lightning.range_v / 2)
pos.z = math.floor(pos.z - (lightning.range_h / 2) + rng:next(1, lightning.range_h))
end
local b, pos2 = minetest.line_of_sight(pos, {x = pos.x, y = pos.y - lightning.range_v, z = pos.z}, 1)
-- nothing but air found
if b then
return nil, nil
end
local n = minetest.get_node({x = pos2.x, y = pos2.y - 1/2, z = pos2.z})
if n.name == "air" or n.name == "ignore" then
return nil, nil
end
return pos, pos2
end
-- lightning strike API
-- * pos: optional, if not given a random pos will be chosen
-- * returns: bool - success if a strike happened
lightning.strike = function(pos)
if lightning.auto then
minetest.after(rng:next(lightning.interval_low, lightning.interval_high), lightning.strike)
end
local pos2
pos, pos2 = choose_pos(pos)
if not pos then
return false
end
minetest.add_particlespawner({
amount = 1,
time = 0.2,
-- make it hit the top of a block exactly with the bottom
minpos = {x = pos2.x, y = pos2.y + (lightning.size / 2) + 1/2, z = pos2.z },
maxpos = {x = pos2.x, y = pos2.y + (lightning.size / 2) + 1/2, z = pos2.z },
minvel = {x = 0, y = 0, z = 0},
maxvel = {x = 0, y = 0, z = 0},
minacc = {x = 0, y = 0, z = 0},
maxacc = {x = 0, y = 0, z = 0},
minexptime = 0.2,
maxexptime = 0.2,
minsize = lightning.size * 10,
maxsize = lightning.size * 10,
collisiondetection = true,
vertical = true,
-- to make it appear hitting the node that will get set on fire, make sure
-- to make the texture lightning bolt hit exactly in the middle of the
-- texture (e.g. 127/128 on a 256x wide texture)
texture = "lightning_lightning_" .. rng:next(1,3) .. ".png",
-- 0.4.15+
glow = 14,
})
minetest.sound_play({ pos = pos, name = "lightning_thunder", gain = 10, max_hear_distance = 500 })
-- damage nearby objects, player or not
for _, obj in ipairs(minetest.get_objects_inside_radius(pos, 5)) do
-- nil as param#1 is supposed to work, but core can't handle it.
obj:punch(obj, 1.0, {full_punch_interval = 1.0, damage_groups = {fleshy=8}}, nil)
end
local playerlist = minetest.get_connected_players()
for i = 1, #playerlist do
local player = playerlist[i]
local sky = {}
sky.bgcolor, sky.type, sky.textures = player:get_sky()
local name = player:get_player_name()
if ps[name] == nil then
ps[name] = {p = player, sky = sky}
player:set_sky(0xffffff, "plain", {})
end
end
-- trigger revert of skybox
ttl = 5
-- set the air node above it on fire
pos2.y = pos2.y + 1/2
if minetest.get_item_group(minetest.get_node({x = pos2.x, y = pos2.y - 1, z = pos2.z}).name, "liquid") < 1 then
if minetest.get_node(pos2).name == "air" then
-- only 1/4 of the time, something is changed
if rng:next(1,4) > 1 then
return
end
-- very rarely, potentially cause a fire
if fire and rng:next(1,1000) == 1 then
minetest.set_node(pos2, {name = "fire:basic_flame"})
else
minetest.set_node(pos2, {name = "lightning:dying_flame"})
end
end
end
-- perform block modifications
if not default or rng:next(1,10) > 1 then
return
end
pos2.y = pos2.y - 1
local n = minetest.get_node(pos2)
if minetest.get_item_group(n.name, "tree") > 0 then
minetest.set_node(pos2, { name = "default:coalblock"})
elseif minetest.get_item_group(n.name, "sand") > 0 then
minetest.set_node(pos2, { name = "default:glass"})
elseif minetest.get_item_group(n.name, "soil") > 0 then
minetest.set_node(pos2, { name = "default:gravel"})
end
end
-- a special fire node that doesn't burn anything, and automatically disappears
minetest.register_node("lightning:dying_flame", {
description = "Dying Flame",
drawtype = "firelike",
tiles = {
{
name = "fire_basic_flame_animated.png",
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 1
},
},
},
inventory_image = "fire_basic_flame.png",
paramtype = "light",
light_source = 14,
walkable = false,
buildable_to = true,
sunlight_propagates = true,
damage_per_second = 4,
groups = {dig_immediate = 3, not_in_creative_inventory=1},
on_timer = function(pos)
minetest.remove_node(pos)
end,
drop = "",
on_construct = function(pos)
minetest.get_node_timer(pos):start(rng:next(20, 40))
if fire and fire.on_flame_add_at then
minetest.after(0.5, fire.on_flame_add_at, pos)
end
end,
})
-- if other mods disable auto lightning during initialization, don't trigger the first lightning.
minetest.after(5, function(dtime)
if lightning.auto then
minetest.after(rng:next(lightning.interval_low,
lightning.interval_high), lightning.strike)
end
end)

View File

@ -0,0 +1 @@
name = lightning

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -1,119 +0,0 @@
minetest.register_privilege("whois", {
description = "Allows player to see other player IPs"})
-- Created by Krock to stop mass-account-creators
-- License: WTFPL
ipnames = {}
ipnames.data = {}
ipnames.tmp_data = {}
ipnames.changes = false
ipnames.save_interval = 120
ipnames.save_time = 0
ipnames.file = minetest.get_worldpath().."/ipnames.txt"
ipnames.name_per_ip_limit = tonumber(minetest.setting_get("max_names_per_ip")) or 4
-- Get accounts self:
minetest.register_chatcommand("whois", {
description = "Gets all players who have the same IP as the specified player",
privs = {whois = true},
func = function(name, param)
if not ipnames.data[param] then
minetest.chat_send_player(name, "The player \"" .. param .. "\" did not join yet.")
return
end
local ip = ipnames.data[param]
local names = "";
for k, v in pairs(ipnames.data) do
if v == ip then
if names ~= "" then
names = names .. ", " .. k
else
names = names .. " " .. k
end
end
end
minetest.chat_send_player(name, "Players for IP address " .. ip .. ": " .. names)
end,
})
-- Get IP if player tries to join, ban if there are too much names per IP:
minetest.register_on_prejoinplayer(function(name, ip)
-- Only stop new accounts:
ipnames.tmp_data[name] = ip
if not ipnames.data[name] then
local count = 1
local names = ""
for k, v in pairs(ipnames.data) do
if v == ip then
count = count + 1
names = names .. k .. ", "
end
end
if count <= ipnames.name_per_ip_limit and count > 1 then
minetest.log("action", name .. " now has " .. count .. " accounts. Other accounts: " .. names)
end
if count > ipnames.name_per_ip_limit then
ipnames.tmp_data[name] = nil
if tostring(ip) ~= "127.0.0.1" then
return ("\nYou exceeded the limit of accounts (" .. ipnames.name_per_ip_limit ..
").\nYou already have the following accounts:\n" .. names)
end
end
end
end)
-- Save IP if player joined:
minetest.register_on_joinplayer(function(player)
local name = player:get_player_name()
ipnames.data[name] = ipnames.tmp_data[name]
ipnames.tmp_data[name] = nil
ipnames.changes = true
end)
function ipnames.load_data()
local file = io.open(ipnames.file, "r")
if not file then
return
end
for line in file:lines() do
if line ~= "" then
local data = line:split("|")
if #data >= 2 then
ipnames.data[data[1]] = data[2]
end
end
end
io.close(file)
end
function ipnames.save_data()
if not ipnames.changes then
return
end
ipnames.changes = false
local file = io.open(ipnames.file, "w")
for i, v in pairs(ipnames.data) do
if v ~= nil then
file:write(i .. "|" .. v .. "\n")
end
end
io.close(file)
end
minetest.register_globalstep(function(t)
ipnames.save_time = ipnames.save_time + t
if ipnames.save_time < ipnames.save_interval then
return
end
ipnames.save_time = 0
ipnames.save_data()
end)
minetest.register_on_shutdown(function() ipnames.save_data() end)
minetest.after(3, function() ipnames.load_data() end)

View File

@ -0,0 +1,4 @@
*~
.settings/*
.project
.buildpath

View File

@ -0,0 +1,47 @@
weather-pack
=======================
Weather mod for Minetest (http://minetest.net/)
Weathers included
-----------------------
* rain
* snow
* thunder
Commands
-----------------------
`set_weather <weather>` requires `weather_manager` privilege.
Dependencies
-----------------------
Thunder weather requres [lightning](https://github.com/minetest-mods/lightning) mod.
Configuration properties
-----------------------
Weather mod for indoor check depends on sunlight propogation check. Some nodes (e.g. glass block) propogates sunlight and thus weather particles will go through it. To change that set `weather_allow_override_nodes=true` in `minetest.conf` file. Be aware that just few nodes will be override and these blocks needs to be re-builded to take effect. Maybe in future other 'cheap' way to check indoor will be available.
Weather mod mostly relies on particles generation however for some small things ABM may be used. Users which do not want it can disable ABM with property `weather_allow_abm=false`.
License of source code:
-----------------------
LGPL 2.1+
Authors of media files:
-----------------------
TeddyDesTodes:
Snowflakes licensed under CC-BY-SA 3.0 by from weather branch at https://github.com/TeddyDesTodes/minetest/tree/weather
* `weather_pack_snow_snowflake1.png` - CC-BY-SA 3.0
* `weather_pack_snow_snowflake2.png` - CC-BY-SA 3.0
xeranas:
* `weather_pack_rain_raindrop_1.png` - CC-0
* `weather_pack_rain_raindrop_2.png` - CC-0
* `weather_pack_rain_raindrop_3.png` - CC-0
inchadney (http://freesound.org/people/inchadney/):
* `weather_rain.ogg` - CC-BY-SA 3.0 (cut from http://freesound.org/people/inchadney/sounds/58835/)

View File

@ -0,0 +1 @@
lightning?

View File

@ -0,0 +1 @@
Set of weathers for minetest.

View File

@ -0,0 +1,13 @@
local modpath = minetest.get_modpath("weather_pack");
dofile(modpath.."/weather_core.lua")
dofile(modpath.."/snow.lua")
dofile(modpath.."/rain.lua")
if minetest.get_modpath("lightning") ~= nil then
dofile(modpath.."/thunder.lua")
end
-- If not located then embeded skycolor mod version will be loaded.
if minetest.get_modpath("skycolor") == nil then
dofile(modpath.."/skycolor.lua")
end

View File

@ -0,0 +1 @@
name = weather_pack

View File

@ -0,0 +1,186 @@
rain = {
-- max rain particles created at time
particles_count = 35,
-- flag to turn on/off extinguish fire for rain
extinguish_fire = true,
-- flag useful when mixing weathers
raining = false,
-- keeping last timeofday value (rounded).
-- Defaulted to non-existing value for initial comparing.
sky_last_update = -1,
init_done = false,
}
rain.sound_handler = function(player)
return minetest.sound_play("weather_rain", {
object = player,
max_hear_distance = 2,
loop = true,
})
end
-- set skybox based on time (uses skycolor api)
rain.set_sky_box = function()
skycolor.add_layer(
"weather-pack-rain-sky",
{{r=0, g=0, b=0},
{r=85, g=86, b=98},
{r=152, g=150, b=159},
{r=85, g=86, b=98},
{r=0, g=0, b=0}})
skycolor.active = true
end
-- creating manually parctiles instead of particles spawner because of easier to control
-- spawn position.
rain.add_rain_particles = function(player)
rain.last_rp_count = 0
for i=rain.particles_count, 1,-1 do
local random_pos_x, random_pos_y, random_pos_z = weather.get_random_pos_by_player_look_dir(player)
if minetest.get_node_light({x=random_pos_x, y=random_pos_y, z=random_pos_z}, 0.5) == 15 then
rain.last_rp_count = rain.last_rp_count + 1
minetest.add_particle({
pos = {x=random_pos_x, y=random_pos_y, z=random_pos_z},
velocity = {x=0, y=-10, z=0},
acceleration = {x=0, y=-30, z=0},
expirationtime = 0.2,
size = math.random(0.5, 3),
collisiondetection = true,
collision_removal = true,
vertical = true,
texture = rain.get_texture(),
playername = player:get_player_name()
})
end
end
end
-- Simple random texture getter
rain.get_texture = function()
local texture_name
local random_number = math.random()
if random_number > 0.33 then
texture_name = "weather_pack_rain_raindrop_1.png"
elseif random_number > 0.66 then
texture_name = "weather_pack_rain_raindrop_2.png"
else
texture_name = "weather_pack_rain_raindrop_3.png"
end
return texture_name;
end
-- register player for rain weather.
-- basically needs for origin sky reference and rain sound controls.
rain.add_player = function(player)
if weather.players[player:get_player_name()] == nil then
local player_meta = {}
player_meta.origin_sky = {player:get_sky()}
weather.players[player:get_player_name()] = player_meta
end
end
-- remove player from player list effected by rain.
-- be sure to remove sound before removing player otherwise soundhandler reference will be lost.
rain.remove_player = function(player)
local player_meta = weather.players[player:get_player_name()]
if player_meta ~= nil and player_meta.origin_sky ~= nil then
player:set_sky(player_meta.origin_sky[1], player_meta.origin_sky[2], player_meta.origin_sky[3])
weather.players[player:get_player_name()] = nil
end
end
-- adds and removes rain sound depending how much rain particles around player currently exist.
-- have few seconds delay before each check to avoid on/off sound too often
-- when player stay on 'edge' where sound should play and stop depending from random raindrop appearance.
rain.update_sound = function(player)
local player_meta = weather.players[player:get_player_name()]
if player_meta ~= nil then
if player_meta.sound_updated ~= nil and player_meta.sound_updated + 5 > os.time() then
return false
end
if player_meta.sound_handler ~= nil then
if rain.last_rp_count == 0 then
minetest.sound_stop(player_meta.sound_handler)
player_meta.sound_handler = nil
end
elseif rain.last_rp_count > 0 then
player_meta.sound_handler = rain.sound_handler(player)
end
player_meta.sound_updated = os.time()
end
end
-- rain sound removed from player.
rain.remove_sound = function(player)
local player_meta = weather.players[player:get_player_name()]
if player_meta ~= nil and player_meta.sound_handler ~= nil then
minetest.sound_stop(player_meta.sound_handler)
player_meta.sound_handler = nil
end
end
-- callback function for removing rain
rain.clear = function()
rain.raining = false
rain.sky_last_update = -1
rain.init_done = false
skycolor.remove_layer("weather-pack-rain-sky")
for _, player in ipairs(minetest.get_connected_players()) do
rain.remove_sound(player)
rain.remove_player(player)
end
end
minetest.register_globalstep(function(dtime)
if weather.state ~= "rain" then
return false
end
rain.make_weather()
end)
rain.make_weather = function()
if rain.init_done == false then
rain.raining = true
rain.set_sky_box()
end
for _, player in ipairs(minetest.get_connected_players()) do
if (weather.is_underwater(player)) then
return false
end
rain.add_player(player)
rain.add_rain_particles(player)
rain.update_sound(player)
end
end
if weather.reg_weathers.rain == nil then
weather.reg_weathers.rain = {
chance = 15,
clear = rain.clear
}
end
-- ABM for extinguish fire
if weather.allow_abm then
minetest.register_abm({
nodenames = {"fire:basic_flame"},
interval = 4.0,
chance = 2,
action = function(pos, node, active_object_count, active_object_count_wider)
if rain.raining and rain.extinguish_fire then
if weather.is_outdoor(pos) then
minetest.remove_node(pos)
end
end
end
})
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -0,0 +1,215 @@
skycolor = {
-- Should be activated before do any effect.
active = false,
-- To skip update interval
force_update = true,
-- Update interval.
update_interval = 15,
-- Main sky colors: starts from midnight to midnight.
-- Please do not set directly. Use add_layer instead.
colors = {},
-- min value which will be used in color gradient, usualy its first user given color in 'pure' color.
min_val = 0,
-- number of colors while constructing gradient of user given colors
max_val = 1000,
-- Enables smooth transition between existing sky color and target.
smooth_transitions = true,
-- Transition between current sky color and new user given.
transition_in_progress = false,
-- Transition colors are generated automaticly during initialization.
transition_colors = {},
-- Time where transition between current color and user given will be done
transition_time = 15,
-- Tracks how much time passed during transition
transition_timer = 0,
-- Table for tracking layer order
layer_names = {},
-- To layer to colors table
add_layer = function(layer_name, layer_color, instant_update)
skycolor.colors[layer_name] = layer_color
table.insert(skycolor.layer_names, layer_name)
if (instant_update ~= true) then
skycolor.init_transition()
end
skycolor.force_update = true
end,
-- Retrieve layer from colors table
retrieve_layer = function()
local last_layer = skycolor.layer_names[#skycolor.layer_names]
return skycolor.colors[last_layer]
end,
-- Remove layer from colors table
remove_layer = function(layer_name)
for k, name in ipairs(skycolor.layer_names) do
if name == layer_name then
table.remove(skycolor.layer_names, k)
skycolor.force_update = true
return
end
end
end,
-- Update sky color. If players not specified update sky for all players.
update_sky_color = function(players)
local color = skycolor.current_sky_layer_color()
if (color == nil) then
skycolor.active = false
skycolor.set_default_sky()
return
end
players = skycolor.utils.get_players(players)
for _, player in ipairs(players) do
player:set_sky(color, "plain", nil)
end
end,
-- Returns current layer color in {r, g, b} format
current_sky_layer_color = function()
if #skycolor.layer_names == 0 then
return nil
end
-- min timeofday value 0; max timeofday value 1. So sky color gradient range will be between 0 and 1 * skycolor.max_value.
local timeofday = minetest.get_timeofday()
local rounded_time = math.floor(timeofday * skycolor.max_val)
local color = skycolor.utils.convert_to_rgb(skycolor.min_val, skycolor.max_val, rounded_time, skycolor.retrieve_layer())
return color
end,
-- Initialy used only on
update_transition_sky_color = function()
if #skycolor.layer_names == 0 then
skycolor.active = false
skycolor.set_default_sky()
return
end
local multiplier = 100
local rounded_time = math.floor(skycolor.transition_timer * multiplier)
if rounded_time >= skycolor.transition_time * multiplier then
skycolor.stop_transition()
return
end
local color = skycolor.utils.convert_to_rgb(0, skycolor.transition_time * multiplier, rounded_time, skycolor.transition_colors)
local players = skycolor.utils.get_players(nil)
for _, player in ipairs(players) do
player:set_sky(color, "plain", nil)
end
end,
-- Reset sky color to game default. If players not specified update sky for all players.
-- Could be sometimes useful but not recomended to use in general case as there may be other color layers
-- which needs to preserve.
set_default_sky = function(players)
local players = skycolor.utils.get_players(players)
for _, player in ipairs(players) do
player:set_sky(nil, "regular", nil)
end
end,
init_transition = function()
-- sadly default sky returns unpredictible colors so transition mode becomes usable only for user defined color layers
-- Here '2' means that one color layer existed before new added and transition is posible.
if #skycolor.layer_names < 2 then
return
end
local transition_start_color = skycolor.utils.get_current_bg_color()
if (transition_start_color == nil) then
return
end
local transition_end_color = skycolor.current_sky_layer_color()
skycolor.transition_colors = {transition_start_color, transition_end_color}
skycolor.transition_in_progress = true
end,
stop_transition = function()
skycolor.transition_in_progress = false
skycolor.transition_colors = {}
skycolor.transition_timer = 0
end,
utils = {
convert_to_rgb = function(minval, maxval, current_val, colors)
local max_index = #colors - 1
local val = (current_val-minval) / (maxval-minval) * max_index + 1.0
local index1 = math.floor(val)
local index2 = math.min(math.floor(val)+1, max_index + 1)
local f = val - index1
local c1 = colors[index1]
local c2 = colors[index2]
return {r=math.floor(c1.r + f*(c2.r - c1.r)), g=math.floor(c1.g + f*(c2.g-c1.g)), b=math.floor(c1.b + f*(c2.b - c1.b))}
end,
-- Simply getter. Ether returns user given players list or get all connected players if none provided
get_players = function(players)
if players == nil or #players == 0 then
players = minetest.get_connected_players()
end
return players
end,
-- Returns first player sky color. I assume that all players are in same color layout.
get_current_bg_color = function()
local players = skycolor.utils.get_players(nil)
for _, player in ipairs(players) do
return player:get_sky()
end
return nil
end
},
}
--maikerumine turned this off to use skybox instead
--[[
local timer = 0
minetest.register_globalstep(function(dtime)
if skycolor.active ~= true or #minetest.get_connected_players() == 0 then
return
end
if skycolor.smooth_transitions and skycolor.transition_in_progress then
skycolor.transition_timer = skycolor.transition_timer + dtime
skycolor.update_transition_sky_color()
return
end
if skycolor.force_update then
skycolor.update_sky_color()
skycolor.force_update = false
return
end
-- regular updates based on iterval
timer = timer + dtime;
if timer >= skycolor.update_interval then
skycolor.update_sky_color()
timer = 0
end
end)
minetest.register_on_joinplayer(function(player)
if (skycolor.active) then
skycolor.update_sky_color({player})
end
end)
]]

View File

@ -0,0 +1,90 @@
snow = {}
snow.particles_count = 15
snow.init_done = false
-- calculates coordinates and draw particles for snow weather
snow.add_rain_particles = function(player)
rain.last_rp_count = 0
for i=snow.particles_count, 1,-1 do
local random_pos_x, random_pos_y, random_pos_z = weather.get_random_pos_by_player_look_dir(player)
random_pos_y = math.random() + math.random(player:getpos().y - 1, player:getpos().y + 7)
if minetest.get_node_light({x=random_pos_x, y=random_pos_y, z=random_pos_z}, 0.5) == 15 then
rain.last_rp_count = rain.last_rp_count + 1
minetest.add_particle({
pos = {x=random_pos_x, y=random_pos_y, z=random_pos_z},
velocity = {x = math.random(-1,-0.5), y = math.random(-2,-1), z = math.random(-1,-0.5)},
acceleration = {x = math.random(-1,-0.5), y=-0.5, z = math.random(-1,-0.5)},
expirationtime = 2.0,
size = math.random(0.5, 2),
collisiondetection = true,
collision_removal = true,
vertical = true,
texture = snow.get_texture(),
playername = player:get_player_name()
})
end
end
end
snow.set_sky_box = function()
skycolor.add_layer(
"weather-pack-snow-sky",
{{r=0, g=0, b=0},
{r=241, g=244, b=249},
{r=0, g=0, b=0}}
)
skycolor.active = true
end
snow.clear = function()
skycolor.remove_layer("weather-pack-snow-sky")
snow.init_done = false
end
-- Simple random texture getter
snow.get_texture = function()
local texture_name
local random_number = math.random()
if random_number > 0.5 then
texture_name = "weather_pack_snow_snowflake1.png"
else
texture_name = "weather_pack_snow_snowflake2.png"
end
return texture_name;
end
local timer = 0
minetest.register_globalstep(function(dtime)
if weather.state ~= "snow" then
return false
end
timer = timer + dtime;
if timer >= 0.5 then
timer = 0
else
return
end
if snow.init_done == false then
snow.set_sky_box()
snow.init_done = true
end
for _, player in ipairs(minetest.get_connected_players()) do
if (weather.is_underwater(player)) then
return false
end
snow.add_rain_particles(player)
end
end)
-- register snow weather
if weather.reg_weathers.snow == nil then
weather.reg_weathers.snow = {
chance = 10,
clear = snow.clear
}
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 B

View File

@ -0,0 +1,37 @@
-- turn off lightning mod 'auto mode'
lightning.auto = false
thunder = {
next_strike = 0,
min_delay = 3,
max_delay = 12,
}
minetest.register_globalstep(function(dtime)
if weather.state ~= "thunder" then
return false
end
rain.make_weather()
if (thunder.next_strike <= os.time()) then
lightning.strike()
local delay = math.random(thunder.min_delay, thunder.max_delay)
thunder.next_strike = os.time() + delay
end
end)
thunder.clear = function()
rain.clear()
end
-- register thunderstorm weather
if weather.reg_weathers.thunder == nil then
weather.reg_weathers.thunder = {
chance = 5,
clear = thunder.clear,
min_duration = 120,
max_duration = 600,
}
end

View File

@ -0,0 +1,175 @@
weather = {
-- weather states, 'none' is default, other states depends from active mods
state = "none",
-- player list for saving player meta info
players = {},
-- time when weather should be re-calculated
next_check = 0,
-- default weather recalculation interval
check_interval = 300,
-- weather min duration
min_duration = 240,
-- weather max duration
max_duration = 3600,
-- weather calculated end time
end_time = nil,
-- registered weathers
reg_weathers = {},
-- automaticly calculates intervals and swap weathers
auto_mode = true,
-- global flag to disable/enable ABM logic.
allow_abm = true,
}
weather.get_rand_end_time = function(min_duration, max_duration)
if min_duration ~= nil and max_duration ~= nil then
return os.time() + math.random(min_duration, max_duration);
else
return os.time() + math.random(weather.min_duration, weather.max_duration);
end
end
weather.is_outdoor = function(pos)
if minetest.get_node_light({x=pos.x, y=pos.y + 1, z=pos.z}, 0.5) == 15 then
return true
end
return false
end
-- checks if player is undewater. This is needed in order to
-- turn off weather particles generation.
weather.is_underwater = function(player)
local ppos = player:getpos()
local offset = player:get_eye_offset()
local player_eye_pos = {x = ppos.x + offset.x,
y = ppos.y + offset.y + 1.5,
z = ppos.z + offset.z}
local node_level = minetest.get_node_level(player_eye_pos)
if node_level == 8 or node_level == 7 then
return true
end
return false
end
-- trying to locate position for particles by player look direction for performance reason.
-- it is costly to generate many particles around player so goal is focus mainly on front view.
weather.get_random_pos_by_player_look_dir = function(player)
local look_dir = player:get_look_dir()
local player_pos = player:getpos()
local random_pos_x = 0
local random_pos_y = 0
local random_pos_z = 0
if look_dir.x > 0 then
if look_dir.z > 0 then
random_pos_x = math.random() + math.random(player_pos.x - 2.5, player_pos.x + 5)
random_pos_z = math.random() + math.random(player_pos.z - 2.5, player_pos.z + 5)
else
random_pos_x = math.random() + math.random(player_pos.x - 2.5, player_pos.x + 5)
random_pos_z = math.random() + math.random(player_pos.z - 5, player_pos.z + 2.5)
end
else
if look_dir.z > 0 then
random_pos_x = math.random() + math.random(player_pos.x - 5, player_pos.x + 2.5)
random_pos_z = math.random() + math.random(player_pos.z - 2.5, player_pos.z + 5)
else
random_pos_x = math.random() + math.random(player_pos.x - 5, player_pos.x + 2.5)
random_pos_z = math.random() + math.random(player_pos.z - 5, player_pos.z + 2.5)
end
end
random_pos_y = math.random() + math.random(player_pos.y + 1, player_pos.y + 3)
return random_pos_x, random_pos_y, random_pos_z
end
minetest.register_globalstep(function(dtime)
if weather.auto_mode == false then
return 0
end
-- recalculate weather only when there aren't currently any
if (weather.state ~= "none") then
if (weather.end_time ~= nil and weather.end_time <= os.time()) then
weather.reg_weathers[weather.state].clear()
weather.state = "none"
end
elseif (weather.next_check <= os.time()) then
for weather_name, weather_meta in pairs(weather.reg_weathers) do
weather.set_random_weather(weather_name, weather_meta)
end
-- fallback next_check set, weather 'none' will be.
weather.next_check = os.time() + weather.check_interval
end
end)
-- sets random weather (which could be 'regular' (no weather)).
weather.set_random_weather = function(weather_name, weather_meta)
if weather.next_check > os.time() then return 0 end
if (weather_meta ~= nil and weather_meta.chance ~= nil) then
local random_roll = math.random(0,100)
if (random_roll <= weather_meta.chance) then
weather.state = weather_name
weather.end_time = weather.get_rand_end_time(weather_meta.min_duration, weather_meta.max_duration)
weather.next_check = os.time() + weather.check_interval
end
end
end
minetest.register_privilege("weather_manager", {
description = "Gives ability to control weather",
give_to_singleplayer = false
})
-- Weather command definition. Set
minetest.register_chatcommand("set_weather", {
params = "<weather>",
description = "Changes weather by given param, parameter none will remove weather.",
privs = {weather_manager = true},
func = function(name, param)
if (param == "none") then
if (weather.state ~= nil and weather.reg_weathers[weather.state] ~= nil) then
weather.reg_weathers[weather.state].clear()
weather.state = param
end
weather.state = "none"
end
if (weather.reg_weathers ~= nil and weather.reg_weathers[param] ~= nil) then
if (weather.state ~= nil and weather.state ~= "none" and weather.reg_weathers[weather.state] ~= nil) then
weather.reg_weathers[weather.state].clear()
end
weather.state = param
end
end
})
-- Configuration setting which allows user to disable ABM for weathers (if they use it).
-- Weather mods expected to be use this flag before registering ABM.
local weather_allow_abm = minetest.setting_getbool("weather_allow_abm")
if weather_allow_abm ~= nil and weather_allow_abm == false then
weather.allow_abm = false
end
-- Overrides nodes 'sunlight_propagates' attribute for efficient indoor check (e.g. for glass roof).
-- Controlled from minetest.conf setting and by default it is disabled.
-- To enable set weather_allow_override_nodes to true.
-- Only new nodes will be effected (glass roof needs to be rebuilded).
if minetest.setting_getbool("weather_allow_override_nodes") then
if minetest.registered_nodes["default:glass"] then
minetest.override_item("default:glass", {sunlight_propagates = false})
end
if minetest.registered_nodes["default:meselamp"] then
minetest.override_item("default:meselamp", {sunlight_propagates = false})
end
end

View File

@ -24,6 +24,8 @@ minetest.register_alias("esmobs:nametag", "mobs:nametag")
minetest.register_alias("esmobs:leather", "mobs:leather")
minetest.register_alias("esmobs:meat_raw", "mobs:meat_raw")
minetest.register_alias("esmobs:meat", "mobs:meat")
minetest.register_alias("badplayer:meat", "mobs:meat")
minetest.register_alias("badplayer:meat_raw", "mobs:meat")
minetest.register_alias("esmobs:pork_raw", "mobs:pork_raw")
minetest.register_alias("esmobs:pork_cooked", "mobs:pork_cooked")
minetest.register_alias("esmobs:rat_cooked", "mobs:rat_cooked")
@ -45,6 +47,7 @@ minetest.register_alias("esmobs:cobweb", "mobs:cobweb")
minetest.register_alias("esmobs:spawner", "mobs:spawner")
minetest.register_alias("mobs:spawner", "es:boneblock")
minetest.register_alias("esmobs:bones", "mobs:bones")
minetest.register_alias("esmobs:fireball", "mobs:fireball")
minetest.register_alias("esmobs:arrow", "mobs:arrow")

View File

@ -13,8 +13,18 @@
--(c) Copyright (2014-2015) maikerumine; CC-BY-SA 3.0
minetest.register_alias("stairs:slab_Dirt", "stairs:slab_dirt")
minetest.register_alias("stairs:stair_Dirt", "stairs:stair_dirt")
minetest.register_alias("stairs:slab_Ruby", "stairs:slab_ruby")
minetest.register_alias("stairs:stair_Ruby", "stairs:stair_ruby")
minetest.register_alias("es:stair_dirt_with_grass", "stairs:stair_dirt")
minetest.register_alias("stairs:stair_granite", "stairs:stair_granite")
minetest.register_alias("stairs:stair_granitebricks", "stairs:stair_granite_bricks")
minetest.register_alias("stairs:stair_marble", "stairs:stair_marble")
minetest.register_alias("stairs:stair_marblebricks", "stairs:stair_marble_bricks")
es = {}
--need micro""_1

View File

@ -274,9 +274,10 @@ minetest.register_alias("technic:solar_panel", "es:aikerumblock")
minetest.register_alias("technic:marble", "es:marble")
minetest.register_alias("technic:granite", "es:granite")
minetest.register_alias("technic:marble_bricks", "es:marble_bricks")
--minetest.register_alias("technic:mineral_uranium", "es:depleted_uranium")
--minetest.register_alias("technic:mineral_chromium", "es:stone_with_aikerum")
--minetest.register_alias("technic:mineral_zinc", "es:stone_with_emerald")
minetest.register_alias("technic:granite_bricks", "es:granite_bricks")
minetest.register_alias("technic:mineral_uranium", "es:depleted_uraniums")
minetest.register_alias("technic:mineral_chromium", "es:stone_with_aikerums")
minetest.register_alias("technic:mineral_zinc", "es:stone_with_emeralds")
minetest.register_alias("technic:mineral_uranium", "es:depleted_coal")
minetest.register_alias("technic:mineral_chromium", "es:stone_with_coal")
minetest.register_alias("technic:mineral_zinc", "es:stone_with_coal")

22
mods/carts/README.txt Normal file
View File

@ -0,0 +1,22 @@
Carts (formerly boost_cart)
==========================
Carts, based almost entirely on the mod boost_cart [1], which
itself is based on (and fully compatible with) the carts mod [2].
The model was originally designed by stujones11 [3] (CC-0).
Cart textures are based on original work from PixelBOX (WTFPL).
[1] https://github.com/SmallJoker/boost_cart/
[2] https://github.com/PilzAdam/carts/
[3] https://github.com/stujones11/railcart/
Features
----------
- A fast cart for your railway or roller coaster (up to 7 m/s!)
- Boost and brake rails
- Rail junction switching with the 'right-left' walking keys
- Handbrake with the 'back' key

403
mods/carts/cart_entity.lua Normal file
View File

@ -0,0 +1,403 @@
local cart_entity = {
physical = false, -- otherwise going uphill breaks
collisionbox = {-0.5, -0.5, -0.5, 0.5, 0.5, 0.5},
visual = "mesh",
mesh = "carts_cart.b3d",
visual_size = {x=1, y=1},
textures = {"carts_cart.png"},
driver = nil,
punched = false, -- used to re-send velocity and position
velocity = {x=0, y=0, z=0}, -- only used on punch
old_dir = {x=1, y=0, z=0}, -- random value to start the cart on punch
old_pos = nil,
old_switch = 0,
railtype = nil,
attached_items = {}
}
function cart_entity:on_rightclick(clicker)
if not clicker or not clicker:is_player() then
return
end
local player_name = clicker:get_player_name()
if self.driver and player_name == self.driver then
self.driver = nil
carts:manage_attachment(clicker, nil)
elseif not self.driver then
self.driver = player_name
carts:manage_attachment(clicker, self.object)
end
end
function cart_entity:on_activate(staticdata, dtime_s)
self.object:set_armor_groups({immortal=1})
if string.sub(staticdata, 1, string.len("return")) ~= "return" then
return
end
local data = minetest.deserialize(staticdata)
if not data or type(data) ~= "table" then
return
end
self.railtype = data.railtype
if data.old_dir then
self.old_dir = data.old_dir
end
if data.old_vel then
self.old_vel = data.old_vel
end
end
function cart_entity:get_staticdata()
return minetest.serialize({
railtype = self.railtype,
old_dir = self.old_dir,
old_vel = self.old_vel
})
end
function cart_entity:on_punch(puncher, time_from_last_punch, tool_capabilities, direction)
local pos = self.object:getpos()
if not self.railtype then
local node = minetest.get_node(pos).name
self.railtype = minetest.get_item_group(node, "connect_to_raillike")
end
-- Punched by non-player
if not puncher or not puncher:is_player() then
local cart_dir = carts:get_rail_direction(pos, self.old_dir, nil, nil, self.railtype)
if vector.equals(cart_dir, {x=0, y=0, z=0}) then
return
end
self.velocity = vector.multiply(cart_dir, 2)
self.punched = true
return
end
-- Player digs cart by sneak-punch
if puncher:get_player_control().sneak then
if self.sound_handle then
minetest.sound_stop(self.sound_handle)
end
-- Detach driver and items
if self.driver then
if self.old_pos then
self.object:setpos(self.old_pos)
end
local player = minetest.get_player_by_name(self.driver)
carts:manage_attachment(player, nil)
end
for _,obj_ in ipairs(self.attached_items) do
if obj_ then
obj_:set_detach()
end
end
-- Pick up cart
local inv = puncher:get_inventory()
if not (creative and creative.is_enabled_for
and creative.is_enabled_for(puncher:get_player_name()))
or not inv:contains_item("main", "carts:cart") then
local leftover = inv:add_item("main", "carts:cart")
-- If no room in inventory add a replacement cart to the world
if not leftover:is_empty() then
minetest.add_item(self.object:getpos(), leftover)
end
end
self.object:remove()
return
end
-- Player punches cart to alter velocity
local vel = self.object:getvelocity()
if puncher:get_player_name() == self.driver then
if math.abs(vel.x + vel.z) > carts.punch_speed_max then
return
end
end
local punch_dir = carts:velocity_to_dir(puncher:get_look_dir())
punch_dir.y = 0
local cart_dir = carts:get_rail_direction(pos, punch_dir, nil, nil, self.railtype)
if vector.equals(cart_dir, {x=0, y=0, z=0}) then
return
end
local punch_interval = 1
if tool_capabilities and tool_capabilities.full_punch_interval then
punch_interval = tool_capabilities.full_punch_interval
end
time_from_last_punch = math.min(time_from_last_punch or punch_interval, punch_interval)
local f = 2 * (time_from_last_punch / punch_interval)
self.velocity = vector.multiply(cart_dir, f)
self.old_dir = cart_dir
self.punched = true
end
local function rail_on_step_event(handler, obj, dtime)
if handler then
handler(obj, dtime)
end
end
-- sound refresh interval = 1.0sec
local function rail_sound(self, dtime)
if not self.sound_ttl then
self.sound_ttl = 1.0
return
elseif self.sound_ttl > 0 then
self.sound_ttl = self.sound_ttl - dtime
return
end
self.sound_ttl = 1.0
if self.sound_handle then
local handle = self.sound_handle
self.sound_handle = nil
minetest.after(0.2, minetest.sound_stop, handle)
end
local vel = self.object:getvelocity()
local speed = vector.length(vel)
if speed > 0 then
self.sound_handle = minetest.sound_play(
"carts_cart_moving", {
object = self.object,
gain = (speed / carts.speed_max) / 2,
loop = true,
})
end
end
local function get_railparams(pos)
local node = minetest.get_node(pos)
return carts.railparams[node.name] or {}
end
local function rail_on_step(self, dtime)
local vel = self.object:getvelocity()
if self.punched then
vel = vector.add(vel, self.velocity)
self.object:setvelocity(vel)
self.old_dir.y = 0
elseif vector.equals(vel, {x=0, y=0, z=0}) then
return
end
local pos = self.object:getpos()
local update = {}
-- stop cart if velocity vector flips
if self.old_vel and self.old_vel.y == 0 and
(self.old_vel.x * vel.x < 0 or self.old_vel.z * vel.z < 0) then
self.old_vel = {x = 0, y = 0, z = 0}
self.old_pos = pos
self.object:setvelocity(vector.new())
self.object:setacceleration(vector.new())
rail_on_step_event(get_railparams(pos).on_step, self, dtime)
return
end
self.old_vel = vector.new(vel)
if self.old_pos and not self.punched then
local flo_pos = vector.round(pos)
local flo_old = vector.round(self.old_pos)
if vector.equals(flo_pos, flo_old) then
-- Do not check one node multiple times
return
end
end
local ctrl, player
-- Get player controls
if self.driver then
player = minetest.get_player_by_name(self.driver)
if player then
ctrl = player:get_player_control()
end
end
if self.old_pos then
-- Detection for "skipping" nodes
local found_path = carts:pathfinder(
pos, self.old_pos, self.old_dir, ctrl, self.old_switch, self.railtype
)
if not found_path then
-- No rail found: reset back to the expected position
pos = vector.new(self.old_pos)
update.pos = true
end
end
local cart_dir = carts:velocity_to_dir(vel)
local railparams
-- dir: New moving direction of the cart
-- switch_keys: Currently pressed L/R key, used to ignore the key on the next rail node
local dir, switch_keys = carts:get_rail_direction(
pos, cart_dir, ctrl, self.old_switch, self.railtype
)
local new_acc = {x=0, y=0, z=0}
if vector.equals(dir, {x=0, y=0, z=0}) then
vel = {x = 0, y = 0, z = 0}
pos = vector.round(pos)
update.pos = true
update.vel = true
else
-- Direction change detected
if not vector.equals(dir, self.old_dir) then
vel = vector.multiply(dir, math.abs(vel.x + vel.z))
update.vel = true
if dir.y ~= self.old_dir.y then
pos = vector.round(pos)
update.pos = true
end
end
-- Center on the rail
if dir.z ~= 0 and math.floor(pos.x + 0.5) ~= pos.x then
pos.x = math.floor(pos.x + 0.5)
update.pos = true
end
if dir.x ~= 0 and math.floor(pos.z + 0.5) ~= pos.z then
pos.z = math.floor(pos.z + 0.5)
update.pos = true
end
-- Slow down or speed up..
local acc = dir.y * -4.0
-- Get rail for corrected position
railparams = get_railparams(pos)
-- no need to check for railparams == nil since we always make it exist.
local speed_mod = railparams.acceleration
if speed_mod and speed_mod ~= 0 then
-- Try to make it similar to the original carts mod
acc = acc + speed_mod
else
-- Handbrake or coast
if ctrl and ctrl.down then
acc = acc - 3
else
acc = acc - 0.4
end
end
new_acc = vector.multiply(dir, acc)
end
-- Limits
local max_vel = carts.speed_max
for _, v in pairs({"x","y","z"}) do
if math.abs(vel[v]) > max_vel then
vel[v] = carts:get_sign(vel[v]) * max_vel
new_acc[v] = 0
update.vel = true
end
end
self.object:setacceleration(new_acc)
self.old_pos = vector.new(pos)
if not vector.equals(dir, {x=0, y=0, z=0}) then
self.old_dir = vector.new(dir)
end
self.old_switch = switch_keys
if self.punched then
-- Collect dropped items
for _, obj_ in pairs(minetest.get_objects_inside_radius(pos, 1)) do
if not obj_:is_player() and
obj_:get_luaentity() and
not obj_:get_luaentity().physical_state and
obj_:get_luaentity().name == "__builtin:item" then
obj_:set_attach(self.object, "", {x=0, y=0, z=0}, {x=0, y=0, z=0})
self.attached_items[#self.attached_items + 1] = obj_
end
end
self.punched = false
update.vel = true
end
railparams = railparams or get_railparams(pos)
if not (update.vel or update.pos) then
rail_on_step_event(railparams.on_step, self, dtime)
return
end
local yaw = 0
if self.old_dir.x < 0 then
yaw = 0.5
elseif self.old_dir.x > 0 then
yaw = 1.5
elseif self.old_dir.z < 0 then
yaw = 1
end
self.object:setyaw(yaw * math.pi)
local anim = {x=0, y=0}
if dir.y == -1 then
anim = {x=1, y=1}
elseif dir.y == 1 then
anim = {x=2, y=2}
end
self.object:set_animation(anim, 1, 0)
self.object:setvelocity(vel)
if update.pos then
self.object:setpos(pos)
end
-- call event handler
rail_on_step_event(railparams.on_step, self, dtime)
end
function cart_entity:on_step(dtime)
rail_on_step(self, dtime)
rail_sound(self, dtime)
end
minetest.register_entity("carts:cart", cart_entity)
minetest.register_craftitem("carts:cart", {
description = "Cart (Sneak+Click to pick up)",
inventory_image = minetest.inventorycube("carts_cart_top.png", "carts_cart_side.png", "carts_cart_side.png"),
wield_image = "carts_cart_side.png",
on_place = function(itemstack, placer, pointed_thing)
local under = pointed_thing.under
local node = minetest.get_node(under)
local udef = minetest.registered_nodes[node.name]
if udef and udef.on_rightclick and
not (placer and placer:get_player_control().sneak) then
return udef.on_rightclick(under, node, placer, itemstack,
pointed_thing) or itemstack
end
if not pointed_thing.type == "node" then
return
end
if carts:is_rail(pointed_thing.under) then
minetest.add_entity(pointed_thing.under, "carts:cart")
elseif carts:is_rail(pointed_thing.above) then
minetest.add_entity(pointed_thing.above, "carts:cart")
else
return
end
minetest.sound_play({name = "default_place_node_metal", gain = 0.5},
{pos = pointed_thing.above})
if not (creative and creative.is_enabled_for
and creative.is_enabled_for(placer:get_player_name())) then
itemstack:take_item()
end
return itemstack
end,
})
minetest.register_craft({
output = "carts:cart",
recipe = {
{"default:steel_ingot", "", "default:steel_ingot"},
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
},
})

1
mods/carts/depends.txt Normal file
View File

@ -0,0 +1 @@
default

View File

@ -1,6 +1,4 @@
function boost_cart:get_sign(z)
function carts:get_sign(z)
if z == 0 then
return 0
else
@ -8,44 +6,37 @@ function boost_cart:get_sign(z)
end
end
function boost_cart:manage_attachment(player, status, obj)
function carts:manage_attachment(player, obj)
if not player then
return
end
local status = obj ~= nil
local player_name = player:get_player_name()
if default.player_attached[player_name] == status then
return
end
default.player_attached[player_name] = status
if status then
player:set_attach(obj, "", {x=0, y=6, z=0}, {x=0, y=0, z=0})
player:set_eye_offset({x=0, y=-2, z=0},{x=0, y=-2, z=0})
player:set_eye_offset({x=0, y=-4, z=0},{x=0, y=-4, z=0})
else
player:set_detach()
player:set_eye_offset({x=0, y=0, z=0},{x=0, y=0, z=0})
end
end
function boost_cart:velocity_to_dir(v)
function carts:velocity_to_dir(v)
if math.abs(v.x) > math.abs(v.z) then
return {x=boost_cart:get_sign(v.x), y=boost_cart:get_sign(v.y), z=0}
return {x=carts:get_sign(v.x), y=carts:get_sign(v.y), z=0}
else
return {x=0, y=boost_cart:get_sign(v.y), z=boost_cart:get_sign(v.z)}
return {x=0, y=carts:get_sign(v.y), z=carts:get_sign(v.z)}
end
end
function boost_cart:is_rail(pos, railtype)
function carts:is_rail(pos, railtype)
local node = minetest.get_node(pos).name
if node == "ignore" then
local vm = minetest.get_voxel_manip()
local emin, emax = vm:read_from_map(pos, pos)
local area = VoxelArea:new{
@ -56,63 +47,50 @@ function boost_cart:is_rail(pos, railtype)
local vi = area:indexp(pos)
node = minetest.get_name_from_content_id(data[vi])
end
if minetest.get_item_group(node, "rail") == 0 then
return false
end
if not railtype then
return true
end
return minetest.get_item_group(node, "connect_to_raillike") == railtype
end
function boost_cart:check_front_up_down(pos, dir_, check_down, railtype)
function carts:check_front_up_down(pos, dir_, check_up, railtype)
local dir = vector.new(dir_)
local cur = nil
local cur
-- Front
dir.y = 0
cur = vector.add(pos, dir)
if boost_cart:is_rail(cur, railtype) then
if carts:is_rail(cur, railtype) then
return dir
end
-- Up
if check_down then
if check_up then
dir.y = 1
cur = vector.add(pos, dir)
if boost_cart:is_rail(cur, railtype) then
if carts:is_rail(cur, railtype) then
return dir
end
end
-- Down
dir.y = -1
cur = vector.add(pos, dir)
if boost_cart:is_rail(cur, railtype) then
if carts:is_rail(cur, railtype) then
return dir
end
return nil
end
function boost_cart:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
function carts:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
local pos = vector.round(pos_)
local cur = nil
local cur
local left_check, right_check = true, true
-- Check left and right
local left = {x=0, y=0, z=0}
local right = {x=0, y=0, z=0}
if dir.z ~= 0 and dir.x == 0 then
left.x = -dir.z
right.x = dir.z
@ -120,146 +98,124 @@ function boost_cart:get_rail_direction(pos_, dir, ctrl, old_switch, railtype)
left.z = dir.x
right.z = -dir.x
end
if ctrl then
if ctrl then
if old_switch == 1 then
left_check = false
elseif old_switch == 2 then
right_check = false
end
if ctrl.left and left_check then
cur = boost_cart:check_front_up_down(pos, left, false, railtype)
cur = carts:check_front_up_down(pos, left, false, railtype)
if cur then
return cur, 1
end
left_check = false
end
if ctrl.right and right_check then
cur = boost_cart:check_front_up_down(pos, right, false, railtype)
cur = carts:check_front_up_down(pos, right, false, railtype)
if cur then
return cur, 2
end
right_check = true
end
end
-- Normal
cur = boost_cart:check_front_up_down(pos, dir, true, railtype)
-- Normal
cur = carts:check_front_up_down(pos, dir, true, railtype)
if cur then
return cur
end
-- Left, if not already checked
if left_check then
cur = boost_cart:check_front_up_down(pos, left, false, railtype)
cur = carts:check_front_up_down(pos, left, false, railtype)
if cur then
return cur
end
end
-- Right, if not already checked
if right_check then
cur = boost_cart:check_front_up_down(pos, right, false, railtype)
cur = carts:check_front_up_down(pos, right, false, railtype)
if cur then
return cur
end
end
-- Backwards
if not old_switch then
cur = boost_cart:check_front_up_down(pos, {
x = -dir.x,
y = dir.y,
z = -dir.z
}, true, railtype)
cur = carts:check_front_up_down(pos, {
x = -dir.x,
y = dir.y,
z = -dir.z
}, true, railtype)
if cur then
return cur
end
end
return {x=0, y=0, z=0}
end
function boost_cart:pathfinder(pos_, expected_pos, old_dir, ctrl, pf_switch, railtype)
function carts:pathfinder(pos_, old_pos, old_dir, ctrl, pf_switch, railtype)
local pos = vector.round(pos_)
local pf_pos = vector.round(expected_pos)
local pf_pos = vector.round(old_pos)
local pf_dir = vector.new(old_dir)
for i = 1, 3 do
if vector.equals(pf_pos, pos) then
return true -- success! cart moved on correctly
-- Success! Cart moved on correctly
return true
end
pf_dir, pf_switch = boost_cart:get_rail_direction(pf_pos, pf_dir,
ctrl, pf_switch, railtype)
if vector.equals(pf_dir, {x = 0, y = 0, z = 0}) then
return false -- no way forwards
pf_dir, pf_switch = carts:get_rail_direction(pf_pos, pf_dir, ctrl, pf_switch, railtype)
if vector.equals(pf_dir, {x=0, y=0, z=0}) then
-- No way forwards
return false
end
pf_pos = vector.add(pf_pos, pf_dir)
end
return false -- cart not found
-- Cart not found
return false
end
function boost_cart:boost_rail(pos, amount)
minetest.get_meta(pos):set_string("cart_acceleration", tostring(amount))
for _,obj_ in pairs(minetest.get_objects_inside_radius(pos, 0.5)) do
if not obj_:is_player()
and obj_:get_luaentity()
and obj_:get_luaentity().name == "carts:cart" then
obj_:get_luaentity():on_punch()
end
end
end
function boost_cart:register_rail(name, def)
local def_default = {
function carts:register_rail(name, def_overwrite, railparams)
local def = {
drawtype = "raillike",
paramtype = "light",
sunlight_propagates = true,
is_ground_content = true,
is_ground_content = false,
walkable = false,
selection_box = {
type = "fixed",
fixed = {-1/2, -1/2, -1/2, 1/2, -1/2+1/16, 1/2},
}
},
sounds = default.node_sound_metal_defaults()
}
for k, v in pairs(def_default) do
for k, v in pairs(def_overwrite) do
def[k] = v
end
if not def.inventory_image then
def.wield_image = def.tiles[1]
def.inventory_image = def.tiles[1]
end
if railparams then
carts.railparams[name] = table.copy(railparams)
end
minetest.register_node(name, def)
end
function carts:get_rail_groups(additional_groups)
-- Get the default rail groups and add more when a table is given
local groups = {dig_immediate = 2, attached_node = 1, rail = 1, connect_to_raillike = 1}
if type(additional_groups) == "table" then
for k, v in pairs(additional_groups) do
groups[k] = v
end
end
return groups
end

20
mods/carts/init.lua Normal file
View File

@ -0,0 +1,20 @@
carts = {}
carts.modpath = minetest.get_modpath("carts")
carts.railparams = {}
-- Maximal speed of the cart in m/s (min = -1)
carts.speed_max = 7
-- Set to -1 to disable punching the cart from inside (min = -1)
carts.punch_speed_max = 5
dofile(carts.modpath.."/functions.lua")
dofile(carts.modpath.."/rails.lua")
-- Support for non-default games
if not default.player_attached then
default.player_attached = {}
end
dofile(carts.modpath.."/cart_entity.lua")

54
mods/carts/license.txt Normal file
View File

@ -0,0 +1,54 @@
License of source code
----------------------
The MIT License (MIT)
Copyright (C) 2012-2016 PilzAdam
Copyright (C) 2014-2016 SmallJoker
Copyright (C) 2012-2016 Various Minetest developers and contributors
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
For more details:
https://opensource.org/licenses/MIT
Licenses of media
-----------------
CC-0, see: https://creativecommons.org/share-your-work/public-domain/cc0/, except
if other license is mentioned.
Authors
---------
Originally from PixelBOX (Gambit):
carts_cart_side.png
carts_cart_top.png
carts_cart_front.png*
carts_cart.png*
sofar + stujones11:
carts_cart.b3d and carts_cart.blend
hexafraction, modified by sofar
carts_rail_*.png
http://www.freesound.org/people/YleArkisto/sounds/253159/ - YleArkisto - CC-BY-3.0
carts_cart_moving.*.ogg

Binary file not shown.

Binary file not shown.

59
mods/carts/rails.lua Normal file
View File

@ -0,0 +1,59 @@
carts:register_rail("carts:rail", {
description = "Rail",
tiles = {
"carts_rail_straight.png", "carts_rail_curved.png",
"carts_rail_t_junction.png", "carts_rail_crossing.png"
},
inventory_image = "carts_rail_straight.png",
wield_image = "carts_rail_straight.png",
groups = carts:get_rail_groups(),
}, {})
minetest.register_craft({
output = "carts:rail 18",
recipe = {
{"default:steel_ingot", "group:wood", "default:steel_ingot"},
{"default:steel_ingot", "", "default:steel_ingot"},
{"default:steel_ingot", "group:wood", "default:steel_ingot"},
}
})
minetest.register_alias("default:rail", "carts:rail")
carts:register_rail("carts:powerrail", {
description = "Powered rail",
tiles = {
"carts_rail_straight_pwr.png", "carts_rail_curved_pwr.png",
"carts_rail_t_junction_pwr.png", "carts_rail_crossing_pwr.png"
},
groups = carts:get_rail_groups(),
}, {acceleration = 5})
minetest.register_craft({
output = "carts:powerrail 18",
recipe = {
{"default:steel_ingot", "group:wood", "default:steel_ingot"},
{"default:steel_ingot", "default:mese_crystal", "default:steel_ingot"},
{"default:steel_ingot", "group:wood", "default:steel_ingot"},
}
})
carts:register_rail("carts:brakerail", {
description = "Brake rail",
tiles = {
"carts_rail_straight_brk.png", "carts_rail_curved_brk.png",
"carts_rail_t_junction_brk.png", "carts_rail_crossing_brk.png"
},
groups = carts:get_rail_groups(),
}, {acceleration = -3})
minetest.register_craft({
output = "carts:brakerail 18",
recipe = {
{"default:steel_ingot", "group:wood", "default:steel_ingot"},
{"default:steel_ingot", "default:coal_lump", "default:steel_ingot"},
{"default:steel_ingot", "group:wood", "default:steel_ingot"},
}
})

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 684 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 660 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 661 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 707 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 697 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 630 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 527 B

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 552 B

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 B

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 637 B

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 527 B

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

View File

@ -27,41 +27,41 @@
"black.png",
}
local time = 0
local time = 0
--minetest.after(1, function()
minetest.register_globalstep(function(dtime)
time = time + dtime
if time > 0 then for _, player in ipairs(minetest.get_connected_players()) do
time = 0
minetest.register_globalstep(function(dtime)
time = time + dtime
if time > 5 then for _, player in ipairs(minetest.get_connected_players()) do
time = 0
local name = player:get_player_name()
local pos = player:getpos()
--If the player has reached Space
if minetest.get_player_by_name(name) and pos.y >= space then
player:set_physics_override(1, 0.6, 0.2,false,false) -- speed, jump, gravity
player:set_sky({}, "skybox", spaceskybox) -- Sets skybox
local name = player:get_player_name()
local pos = player:getpos()
--If the player is on Earth
elseif minetest.get_player_by_name(name) and pos.y < space then
player:set_physics_override(1, 1, 1,true,true) -- speed, jump, gravity [default]
player:set_sky({}, "regular", {}) -- Sets skybox, in this case it sets the skybox to it's default setting if and only if the player's Y value is less than the value of space.
--If the player has reached Space
if minetest.get_player_by_name(name) and pos.y >= space then
player:set_physics_override(1, 0.6, 0.2,false,false) -- speed, jump, gravity
player:set_sky({}, "skybox", spaceskybox) -- Sets skybox
--If the player has reached Cave
if minetest.get_player_by_name(name) and pos.y <=cave then
player:set_physics_override(1, 1, 1.2,true,true) -- speed, jump, gravity
player:set_sky({}, "cavebox", caveskybox) -- Sets skybox
end
end
end
end
end)
--end)
--If the player is on Earth
elseif minetest.get_player_by_name(name) and pos.y < space then
player:set_physics_override(1, 1, 1,true,true) -- speed, jump, gravity [default]
player:set_sky({}, "regular", {}) -- Sets skybox, in this case it sets the skybox to it's default setting if and only if the player's Y value is less than the value of space.
--If the player has reached Cave
if minetest.get_player_by_name(name) and pos.y <=cave then
player:set_physics_override(1, 1, 1.2,true,true) -- speed, jump, gravity
player:set_sky({}, "cavebox", caveskybox) -- Sets skybox
end
end
end
end
end)
minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
if name then
player:set_sky({}, "regular", {})
end
end)
minetest.register_on_leaveplayer(function(player)
local name = player:get_player_name()
if name then
player:set_sky({}, "regular", {})
end
end)

View File

@ -24,6 +24,7 @@ es.modpath = modpath
dofile(modpath.."/crafting.lua")
dofile(modpath.."/antigrief.lua")
dofile(modpath.."/armor.lua")
dofile(modpath.."/kill.lua")
dofile(modpath.."/shields.lua")
dofile(modpath.."/shutdown.lua")
dofile(modpath.."/spawn.lua")

26
mods/es/kill.lua Normal file
View File

@ -0,0 +1,26 @@
minetest.register_chatcommand("killme", {
description = "Kill yourself to respawn",
func = function(name)
local player = minetest.get_player_by_name(name)
if player then
if minetest.settings:get_bool("enable_damage") then
player:set_hp(0)
return true
else
for _, callback in pairs(core.registered_on_respawnplayers) do
if callback(player) then
return true
end
end
-- There doesn't seem to be a way to get a default spawn pos from the lua API
return false, "No static_spawnpoint defined"
end
else
-- Show error message if used when not logged in, eg: from IRC mod
return false, "You need to be online to be killed!"
end
end
})

View File

@ -20,10 +20,10 @@ es = {}
--Modified by maikerumine
-- Time to shut down server.
-- Default is twice a day: at 06:05 and 18:05
local H = 18
local X = 18
local Y = 19
local Z = 19
local H = 19
local X = 19
local Y = 20
local Z = 20
local M = 55
local N = 00
@ -41,7 +41,7 @@ minetest.register_globalstep(function(dtime)
local t = os.date("*t")
if ((t.hour == H or t.hour == X) and (t.min == M) and (t.sec <= 2)
and ((D == nil) or (t.wday == D))) then
minetest.chat_send_all("Scheduled shutdown. 1900 Eastern Time Zone"
minetest.chat_send_all("Scheduled shutdown. 2000 Eastern Time Zone DST 0000 ZULU "
.."Shutting down in FIVE minutes. Enjoy the break")
minetest.chat_send_all("STORE YOUR ITEMS WITHIN 4 MINUTES. "
.."Shutting down in FIVE minutes.")
@ -49,18 +49,18 @@ minetest.register_globalstep(function(dtime)
end
if ((t.hour == Y or t.hour == Z) and (t.min ==N) and (t.sec <= 2)
and ((D == nil) or (t.wday == D))) then
minetest.chat_send_all("SHUTTING SERVER DOWN NOW!"
.." Please come back in a few while map is backed-up.")
minetest.chat_send_all("5 SHUTTING SERVER DOWN NOW!"
.." Please come back in a few while map is backed--up.")
minetest.chat_send_all("4 SHUTTING SERVER DOWN NOW!"
.." Please come back in a few while map is backed---up.")
minetest.chat_send_all("3 SHUTTING SERVER DOWN NOW!"
.." Please come back in a few while map is backed----up.")
minetest.chat_send_all("2 SHUTTING SERVER DOWN NOW!"
.." Please come back in a few while map is backed-----up.")
minetest.chat_send_all("1 SHUTTING SERVER DOWN NOW!"
.." Please come back in a few while map is backed------up.")
minetest.chat_send_all("SHUTTING SERVER DOWN NOW! "
.." Please come back in a few while map is backed-up. ")
minetest.chat_send_all("E SHUTTING SERVER DOWN NOW! "
.." Please come back in a few while map is backed--up. ")
minetest.chat_send_all("S SHUTTING SERVER DOWN NOW! "
.." Please come back in a few while map is backed---up. ")
minetest.chat_send_all("M SHUTTING SERVER DOWN NOW! "
.." Please come back in a few while map is backed----up. ")
minetest.chat_send_all("! SHUTTING SERVER DOWN NOW! "
.." Please come back in a few while map is backed-----up. ")
minetest.chat_send_all("! SHUTTING SERVER DOWN NOW! "
.." Please come back in a few while map is backed------up. ")
minetest.after(2, minetest.request_shutdown)
end
end)

View File

@ -41,7 +41,7 @@ local crop_def = {
snappy = 3, flammable = 2, plant = 1, attached_node = 1,
not_in_creative_inventory = 1, growing = 1
},
sounds = default.node_sound_leaves_defaults()
sounds = default.node_sound_wood_defaults()
}
-- stage 1

View File

@ -1,13 +0,0 @@
minetest.register_on_newplayer(function(player)
--print("on_newplayer")
minetest.log("action", "Giving initial stuff to player "..player:get_player_name())
player:get_inventory():add_item('main', 'default:torch 3')
player:get_inventory():add_item('main', 'default:apple 3')
player:get_inventory():add_item('main', 'default:pick_wood 1')
player:get_inventory():add_item('main', 'mt_seasons:jackolantern 1')
player:get_inventory():add_item('main', 'default:goldblock 1')
end)

View File

@ -1,28 +0,0 @@
maikerumine changed to add es nodes and added metal sound compatibility.
Stairs Redo 0.1 based on Minetest 0.4 mod: stairs
License of source code:
-----------------------
Copyright (C) 2011-2012 Kahrl <kahrl@gmx.net>
Copyright (C) 2011-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
This program 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 of the License, or
(at your option) any later version.
http://www.gnu.org/licenses/lgpl-2.1.html
License of media (textures and sounds)
--------------------------------------
Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0)
http://creativecommons.org/licenses/by-sa/3.0/
Authors of media files
-----------------------
Everything not listed in here:
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
Note: This mod has been changed by TenPlus1 to include other blocks from different mods as well as corner stairs...

16
mods/stairs/README.txt Normal file
View File

@ -0,0 +1,16 @@
Minetest Game mod: stairs
=========================
See license.txt for license information.
Authors of source code
----------------------
Originally by Kahrl <kahrl@gmx.net> (LGPL 2.1) and
celeron55, Perttu Ahola <celeron55@gmail.com> (LGPL 2.1)
Various Minetest developers and contributors (LGPL 2.1)
Authors of media (models)
-------------------------
Jean-Patrick G. (kilbith) <jeanpatrick.guerrero@gmail.com> (CC BY-SA 3.0):
stairs_stair.obj

View File

@ -1 +1,2 @@
default
farming

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