built on 06/08/2022 15:09:51

This commit is contained in:
Joachim Stolberg 2022-08-06 15:09:51 +02:00
parent 5a39e9f0a6
commit 09584b8a2d
35 changed files with 609 additions and 157 deletions

View File

@ -1,7 +1,7 @@
# Modpack Tech Age [techage] # Modpack Tech Age [techage]
This modpack covers all necessary and useful mods to be able to use techage. This modpack covers all necessary and useful mods to be able to use techage.
All mods have the own README.txt. For further information please consult these files. All mods have their own README.txt. For further information please consult these files.
This modpack contains: This modpack contains:
- techage: The main mod - techage: The main mod

View File

@ -1,4 +0,0 @@
default
moreblocks?
techage?
minecart?

View File

@ -1 +0,0 @@
Street mod for faster travelling.

View File

@ -1 +1,5 @@
name=autobahn name=autobahn
title=Autobahn
description=Street mod for faster travelling.
depends=default
optional_depends=moreblocks, techage, minecart

View File

@ -1 +0,0 @@

2
datastorage/mod.conf Normal file
View File

@ -0,0 +1,2 @@
name=datastorage
description=Helper mod to manage players data.

View File

@ -115,10 +115,10 @@ local generate_texture = function(lines)
end end
local lcds = { local lcds = {
[2] = {delta = {x = 0.437, y = 0, z = 0}, yaw = math.pi / -2}, [2] = {delta = {x = 0.425, y = 0, z = 0}, yaw = math.pi / -2},
[3] = {delta = {x = -0.437, y = 0, z = 0}, yaw = math.pi / 2}, [3] = {delta = {x = -0.425, y = 0, z = 0}, yaw = math.pi / 2},
[4] = {delta = {x = 0, y = 0, z = 0.437}, yaw = 0}, [4] = {delta = {x = 0, y = 0, z = 0.425}, yaw = 0},
[5] = {delta = {x = 0, y = 0, z = -0.437}, yaw = math.pi}, [5] = {delta = {x = 0, y = 0, z = -0.425}, yaw = math.pi},
} }
local clearscreen = function(pos) local clearscreen = function(pos)

View File

View File

@ -1,4 +0,0 @@
SaferLua [safer_lua], a subset of the language Lua for safe and secure Lua sandboxes

View File

@ -1 +1,2 @@
name=safer_lua name=safer_lua
description = SaferLua [safer_lua], a subset of the language Lua for safe and secure Lua sandboxes

View File

@ -11,7 +11,7 @@ and by the historical game Lunar Lander.
Instructions: Instructions:
- Craft TA4 Jetpack, Jetpack Controller and Training Mat - Craft TA4 Jetpack, Jetpack Controller and Training Mat
- Use the armor extension (3d_armor) of the player menu to strap the Jetpack on your back - Use the armor extension (3d_armor) of the player menu to strap the Jetpack on your back
- You can refuel the jetpack by left-clicking with the controller on a hydrogen tank - You can refuel the jetpack by left-clicking with the controller on a TA3/TA4 tank previously charged with hydrogen
- Turn the controller on by right-click and check the fuel tank level (the small colored bar below the controller icon) - Turn the controller on by right-click and check the fuel tank level (the small colored bar below the controller icon)
- Use the space bar to activate the Jetpack and the WASD keys to control the direction - Use the space bar to activate the Jetpack and the WASD keys to control the direction
- Before your first flight you should do some training starts and landings on the Training Mat - Before your first flight you should do some training starts and landings on the Training Mat

View File

@ -1,80 +1,476 @@
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Script to generate the template file and update the translation files. # 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 # Copyright (C) 2019 Joachim Stolberg, 2020 FaceDeer, 2020 Louis Royer
# LGPLv2.1+ # LGPLv2.1+
# #
# Copy the script into the mod root folder and adapt the last code lines to you needs. # See https://github.com/minetest-tools/update_translations for
# potential future updates to this script.
from __future__ import print_function from __future__ import print_function
import os, fnmatch, re, shutil import os, fnmatch, re, shutil, errno
from sys import argv as _argv
from sys import stderr as _stderr
pattern_lua = re.compile(r'[ \.=^\t]S\("(.+?)"\)', re.DOTALL) # Running params
pattern_tr = re.compile(r'(.+?[^@])=(.+)') params = {"recursive": False,
"help": False,
"mods": False,
"verbose": False,
"folders": [],
"no-old-file": False,
"break-long-lines": False,
"sort": False,
"print-source": False,
"truncate-unused": False,
}
# Available CLI options
options = {"recursive": ['--recursive', '-r'],
"help": ['--help', '-h'],
"mods": ['--installed-mods', '-m'],
"verbose": ['--verbose', '-v'],
"no-old-file": ['--no-old-file', '-O'],
"break-long-lines": ['--break-long-lines', '-b'],
"sort": ['--sort', '-s'],
"print-source": ['--print-source', '-p'],
"truncate-unused": ['--truncate-unused', '-t'],
}
def gen_template(templ_file, lkeyStrings): # Strings longer than this will have extra space added between
lOut = [] # them in the translation files to make it easier to distinguish their
lkeyStrings.sort() # beginnings and endings at a glance
for s in lkeyStrings: doublespace_threshold = 80
lOut.append("%s=" % s)
open(templ_file, "wt").write("\n".join(lOut))
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["sort"])}
sort output strings alphabetically
{', '.join(options["break-long-lines"])}
add extra line breaks before and after long strings
{', '.join(options["print-source"])}
add comments denoting the source file
{', '.join(options["verbose"])}
add output information
{', '.join(options["truncate-unused"])}
delete unused strings from files
''')
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.expanduser('~/.minetest/mods/')}")
run_all_subfolders(os.path.expanduser("~/.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_s = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*(["\'])((?:\\\1|(?:(?!\1)).)*)(\1)[\s,\)]', re.DOTALL)
pattern_lua_fs = re.compile(r'[\.=^\t,{\(\s]N?FS\(\s*(["\'])((?:\\\1|(?:(?!\1)).)*)(\1)[\s,\)]', re.DOTALL)
pattern_lua_bracketed_s = re.compile(r'[\.=^\t,{\(\s]N?S\(\s*\[\[(.*?)\]\][\s,\)]', re.DOTALL)
pattern_lua_bracketed_fs = re.compile(r'[\.=^\t,{\(\s]N?FS\(\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 or folder name. 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:
if not os.path.isfile(os.path.join(folder, "modpack.txt")):
folder_name = os.path.basename(folder)
# Special case when run in Minetest's builtin directory
if folder_name == "builtin":
return "__builtin"
else:
return folder_name
else:
return None
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 = f'{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, header_comments):
lOut = [f"# textdomain: {mod_name}"]
if header_comments is not None:
lOut.append(header_comments)
dGroupedBySource = {}
for key in dkeyStrings:
sourceList = list(dkeyStrings[key])
if params["sort"]:
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]
if params["sort"]:
localizedStrings.sort()
if params["print-source"]:
if lOut[-1] != "":
lOut.append("")
lOut.append(source)
for localizedString in localizedStrings:
val = dOld.get(localizedString, {})
translation = val.get("translation", "")
comment = val.get("comment")
if params["break-long-lines"] and len(localizedString) > doublespace_threshold and not lOut[-1] == "":
lOut.append("")
if comment != None and comment != "" and not comment.startswith("# textdomain:"):
lOut.append(comment)
lOut.append(f"{localizedString}={translation}")
if params["break-long-lines"] and len(localizedString) > doublespace_threshold:
lOut.append("")
unusedExist = False
if not params["truncate-unused"]:
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 params["break-long-lines"] and len(key) > doublespace_threshold and not lOut[-1] == "":
lOut.append("")
if comment != None:
lOut.append(comment)
lOut.append(f"{key}={translation}")
if params["break-long-lines"] and 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, existing_template[2])
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): def read_lua_file_strings(lua_file):
lOut = [] lOut = []
text = open(lua_file).read() with open(lua_file, encoding='utf-8') as text_file:
for s in pattern_lua.findall(text): text = text_file.read()
s = re.sub(r'"\.\.\s+"', "", s) #TODO remove comments here
s = re.sub("@[^@=n]", "@@", s)
s = s.replace("\n", "@n") text = re.sub(pattern_concat, "", text)
s = s.replace("\\n", "@n")
s = s.replace("=", "@=") strings = []
lOut.append(s) for s in pattern_lua_s.findall(text):
strings.append(s[1])
for s in pattern_lua_bracketed_s.findall(text):
strings.append(s)
for s in pattern_lua_fs.findall(text):
strings.append(s[1])
for s in pattern_lua_bracketed_fs.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 return lOut
def inport_tr_file(tr_file): # 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.
# Returns also header comments in the third return value.
def import_tr_file(tr_file):
dOut = {} dOut = {}
text = None
header_comment = None
if os.path.exists(tr_file): if os.path.exists(tr_file):
for line in open(tr_file, "r").readlines(): with open(tr_file, "r", encoding='utf-8') as existing_file :
s = line.strip() # save the full text to allow for comparison
if s == "" or s[0] == "#": # of the old version with the new output
continue text = existing_file.read()
match = pattern_tr.match(s) existing_file.seek(0)
if match: # a running record of the current comment block
dOut[match.group(1)] = match.group(2) # we're inside, to allow preceeding multi-line comments
return dOut # to be retained for a translation line
latest_comment_block = None
for line in existing_file.readlines():
line = line.rstrip('\n')
if line.startswith("###"):
if header_comment is None and not latest_comment_block is None:
# Save header comments
header_comment = latest_comment_block
# Strip textdomain line
tmp_h_c = ""
for l in header_comment.split('\n'):
if not l.startswith("# textdomain:"):
tmp_h_c += l + '\n'
header_comment = tmp_h_c
def generate_template(templ_file): # Reset comment block if we hit a header
lOut = [] latest_comment_block = None
for root, dirs, files in os.walk('./'): continue
elif line.startswith("#"):
# 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, header_comment)
# 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: for name in files:
if fnmatch.fnmatch(name, "*.lua"): if fnmatch.fnmatch(name, "*.lua"):
fname = os.path.join(root, name) fname = os.path.join(root, name)
found = read_lua_file_strings(fname) found = read_lua_file_strings(fname)
print(fname, len(found)) if params["verbose"]:
lOut.extend(found) print(f"{fname}: {str(len(found))} translatable strings")
lOut = list(set(lOut))
lOut.sort()
gen_template(templ_file, lOut)
return lOut
def update_tr_file(lNew, mod_name, tr_file): for s in found:
lOut = ["# textdomain: %s\n" % mod_name] sources = dOut.get(s, set())
if os.path.exists(tr_file): sources.add(f"### {os.path.basename(fname)} ###")
shutil.copyfile(tr_file, tr_file+".old") dOut[s] = sources
dOld = inport_tr_file(tr_file)
for key in lNew: if len(dOut) == 0:
val = dOld.get(key, "") return None
lOut.append("%s=%s" % (key, val)) templ_file = os.path.join(folder, "locale/template.txt")
lOut.append("##### not used anymore #####") write_template(templ_file, dOut, mod_name)
for key in dOld: return dOut
if key not in lNew:
lOut.append("%s=%s" % (key, dOld[key])) # Updates an existing .tr file, copying the old one to a ".old" file
open(tr_file, "w").write("\n".join(lOut)) # if any changes have happened
# dNew is the data used to generate the template, it has all the
data = generate_template("./locale/template.txt") # currently-existing localized strings
update_tr_file(data, "ta4_jetpack", "./locale/ta4_jetpack.de.tr") def update_tr_file(dNew, mod_name, tr_file):
print("Done.\n") 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, tr_import[2])
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(f"\033[31mUnable to find modname in folder {folder}.\033[0m", file=_stderr)
exit(1)
# 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() and not f.name.startswith('.')]
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() and not f.name.startswith('.')]:
update_folder(modfolder)
main()

View File

@ -320,6 +320,10 @@ end
minetest.after(WEAR_CYCLE, jetpack_wearout) minetest.after(WEAR_CYCLE, jetpack_wearout)
local function round(val)
return math.floor((val * 10) + 0.5) / 10.0
end
local function load_fuel(itemstack, user, pointed_thing) local function load_fuel(itemstack, user, pointed_thing)
local pos = pointed_thing.under local pos = pointed_thing.under
if pos then if pos then
@ -340,11 +344,11 @@ local function load_fuel(itemstack, user, pointed_thing)
newvalue = value - (amount - rest) newvalue = value - (amount - rest)
else else
local amount = math.max(math.min(FUEL_UNIT, MAX_FUEL - value), 0) local amount = math.max(math.min(FUEL_UNIT, MAX_FUEL - value), 0)
local taken = liquid.srv_take(nvm, "techage:hydrogen", amount) local taken = liquid.srv_take(nvm, "techage:hydrogen", math.floor(amount))
newvalue = value + taken newvalue = value + taken
end end
set_fuel_value(name, newvalue) set_fuel_value(name, newvalue)
minetest.chat_send_player(name, S("[Jetpack]") .. ": " .. newvalue .. "/" .. MAX_FUEL) minetest.chat_send_player(name, S("[Jetpack]") .. ": " .. round(newvalue) .. "/" .. MAX_FUEL)
end end
end end
return itemstack return itemstack
@ -417,7 +421,7 @@ minetest.register_tool("ta4_jetpack:controller_off", {
stack_max = 1, stack_max = 1,
}) })
armor:register_armor("ta4_jetpack:jetpack", { armor:register_armor("ta4_jetpack:jetpack_material", {
description = S("TA4 Jetpack"), description = S("TA4 Jetpack"),
texture = "ta4_jetpack_jetpack.png", texture = "ta4_jetpack_jetpack.png",
inventory_image = "ta4_jetpack_jetpack_inv.png", inventory_image = "ta4_jetpack_jetpack_inv.png",
@ -441,6 +445,8 @@ armor:register_armor("ta4_jetpack:jetpack", {
end end
}) })
minetest.register_alias("ta4_jetpack:jetpack", "ta4_jetpack:jetpack_material")
-- For some reason, prevent to move/put/take a running controller -- For some reason, prevent to move/put/take a running controller
minetest.register_allow_player_inventory_action(function(player, action, inventory, inventory_info) minetest.register_allow_player_inventory_action(function(player, action, inventory, inventory_info)
if inventory_info.stack and inventory_info.stack:get_name() == "ta4_jetpack:controller_on" then if inventory_info.stack and inventory_info.stack:get_name() == "ta4_jetpack:controller_on" then

View File

@ -1,15 +1,13 @@
# textdomain: ta4_jetpack # textdomain: ta4_jetpack
Jetpack Training Mat=Jetpack Trainingsmatte
TA4 Jetpack=TA4 Jetpac
TA4 Jetpack Controller Off=TA4 Jetpack Controller Aus
TA4 Jetpack Controller On=TA4 Jetpack Controller An
Use the controller (left click) to fill the tank with hydrogen=Benutze den Controller (linksklick) um den Tank mit Wasserstoff zu füllen
You are too heavy: Check your bags!=Du bist zu schwer: Prüfe deine Rucksäcke! You are too heavy: Check your bags!=Du bist zu schwer: Prüfe deine Rucksäcke!
You are too heavy: Check your crafting menu!=Du bist zu schwer: Prüfe dein Crafting Menü! You are too heavy: Check your crafting menu!=Du bist zu schwer: Prüfe dein Crafting Menü!
You are too heavy: Check your inventory!=Du bist zu schwer: Prüfe dein Inventar! You are too heavy: Check your inventory!=Du bist zu schwer: Prüfe dein Inventar!
You may not transport @1 with a jetpack!=Du darfst @1 nicht mit dem Jetpack transportieren! You may not transport @1 with a jetpack!=Du darfst @1 nicht mit dem Jetpack transportieren!
[Jetpack]=[Jetpack]
[Jetpack] You don't have your jetpack on your back!=[Jetpack] Du hast dein Jetpack nicht auf dem Rücken! [Jetpack] You don't have your jetpack on your back!=[Jetpack] Du hast dein Jetpack nicht auf dem Rücken!
[Jetpack]=[Jetpack]
[Jetpack] Your tank is empty!=[Jetpack] Dein Tank ist leer! [Jetpack] Your tank is empty!=[Jetpack] Dein Tank ist leer!
##### not used anymore ##### Use the controller (left click) to fill the tank with hydrogen=Benutze den Controller (linksklick) um den Tank mit Wasserstoff zu füllen
TA4 Jetpack Controller On=TA4 Jetpack Controller An
TA4 Jetpack Controller Off=TA4 Jetpack Controller Aus
TA4 Jetpack=TA4 Jetpac
Jetpack Training Mat=Jetpack Trainingsmatte

View File

@ -1,13 +1,13 @@
Jetpack Training Mat= # textdomain: ta4_jetpack
TA4 Jetpack=
TA4 Jetpack Controller Off=
TA4 Jetpack Controller On=
Use the controller (left click) to fill the tank with hydrogen=
You are too heavy: Check your bags!= You are too heavy: Check your bags!=
You are too heavy: Check your crafting menu!= You are too heavy: Check your crafting menu!=
You are too heavy: Check your inventory!= You are too heavy: Check your inventory!=
You may not transport @1 with a jetpack!= You may not transport @1 with a jetpack!=
[Jetpack]=
[Jetpack] You don't have your jetpack on your back!= [Jetpack] You don't have your jetpack on your back!=
[Jetpack]=
[Jetpack] Your tank is empty!= [Jetpack] Your tank is empty!=
##### not used anymore ##### Use the controller (left click) to fill the tank with hydrogen=
TA4 Jetpack Controller On=
TA4 Jetpack Controller Off=
TA4 Jetpack=
Jetpack Training Mat=

View File

@ -9,7 +9,7 @@ Das Jetpack ist inspiriert vom Jetpack von spirit689 (https://github.com/spirit6
- TA4 Jetpack, Jetpack Controller und Trainingsmatte herstellen (craften) - TA4 Jetpack, Jetpack Controller und Trainingsmatte herstellen (craften)
- Verwende die '3d_armor' Erweiterung des Spielermenüs, um das Jetpack auf deinem Rücken zu schnallen - Verwende die '3d_armor' Erweiterung des Spielermenüs, um das Jetpack auf deinem Rücken zu schnallen
- Du kannst das Jetpack auftanken, indem du mit dem Controller und mit der linken Maustaste auf einen Wasserstofftanks klickst - Du kannst das Jetpack auftanken, indem du mit dem Controller und mit der linken Maustaste auf einen TA3/TA4 Tank mit Wasserstoff klickst
- Schalte den Controller mit der rechten Maustaste ein und überprüfe den Füllstand des Kraftstofftanks (der kleine farbige Balken unter dem Reglersymbol). - Schalte den Controller mit der rechten Maustaste ein und überprüfe den Füllstand des Kraftstofftanks (der kleine farbige Balken unter dem Reglersymbol).
- Verwende die Leertaste, um das Jetpack zu aktivieren und die WASD-Tasten, um die Richtung zu steuern - Verwende die Leertaste, um das Jetpack zu aktivieren und die WASD-Tasten, um die Richtung zu steuern
- Vor dem ersten Flug solltest du einige Trainingsstarts und Landungen auf der Trainingsmatte durchführen - Vor dem ersten Flug solltest du einige Trainingsstarts und Landungen auf der Trainingsmatte durchführen

View File

@ -10,7 +10,7 @@ and by the historical game Lunar Lander.
- Craft TA4 Jetpack, Jetpack Controller and Training Mat - Craft TA4 Jetpack, Jetpack Controller and Training Mat
- Use the armor extension (3d_armor) of the player menu to strap the Jetpack on your back - Use the armor extension (3d_armor) of the player menu to strap the Jetpack on your back
- You can refuel the jetpack by left-clicking with the controller on a hydrogen tank - You can refuel the jetpack by left-clicking with the controller on a TA3/TA4 tank previously charged with hydrogen
- Turn the controller on by right-click and check the fuel tank level (the small colored bar below the controller icon) - Turn the controller on by right-click and check the fuel tank level (the small colored bar below the controller icon)
- Use the space bar to activate the Jetpack and the WASD keys to control the direction - Use the space bar to activate the Jetpack and the WASD keys to control the direction
- Before your first flight you should do some training starts and landings on the Training Mat - Before your first flight you should do some training starts and landings on the Training Mat

View File

@ -0,0 +1,43 @@
local M = minetest.get_meta
minetest.register_node("techage:testblock", {
description = "Testblock",
tiles = {
"techage_top_ta4.png",
"techage_filling_ta4.png^techage_frame_ta4.png",
},
paramtype2 = "facedir",
groups = {cracky=2, crumbly=2, choppy=2},
is_ground_content = false,
after_place_node = function(pos, placer)
local nvm = techage.get_nvm(pos)
nvm.test_val = 1
M(pos):set_int("test_val", 1)
M(pos):set_string("infotext", "Value = " .. 1)
end,
})
minetest.register_lbm({
label = "Update testblock",
name = "techage:update_testblock",
nodenames = {
"techage:testblock",
},
run_at_every_load = true,
action = function(pos, node)
local nvm = techage.get_nvm(pos)
if M(pos):get_int("test_val") == nvm.test_val then
nvm.test_val = nvm.test_val + 1
M(pos):set_int("test_val", nvm.test_val)
M(pos):set_string("infotext", "Value = " .. nvm.test_val)
else
minetest.log("error", "[techage] Memory error at " .. minetest.pos_to_string(pos))
M(pos):set_string("infotext", "Error")
end
end,
})

View File

@ -336,7 +336,7 @@ local function entity_to_node(pos, obj)
meta:set_string("ta_move_block", minetest.serialize({name=name, param2=param2})) meta:set_string("ta_move_block", minetest.serialize({name=name, param2=param2}))
return return
end end
minetest.add_item(pos, ItemStack(name)) --minetest.add_item(pos, ItemStack(name))
elseif ndef1 then elseif ndef1 then
minetest.add_item(pos, ItemStack(name)) minetest.add_item(pos, ItemStack(name))
end end

View File

@ -97,7 +97,9 @@ minetest.register_globalstep(function(dtime)
SystemTime = SystemTime + dtime SystemTime = SystemTime + dtime
local key = pop() local key = pop()
if key and NvmStore[key] then if key and NvmStore[key] then
--debug(key, NvmStore[key]) -- minetest.log("warning",
-- string.format("[TA Storage] SystemTime = %.3f, #JobQueue = %d, in_use = %s",
-- SystemTime, last - first, NvmStore[key].in_use))
local t = minetest.get_us_time() local t = minetest.get_us_time()
if NvmStore[key].in_use then if NvmStore[key].in_use then
NvmStore[key].in_use = nil NvmStore[key].in_use = nil

View File

@ -20,6 +20,7 @@ local M = minetest.get_meta
------------------------------------------------------------------- -------------------------------------------------------------------
local MN = minetest.get_current_modname() local MN = minetest.get_current_modname()
local WP = minetest.get_worldpath() local WP = minetest.get_worldpath()
local use_marshal = minetest.settings:get_bool('techage_use_marshal', false)
local MAR_MAGIC = 0x8e local MAR_MAGIC = 0x8e
if not techage.IE then if not techage.IE then
@ -55,7 +56,6 @@ local function set_block(key, data)
set:bind(1, key) set:bind(1, key)
set:bind_blob(2, data) set:bind_blob(2, data)
set:step() set:step()
return true
end end
local function get_block(key) local function get_block(key)
@ -72,10 +72,11 @@ end
local api = {} local api = {}
function api.store_mapblock_data(key, mapblock_data) function api.store_mapblock_data(key, mapblock_data)
-- deactivated due to weird server crashes without error logs if use_marshal then
--local s = marshal.encode(mapblock_data) set_block(key, marshal.encode(mapblock_data))
local s = minetest.serialize(mapblock_data) else
return set_block(key, s) set_block(key, minetest.serialize(mapblock_data))
end
end end
function api.get_mapblock_data(key) function api.get_mapblock_data(key)

View File

@ -1800,7 +1800,7 @@ techage.manual_DE.aText = {
"Ein Teilchenbeschleuniger besteht aus einem \"Ring\" aus Röhren und Magneten sowie dem Detektor mit Kühlanlage. \n".. "Ein Teilchenbeschleuniger besteht aus einem \"Ring\" aus Röhren und Magneten sowie dem Detektor mit Kühlanlage. \n"..
"\n".. "\n"..
" - Der Detektor ist das Herz der Anlage. Hier finden die wissenschaftlichen Experimente statt. Der Detektor ist 3x3x7 Blöcke groß.\n".. " - Der Detektor ist das Herz der Anlage. Hier finden die wissenschaftlichen Experimente statt. Der Detektor ist 3x3x7 Blöcke groß.\n"..
" - Die TA4 Collider Detector Magnete (22 Stück) müssen über jeweils 5 Blöcken der TA4 Vakuumröhre miteinander verbunden werden. Jeder Magnet benötigt zusätzlich Strom und einen Gasanschluss für die Kühlung. Das ganze bildet (wie rechts im Plan abgebildet) ein Quadrat mit einer Kantenlänge von 37 Metern.\n".. " - 22 TA4 Collider Magnete (nicht die TA4 Collider Detector Magnete!) müssen über jeweils 5 Blöcken der TA4 Vakuumröhre miteinander verbunden werden. Jeder Magnet benötigt zusätzlich Strom und einen Gasanschluss für die Kühlung. Das ganze bildet (wie rechts im Plan abgebildet) ein Quadrat mit einer Kantenlänge von 37 Metern.\n"..
" - Zusätzlich wird eine Kühlung benötigt\\, welche zusätzlich beim Detektor aufgebaut werden muss. Für die Kühlung wird Isobutan benötigt.\n".. " - Zusätzlich wird eine Kühlung benötigt\\, welche zusätzlich beim Detektor aufgebaut werden muss. Für die Kühlung wird Isobutan benötigt.\n"..
" - Die Anlage benötigt einiges an Strom. Daher ist eine eigene Stromversorgung sinnvoll.\n".. " - Die Anlage benötigt einiges an Strom. Daher ist eine eigene Stromversorgung sinnvoll.\n"..
"\n".. "\n"..

View File

@ -1796,7 +1796,7 @@ techage.manual_EN.aText = {
"A collider consists of a \"ring\" made of tubes and magnets as well as a detector with a cooling system.\n".. "A collider consists of a \"ring\" made of tubes and magnets as well as a detector with a cooling system.\n"..
"\n".. "\n"..
" - The detector is the heart of the system. This is where the scientific experiments take place. The detector is 3x3x7 blocks in size.\n".. " - The detector is the heart of the system. This is where the scientific experiments take place. The detector is 3x3x7 blocks in size.\n"..
" - The TA4 Collider Detector magnets (22 pieces) must be connected to each other via 5 blocks of the TA4 vacuum tube. Each magnet also requires electricity and a gas connection for cooling. The whole thing forms (as shown in the plan on the right) a square with an edge length of 37 meters.\n".. " - 22 TA4 Collider Magnets (not the TA4 Collider Detector Magnets!) must be connected to each other via 5 blocks of the TA4 vacuum tube. Each magnet also requires electricity and a gas connection for cooling. The whole thing forms (as shown in the plan on the right) a square with an edge length of 37 meters.\n"..
" - In addition\\, cooling is required\\, which must also be installed at the detector. Isobutane is required for cooling.\n".. " - In addition\\, cooling is required\\, which must also be installed at the detector. Isobutane is required for cooling.\n"..
" - The system requires quite a bit of electricity. Therefore\\, it makes sense to have your own power supply.\n".. " - The system requires quite a bit of electricity. Therefore\\, it makes sense to have your own power supply.\n"..
"\n".. "\n"..

View File

@ -56,6 +56,7 @@ techage.basalt_stone_enabled = minetest.settings:get_bool("techage_basalt_stone_
techage.ore_rarity = tonumber(minetest.settings:get("techage_ore_rarity")) or 1 techage.ore_rarity = tonumber(minetest.settings:get("techage_ore_rarity")) or 1
techage.modified_recipes_enabled = minetest.settings:get_bool("techage_modified_recipes_enabled") ~= false techage.modified_recipes_enabled = minetest.settings:get_bool("techage_modified_recipes_enabled") ~= false
techage.collider_min_depth = tonumber(minetest.settings:get("techage_collider_min_depth")) or -28 techage.collider_min_depth = tonumber(minetest.settings:get("techage_collider_min_depth")) or -28
techage.recipe_checker_enabled = minetest.settings:get_bool("techage_recipe_checker_enabled") ~= false
-- allow to load marshal and sqlite3 -- allow to load marshal and sqlite3
techage.IE = minetest.request_insecure_environment() techage.IE = minetest.request_insecure_environment()
@ -310,8 +311,11 @@ dofile(MP.."/move_controller/soundblock.lua")
-- Test -- Test
dofile(MP.."/recipe_checker.lua") if techage.recipe_checker_enabled then
dofile(MP.."/recipe_checker.lua")
end
dofile(MP.."/.test/sink.lua") dofile(MP.."/.test/sink.lua")
dofile(MP.."/.test/testblock.lua")
-- Solar -- Solar
dofile(MP.."/solar/minicell.lua") dofile(MP.."/solar/minicell.lua")

View File

@ -692,7 +692,7 @@ Pro Spieler kann nur ein Teilchenbeschleuniger betrieben werden. Es macht also k
Ein Teilchenbeschleuniger besteht aus einem "Ring" aus Röhren und Magneten sowie dem Detektor mit Kühlanlage. Ein Teilchenbeschleuniger besteht aus einem "Ring" aus Röhren und Magneten sowie dem Detektor mit Kühlanlage.
- Der Detektor ist das Herz der Anlage. Hier finden die wissenschaftlichen Experimente statt. Der Detektor ist 3x3x7 Blöcke groß. - Der Detektor ist das Herz der Anlage. Hier finden die wissenschaftlichen Experimente statt. Der Detektor ist 3x3x7 Blöcke groß.
- Die TA4 Collider Detector Magnete (22 Stück) müssen über jeweils 5 Blöcken der TA4 Vakuumröhre miteinander verbunden werden. Jeder Magnet benötigt zusätzlich Strom und einen Gasanschluss für die Kühlung. Das ganze bildet (wie rechts im Plan abgebildet) ein Quadrat mit einer Kantenlänge von 37 Metern. - 22 TA4 Collider Magnete (nicht die TA4 Collider Detector Magnete!) müssen über jeweils 5 Blöcken der TA4 Vakuumröhre miteinander verbunden werden. Jeder Magnet benötigt zusätzlich Strom und einen Gasanschluss für die Kühlung. Das ganze bildet (wie rechts im Plan abgebildet) ein Quadrat mit einer Kantenlänge von 37 Metern.
- Zusätzlich wird eine Kühlung benötigt, welche zusätzlich beim Detektor aufgebaut werden muss. Für die Kühlung wird Isobutan benötigt. - Zusätzlich wird eine Kühlung benötigt, welche zusätzlich beim Detektor aufgebaut werden muss. Für die Kühlung wird Isobutan benötigt.
- Die Anlage benötigt einiges an Strom. Daher ist eine eigene Stromversorgung sinnvoll. - Die Anlage benötigt einiges an Strom. Daher ist eine eigene Stromversorgung sinnvoll.

View File

@ -684,7 +684,7 @@ Only one collider can be operated per player. So it makes no sense to set up two
A collider consists of a "ring" made of tubes and magnets as well as a detector with a cooling system. A collider consists of a "ring" made of tubes and magnets as well as a detector with a cooling system.
- The detector is the heart of the system. This is where the scientific experiments take place. The detector is 3x3x7 blocks in size. - The detector is the heart of the system. This is where the scientific experiments take place. The detector is 3x3x7 blocks in size.
- The TA4 Collider Detector magnets (22 pieces) must be connected to each other via 5 blocks of the TA4 vacuum tube. Each magnet also requires electricity and a gas connection for cooling. The whole thing forms (as shown in the plan on the right) a square with an edge length of 37 meters. - 22 TA4 Collider Magnets (not the TA4 Collider Detector Magnets!) must be connected to each other via 5 blocks of the TA4 vacuum tube. Each magnet also requires electricity and a gas connection for cooling. The whole thing forms (as shown in the plan on the right) a square with an edge length of 37 meters.
- In addition, cooling is required, which must also be installed at the detector. Isobutane is required for cooling. - In addition, cooling is required, which must also be installed at the detector. Isobutane is required for cooling.
- The system requires quite a bit of electricity. Therefore, it makes sense to have your own power supply. - The system requires quite a bit of electricity. Therefore, it makes sense to have your own power supply.

View File

@ -274,9 +274,9 @@ techage.register_node({"techage:ta4_movecontroller"}, {
end end
elseif move_xyz and topic == 18 then -- move xyz elseif move_xyz and topic == 18 then -- move xyz
local line = { local line = {
x = techage.in_range(techage.beduino_signed_var(payload[1]), -10, 10), x = techage.in_range(techage.beduino_signed_var(payload[1]), -100, 100),
y = techage.in_range(techage.beduino_signed_var(payload[2]), -10, 10), y = techage.in_range(techage.beduino_signed_var(payload[2]), -100, 100),
z = techage.in_range(techage.beduino_signed_var(payload[3]), -10, 10), z = techage.in_range(techage.beduino_signed_var(payload[3]), -100, 100),
} }
nvm.running = true nvm.running = true
nvm.controller_mode = true nvm.controller_mode = true

View File

@ -200,6 +200,7 @@ minetest.register_node("techage:power_pole2", {
if not Cable:after_place_tube(pos, placer, pointed_thing) then if not Cable:after_place_tube(pos, placer, pointed_thing) then
minetest.chat_send_player(placer:get_player_name(), "invalid pole position ") minetest.chat_send_player(placer:get_player_name(), "invalid pole position ")
minetest.remove_node(pos) minetest.remove_node(pos)
Cable:after_dig_node(pos)
return true return true
end end
return false return false

View File

@ -3,6 +3,7 @@
-- --
local Recipes = {} local Recipes = {}
local function recipe_key(items) local function recipe_key(items)
local tbl = {} local tbl = {}
for idx = 1,9 do for idx = 1,9 do
@ -34,3 +35,5 @@ minetest.after(1, function()
end end
end end
end) end)
print ("[techage] Recipe checker loaded")

View File

@ -37,4 +37,7 @@ techage_collider_min_depth (Min. depth to build a TA4 Collider) int -30
# Average waiting time in minutes to get one Collider expoint. # Average waiting time in minutes to get one Collider expoint.
# Default value is 60, which means one point per hour. # Default value is 60, which means one point per hour.
techage_expoint_rate_in_min (average waiting time for one expoint) int 60 techage_expoint_rate_in_min (average waiting time for one expoint) int 60
# For testing purpuses only
techage_recipe_checker_enabled (test techage recipes) bool false

View File

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

View File

@ -1,2 +0,0 @@
Simple stairways and bridges for your machines.

View File

@ -1,2 +1,4 @@
name=techpack_stairway name=techpack_stairway
title=Techpack stairway
description=Simple stairways and bridges for your machines.
depends=default

View File

@ -7,17 +7,17 @@ Bag @1=背包@1
Small Bag=小背包 Small Bag=小背包
Medium Bag=中背包 Medium Bag=中背包
Large Bag=大背包 Large Bag=大背包
All Items= All Items=所有物品
Misc. Items= Misc. Items=杂项
Plant Life= Plant Life=植物
Building Materials= Building Materials=建材
Tools= Tools=工具
Minerals and Metals= Minerals and Metals=矿物与金属
Environment and Worldgen= Environment and Worldgen=自然环境
Lighting= Lighting=光源
and = 和 and = 和
Scroll categories left= Scroll categories left=向左滚动分类栏
Scroll categories right= Scroll categories right=向右滚动分类栏
Search=搜索 Search=搜索
Reset search and display everything=重置搜索并显示所有物品 Reset search and display everything=重置搜索并显示所有物品
First page=第一页 First page=第一页
@ -32,7 +32,7 @@ Page=页面
@1 of @2=第@1页共@2页 @1 of @2=第@1页共@2页
Filter=过滤器 Filter=过滤器
Can use the creative inventory=可以使用创造背包 Can use the creative inventory=可以使用创造背包
Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally= Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=如果轻量模式被全局配置强迫Unified Inventory以完全模式展现。
Crafting Grid=合成表 Crafting Grid=合成表
Crafting Guide=合成指南 Crafting Guide=合成指南
Set home position=设置家的位置 Set home position=设置家的位置
@ -45,7 +45,7 @@ You don't have the settime privilege!=你没有“settime”权限
Set time to night=设置时间到晚上 Set time to night=设置时间到晚上
Time of day set to 9pm=时间设置到晚上9点 Time of day set to 9pm=时间设置到晚上9点
Clear inventory=清空背包 Clear inventory=清空背包
This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.= This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=此按钮已在非创造模式中禁用以防止意外的背包清空。@n请使用垃圾桶栏。
Inventory cleared!=清空背包 Inventory cleared!=清空背包
Trash:=丢弃: Trash:=丢弃:
Refill:=填满: Refill:=填满:
@ -57,13 +57,13 @@ No recipes=没有配方
No usages=没有用法 No usages=没有用法
Result=结果 Result=结果
Ingredient=原料 Ingredient=原料
Show next recipe= Show next recipe=显示下一个配方
Show next usage= Show next usage=显示下一个用法
Show previous recipe= Show previous recipe=显示前一个配方
Show previous usage= Show previous usage=显示前一个用法
@1 (@2)= @1 (@2)=@1 (@2)
Give me:=给予: Give me:=给予:
This recipe is too@@large to be displayed.= This recipe is too@@large to be displayed.=该配方太@@大,不能显示。
To craft grid:=填充物品到合成表 To craft grid:=填充物品到合成表
All=全部 All=全部
Crafting=合成 Crafting=合成
@ -76,10 +76,10 @@ Waypoints=航路点
Select Waypoint #@1=查询航路点 #@1 Select Waypoint #@1=查询航路点 #@1
Waypoint @1=航路点 @1 Waypoint @1=航路点 @1
Set waypoint to current location=将航路点设置到当前位置 Set waypoint to current location=将航路点设置到当前位置
Hide waypoint= Hide waypoint=隐藏航路点
Show waypoint= Show waypoint=显示航路点
Hide coordinates= Hide coordinates=隐藏坐标
Show coordinates= Show coordinates=显示坐标
Change color of waypoint display=改变航路点显示的颜色 Change color of waypoint display=改变航路点显示的颜色
Edit waypoint name=编辑航路点名称 Edit waypoint name=编辑航路点名称
Waypoint active=航路点已激活 Waypoint active=航路点已激活

View File

@ -7,17 +7,17 @@ Bag @1=揹包@1
Small Bag=小揹包 Small Bag=小揹包
Medium Bag=中揹包 Medium Bag=中揹包
Large Bag=大揹包 Large Bag=大揹包
All Items= All Items=所有物品
Misc. Items= Misc. Items=雜項
Plant Life= Plant Life=植物
Building Materials= Building Materials=建材
Tools= Tools=工具
Minerals and Metals= Minerals and Metals=礦物與金屬
Environment and Worldgen= Environment and Worldgen=自然環境
Lighting= Lighting=光源
and = 和 and = 和
Scroll categories left= Scroll categories left=向左滾動分類欄
Scroll categories right= Scroll categories right=向右滾動分類欄
Search=搜索 Search=搜索
Reset search and display everything=重置搜索並顯示所有物品 Reset search and display everything=重置搜索並顯示所有物品
First page=第一頁 First page=第一頁
@ -32,7 +32,7 @@ Page=頁面
@1 of @2=第@1頁共@2頁 @1 of @2=第@1頁共@2頁
Filter=過濾器 Filter=過濾器
Can use the creative inventory=可以使用創造揹包 Can use the creative inventory=可以使用創造揹包
Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally= Forces Unified Inventory to be displayed in Full mode if Lite mode is configured globally=如果輕量模式被全局配置強迫Unified Inventory以完全模式展現。
Crafting Grid=合成表 Crafting Grid=合成表
Crafting Guide=合成指南 Crafting Guide=合成指南
Set home position=設置家的位置 Set home position=設置家的位置
@ -45,7 +45,7 @@ You don't have the settime privilege!=你沒有“settime”權限
Set time to night=設置時間到晚上 Set time to night=設置時間到晚上
Time of day set to 9pm=時間設置到晚上9點 Time of day set to 9pm=時間設置到晚上9點
Clear inventory=清空揹包 Clear inventory=清空揹包
This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.= This button has been disabled outside of creative mode to prevent accidental inventory trashing.@nUse the trash slot instead.=此按鈕已在非創造模式中禁用以防止意外的背包清空。@n請使用垃圾桶欄。
Inventory cleared!=清空揹包 Inventory cleared!=清空揹包
Trash:=丟棄: Trash:=丟棄:
Refill:=填滿: Refill:=填滿:
@ -57,13 +57,13 @@ No recipes=沒有配方
No usages=沒有用法 No usages=沒有用法
Result=結果 Result=結果
Ingredient=原料 Ingredient=原料
Show next recipe= Show next recipe=顯示下一個配方
Show next usage= Show next usage=顯示下一個用法
Show previous recipe= Show previous recipe=顯示上一個配方
Show previous usage= Show previous usage=顯示上一個用法
@1 (@2)= @1 (@2)=@1 (@2)
Give me:=給予: Give me:=給予:
This recipe is too@@large to be displayed.= This recipe is too@@large to be displayed.=該配方太@@大,不能顯示。
To craft grid:=填充物品到合成表 To craft grid:=填充物品到合成表
All=全部 All=全部
Crafting=合成 Crafting=合成
@ -76,10 +76,10 @@ Waypoints=航路點
Select Waypoint #@1=查詢航路點 #@1 Select Waypoint #@1=查詢航路點 #@1
Waypoint @1=航路點 @1 Waypoint @1=航路點 @1
Set waypoint to current location=將航路點設置到當前位置 Set waypoint to current location=將航路點設置到當前位置
Hide waypoint= Hide waypoint=隱藏航路點
Show waypoint= Show waypoint=顯示航路點
Hide coordinates= Hide coordinates=隱藏坐標
Show coordinates= Show coordinates=顯示坐標
Change color of waypoint display=改變航路點顯示的顏色 Change color of waypoint display=改變航路點顯示的顏色
Edit waypoint name=編輯航路點名稱 Edit waypoint name=編輯航路點名稱
Waypoint active=航路點已激活 Waypoint active=航路點已激活