Merge remote-tracking branch 'origin/master' into NALC2
							
								
								
									
										2
									
								
								other_things/irc-old-save/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,2 +0,0 @@ | ||||
| *~ | ||||
|  | ||||
							
								
								
									
										3
									
								
								other_things/irc-old-save/.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,3 +0,0 @@ | ||||
| [submodule "src/LuaIRC"] | ||||
| 	path = irc | ||||
| 	url = https://github.com/ShadowNinja/LuaIRC.git | ||||
| @@ -1,90 +0,0 @@ | ||||
| IRC Mod API | ||||
| =========== | ||||
|  | ||||
| This file documents the Minetest IRC mod API. | ||||
|  | ||||
| Basics | ||||
| ------ | ||||
|  | ||||
| In order to allow your mod to interface with this mod, you must add `irc` | ||||
| to your mod's `depends.txt` file. | ||||
|  | ||||
|  | ||||
| Reference | ||||
| --------- | ||||
|  | ||||
| irc:say([name,] message) | ||||
| Sends <message> to either the channel (if <name> is nil or not specified), | ||||
| or to the given user (if <name> is specified). | ||||
| Example: | ||||
| 	irc:say("Hello, Channel!") | ||||
| 	irc:say("john1234", "How are you?") | ||||
|  | ||||
| irc:register_bot_command(name, cmdDef) | ||||
| 	Registers a new bot command named <name>. | ||||
| 	When an user sends a private message to the bot with the command name, the | ||||
| 	command's function is called. | ||||
| 	Here's the format of a command definition (<cmdDef>): | ||||
| 		cmdDef = { | ||||
| 			params = "<param1> ...",      -- A description of the command's parameters | ||||
| 			description = "My command",   -- A description of what the command does. (one-liner) | ||||
| 			func = function(user, args) | ||||
| 				-- This function gets called when the command is invoked. | ||||
| 				-- <user> is a user table for the user that ran the command. | ||||
| 				--   (See the LuaIRC documentation for details.) | ||||
| 				--   It contains fields such as 'nick' and 'ident' | ||||
| 				-- <args> is a string of arguments to the command (may be "") | ||||
| 				-- This function should return boolean success and a message. | ||||
| 			end, | ||||
| 		}; | ||||
| 	Example: | ||||
| 		irc:register_bot_command("hello", { | ||||
| 			params = "", | ||||
| 			description = "Greet user", | ||||
| 			func = function(user, param) | ||||
| 				return true, "Hello!" | ||||
| 			end, | ||||
| 		}); | ||||
|  | ||||
| irc.joined_players[name] | ||||
| 	This table holds the players who are currently on the channel (may be less | ||||
| 	than the players in the game). It is modified by the /part and /join chat | ||||
| 	commands. | ||||
| 	Example: | ||||
| 	if irc.joined_players["joe"] then | ||||
| 		-- Joe is talking on IRC | ||||
| 	end | ||||
|  | ||||
| irc:register_hook(name, func) | ||||
| 	Registers a function to be called when an event happens. <name> is the name | ||||
| 	of the event, and <func> is the function to be called. See HOOKS below | ||||
| 	for more information | ||||
| 	Example: | ||||
| 	irc:register_hook("OnSend", function(line) | ||||
| 		print("SEND: "..line) | ||||
| 	end) | ||||
|  | ||||
| This mod also supplies some utility functions: | ||||
|  | ||||
| string.expandvars(string, vars) | ||||
| 	Expands all occurrences of the pattern "$(varname)" with the value of | ||||
| 	'varname' in the <vars> table. Variable names not found on the table | ||||
| 	are left verbatim in the string. | ||||
| 	Example: | ||||
| 	local tpl = "$(foo) $(bar) $(baz)" | ||||
| 	local s = tpl:expandvars({foo=1, bar="Hello"}) | ||||
| 	assert(s == "1 Hello $(baz)")  | ||||
|  | ||||
| In addition, all the configuration options decribed in `README.txt` are | ||||
| available to other mods, though they should be considered read-only. Do | ||||
| not modify these settings at runtime or you might crash the server! | ||||
|  | ||||
|  | ||||
| Hooks | ||||
| ----- | ||||
|  | ||||
| The `irc:register_hook` function can register functions to be called | ||||
| when some events happen. The events supported are the same as the LuaIRC | ||||
| ones with a few added (mostly for internal use). | ||||
| See src/LuaIRC/doc/irc.luadoc for more information. | ||||
|  | ||||
| @@ -1,22 +0,0 @@ | ||||
| Copyright (c) 2013, Diego Martinez (kaeza) | ||||
| All rights reserved. | ||||
|  | ||||
| Redistribution and use in source and binary forms, with or without | ||||
| modification, are permitted provided that the following conditions are met: | ||||
|  - Redistributions of source code must retain the above copyright notice, | ||||
|    this list of conditions and the following disclaimer. | ||||
|  - Redistributions in binary form must reproduce the above copyright notice, | ||||
|    this list of conditions and the following disclaimer in the documentation | ||||
|    and/or other materials provided with the distribution. | ||||
|  | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||||
| FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||
| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||
| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||||
| OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  | ||||
| @@ -1,160 +0,0 @@ | ||||
| IRC Mod for Minetest | ||||
| ==================== | ||||
|  | ||||
| Introduction | ||||
| ------------ | ||||
| This mod is just a glue between IRC and Minetest. It provides two-way | ||||
|  communication between the in-game chat, and an arbitrary IRC channel. | ||||
|  | ||||
| The forum topic is at http://minetest.net/forum/viewtopic.php?id=3905 | ||||
|  | ||||
|   | ||||
| Installing | ||||
| ---------- | ||||
|  | ||||
| Quick one line install for linux: | ||||
|  | ||||
| 	cd <Mod directory> && git clone https://github.com/kaeza/minetest-irc.git irc && cd irc && git submodule update --init | ||||
|  | ||||
| Please change `<Mod directory>` to fit your installation of minetest. | ||||
| For more information, see [the wiki](http://wiki.minetest.net/Installing_mods). | ||||
|  | ||||
| The Minetest IRC mod uses submodules, therefore you will have to run | ||||
| `git submodule init` when first installing the mod, and `git submodule update` | ||||
| every time that a submodule is updated.  These steps can be combined as | ||||
| `git submodule update --init`. | ||||
|  | ||||
| The Minetest IRC mod also requires LuaSocket.  This can be installed using your | ||||
| package manager on many distributions, for example on Arch Linux: | ||||
|  | ||||
| 	# pacman -S lua51-socket | ||||
|  | ||||
|  | ||||
| Settings | ||||
| -------- | ||||
| All settings are changed in `minetest.conf`. If any of these settings | ||||
| are not set, the default value is used. | ||||
|  | ||||
|   * `irc.server` (string, default "irc.freenode.net") | ||||
| 	This is the IRC server the mod connects to. | ||||
|  | ||||
|   * `irc.channel` (string, default "##mt-irc-mod") | ||||
| 	The IRC channel to join. | ||||
|  | ||||
|   * `irc.interval` (number, default 2.0) | ||||
| 	This prevents the server from flooding. It should be at | ||||
| 	least 2.0 but can be higher. After four messages this much | ||||
| 	time must pass between folowing messages. | ||||
|  | ||||
|   * `irc.nick` (string, default "MT-FFFFFF") | ||||
| 	Nickname used as "proxy" for the in-game chat.  | ||||
| 	'F' stands for a random base-16 number. | ||||
|  | ||||
|   * `irc.password` (string, default "") | ||||
| 	Password to use when connecting to the server. | ||||
|  | ||||
|   * `irc.NSPass` (string, default nil) | ||||
| 	NickServ password. Don't use this if you use SASL authentication. | ||||
|  | ||||
|   * `irc.sasl.pass` (string, default nil) | ||||
| 	SASL password, same as nickserv password. | ||||
| 	You should use this instead of NickServ authentication | ||||
| 	if the server supports it. | ||||
|  | ||||
|   * `irc.sasl.user` (string, default `irc.nick`) | ||||
| 	The SASL username. This should normaly be set to your main NickServ account name. | ||||
|  | ||||
|   * `irc.debug` (boolean, default false) | ||||
| 	Whether to output debug information. | ||||
|  | ||||
|   * `irc.disable_auto_connect` (boolean, default false) | ||||
| 	If false, the bot is connected by default. If true, a player with | ||||
| 	the 'irc_admin' privilege has to use the /irc_connect command to | ||||
| 	connect to the server. | ||||
|  | ||||
|   * `irc.disable_auto_join` (boolean, default false) | ||||
| 	If false, players join the channel automatically upon entering the | ||||
| 	game. If true, each user must manually use the /join command to | ||||
| 	join the channel. In any case, the players may use the /part | ||||
| 	command to opt-out of being in the channel. | ||||
|  | ||||
|   * `irc.send_join_part` (boolean, default true) | ||||
| 	Determines whether to send player join and part messages to the channel. | ||||
|  | ||||
| Usage | ||||
| ----- | ||||
|  | ||||
| Once the game is connected to the IRC channel, chatting using the 'T' or | ||||
| F10 hotkeys will send the messages to the channel, and will be visible | ||||
| by anyone. Also, when someone sends a message to the channel, that text | ||||
| will be visible in-game. | ||||
|  | ||||
| Messages that begin with `[off]` from in-game or IRC are not sent to the | ||||
| other side. | ||||
|  | ||||
| This mod also adds a few chat commands: | ||||
|  | ||||
|   * `/irc_msg <nick> <message>` | ||||
| 	Sends a private message to a IRC user. | ||||
|  | ||||
|   * `/join` | ||||
| 	Join the IRC chat. | ||||
|  | ||||
|   * `/part` | ||||
| 	Part the IRC chat. | ||||
|  | ||||
|   * `/irc_connect` | ||||
| 	Connect the bot manually to the IRC network. | ||||
|  | ||||
|   * `/irc_disconnect` | ||||
| 	Disconnect the bot manually from the IRC network (this does not | ||||
| 	shutdown the game). | ||||
|  | ||||
|   * `/irc_reconnect` | ||||
| 	Equivilant to `/irc_disconnect` followed by `/irc_connect`. | ||||
|  | ||||
| You can also send private messages from IRC to in-game players. | ||||
|  | ||||
| To do it, you must send a private message to the bot (set with | ||||
| the `irc.nick` option above), in the following format: | ||||
|  | ||||
| 	@playername message | ||||
|  | ||||
| For example, if there's a player named `mtuser`, you can send him/her | ||||
| a private message from IRC with: | ||||
|  | ||||
| 	/msg server_nick @mtuser Hello! | ||||
|  | ||||
| To avoid possible misunderstandings (since all in-game players use the | ||||
| same IRC user to converse with you), the "proxy" user will reject any | ||||
| private messages that are not in that format, and will send back a | ||||
| nice reminder as a private message. | ||||
|  | ||||
| The bot also supports some basic commands, which are invoked by sending | ||||
| a private message to it. Use `!list` to get a list of commands, and | ||||
| `!help <command>` to get help about a specific command. | ||||
|  | ||||
|  | ||||
| Thanks | ||||
| ------ | ||||
|  | ||||
| I'd like to thank the users who supported this mod both on the Minetest | ||||
| Forums and on the #minetest channel. In no particular order: | ||||
|  | ||||
| 0gb.us, ShadowNinja, Shaun/kizeren, RAPHAEL, DARGON, Calinou, Exio, | ||||
| vortexlabs/mrtux, marveidemanis, marktraceur, jmf/john\_minetest, | ||||
| sdzen/Muadtralk, VanessaE, PilzAdam, sfan5, celeron55, KikaRz, | ||||
| OldCoder, RealBadAngel, and all the people who commented in the | ||||
| forum topic. Thanks to you all! | ||||
|  | ||||
|  | ||||
| License | ||||
| ------- | ||||
|  | ||||
| (C) 2012-2013 Diego Martínez <kaeza@users.sf.net> | ||||
|  | ||||
| See LICENSE.txt for licensing information. | ||||
|  | ||||
| The files in the irc directory are part of the LuaIRC project. | ||||
| See irc/LICENSE.txt for licensing information. | ||||
|  | ||||
| @@ -1,165 +0,0 @@ | ||||
| irc.whereis_timer = {} | ||||
| irc.whereis_timer_max_limit = 120 | ||||
| irc.bot_commands = {} | ||||
|  | ||||
| function irc:check_botcmd(msg) | ||||
| 	local prefix = irc.config.command_prefix | ||||
| 	local nick = irc.conn.nick:lower() | ||||
| 	local text = msg.args[2] | ||||
| 	local nickpart = text:sub(1, #nick + 2):lower() | ||||
|  | ||||
| 	-- First check for a nick prefix | ||||
| 	if nickpart == nick..": " or | ||||
| 	   nickpart == nick..", " then | ||||
| 		self:bot_command(msg, text:sub(#nick + 3)) | ||||
| 		return true | ||||
| 	-- Then check for the configured prefix | ||||
| 	elseif prefix and text:sub(1, #prefix):lower() == prefix:lower() then | ||||
| 		self:bot_command(msg, text:sub(#prefix + 1)) | ||||
| 		return true | ||||
| 	end | ||||
| 	return false | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc:bot_command(msg, text) | ||||
| 	if text:sub(1, 1) == "@" then | ||||
| 		local found, _, player_to, message = text:find("^.([^%s]+)%s(.+)$") | ||||
| 		if not minetest.get_player_by_name(player_to) then | ||||
| 			irc:reply("User '"..player_to.."' is not in the game.") | ||||
| 			return | ||||
| 		elseif not irc.joined_players[player_to] then | ||||
| 			irc:reply("User '"..player_to.."' is not using IRC.") | ||||
| 			return | ||||
| 		end | ||||
| 		minetest.chat_send_player(player_to, | ||||
| 				"PM from "..msg.user.nick.."@IRC: "..message, false) | ||||
| 		irc:reply("Message sent!") | ||||
| 		return | ||||
| 	end | ||||
| 	local pos = text:find(" ", 1, true) | ||||
| 	local cmd, args | ||||
| 	if pos then | ||||
| 		cmd = text:sub(1, pos - 1) | ||||
| 		args = text:sub(pos + 1) | ||||
| 	else | ||||
| 		cmd = text | ||||
| 		args = "" | ||||
| 	end | ||||
|   | ||||
| 	if not self.bot_commands[cmd] then | ||||
| 		self:reply("Unknown command '"..cmd.."'. Try 'list'." | ||||
| 			.." Or use @playername <message> to send a private message") | ||||
| 		return | ||||
| 	end | ||||
|   | ||||
| 	local success, message = self.bot_commands[cmd].func(msg.user, args) | ||||
| 	if message then | ||||
| 		self:reply(message) | ||||
| 	end | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc:register_bot_command(name, def) | ||||
| 	if (not def.func) or (type(def.func) ~= "function") then | ||||
| 		error("Erroneous bot command definition. def.func missing.", 2) | ||||
| 	elseif name:sub(1, 1) == "@" then | ||||
| 		error("Erroneous bot command name. Command name begins with '@'.", 2) | ||||
| 	end | ||||
| 	self.bot_commands[name] = def | ||||
| end | ||||
|  | ||||
|  | ||||
| irc:register_bot_command("help", { | ||||
| 	params = "<command>", | ||||
| 	description = "Get help about a command", | ||||
| 	func = function(user, args) | ||||
| 		if args == "" then | ||||
| 			return false, "No command name specified. Use 'list' for a list of commands." | ||||
| 		end | ||||
|  | ||||
| 		local cmd = irc.bot_commands[args] | ||||
| 		if not cmd then | ||||
| 			return false, "Unknown command '"..cmdname.."'." | ||||
| 		end | ||||
|  | ||||
| 		return true, ("Usage: %c%s %s -- %s"):format( | ||||
| 				irc.config.command_prefix, | ||||
| 				args, | ||||
| 				cmd.params or "<no parameters>", | ||||
| 				cmd.description or "<no description>") | ||||
| 	end | ||||
| }) | ||||
|  | ||||
|  | ||||
| irc:register_bot_command("list", { | ||||
| 	params = "", | ||||
| 	description = "List available commands.", | ||||
| 	func = function(user, args) | ||||
| 		local cmdlist = "Available commands: " | ||||
| 		for name, cmd in pairs(irc.bot_commands) do | ||||
| 			cmdlist = cmdlist..name..", " | ||||
| 		end | ||||
| 		return true, cmdlist.." -- Use 'help <command name>' to get" | ||||
| 			.." help about a specific command." | ||||
| 	end | ||||
| }) | ||||
|  | ||||
|  | ||||
| irc:register_bot_command("whereis", { | ||||
| 	params = "<player>", | ||||
| 	description = "Tell the location of <player>", | ||||
| 	func = function(user, args) | ||||
| 		if args == "" then | ||||
| 			return false, "Player name required." | ||||
| 		end | ||||
| 		local player = minetest.get_player_by_name(args) | ||||
| 		if not player then | ||||
| 			return false, "There is no player named '"..args.."'" | ||||
| 		end | ||||
| 		if irc.whereis_timer[user.nick] ~= nil then | ||||
| 			local timer_player = os.difftime(os.time(),irc.whereis_timer[user.nick]) | ||||
| 			if timer_player < irc.whereis_timer_max_limit then | ||||
| 				local answer = "Command used too often, retry in %d seconds." | ||||
| 				return false,answer:format(irc.whereis_timer_max_limit - timer_player) | ||||
| 			end | ||||
| 		end | ||||
| 		local fmt = "Player %s is at (%.2f,%.2f,%.2f)" | ||||
| 		local pos = player:getpos() | ||||
| 		irc.whereis_timer[user.nick] = os.time() | ||||
| 		minetest.log("action","IRC user ".. user.nick.."!"..user.username.."@"..user.host.." asked for position of player "..player:get_player_name()) | ||||
| 		minetest.chat_send_player(player:get_player_name(),"IRC user ".. user.nick.."!"..user.username.."@"..user.host.." asked for your position") | ||||
| 		return true, fmt:format(args, pos.x, pos.y, pos.z) | ||||
| 	end | ||||
| }) | ||||
|  | ||||
|  | ||||
| local starttime = os.time() | ||||
| irc:register_bot_command("uptime", { | ||||
| 	description = "Tell how much time the server has been up", | ||||
| 	func = function(user, args) | ||||
| 		local cur_time = os.time() | ||||
| 		local diff = os.difftime(cur_time, starttime) | ||||
| 		local fmt = "Server has been running for %d:%02d:%02d" | ||||
| 		return true, fmt:format( | ||||
| 			math.floor(diff / 60 / 60), | ||||
| 			math.floor(diff / 60) % 60, | ||||
| 			math.floor(diff) % 60 | ||||
| 		) | ||||
| 	end | ||||
| }) | ||||
|  | ||||
|  | ||||
| irc:register_bot_command("players", { | ||||
| 	description = "List the players on the server", | ||||
| 	func = function(user, args) | ||||
| 		local players = minetest.get_connected_players() | ||||
| 		local names = {} | ||||
| 		for _, player in pairs(players) do | ||||
| 			table.insert(names, player:get_player_name()) | ||||
| 		end | ||||
| 		return true, "Connected players: " | ||||
| 				..table.concat(names, ", ") | ||||
| 	end | ||||
| }) | ||||
|  | ||||
| @@ -1,40 +0,0 @@ | ||||
| -- This file is licensed under the terms of the BSD 2-clause license. | ||||
| -- See LICENSE.txt for details. | ||||
|  | ||||
|  | ||||
| minetest.register_on_joinplayer(function(player) | ||||
| 	local name = player:get_player_name() | ||||
| 	if irc.connected and irc.config.send_join_part then | ||||
| 		irc:say("*** "..name.." joined the game") | ||||
| 	end | ||||
| end) | ||||
|  | ||||
|  | ||||
| minetest.register_on_leaveplayer(function(player) | ||||
| 	local name = player:get_player_name() | ||||
| 	if irc.connected and irc.config.send_join_part then | ||||
| 		irc:say("*** "..name.." left the game") | ||||
| 	end | ||||
| end) | ||||
|  | ||||
|  | ||||
| minetest.register_on_chat_message(function(name, message) | ||||
| 	if not irc.connected | ||||
| 	   or message:sub(1, 1) == "/" | ||||
| 	   or message:sub(1, 5) == "[off]" | ||||
| 	   or not irc.joined_players[name] | ||||
| 	   or (not minetest.check_player_privs(name, {shout=true})) then | ||||
| 		return | ||||
| 	end | ||||
| 	local nl = message:find("\n", 1, true) | ||||
| 	if nl then | ||||
| 		message = message:sub(1, nl - 1) | ||||
| 	end | ||||
| 	irc:say(irc:playerMessage(name, message)) | ||||
| end) | ||||
|  | ||||
|  | ||||
| minetest.register_on_shutdown(function() | ||||
| 	irc:disconnect("Game shutting down.") | ||||
| end) | ||||
|  | ||||
| @@ -1,126 +0,0 @@ | ||||
| -- This file is licensed under the terms of the BSD 2-clause license. | ||||
| -- See LICENSE.txt for details. | ||||
|  | ||||
| -- Note: This file does NOT conatin every chat command, only general ones. | ||||
| -- Feature-specific commands (like /join) are in their own files. | ||||
|  | ||||
|  | ||||
| minetest.register_chatcommand("irc_msg", { | ||||
| 	params = "<name> <message>", | ||||
| 	description = "Send a private message to an IRC user", | ||||
| 	privs = {shout=true}, | ||||
| 	func = function(name, param) | ||||
| 		if not irc.connected then | ||||
| 			minetest.chat_send_player(name, "Not connected to IRC. Use /irc_connect to connect.") | ||||
| 			return | ||||
| 		end | ||||
| 		local found, _, toname, message = param:find("^([^%s]+)%s(.+)") | ||||
| 		if not found then | ||||
| 			minetest.chat_send_player(name, "Invalid usage, see /help irc_msg.") | ||||
| 			return | ||||
| 		end | ||||
| 		local toname_l = toname:lower() | ||||
| 		local validNick = false | ||||
| 		for nick, user in pairs(irc.conn.channels[irc.config.channel].users) do | ||||
| 			if nick:lower() == toname_l then | ||||
| 				validNick = true | ||||
| 				break | ||||
| 			end | ||||
| 		end | ||||
| 		if toname_l:find("serv$") or toname_l:find("bot$") then | ||||
| 			validNick = false | ||||
| 		end | ||||
| 		if not validNick then | ||||
| 			minetest.chat_send_player(name, | ||||
| 				"You can not message that user. (Hint: They have to be in the channel)") | ||||
| 			return | ||||
| 		end | ||||
| 		irc:say(toname, irc:playerMessage(name, message)) | ||||
| 		minetest.chat_send_player(name, "Message sent!") | ||||
| 	end | ||||
| }) | ||||
|  | ||||
|  | ||||
| minetest.register_chatcommand("irc_names", { | ||||
| 	params = "", | ||||
| 	description = "List the users in IRC.", | ||||
| 	func = function(name, params) | ||||
| 		if not irc.connected then | ||||
| 			minetest.chat_send_player(name, "Not connected to IRC. Use /irc_connect to connect.") | ||||
| 			return | ||||
| 		end | ||||
| 		local users = { } | ||||
| 		for k, v in pairs(irc.conn.channels[irc.config.channel].users) do | ||||
| 			table.insert(users, k) | ||||
| 		end | ||||
| 		minetest.chat_send_player(name, "Users in IRC: "..table.concat(users, ", ")) | ||||
| 	end | ||||
| }) | ||||
|  | ||||
|  | ||||
| minetest.register_chatcommand("irc_connect", { | ||||
| 	description = "Connect to the IRC server.", | ||||
| 	privs = {irc_admin=true}, | ||||
| 	func = function(name, param) | ||||
| 		if irc.connected then | ||||
| 			minetest.chat_send_player(name, "You are already connected to IRC.") | ||||
| 			return | ||||
| 		end | ||||
| 		minetest.chat_send_player(name, "IRC: Connecting...") | ||||
| 		irc:connect() | ||||
| 	end | ||||
| }) | ||||
|  | ||||
|  | ||||
| minetest.register_chatcommand("irc_disconnect", { | ||||
| 	params = "[message]", | ||||
| 	description = "Disconnect from the IRC server.", | ||||
| 	privs = {irc_admin=true}, | ||||
| 	func = function(name, param) | ||||
| 		if not irc.connected then | ||||
| 			minetest.chat_send_player(name, "You are not connected to IRC.") | ||||
| 			return | ||||
| 		end | ||||
| 		if params == "" then | ||||
| 			params = "Manual disconnect by "..name | ||||
| 		end | ||||
| 		irc:disconnect(param) | ||||
| 	end | ||||
| }) | ||||
|  | ||||
|  | ||||
| minetest.register_chatcommand("irc_reconnect", { | ||||
| 	description = "Reconnect to the IRC server.", | ||||
| 	privs = {irc_admin=true}, | ||||
| 	func = function(name, param) | ||||
| 		if not irc.connected then | ||||
| 			minetest.chat_send_player(name, "You are not connected to IRC.") | ||||
| 			return | ||||
| 		end | ||||
| 		irc:disconnect("Reconnecting...") | ||||
| 		irc:connect() | ||||
| 	end | ||||
| }) | ||||
|  | ||||
|  | ||||
| minetest.register_chatcommand("irc_quote", { | ||||
| 	params = "<command>", | ||||
| 	description = "Send a raw command to the IRC server.", | ||||
| 	privs = {irc_admin=true}, | ||||
| 	func = function(name, param) | ||||
| 		if not irc.connected then | ||||
| 			minetest.chat_send_player(name, "You are not connected to IRC.") | ||||
| 			return | ||||
| 		end | ||||
| 		irc:queue(param) | ||||
| 		minetest.chat_send_player(name, "Command sent!") | ||||
| 	end | ||||
| }) | ||||
|  | ||||
|  | ||||
| local oldme = minetest.chatcommands["me"].func | ||||
| minetest.chatcommands["me"].func = function(name, param, ...) | ||||
| 	oldme(name, param, ...) | ||||
| 	irc:say(("* %s %s"):format(name, param)) | ||||
| end | ||||
|  | ||||
| @@ -1,59 +0,0 @@ | ||||
| -- This file is licensed under the terms of the BSD 2-clause license. | ||||
| -- See LICENSE.txt for details. | ||||
|  | ||||
|  | ||||
| irc.config = {} | ||||
|  | ||||
| local function setting(stype, name, default) | ||||
| 	local value | ||||
| 	if stype == "bool" then | ||||
| 		value = minetest.setting_getbool("irc."..name) | ||||
| 	elseif stype == "string" then | ||||
| 		value = minetest.setting_get("irc."..name) | ||||
| 	elseif stype == "number" then | ||||
| 		value = tonumber(minetest.setting_get("irc."..name)) | ||||
| 	end | ||||
| 	if value == nil then | ||||
| 		value = default | ||||
| 	end | ||||
| 	irc.config[name] = value | ||||
| end | ||||
|  | ||||
| ------------------------- | ||||
| -- BASIC USER SETTINGS -- | ||||
| ------------------------- | ||||
|  | ||||
| setting("string", "nick") -- Nickname (default "MT-<hash>", <hash> 6 random hexidecimal characters) | ||||
| setting("string", "server", "irc.freenode.net") -- Server to connect on joinplayer | ||||
| setting("number", "port", 6667) -- Port to connect on joinplayer | ||||
| setting("string", "NSPass") -- NickServ password | ||||
| setting("string", "sasl.user", irc.config.nick) -- SASL username | ||||
| setting("string", "sasl.pass") -- SASL password | ||||
| setting("string", "channel", "##mt-irc-mod") -- Channel to join | ||||
| setting("string", "key") -- Key for the channel | ||||
| setting("bool",   "send_join_part", true) -- Whether to send player join and part messages to the channel | ||||
|  | ||||
| ----------------------- | ||||
| -- ADVANCED SETTINGS -- | ||||
| ----------------------- | ||||
|  | ||||
| setting("string", "password") -- Server password | ||||
| setting("bool",   "secure", false) -- Enable a TLS connection, requires LuaSEC | ||||
| setting("number", "timeout", 60) -- Underlying socket timeout in seconds. | ||||
| setting("string", "command_prefix") -- Prefix to use for bot commands | ||||
| setting("bool",   "debug", false) -- Enable debug output | ||||
| setting("bool",   "enable_player_part", true) -- Whether to enable players joining and parting the channel | ||||
| setting("bool",   "auto_join", true) -- Whether to automatically show players in the channel when they join | ||||
| setting("bool",   "auto_connect", true) -- Whether to automatically connect to the server on mod load | ||||
|  | ||||
| -- Generate a random nickname if one isn't specified. | ||||
| if not irc.config.nick then | ||||
| 	local pr = PseudoRandom(os.time()) | ||||
| 	-- Workaround for bad distribution in minetest PRNG implementation. | ||||
| 	irc.config.nick = ("MT-%02X%02X%02X"):format( | ||||
| 		pr:next(0, 255), | ||||
| 		pr:next(0, 255), | ||||
| 		pr:next(0, 255) | ||||
| 	) | ||||
| end | ||||
|  | ||||
| @@ -1,260 +0,0 @@ | ||||
| -- This file is licensed under the terms of the BSD 2-clause license. | ||||
| -- See LICENSE.txt for details. | ||||
|  | ||||
| -- MIME is part of LuaSocket | ||||
| local b64e = require("mime").b64 | ||||
|  | ||||
| irc.hooks = {} | ||||
| irc.registered_hooks = {} | ||||
|  | ||||
|  | ||||
| -- TODO: Add proper conversion from CP1252 to UTF-8. | ||||
| local stripped_chars = {"\2", "\31"} | ||||
| for c = 127, 255 do | ||||
| 	table.insert(stripped_chars, string.char(c)) | ||||
| end | ||||
| stripped_chars = "["..table.concat(stripped_chars, "").."]" | ||||
|  | ||||
| local function normalize(text) | ||||
| 	-- Strip colors | ||||
| 	text = text:gsub("\3[0-9][0-9,]*", "") | ||||
|  | ||||
| 	return text:gsub(stripped_chars, "") | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc:doHook(conn) | ||||
| 	for name, hook in pairs(self.registered_hooks) do | ||||
| 		for _, func in pairs(hook) do | ||||
| 			conn:hook(name, func) | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc:register_hook(name, func) | ||||
| 	self.registered_hooks[name] = self.registered_hooks[name] or {} | ||||
| 	table.insert(self.registered_hooks[name], func) | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc.hooks.raw(line) | ||||
| 	if irc.config.debug then | ||||
| 		print("RECV: "..line) | ||||
| 	end | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc.hooks.send(line) | ||||
| 	if irc.config.debug then | ||||
| 		print("SEND: "..line) | ||||
| 	end | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc.hooks.chat(msg) | ||||
| 	local channel, text = msg.args[1], msg.args[2] | ||||
| 	if text:sub(1, 1) == string.char(1) then | ||||
| 		irc.conn:invoke("OnCTCP", msg) | ||||
| 		return | ||||
| 	end | ||||
|  | ||||
| 	if channel == irc.conn.nick then | ||||
| 		irc.last_from = msg.user.nick | ||||
| 		irc.conn:invoke("PrivateMessage", msg) | ||||
| 	else | ||||
| 		irc.last_from = channel | ||||
| 		irc.conn:invoke("OnChannelChat", msg) | ||||
| 	end | ||||
| end | ||||
|  | ||||
|  | ||||
| local function get_core_version() | ||||
| 	local status = minetest.get_server_status() | ||||
| 	local start_pos = select(2, status:find("version=", 1, true)) | ||||
| 	local end_pos = status:find(",", start_pos, true) | ||||
| 	return status:sub(start_pos + 1, end_pos - 1) | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc.hooks.ctcp(msg) | ||||
| 	local text = msg.args[2]:sub(2, -2)  -- Remove ^C | ||||
| 	local args = text:split(' ') | ||||
| 	local command = args[1]:upper() | ||||
|  | ||||
| 	local function reply(s) | ||||
| 		irc:queue(irc.msgs.notice(msg.user.nick, | ||||
| 				("\1%s %s\1"):format(command, s))) | ||||
| 	end | ||||
|  | ||||
| 	if command == "ACTION" and msg.args[1] == irc.config.channel then | ||||
| 		local action = text:sub(8, -1) | ||||
| 		irc:sendLocal(("* %s@IRC %s"):format(msg.user.nick, action)) | ||||
| 	elseif command == "VERSION" then | ||||
| 		reply(("Minetest version %s, IRC mod version %s.") | ||||
| 			:format(get_core_version(), irc.version)) | ||||
| 	elseif command == "PING" then | ||||
| 		reply(args[2]) | ||||
| 	elseif command == "TIME" then | ||||
| 		reply(os.date()) | ||||
| 	end | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc.hooks.channelChat(msg) | ||||
| 	local text = normalize(msg.args[2]) | ||||
|  | ||||
| 	irc:check_botcmd(msg) | ||||
|  | ||||
| 	-- Don't let a user impersonate someone else by using the nick "IRC" | ||||
| 	if msg.user.nick == "IRC" then | ||||
| 		irc:sendLocal("<IRC@IRC> "..text) | ||||
| 		return | ||||
| 	end | ||||
|  | ||||
| 	-- Support multiple servers in a channel better by converting: | ||||
| 	-- "<server@IRC> <player> message" into "<player@server> message" | ||||
| 	-- "<server@IRC> *** player joined/left the game" into "*** player joined/left server" | ||||
| 	-- and "<server@IRC> * player orders a pizza" into "* player@server orders a pizza" | ||||
| 	local foundchat, _, chatnick, chatmessage = | ||||
| 		text:find("^<([^>]+)> (.*)$") | ||||
| 	local foundjoin, _, joinnick = | ||||
| 		text:find("^%*%*%* ([^%s]+) joined the game$") | ||||
| 	local foundleave, _, leavenick = | ||||
| 		text:find("^%*%*%* ([^%s]+) left the game$") | ||||
| 	local foundaction, _, actionnick, actionmessage = | ||||
| 		text:find("^%* ([^%s]+) (.*)$") | ||||
|  | ||||
| 	if text:sub(1, 5) == "[off]" then | ||||
| 		return | ||||
| 	elseif foundchat then | ||||
| 		irc:sendLocal(("<%s@%s> %s") | ||||
| 				:format(chatnick, msg.user.nick, chatmessage)) | ||||
| 	elseif foundjoin then | ||||
| 		irc:sendLocal(("*** %s joined %s") | ||||
| 				:format(joinnick, msg.user.nick)) | ||||
| 	elseif foundleave then | ||||
| 		irc:sendLocal(("*** %s left %s") | ||||
| 				:format(leavenick, msg.user.nick)) | ||||
| 	elseif foundaction then | ||||
| 		irc:sendLocal(("* %s@%s %s") | ||||
| 				:format(actionnick, msg.user.nick, actionmessage)) | ||||
| 	else | ||||
| 		irc:sendLocal(("<%s@IRC> %s"):format(msg.user.nick, text)) | ||||
| 	end | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc.hooks.pm(msg) | ||||
| 	-- Trim prefix if it is found | ||||
| 	local text = msg.args[2] | ||||
| 	local prefix = irc.config.command_prefix | ||||
| 	if prefix and text:sub(1, #prefix) == prefix then | ||||
| 		text = text:sub(#prefix + 1) | ||||
| 	end | ||||
| 	irc:bot_command(msg, text) | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc.hooks.kick(channel, target, prefix, reason) | ||||
| 	if target == irc.conn.nick then | ||||
| 		minetest.chat_send_all("IRC: kicked from "..channel.." by "..prefix.nick..".") | ||||
| 		irc:disconnect("Kicked") | ||||
| 	else | ||||
| 		irc:sendLocal(("-!- %s was kicked from %s by %s [%s]") | ||||
| 				:format(target, channel, prefix.nick, reason)) | ||||
| 	end | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc.hooks.notice(user, target, message) | ||||
| 	if user.nick and target == irc.config.channel then | ||||
| 		irc:sendLocal("-"..user.nick.."@IRC- "..message) | ||||
| 	end | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc.hooks.mode(user, target, modes, ...) | ||||
| 	local by = "" | ||||
| 	if user.nick then | ||||
| 		by = " by "..user.nick | ||||
| 	end | ||||
| 	local options = "" | ||||
| 	if select("#", ...) > 0 then | ||||
| 		options = " " | ||||
| 	end | ||||
| 	options = options .. table.concat({...}, " ") | ||||
| 	minetest.chat_send_all(("-!- mode/%s [%s%s]%s") | ||||
| 			:format(target, modes, options, by)) | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc.hooks.nick(user, newNick) | ||||
| 	irc:sendLocal(("-!- %s is now known as %s") | ||||
| 			:format(user.nick, newNick)) | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc.hooks.join(user, channel) | ||||
| 	irc:sendLocal(("-!- %s joined %s") | ||||
| 			:format(user.nick, channel)) | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc.hooks.part(user, channel, reason) | ||||
| 	reason = reason or "" | ||||
| 	irc:sendLocal(("-!- %s has left %s [%s]") | ||||
| 			:format(user.nick, channel, reason)) | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc.hooks.quit(user, reason) | ||||
| 	irc:sendLocal(("-!- %s has quit [%s]") | ||||
| 			:format(user.nick, reason)) | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc.hooks.disconnect(message, isError) | ||||
| 	irc.connected = false | ||||
| 	if isError then | ||||
| 		minetest.log("error",  "IRC: Error: Disconnected, reconnecting in one minute.") | ||||
| 		minetest.chat_send_all("IRC: Error: Disconnected, reconnecting in one minute.") | ||||
| 		minetest.after(60, irc.connect, irc) | ||||
| 	else | ||||
| 		minetest.log("action", "IRC: Disconnected.") | ||||
| 		minetest.chat_send_all("IRC: Disconnected.") | ||||
| 	end | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc.hooks.preregister(conn) | ||||
| 	if not (irc.config["sasl.user"] and irc.config["sasl.pass"]) then return end | ||||
| 	local authString = b64e( | ||||
| 		("%s\x00%s\x00%s"):format( | ||||
| 		irc.config["sasl.user"], | ||||
| 		irc.config["sasl.user"], | ||||
| 		irc.config["sasl.pass"]) | ||||
| 	) | ||||
| 	conn:send("CAP REQ sasl") | ||||
| 	conn:send("AUTHENTICATE PLAIN") | ||||
| 	conn:send("AUTHENTICATE "..authString) | ||||
| 	--LuaIRC will send CAP END | ||||
| end | ||||
|  | ||||
|  | ||||
| irc:register_hook("PreRegister",     irc.hooks.preregister) | ||||
| irc:register_hook("OnRaw",           irc.hooks.raw) | ||||
| irc:register_hook("OnSend",          irc.hooks.send) | ||||
| irc:register_hook("DoPrivmsg",       irc.hooks.chat) | ||||
| irc:register_hook("OnPart",          irc.hooks.part) | ||||
| irc:register_hook("OnKick",          irc.hooks.kick) | ||||
| irc:register_hook("OnJoin",          irc.hooks.join) | ||||
| irc:register_hook("OnQuit",          irc.hooks.quit) | ||||
| irc:register_hook("NickChange",      irc.hooks.nick) | ||||
| irc:register_hook("OnCTCP",          irc.hooks.ctcp) | ||||
| irc:register_hook("PrivateMessage",  irc.hooks.pm) | ||||
| irc:register_hook("OnNotice",        irc.hooks.notice) | ||||
| irc:register_hook("OnChannelChat",   irc.hooks.channelChat) | ||||
| irc:register_hook("OnModeChange",    irc.hooks.mode) | ||||
| irc:register_hook("OnDisconnect",    irc.hooks.disconnect) | ||||
|  | ||||
| @@ -1,157 +0,0 @@ | ||||
| -- This file is licensed under the terms of the BSD 2-clause license. | ||||
| -- See LICENSE.txt for details. | ||||
|  | ||||
| local modpath = minetest.get_modpath(minetest.get_current_modname()) | ||||
|  | ||||
| package.path = | ||||
| 		-- To find LuaIRC's init.lua | ||||
| 		modpath.."/?/init.lua;" | ||||
| 		-- For LuaIRC to find its files | ||||
| 		..modpath.."/?.lua;" | ||||
| 		..package.path | ||||
|  | ||||
| -- The build of Lua that Minetest comes with only looks for libraries under | ||||
| -- /usr/local/share and /usr/local/lib but LuaSocket is often installed under | ||||
| -- /usr/share and /usr/lib. | ||||
| if not rawget(_G,"jit") and package.config:sub(1, 1) == "/" then | ||||
| 	package.path = package.path.. | ||||
| 			";/usr/share/lua/5.1/?.lua".. | ||||
| 			";/usr/share/lua/5.1/?/init.lua" | ||||
|    	package.cpath = package.cpath.. | ||||
|  --			";/usr/lib/lua/5.1/?.so" | ||||
| 			";/usr/lib/x86_64-linux-gnu/lua/5.1/?.so" | ||||
| end | ||||
|  | ||||
| irc = { | ||||
| 	version = "0.2.0", | ||||
| 	connected = false, | ||||
| 	cur_time = 0, | ||||
| 	message_buffer = {}, | ||||
| 	recent_message_count = 0, | ||||
| 	joined_players = {}, | ||||
| 	modpath = modpath, | ||||
| 	lib = require("irc"), | ||||
| } | ||||
|  | ||||
| -- Compatibility | ||||
| mt_irc = irc | ||||
|  | ||||
| dofile(modpath.."/config.lua") | ||||
| dofile(modpath.."/messages.lua") | ||||
| dofile(modpath.."/hooks.lua") | ||||
| dofile(modpath.."/callback.lua") | ||||
| dofile(modpath.."/chatcmds.lua") | ||||
| dofile(modpath.."/botcmds.lua") | ||||
| if irc.config.enable_player_part then | ||||
| 	dofile(modpath.."/player_part.lua") | ||||
| else | ||||
| 	setmetatable(irc.joined_players, {__index = function(index) return true end}) | ||||
| end | ||||
|  | ||||
| minetest.register_privilege("irc_admin", { | ||||
| 	description = "Allow IRC administrative tasks to be performed.", | ||||
| 	give_to_singleplayer = true | ||||
| }) | ||||
|  | ||||
| local stepnum = 0 | ||||
|  | ||||
| minetest.register_globalstep(function(dtime) return irc:step(dtime) end) | ||||
|  | ||||
| function irc:step(dtime) | ||||
| 	if stepnum == 3 then | ||||
| 		if self.config.auto_connect then | ||||
| 			self:connect() | ||||
| 		end | ||||
| 	end | ||||
| 	stepnum = stepnum + 1 | ||||
|  | ||||
| 	if not self.connected then return end | ||||
|  | ||||
| 	-- Hooks will manage incoming messages and errors | ||||
| 	local good, err = xpcall(function() self.conn:think() end, debug.traceback) | ||||
| 	if not good then | ||||
| 		print(err) | ||||
| 		return | ||||
| 	end | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc:connect() | ||||
| 	if self.connected then | ||||
| 		minetest.log("error", "IRC: Ignoring attempt to connect when already connected.") | ||||
| 		return | ||||
| 	end | ||||
| 	self.conn = irc.lib.new({ | ||||
| 		nick = self.config.nick, | ||||
| 		username = "Minetest", | ||||
| 		realname = "Minetest", | ||||
| 	}) | ||||
| 	self:doHook(self.conn) | ||||
| 	local good, message = pcall(function() | ||||
| 		self.conn:connect({ | ||||
| 			host = self.config.server, | ||||
| 			port = self.config.port, | ||||
| 			password = self.config.password, | ||||
| 			timeout = self.config.timeout, | ||||
| 			secure = self.config.secure | ||||
| 		}) | ||||
| 	end) | ||||
|  | ||||
| 	if not good then | ||||
| 		minetest.log("error", ("IRC: Connection error: %s: %s -- Reconnecting in ten minutes...") | ||||
| 					:format(self.config.server, message)) | ||||
| 		minetest.after(600, function() self:connect() end) | ||||
| 		return | ||||
| 	end | ||||
|  | ||||
| 	print("== This is a debug line, please check for it ==") | ||||
| 	print(self.config.NSPass) | ||||
| 	print("=== DEBUG FINISHED ===") | ||||
| 	if self.config.NSPass then | ||||
| 		self:say("NickServ", "IDENTIFY "..self.config.NSPass) | ||||
| 	end | ||||
|  | ||||
| 	self.conn:join(self.config.channel, self.config.key) | ||||
| 	self.connected = true | ||||
| 	minetest.log("action", "IRC: Connected!") | ||||
| 	minetest.chat_send_all("IRC: Connected!") | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc:disconnect(message) | ||||
| 	if self.connected then | ||||
| 		--The OnDisconnect hook will clear self.connected and print a disconnect message | ||||
| 		self.conn:disconnect(message) | ||||
| 	end | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc:say(to, message) | ||||
| 	if not message then | ||||
| 		message = to | ||||
| 		to = self.config.channel | ||||
| 	end | ||||
| 	to = to or self.config.channel | ||||
|  | ||||
| 	self:queue(irc.msgs.privmsg(to, message)) | ||||
| end | ||||
|  | ||||
|  | ||||
| function irc:reply(message) | ||||
| 	if not self.last_from then | ||||
| 		return | ||||
| 	end | ||||
| 	message = message:gsub("[\r\n%z]", " \\n ") | ||||
| 	self:say(self.last_from, message) | ||||
| end | ||||
|  | ||||
| function irc:send(msg) | ||||
| 	if not self.connected then return end | ||||
| 	self.conn:send(msg) | ||||
| end | ||||
|  | ||||
| function irc:queue(msg) | ||||
| 	if not self.connected then return end | ||||
| 	self.conn:queue(msg) | ||||
| end | ||||
|  | ||||
							
								
								
									
										3
									
								
								other_things/irc-old-save/irc/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -1,3 +0,0 @@ | ||||
| /gh-pages/ | ||||
| *~ | ||||
|  | ||||
| @@ -1,26 +0,0 @@ | ||||
| --[[ | ||||
|  Lua IRC library | ||||
|  | ||||
|  Copyright (c) 2010 Jakob Ovrum | ||||
|  | ||||
|  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.]] | ||||
|  | ||||
| @@ -1,18 +0,0 @@ | ||||
| LuaIRC | ||||
| ============ | ||||
|  | ||||
| IRC library for Lua. | ||||
|  | ||||
| Dependencies | ||||
| ------------- | ||||
|  | ||||
|  * [LuaSocket](http://w3.impa.br/~diego/software/luasocket/) | ||||
|  | ||||
| **Only required if you want to make use of the TLS support** | ||||
|  | ||||
|  * [LuaSec](http://www.inf.puc-rio.br/~brunoos/luasec/) | ||||
|  | ||||
| Documentation | ||||
| ------------- | ||||
| Documentation can be automatically generated by passing irc.luadoc (in doc/) to [LuaDoc](http://luadoc.luaforge.net/), or pre-generated documentation can be found in the 'gh-pages' branch, which can also be browsed [online](http://jakobovrum.github.com/LuaIRC/doc/modules/irc.html). | ||||
|  | ||||
| @@ -1,90 +0,0 @@ | ||||
| local irc = require("irc.main") | ||||
|  | ||||
| local meta = irc.meta | ||||
|  | ||||
| function meta:send(msg, ...) | ||||
| 	if type(msg) == "table" then | ||||
| 		msg = msg:toRFC1459() | ||||
| 	else | ||||
| 		if select("#", ...) > 0 then | ||||
| 			msg = msg:format(...) | ||||
| 		end | ||||
| 	end | ||||
| 	self:invoke("OnSend", msg) | ||||
|  | ||||
| 	local bytes, err = self.socket:send(msg .. "\r\n") | ||||
|  | ||||
| 	if not bytes and err ~= "timeout" and err ~= "wantwrite" then | ||||
| 		self:invoke("OnDisconnect", err, true) | ||||
| 		self:shutdown() | ||||
| 		error(err, errlevel) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| function meta:queue(msg) | ||||
| 	table.insert(self.messageQueue, msg) | ||||
| end | ||||
|  | ||||
| local function verify(str, errLevel) | ||||
| 	if str:find("^:") or str:find("%s%z") then | ||||
| 		error(("malformed parameter '%s' to irc command"):format(str), errLevel) | ||||
| 	end | ||||
|  | ||||
| 	return str | ||||
| end | ||||
|  | ||||
| function meta:sendChat(target, msg) | ||||
| 	-- Split the message into segments if it includes newlines. | ||||
| 	for line in msg:gmatch("([^\r\n]+)") do | ||||
| 		self:queue(irc.msgs.privmsg(verify(target, 3), line)) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| function meta:sendNotice(target, msg) | ||||
| 	-- Split the message into segments if it includes newlines. | ||||
| 	for line in msg:gmatch("([^\r\n]+)") do | ||||
| 		self:queue(irc.msgs.notice(verify(target, 3), line)) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| function meta:join(channel, key) | ||||
| 	self:queue(irc.msgs.join( | ||||
| 			verify(channel, 3), | ||||
| 			key and verify(key, 3) or nil)) | ||||
| end | ||||
|  | ||||
| function meta:part(channel, reason) | ||||
| 	channel = verify(channel, 3) | ||||
| 	self:queue(irc.msgs.part(channel, reason)) | ||||
| 	if self.track_users then | ||||
| 		self.channels[channel] = nil | ||||
| 	end | ||||
| end | ||||
|  | ||||
| function meta:trackUsers(b) | ||||
| 	self.track_users = b | ||||
| 	if not b then | ||||
| 		for k,v in pairs(self.channels) do | ||||
| 			self.channels[k] = nil | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| function meta:setMode(t) | ||||
| 	local target = t.target or self.nick | ||||
| 	local mode = "" | ||||
| 	local add, rem = t.add, t.remove | ||||
|  | ||||
| 	assert(add or rem, "table contains neither 'add' nor 'remove'") | ||||
|  | ||||
| 	if add then | ||||
| 		mode = table.concat{"+", verify(add, 3)} | ||||
| 	end | ||||
|  | ||||
| 	if rem then | ||||
| 		mode = table.concat{mode, "-", verify(rem, 3)} | ||||
| 	end | ||||
|  | ||||
| 	self:queue(irc.msgs.mode(verify(target, 3), mode)) | ||||
| end | ||||
|  | ||||
| @@ -1,184 +0,0 @@ | ||||
| --- LuaIRC is a low-level IRC library for Lua. | ||||
| -- All functions raise Lua exceptions on error. | ||||
| -- | ||||
| -- Use <code>new</code> to create a new IRC object.<br/> | ||||
| -- Example:<br/><br/> | ||||
| --<code> | ||||
| --require "irc"<br/> | ||||
| --local sleep = require "socket".sleep<br/> | ||||
| --<br/> | ||||
| --local s = irc.new{nick = "example"}<br/> | ||||
| --<br/> | ||||
| --s:hook("OnChat", function(user, channel, message)<br/> | ||||
| --    print(("[%s] %s: %s"):format(channel, user.nick, message))<br/> | ||||
| --end)<br/> | ||||
| --<br/> | ||||
| --s:connect("irc.example.net")<br/> | ||||
| --s:join("#example")<br/> | ||||
| --<br/> | ||||
| --while true do<br/> | ||||
| --    s:think()<br/> | ||||
| --    sleep(0.5)<br/> | ||||
| --end<br/> | ||||
| --</code> | ||||
|  | ||||
| module "irc" | ||||
|  | ||||
| --- Create a new IRC object. Use <code>irc:connect</code> to connect to a server. | ||||
| -- @param user Table with fields <code>nick</code>, <code>username</code> and <code>realname</code>. | ||||
| -- The <code>nick</code> field is required. | ||||
| -- | ||||
| -- @return Returns a new <code>irc</code> object. | ||||
| function new(user) | ||||
|  | ||||
| --- Hook a function to an event. | ||||
| -- @param name Name of event. | ||||
| -- @param id Unique tag. | ||||
| -- @param f Callback function. [defaults to <code>id</code>] | ||||
| -- @see Hooks | ||||
| function irc:hook(name, id, f) | ||||
|  | ||||
| --- Remove previous hooked callback. | ||||
| -- @param name Name of event. | ||||
| -- @param id Unique tag. | ||||
| function irc:unhook(name, id) | ||||
|  | ||||
| --- Connect <code>irc</code> to an IRC server. | ||||
| -- @param host Host address. | ||||
| -- @param port Server port. [default 6667] | ||||
| function irc:connect(server, port) | ||||
|  | ||||
| -- @param table Table of connection details | ||||
| -- @see Connection | ||||
| function irc:connect(table) | ||||
|  | ||||
| --- Disconnect <code>irc</code> from the server. | ||||
| -- @param message Quit message. | ||||
| function irc:disconnect(message) | ||||
|  | ||||
| --- Handle incoming data for <code>irc</code>, and invoke previously hooked callbacks based on new server input. | ||||
| -- You should call this in some kind of main loop, or at least often enough to not time out. | ||||
| function irc:think() | ||||
|  | ||||
| --- Look up user info. | ||||
| -- @param nick Nick of user to query. | ||||
| -- @return Table with fields <code>userinfo</code>, <code>node</code>, <code>channels</code> and <code>account</code>. | ||||
| function irc:whois(nick) | ||||
|  | ||||
| --- Look up topic. | ||||
| -- Use this to invoke the hooks OnTopic and OnTopicInfo at any time. | ||||
| -- @param channel Channel to query. | ||||
| function irc:topic(channel) | ||||
|  | ||||
| --- Send a IRC message to the server. | ||||
| -- @param msg Message or raw line to send, excluding newline characters. | ||||
| -- @param ... Format parameters for <code>msg</code>, with <code>string.format</code> semantics. [optional] | ||||
| function irc:send(msg, ...) | ||||
|  | ||||
| --- Queue Message to be sent to the server. | ||||
| -- @param msg Message to be sent. | ||||
| function irc:queue(msg) | ||||
|  | ||||
| --- Send a message to a channel or user. | ||||
| -- @param target Nick or channel to send to. | ||||
| -- @param message Message text. | ||||
| function irc:sendChat(target, message) | ||||
|  | ||||
| --- Send a notice to a channel or user. | ||||
| -- @param target Nick or channel to send to. | ||||
| -- @param message Notice text. | ||||
| function irc:sendNotice(target, message) | ||||
|  | ||||
| --- Join a channel. | ||||
| -- @param channel Channel to join. | ||||
| -- @param key Channel key. [optional] | ||||
| function irc:join(channel, key) | ||||
|  | ||||
| --- Leave a channel. | ||||
| -- @param channel Channel to leave. | ||||
| function irc:part(channel) | ||||
|  | ||||
| --- Turn user information tracking on or off. User tracking is enabled by default. | ||||
| -- @param b Boolean whether or not to track user information. | ||||
| function irc:trackUsers(b) | ||||
|  | ||||
| --- Add/remove modes for a channel or nick. | ||||
| -- @param t Table with fields <code>target, nick, add</code> and/or <code>rem</code>. <code>target</code> or <code>nick</code> | ||||
| -- specifies the user or channel to add/remove modes. <code>add</code> is a list of modes to add to the user or channel. | ||||
| -- <code>rem</code> is a list of modes to remove from the user or channel. | ||||
| -- @usage Example which sets +m (moderated) for #channel: <br/> | ||||
| -- <code>irc:setMode{target = "#channel", add = "m"}</code> | ||||
| function irc:setMode(t) | ||||
|  | ||||
| --internal | ||||
| function irc:invoke(name, ...) | ||||
| function irc:handle(msg) | ||||
| function irc:shutdown() | ||||
|  | ||||
| --- Table with connection information. | ||||
| -- <ul> | ||||
| -- <li><code>host</code> - Server host name.</li> | ||||
| -- <li><code>port</code> - Server port. [defaults to <code>6667</code>]</li> | ||||
| -- <li><code>timeout</code> - Connect timeout. [defaults to <code>30</code>]</li> | ||||
| -- <li><code>password</code> - Server password.</li> | ||||
| -- <li><code>secure</code> - Boolean to enable TLS connection, pass a params table (described, [luasec]) to control</li> | ||||
| -- </ul> | ||||
| -- [luasec]: http://www.inf.puc-rio.br/~brunoos/luasec/reference.html | ||||
| -- @name Connection | ||||
| -- @class table | ||||
|  | ||||
| --- Class representing an IRC message. | ||||
| -- @name Message | ||||
| -- @class table | ||||
| -- @field args A list of the command arguments | ||||
| -- @field command The IRC command | ||||
| -- @field prefix The prefix of the message | ||||
| -- @field raw A raw IRC line for this message | ||||
| -- @field tags A table of IRCv3 tags | ||||
| -- @field user A User object describing the sender of the message | ||||
| -- Fields may be missing. | ||||
| -- Messages have the following methods: | ||||
| -- <ul> | ||||
| -- <li><code>toRFC1459()</code> - Returns the message serialized in RFC 1459 format.</li> | ||||
| -- </ul> | ||||
|  | ||||
| --- List of hooks you can use with irc:hook. | ||||
| -- The parameter list describes the parameters passed to the callback function. | ||||
| -- <ul> | ||||
| -- <li><code>PreRegister(connection)</code>Useful for CAP commands and SASL.</li> | ||||
| -- <li><code>OnRaw(line) - (any non false/nil return value assumes line handled and will not be further processed)</code></li> | ||||
| -- <li><code>OnSend(line)</code></li> | ||||
| -- <li><code>OnDisconnect(message, errorOccurred)</code></li> | ||||
| -- <li><code>OnChat(user, channel, message)</code></li> | ||||
| -- <li><code>OnNotice(user, channel, message)</code></li> | ||||
| -- <li><code>OnJoin(user, channel)</code>*</li> | ||||
| -- <li><code>OnPart(user, channel)</code>*</li> | ||||
| -- <li><code>OnQuit(user, message)</code></li> | ||||
| -- <li><code>NickChange(user, newnick, channel)</code>*<2A></li> | ||||
| -- <li><code>NameList(channel, names)</code></li> | ||||
| -- <li><code>OnTopic(channel, topic)</code></li> | ||||
| -- <li><code>OnTopicInfo(channel, creator, timeCreated)</code></li> | ||||
| -- <li><code>OnKick(channel, nick, kicker, reason)</code>* (kicker is a <code>user</code> table)</li> | ||||
| -- <li><code>OnUserMode(modes)</code></li> | ||||
| -- <li><code>OnChannelMode(user, channel, modes)</code></li> | ||||
| -- <li><code>OnModeChange(user, target, modes, ...)</code>* ('...' contains mode options such as banmasks)</li> | ||||
| -- <li><code>DoX(msg)</code>'X' is any IRC command or numeric with the first letter capitalized (eg, DoPing and Do001)</li> | ||||
| -- </ul> | ||||
| -- * Event also invoked for yourself. | ||||
| -- <20> Channel passed only when user tracking is enabled | ||||
| -- @name Hooks | ||||
| -- @class table | ||||
|  | ||||
| --- Table with information about a user. | ||||
| -- <ul> | ||||
| -- <li><code>server</code> - Server name.</li> | ||||
| -- <li><code>nick</code> - User nickname.</li> | ||||
| -- <li><code>username</code> - User username.</li> | ||||
| -- <li><code>host</code> - User hostname.</li> | ||||
| -- <li><code>realname</code> - User real name.</li> | ||||
| -- <li><code>access</code> - User access, available in channel-oriented callbacks. A table containing boolean fields for each access mode that the server supports. Eg: 'o', and 'v'.</li> | ||||
| -- </ul> | ||||
| -- Fields may be missing. To fill them in, enable user tracking and use irc:whois. | ||||
| -- @name User | ||||
| -- @class table | ||||
|  | ||||
| @@ -1,210 +0,0 @@ | ||||
| local irc = require("irc.main") | ||||
|  | ||||
| irc.handlers = {} | ||||
| local handlers = irc.handlers | ||||
|  | ||||
| handlers["PING"] = function(conn, msg) | ||||
| 	conn:send(irc.Message({command="PONG", args=msg.args})) | ||||
| end | ||||
|  | ||||
| handlers["001"] = function(conn, msg) | ||||
| 	conn.authed = true | ||||
| 	conn.nick = msg.args[1] | ||||
| end | ||||
|  | ||||
| handlers["PRIVMSG"] = function(conn, msg) | ||||
| 	conn:invoke("OnChat", msg.user, msg.args[1], msg.args[2]) | ||||
| end | ||||
|  | ||||
|  | ||||
| handlers["NOTICE"] = function(conn, msg) | ||||
| 	conn:invoke("OnNotice", msg.user, msg.args[1], msg.args[2]) | ||||
| end | ||||
|  | ||||
| handlers["JOIN"] = function(conn, msg) | ||||
| 	local channel = msg.args[1] | ||||
| 	if conn.track_users then | ||||
| 		if msg.user.nick == conn.nick then | ||||
| 			conn.channels[channel] = {users = {}} | ||||
| 		else | ||||
| 			conn.channels[channel].users[msg.user.nick] = msg.user | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	conn:invoke("OnJoin", msg.user, msg.args[1]) | ||||
| end | ||||
|  | ||||
| handlers["PART"] = function(conn, msg) | ||||
| 	local channel = msg.args[1] | ||||
| 	if conn.track_users then | ||||
| 		if msg.user.nick == conn.nick then | ||||
| 			conn.channels[channel] = nil | ||||
| 		else | ||||
| 			conn.channels[channel].users[msg.user.nick] = nil | ||||
| 		end | ||||
| 	end | ||||
| 	conn:invoke("OnPart", msg.user, msg.args[1], msg.args[2]) | ||||
| end | ||||
|  | ||||
| handlers["QUIT"] = function(conn, msg) | ||||
| 	if conn.track_users then | ||||
| 		for chanName, chan in pairs(conn.channels) do | ||||
| 			chan.users[msg.user.nick] = nil | ||||
| 		end | ||||
| 	end | ||||
| 	conn:invoke("OnQuit", msg.user, msg.args[1], msg.args[2]) | ||||
| end | ||||
|  | ||||
| handlers["NICK"] = function(conn, msg) | ||||
| 	local newNick = msg.args[1] | ||||
| 	if conn.track_users then | ||||
| 		for chanName, chan in pairs(conn.channels) do | ||||
| 			local users = chan.users | ||||
| 			local oldinfo = users[msg.user.nick] | ||||
| 			if oldinfo then | ||||
| 				users[newNick] = oldinfo | ||||
| 				users[msg.user.nick] = nil | ||||
| 				conn:invoke("NickChange", msg.user, newNick, chanName) | ||||
| 			end | ||||
| 		end | ||||
| 	else | ||||
| 		conn:invoke("NickChange", msg.user, newNick) | ||||
| 	end | ||||
| 	if msg.user.nick == conn.nick then | ||||
| 		conn.nick = newnick | ||||
| 	end | ||||
| end | ||||
|  | ||||
| local function needNewNick(conn, msg) | ||||
| 	local newnick = conn.nickGenerator(msg.args[2]) | ||||
| 	if msg.nick then | ||||
| 		conn:queue(msg.nick(newnick)) | ||||
| 	end | ||||
| 	-- Ugly hack to fix crash | ||||
| end | ||||
|  | ||||
| -- ERR_ERRONEUSNICKNAME (Misspelt but remains for historical reasons) | ||||
| handlers["432"] = needNewNick | ||||
|  | ||||
| -- ERR_NICKNAMEINUSE | ||||
| handlers["433"] = needNewNick | ||||
|  | ||||
| -- RPL_ISUPPORT | ||||
| handlers["005"] = function(conn, msg) | ||||
| 	local arglen = #msg.args | ||||
| 	-- Skip first and last parameters (nick and info) | ||||
| 	for i = 2, arglen - 1 do | ||||
| 		local item = msg.args[i] | ||||
| 		local pos = item:find("=") | ||||
| 		if pos then | ||||
| 			conn.supports[item:sub(1, pos - 1)] = item:sub(pos + 1) | ||||
| 		else | ||||
| 			conn.supports[item] = true | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| -- RPL_MOTDSTART | ||||
| handlers["375"] = function(conn, msg) | ||||
| 	conn.motd = "" | ||||
| end | ||||
|  | ||||
| -- RPL_MOTD | ||||
| handlers["372"] = function(conn, msg) | ||||
| 	-- MOTD lines have a "- " prefix, strip it. | ||||
| 	conn.motd = conn.motd .. msg.args[2]:sub(3) .. '\n' | ||||
| end | ||||
|  | ||||
| -- NAMES list | ||||
| handlers["353"] = function(conn, msg) | ||||
| 	local chanType = msg.args[2] | ||||
| 	local channel = msg.args[3] | ||||
| 	local names = msg.args[4] | ||||
| 	if conn.track_users then | ||||
| 		conn.channels[channel] = conn.channels[channel] or {users = {}, type = chanType} | ||||
|  | ||||
| 		local users = conn.channels[channel].users | ||||
| 		for nick in names:gmatch("(%S+)") do | ||||
| 			local access, name = irc.parseNick(conn, nick) | ||||
| 			users[name] = {access = access} | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| -- End of NAMES list | ||||
| handlers["366"] = function(conn, msg) | ||||
| 	if conn.track_users then | ||||
| 		conn:invoke("NameList", msg.args[2], msg.args[3]) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| -- No topic | ||||
| handlers["331"] = function(conn, msg) | ||||
| 	conn:invoke("OnTopic", msg.args[2], nil) | ||||
| end | ||||
|  | ||||
| handlers["TOPIC"] = function(conn, msg) | ||||
| 	conn:invoke("OnTopic", msg.args[1], msg.args[2]) | ||||
| end | ||||
|  | ||||
| handlers["332"] = function(conn, msg) | ||||
| 	conn:invoke("OnTopic", msg.args[2], msg.args[3]) | ||||
| end | ||||
|  | ||||
| -- Topic creation info | ||||
| handlers["333"] = function(conn, msg) | ||||
| 	conn:invoke("OnTopicInfo", msg.args[2], msg.args[3], tonumber(msg.args[4])) | ||||
| end | ||||
|  | ||||
| handlers["KICK"] = function(conn, msg) | ||||
| 	conn:invoke("OnKick", msg.args[1], msg.args[2], msg.user, msg.args[3]) | ||||
| end | ||||
|  | ||||
| -- RPL_UMODEIS | ||||
| -- To answer a query about a client's own mode, RPL_UMODEIS is sent back | ||||
| handlers["221"] = function(conn, msg) | ||||
| 	conn:invoke("OnUserMode", msg.args[2]) | ||||
| end | ||||
|  | ||||
| -- RPL_CHANNELMODEIS | ||||
| -- The result from common irc servers differs from that defined by the rfc | ||||
| handlers["324"] = function(conn, msg) | ||||
| 	conn:invoke("OnChannelMode", msg.args[2], msg.args[3]) | ||||
| end | ||||
|  | ||||
| handlers["MODE"] = function(conn, msg) | ||||
| 	local target = msg.args[1] | ||||
| 	local modes = msg.args[2] | ||||
| 	local optList = {} | ||||
| 	for i = 3, #msg.args do | ||||
| 		table.insert(optList, msg.args[i]) | ||||
| 	end | ||||
| 	if conn.track_users and target ~= conn.nick then | ||||
| 		local add = true | ||||
| 		local argNum = 1 | ||||
| 		irc.updatePrefixModes(conn) | ||||
| 		for c in modes:gmatch(".") do | ||||
| 			if     c == "+" then add = true | ||||
| 			elseif c == "-" then add = false | ||||
| 			elseif conn.modeprefix[c] then | ||||
| 				local nick = optList[argNum] | ||||
| 				argNum = argNum + 1 | ||||
| 				local user = conn.channels[target].users[nick] | ||||
| 				user.access = user.access or {} | ||||
| 				local access = user.access | ||||
| 				access[c] = add | ||||
| 				if     c == "o" then access.op = add | ||||
| 				elseif c == "v" then access.voice = add | ||||
| 				end | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| 	conn:invoke("OnModeChange", msg.user, target, modes, unpack(optList)) | ||||
| end | ||||
|  | ||||
| handlers["ERROR"] = function(conn, msg) | ||||
| 	conn:invoke("OnDisconnect", msg.args[1], true) | ||||
| 	conn:shutdown() | ||||
| 	error(msg.args[1], 3) | ||||
| end | ||||
|  | ||||
| @@ -1,9 +0,0 @@ | ||||
|  | ||||
| local irc = require("irc.main") | ||||
| require("irc.util") | ||||
| require("irc.asyncoperations") | ||||
| require("irc.handlers") | ||||
| require("irc.messages") | ||||
|  | ||||
| return irc | ||||
|  | ||||
| @@ -1,241 +0,0 @@ | ||||
| local socket = require "socket" | ||||
|  | ||||
| -- Module table | ||||
| local irc = {} | ||||
|  | ||||
| local meta = {} | ||||
| meta.__index = meta | ||||
| irc.meta = meta | ||||
|  | ||||
| local meta_preconnect = {} | ||||
| function meta_preconnect.__index(o, k) | ||||
| 	local v = rawget(meta_preconnect, k) | ||||
|  | ||||
| 	if not v and meta[k] then | ||||
| 		error(("field '%s' is not accessible before connecting"):format(k), 2) | ||||
| 	end | ||||
| 	return v | ||||
| end | ||||
|  | ||||
| function irc.new(data) | ||||
| 	local o = { | ||||
| 		nick = assert(data.nick, "Field 'nick' is required"); | ||||
| 		username = data.username or "lua"; | ||||
| 		realname = data.realname or "Lua owns"; | ||||
| 		nickGenerator = data.nickGenerator or irc.defaultNickGenerator; | ||||
| 		hooks = {}; | ||||
| 		track_users = true; | ||||
| 		supports = {}; | ||||
| 		messageQueue = {}; | ||||
| 		lastThought = 0; | ||||
| 		recentMessages = 0; | ||||
| 	} | ||||
| 	assert(irc.checkNick(o.nick), "Erroneous nickname passed to irc.new") | ||||
| 	return setmetatable(o, meta_preconnect) | ||||
| end | ||||
|  | ||||
| function meta:hook(name, id, f) | ||||
| 	f = f or id | ||||
| 	self.hooks[name] = self.hooks[name] or {} | ||||
| 	self.hooks[name][id] = f | ||||
| 	return id or f | ||||
| end | ||||
| meta_preconnect.hook = meta.hook | ||||
|  | ||||
|  | ||||
| function meta:unhook(name, id) | ||||
| 	local hooks = self.hooks[name] | ||||
|  | ||||
| 	assert(hooks, "no hooks exist for this event") | ||||
| 	assert(hooks[id], "hook ID not found") | ||||
|  | ||||
| 	hooks[id] = nil | ||||
| end | ||||
| meta_preconnect.unhook = meta.unhook | ||||
|  | ||||
| function meta:invoke(name, ...) | ||||
| 	local hooks = self.hooks[name] | ||||
| 	if hooks then | ||||
| 		for id, f in pairs(hooks) do | ||||
| 			if f(...) then | ||||
| 				return true | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| function meta_preconnect:connect(_host, _port) | ||||
| 	local host, port, password, secure, timeout | ||||
|  | ||||
| 	if type(_host) == "table" then | ||||
| 		host = _host.host | ||||
| 		port = _host.port | ||||
| 		timeout = _host.timeout | ||||
| 		password = _host.password | ||||
| 		secure = _host.secure | ||||
| 	else | ||||
| 		host = _host | ||||
| 		port = _port | ||||
| 	end | ||||
|  | ||||
| 	host = host or error("host name required to connect", 2) | ||||
| 	port = port or 6667 | ||||
|  | ||||
| 	local s = socket.tcp() | ||||
|  | ||||
| 	s:settimeout(timeout or 30) | ||||
| 	assert(s:connect(host, port)) | ||||
|  | ||||
| 	if secure then | ||||
| 		local work, ssl = pcall(require, "ssl") | ||||
| 		if not work then | ||||
| 			error("LuaSec required for secure connections", 2) | ||||
| 		end | ||||
|  | ||||
| 		local params | ||||
| 		if type(secure) == "table" then | ||||
| 			params = secure | ||||
| 		else | ||||
| 			params = {mode = "client", protocol = "tlsv1"} | ||||
| 		end | ||||
|  | ||||
| 		s = ssl.wrap(s, params) | ||||
| 		local success, errmsg = s:dohandshake() | ||||
| 		if not success then | ||||
| 			error(("could not make secure connection: %s"):format(errmsg), 2) | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	self.socket = s | ||||
| 	setmetatable(self, meta) | ||||
|  | ||||
| 	self:queue(irc.Message({command="CAP", args={"REQ", "multi-prefix"}})) | ||||
|  | ||||
| 	self:invoke("PreRegister", self) | ||||
| 	self:queue(irc.Message({command="CAP", args={"END"}})) | ||||
|  | ||||
| 	if password then | ||||
| 		self:queue(irc.Message({command="PASS", args={password}})) | ||||
| 	end | ||||
|  | ||||
| 	self:queue(irc.msgs.nick(self.nick)) | ||||
| 	self:queue(irc.Message({command="USER", args={self.username, "0", "*", self.realname}})) | ||||
|  | ||||
| 	self.channels = {} | ||||
|  | ||||
| 	s:settimeout(0) | ||||
|  | ||||
| 	repeat | ||||
| 		self:think() | ||||
| 		socket.sleep(0.1) | ||||
| 	until self.authed | ||||
| end | ||||
|  | ||||
| function meta:disconnect(message) | ||||
| 	message = message or "Bye!" | ||||
|  | ||||
| 	self:invoke("OnDisconnect", message, false) | ||||
| 	self:send(irc.msgs.quit(message)) | ||||
|  | ||||
| 	self:shutdown() | ||||
| end | ||||
|  | ||||
| function meta:shutdown() | ||||
| 	self.socket:close() | ||||
| 	setmetatable(self, nil) | ||||
| end | ||||
|  | ||||
| local function getline(self, errlevel) | ||||
| 	local line, err = self.socket:receive("*l") | ||||
|  | ||||
| 	if not line and err ~= "timeout" and err ~= "wantread" then | ||||
| 		self:invoke("OnDisconnect", err, true) | ||||
| 		self:shutdown() | ||||
| 		error(err, errlevel) | ||||
| 	end | ||||
|  | ||||
| 	return line | ||||
| end | ||||
|  | ||||
| function meta:think() | ||||
| 	while true do | ||||
| 		local line = getline(self, 3) | ||||
| 		if line and #line > 0 then | ||||
| 			if not self:invoke("OnRaw", line) then | ||||
| 				self:handle(irc.Message({raw=line})) | ||||
| 			end | ||||
| 		else | ||||
| 			break | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	-- Handle outgoing message queue | ||||
| 	local diff = socket.gettime() - self.lastThought | ||||
| 	self.recentMessages = self.recentMessages - (diff * 2) | ||||
| 	if self.recentMessages < 0 then | ||||
| 		self.recentMessages = 0 | ||||
| 	end | ||||
| 	for i = 1, #self.messageQueue do | ||||
| 		if self.recentMessages > 4 then | ||||
| 			break | ||||
| 		end | ||||
| 		self:send(table.remove(self.messageQueue, 1)) | ||||
| 		self.recentMessages = self.recentMessages + 1 | ||||
| 	end | ||||
| 	self.lastThought = socket.gettime() | ||||
| end | ||||
|  | ||||
| local handlers = handlers | ||||
|  | ||||
| function meta:handle(msg) | ||||
| 	local handler = irc.handlers[msg.command] | ||||
| 	if handler then | ||||
| 		handler(self, msg) | ||||
| 	end | ||||
| 	self:invoke("Do" .. irc.capitalize(msg.command), msg) | ||||
| end | ||||
|  | ||||
| local whoisHandlers = { | ||||
| 	["311"] = "userinfo"; | ||||
| 	["312"] = "node"; | ||||
| 	["319"] = "channels"; | ||||
| 	["330"] = "account"; -- Freenode | ||||
| 	["307"] = "registered"; -- Unreal | ||||
| } | ||||
|  | ||||
| function meta:whois(nick) | ||||
| 	self:send(irc.msgs.whois(nick)) | ||||
|  | ||||
| 	local result = {} | ||||
|  | ||||
| 	while true do | ||||
| 		local line = getline(self, 3) | ||||
| 		if line then | ||||
| 			local msg = irc.Message({raw=line}) | ||||
|  | ||||
| 			local handler = whoisHandlers[msg.command] | ||||
| 			if handler then | ||||
| 				result[handler] = msg.args | ||||
| 			elseif msg.command == "318" then | ||||
| 				break | ||||
| 			else | ||||
| 				self:handle(msg) | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	if result.account then | ||||
| 		result.account = result.account[3] | ||||
| 	elseif result.registered then | ||||
| 		result.account = result.registered[2] | ||||
| 	end | ||||
|  | ||||
| 	return result | ||||
| end | ||||
|  | ||||
| function meta:topic(channel) | ||||
| 	self:queue(irc.msgs.topic(channel)) | ||||
| end | ||||
|  | ||||
| return irc | ||||
|  | ||||
| @@ -1,200 +0,0 @@ | ||||
| local irc = require("irc.main") | ||||
|  | ||||
| irc.msgs = {} | ||||
| local msgs = irc.msgs | ||||
|  | ||||
| local msg_meta = {} | ||||
| msg_meta.__index = msg_meta | ||||
|  | ||||
| function irc.Message(opts) | ||||
| 	opts = opts or {} | ||||
| 	setmetatable(opts, msg_meta) | ||||
| 	if opts.raw then | ||||
| 		opts:fromRFC1459(opts.raw) | ||||
| 	end | ||||
| 	return opts | ||||
| end | ||||
|  | ||||
| local tag_escapes = { | ||||
| 	[";"] = "\\:", | ||||
| 	[" "] = "\\s", | ||||
| 	["\0"] = "\\0", | ||||
| 	["\\"] = "\\\\", | ||||
| 	["\r"] = "\\r", | ||||
| 	["\n"] = "\\n", | ||||
| } | ||||
|  | ||||
| local tag_unescapes = {} | ||||
| for x, y in pairs(tag_escapes) do tag_unescapes[y] = x end | ||||
|  | ||||
| function msg_meta:toRFC1459() | ||||
| 	local s = "" | ||||
|  | ||||
| 	if self.tags then | ||||
| 		s = s.."@" | ||||
| 		for key, value in pairs(self.tags) do | ||||
| 			s = s..key | ||||
| 			if value ~= true then | ||||
| 				value = value:gsub("[; %z\\\r\n]", tag_escapes) | ||||
| 				s = s.."="..value | ||||
| 			end | ||||
| 			s = s..";" | ||||
| 		end | ||||
| 		-- Strip trailing semicolon | ||||
| 		s = s:sub(1, -2) | ||||
| 		s = s.." " | ||||
| 	end | ||||
|  | ||||
| 	s = s..self.command | ||||
|  | ||||
| 	local argnum = #self.args | ||||
| 	for i = 1, argnum do | ||||
| 		local arg = self.args[i] | ||||
| 		local startsWithColon = (arg:sub(1, 1) == ":") | ||||
| 		local hasSpace = arg:find(" ") | ||||
| 		if i == argnum and (hasSpace or startsWithColon) then | ||||
| 			s = s.." :" | ||||
| 		else | ||||
| 			assert(not hasSpace and not startsWithColon, | ||||
| 					"Message arguments can not be " | ||||
| 					.."serialized to RFC1459 format") | ||||
| 			s = s.." " | ||||
| 		end | ||||
| 		s = s..arg | ||||
| 	end | ||||
|  | ||||
| 	return s | ||||
| end | ||||
|  | ||||
| local function parsePrefix(prefix) | ||||
| 	local user = {} | ||||
| 	user.nick, user.username, user.host = prefix:match("^(.+)!(.+)@(.+)$") | ||||
| 	if not user.nick and prefix:find(".", 1, true) then | ||||
| 		user.server = prefix | ||||
| 	end | ||||
| 	return user | ||||
| end | ||||
|  | ||||
| function msg_meta:fromRFC1459(line) | ||||
| 	-- IRCv3 tags | ||||
| 	if line:sub(1, 1) == "@" then | ||||
| 		self.tags = {} | ||||
| 		local space = line:find(" ", 1, true) | ||||
| 		-- For each semicolon-delimited section from after | ||||
| 		-- the @ character to before the space character. | ||||
| 		for tag in line:sub(2, space - 1):gmatch("([^;]+)") do | ||||
| 			local eq = tag:find("=", 1, true) | ||||
| 			if eq then | ||||
| 				self.tags[tag:sub(1, eq - 1)] = | ||||
| 					tag:sub(eq + 1):gsub("\\([:s0\\rn])", tag_unescapes) | ||||
| 			else | ||||
| 				self.tags[tag] = true | ||||
| 			end | ||||
| 		end | ||||
| 		line = line:sub(space + 1) | ||||
| 	end | ||||
|  | ||||
| 	if line:sub(1, 1) == ":" then | ||||
| 		local space = line:find(" ", 1, true) | ||||
| 		self.prefix = line:sub(2, space - 1) | ||||
| 		self.user = parsePrefix(self.prefix) | ||||
| 		line = line:sub(space + 1) | ||||
| 	end | ||||
|  | ||||
| 	local pos | ||||
| 	self.command, pos = line:match("(%S+)()") | ||||
| 	line = line:sub(pos) | ||||
|  | ||||
| 	self.args = self.args or {} | ||||
| 	for pos, param in line:gmatch("()(%S+)") do | ||||
| 		if param:sub(1, 1) == ":" then | ||||
| 			param = line:sub(pos + 1) | ||||
| 			table.insert(self.args, param) | ||||
| 			break | ||||
| 		end | ||||
| 		table.insert(self.args, param) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| function msgs.privmsg(to, text) | ||||
| 	return irc.Message({command="PRIVMSG", args={to, text}}) | ||||
| end | ||||
|  | ||||
| function msgs.notice(to, text) | ||||
| 	return irc.Message({command="NOTICE", args={to, text}}) | ||||
| end | ||||
|  | ||||
| function msgs.action(to, text) | ||||
| 	return irc.Message({command="PRIVMSG", args={to, ("\x01ACTION %s\x01"):format(text)}}) | ||||
| end | ||||
|  | ||||
| function msgs.ctcp(command, to, args) | ||||
| 	s = "\x01"..command | ||||
| 	if args then | ||||
| 		s = ' '..args | ||||
| 	end | ||||
| 	s = s..'\x01' | ||||
| 	return irc.Message({command="PRIVMSG", args={to, s}}) | ||||
| end | ||||
|  | ||||
| function msgs.kick(channel, target, reason) | ||||
| 	return irc.Message({command="KICK", args={channel, target, reason}}) | ||||
| end | ||||
|  | ||||
| function msgs.join(channel, key) | ||||
| 	return irc.Message({command="JOIN", args={channel, key}}) | ||||
| end | ||||
|  | ||||
| function msgs.part(channel, reason) | ||||
| 	return irc.Message({command="PART", args={channel, reason}}) | ||||
| end | ||||
|  | ||||
| function msgs.quit(reason) | ||||
| 	return irc.Message({command="QUIT", args={reason}}) | ||||
| end | ||||
|  | ||||
| function msgs.kill(target, reason) | ||||
| 	return irc.Message({command="KILL", args={target, reason}}) | ||||
| end | ||||
|  | ||||
| function msgs.kline(time, mask, reason, operreason) | ||||
| 	local args = nil | ||||
| 	if time then | ||||
| 		args = {time, mask, reason..'|'..operreason} | ||||
| 	else | ||||
| 		args = {mask, reason..'|'..operreason} | ||||
| 	end | ||||
| 	return irc.Message({command="KLINE", args=args}) | ||||
| end | ||||
|  | ||||
| function msgs.whois(nick, server) | ||||
| 	local args = nil | ||||
| 	if server then | ||||
| 		args = {server, nick} | ||||
| 	else | ||||
| 		args = {nick} | ||||
| 	end | ||||
| 	return irc.Message({command="WHOIS", args=args}) | ||||
| end | ||||
|  | ||||
| function msgs.topic(channel, text) | ||||
| 	return irc.Message({command="TOPIC", args={channel, text}}) | ||||
| end | ||||
|  | ||||
| function msgs.invite(channel, target) | ||||
| 	return irc.Message({command="INVITE", args={channel, target}}) | ||||
| end | ||||
|  | ||||
| function msgs.nick(nick) | ||||
| 	return irc.Message({command="NICK", args={nick}}) | ||||
| end | ||||
|  | ||||
| function msgs.mode(target, modes) | ||||
| 	-- We have to split the modes parameter because the mode string and | ||||
| 	-- each parameter are seperate arguments (The first command is incorrect) | ||||
| 	--   MODE foo :+ov Nick1 Nick2 | ||||
| 	--   MODE foo +ov Nick1 Nick2 | ||||
| 	local mt = irc.split(modes) | ||||
| 	return irc.Message({command="MODE", args={target, unpack(mt)}}) | ||||
| end | ||||
|  | ||||
| @@ -1,19 +0,0 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| if [ "$TRAVIS_REPO_SLUG" == "JakobOvrum/LuaIRC" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_BRANCH" == "master" ]; then | ||||
|  | ||||
|   echo -e "Generating luadoc...\n" | ||||
|  | ||||
|   git config --global user.email "travis@travis-ci.org" | ||||
|   git config --global user.name "travis-ci" | ||||
|   git clone --quiet --branch=gh-pages https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG} gh-pages > /dev/null | ||||
|  | ||||
|   cd gh-pages | ||||
|   git rm -rf ./doc | ||||
|   sh ./generate.sh | ||||
|   git add -f ./doc | ||||
|   git commit -m "Lastest documentation on successful travis build $TRAVIS_BUILD_NUMBER auto-pushed to gh-pages" | ||||
|   git push -fq origin gh-pages > /dev/null | ||||
|  | ||||
|   echo -e "Published luadoc to gh-pages.\n" | ||||
| fi | ||||
| @@ -1,52 +0,0 @@ | ||||
| local select = require "socket".select | ||||
|  | ||||
| local m = {} | ||||
| local set = {} | ||||
| set.__index = set | ||||
|  | ||||
| function m.new(t) | ||||
| 	t.connections = {} | ||||
| 	t.sockets = {} | ||||
| 	return setmetatable(t, set) | ||||
| end | ||||
|  | ||||
| function set:add(connection) | ||||
| 	local socket = connection.socket | ||||
| 	insert(self.sockets, socket) | ||||
| 	 | ||||
| 	self.connections[socket] = connection | ||||
| 	insert(self.connections, connection) | ||||
| end | ||||
|  | ||||
| function set:remove(connection) | ||||
| 	local socket = connection.socket | ||||
| 	self.connections[socket] = nil | ||||
| 	for k, s in ipairs(self.sockets) do | ||||
| 		if socket == s then | ||||
| 			remove(self.sockets, k) | ||||
| 			remove(self.connections, k) | ||||
| 			break | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| function set:select() | ||||
| 	local read, write, err = select(self.sockets, nil, self.timeout) | ||||
| 	 | ||||
| 	if read then | ||||
| 		for k, socket in ipairs(read) do | ||||
| 			read[k] = self.connections[socket] | ||||
| 		end | ||||
| 	end | ||||
| 	 | ||||
| 	return read, err | ||||
| end | ||||
|  | ||||
| -- Select - but if it times out, it returns all connections. | ||||
| function set:poll() | ||||
| 	local read, err = self:select() | ||||
| 	return err == "timeout" and self.connections or read | ||||
| end | ||||
|  | ||||
| return m | ||||
|  | ||||
| @@ -1,116 +0,0 @@ | ||||
| local irc = require("irc.main") | ||||
|  | ||||
| function irc.parseNick(conn, nick) | ||||
| 	local access = {} | ||||
| 	irc.updatePrefixModes(conn) | ||||
| 	local namestart = 1 | ||||
| 	for i = 1, #nick - 1 do | ||||
| 		local c = nick:sub(i, i) | ||||
| 		if conn.prefixmode[c] then | ||||
| 			access[conn.prefixmode[c]] = true | ||||
| 		else | ||||
| 			namestart = i | ||||
| 			break | ||||
| 		end | ||||
| 	end | ||||
| 	access.op = access.o | ||||
| 	access.voice = access.v | ||||
| 	local name = nick:sub(namestart) | ||||
| 	return access, name | ||||
| end | ||||
|  | ||||
| function irc.updatePrefixModes(conn) | ||||
| 	if conn.prefixmode and conn.modeprefix then | ||||
| 		return | ||||
| 	end | ||||
| 	conn.prefixmode = {} | ||||
| 	conn.modeprefix = {} | ||||
| 	if conn.supports.PREFIX then | ||||
| 		local modes, prefixes = conn.supports.PREFIX:match("%(([^%)]*)%)(.*)") | ||||
| 		for i = 1, #modes do | ||||
| 			conn.prefixmode[prefixes:sub(i, i)] =    modes:sub(i, i) | ||||
| 			conn.modeprefix[   modes:sub(i, i)] = prefixes:sub(i, i) | ||||
| 		end | ||||
| 	else | ||||
| 		conn.prefixmode['@'] = 'o' | ||||
| 		conn.prefixmode['+'] = 'v' | ||||
| 		conn.modeprefix['o'] = '@' | ||||
| 		conn.modeprefix['v'] = '+' | ||||
| 	end | ||||
| end | ||||
|  | ||||
| -- mIRC markup scheme (de-facto standard) | ||||
| irc.color = { | ||||
| 	black = 1, | ||||
| 	blue = 2, | ||||
| 	green = 3, | ||||
| 	red = 4, | ||||
| 	lightred = 5, | ||||
| 	purple = 6, | ||||
| 	brown = 7, | ||||
| 	yellow = 8, | ||||
| 	lightgreen = 9, | ||||
| 	navy = 10, | ||||
| 	cyan = 11, | ||||
| 	lightblue = 12, | ||||
| 	violet = 13, | ||||
| 	gray = 14, | ||||
| 	lightgray = 15, | ||||
| 	white = 16 | ||||
| } | ||||
|  | ||||
| local colByte = string.char(3) | ||||
| setmetatable(irc.color, {__call = function(_, text, colornum) | ||||
| 	colornum = (type(colornum) == "string" and | ||||
| 			assert(irc.color[colornum], "Invalid color '"..colornum.."'") or | ||||
| 			colornum) | ||||
| 	return table.concat{colByte, tostring(colornum), text, colByte} | ||||
| end}) | ||||
|  | ||||
| local boldByte = string.char(2) | ||||
| function irc.bold(text) | ||||
| 	return boldByte..text..boldByte | ||||
| end | ||||
|  | ||||
| local underlineByte = string.char(31) | ||||
| function irc.underline(text) | ||||
| 	return underlineByte..text..underlineByte | ||||
| end | ||||
|  | ||||
| function irc.checkNick(nick) | ||||
| 	return nick:find("^[a-zA-Z_%-%[|%]%^{|}`][a-zA-Z0-9_%-%[|%]%^{|}`]*$") ~= nil | ||||
| end | ||||
|  | ||||
| function irc.defaultNickGenerator(nick) | ||||
| 	-- LuaBot -> LuaCot -> LuaCou -> ... | ||||
| 	-- We change a random character rather than appending to the | ||||
| 	-- nickname as otherwise the new nick could exceed the ircd's | ||||
| 	-- maximum nickname length. | ||||
| 	local randindex = math.random(1, #nick) | ||||
| 	local randchar = string.sub(nick, randindex, randindex) | ||||
| 	local b = string.byte(randchar) | ||||
| 	b = b + 1 | ||||
| 	if b < 65 or b > 125 then | ||||
| 		b = 65 | ||||
| 	end | ||||
| 	-- Get the halves before and after the changed character | ||||
| 	local first = string.sub(nick, 1, randindex - 1) | ||||
| 	local last = string.sub(nick, randindex + 1, #nick) | ||||
| 	nick = first .. string.char(b) .. last  -- Insert the new charachter | ||||
| 	return nick | ||||
| end | ||||
|  | ||||
| function irc.capitalize(text) | ||||
|   -- Converts first character to upercase and the rest to lowercase. | ||||
|   -- "PING" -> "Ping" | "hello" -> "Hello" | "123" -> "123" | ||||
|   return text:sub(1, 1):upper()..text:sub(2):lower() | ||||
| end | ||||
|  | ||||
| function irc.split(str, sep) | ||||
| 	local t = {} | ||||
| 	for s in str:gmatch("%S+") do | ||||
| 		table.insert(t, s) | ||||
| 	end | ||||
| 	return t | ||||
| end | ||||
|  | ||||
| @@ -1,13 +0,0 @@ | ||||
| -- This file is licensed under the terms of the BSD 2-clause license. | ||||
| -- See LICENSE.txt for details. | ||||
|  | ||||
| irc.msgs = irc.lib.msgs | ||||
|  | ||||
| function irc:sendLocal(message) | ||||
| 	minetest.chat_send_all(message) | ||||
| end | ||||
|  | ||||
| function irc:playerMessage(name, message) | ||||
| 	return ("<%s> %s"):format(name, message) | ||||
| end | ||||
|  | ||||
| @@ -1,69 +0,0 @@ | ||||
| -- This file is licensed under the terms of the BSD 2-clause license. | ||||
| -- See LICENSE.txt for details. | ||||
|  | ||||
|  | ||||
| function irc:player_part(name) | ||||
| 	if not self.joined_players[name] then | ||||
| 		minetest.chat_send_player(name, "IRC: You are not in the channel.") | ||||
| 		return | ||||
| 	end | ||||
| 	self.joined_players[name] = nil | ||||
| 	minetest.chat_send_player(name, "IRC: You are now out of the channel.") | ||||
| end | ||||
|   | ||||
| function irc:player_join(name) | ||||
| 	if self.joined_players[name] then | ||||
| 		minetest.chat_send_player(name, "IRC: You are already in the channel.") | ||||
| 		return | ||||
| 	end | ||||
| 	self.joined_players[name] = true | ||||
| 	minetest.chat_send_player(name, "IRC: You are now in the channel.") | ||||
| end | ||||
|  | ||||
|  | ||||
| minetest.register_chatcommand("join", { | ||||
| 	description = "Join the IRC channel", | ||||
| 	privs = {shout=true}, | ||||
| 	func = function(name, param) | ||||
| 		irc:player_join(name) | ||||
| 	end | ||||
| }) | ||||
|   | ||||
| minetest.register_chatcommand("part", { | ||||
| 	description = "Part the IRC channel", | ||||
| 	privs = {shout=true}, | ||||
| 	func = function(name, param) | ||||
| 		irc:player_part(name) | ||||
| 	end | ||||
| }) | ||||
|   | ||||
| minetest.register_chatcommand("who", { | ||||
| 	description = "Tell who is currently on the channel", | ||||
| 	privs = {}, | ||||
| 	func = function(name, param) | ||||
| 		local s = "" | ||||
| 		for name, _ in pairs(irc.joined_players) do | ||||
| 			s = s..", "..name | ||||
| 		end | ||||
| 		minetest.chat_send_player(name, "Players On Channel:"..s) | ||||
| 	end | ||||
| }) | ||||
|  | ||||
|   | ||||
| minetest.register_on_joinplayer(function(player) | ||||
| 	local name = player:get_player_name() | ||||
| 	irc.joined_players[name] = irc.config.auto_join | ||||
| end) | ||||
|   | ||||
|   | ||||
| minetest.register_on_leaveplayer(function(player) | ||||
| 	local name = player:get_player_name() | ||||
| 	irc.joined_players[name] = nil | ||||
| end) | ||||
|  | ||||
| function irc:sendLocal(message) | ||||
|         for name, _ in pairs(self.joined_players) do | ||||
| 		minetest.chat_send_player(name, message) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| @@ -1,3 +0,0 @@ | ||||
| Remarque :  | ||||
|  | ||||
| Ajouter d'autres logos avec des cubes ou dessins à l'intérieur serait bien pour la diversité du sondage/vote futur ! :) | ||||
| Before Width: | Height: | Size: 219 KiB | 
| Before Width: | Height: | Size: 51 KiB | 
| Before Width: | Height: | Size: 13 KiB | 
| Before Width: | Height: | Size: 155 KiB | 
| Before Width: | Height: | Size: 415 KiB | 
| Before Width: | Height: | Size: 1.3 MiB | 
| Before Width: | Height: | Size: 22 KiB | 
| Before Width: | Height: | Size: 22 KiB | 
| Before Width: | Height: | Size: 22 KiB | 
| Before Width: | Height: | Size: 22 KiB | 
| Before Width: | Height: | Size: 16 KiB | 
| Before Width: | Height: | Size: 3.4 KiB | 
| Before Width: | Height: | Size: 15 KiB | 
| Before Width: | Height: | Size: 696 B | 
| Before Width: | Height: | Size: 731 B | 
| @@ -1,644 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||||
| <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||||
|  | ||||
| <svg | ||||
|    xmlns:dc="http://purl.org/dc/elements/1.1/" | ||||
|    xmlns:cc="http://creativecommons.org/ns#" | ||||
|    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||||
|    xmlns:svg="http://www.w3.org/2000/svg" | ||||
|    xmlns="http://www.w3.org/2000/svg" | ||||
|    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | ||||
|    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | ||||
|    width="1080" | ||||
|    height="1080" | ||||
|    id="svg2" | ||||
|    version="1.1" | ||||
|    inkscape:version="0.48.5 r10040" | ||||
|    sodipodi:docname="mffnewconc2?.svg" | ||||
|    inkscape:export-filename="/home/robin/Documents/mffnewconc9?.png" | ||||
|    inkscape:export-xdpi="90" | ||||
|    inkscape:export-ydpi="90"> | ||||
|   <defs | ||||
|      id="defs4"> | ||||
|     <inkscape:perspective | ||||
|        sodipodi:type="inkscape:persp3d" | ||||
|        inkscape:vp_x="260 : 540 : 1" | ||||
|        inkscape:vp_y="0 : 1000 : 0" | ||||
|        inkscape:vp_z="820 : 541.42857 : 1" | ||||
|        inkscape:persp3d-origin="540 : 360 : 1" | ||||
|        id="perspective3815" /> | ||||
|     <inkscape:perspective | ||||
|        sodipodi:type="inkscape:persp3d" | ||||
|        inkscape:vp_x="220.16209 : 539.34384 : 1" | ||||
|        inkscape:vp_y="0 : 1147.5441 : 0" | ||||
|        inkscape:vp_z="859.51372 : 540.98317 : 1" | ||||
|        inkscape:persp3d-origin="539.83791 : 332.78589 : 1" | ||||
|        id="perspective3815-8" /> | ||||
|     <inkscape:perspective | ||||
|        sodipodi:type="inkscape:persp3d" | ||||
|        inkscape:vp_x="260.14183 : 540.00001 : 1" | ||||
|        inkscape:vp_y="0 : 999.99996 : 0" | ||||
|        inkscape:vp_z="819.5745 : 541.42856 : 1" | ||||
|        inkscape:persp3d-origin="539.85817 : 360 : 1" | ||||
|        id="perspective3815-8-7" /> | ||||
|     <inkscape:perspective | ||||
|        sodipodi:type="inkscape:persp3d" | ||||
|        inkscape:vp_x="300.12157 : 540.00002 : 1" | ||||
|        inkscape:vp_y="0 : 857.14285 : 0" | ||||
|        inkscape:vp_z="779.63528 : 541.22449 : 1" | ||||
|        inkscape:persp3d-origin="539.87843 : 385.71429 : 1" | ||||
|        id="perspective3815-8-7-0" /> | ||||
|     <inkscape:perspective | ||||
|        sodipodi:type="inkscape:persp3d" | ||||
|        inkscape:vp_x="340.10131 : 540.00001 : 1" | ||||
|        inkscape:vp_y="0 : 714.28573 : 0" | ||||
|        inkscape:vp_z="739.69607 : 541.02041 : 1" | ||||
|        inkscape:persp3d-origin="539.89869 : 411.42857 : 1" | ||||
|        id="perspective3815-8-7-0-6" /> | ||||
|     <inkscape:perspective | ||||
|        sodipodi:type="inkscape:persp3d" | ||||
|        inkscape:vp_x="420.06078 : 540.00001 : 1" | ||||
|        inkscape:vp_y="0 : 428.57144 : 0" | ||||
|        inkscape:vp_z="659.81765 : 540.61225 : 1" | ||||
|        inkscape:persp3d-origin="539.93922 : 462.85714 : 1" | ||||
|        id="perspective3815-8-7-0-6-3" /> | ||||
|     <inkscape:perspective | ||||
|        sodipodi:type="inkscape:persp3d" | ||||
|        inkscape:vp_x="240.16209 : 679.34384 : 1" | ||||
|        inkscape:vp_y="0 : 1147.5441 : 0" | ||||
|        inkscape:vp_z="879.51372 : 680.98317 : 1" | ||||
|        inkscape:persp3d-origin="559.83791 : 472.78589 : 1" | ||||
|        id="perspective3815-8-0" /> | ||||
|     <inkscape:perspective | ||||
|        sodipodi:type="inkscape:persp3d" | ||||
|        inkscape:vp_x="20.263402 : 540 : 1" | ||||
|        inkscape:vp_y="0 : 1857.1429 : 0" | ||||
|        inkscape:vp_z="1059.2098 : 542.65302 : 1" | ||||
|        inkscape:persp3d-origin="539.7366 : 205.71429 : 1" | ||||
|        id="perspective3815-8-8" /> | ||||
|   </defs> | ||||
|   <sodipodi:namedview | ||||
|      id="base" | ||||
|      pagecolor="#ffffff" | ||||
|      bordercolor="#666666" | ||||
|      borderopacity="1.0" | ||||
|      inkscape:pageopacity="0.0" | ||||
|      inkscape:pageshadow="2" | ||||
|      inkscape:zoom="0.5" | ||||
|      inkscape:cx="529.95296" | ||||
|      inkscape:cy="538.9772" | ||||
|      inkscape:document-units="px" | ||||
|      inkscape:current-layer="layer1" | ||||
|      showgrid="true" | ||||
|      showguides="true" | ||||
|      inkscape:guide-bbox="true" | ||||
|      inkscape:window-width="1280" | ||||
|      inkscape:window-height="734" | ||||
|      inkscape:window-x="0" | ||||
|      inkscape:window-y="27" | ||||
|      inkscape:window-maximized="1"> | ||||
|     <inkscape:grid | ||||
|        type="xygrid" | ||||
|        id="grid2985" | ||||
|        empspacing="5" | ||||
|        visible="true" | ||||
|        enabled="true" | ||||
|        snapvisiblegridlinesonly="true" /> | ||||
|   </sodipodi:namedview> | ||||
|   <metadata | ||||
|      id="metadata7"> | ||||
|     <rdf:RDF> | ||||
|       <cc:Work | ||||
|          rdf:about=""> | ||||
|         <dc:format>image/svg+xml</dc:format> | ||||
|         <dc:type | ||||
|            rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | ||||
|         <dc:title></dc:title> | ||||
|       </cc:Work> | ||||
|     </rdf:RDF> | ||||
|   </metadata> | ||||
|   <g | ||||
|      inkscape:groupmode="layer" | ||||
|      id="layer5" | ||||
|      inkscape:label="Calque#3"> | ||||
|     <g | ||||
|        id="g3910-2-6" | ||||
|        transform="matrix(0.61739494,0,0,0.61739493,206.60674,223.67019)" | ||||
|        style="fill:#4d4d4d"> | ||||
|       <g | ||||
|          id="g3882-5-4" | ||||
|          style="fill:#4d4d4d"> | ||||
|         <path | ||||
|            style="fill:#4d4d4d;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|            d="M 540,0 320,0 0,320 l 0,440 320,320 220,0 0,-80 -180,0 L 80,720 80,360 360,80 540,80 z" | ||||
|            id="path3093-1-4" | ||||
|            inkscape:connector-curvature="0" | ||||
|            transform="translate(0,-27.637817)" | ||||
|            sodipodi:nodetypes="ccccccccccccc" /> | ||||
|         <path | ||||
|            style="fill:#4d4d4d;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|            d="m 540,-27.637817 220,0 320,319.999997 0,440 -320,320.00002 -220,0 0,-80.00002 180,0 280,-280 0,-360 -280,-279.999997 -180,0 z" | ||||
|            id="path3093-2-8-1" | ||||
|            inkscape:connector-curvature="0" | ||||
|            sodipodi:nodetypes="ccccccccccccc" /> | ||||
|       </g> | ||||
|       <g | ||||
|          transform="matrix(0.92620513,-0.37701997,0.37701997,0.92620513,-153.32155,241.40048)" | ||||
|          id="g3882-3-7-5" | ||||
|          style="fill:#4d4d4d"> | ||||
|         <path | ||||
|            style="fill:#4d4d4d;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|            d="M 540,0 320,0 0,320 l 0,440 320,320 220,0 0,-80 -180,0 L 80,720 80,360 360,80 540,80 z" | ||||
|            id="path3093-7-0-4" | ||||
|            inkscape:connector-curvature="0" | ||||
|            transform="translate(0,-27.637817)" | ||||
|            sodipodi:nodetypes="ccccccccccccc" /> | ||||
|         <path | ||||
|            style="fill:#4d4d4d;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|            d="m 540,-27.637817 220,0 320,319.999997 0,440 -320,320.00002 -220,0 0,-80.00002 180,0 280,-280 0,-360 -280,-279.999997 -180,0 z" | ||||
|            id="path3093-2-3-9-5" | ||||
|            inkscape:connector-curvature="0" | ||||
|            sodipodi:nodetypes="ccccccccccccc" /> | ||||
|       </g> | ||||
|     </g> | ||||
|     <g | ||||
|        id="g3910-2-6-7" | ||||
|        transform="matrix(0.61739494,0,0,0.61739493,206.4991,223.67019)" | ||||
|        style="fill:#4d4d4d"> | ||||
|       <g | ||||
|          id="g3882-5-4-8" | ||||
|          style="fill:#4d4d4d"> | ||||
|         <path | ||||
|            style="fill:#4d4d4d;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|            d="M 540,0 320,0 0,320 l 0,440 320,320 220,0 0,-80 -180,0 L 80,720 80,360 360,80 540,80 z" | ||||
|            id="path3093-1-4-1" | ||||
|            inkscape:connector-curvature="0" | ||||
|            transform="translate(0,-27.637817)" | ||||
|            sodipodi:nodetypes="ccccccccccccc" /> | ||||
|         <path | ||||
|            style="fill:#4d4d4d;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|            d="m 540,-27.637817 220,0 320,319.999997 0,440 -320,320.00002 -220,0 0,-80.00002 180,0 280,-280 0,-360 -280,-279.999997 -180,0 z" | ||||
|            id="path3093-2-8-1-3" | ||||
|            inkscape:connector-curvature="0" | ||||
|            sodipodi:nodetypes="ccccccccccccc" /> | ||||
|       </g> | ||||
|       <g | ||||
|          transform="matrix(0.92620513,-0.37701997,0.37701997,0.92620513,-153.32155,241.40048)" | ||||
|          id="g3882-3-7-5-2" | ||||
|          style="fill:#4d4d4d"> | ||||
|         <path | ||||
|            style="fill:#4d4d4d;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|            d="M 540,0 320,0 0,320 l 0,440 320,320 220,0 0,-80 -180,0 L 80,720 80,360 360,80 540,80 z" | ||||
|            id="path3093-7-0-4-2" | ||||
|            inkscape:connector-curvature="0" | ||||
|            transform="translate(0,-27.637817)" | ||||
|            sodipodi:nodetypes="ccccccccccccc" /> | ||||
|         <path | ||||
|            style="fill:#4d4d4d;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|            d="m 540,-27.637817 220,0 320,319.999997 0,440 -320,320.00002 -220,0 0,-80.00002 180,0 280,-280 0,-360 -280,-279.999997 -180,0 z" | ||||
|            id="path3093-2-3-9-5-2" | ||||
|            inkscape:connector-curvature="0" | ||||
|            sodipodi:nodetypes="ccccccccccccc" /> | ||||
|       </g> | ||||
|     </g> | ||||
|     <g | ||||
|        id="g3910-2-6-7-5" | ||||
|        transform="matrix(0.61739494,0,0,0.61739493,206.4991,223.67019)" | ||||
|        style="fill:#4d4d4d"> | ||||
|       <g | ||||
|          id="g3882-5-4-8-5" | ||||
|          style="fill:#4d4d4d"> | ||||
|         <path | ||||
|            style="fill:#4d4d4d;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|            d="M 540,0 320,0 0,320 l 0,440 320,320 220,0 0,-80 -180,0 L 80,720 80,360 360,80 540,80 z" | ||||
|            id="path3093-1-4-1-7" | ||||
|            inkscape:connector-curvature="0" | ||||
|            transform="translate(0,-27.637817)" | ||||
|            sodipodi:nodetypes="ccccccccccccc" /> | ||||
|         <path | ||||
|            style="fill:#4d4d4d;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|            d="m 540,-27.637817 220,0 320,319.999997 0,440 -320,320.00002 -220,0 0,-80.00002 180,0 280,-280 0,-360 -280,-279.999997 -180,0 z" | ||||
|            id="path3093-2-8-1-3-4" | ||||
|            inkscape:connector-curvature="0" | ||||
|            sodipodi:nodetypes="ccccccccccccc" /> | ||||
|       </g> | ||||
|       <g | ||||
|          transform="matrix(0.92620513,-0.37701997,0.37701997,0.92620513,-153.32155,241.40048)" | ||||
|          id="g3882-3-7-5-2-1" | ||||
|          style="fill:#4d4d4d"> | ||||
|         <path | ||||
|            style="fill:#4d4d4d;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|            d="M 540,0 320,0 0,320 l 0,440 320,320 220,0 0,-80 -180,0 L 80,720 80,360 360,80 540,80 z" | ||||
|            id="path3093-7-0-4-2-0" | ||||
|            inkscape:connector-curvature="0" | ||||
|            transform="translate(0,-27.637817)" | ||||
|            sodipodi:nodetypes="ccccccccccccc" /> | ||||
|         <path | ||||
|            style="fill:#4d4d4d;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|            d="m 540,-27.637817 220,0 320,319.999997 0,440 -320,320.00002 -220,0 0,-80.00002 180,0 280,-280 0,-360 -280,-279.999997 -180,0 z" | ||||
|            id="path3093-2-3-9-5-2-7" | ||||
|            inkscape:connector-curvature="0" | ||||
|            sodipodi:nodetypes="ccccccccccccc" /> | ||||
|       </g> | ||||
|     </g> | ||||
|   </g> | ||||
|   <g | ||||
|      inkscape:groupmode="layer" | ||||
|      id="layer2" | ||||
|      inkscape:label="Calque" | ||||
|      style="display:none" | ||||
|      sodipodi:insensitive="true"> | ||||
|     <g | ||||
|        sodipodi:type="inkscape:box3d" | ||||
|        style="fill:#c83737;fill-opacity:1;stroke:none" | ||||
|        id="g3817-6-7" | ||||
|        inkscape:perspectiveID="#perspective3815-8-0" | ||||
|        inkscape:corner0="1 : 0.32 : 0 : 1" | ||||
|        inkscape:corner7="-2.220446e-16 : 0.04 : 1.0040647 : 1"> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3827-4-7" | ||||
|          style="fill:#c83737;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="13" | ||||
|          d="M 400,480.98425 559.83791,561.31235 720,480 560.27045,453.58784 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3819-4-1" | ||||
|          style="fill:#c83737;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="6" | ||||
|          d="m 400,320.32808 0,160.65617 160.27045,-27.39641 0,-106.9592 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3829-4-6" | ||||
|          style="fill:#c83737;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="11" | ||||
|          d="M 560.27045,346.62864 720,319.66968 720,480 560.27045,453.58784 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3821-3-2" | ||||
|          style="fill:#c83737;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="5" | ||||
|          d="M 400,320.32808 559.83791,240 720,319.66968 560.27045,346.62864 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3825-2-3" | ||||
|          style="fill:#c83737;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="14" | ||||
|          d="m 559.83791,240 0,321.31235 L 720,480 720,319.66968 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3823-6-2" | ||||
|          style="fill:#c83737;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="3" | ||||
|          d="M 400,320.32808 559.83791,240 l 0,321.31235 L 400,480.98425 z" /> | ||||
|     </g> | ||||
|     <path | ||||
|        sodipodi:type="arc" | ||||
|        style="fill:#000000;fill-opacity:1;stroke:none" | ||||
|        id="path3049-3" | ||||
|        sodipodi:cx="540" | ||||
|        sodipodi:cy="540" | ||||
|        sodipodi:rx="540" | ||||
|        sodipodi:ry="540" | ||||
|        d="M 1080,540 A 540,540 0 1 1 0,540 540,540 0 1 1 1080,540 z" | ||||
|        transform="matrix(0.77777778,0,0,0.77777778,120,120)" /> | ||||
|     <path | ||||
|        sodipodi:type="arc" | ||||
|        style="fill:#b7c4c8;fill-opacity:1;stroke:none" | ||||
|        id="path3051-1" | ||||
|        sodipodi:cx="540" | ||||
|        sodipodi:cy="540" | ||||
|        sodipodi:rx="380" | ||||
|        sodipodi:ry="380" | ||||
|        d="m 920,540 a 380,380 0 1 1 -760,0 380,380 0 1 1 760,0 z" /> | ||||
|   </g> | ||||
|   <g | ||||
|      inkscape:groupmode="layer" | ||||
|      id="layer4" | ||||
|      inkscape:label="Calque#2" | ||||
|      style="display:inline" | ||||
|      sodipodi:insensitive="true"> | ||||
|     <path | ||||
|        style="fill:#1c2422;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|        d="m 540,190 -300,200 0,300 300,200 300,-200 0,-300 z" | ||||
|        id="path4270" | ||||
|        inkscape:connector-curvature="0" | ||||
|        sodipodi:nodetypes="ccccccc" /> | ||||
|     <path | ||||
|        style="fill:#b7c4c8;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|        d="M 260,400 260,680 540,870 820,680 820,400 540,210 z" | ||||
|        id="path4272" | ||||
|        inkscape:connector-curvature="0" | ||||
|        sodipodi:nodetypes="ccccccc" /> | ||||
|     <path | ||||
|        style="fill:#8f9ca0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|        d="m 260,680 20,-10 0,-260 -20,-10 280,-190 280,190 -20,10 0,260 20,10 -280,190 z" | ||||
|        id="path5704" | ||||
|        inkscape:connector-curvature="0" | ||||
|        sodipodi:nodetypes="ccccccccccc" /> | ||||
|   </g> | ||||
|   <g | ||||
|      inkscape:groupmode="layer" | ||||
|      id="layer3" | ||||
|      inkscape:label="Calque#1" | ||||
|      sodipodi:insensitive="true"> | ||||
|     <path | ||||
|        style="fill:#af69c0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|        d="m 380,460 0,160 160,80 0,100 -260,-130 0,-260 z" | ||||
|        id="path5688" | ||||
|        inkscape:connector-curvature="0" /> | ||||
|     <path | ||||
|        style="fill:#be78ca;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|        d="m 540,700 0,100 260,-130 0,-260 -100,50 0,160 z" | ||||
|        id="path5698" | ||||
|        inkscape:connector-curvature="0" | ||||
|        sodipodi:nodetypes="ccccccc" /> | ||||
|     <path | ||||
|        style="fill:#cd87de;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|        d="M 280,410 540,280 800,410 540,540 z" | ||||
|        id="path3873" | ||||
|        inkscape:connector-curvature="0" /> | ||||
|   </g> | ||||
|   <g | ||||
|      inkscape:label="Calque 1" | ||||
|      inkscape:groupmode="layer" | ||||
|      id="layer1" | ||||
|      transform="translate(0,27.637817)"> | ||||
|     <g | ||||
|        sodipodi:type="inkscape:box3d" | ||||
|        style="fill:#333333;fill-opacity:1;stroke:none" | ||||
|        id="g3817" | ||||
|        inkscape:perspectiveID="#perspective3815" | ||||
|        inkscape:corner0="1 : 0.32 : 0 : 1" | ||||
|        inkscape:corner7="-2.220446e-16 : 0.04 : 1.0040647 : 1"> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3827" | ||||
|          style="fill:#afafde;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="13" | ||||
|          d="m 400,582.36218 140,70 140.28395,-70.85771 -139.90509,-23.01624 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3819" | ||||
|          style="fill:#353564;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="6" | ||||
|          d="m 400,442.36218 0,140 140.37886,-23.87395 0,-93.20705 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3829" | ||||
|          style="fill:#e9e9ff;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="11" | ||||
|          d="m 540.37886,465.28118 139.90509,-23.49275 0,139.71604 -139.90509,-23.01624 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3821" | ||||
|          style="fill:#4d4d9f;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="5" | ||||
|          d="m 400,442.36218 140,-70 140.28395,69.42625 -139.90509,23.49275 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3825" | ||||
|          style="fill:#d7d7ff;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="14" | ||||
|          d="m 540,372.36218 0,280 140.28395,-70.85771 0,-139.71604 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3823" | ||||
|          style="fill:#8686bf;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="3" | ||||
|          d="m 400,442.36218 140,-70 0,280 -140,-70 z" /> | ||||
|     </g> | ||||
|     <g | ||||
|        sodipodi:type="inkscape:box3d" | ||||
|        style="fill:#71c837;fill-opacity:1;stroke:none" | ||||
|        id="g3817-6-3" | ||||
|        inkscape:perspectiveID="#perspective3815-8-7" | ||||
|        inkscape:corner0="1 : 0.32 : 0 : 1" | ||||
|        inkscape:corner7="-2.220446e-16 : 0.04 : 1.0040647 : 1"> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3827-4-0" | ||||
|          style="fill:#71c837;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="13" | ||||
|          d="m 400,582.36218 139.85817,70 L 680,581.50448 540.23664,558.48823 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3819-4-0" | ||||
|          style="fill:#71c837;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="6" | ||||
|          d="m 400,442.36218 0,140 140.23664,-23.87395 0,-93.20704 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3829-4-0" | ||||
|          style="fill:#71c837;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="11" | ||||
|          d="M 540.23664,465.28119 680,441.78844 680,581.50448 540.23664,558.48823 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3821-3-3" | ||||
|          style="fill:#71c837;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="5" | ||||
|          d="M 400,442.36218 539.85817,372.3622 680,441.78844 540.23664,465.28119 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3825-2-9" | ||||
|          style="fill:#71c837;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="14" | ||||
|          d="m 539.85817,372.3622 0,279.99998 L 680,581.50448 680,441.78844 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3823-6-1" | ||||
|          style="fill:#71c837;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="3" | ||||
|          d="m 400,442.36218 139.85817,-69.99998 0,279.99998 -139.85817,-70 z" /> | ||||
|     </g> | ||||
|     <g | ||||
|        sodipodi:type="inkscape:box3d" | ||||
|        style="fill:#3771c8;fill-opacity:1;stroke:none" | ||||
|        id="g3817-6-3-1" | ||||
|        inkscape:perspectiveID="#perspective3815-8-7-0" | ||||
|        inkscape:corner0="1 : 0.32 : 0 : 1" | ||||
|        inkscape:corner7="-2.220446e-16 : 0.04 : 1.0040647 : 1"> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3827-4-0-7" | ||||
|          style="fill:#3771c8;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="13" | ||||
|          d="M 420,572.36217 539.87843,632.36218 660,571.627 540.20283,551.89878 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3819-4-0-0" | ||||
|          style="fill:#3771c8;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="6" | ||||
|          d="m 420,452.36217 0,120 120.20283,-20.46339 0,-79.89175 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3829-4-0-1" | ||||
|          style="fill:#3771c8;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="11" | ||||
|          d="M 540.20283,472.00703 660,451.87039 660,571.627 540.20283,551.89878 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3821-3-3-9" | ||||
|          style="fill:#3771c8;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="5" | ||||
|          d="M 420,452.36217 539.87843,392.36218 660,451.87039 540.20283,472.00703 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3825-2-9-5" | ||||
|          style="fill:#3771c8;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="14" | ||||
|          d="m 539.87843,392.36218 0,240 L 660,571.627 660,451.87039 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3823-6-1-9" | ||||
|          style="fill:#3771c8;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="3" | ||||
|          d="m 420,452.36217 119.87843,-59.99999 0,240 L 420,572.36217 z" /> | ||||
|     </g> | ||||
|     <g | ||||
|        sodipodi:type="inkscape:box3d" | ||||
|        style="fill:#000000;fill-opacity:1;stroke:none" | ||||
|        id="g3817-6-3-1-0" | ||||
|        inkscape:perspectiveID="#perspective3815-8-7-0-6" | ||||
|        inkscape:corner0="1 : 0.32 : 0 : 1" | ||||
|        inkscape:corner7="-2.220446e-16 : 0.04 : 1.0040647 : 1"> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3827-4-0-7-6" | ||||
|          style="fill:#000000;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="13" | ||||
|          d="m 440,562.36218 99.89869,50 L 640,561.74953 540.16903,545.30935 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3819-4-0-0-2" | ||||
|          style="fill:#000000;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="6" | ||||
|          d="m 440,462.36218 0,100 100.16903,-17.05283 0,-66.57646 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3829-4-0-1-5" | ||||
|          style="fill:#000000;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="11" | ||||
|          d="M 540.16903,478.73289 640,461.95235 l 0,99.79718 -99.83097,-16.44018 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3821-3-3-9-8" | ||||
|          style="fill:#000000;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="5" | ||||
|          d="m 440,462.36218 99.89869,-50 L 640,461.95235 540.16903,478.73289 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3825-2-9-5-8" | ||||
|          style="fill:#000000;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="14" | ||||
|          d="m 539.89869,412.36218 0,200 L 640,561.74953 l 0,-99.79718 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3823-6-1-9-2" | ||||
|          style="fill:#000000;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="3" | ||||
|          d="m 440,462.36218 99.89869,-50 0,200 -99.89869,-50 z" /> | ||||
|     </g> | ||||
|     <g | ||||
|        sodipodi:type="inkscape:box3d" | ||||
|        style="fill:#ffffff;fill-opacity:1;stroke:none" | ||||
|        id="g3817-6-3-1-0-1" | ||||
|        inkscape:perspectiveID="#perspective3815-8-7-0-6-3" | ||||
|        inkscape:corner0="1 : 0.32 : 0 : 1" | ||||
|        inkscape:corner7="-2.220446e-16 : 0.04 : 1.0040647 : 1"> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3827-4-0-7-6-2" | ||||
|          style="fill:#ffffff;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="13" | ||||
|          d="m 480,542.36218 59.93922,30.00001 60.06079,-30.3676 -59.89859,-9.86411 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3819-4-0-0-2-5" | ||||
|          style="fill:#ffffff;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="6" | ||||
|          d="m 480,482.36218 0,60 60.10142,-10.2317 0,-39.94587 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3829-4-0-1-5-4" | ||||
|          style="fill:#ffffff;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="11" | ||||
|          d="m 540.10142,492.18461 59.89859,-10.06833 0,59.87831 -59.89859,-9.86411 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3821-3-3-9-8-1" | ||||
|          style="fill:#ffffff;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="5" | ||||
|          d="m 480,482.36218 59.93922,-30 60.06079,29.7541 -59.89859,10.06833 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3825-2-9-5-8-9" | ||||
|          style="fill:#ffffff;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="14" | ||||
|          d="m 539.93922,452.36218 0,120.00001 60.06079,-30.3676 0,-59.87831 z" /> | ||||
|       <path | ||||
|          sodipodi:type="inkscape:box3dside" | ||||
|          id="path3823-6-1-9-2-0" | ||||
|          style="fill:#ffffff;fill-rule:evenodd;stroke:none" | ||||
|          inkscape:box3dsidetype="3" | ||||
|          d="m 480,482.36218 59.93922,-30 0,120.00001 L 480,542.36218 z" /> | ||||
|     </g> | ||||
|     <path | ||||
|        style="fill:#b3b3b3;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|        d="m 480,510 60,30 0,60 -60,-30 z" | ||||
|        id="path5680" | ||||
|        inkscape:connector-curvature="0" | ||||
|        transform="translate(0,-27.637817)" /> | ||||
|     <path | ||||
|        style="fill:#1449a0;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|        d="m 420,480 20,10 0,100 100,50 0,20 -120,-60 z" | ||||
|        id="path5682" | ||||
|        inkscape:connector-curvature="0" | ||||
|        transform="translate(0,-27.637817)" /> | ||||
|     <path | ||||
|        style="fill:#49a014;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|        d="m 400,470 20,10 0,120 120,60 0,20 -140,-70 z" | ||||
|        id="path5684" | ||||
|        inkscape:connector-curvature="0" | ||||
|        transform="translate(0,-27.637817)" /> | ||||
|     <path | ||||
|        style="fill:#a01414;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|        d="m 380,460 20,10 0,140 140,70 0,21 -160,-81 z" | ||||
|        id="path5686" | ||||
|        inkscape:connector-curvature="0" | ||||
|        transform="translate(0,-27.637817)" | ||||
|        sodipodi:nodetypes="ccccccc" /> | ||||
|     <path | ||||
|        style="fill:#cccccc;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|        d="m 540,540 60,-30 0,60 -60,30 z" | ||||
|        id="path5690" | ||||
|        inkscape:connector-curvature="0" | ||||
|        transform="translate(0,-27.637817)" /> | ||||
|     <path | ||||
|        style="fill:#1e64b4;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|        d="m 640,490 20,-10 0,120 -120,60 0,-20 100,-50 z" | ||||
|        id="path5692" | ||||
|        inkscape:connector-curvature="0" | ||||
|        transform="translate(0,-27.637817)" /> | ||||
|     <path | ||||
|        style="fill:#64b41e;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|        d="m 660,480 20,-10 0,140 -140,70 0,-20 120,-60 z" | ||||
|        id="path5694" | ||||
|        inkscape:connector-curvature="0" | ||||
|        transform="translate(0,-27.637817)" /> | ||||
|     <path | ||||
|        style="fill:#b41e1e;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|        d="m 680,470 20,-10 0,160 -160,81 0,-21 140,-70 z" | ||||
|        id="path5696" | ||||
|        inkscape:connector-curvature="0" | ||||
|        transform="translate(0,-27.637817)" | ||||
|        sodipodi:nodetypes="ccccccc" /> | ||||
|     <path | ||||
|        style="fill:#c83737;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" | ||||
|        d="m 400,470 140,-70 140,70 20,-10 -160,-80 -160,80 z" | ||||
|        id="path3886" | ||||
|        inkscape:connector-curvature="0" | ||||
|        transform="translate(0,-27.637817)" /> | ||||
|   </g> | ||||
| </svg> | ||||
| Before Width: | Height: | Size: 28 KiB | 
| @@ -1,182 +0,0 @@ | ||||
| #!/usr/bin/env python2 | ||||
| # -*- coding: UTF-8 -*- | ||||
| import sys, os, sqlite3 | ||||
| import encodings, calendar, time | ||||
| from cStringIO import StringIO | ||||
|  | ||||
| home = os.environ.get("HOME") | ||||
| db = "%s/rollback/rollback.sqlite" % (home) | ||||
|  | ||||
| #[id=6,actor=Mg,type=1;list=None,index=None,add=None,stacknode=None,stackquantity=None;x=252,y=59,z=-401;newnode=air,newparam1=15,newparam2=None,newmeta=None] | ||||
|  | ||||
| class Convert_id(object): | ||||
| 	def __init__(self, base): | ||||
| 		self.__players = dict() | ||||
| 		self.__nodes = dict() | ||||
| 		try: | ||||
| 			conn = sqlite3.connect(db) | ||||
| 			cur = conn.cursor() | ||||
| 		except Exception as err: | ||||
| 			print(err) | ||||
| 			print("problème avec la base de données") | ||||
| 			sys.exit(1) | ||||
| 		else: | ||||
| 			try: | ||||
| 				cur.execute("SELECT * from actor") | ||||
| 			except sqlite3.OperationalError as err: | ||||
| 				print(err) | ||||
| 			else: | ||||
| 				result = cur.fetchall() | ||||
| 				for res in result: | ||||
| 					self.__players[res[0]] = res[1][len("player:"):] | ||||
| 			try: | ||||
| 				cur.execute("SELECT * from node") | ||||
| 			except sqlite3.OperationalError as err: | ||||
| 				print(err) | ||||
| 			else: | ||||
| 				result = cur.fetchall() | ||||
| 				for res in result: | ||||
| 					self.__nodes[res[0]] = res[1] | ||||
| 			finally: | ||||
| 				cur.close() | ||||
| 				conn.close() | ||||
|  | ||||
| 	def get_player_name(self, player_id): | ||||
| 		if self.__players.has_key(player_id): | ||||
| 			return self.__players[player_id] | ||||
| 		else: | ||||
| 			return None | ||||
|  | ||||
| 	def get_node_name(self, node_id): | ||||
| 		if self.__nodes.has_key(node_id): | ||||
| 			return self.__nodes[node_id] | ||||
| 		else: | ||||
| 			return None | ||||
|  | ||||
| ######################################################################## | ||||
| ## Utilities | ||||
| # | ||||
|  | ||||
| def ston(a): | ||||
| 	""" | ||||
| 		Returns a string equal to a or None | ||||
| 	""" | ||||
| 	if a: | ||||
| 		return str(a) | ||||
| 	else: | ||||
| 		return None | ||||
|  | ||||
| def select_all_nodes(startstamp, endstamp): | ||||
| 	try: | ||||
| 		conn = sqlite3.connect(db) | ||||
| 		conn.text_factory = str | ||||
| 		cur = conn.cursor() | ||||
| 	except sqlite3.OperationalError as err: | ||||
| 		print(err) | ||||
| 		sys.exit(1) | ||||
| 	try: | ||||
| 		# x because we need position | ||||
| 		cur.execute("SELECT * FROM action WHERE x AND timestamp >=:startstamp AND timestamp < :endstamp", {"startstamp":startstamp, "endstamp":endstamp}) | ||||
| 	except sqlite3.OperationalError as err: | ||||
| 		print(err) | ||||
| 		sys.exit(1) | ||||
| 	else: | ||||
| 		result = cur.fetchall() | ||||
| 	finally: | ||||
| 		cur.close() | ||||
| 		conn.close() | ||||
| 	return(result) | ||||
|  | ||||
|  | ||||
| # Big-endian!!! | ||||
| def readU16(strm): | ||||
| 	return (ord(strm.read(1)) << 16) + (ord(strm.read(1))) | ||||
|  | ||||
| def readU32(strm): | ||||
| 	return (ord(strm.read(1)) << 24) + (ord(strm.read(1)) << 16) + (ord(strm.read(1)) << 8) + (ord(strm.read(1))) | ||||
|  | ||||
| def decode(chaine): | ||||
| 	if not chaine : | ||||
| 		return None | ||||
| 	else: | ||||
| 		strm = StringIO(chaine) | ||||
| 		table = "[" | ||||
| 		nEntries = readU32(strm) | ||||
| 		for n in range(nEntries): | ||||
| 			keyLen = readU16(strm) | ||||
| 			key = strm.read(keyLen) | ||||
| 			valLen = readU32(strm) | ||||
| 			val = strm.read(valLen) | ||||
| 			# Beware of potential quotes in meta, they must be escaped | ||||
| 			# Fortunately their escape codes are the same in Python and Lua | ||||
| 			# (and pretty much every language influenced by C) | ||||
| 			# ------------ | ||||
| 			# Attention aux potentiels quotes dedans les meta, il faut les escape | ||||
| 			# Heureusement leur mode d'escape est quasi le même en Python que Lua | ||||
| 			table += '%s="%s"' % (key, val.encode('string-escape').replace('"', '\\"')) | ||||
| 			if n != nEntries-1: | ||||
| 				table += "," | ||||
| 		table += "]" | ||||
| 		return table | ||||
|  | ||||
|  | ||||
|  | ||||
| def to_table(node): | ||||
| 	# Init bracket and basic datas | ||||
| 	table = "[" | ||||
| 	table += 'id=%d' % node[0] | ||||
| 	table += ',actor=%s' % Id.get_player_name(node[1]) | ||||
| 	table += ',type=%d' % node[3] | ||||
| 	# Inventory Manipulation | ||||
| 	table += ';list=%s' % node[4] | ||||
| 	table += ',index=%s' % node[5] | ||||
| 	table += ',add=%s' % node[6] | ||||
| 	table += ',stacknode=%s' % Id.get_node_name(node[7]) | ||||
| 	table += ',stackquantity=%s' % node[8] | ||||
| 	# Position | ||||
| 	table += ';x=%s,y=%s,z=%s' % (node[10], node[11], node[12]) | ||||
| 	# New node | ||||
| 	table += ';newnode=%s' % Id.get_node_name(node[17]) | ||||
| 	table += ',newparam1=%s' % ston(node[18]) | ||||
| 	table += ',newparam2=%s' % ston(node[19]) | ||||
| 	table += ',newmeta=%s' % decode(node[20]) | ||||
| 	# Ending | ||||
| 	table += ']\n' | ||||
| 	return (table) | ||||
|  | ||||
| def write_list(nodes, i): | ||||
| 	try: | ||||
| 		name = "rollback/database-output.%s.txt" % i | ||||
| 		f = open(name, "w") | ||||
| 	except Exception as err: | ||||
| 		print(err) | ||||
| 		sys.exit(1) | ||||
|  | ||||
| 	for node in nodes: | ||||
| 		table = to_table(node) | ||||
| 		f.write(table) | ||||
| 	f.close() | ||||
|  | ||||
|  | ||||
| ######################################################################## | ||||
| ## Main | ||||
| # | ||||
|  | ||||
| if __name__ == '__main__': | ||||
| 	Id = Convert_id(db) | ||||
| 	#select all nodes player as set i where time >= time | ||||
| 	#timestamp = 1426978800 | ||||
| 	timestamp = 0 | ||||
| 	i = 0 | ||||
| 	while timestamp <= time.time(): | ||||
| 			all_nodes = select_all_nodes(timestamp, timestamp+24*60*60) | ||||
| 			if len(all_nodes) > 0: | ||||
| 				write_list(all_nodes, i) | ||||
| 				i += 1 | ||||
| 				print("%s (%s) to %s (%s) => %s entries" % ( | ||||
| 					time.strftime("%m/%d/%Y", time.gmtime(timestamp)), timestamp, | ||||
| 					time.strftime("%m/%d/%Y", time.gmtime(timestamp+24*60*60)), timestamp+24*60*60, | ||||
| 					len(all_nodes)) | ||||
| 				) | ||||
| 			timestamp += 24*60*60 | ||||
|  | ||||
| @@ -1,21 +0,0 @@ | ||||
| # Rebase actives branches | ||||
| # Script by LeMagnesium (20/12/15) | ||||
| # @param : Branches to rebase from master | ||||
| # Must be ran from the root of the repo or a subdirectory | ||||
|  | ||||
| for branch in $( git branch ); do | ||||
| 	if [ branch != "master" ]; | ||||
| 	then | ||||
| 		git checkout $branch | ||||
| 		git pull origin $branch | ||||
| 		git rebase master | ||||
| 		git push -f origin $branch | ||||
| 	fi | ||||
| done | ||||
|  | ||||
| git checkout master | ||||
|  | ||||
| echo "Branches rebased." | ||||
|  | ||||
|  | ||||
| #EOF | ||||
| @@ -1,17 +0,0 @@ | ||||
| #!/bin/bash | ||||
| # Script to remove whitespaces from our repository's lua files | ||||
| # Script ßý LeMagnesium, 2015 | ||||
| # (Note: You need this : https://github.com/LeMagnesium/mucro ) | ||||
|  | ||||
| # Go to repo root | ||||
| mydir="`dirname "$0"`" | ||||
| test -d "$mydir" && cd "$mydir/../../../" | ||||
|  | ||||
| # Get all lua file's names | ||||
| luafiles=$(find -type f -name "*.lua") | ||||
| sed -i 's/[ \t]*$//' $luafiles | ||||
|  | ||||
| # Done | ||||
| echo "Done" | ||||
|  | ||||
| #EOF | ||||
| @@ -1,15 +0,0 @@ | ||||
| # Reversing script | ||||
|  | ||||
| cd ~/Programmation/Gits/Ombridride-minetest-minetestforfun-server-access/ | ||||
|  | ||||
| # Removed old files... While saving IRC mod | ||||
|  | ||||
| rm -rf ./mods/* | ||||
| rm -rf ./minetestforfun_game/* | ||||
|  | ||||
|  | ||||
| # Copy files | ||||
| cp -Rf ~/.minetest/worlds/NodesJustWannaHaveFun/worldmods/* ./mods/ | ||||
| cp -Rf ~/.minetest/games/minetestforfun_game/* ./minetestforfun_game/ | ||||
|  | ||||
| echo "Finished" | ||||
| @@ -1,34 +0,0 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| # Update MinetestForFun Sources | ||||
|  | ||||
| datecom=`date` | ||||
| echo "[$datecom] Updated MinetestForFun Sources by $USER" >> ~/.git_sh_history | ||||
|  | ||||
| cd ~/Programmation/ | ||||
| cd Gits/Ombridride-minetest-minetestforfun-server-access | ||||
|  | ||||
| # If argument is passed, then update the clone | ||||
| if [ ! -z $1 ] | ||||
| then | ||||
| 	echo "=> Getting lastest sources..." | ||||
| 	# Actualize MFF's clone | ||||
| 	git checkout master | ||||
| 	git pull origin master | ||||
| else | ||||
| 	echo "=> Skipping clone actualization" | ||||
| fi | ||||
|  | ||||
| echo "=> Copying files..." | ||||
| cd mods | ||||
| rm -rf ~/.minetest/worlds/NodesJustWannaHaveFun/worldmods/* | ||||
| cp -R ./* ~/.minetest/worlds/NodesJustWannaHaveFun/worldmods/ | ||||
|  | ||||
| cd .. | ||||
| rm -rf ~/.minetest/games/minetestforfun_game | ||||
| cp -r ./minetestforfun_game ~/.minetest/games | ||||
|  | ||||
| cp -f ./worlds/minetestforfun/news.txt ~/.minetest/worlds/NodesJustWannaHaveFun/ | ||||
|  | ||||
| echo "== Finished ==" | ||||
| sleep 2 | ||||
| @@ -1,28 +0,0 @@ | ||||
| #!/bin/bash | ||||
| # | ||||
| # Script created by LeMagnesium on 4/18/15 | ||||
| # This script should be launched from the root of the clone or deeper in it | ||||
| # It copies all the meshes from homdecor from the mmdb's copy I have to our | ||||
| # own version | ||||
| # @param : $1 or the fresh clone from the mmdb's path while $2 is the static | ||||
| # path to our version | ||||
|  | ||||
| if [ -z $1 ] | ||||
| then | ||||
| 	echo "Missing parameter : source" | ||||
| else | ||||
| 	if [ -z $2 ] | ||||
| 	then | ||||
| 		echo "Missing parameter : target" | ||||
| 	else | ||||
| 		cp $1/lavalamp/models/* $2/lavalamp/models/ | ||||
| 		cp $1/chains/models/* $2/chains/models/ | ||||
| 		cp $1/computer/models/* $2/computer/models/ | ||||
| 		cp $1/plasmascreen/models/* $2/plasmascreen/models/ | ||||
| 		cp $1/homedecor_3d_extras/models/* $2/homedecor_3d_extras/models/ | ||||
| 		cp $1/inbox/models/* $2/inbox/models/ | ||||
| 		cp $1/homedecor/models/* $2/homedecor/models/ | ||||
| 		cp $1/lrfurn/models/* $2/lrfurn/models/ | ||||
| 		echo "Done." | ||||
| 	fi | ||||
| fi | ||||
| @@ -1,76 +0,0 @@ | ||||
| #!/usr/bin/python2 | ||||
| # -*- coding: UTF-8 -*- | ||||
|  | ||||
| ## script to display diplicated textures in mods and subgame | ||||
| ## by Crabman | ||||
| ## ./find_duplicate_textures.py /path_to_/minetest-minetestforfun-server or ../../path_to_/minetest-minetestforfun-server or ../../ | ||||
|  | ||||
| import sys, os, glob | ||||
|  | ||||
| def format_center(string, lt): | ||||
| 	# "     string     " lt=string total | ||||
| 	return (('{:^%s}' % lt).format(string) ) | ||||
|  | ||||
| def format_left(string, lt): | ||||
| 	# "string     "   lt=string total | ||||
| 	return (('{:<%s}' % lt).format(string) ) | ||||
|  | ||||
| def format_right(string, lt): | ||||
| 	# "     string"   lt=string total | ||||
| 	return (('{:>%s}' % lt).format(string) ) | ||||
|  | ||||
|  | ||||
| class Textures: | ||||
| 	def __init__(self): | ||||
| 		self.textures_list = dict() | ||||
| 		self.duplicated = 0 | ||||
| 	 | ||||
| 	def get_duplicate_nb(self): | ||||
| 		return self.duplicated | ||||
| 	 | ||||
| 	def get_nb(self): | ||||
| 		return len(self.textures_list) | ||||
| 	 | ||||
| 	def set_textures(self, files): | ||||
| 		for texture in files: | ||||
| 			path, name = os.path.split(texture) | ||||
| 			if self.textures_list.has_key(name): | ||||
| 				if len(self.textures_list[name]) == 1: | ||||
| 					self.duplicated += 1 | ||||
| 				self.textures_list[name].append(path) | ||||
| 			else: | ||||
| 				self.textures_list[name] = [path] | ||||
| 	 | ||||
| 	def show_duplicate(self): | ||||
| 		for t, l in self.textures_list.iteritems(): | ||||
| 			nb = len(l) | ||||
| 			if nb > 1: | ||||
| 				print("%s: %s %s" % (nb, format_left(t, 40), l) ) | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
| 	if len(sys.argv) <=1: | ||||
| 		print("Missing arg path!") | ||||
| 		sys.exit(1) | ||||
| 	 | ||||
| 	if sys.argv[1].startswith("/"): | ||||
| 		dir_path = sys.argv[1] | ||||
| 	else: | ||||
| 		dir_path = os.path.join(os.getcwd(), sys.argv[1]) | ||||
| 	 | ||||
| 	try: | ||||
| 		os.chdir(dir_path) | ||||
| 	except Exception as err: | ||||
| 		print(err) | ||||
| 		sys.exit(1) | ||||
| 	 | ||||
| 	T = Textures() | ||||
| 	# find in subgame/mods and mods | ||||
| 	for f in ["*/mods", "mods"]: | ||||
| 		files = glob.glob( os.path.join(f,'*/textures/*.png') ) # find in mods | ||||
| 		T.set_textures(files) | ||||
| 		files = glob.glob( os.path.join(f,'*/*/textures/*.png') ) # find in modpack | ||||
| 		T.set_textures(files) | ||||
| 	print("%s textures total    %s duplicated\n" % ( T.get_nb(), T.get_duplicate_nb() ) ) | ||||
| 	T.show_duplicate() | ||||
|  | ||||
| @@ -1,99 +0,0 @@ | ||||
| #!/usr/bin/env python3 | ||||
| # -*- encoding: utf-8 -*- | ||||
| ########################## | ||||
| ## Skin Preview Generator | ||||
| ## ßÿ Mg / LeMagnesium | ||||
| ## License : WTFPL | ||||
| ## | ||||
|  | ||||
| import sys | ||||
| import os.path | ||||
|  | ||||
| from PIL import Image | ||||
|  | ||||
| for arg in sys.argv[1:]: | ||||
| 	try: | ||||
| 		open(arg) | ||||
| 	except Exception as err: | ||||
| 		print("Couldn't open {} : {}".format(os.path.basename(arg), err)) | ||||
| 		continue | ||||
|  | ||||
| 	im = Image.open(arg).convert("RGBA") | ||||
| 	print("Opened {}".format(os.path.basename(arg))) | ||||
|  | ||||
| 	s = im.size | ||||
| 	if not s[0] == s[1] * 2: | ||||
| 		print("Invalid size : {}".format(s)) | ||||
| 		continue | ||||
|  | ||||
| 	cw = int(s[0] / 8) | ||||
|  | ||||
| #	backp = Image.new("RGBA", (cw * 2, cw * 4)) | ||||
|  | ||||
| 	head = im.crop(box = (cw, cw, cw * 2, cw * 2)) | ||||
| 	chest = im.crop(box = ( | ||||
| 		cw * 2 + int(1/2.0 * cw), | ||||
| 		cw * 2 + int(1/2.0 * cw), | ||||
| 		cw * 3 + int(1/2.0 * cw), | ||||
| 		s[1], | ||||
| 	)) | ||||
| 	leftarm = im.crop(box = ( | ||||
| 		5 * cw + int(cw / 2), | ||||
| 		2 * cw + int(cw / 2), | ||||
| 		6 * cw, | ||||
| 		s[1] | ||||
| 	)) | ||||
| 	rightarm = im.crop(box = ( | ||||
| 		6 * cw, | ||||
| 		2 * cw + int(cw / 2), | ||||
| 		6 * cw + int(cw / 2), | ||||
| 		s[1] | ||||
| 	)) | ||||
| 	leftleg = im.crop(box = ( | ||||
| 		int(1/2 * cw), | ||||
| 		2 * cw + int(cw / 2), | ||||
| 		cw, | ||||
| 		s[1] | ||||
| 	)) | ||||
|  | ||||
| 	# Paste | ||||
| 	front = Image.new("RGBA", ( | ||||
| 		cw * 2, # + int(2/8.0 * cw), | ||||
| 		cw * 4 | ||||
| 	)) | ||||
| 	for y in range(front.size[0]): | ||||
| 		for x in range(front.size[1]): | ||||
| 			front.putpixel((y, x), (255, 255, 255, 0)) | ||||
|  | ||||
| 	front.paste(head, box = ( | ||||
| 		int(cw / 2), | ||||
| 		0, | ||||
| 	)) | ||||
|  | ||||
| 	front.paste(chest, box = ( | ||||
| 		int(cw / 2), | ||||
| 		cw | ||||
| 	)) | ||||
|  | ||||
| 	front.paste(leftarm, box = ( | ||||
| 		0, | ||||
| 		cw | ||||
| 	)) | ||||
|  | ||||
| 	front.paste(leftarm, box = ( | ||||
| 		int(1.5 * cw), | ||||
| 		cw | ||||
| 	)) | ||||
|  | ||||
| 	front.paste(leftleg, box = ( | ||||
| 		int(cw / 2), | ||||
| 		int(2.5 * cw) | ||||
| 	)) | ||||
|  | ||||
| 	front.paste(leftleg, box = ( | ||||
| 		cw, | ||||
| 		int(2.5 * cw) | ||||
| 	)) | ||||
|  | ||||
| 	exts = os.path.splitext(arg) | ||||
| 	front.save("{}_preview{}".format(exts[0], "".join(exts[1:]))) | ||||
| @@ -1,15 +0,0 @@ | ||||
| #!/bin/sh | ||||
| # | ||||
| # Script to chmod all files in the repository at 755 | ||||
| # Script ßý LeMagnesium | ||||
| # | ||||
|  | ||||
| # Go to repo root | ||||
| mydir="`dirname "$0"`" | ||||
| test -d "$mydir" && cd "$mydir/../../" | ||||
|  | ||||
| # CHMOD TIME! | ||||
| chmod -R 755 . | ||||
| echo "All files have been chmod-ed to mode 755." | ||||
|  | ||||
| #EOF | ||||
| @@ -1,8 +0,0 @@ | ||||
| #!/bin/sh  | ||||
| #rsync -e "ssh -i /root/.ssh/id_dsa" -av --delete-after /home/quentinbd/minetest/worlds/minetestforfun/news.txt root@192.168.1.20:/var/www/wordpress/wp-content/uploads/news/ | ||||
| # Check the public key rights | ||||
| chmod 600 /home/quentinbd/.ssh/id_rsa | ||||
| chmod 600 /home/quentinbd/.ssh/id_rsa.pub | ||||
| # Begin the RSYNC | ||||
| rsync -azrv --delete /home/quentinbd/mff/worlds/minetestforfun/news.txt quentinbd@192.168.1.20:/var/www/wordpress/wp-content/uploads/news/ | ||||
| echo "Transfert réussi de news.txt sur le wordpress" | ||||
| @@ -1,26 +0,0 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| DEBUG='/home/quentinbd/script/debug-mff-creative.txt' | ||||
| MOREDEBUG='/home/quentinbd/script/moredebug-mff-creative.txt' | ||||
|  | ||||
| cd /home/quentinbd/mff-creative | ||||
|  | ||||
| while true | ||||
| 	do | ||||
| 	sleep 5 | ||||
|  | ||||
| 	echo "----------------------" >>$MOREDEBUG | ||||
| 	echo "Server restarted at "`date` >>$MOREDEBUG | ||||
| 	echo "----------------------" >>$MOREDEBUG | ||||
|  | ||||
| 	echo "0" >/tmp/players_c.txt | ||||
|  | ||||
| 	/home/quentinbd/mff-creative/bin/minetestserver \ | ||||
| 		--world /home/quentinbd/mff-creative/worlds/minetestforfun-creative/ \ | ||||
| 		--config /home/quentinbd/mff-creative/minetest.conf \ | ||||
| 		--gameid minetestforfun_creative \ | ||||
| 		--port 30088 \ | ||||
| #		--logfile $DEBUG | ||||
|  | ||||
| 	sleep 25 | ||||
| done &>> $MOREDEBUG | ||||
| @@ -1,26 +0,0 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| DEBUG='/home/quentinbd/script/debug-mff-hg.txt' | ||||
| MOREDEBUG='/home/quentinbd/script/moredebug-mff-hg.txt' | ||||
|  | ||||
| cd /home/quentinbd/mff-hg | ||||
|  | ||||
| while true | ||||
| 	do | ||||
| 	sleep 5 | ||||
|  | ||||
| 	echo "----------------------" >>$MOREDEBUG | ||||
| 	echo "Server restarted at "`date` >>$MOREDEBUG | ||||
| 	echo "----------------------" >>$MOREDEBUG | ||||
|  | ||||
| 	echo "0" >/tmp/players_c.txt | ||||
|  | ||||
| 	/home/quentinbd/mff-hg/bin/minetestserver \ | ||||
| 		--world /home/quentinbd/mff-hg/worlds/minetestforfun-hg/ \ | ||||
| 		--config /home/quentinbd/mff-hg/minetest.conf \ | ||||
| 		--gameid minetestforfun_hg \ | ||||
| 		--port 30042 \ | ||||
| #		--logfile $DEBUG | ||||
|  | ||||
| 	sleep 25 | ||||
| done &>> $MOREDEBUG | ||||
| @@ -1,26 +0,0 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| DEBUG='/home/quentinbd/script/debug-mff-skyblock.txt' | ||||
| MOREDEBUG='/home/quentinbd/script/moredebug-mff-skyblock.txt' | ||||
|  | ||||
| cd /home/quentinbd/mff-skyblock | ||||
|  | ||||
| while true | ||||
| 	do | ||||
| 	sleep 5 | ||||
|  | ||||
| 	echo "----------------------" >>$MOREDEBUG | ||||
| 	echo "Server restarted at "`date` >>$MOREDEBUG | ||||
| 	echo "----------------------" >>$MOREDEBUG | ||||
|  | ||||
| 	echo "0" >/tmp/players_c.txt | ||||
|  | ||||
| 	/home/quentinbd/mff-skyblock/bin/minetestserver \ | ||||
| 		--world /home/quentinbd/mff-skyblock/worlds/minetestforfun-skyblock/ \ | ||||
| 		--config /home/quentinbd/mff-skyblock/minetest.conf \ | ||||
| 		--gameid minetestforfun_skyblock \ | ||||
| 		--port 30054 \ | ||||
| #		--logfile $DEBUG | ||||
|  | ||||
| 	sleep 25 | ||||
| done &>> $MOREDEBUG | ||||
| @@ -1,50 +0,0 @@ | ||||
| # on récupère la dernière version du jeu | ||||
| cd /home/quentinbd/ | ||||
| git clone https://github.com/MinetestForFun/server-minetestforfun-creative.git | ||||
| echo "Clone de server-minetestforfun-creative réussit." | ||||
| cd /home/quentinbd/server-minetestforfun-creative/ | ||||
| git submodule update --init --recursive | ||||
|  | ||||
| # On sauvegarde les anciens ../games et ../mods | ||||
| rm -R /home/quentinbd/upgrade-mff-creative/olds-part/games/ | ||||
| rm -R /home/quentinbd/upgrade-mff-creative/olds-part/mods/ | ||||
| echo "Ancienne sauvegarde de /mods et /games correctement supprimée." | ||||
|  | ||||
| cp -R /home/quentinbd/mff-creative/mods/ /home/quentinbd/upgrade-mff-creative/olds-part/ | ||||
| cp -R /home/quentinbd/mff-creative/games/ /home/quentinbd/upgrade-mff-creative/olds-part/ | ||||
| echo "Sauvegarde de /mods et /games correctement effectuée." | ||||
|  | ||||
| # On MAJ les nouveaux minetest/games et minetest/mods | ||||
| rm -R /home/quentinbd/mff-creative/mods/ | ||||
| rm -R /home/quentinbd/mff-creative/games/ | ||||
| mkdir -p /home/quentinbd/mff-creative/games/ | ||||
| cp -R /home/quentinbd/server-minetestforfun-creative/minetestforfun_game/ /home/quentinbd/mff-creative/games/ | ||||
| mv /home/quentinbd/mff-creative/games/minetestforfun_game/ /home/quentinbd/mff-creative/games/minetestforfun_creative/ | ||||
| mkdir -p /home/quentinbd/mff-creative/games/minetestforfun_creative/ | ||||
| mkdir -p /home/quentinbd/mff-creative/games/minetestforfun_creative/mods/ | ||||
| cp -R /home/quentinbd/server-minetestforfun-creative/mods/ /home/quentinbd/mff-creative/ | ||||
| echo "Nouveaux /mods et /games correctement déplacés" | ||||
|  | ||||
| # On MAJ le minetest.conf, game.conf, world.mt, random_messages, et le forbidden_names | ||||
| mkdir -p /home/quentinbd/mff-creative/worlds/minetestforfun-creative/ | ||||
| cp /home/quentinbd/server-minetestforfun-creative/minetestforfun_game/game.conf /home/quentinbd/mff-creative/games/minetestforfun_creative/ | ||||
| rm /home/quentinbd/mff-creative/minetest.conf | ||||
| rm /home/quentinbd/mff-creative/worlds/minetestforfun-creative/world.mt | ||||
| rm /home/quentinbd/mff-creative/worlds/minetestforfun-creative/random_messages | ||||
| # On les remet | ||||
| cp /home/quentinbd/server-minetestforfun-creative/minetest.conf /home/quentinbd/mff-creative/games/minetestforfun_creative/ | ||||
| cp /home/quentinbd/server-minetestforfun-creative/minetest.conf /home/quentinbd/mff-creative/ | ||||
| cp /home/quentinbd/server-minetestforfun-creative/minetestforfun_game/game.conf /home/quentinbd/mff-creative/games/minetestforfun_creative/ | ||||
| cp /home/quentinbd/server-minetestforfun-creative/worlds/minetestforfun-creative/world.mt /home/quentinbd/mff-creative/worlds/minetestforfun-creative/ | ||||
| cp /home/quentinbd/server-minetestforfun-creative/worlds/minetestforfun-creative/random_messages /home/quentinbd/mff-creative/worlds/minetestforfun-creative/ | ||||
| cp /home/quentinbd/server-minetestforfun-creative/worlds/minetestforfun-creative/forbidden_names.txt /home/quentinbd/mff-creative/worlds/minetestforfun-creative/ | ||||
| echo "Nouveau minetest.conf, game.conf, world.mt, random_messages, et le forbidden_names correctement déplacé" | ||||
|  | ||||
| # Suppression du dossier cloné | ||||
| rm -Rf /home/quentinbd/server-minetestforfun-creative/ | ||||
| echo "Bravo ! mff-creative/mods et mff-creative/games maintenant à jour" | ||||
|  | ||||
| # On ré-attribut les droits à quentinbd et en 755 | ||||
| chown -R quentinbd:quentinbd /home/quentinbd/mff-creative/ | ||||
| chmod -R 755 /home/quentinbd/mff-creative/ | ||||
| echo "ré-attribution des droits à quentinbd:quentinbd" | ||||
| @@ -1,44 +0,0 @@ | ||||
| # passer sur branche master ou stable github | ||||
| cd /home/quentinbd/mff-creative/ | ||||
|  | ||||
| # Suppression des anciens fichiers | ||||
| rm -Rv /home/quentinbd/upgrade-mff-creative/olds | ||||
| rm -Rv /home/quentinbd/upgrade-mff-creative/mff-creative.tar.gz | ||||
|  | ||||
| # Sauvegarde des fichiers critiques | ||||
| cp -Rv /home/quentinbd/mff-creative/games/minetestforfun_creative/ /home/quentinbd/upgrade-mff-creative/olds/ | ||||
| cp -Rv /home/quentinbd/mff-creative/mods/ /home/quentinbd/upgrade-mff-creative/olds/ | ||||
| cp -Rv /home/quentinbd/mff-creative/worlds/ /home/quentinbd/upgrade-mff-creative/olds/ | ||||
| cp /home/quentinbd/mff-creative/minetest.conf /home/quentinbd/upgrade-mff-creative/olds/ | ||||
|  | ||||
| # Sauvegarde et compression du dossier minetest (au cas ou) | ||||
| cd /home/quentinbd/upgrade-mff-creative/ | ||||
| tar -cf mff-creative.tar.gz /home/quentinbd/mff-creative/ | ||||
|  | ||||
| # Suppression de minetest | ||||
| rm -Rv /home/quentinbd/mff-creative/ | ||||
|  | ||||
| # Réinstallaton de minetest | ||||
| cd /home/quentinbd/ | ||||
| # DEBUT - Utilisation de la dernière version 0.4 stable | ||||
| wget https://codeload.github.com/minetest/minetest/zip/stable-0.4 | ||||
| unzip /home/quentinbd/stable-0.4 | ||||
| mv /home/quentinbd/minetest-stable-0.4/ /home/quentinbd/mff-creative/ | ||||
| rm -v /home/quentinbd/stable-0.4 | ||||
| # FIN - Utilisation de la version 0.4 stable | ||||
|  | ||||
| # Compilation | ||||
| cd /home/quentinbd/mff-creative/ | ||||
| # build SQLITE3 | ||||
| cmake . -DBUILD_CLIENT=0 -DBUILD_SERVER=1 -DRUN_IN_PLACE=1 -DENABLE_GETTEXT=1 -DENABLE_FREETYPE=1 -DENABLE_LUAJIT=1 -DCMAKE_INSTALL_PREFIX:PATH=/usr | ||||
| make -j$(grep -c processor /proc/cpuinfo) | ||||
|  | ||||
| # Ajout des fichiers critiques au nouveau dossier minetest | ||||
| cp -Rv /home/quentinbd/upgrade-mff-creative/olds/minetestforfun_creative/ /home/quentinbd/mff-creative/games/ | ||||
| cp -Rv /home/quentinbd/upgrade-mff-creative/olds/mods/ /home/quentinbd/mff-creative/ | ||||
| cp -Rv /home/quentinbd/upgrade-mff-creative/olds/worlds/ /home/quentinbd/mff-creative/ | ||||
| cp /home/quentinbd/upgrade-mff-creative/olds/minetest.conf /home/quentinbd/mff-creative/ | ||||
|  | ||||
| # Donne les droits à quentinbd | ||||
| chmod -R 755 /home/quentinbd/mff-creative/ | ||||
| chown -R quentinbd:quentinbd /home/quentinbd/mff-creative/ | ||||
| @@ -1,51 +0,0 @@ | ||||
| # on récupère la dernière version du jeu | ||||
| cd /home/quentinbd/ | ||||
| git clone https://github.com/MinetestForFun/server-minetestforfun-hungry_games.git | ||||
| echo "Clone de server-minetestforfun-hungry_games réussit." | ||||
| cd /home/quentinbd/server-minetestforfun-hungry_games/ | ||||
| git submodule update --init --recursive | ||||
|  | ||||
| # On sauvegarde les anciens ../games et ../mods | ||||
| rm -R /home/quentinbd/upgrade-mff-hg/olds-part/games/ | ||||
| rm -R /home/quentinbd/upgrade-mff-hg/olds-part/mods/ | ||||
| echo "Ancienne sauvegarde de /mods et /games correctement supprimée." | ||||
|  | ||||
| cp -R /home/quentinbd/mff-hg/mods/ /home/quentinbd/upgrade-mff-hg/olds-part/ | ||||
| cp -R /home/quentinbd/mff-hg/games/ /home/quentinbd/upgrade-mff-hg/olds-part/ | ||||
| echo "Sauvegarde de /mods et /games correctement effectuée." | ||||
|  | ||||
| # On MAJ les nouveaux minetest/games et minetest/mods | ||||
| rm -R /home/quentinbd/mff-hg/mods/ | ||||
| rm -R /home/quentinbd/mff-hg/games/ | ||||
| mkdir -p /home/quentinbd/mff-hg/games/ | ||||
| mkdir -p /home/quentinbd/server-minetestforfun-hungry_games/games | ||||
| mkdir -p /home/quentinbd/mff-hg/games/minetestforfun_hg/ | ||||
| mkdir -p /home/quentinbd/mff-hg/games/minetestforfun_hg/mods/ | ||||
| cp -R /home/quentinbd/server-minetestforfun-hungry_games/mods/ /home/quentinbd/mff-hg/games/minetestforfun_hg/ | ||||
| echo "Nouveaux /mods et /games correctement déplacés" | ||||
|  | ||||
| # On MAJ le minetest.conf, world.mt, random_messages, top_config.txt, et le forbidden_names | ||||
| mkdir -p /home/quentinbd/mff-hg/worlds/minetestforfun-hg/ | ||||
| rm /home/quentinbd/mff-hg/minetest.conf | ||||
| rm /home/quentinbd/mff-hg/worlds/minetestforfun-hg/world.mt | ||||
| rm /home/quentinbd/mff-hg/worlds/minetestforfun-hg/random_messages | ||||
| rm /home/quentinbd/mff-hg/worlds/minetestforfun-hg/top_config.txt | ||||
| rm /home/quentinbd/mff-hg/worlds/minetestforfun-hg/forbidden_names.txt | ||||
| # On les remet | ||||
| cp /home/quentinbd/server-minetestforfun-hungry_games/minetest.conf /home/quentinbd/mff-hg/games/minetestforfun_hg/ | ||||
| cp /home/quentinbd/server-minetestforfun-hungry_games/minetest.conf /home/quentinbd/mff-hg/ | ||||
| cp /home/quentinbd/server-minetestforfun-hungry_games/game.conf /home/quentinbd/mff-hg/games/minetestforfun_hg/ | ||||
| #cp /home/quentinbd/server-minetestforfun-hungry_games/worlds/minetestforfun-hg/world.mt /home/quentinbd/mff-hg/worlds/minetestforfun-hg/ | ||||
| cp /home/quentinbd/server-minetestforfun-hungry_games/worlds/minetestforfun-hg/random_messages /home/quentinbd/mff-hg/worlds/minetestforfun-hg/ | ||||
| cp /home/quentinbd/server-minetestforfun-hungry_games/worlds/minetestforfun-hg/top_config.txt /home/quentinbd/mff-hg/worlds/minetestforfun-hg/ | ||||
| cp /home/quentinbd/server-minetestforfun-hungry_games/worlds/minetestforfun-hg/forbidden_names.txt /home/quentinbd/mff-hg/worlds/minetestforfun-hg/ | ||||
| echo "Nouveau minetest.conf, world.mt, random_messages, top_config.txt, et le forbidden_names correctement déplacé" | ||||
|  | ||||
| # Suppression du dossier cloné | ||||
| rm -Rf /home/quentinbd/server-minetestforfun-hungry_games/ | ||||
| echo "Bravo ! mff-hg/mods et mff-hg/games maintenant à jour" | ||||
|  | ||||
| # On ré-attribut les droits à quentinbd et en 755 | ||||
| chown -R quentinbd:quentinbd /home/quentinbd/mff-hg/ | ||||
| chmod -R 755 /home/quentinbd/mff-hg/ | ||||
| echo "ré-attribution des droits à quentinbd:quentinbd" | ||||
| @@ -1,44 +0,0 @@ | ||||
| # passer sur branche master ou stable github | ||||
| cd /home/quentinbd/mff-hg/ | ||||
|  | ||||
| # Suppression des anciens fichiers | ||||
| rm -Rv /home/quentinbd/upgrade-mff-hg/olds | ||||
| rm -Rv /home/quentinbd/upgrade-mff-hg/mff-hg.tar.gz | ||||
|  | ||||
| # Sauvegarde des fichiers critiques | ||||
| cp -Rv /home/quentinbd/mff-hg/games/minetestforfun_hg/ /home/quentinbd/upgrade-mff-hg/olds/ | ||||
| cp -Rv /home/quentinbd/mff-hg/mods/ /home/quentinbd/upgrade-mff-hg/olds/ | ||||
| cp -Rv /home/quentinbd/mff-hg/worlds/ /home/quentinbd/upgrade-mff-hg/olds/ | ||||
| cp /home/quentinbd/mff-hg/minetest.conf /home/quentinbd/upgrade-mff-hg/olds/ | ||||
|  | ||||
| # Sauvegarde et compression du dossier minetest (au cas ou) | ||||
| cd /home/quentinbd/upgrade-mff-hg/ | ||||
| tar -cf mff-hg.tar.gz /home/quentinbd/mff-hg/ | ||||
|  | ||||
| # Suppression de minetest | ||||
| rm -Rv /home/quentinbd/mff-hg/ | ||||
|  | ||||
| # Réinstallaton de minetest | ||||
| cd /home/quentinbd/ | ||||
| # DEBUT - Utilisation de la dernière version 0.4 stable | ||||
| wget https://codeload.github.com/minetest/minetest/zip/stable-0.4 | ||||
| unzip /home/quentinbd/stable-0.4 | ||||
| mv /home/quentinbd/minetest-stable-0.4/ /home/quentinbd/mff-hg/ | ||||
| rm -v /home/quentinbd/stable-0.4 | ||||
| # FIN - Utilisation de la version 0.4 stable | ||||
|  | ||||
| # Compilation | ||||
| cd /home/quentinbd/mff-hg/ | ||||
| # build SQLITE3 | ||||
| cmake . -DBUILD_CLIENT=0 -DBUILD_SERVER=1 -DRUN_IN_PLACE=1 -DENABLE_GETTEXT=1 -DENABLE_FREETYPE=1 -DENABLE_LUAJIT=1 -DCMAKE_INSTALL_PREFIX:PATH=/usr | ||||
| make -j$(grep -c processor /proc/cpuinfo) | ||||
|  | ||||
| # Ajout des fichiers critiques au nouveau dossier minetest | ||||
| cp -Rv /home/quentinbd/upgrade-mff-hg/olds/minetestforfun_game/ /home/quentinbd/mff-hg/games/ | ||||
| cp -Rv /home/quentinbd/upgrade-mff-hg/olds/mods/ /home/quentinbd/mff-hg/ | ||||
| cp -Rv /home/quentinbd/upgrade-mff-hg/olds/worlds/ /home/quentinbd/mff-hg/ | ||||
| cp /home/quentinbd/upgrade-mff-hg/olds/minetest.conf /home/quentinbd/mff-hg/ | ||||
|  | ||||
| # Donne les droits à quentinbd | ||||
| chmod -R 755 /home/quentinbd/mff-hg/ | ||||
| chown -R quentinbd:quentinbd /home/quentinbd/mff-hg/ | ||||
| @@ -1,49 +0,0 @@ | ||||
| # on récupère la dernière version du jeu | ||||
| cd /home/quentinbd/ | ||||
| git clone https://github.com/MinetestForFun/server-minetestforfun-skyblock.git | ||||
| echo "Clone de server-minetestforfun-skyblock réussit." | ||||
| cd /home/quentinbd/server-minetestforfun-skyblock/ | ||||
| git submodule update --init --recursive | ||||
|  | ||||
| # On sauvegarde les anciens ../games et ../mods | ||||
| rm -R /home/quentinbd/upgrade-mff-skyblock/olds-part/games/ | ||||
| rm -R /home/quentinbd/upgrade-mff-skyblock/olds-part/mods/ | ||||
| echo "Ancienne sauvegarde de /mods et /games correctement supprimée." | ||||
|  | ||||
| cp -R /home/quentinbd/mff-skyblock/mods/ /home/quentinbd/upgrade-mff-skyblock/olds-part/ | ||||
| cp -R /home/quentinbd/mff-skyblock/games/ /home/quentinbd/upgrade-mff-skyblock/olds-part/ | ||||
| echo "Sauvegarde de /mods et /games correctement effectuée." | ||||
|  | ||||
| # On MAJ les nouveaux minetest/games et minetest/mods | ||||
| rm -R /home/quentinbd/mff-skyblock/mods/ | ||||
| rm -R /home/quentinbd/mff-skyblock/games/ | ||||
| mkdir -p /home/quentinbd/mff-skyblock/games/ | ||||
| mkdir -p /home/quentinbd/server-minetestforfun-skyblock/games | ||||
| mkdir -p /home/quentinbd/mff-skyblock/games/minetestforfun_skyblock/ | ||||
| mkdir -p /home/quentinbd/mff-skyblock/games/minetestforfun_skyblock/mods/ | ||||
| cp -R /home/quentinbd/server-minetestforfun-skyblock/mods/ /home/quentinbd/mff-skyblock/games/minetestforfun_skyblock/ | ||||
| echo "Nouveaux /mods et /games correctement déplacés" | ||||
|  | ||||
| # On MAJ le minetest.conf, world.mt, le random_messages et le forbidden_names | ||||
| mkdir -p /home/quentinbd/mff-skyblock/worlds/minetestforfun-skyblock/ | ||||
| rm /home/quentinbd/mff-skyblock/minetest.conf | ||||
| rm /home/quentinbd/mff-skyblock/worlds/minetestforfun-skyblock/world.mt | ||||
| rm /home/quentinbd/mff-skyblock/worlds/minetestforfun-skyblock/random_messages | ||||
| rm /home/quentinbd/mff-skyblock/worlds/minetestforfun-skyblock/forbidden_names.txt | ||||
| # On les remet | ||||
| cp /home/quentinbd/server-minetestforfun-skyblock/minetest.conf /home/quentinbd/mff-skyblock/games/minetestforfun_skyblock/ | ||||
| cp /home/quentinbd/server-minetestforfun-skyblock/minetest.conf /home/quentinbd/mff-skyblock/ | ||||
| cp /home/quentinbd/server-minetestforfun-skyblock/game.conf /home/quentinbd/mff-skyblock/games/minetestforfun_skyblock/ | ||||
| #cp /home/quentinbd/server-minetestforfun-skyblock/worlds/minetestforfun-skyblock/world.mt /home/quentinbd/mff-skyblock/worlds/minetestforfun-skyblock/ | ||||
| cp /home/quentinbd/server-minetestforfun-skyblock/worlds/minetestforfun-skyblock/random_messages /home/quentinbd/mff-skyblock/worlds/minetestforfun-skyblock/ | ||||
| cp /home/quentinbd/server-minetestforfun-skyblock/worlds/minetestforfun-skyblock/forbidden_names.txt /home/quentinbd/mff-skyblock/worlds/minetestforfun-skyblock/ | ||||
| echo "Nouveau minetest.conf, world.mt, le random_messages et le forbidden_names correctement déplacé" | ||||
|  | ||||
| # Suppression du dossier cloné | ||||
| rm -Rf /home/quentinbd/server-minetestforfun-skyblock/ | ||||
| echo "Bravo ! mff-skyblock/mods et mff-skyblock/games maintenant à jour" | ||||
|  | ||||
| # On ré-attribut les droits à quentinbd et en 755 | ||||
| chown -R quentinbd:quentinbd /home/quentinbd/mff-skyblock/ | ||||
| chmod -R 755 /home/quentinbd/mff-skyblock/ | ||||
| echo "ré-attribution des droits à quentinbd:quentinbd" | ||||
| @@ -1,45 +0,0 @@ | ||||
| # passer sur branche master ou stable github | ||||
| cd /home/quentinbd/mff-skyblock/ | ||||
|  | ||||
| # Suppression des anciens fichiers | ||||
| rm -Rv /home/quentinbd/upgrade-mff-skyblock/olds | ||||
| rm -Rv /home/quentinbd/upgrade-mff-skyblock/mff-skyblock.tar.gz | ||||
|  | ||||
| # Sauvegarde des fichiers critiques | ||||
| mkdir /home/quentinbd/mff-skyblock/games/minetestforfun_skyblock/ | ||||
| cp -Rv /home/quentinbd/mff-skyblock/games/minetestforfun_skyblock/ /home/quentinbd/upgrade-mff-skyblock/olds/ | ||||
| cp -Rv /home/quentinbd/mff-skyblock/mods/ /home/quentinbd/upgrade-mff-skyblock/olds/ | ||||
| cp -Rv /home/quentinbd/mff-skyblock/worlds/ /home/quentinbd/upgrade-mff-skyblock/olds/ | ||||
| cp /home/quentinbd/mff-skyblock/minetest.conf /home/quentinbd/upgrade-mff-skyblock/olds/ | ||||
|  | ||||
| # Sauvegarde et compression du dossier minetest (au cas ou) | ||||
| cd /home/quentinbd/upgrade-mff-skyblock/ | ||||
| tar -cf mff-skyblock.tar.gz /home/quentinbd/mff-skyblock/ | ||||
|  | ||||
| # Suppression de minetest | ||||
| rm -Rv /home/quentinbd/mff-skyblock/ | ||||
|  | ||||
| # Réinstallaton de minetest | ||||
| cd /home/quentinbd/ | ||||
| # DEBUT - Utilisation de la dernière version 0.4 stable | ||||
| wget https://codeload.github.com/minetest/minetest/zip/stable-0.4 | ||||
| unzip /home/quentinbd/stable-0.4 | ||||
| mv /home/quentinbd/minetest-stable-0.4/ /home/quentinbd/mff-skyblock/ | ||||
| rm -v /home/quentinbd/stable-0.4 | ||||
| # FIN - Utilisation de la version 0.4 stable | ||||
|  | ||||
| # Compilation | ||||
| cd /home/quentinbd/mff-skyblock/ | ||||
| # build SQLITE3 | ||||
| cmake . -DBUILD_CLIENT=0 -DBUILD_SERVER=1 -DRUN_IN_PLACE=1 -DENABLE_GETTEXT=1 -DENABLE_FREETYPE=1 -DENABLE_LUAJIT=1 -DCMAKE_INSTALL_PREFIX:PATH=/usr | ||||
| make -j$(grep -c processor /proc/cpuinfo) | ||||
|  | ||||
| # Ajout des fichiers critiques au nouveau dossier minetest | ||||
| cp -Rv /home/quentinbd/upgrade-mff-skyblock/olds/minetestforfun_skyblock/ /home/quentinbd/mff-skyblock/games/ | ||||
| cp -Rv /home/quentinbd/upgrade-mff-skyblock/olds/mods/ /home/quentinbd/mff-skyblock/ | ||||
| cp -Rv /home/quentinbd/upgrade-mff-skyblock/olds/worlds/ /home/quentinbd/mff-skyblock/ | ||||
| cp /home/quentinbd/upgrade-mff-skyblock/olds/minetest.conf /home/quentinbd/mff-skyblock/ | ||||
|  | ||||
| # Donne les droits à quentinbd | ||||
| chmod -R 755 /home/quentinbd/mff-skyblock/ | ||||
| chown -R quentinbd:quentinbd /home/quentinbd/mff-skyblock/ | ||||
| @@ -1,120 +0,0 @@ | ||||
| <?xml version="1.0" standalone="no" ?> | ||||
| <!DOCTYPE project PUBLIC "-//audacityproject-1.3.0//DTD//EN" "http://audacity.sourceforge.net/xml/audacityproject-1.3.0.dtd" > | ||||
| <project xmlns="http://audacity.sourceforge.net/xml/" projname="fnpc_data" version="1.3.0" audacityversion="2.0.5" sel0="901.5675516831" sel1="901.5675516831" vpos="496" h="0.0000000000" zoom="119.7484695952" rate="44100.0"> | ||||
| 	<tags/> | ||||
| 	<wavetrack name="mobs_fnpc_damage_1" channel="2" linked="0" mute="0" solo="0" height="150" minimized="0" isSelected="0" rate="44100" gain="1.0" pan="0.0"> | ||||
| 		<waveclip offset="0.00000000"> | ||||
| 			<sequence maxsamples="262144" sampleformat="262159" numsamples="17943"> | ||||
| 				<waveblock start="0"> | ||||
| 					<simpleblockfile filename="e0001c16.au" len="17943" min="-0.249695" max="0.27417" rms="0.027438"/> | ||||
| 				</waveblock> | ||||
| 			</sequence> | ||||
| 			<envelope numpoints="0"/> | ||||
| 		</waveclip> | ||||
| 	</wavetrack> | ||||
| 	<wavetrack name="mobs_fnpc_damage_2" channel="2" linked="0" mute="0" solo="0" height="150" minimized="0" isSelected="0" rate="44100" gain="1.0" pan="0.0"> | ||||
| 		<waveclip offset="1.10623583"> | ||||
| 			<sequence maxsamples="262144" sampleformat="262159" numsamples="5309"> | ||||
| 				<waveblock start="0"> | ||||
| 					<simpleblockfile filename="e0001e35.au" len="5309" min="-0.233795" max="0.218597" rms="0.01566"/> | ||||
| 				</waveblock> | ||||
| 			</sequence> | ||||
| 			<envelope numpoints="0"/> | ||||
| 		</waveclip> | ||||
| 	</wavetrack> | ||||
| 	<wavetrack name="mobs_fnpc_damage_3" channel="2" linked="0" mute="0" solo="0" height="150" minimized="0" isSelected="0" rate="44100" gain="1.0" pan="0.0"> | ||||
| 		<waveclip offset="2.23535147"> | ||||
| 			<sequence maxsamples="262144" sampleformat="262159" numsamples="25269"> | ||||
| 				<waveblock start="0"> | ||||
| 					<simpleblockfile filename="e000107c.au" len="25269" min="-0.562341" max="0.562324" rms="0.161678"/> | ||||
| 				</waveblock> | ||||
| 			</sequence> | ||||
| 			<envelope numpoints="0"/> | ||||
| 		</waveclip> | ||||
| 	</wavetrack> | ||||
| 	<wavetrack name="mobs_fnpc_damage_4" channel="2" linked="0" mute="0" solo="0" height="150" minimized="0" isSelected="0" rate="44100" gain="1.0" pan="0.0"> | ||||
| 		<waveclip offset="3.79902494"> | ||||
| 			<sequence maxsamples="262144" sampleformat="262159" numsamples="47140"> | ||||
| 				<waveblock start="0"> | ||||
| 					<simpleblockfile filename="e0001e8b.au" len="47140" min="-1.0" max="0.999969" rms="0.203017"/> | ||||
| 				</waveblock> | ||||
| 			</sequence> | ||||
| 			<envelope numpoints="0"/> | ||||
| 		</waveclip> | ||||
| 	</wavetrack> | ||||
| 	<wavetrack name="mobs_fnpc_random_1" channel="2" linked="0" mute="0" solo="0" height="150" minimized="0" isSelected="1" rate="44100" gain="1.0" pan="0.0"> | ||||
| 		<waveclip offset="5.39761905"> | ||||
| 			<sequence maxsamples="262144" sampleformat="262159" numsamples="51492"> | ||||
| 				<waveblock start="0"> | ||||
| 					<simpleblockfile filename="e00010bc.au" len="16987" min="-0.481633" max="0.419265" rms="0.03306"/> | ||||
| 				</waveblock> | ||||
| 				<waveblock start="16987"> | ||||
| 					<simpleblockfile filename="e00011a6.au" len="34505" min="-0.630957" max="0.630938" rms="0.116615"/> | ||||
| 				</waveblock> | ||||
| 			</sequence> | ||||
| 			<envelope numpoints="0"/> | ||||
| 		</waveclip> | ||||
| 	</wavetrack> | ||||
| 	<wavetrack name="mobs_fnpc_death" channel="2" linked="0" mute="0" solo="0" height="150" minimized="0" isSelected="0" rate="44100" gain="1.0" pan="0.0"> | ||||
| 		<waveclip offset="7.57882086"> | ||||
| 			<sequence maxsamples="262144" sampleformat="262159" numsamples="43610"> | ||||
| 				<waveblock start="0"> | ||||
| 					<simpleblockfile filename="e000183c.au" len="43610" min="-0.265104" max="0.319614" rms="0.07648"/> | ||||
| 				</waveblock> | ||||
| 			</sequence> | ||||
| 			<envelope numpoints="1"> | ||||
| 				<controlpoint t="0.988866213152" val="1.000000000000"/> | ||||
| 			</envelope> | ||||
| 		</waveclip> | ||||
| 	</wavetrack> | ||||
| 	<wavetrack name="mobs_fnpc_random_2" channel="2" linked="0" mute="0" solo="0" height="150" minimized="0" isSelected="0" rate="44100" gain="1.0" pan="0.0"> | ||||
| 		<waveclip offset="10.69594105"> | ||||
| 			<sequence maxsamples="262144" sampleformat="262159" numsamples="43318"> | ||||
| 				<waveblock start="0"> | ||||
| 					<simpleblockfile filename="e00013bf.au" len="43318" min="-1.0" max="0.999969" rms="0.208513"/> | ||||
| 				</waveblock> | ||||
| 			</sequence> | ||||
| 			<envelope numpoints="0"/> | ||||
| 		</waveclip> | ||||
| 	</wavetrack> | ||||
| 	<wavetrack name="mobs_fnpc_random_3" channel="2" linked="0" mute="0" solo="0" height="150" minimized="0" isSelected="0" rate="44100" gain="1.0" pan="0.0"> | ||||
| 		<waveclip offset="12.46124717"> | ||||
| 			<sequence maxsamples="262144" sampleformat="262159" numsamples="71984"> | ||||
| 				<waveblock start="0"> | ||||
| 					<simpleblockfile filename="e00013d5.au" len="71984" min="-0.553684" max="0.564332" rms="0.0919"/> | ||||
| 				</waveblock> | ||||
| 			</sequence> | ||||
| 			<envelope numpoints="0"/> | ||||
| 		</waveclip> | ||||
| 	</wavetrack> | ||||
| 	<wavetrack name="mobs_fnpc_random_4" channel="2" linked="0" mute="0" solo="0" height="150" minimized="0" isSelected="0" rate="44100" gain="1.0" pan="0.0"> | ||||
| 		<waveclip offset="14.62798186"> | ||||
| 			<sequence maxsamples="262144" sampleformat="262159" numsamples="57705"> | ||||
| 				<waveblock start="0"> | ||||
| 					<simpleblockfile filename="e000194c.au" len="57705" min="-0.231262" max="0.193756" rms="0.066454"/> | ||||
| 				</waveblock> | ||||
| 			</sequence> | ||||
| 			<envelope numpoints="0"/> | ||||
| 		</waveclip> | ||||
| 	</wavetrack> | ||||
| 	<wavetrack name="mobs_fnpc_annoyed" channel="2" linked="0" mute="0" solo="0" height="150" minimized="0" isSelected="0" rate="44100" gain="1.0" pan="0.0"> | ||||
| 		<waveclip offset="16.54319728"> | ||||
| 			<sequence maxsamples="262144" sampleformat="262159" numsamples="44327"> | ||||
| 				<waveblock start="0"> | ||||
| 					<simpleblockfile filename="e00010db.au" len="44327" min="-0.939636" max="0.942261" rms="0.142908"/> | ||||
| 				</waveblock> | ||||
| 			</sequence> | ||||
| 			<envelope numpoints="0"/> | ||||
| 		</waveclip> | ||||
| 	</wavetrack> | ||||
| 	<wavetrack name="mobs_fnpc_useless" channel="2" linked="0" mute="0" solo="0" height="150" minimized="0" isSelected="0" rate="44100" gain="1.0" pan="0.0"> | ||||
| 		<waveclip offset="18.16464853"> | ||||
| 			<sequence maxsamples="262144" sampleformat="262159" numsamples="80582"> | ||||
| 				<waveblock start="0"> | ||||
| 					<simpleblockfile filename="e000191a.au" len="80582" min="-0.820923" max="0.774841" rms="0.059793"/> | ||||
| 				</waveblock> | ||||
| 			</sequence> | ||||
| 			<envelope numpoints="0"/> | ||||
| 		</waveclip> | ||||
| 	</wavetrack> | ||||
| </project> | ||||