aboutsummaryrefslogtreecommitdiff
path: root/src/script/lua_api
Commit message (Expand)AuthorAge
...
* Use numeric indices and raw table access with LUA_REGISTRYINDEXKahrl2015-08-27
* SAPI: Disable unlockable time profilingkwolekr2015-08-18
* SEnv: Remove static_exists from ActiveObjects in deleted blockskwolekr2015-08-16
* minimap: Add ability to disable from serverkwolekr2015-08-13
* SAPI: Track last executed mod and include in error messageskwolekr2015-08-12
* Improve Script CPP API diagnosticskwolekr2015-08-05
* Biome API: Make fallback biome stone and water, disable fillerparamat2015-08-03
* Add AreaStore data structureest312015-07-27
* Fix MSVC number conversion warningSmallJoker2015-07-25
* Fix minetest.get_(all)_craft_recipe(s) regressionest312015-07-25
* Cleanup server addparticle(spawner) by merge two identical functions.Loic Blot2015-07-25
* Optional reconnect functionalityest312015-07-23
* Added get_player_velocity() method. Fixes #1176Elia Argentieri2015-07-20
* Refactor particle code to remove the while loopsTeTpaAka2015-07-18
* Make acc and vel deprecated in add_particle and search for acceleration and v...TeTpaAka2015-07-18
* Fix invisible player when the attached entity is removedTeTpaAka2015-07-18
* Fix damage flash when damage disabledkwolekr2015-07-10
* Use UTF-8 instead of narrowest312015-07-08
* Fix bug when craft input isn't replacedTeTpaAka2015-06-22
* Fix some issues with animations, and allow non-looped animations to be definedMirceaKitsune2015-06-22
* Mapgen objects: Enable heatmap and humidmap for all biome api mapgensparamat2015-06-20
* Use utf-8 in formspecsIlya Zhuravlev2015-06-13
* Add return list of individual counts to find_node_in_areaTeTpaAka2015-06-13
* Make get_biome_list() error message more helpfulkwolekr2015-05-28
* Add some missing getter functions to the lua APITeTpaAka2015-05-28
* Replace instances of std::map<std::string, std::string> with StringMapkwolekr2015-05-19
* Fix null dereference when loading schematic from definition without a NodeDef...kwolekr2015-05-17
* Record MapBlock modification reasons as flags instead of stringskwolekr2015-05-17
* SAPI/Noise: Add PerlinNoiseMap:getMapSlice() functionkwolekr2015-05-17
* Add optional buffer param for bulk data array writes in Luakwolekr2015-05-17
* Fix current mod name change missed during rebaseShadowNinja2015-05-16
* SAPI: Accept either ARGB8 table or ColorString to specify colorskwolekr2015-05-16
* Add core.get_dir_listShadowNinja2015-05-16
* Add core.request_insecure_environment()ShadowNinja2015-05-16
* Add core.mkdirShadowNinja2015-05-16
* Add mod securityShadowNinja2015-05-16
* Add push_ARGB8 to script/common/c_converterTeTpaAka2015-05-15
* Generalize core.get/set_nametag_color into core.get/set_nametag_attributesTeTpaAka2015-05-15
* Add get and set functions for the nametag colorTeTpaAka2015-05-15
* Fix compiler warning about sign comparisonest312015-05-13
* is_player() is no player-only functionest312015-05-12
* Make early protocol auth mechanism generic, and add SRPest312015-05-11
* Schematics: Add per-node force placement optionkwolekr2015-05-09
* Tests: Add schematic unittestskwolekr2015-05-08
* Schematics: Add indent-with-space option for schematic Lua table serializationkwolekr2015-05-07
* NodeResolver: Remove NodeResolveMethodkwolekr2015-05-07
* Add core.find_nodes_with_meta() script APIkwolekr2015-05-05
* Ore: Add biomes parameterkwolekr2015-04-20
* Add 'persistence' alias for Lua noiseparams and validate more vector parameterskwolekr2015-04-19
* Biome API: Add biome-specific river waterparamat2015-04-19
8 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615
local modstorage = core.get_mod_storage()

-- crashed on pre-5.2
-- local modpath = minetest.get_modpath("colour_chat")
-- dofile(modpath .. "/colournames.lua")

-- This list of colour names was extracted and converted from
-- https://drafts.csswg.org/css-color/#named-colors


local colournames = {}

colournames["aliceblue"] =  "#F0F8FF"
colournames["antiquewhite"] =  "#FAEBD7"
colournames["aqua"] =  "#00FFFF"
colournames["aquamarine"] =  "#7FFFD4"
colournames["azure"] =  "#F0FFFF"
colournames["beige"] =  "#F5F5DC"
colournames["bisque"] =  "#FFE4C4"
colournames["black"] =  "#000000"
colournames["blanchedalmond"] =  "#FFEBCD"
colournames["blue"] =  "#0000FF"
colournames["blueviolet"] =  "#8A2BE2"
colournames["brown"] =  "#A52A2A"
colournames["burlywood"] =  "#DEB887"
colournames["cadetblue"] =  "#5F9EA0"
colournames["chartreuse"] =  "#7FFF00"
colournames["chocolate"] =  "#D2691E"
colournames["coral"] =  "#FF7F50"
colournames["cornflowerblue"] =  "#6495ED"
colournames["cornsilk"] =  "#FFF8DC"
colournames["crimson"] =  "#DC143C"
colournames["cyan"] =  "#00FFFF"
colournames["darkblue"] =  "#00008B"
colournames["darkcyan"] =  "#008B8B"
colournames["darkgoldenrod"] =  "#B8860B"
colournames["darkgray"] =  "#A9A9A9"
colournames["darkgreen"] =  "#006400"
colournames["darkgrey"] =  "#A9A9A9"
colournames["darkkhaki"] =  "#BDB76B"
colournames["darkmagenta"] =  "#8B008B"
colournames["darkolivegreen"] =  "#556B2F"
colournames["darkorange"] =  "#FF8C00"
colournames["darkorchid"] =  "#9932CC"
colournames["darkred"] =  "#8B0000"
colournames["darksalmon"] =  "#E9967A"
colournames["darkseagreen"] =  "#8FBC8F"
colournames["darkslateblue"] =  "#483D8B"
colournames["darkslategray"] =  "#2F4F4F"
colournames["darkslategrey"] =  "#2F4F4F"
colournames["darkturquoise"] =  "#00CED1"
colournames["darkviolet"] =  "#9400D3"
colournames["deeppink"] =  "#FF1493"
colournames["deepskyblue"] =  "#00BFFF"
colournames["dimgray"] =  "#696969"
colournames["dimgrey"] =  "#696969"
colournames["dodgerblue"] =  "#1E90FF"
colournames["firebrick"] =  "#B22222"
colournames["floralwhite"] =  "#FFFAF0"
colournames["forestgreen"] =  "#228B22"
colournames["fuchsia"] =  "#FF00FF"
colournames["gainsboro"] =  "#DCDCDC"
colournames["ghostwhite"] =  "#F8F8FF"
colournames["gold"] =  "#FFD700"
colournames["goldenrod"] =  "#DAA520"
colournames["gray"] =  "#808080"
colournames["green"] =  "#008000"
colournames["greenyellow"] =  "#ADFF2F"
colournames["grey"] =  "#808080"
colournames["honeydew"] =  "#F0FFF0"
colournames["hotpink"] =  "#FF69B4"
colournames["indianred"] =  "#CD5C5C"
colournames["indigo"] =  "#4B0082"
colournames["ivory"] =  "#FFFFF0"
colournames["khaki"] =  "#F0E68C"
colournames["lavender"] =  "#E6E6FA"
colournames["lavenderblush"] =  "#FFF0F5"
colournames["lawngreen"] =  "#7CFC00"
colournames["lemonchiffon"] =  "#FFFACD"
colournames["lightblue"] =  "#ADD8E6"
colournames["lightcoral"] =  "#F08080"
colournames["lightcyan"] =  "#E0FFFF"
colournames["lightgoldenrodyellow"] =  "#FAFAD2"
colournames["lightgray"] =  "#D3D3D3"
colournames["lightgreen"] =  "#90EE90"
colournames["lightgrey"] =  "#D3D3D3"
colournames["lightpink"] =  "#FFB6C1"
colournames["lightsalmon"] =  "#FFA07A"
colournames["lightseagreen"] =  "#20B2AA"
colournames["lightskyblue"] =  "#87CEFA"
colournames["lightslategray"] =  "#778899"
colournames["lightslategrey"] =  "#778899"
colournames["lightsteelblue"] =  "#B0C4DE"
colournames["lightyellow"] =  "#FFFFE0"
colournames["lime"] =  "#00FF00"
colournames["limegreen"] =  "#32CD32"
colournames["linen"] =  "#FAF0E6"
colournames["magenta"] =  "#FF00FF"
colournames["maroon"] =  "#800000"
colournames["mediumaquamarine"] =  "#66CDAA"
colournames["mediumblue"] =  "#0000CD"
colournames["mediumorchid"] =  "#BA55D3"
colournames["mediumpurple"] =  "#9370DB"
colournames["mediumseagreen"] =  "#3CB371"
colournames["mediumslateblue"] =  "#7B68EE"
colournames["mediumspringgreen"] =  "#00FA9A"
colournames["mediumturquoise"] =  "#48D1CC"
colournames["mediumvioletred"] =  "#C71585"
colournames["midnightblue"] =  "#191970"
colournames["mintcream"] =  "#F5FFFA"
colournames["mistyrose"] =  "#FFE4E1"
colournames["moccasin"] =  "#FFE4B5"
colournames["navajowhite"] =  "#FFDEAD"
colournames["navy"] =  "#000080"
colournames["oldlace"] =  "#FDF5E6"
colournames["olive"] =  "#808000"
colournames["olivedrab"] =  "#6B8E23"
colournames["orange"] =  "#FFA500"
colournames["orangered"] =  "#FF4500"
colournames["orchid"] =  "#DA70D6"
colournames["palegoldenrod"] =  "#EEE8AA"
colournames["palegreen"] =  "#98FB98"
colournames["paleturquoise"] =  "#AFEEEE"
colournames["palevioletred"] =  "#DB7093"
colournames["papayawhip"] =  "#FFEFD5"
colournames["peachpuff"] =  "#FFDAB9"
colournames["peru"] =  "#CD853F"
colournames["pink"] =  "#FFC0CB"
colournames["plum"] =  "#DDA0DD"
colournames["powderblue"] =  "#B0E0E6"
colournames["purple"] =  "#800080"
colournames["rebeccapurple"] =  "#663399"
colournames["red"] =  "#FF0000"
colournames["rosybrown"] =  "#BC8F8F"
colournames["royalblue"] =  "#4169E1"
colournames["saddlebrown"] =  "#8B4513"
colournames["salmon"] =  "#FA8072"
colournames["sandybrown"] =  "#F4A460"
colournames["seagreen"] =  "#2E8B57"
colournames["seashell"] =  "#FFF5EE"
colournames["sienna"] =  "#A0522D"
colournames["silver"] =  "#C0C0C0"
colournames["skyblue"] =  "#87CEEB"
colournames["slateblue"] =  "#6A5ACD"
colournames["slategray"] =  "#708090"
colournames["slategrey"] =  "#708090"
colournames["snow"] =  "#FFFAFA"
colournames["springgreen"] =  "#00FF7F"
colournames["steelblue"] =  "#4682B4"
colournames["tan"] =  "#D2B48C"
colournames["teal"] =  "#008080"
colournames["thistle"] =  "#D8BFD8"
colournames["tomato"] =  "#FF6347"
colournames["turquoise"] =  "#40E0D0"
colournames["violet"] =  "#EE82EE"
colournames["wheat"] =  "#F5DEB3"
colournames["white"] =  "#FFFFFF"
colournames["whitesmoke"] =  "#F5F5F5"
colournames["yellow"] =  "#FFFF00"
colournames["yellowgreen"] =  "#9ACD32"


function colourname2hex(colname)
   if not colname then return "" end
   if colname == "" then return "" end
   if colname:sub(1,1) == "#" then
      if #colname == 7 then
	 -- let's guess it's a hexcode as colour
	 return colname
      end 
   end
   if colournames[colname] then
      return colournames[colname]
   end
   -- be safe and return nothing
   return ""
end



local cr = minetest.get_csm_restrictions()
local limitationlist = { "load_client_mods", "chat_messages", "read_itemdefs", 
   "read_nodedefs", "lookup_nodes", "read_playerinfo" }

local modfunction_limited = {}

if not cr then
   minetest.display_chat_message("cr == nil")
   return
else
   for _,r in ipairs(limitationlist) do
      modfunction_limited[r] = true
      if cr[r] then
	 modfunction_limited[r] = false
      end
   end
end

local function show_restrictions()
   for _,r in ipairs(limitationlist) do
      minetest.display_chat_message(string.format("%-20s: %s",r, (modfunction_limited[r] and "allowed") or "forbidden"))
   end
end

show_restrictions()

if not modfunction_limited[ "chat_messages" ] then
   minetest.display_chat_message( "chat_messages".." are forbidden --> not loading")
   return
end   

local register_on_message = core.register_on_sending_chat_message
if core.register_on_sending_chat_messages then
	register_on_message = core.register_on_sending_chat_messages
end

local function safe(func)
    -- wrap a function w/ logic to avoid crashing the game
    local f = function(...)
        local status, out = pcall(func, ...)
        if status then
            return out
        else
            log('warning', 'Error (func):  ' .. out)
            return nil
        end
    end
    return f
end

local function paramsplit(str)
   -- minetest.display_chat_message("paramsplit 1")
   local s = str:gsub("^%s*(.-)%s*$", "%1")
   local p1 = string.find(s," ",1,true)
   if not p1 then return nil end
   -- minetest.display_chat_message("paramsplit 2")
   local p2 = string.find(s," ",p1+1,true)
   local s1 = str:sub(1,p1-1)
   if not p2 then return {s1,s1,str:sub(p1+1,512)}
 end
   -- minetest.display_chat_message("paramsplit 3")
   local s2 = str:sub(p1+1,p2-1)
   local s3 = str:sub(p2+1,512)
   return {s1,s2,s3}
end

local function rgb_to_hex(rgb)
	local hexadecimal = '#'

	for key, value in pairs(rgb) do
		local hex = ''

		while(value > 0)do
			local index = math.fmod(value, 16) + 1
			value = math.floor(value / 16)
			hex = string.sub('0123456789ABCDEF', index, index) .. hex			
		end

		if(string.len(hex) == 0)then
			hex = '00'

		elseif(string.len(hex) == 1)then
			hex = '0' .. hex
		end

		hexadecimal = hexadecimal .. hex
	end

	return hexadecimal
end

local function color_from_hue(hue)
	local h = hue / 60
	local c = 255
	local x = (1 - math.abs(h%2 - 1)) * 255

  	local i = math.floor(h);
  	if (i == 0) then
		return rgb_to_hex({c, x, 0})
  	elseif (i == 1) then 
		return rgb_to_hex({x, c, 0})
  	elseif (i == 2) then 
		return rgb_to_hex({0, c, x})
	elseif (i == 3) then
		return rgb_to_hex({0, x, c});
	elseif (i == 4) then
		return rgb_to_hex({x, 0, c});
	else 
		return rgb_to_hex({c, 0, x});
	end
end

local function pastel_from_hue(hue)
	local h = hue / 60
	local c = 255
   local d = 192
	local x = (1 - math.abs(h%2 - 1)) * 255

  	local i = math.floor(h);
  	if (i == 0) then
		return rgb_to_hex({c, x, d})
  	elseif (i == 1) then 
		return rgb_to_hex({x, c, d})
  	elseif (i == 2) then 
		return rgb_to_hex({d, c, x})
	elseif (i == 3) then
		return rgb_to_hex({d, x, c});
	elseif (i == 4) then
		return rgb_to_hex({x, d, c});
	else 
		return rgb_to_hex({c, d, x});
	end
end

function hex2rgb(hex)  -- added - found on github
    hex = hex:gsub("#","")
    return {tonumber("0x"..hex:sub(1,2)), tonumber("0x"..hex:sub(3,4)), tonumber("0x"..hex:sub(5,6))}
end

local function color_step(pos, col1, col2)  -- added - gets a color between colors
   --   if not col1 then col1 = "#888888" end
   -- if not col2 then col2 = "#888888" end
	local rgb1 = hex2rgb(col1)
	local rgb2 = hex2rgb(col2)
	local rgb = {}
	for i, v in pairs(rgb1) do
		rgb[i] = rgb1[i]+(rgb2[i]-rgb1[i])*(pos/255)
	end
	return rgb_to_hex(rgb)
end

local function canTalk()
	if core.get_privilege_list then
		return core.get_privilege_list().shout
	else
		return true
	end
end


local function get_status(ausgeben)
   local z = true
   local sd = modstorage:get("status")
   if not sd then z = true
   else z = sd == "true"
   end
   if ausgeben then
      minetest.display_chat_message("colourchat is "..((get_status() and "en") or "dis").."abled\n")
   end
   return z
end

local function set_status(zustand)
   modstorage:set_string("status", tostring(zustand))
   get_status()
end


local function say(message)
	if not canTalk() then
		minetest.display_chat_message("You need 'shout' in order to talk")
		return
	end
	minetest.send_chat_message(message)
	if minetest.get_server_info().protocol_version < 29 then
		local name = minetest.localplayer:get_name()
		minetest.display_chat_message("<"..name.."> " .. message)
	end
end

function fade(parameter)
   local p = paramsplit(parameter)
   if not p then return end
   -- local col1 = string.sub(parameter, 1, 7)
   -- local col2 = string.sub(parameter, 9, 15)
   -- local message = string.sub(parameter, 17)

   local col1 = colourname2hex(p[1])
   -- minetest.display_chat_message("col1.a: "..col1)
   -- minetest.display_chat_message("col1.b: "..core.get_color_escape_sequence(col1):sub(2,-1))
   -- minetest.display_chat_message("col1.c: "..minetest.colorize(col1):sub(2,-1))
   local col2 = colourname2hex(p[2])
   -- minetest.display_chat_message("col2.a: "..p[2])
   -- minetest.display_chat_message("col2.b: "..col2)
   local message = p[3]
   -- minetest.display_chat_message("msg: "..message)

   -- if true then return end

   if not canTalk() then
      return false, "You need 'shout' in order to use this command"
   end
   if col1 == col2 then
      -- minetest.display_chat_message("col1=col2")
      say(minetest.get_color_escape_sequence(col1) .. message)
      -- minetest.display_chat_message("col1=col2 b")
      return true
   end

   -- minetest.display_chat_message("pos4")

   local step = 255 / (message:len()/2)
   local pos = 0
   local output = ""
   for i = 1, message:len() do
      local char = message:sub(i,i)
      if char:match("%s") then
	 output = output .. char
      else
	 output = output .. minetest.get_color_escape_sequence(color_step(pos, col1, col2)) .. char 
      end
      pos = pos + step
   end
   say(output)
   return true
end

register_on_message(function(message)
	if not get_status() then return false end
	if message:sub(1,1) == "/" or modstorage:get_string("colour") == "" or modstorage:get_string("colour") == "white" then
		return false
	end

	fade(modstorage:get_string("colour") .. " " .. message)
	return true
end)

core.register_chatcommand("set_colour", {
	description = core.gettext("Change chat colour"),
	func = function(colour)
		  local c = paramsplit(colour)
		  if not c then 		     
		     local c1 = colourname2hex(colour)
		     if c1 and c1 ~= "" then 
			modstorage:set_string("colour", colour.." "..colour)
			return true, "Chat colour changed."
		     else
			return true,"'"..colour.."' is not a colour"
		     end
		  end
		  c1  = colourname2hex(c[1])
		  c2  = colourname2hex(c[3])
		  if not c1 or c1 == "" then 
		     return true,"'"..c[1].."' is not a colour"
		  end
		  if not c2 or c2 == "" then 
		     return true,"'"..c[2].."' is not a colour"
		  end
		  modstorage:set_string("colour", c1.." "..c2)
		  return true, "Chat colours changed."
	       end,
})

core.register_chatcommand("get_colour", {
        description = core.gettext("Display chat colour"),
	func = function()
		  local cc = modstorage:get_string("colour")
		  return true, "Current chat colour: " .. cc
	       end,
     })
			     

core.register_chatcommand("rainbow", {
	description = core.gettext("rainbow text"),
	func = function(param)
		if not canTalk() then
			return false, "You need 'shout' in order to use this command"
		end
		local step = 360 / param:len()
 		local hue = 0
     		 -- iterate the whole 360 degrees
		local output = ""
      		for i = 1, param:len() do
			local char = param:sub(i,i)
			if char:match("%s") then
				output = output .. char
			else
        			output = output  .. core.get_color_escape_sequence(colour_from_hue(hue)) .. char 
			end
        		hue = hue + step
		end
		say(output)
		return true
end,
})

core.register_chatcommand("fade", {  -- added - fades between any two colors
			     description = core.gettext("fade message between two colors"),
			     func = fade,
			  })

core.register_chatcommand("pastel", {
	description = core.gettext("pastel rainbow text"),
	func = function(param)
		if not canTalk() then
			return false, "You need 'shout' in order to use this command"
		end
		local step = 360 / param:len()
 		local hue = 0
     		 -- iterate the whole 360 degrees
		local output = ""
      		for i = 1, param:len() do
			local char = param:sub(i,i)
			if char:match("%s") then
				output = output .. char
			else
        			output = output  .. core.get_color_escape_sequence(pastel_from_hue(hue)) .. char 
			end
        		hue = hue + step
		end
		say(output)
		return true
end,
})

core.register_chatcommand("mw", {
        description = core.gettext("moderator warning"),
        func = function(param)
                if not canTalk() then
                        return false, "You need 'shout' in order to use this comand"
                end
		minetest.run_server_chatcommand('mw', param)
                -- local output = ""
                -- output = core.get_color_escape_sequence("#ffdf00") .. "MODERATOR WARNING: "
                -- output = output .. core.get_color_escape_sequence("#ff7fff") ..param
                -- say(output)
                return true
end,
})


core.register_chatcommand("mi", {
        description = core.gettext("moderator info"),
        func = function(param)
                if not canTalk() then
                        return false, "You need 'shout' in order to use this command"
                end
		minetest.run_server_chatcommand('mi', param)
                -- local output = ""
		-- output = core.get_color_escape_sequence("#d0ff00") .. "MODERATOR INFO: " 
		-- output = output .. core.get_color_escape_sequence("#dfdfff") .. param
    		-- say(output)
		return true
end,
})



--core.register_chatcommand("rainbow", {
--	description = core.gettext("rainbow text"),
--	func = function(param)
--		if not canTalk() then
--			return false, "You need 'shout' in order to use this command"
--		end
--		local step = 360 / param:len()
-- 		local hue = 0
--     		 -- iterate the whole 360 degrees
--		local output = ""
--      		for i = 1, param:len() do
--			local char = param:sub(i,i)
--			if char:match("%s") then
--				output = output .. char
--			else
--        			output = output  .. core.get_color_escape_sequence(color_from_hue(hue)) .. char 
--			end
--        		hue = hue + step
--		end
--		say(output)
--		return true
--end,
--})

core.register_chatcommand("say", {
	description = core.gettext("Send text without applying colour to it"),
	func = function(text)
		say(text)
		return true
	end,
})


core.register_chatcommand("colourchat_status", {
	description = core.gettext("enable/disable the text colouring"),
	func = function(text)
		  if text == "on" or text == "ein" or
		     text == "+" or text == "1" then
		     set_status(true)
		  elseif text == "off" or text == "aus" 
		     or text == "-" or text == "0" then
		     set_status(false)
		  elseif text == "?" or text == "status" 
		     or text == "." or text == "#" 
		     or text == "#" or text == "" then
		     get_status(true)
		  else
		     minetest.display_chat_message(".colourchat_status +|-|1|0..\n")
		  end
		return true
	end,
})



minetest.display_chat_message( "[CSM colour_chat] loaded")