Initial Commit.

This commit is contained in:
A.C.M 2020-04-11 03:15:26 +02:00
parent c94cbce638
commit b97c845657
18 changed files with 1325 additions and 1 deletions

17
.luacheckrc Normal file
View File

@ -0,0 +1,17 @@
unused_args = false
allow_defined_top = true
globals = {
"minetest",
}
read_globals = {
string = {fields = {"split"}},
table = {fields = {"copy", "getn"}},
-- Builtin
"vector", "ItemStack",
"dump", "DIR_DELIM", "VoxelArea", "Settings",
-- MTG
}

View File

@ -1,2 +1,21 @@
# smart_chat
# Smart Chat
A simple chat, which supports chat-channels for minetest.
## Description
Adds the ability to the plain chat, that user can join to channels.
The mod is easy extendable, because you only have to develop a module and
the chat has new commands.
There is a self-growing Helpsystem integrated too.
## Requirements:
Minetest 5.x
## Depends
## optional Depends
## License:
GPL 3.0
## Download
https://github.com/acmgit/smart_chat

52
cmd_all.lua Normal file
View File

@ -0,0 +1,52 @@
local sc = smart_chat
local S = sc.S
sc.register_help({
Name = "all",
Usage = "/c all <message>",
Description = S("Send's a message on all."),
Parameter = "<message>",
Shortcut = "/c a <message>",
}
)
sc["all"] = function(player, parameter)
local pprivs = minetest.get_player_privs(player)
if not pprivs.basic_privs then
minetest.chat_send_player(player,sc.red .. S("Error - require 'basic_privs' privilege."))
return
end
if(parameter[2] == nil or parameter[2] == "") then
sc.print(player, sc.red .. S("Error: No Message given."))
return
end
local message = ""
for i = 2, #parameter, 1 do
message = message .. " " .. parameter[i]
end
local channel = sc.player[player]
if(sc.player[player] ~= nil) then
minetest.chat_send_all(sc.yellow .. "[" .. sc.yellow .. player .. "@" .. channel
.. sc.yellow .. "] " .. sc.green .. message)
else
minetest.chat_send_all(sc.yellow .. "[" .. sc.yellow .. player
.. sc.yellow .. "] " .. sc.green .. message)
end
end -- sc["all"
sc["a"] = function(player, parameter)
sc["all"](player, parameter)
end -- sc["a"

40
cmd_channels.lua Normal file
View File

@ -0,0 +1,40 @@
local sc = smart_chat
local S = sc.S
sc.register_help({
Name = "channels",
Usage = "/c channels",
Description = S("Lists all channels on the Server."),
Parameter = "<>",
Shortcut = "/c c"
}
)
sc["channels"] = function(player)
local list = {}
local all_player = minetest.get_connected_players()
sc.print(player, sc.green .. S("Channels on Server:"))
for _,players in pairs(all_player) do
local pname = players:get_player_name()
if(sc.player[pname] ~= nil) then
list[sc.player[pname]] = sc.player[pname]
end -- if(sc.player[pname] ~= nil
end -- for_,players
for _,entry in pairs(list) do
sc.print(player, sc.orange .. entry)
end
end -- sc["list"
sc["c"] = function(player, parameter)
sc["channels"](player, parameter)
end -- sc["l"

61
cmd_help.lua Normal file
View File

@ -0,0 +1,61 @@
local lib = smart_chat
local S = lib.S
lib.register_help({
Name = "help",
Usage = "/c help <> | <command>",
Description = S("Helpsystem for ") .." " .. lib.modname .. ".",
Parameter = "<> | " .. S("<command>") .. lib.green .. "." ..
"\n" .. lib.orange .. "<>" ..
lib.green.. " - " .. S("Shows you the entire help for ") .. lib.modname ..
"." .. "\n" .. lib.orange .. S("<command>") ..
lib.green .. " - " .. S("Shows you the help for ") ..
lib.modname .. "-" .. S("command") .. ".",
Shortcut = "/c h <> | <command>",
}
)
lib["help"] = function(player, parameter)
if(parameter[2] == "" or parameter[2] == nil) then
lib.print(player, lib.green .. S("Commands for ") .. lib.modname .. " " .. lib.orange ..
lib.version .. "." .. lib.revision .. lib.green .. ".")
for _,value in pairs(lib.helpsystem) do
lib.print(player, lib.yellow .. "---------------")
lib.print(player, lib.green .. S("Name: ") .. lib.orange .. value.Name)
lib.print(player, lib.green .. S("Description: ") .. lib.yellow .. value.Description)
lib.print(player, lib.green .. S("Usage: ") .. lib.orange .. value.Usage)
lib.print(player, lib.green .. S("Parameter: ") .. lib.orange .. value.Parameter)
lib.print(player, lib.green .. S("Shortcut: ") .. lib.orange .. value.Shortcut)
end -- for _,value
lib.print(player, lib.yellow .. "---------------")
else
if(lib.helpsystem[parameter[2]] ~= nil) then
lib.print(player, lib.green .. S("Name: ") .. lib.orange ..
lib.helpsystem[parameter[2]].Name)
lib.print(player, lib.green .. S("Description: ") .. lib.yellow ..
lib.helpsystem[parameter[2]].Description)
lib.print(player, lib.green .. S("Usage: ") .. lib.orange ..
lib.helpsystem[parameter[2]].Usage)
lib.print(player, lib.green .. S("Parameter: ") .. lib.orange ..
lib.helpsystem[parameter[2]].Parameter)
lib.print(player, lib.green .. S("Shortcut: ") .. lib.orange ..
lib.helpsystem[parameter[2]].Parameter)
else
lib.print(player, lib.red .. S("No entry in help for command") .. " <" ..
lib.orange .. parameter[2] .. lib.red .. "> " .. S("found" .. "."))
end -- if(lib.help[parameter[2
end -- if(parameter[2]
end -- function help
lib["h"] = function(player, parameter)
lib["help"](player, parameter)
end -- lib["h"

46
cmd_invite.lua Normal file
View File

@ -0,0 +1,46 @@
local sc = smart_chat
local S = sc.S
sc.register_help({
Name = "invite",
Usage = "/c invite <player>",
Description = S("Invites a <player> to your Channel."),
Parameter = "<player>",
Shortcut = "/c i <player>",
}
)
sc["invite"] = function(player, parameter)
if(parameter[2] == nil or parameter[2] == "") then
sc.print(player, sc.red .. S("Error: No playername given."))
return
end
local guest = parameter[2]
local channel = sc.player[player]
if(channel == nil) then
sc.print(player, sc.red .. S("Error: You can not invite a player in the public chat."))
return
end
if(minetest.get_player_by_name(guest)) then
minetest.chat_send_player(guest, sc.yellow .. "[" .. sc.yellow .. player .. "@" .. channel .. sc.yellow .. "] "
.. sc.green .. S("Invites you in the channel: ") .. sc.orange .. channel .. ". "
.. sc.green .. S("Enter /c j ") .. sc.green .. channel .. S(" to join the Channel.")
)
sc.report(player,sc.green .. player .. " invites " .. sc.orange .. guest .. sc.green .. " to join the Channel.")
else
sc.print(player, sc.red .. S("Error: No Player with the name found."))
end
end -- sc["invite"
sc["i"] = function(player, parameter)
sc["invite"](player, parameter)
end -- sc["i"

30
cmd_join.lua Normal file
View File

@ -0,0 +1,30 @@
local sc = smart_chat
local S = sc.S
sc.register_help({
Name = "join",
Usage = "/c join <channel>",
Description = S("Join or change a channel to <channel>."),
Parameter = "<channel>",
Shortcut = "/c j <channel>",
}
)
sc["join"] = function(player, parameter)
if(parameter[2] == nil or parameter[2] == "") then
sc.print(player, sc.red .. S("Error: No channel to join given."))
return
end
sc.report(player, S("Leaves the Channel."))
sc.player[player] = parameter[2]
sc.report(player, S("Enter the Channel."))
end -- sc["join"
sc["j"] = function(player, parameter)
sc["join"](player, parameter)
end -- sc["j"

29
cmd_leave.lua Normal file
View File

@ -0,0 +1,29 @@
local sc = smart_chat
local S = sc.S
sc.register_help({
Name = "leave",
Usage = "/c leave",
Description = S("Leaves a channel"),
Parameter = "",
Shortcut = "/c l",
}
)
sc["leave"] = function(player)
if(sc.player[player] ~= nil) then
sc.report(player, S("Leaves the Channel."))
sc.player[player] = nil
sc.report(player, S("Enter the public Chat."))
else
sc.print(player, sc.red .. S("Error: You're already in the public chat."))
end -- if(sc.player[player]
end -- sc["leave"
sc["l"] = function(player, parameter)
sc["leave"](player, parameter)
end -- sc["l"

52
cmd_list.lua Normal file
View File

@ -0,0 +1,52 @@
local sc = smart_chat
local S = sc.S
sc.register_help({
Name = "list",
Usage = "/c list <name>",
Description = S("Lists all player in the channel."),
Parameter = "<>",
Shortcut = "/c li <name>",
}
)
sc["list"] = function(player, parameter)
local channel = sc.player[player]
local all_player = minetest.get_connected_players()
if(parameter[2] == "" or parameter[2] == nil) then
sc.print(player, sc.green .. "Player in Channel:")
for _,players in pairs(all_player) do
local pname = players:get_player_name()
if(sc.check_channel(pname, channel)) then
sc.print(player, sc.orange .. pname)
end -- if(sc.check_channel
end -- for_,players
else
local channelname = parameter[2]
sc.print(player, sc.green .. S("Player in Channel") .. " [" .. sc.orange .. channelname .. sc.green .. "]:")
for _,players in pairs(all_player) do
local pname = players:get_player_name()
if(sc.check_channel(pname, channelname)) then
sc.print(player, sc.orange .. pname)
end -- if(sc.check_channel
end -- for _,players
end -- if(paramter[2]
end -- sc["list"
sc["li"] = function(player, parameter)
sc["list"](player, parameter)
end -- sc["l"

34
cmd_toggle.lua Normal file
View File

@ -0,0 +1,34 @@
local sc = smart_chat
local S = sc.S
sc.register_help({
Name = "toggle",
Usage = "/c toggle",
Description = S("Turn's the permanent public Chat on or off."),
Parameter = "<>",
Shortcut = "/c t",
}
)
sc["toggle"] = function(player)
local status = sc.public[player]
if(status == nil) then
sc.public[player] = player
minetest.chat_send_player(player, sc.green .. S("The permanent public chat is now on."))
else
sc.public[player] = nil
minetest.chat_send_player(player, sc.orange .. S("The permanent public chat is now off."))
end
end -- sc["toggle"
sc["t"] = function(player, parameter)
sc["toggle"](player, parameter)
end -- sc["t"

50
cmd_where.lua Normal file
View File

@ -0,0 +1,50 @@
local sc = smart_chat
local S = sc.S
sc.register_help({
Name = "where",
Usage = "/c where <name>",
Description = S("Show's the room, where <name> is."),
Parameter = "<>",
Shortcut = "/c w <name>",
}
)
sc["where"] = function(player, parameter)
if(parameter[2] == "" or parameter[2] == nil) then
sc.print(sc.red .. S("Error: No name given."))
else
local pname = parameter[2]
local channel = sc.player[pname]
if(minetest.get_player_by_name(pname)) then
local room = sc.player[pname]
if(room ~= nil) then
sc.print(player, sc.green .. S("Player [") .. sc.orange .. pname
.. sc.green .. S(" is in Channel {")
.. sc.yellow .. channel .. sc.green .. "}.")
else
sc.print(player, sc.green .. S("Player [") .. sc.orange .. pname
.. sc.green .. S("] is in the public Chat."))
end -- if(room ~= nil)
else -- if(minetest.get_player_by_name
sc.print(player, sc.red .. S("Error: Player is not online."))
end -- if(minetest.get_player_by_name
end -- if(paramter[2]
end -- sc["where"
sc["w"] = function(player, parameter)
sc["where"](player, parameter)
end -- sc["w"

33
core.lua Normal file
View File

@ -0,0 +1,33 @@
local sc = smart_chat
minetest.register_on_chat_message(function(player, message)
if(player ~= "" or player ~= nil) then
--local playername = minetest.get_player_by_name(player)
return sc.chat(player, message)
else
return false -- Systemmessage, no processing for us.
end
end) -- register_on_chatmessage()
minetest.register_on_joinplayer(function(player)
local playername = player:get_player_name()
sc.player[playername] = nil -- the public Chat
sc.public[playername] = nil
end) -- register_on_joinplayer()
minetest.register_on_leaveplayer(function(player)
local playername = player:get_player_name()
sc.player[playername] = nil
sc.public[playername] = nil
end)

426
i18n.py Executable file
View File

@ -0,0 +1,426 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Script to generate the template file and update the translation files.
# Copy the script into the mod or modpack root folder and run it there.
#
# Copyright (C) 2019 Joachim Stolberg, 2020 FaceDeer, 2020 Louis Royer
# LGPLv2.1+
#
# See https://github.com/minetest-tools/update_translations for
# potential future updates to this script.
from __future__ import print_function
import os, fnmatch, re, shutil, errno
from sys import argv as _argv
# Running params
params = {"recursive": False,
"help": False,
"mods": False,
"verbose": False,
"folders": [],
"no-old-file": False
}
# Available CLI options
options = {"recursive": ['--recursive', '-r'],
"help": ['--help', '-h'],
"mods": ['--installed-mods'],
"verbose": ['--verbose', '-v'],
"no-old-file": ['--no-old-file']
}
# Strings longer than this will have extra space added between
# them in the translation files to make it easier to distinguish their
# beginnings and endings at a glance
doublespace_threshold = 60
def set_params_folders(tab: list):
'''Initialize params["folders"] from CLI arguments.'''
# Discarding argument 0 (tool name)
for param in tab[1:]:
stop_param = False
for option in options:
if param in options[option]:
stop_param = True
break
if not stop_param:
params["folders"].append(os.path.abspath(param))
def set_params(tab: list):
'''Initialize params from CLI arguments.'''
for option in options:
for option_name in options[option]:
if option_name in tab:
params[option] = True
break
def print_help(name):
'''Prints some help message.'''
print(f'''SYNOPSIS
{name} [OPTIONS] [PATHS...]
DESCRIPTION
{', '.join(options["help"])}
prints this help message
{', '.join(options["recursive"])}
run on all subfolders of paths given
{', '.join(options["mods"])}
run on locally installed modules
{', '.join(options["no-old-file"])}
do not create *.old files
{', '.join(options["verbose"])}
add output information
''')
def main():
'''Main function'''
set_params(_argv)
set_params_folders(_argv)
if params["help"]:
print_help(_argv[0])
elif params["recursive"] and params["mods"]:
print("Option --installed-mods is incompatible with --recursive")
else:
# Add recursivity message
print("Running ", end='')
if params["recursive"]:
print("recursively ", end='')
# Running
if params["mods"]:
print(f"on all locally installed modules in {os.path.abspath('~/.minetest/mods/')}")
run_all_subfolders("~/.minetest/mods")
elif len(params["folders"]) >= 2:
print("on folder list:", params["folders"])
for f in params["folders"]:
if params["recursive"]:
run_all_subfolders(f)
else:
update_folder(f)
elif len(params["folders"]) == 1:
print("on folder", params["folders"][0])
if params["recursive"]:
run_all_subfolders(params["folders"][0])
else:
update_folder(params["folders"][0])
else:
print("on folder", os.path.abspath("./"))
if params["recursive"]:
run_all_subfolders(os.path.abspath("./"))
else:
update_folder(os.path.abspath("./"))
#group 2 will be the string, groups 1 and 3 will be the delimiters (" or ')
#See https://stackoverflow.com/questions/46967465/regex-match-text-in-either-single-or-double-quote
pattern_lua = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*(["\'])((?:\\\1|(?:(?!\1)).)*)(\1)[\s,\)]', re.DOTALL)
pattern_lua_bracketed = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*\[\[(.*?)\]\][\s,\)]', re.DOTALL)
# Handles "concatenation" .. " of strings"
pattern_concat = re.compile(r'["\'][\s]*\.\.[\s]*["\']', re.DOTALL)
pattern_tr = re.compile(r'(.+?[^@])=(.*)')
pattern_name = re.compile(r'^name[ ]*=[ ]*([^ \n]*)')
pattern_tr_filename = re.compile(r'\.tr$')
pattern_po_language_code = re.compile(r'(.*)\.po$')
#attempt to read the mod's name from the mod.conf file. Returns None on failure
def get_modname(folder):
try:
with open(os.path.join(folder, "mod.conf"), "r", encoding='utf-8') as mod_conf:
for line in mod_conf:
match = pattern_name.match(line)
if match:
return match.group(1)
except FileNotFoundError:
pass
return None
#If there are already .tr files in /locale, returns a list of their names
def get_existing_tr_files(folder):
out = []
for root, dirs, files in os.walk(os.path.join(folder, 'locale/')):
for name in files:
if pattern_tr_filename.search(name):
out.append(name)
return out
# A series of search and replaces that massage a .po file's contents into
# a .tr file's equivalent
def process_po_file(text):
# The first three items are for unused matches
text = re.sub(r'#~ msgid "', "", text)
text = re.sub(r'"\n#~ msgstr ""\n"', "=", text)
text = re.sub(r'"\n#~ msgstr "', "=", text)
# comment lines
text = re.sub(r'#.*\n', "", text)
# converting msg pairs into "=" pairs
text = re.sub(r'msgid "', "", text)
text = re.sub(r'"\nmsgstr ""\n"', "=", text)
text = re.sub(r'"\nmsgstr "', "=", text)
# various line breaks and escape codes
text = re.sub(r'"\n"', "", text)
text = re.sub(r'"\n', "\n", text)
text = re.sub(r'\\"', '"', text)
text = re.sub(r'\\n', '@n', text)
# remove header text
text = re.sub(r'=Project-Id-Version:.*\n', "", text)
# remove double-spaced lines
text = re.sub(r'\n\n', '\n', text)
return text
# Go through existing .po files and, if a .tr file for that language
# *doesn't* exist, convert it and create it.
# The .tr file that results will subsequently be reprocessed so
# any "no longer used" strings will be preserved.
# Note that "fuzzy" tags will be lost in this process.
def process_po_files(folder, modname):
for root, dirs, files in os.walk(os.path.join(folder, 'locale/')):
for name in files:
code_match = pattern_po_language_code.match(name)
if code_match == None:
continue
language_code = code_match.group(1)
tr_name = modname + "." + language_code + ".tr"
tr_file = os.path.join(root, tr_name)
if os.path.exists(tr_file):
if params["verbose"]:
print(f"{tr_name} already exists, ignoring {name}")
continue
fname = os.path.join(root, name)
with open(fname, "r", encoding='utf-8') as po_file:
if params["verbose"]:
print(f"Importing translations from {name}")
text = process_po_file(po_file.read())
with open(tr_file, "wt", encoding='utf-8') as tr_out:
tr_out.write(text)
# from https://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python/600612#600612
# Creates a directory if it doesn't exist, silently does
# nothing if it already exists
def mkdir_p(path):
try:
os.makedirs(path)
except OSError as exc: # Python >2.5
if exc.errno == errno.EEXIST and os.path.isdir(path):
pass
else: raise
# Converts the template dictionary to a text to be written as a file
# dKeyStrings is a dictionary of localized string to source file sets
# dOld is a dictionary of existing translations and comments from
# the previous version of this text
def strings_to_text(dkeyStrings, dOld, mod_name):
lOut = [f"# textdomain: {mod_name}\n"]
dGroupedBySource = {}
for key in dkeyStrings:
sourceList = list(dkeyStrings[key])
sourceList.sort()
sourceString = "\n".join(sourceList)
listForSource = dGroupedBySource.get(sourceString, [])
listForSource.append(key)
dGroupedBySource[sourceString] = listForSource
lSourceKeys = list(dGroupedBySource.keys())
lSourceKeys.sort()
for source in lSourceKeys:
localizedStrings = dGroupedBySource[source]
localizedStrings.sort()
lOut.append("")
lOut.append(source)
lOut.append("")
for localizedString in localizedStrings:
val = dOld.get(localizedString, {})
translation = val.get("translation", "")
comment = val.get("comment")
if len(localizedString) > doublespace_threshold and not lOut[-1] == "":
lOut.append("")
if comment != None:
lOut.append(comment)
lOut.append(f"{localizedString}={translation}")
if len(localizedString) > doublespace_threshold:
lOut.append("")
unusedExist = False
for key in dOld:
if key not in dkeyStrings:
val = dOld[key]
translation = val.get("translation")
comment = val.get("comment")
# only keep an unused translation if there was translated
# text or a comment associated with it
if translation != None and (translation != "" or comment):
if not unusedExist:
unusedExist = True
lOut.append("\n\n##### not used anymore #####\n")
if len(key) > doublespace_threshold and not lOut[-1] == "":
lOut.append("")
if comment != None:
lOut.append(comment)
lOut.append(f"{key}={translation}")
if len(key) > doublespace_threshold:
lOut.append("")
return "\n".join(lOut) + '\n'
# Writes a template.txt file
# dkeyStrings is the dictionary returned by generate_template
def write_template(templ_file, dkeyStrings, mod_name):
# read existing template file to preserve comments
existing_template = import_tr_file(templ_file)
text = strings_to_text(dkeyStrings, existing_template[0], mod_name)
mkdir_p(os.path.dirname(templ_file))
with open(templ_file, "wt", encoding='utf-8') as template_file:
template_file.write(text)
# Gets all translatable strings from a lua file
def read_lua_file_strings(lua_file):
lOut = []
with open(lua_file, encoding='utf-8') as text_file:
text = text_file.read()
#TODO remove comments here
text = re.sub(pattern_concat, "", text)
strings = []
for s in pattern_lua.findall(text):
strings.append(s[1])
for s in pattern_lua_bracketed.findall(text):
strings.append(s)
for s in strings:
s = re.sub(r'"\.\.\s+"', "", s)
s = re.sub("@[^@=0-9]", "@@", s)
s = s.replace('\\"', '"')
s = s.replace("\\'", "'")
s = s.replace("\n", "@n")
s = s.replace("\\n", "@n")
s = s.replace("=", "@=")
lOut.append(s)
return lOut
# Gets strings from an existing translation file
# returns both a dictionary of translations
# and the full original source text so that the new text
# can be compared to it for changes.
def import_tr_file(tr_file):
dOut = {}
text = None
if os.path.exists(tr_file):
with open(tr_file, "r", encoding='utf-8') as existing_file :
# save the full text to allow for comparison
# of the old version with the new output
text = existing_file.read()
existing_file.seek(0)
# a running record of the current comment block
# we're inside, to allow preceeding multi-line comments
# to be retained for a translation line
latest_comment_block = None
for line in existing_file.readlines():
line = line.rstrip('\n')
if line[:3] == "###":
# Reset comment block if we hit a header
latest_comment_block = None
continue
if line[:1] == "#":
# Save the comment we're inside
if not latest_comment_block:
latest_comment_block = line
else:
latest_comment_block = latest_comment_block + "\n" + line
continue
match = pattern_tr.match(line)
if match:
# this line is a translated line
outval = {}
outval["translation"] = match.group(2)
if latest_comment_block:
# if there was a comment, record that.
outval["comment"] = latest_comment_block
latest_comment_block = None
dOut[match.group(1)] = outval
return (dOut, text)
# Walks all lua files in the mod folder, collects translatable strings,
# and writes it to a template.txt file
# Returns a dictionary of localized strings to source file sets
# that can be used with the strings_to_text function.
def generate_template(folder, mod_name):
dOut = {}
for root, dirs, files in os.walk(folder):
for name in files:
if fnmatch.fnmatch(name, "*.lua"):
fname = os.path.join(root, name)
found = read_lua_file_strings(fname)
if params["verbose"]:
print(f"{fname}: {str(len(found))} translatable strings")
for s in found:
sources = dOut.get(s, set())
sources.add(f"### {os.path.basename(fname)} ###")
dOut[s] = sources
if len(dOut) == 0:
return None
templ_file = os.path.join(folder, "locale/template.txt")
write_template(templ_file, dOut, mod_name)
return dOut
# Updates an existing .tr file, copying the old one to a ".old" file
# if any changes have happened
# dNew is the data used to generate the template, it has all the
# currently-existing localized strings
def update_tr_file(dNew, mod_name, tr_file):
if params["verbose"]:
print(f"updating {tr_file}")
tr_import = import_tr_file(tr_file)
dOld = tr_import[0]
textOld = tr_import[1]
textNew = strings_to_text(dNew, dOld, mod_name)
if textOld and textOld != textNew:
print(f"{tr_file} has changed.")
if not params["no-old-file"]:
shutil.copyfile(tr_file, f"{tr_file}.old")
with open(tr_file, "w", encoding='utf-8') as new_tr_file:
new_tr_file.write(textNew)
# Updates translation files for the mod in the given folder
def update_mod(folder):
modname = get_modname(folder)
if modname is not None:
process_po_files(folder, modname)
print(f"Updating translations for {modname}")
data = generate_template(folder, modname)
if data == None:
print(f"No translatable strings found in {modname}")
else:
for tr_file in get_existing_tr_files(folder):
update_tr_file(data, modname, os.path.join(folder, "locale/", tr_file))
else:
print("Unable to find modname in folder " + folder)
# Determines if the folder being pointed to is a mod or a mod pack
# and then runs update_mod accordingly
def update_folder(folder):
is_modpack = os.path.exists(os.path.join(folder, "modpack.txt")) or os.path.exists(os.path.join(folder, "modpack.conf"))
if is_modpack:
subfolders = [f.path for f in os.scandir(folder) if f.is_dir()]
for subfolder in subfolders:
update_mod(subfolder + "/")
else:
update_mod(folder)
print("Done.")
def run_all_subfolders(folder):
for modfolder in [f.path for f in os.scandir(folder) if f.is_dir()]:
update_folder(modfolder + "/")
main()

89
init.lua Normal file
View File

@ -0,0 +1,89 @@
--[[
****************************************************************
******* Simple Chat ******
******* A Mod to manage the Chat in Minetest ******
******* License: GPL 3.0 ******
******* by A.C.M. ******
****************************************************************
--]]
smart_chat = {}
local sc = smart_chat
sc.player = {}
sc.public = {}
sc.version = 1
sc.revision = 0
sc.modname = minetest.get_current_modname()
sc.modpath = minetest.get_modpath(sc.modname)
local path = sc.modpath
sc.helpsystem = {}
-- Colors for Chat
sc.green = minetest.get_color_escape_sequence('#00FF00')
sc.red = minetest.get_color_escape_sequence('#FF0000')
sc.orange = minetest.get_color_escape_sequence('#FF6700')
sc.blue = minetest.get_color_escape_sequence('#0000FF')
sc.yellow = minetest.get_color_escape_sequence('#FFFF00')
sc.purple = minetest.get_color_escape_sequence('#FF00FF')
sc.pink = minetest.get_color_escape_sequence('#FFAAFF')
sc.white = minetest.get_color_escape_sequence('#FFFFFF')
sc.black = minetest.get_color_escape_sequence('#000000')
sc.grey = minetest.get_color_escape_sequence('#888888')
sc.light_blue = minetest.get_color_escape_sequence('#8888FF')
sc.light_green = minetest.get_color_escape_sequence('#88FF88')
sc.light_red = minetest.get_color_escape_sequence('#FF8888')
sc.S = nil
local S
if(minetest.get_translator ~= nil) then
S = minetest.get_translator(sc.modname)
else
S = function ( s ) return s end
end
sc.S = S
dofile(path .. "/lib.lua")
dofile(path .. "/cmd_help.lua")
dofile(path .. "/core.lua")
dofile(path .. "/cmd_join.lua")
dofile(path .. "/cmd_leave.lua")
dofile(path .. "/cmd_list.lua")
dofile(path .. "/cmd_channels.lua")
dofile(path .. "/cmd_all.lua")
dofile(path .. "/cmd_invite.lua")
dofile(path .. "/cmd_toggle.lua")
dofile(path .. "/cmd_where.lua")
--[[
****************************************************************
******* Registered Chatcommands ******
****************************************************************
--]]
minetest.register_chatcommand("c",{
param = "<command> <parameter>",
privs = {
interact = true,
shout = true
},
description = S("Gives Simple_Chat a command with or without Parameter.") .. "\n",
func = function(player, cmd)
if(cmd.type == "string") then
cmd = cmd:lower()
end
local command = sc.split(cmd)
sc.check(player, command)
end -- function
}) -- minetest.register_chatcommand

185
lib.lua Normal file
View File

@ -0,0 +1,185 @@
local lib = smart_chat
local mn = lib.modname
--[[
****************************************************************
******* Function split(parameter) ******
****************************************************************
Split Command and Parameter and write it to a table
--]]
function lib.split(parameter)
local cmd = {}
for word in string.gmatch(parameter, "[%w%-%:%.2f%_]+") do
table.insert(cmd, word)
end -- for word
return cmd
end -- function lib.split
--[[
****************************************************************
******* Function check(command) ******
****************************************************************
Check if the command is valid
--]]
function lib.check(player, cmd)
if(cmd ~= nil and cmd[1] ~= nil) then
if(lib[cmd[1]] ~= nil) then
-- Command is valid, execute it with parameter
lib[cmd[1]](player, cmd)
else -- A command is given, but
-- Command not found, report it.
if(cmd[1] ~= nil) then
lib.print(player, lib.red .. mn ..": Unknown Command \"" ..
lib.orange .. cmd[1] .. lib.red .. "\".")
else
if(lib["help"]) then
lib["help"](player, cmd)
else
lib.print(player, lib.red .. "Unknown Command. No helpsystem available.")
end --if(distancer["help"]
end -- if(cmd[1]
end -- if(distancer[cmd[1
else
lib.print(player, lib.red .. "No Command for " .. mn .. " given.")
lib.print(player, lib.red .. "Try /c help.")
end -- if(not cmd)
end -- function lib.check(cmd
--[[
****************************************************************
******* Function register_help() ******
****************************************************************
Registers a new Entry in the Helpsystem for an Command.
]]--
function lib.register_help(entry)
lib.helpsystem[entry.Name] = {
Name = entry.Name,
Usage = entry.Usage,
Description = entry.Description,
Parameter = entry.Parameter,
Shortcut = entry.Shortcut,
}
end
--[[
****************************************************************
******* Function display_chat_message(message) ******
****************************************************************
]]--
function lib.print(player, text)
local lprint = minetest.chat_send_player
--local playername = minetest.get_player_by_name(player)
lprint(player, text)
end -- function distancer.print(
function lib.check_global(cplayer)
if(lib.player[cplayer] == nil) then
return true
else
return false
end
end
function lib.check_channel(cplayer, channel)
if(lib.player[cplayer] == channel) then
return true
else
return false
end -- if(sc.player[
end -- lib.check_channel
--[[
****************************************************************
******* Function report() ******
****************************************************************
]]--
function lib.report(player, message)
local all_player = minetest.get_connected_players()
local channel = lib.player[player]
for _,players in pairs(all_player) do
local pname = players:get_player_name()
if(lib.check_channel(pname, channel)) then
lib.print(pname, lib.orange .. "<" .. lib.yellow .. player .. lib.orange .. "> " .. message)
end -- if(check_channel
end -- for _,players
end -- lib.report(
--[[
****************************************************************
******* Function print_all() ******
****************************************************************
]]--
function lib.chat(playername, text)
local all_player = minetest.get_connected_players()
local channel = lib.player[playername] -- Get the Channel of the player
for _,players in pairs(all_player) do
local pname = players:get_player_name()
if(channel == nil) then
if(lib.check_global(pname)) then
minetest.chat_send_player(pname, "<" .. playername .. ">" .. text)
minetest.log("action", "CHAT: # <" .. playername .. ">" .. text)
end -- if(lib.check_global(
elseif(lib.check_channel(pname, channel)) then
minetest.chat_send_player(pname, lib.yellow .. "<" .. lib.orange .. playername .. "@"
.. channel .. lib.yellow .. ">" .. text)
minetest.log("action", "CHAT: # <" .. playername .. "@" .. channel .. ">" .. text)
end -- if(channel == nil
end -- for _,players
-- Send's the message to all public Players too
for _,players in pairs(lib.public) do
if(players ~= playername) then
minetest.chat_send_player(players, "<" .. playername .. ">" .. text)
end -- if(players ~= playername
end -- for _,players
return true
end -- function chat
--[[
****************************************************************
******* Function show_version() ******
****************************************************************
]]--
function lib.show_version()
print("[MOD]" .. lib.modname .. " v " .. lib.version .. "." .. lib.revision .. " loaded. \n")
end -- lib.show_version

80
locale/smart_chat.de.tr Normal file
View File

@ -0,0 +1,80 @@
# textdomain: smart_chat
### cmd_all.lua ###
Error - require 'basic_privs' privilege.=Fehler - 'basic_privs' benötigt.
Error: No Message given.=Fehler: Keine Nachricht angebeben.
Send's a message on all.=Sendet eine Nachricht an alle.
### cmd_channels.lua ###
Channels on Server:=Kanäle am Server:
Lists all channels on the Server.=Listet alle Kanäle auf dem Server.
### cmd_help.lua ###
<command>=<Kommando>
Commands for =Kommanden für
Description: =Beschreibung:
Helpsystem for =Hilfssystem für
Name: =Name:
No entry in help for command=Kein Eintrag in der Hilfe für Kommando
Parameter: =Parameter:
Shortcut: =Kurzbefehl:
Shows you the entire help for =Zeigt dir die gesamte Hilfe für
Shows you the help for =Zeigt dir die Hilfe für
Usage: =Benutzung:
command=Kommando
found.=gefunden.
### cmd_invite.lua ###
to join the Channel.= ein, um den Kanal zu betreten.
Enter /c j =Gib /c j
Error: No Player with the name found.=Fehler: Kein Spieler mit dem Namen gefunden.
Error: No playername given.=Fehler: Kein Spielernamen angegeben.
Error: You can not invite a player in the public chat.=Fehler: Du kannst keinen Spieler in den öffentlichen Chat einladen.
Invites a <player> to your Channel.=Lädt einen <Spieler> in deinen Kanal ein.
Invites you in the channel: =Lädt dich ein in den Kanal:
### cmd_join.lua ###
Enter the Channel.=Betritt den Kanal.
Error: No channel to join given.=Fehler: Kein Kanal zum Betreten angegeben.
Join or change a channel to <channel>.=Betritt oder wechselt den Kanal zu <Kanal>.
### cmd_join.lua ###
### cmd_leave.lua ###
Leaves the Channel.=Verlässt den Kanal.
### cmd_leave.lua ###
Enter the public Chat.=Betritt den öffentlichen Chat.
Error: You're already in the public chat.=Fehler: Du bist schon im öffentlichem Chat.
Leaves a channel=Verlässt einen Kanal
### cmd_list.lua ###
Lists all player in the channel.=Zeigt alle Spieler in dem Kanal.
Player in Channel=Spieler im Kanal
### cmd_toggle.lua ###
The permanent public chat is now off.=Der permanente öffentliche Chat ist nun aus.
The permanent public chat is now on.=Der permanente öffentliche Chat ist nun ein.
Turn's the permanent public Chat on or off.=Schaltet den permanent öffentlichen Chat ein oder aus.
### cmd_where.lua ###
is in Channel {= ist im Kanal {
Error: No name given.=Fehler: Keinen Namen angegeben.
Error: Player is not online.=Fehler: Spieler ist nicht online.
Player [=Spieler [
Show's the room, where <name> is.=Zeigt den Raum, wo sich <Name> aufhält.
] is in the public Chat.=] ist im öffentlichem Chat.
### init.lua ###
Gives Simple_Chat a command with or without Parameter.=Gibt Simple_Chat ein Kommando mit oder ohne Parameter.

80
locale/template.txt Normal file
View File

@ -0,0 +1,80 @@
# textdomain: smart_chat
### cmd_all.lua ###
Error - require 'basic_privs' privilege.=
Error: No Message given.=
Send's a message on all.=
### cmd_channels.lua ###
Channels on Server:=
Lists all channels on the Server.=
### cmd_help.lua ###
<command>=
Commands for =
Description: =
Helpsystem for =
Name: =
No entry in help for command=
Parameter: =
Shortcut: =
Shows you the entire help for =
Shows you the help for =
Usage: =
command=
found.=
### cmd_invite.lua ###
to join the Channel.=
Enter /c j =
Error: No Player with the name found.=
Error: No playername given.=
Error: You can not invite a player in the public chat.=
Invites a <player> to your Channel.=
Invites you in the channel: =
### cmd_join.lua ###
Enter the Channel.=
Error: No channel to join given.=
Join or change a channel to <channel>.=
### cmd_join.lua ###
### cmd_leave.lua ###
Leaves the Channel.=
### cmd_leave.lua ###
Enter the public Chat.=
Error: You're already in the public chat.=
Leaves a channel=
### cmd_list.lua ###
Lists all player in the channel.=
Player in Channel=
### cmd_toggle.lua ###
The permanent public chat is now off.=
The permanent public chat is now on.=
Turn's the permanent public Chat on or off.=
### cmd_where.lua ###
is in Channel {=
Error: No name given.=
Error: Player is not online.=
Player [=
Show's the room, where <name> is.=
] is in the public Chat.=
### init.lua ###
Gives Simple_Chat a command with or without Parameter.=

1
mod.conf Normal file
View File

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