diff --git a/android/src/mindustry/android/AndroidLauncher.java b/android/src/mindustry/android/AndroidLauncher.java index 6c0a695000..561ce0b998 100644 --- a/android/src/mindustry/android/AndroidLauncher.java +++ b/android/src/mindustry/android/AndroidLauncher.java @@ -150,10 +150,22 @@ public class AndroidLauncher extends AndroidApplication{ }}); checkFiles(getIntent()); + //new external folder Fi data = Core.files.absolute(getContext().getExternalFilesDir(null).getAbsolutePath()); + Core.settings.setDataDirectory(data); - //moved to internal storage if there's no file indicating that it moved + //delete old external files due to screwup + if(Core.files.local("files_moved").exists() && !Core.files.local("files_moved_103").exists()){ + for(Fi fi : data.list()){ + fi.deleteDirectory(); + } + + Core.files.local("files_moved").delete(); + Core.files.local("files_moved_103").writeString("files moved again"); + } + + //move to internal storage if there's no file indicating that it moved if(!Core.files.local("files_moved").exists()){ Log.info("Moving files to external storage..."); @@ -161,7 +173,7 @@ public class AndroidLauncher extends AndroidApplication{ //current local storage folder Fi src = Core.files.absolute(Core.files.getLocalStoragePath()); for(Fi fi : src.list()){ - fi.copyTo(data.child(fi.name())); + fi.copyTo(data); } //create marker Core.files.local("files_moved").writeString("files moved to " + data); @@ -170,8 +182,6 @@ public class AndroidLauncher extends AndroidApplication{ Log.err("Failed to move files!"); t.printStackTrace(); } - }else{ - Core.settings.setDataDirectory(data); } } diff --git a/annotations/src/main/java/mindustry/annotations/BaseProcessor.java b/annotations/src/main/java/mindustry/annotations/BaseProcessor.java index f9a83c80fd..effbb72400 100644 --- a/annotations/src/main/java/mindustry/annotations/BaseProcessor.java +++ b/annotations/src/main/java/mindustry/annotations/BaseProcessor.java @@ -3,6 +3,7 @@ package mindustry.annotations; import javax.annotation.processing.*; import javax.lang.model.*; import javax.lang.model.element.*; +import javax.lang.model.util.*; import java.util.*; @SupportedSourceVersion(SourceVersion.RELEASE_8) @@ -10,20 +11,34 @@ public abstract class BaseProcessor extends AbstractProcessor{ /** Name of the base package to put all the generated classes. */ public static final String packageName = "mindustry.gen"; - private int round; + public static Types typeu; + public static Elements elementu; + public static Filer filer; + public static Messager messager; + + protected int round; + + public static String getMethodName(Element element){ + return ((TypeElement)element.getEnclosingElement()).getQualifiedName().toString() + "." + element.getSimpleName(); + } + + public static boolean isPrimitive(String type){ + return type.equals("boolean") || type.equals("byte") || type.equals("short") || type.equals("int") + || type.equals("long") || type.equals("float") || type.equals("double") || type.equals("char"); + } @Override public synchronized void init(ProcessingEnvironment processingEnv){ super.init(processingEnv); - //put all relevant utils into utils class - Utils.typeUtils = processingEnv.getTypeUtils(); - Utils.elementUtils = processingEnv.getElementUtils(); - Utils.filer = processingEnv.getFiler(); - Utils.messager = processingEnv.getMessager(); + + typeu = processingEnv.getTypeUtils(); + elementu = processingEnv.getElementUtils(); + filer = processingEnv.getFiler(); + messager = processingEnv.getMessager(); } @Override - public final boolean process(Set annotations, RoundEnvironment roundEnv){ + public boolean process(Set annotations, RoundEnvironment roundEnv){ if(round++ != 0) return false; //only process 1 round try{ process(roundEnv); @@ -39,5 +54,7 @@ public abstract class BaseProcessor extends AbstractProcessor{ return SourceVersion.RELEASE_8; } - public abstract void process(RoundEnvironment env) throws Exception; + public void process(RoundEnvironment env) throws Exception{ + + } } diff --git a/annotations/src/main/java/mindustry/annotations/CallSuperAnnotationProcessor.java b/annotations/src/main/java/mindustry/annotations/CallSuperAnnotationProcessor.java deleted file mode 100644 index 01a3fdb0e1..0000000000 --- a/annotations/src/main/java/mindustry/annotations/CallSuperAnnotationProcessor.java +++ /dev/null @@ -1,62 +0,0 @@ -package mindustry.annotations; - -import com.sun.source.util.*; -import com.sun.tools.javac.tree.*; -import com.sun.tools.javac.tree.JCTree.*; -import mindustry.annotations.Annotations.*; - -import javax.annotation.processing.*; -import javax.lang.model.*; -import javax.lang.model.element.*; -import javax.tools.Diagnostic.*; -import java.util.*; - -@SupportedAnnotationTypes({"java.lang.Override"}) -public class CallSuperAnnotationProcessor extends AbstractProcessor{ - private Trees trees; - - @Override - public void init(ProcessingEnvironment pe){ - super.init(pe); - trees = Trees.instance(pe); - } - - public boolean process(Set annotations, RoundEnvironment roundEnv){ - for(Element e : roundEnv.getElementsAnnotatedWith(Override.class)){ - if(e.getAnnotation(OverrideCallSuper.class) != null) return false; - - CodeAnalyzerTreeScanner codeScanner = new CodeAnalyzerTreeScanner(); - codeScanner.setMethodName(e.getSimpleName().toString()); - - TreePath tp = trees.getPath(e.getEnclosingElement()); - codeScanner.scan(tp, trees); - - if(codeScanner.isCallSuperUsed()){ - List list = codeScanner.getMethod().getBody().getStatements(); - - if(!doesCallSuper(list, codeScanner.getMethodName())){ - processingEnv.getMessager().printMessage(Kind.ERROR, "Overriding method '" + codeScanner.getMethodName() + "' must explicitly call super method from its parent class.", e); - } - } - } - - return false; - } - - private boolean doesCallSuper(List list, String methodName){ - for(Object object : list){ - if(object instanceof JCTree.JCExpressionStatement){ - JCTree.JCExpressionStatement expr = (JCExpressionStatement)object; - String exprString = expr.toString(); - if(exprString.startsWith("super." + methodName) && exprString.endsWith(");")) return true; - } - } - - return false; - } - - @Override - public SourceVersion getSupportedSourceVersion(){ - return SourceVersion.RELEASE_8; - } -} diff --git a/annotations/src/main/java/mindustry/annotations/CodeAnalyzerTreeScanner.java b/annotations/src/main/java/mindustry/annotations/CodeAnalyzerTreeScanner.java deleted file mode 100644 index 13059b38b8..0000000000 --- a/annotations/src/main/java/mindustry/annotations/CodeAnalyzerTreeScanner.java +++ /dev/null @@ -1,110 +0,0 @@ -package mindustry.annotations; - -import com.sun.source.tree.*; -import com.sun.source.util.TreePathScanner; -import com.sun.source.util.Trees; -import com.sun.tools.javac.code.Scope; -import com.sun.tools.javac.code.Symbol; -import com.sun.tools.javac.code.Symbol.MethodSymbol; -import com.sun.tools.javac.code.Type.ClassType; -import com.sun.tools.javac.tree.JCTree.JCIdent; -import com.sun.tools.javac.tree.JCTree.JCTypeApply; -import mindustry.annotations.Annotations.CallSuper; - -import java.lang.annotation.Annotation; - -class CodeAnalyzerTreeScanner extends TreePathScanner { - private String methodName; - private MethodTree method; - private boolean callSuperUsed; - - @Override - public Object visitClass (ClassTree classTree, Trees trees) { - Tree extendTree = classTree.getExtendsClause(); - - if (extendTree instanceof JCTypeApply) { //generic classes case - JCTypeApply generic = (JCTypeApply) extendTree; - extendTree = generic.clazz; - } - - if (extendTree instanceof JCIdent) { - JCIdent tree = (JCIdent) extendTree; - Scope members = tree.sym.members(); - - if (checkScope(members)) - return super.visitClass(classTree, trees); - - if (checkSuperTypes((ClassType) tree.type)) - return super.visitClass(classTree, trees); - - } - callSuperUsed = false; - - return super.visitClass(classTree, trees); - } - - public boolean checkSuperTypes (ClassType type) { - if (type.supertype_field != null && type.supertype_field.tsym != null) { - if (checkScope(type.supertype_field.tsym.members())) - return true; - else - return checkSuperTypes((ClassType) type.supertype_field); - } - - return false; - } - - @SuppressWarnings("unchecked") - public boolean checkScope (Scope members) { - Iterable it; - try{ - it = (Iterable)members.getClass().getMethod("getElements").invoke(members); - }catch(Throwable t){ - try{ - it = (Iterable)members.getClass().getMethod("getSymbols").invoke(members); - }catch(Exception e){ - throw new RuntimeException(e); - } - } - - for (Symbol s : it) { - if (s instanceof MethodSymbol) { - MethodSymbol ms = (MethodSymbol) s; - - if (ms.getSimpleName().toString().equals(methodName)) { - Annotation annotation = ms.getAnnotation(CallSuper.class); - if (annotation != null) { - callSuperUsed = true; - return true; - } - } - } - } - - return false; - } - - @Override - public Object visitMethod (MethodTree methodTree, Trees trees) { - if (methodTree.getName().toString().equals(methodName)) - method = methodTree; - - return super.visitMethod(methodTree, trees); - } - - public void setMethodName (String methodName) { - this.methodName = methodName; - } - - public String getMethodName () { - return methodName; - } - - public MethodTree getMethod () { - return method; - } - - public boolean isCallSuperUsed () { - return callSuperUsed; - } -} \ No newline at end of file diff --git a/annotations/src/main/java/mindustry/annotations/Utils.java b/annotations/src/main/java/mindustry/annotations/Utils.java deleted file mode 100644 index 773d6561d2..0000000000 --- a/annotations/src/main/java/mindustry/annotations/Utils.java +++ /dev/null @@ -1,24 +0,0 @@ -package mindustry.annotations; - -import javax.annotation.processing.Filer; -import javax.annotation.processing.Messager; -import javax.lang.model.element.Element; -import javax.lang.model.element.TypeElement; -import javax.lang.model.util.Elements; -import javax.lang.model.util.Types; - -public class Utils{ - public static Types typeUtils; - public static Elements elementUtils; - public static Filer filer; - public static Messager messager; - - public static String getMethodName(Element element){ - return ((TypeElement)element.getEnclosingElement()).getQualifiedName().toString() + "." + element.getSimpleName(); - } - - public static boolean isPrimitive(String type){ - return type.equals("boolean") || type.equals("byte") || type.equals("short") || type.equals("int") - || type.equals("long") || type.equals("float") || type.equals("double") || type.equals("char"); - } -} diff --git a/annotations/src/main/java/mindustry/annotations/AssetsAnnotationProcessor.java b/annotations/src/main/java/mindustry/annotations/impl/AssetsAnnotationProcessor.java similarity index 94% rename from annotations/src/main/java/mindustry/annotations/AssetsAnnotationProcessor.java rename to annotations/src/main/java/mindustry/annotations/impl/AssetsAnnotationProcessor.java index 0ef33f671d..2ac95b7b40 100644 --- a/annotations/src/main/java/mindustry/annotations/AssetsAnnotationProcessor.java +++ b/annotations/src/main/java/mindustry/annotations/impl/AssetsAnnotationProcessor.java @@ -1,10 +1,11 @@ -package mindustry.annotations; +package mindustry.annotations.impl; import arc.files.*; import arc.scene.style.*; import arc.struct.*; import arc.util.serialization.*; import com.squareup.javapoet.*; +import mindustry.annotations.*; import mindustry.annotations.Annotations.*; import javax.annotation.processing.*; @@ -20,7 +21,7 @@ public class AssetsAnnotationProcessor extends BaseProcessor{ @Override public void process(RoundEnvironment env) throws Exception{ - path = Fi.get(Utils.filer.createResource(StandardLocation.CLASS_OUTPUT, "no", "no") + path = Fi.get(BaseProcessor.filer.createResource(StandardLocation.CLASS_OUTPUT, "no", "no") .toUri().toURL().toString().substring(System.getProperty("os.name").contains("Windows") ? 6 : "file:".length())) .parent().parent().parent().parent().parent().parent().toString(); path = path.replace("%20", " "); @@ -85,12 +86,12 @@ public class AssetsAnnotationProcessor extends BaseProcessor{ } ictype.addMethod(icload.build()); - JavaFile.builder(packageName, ichtype.build()).build().writeTo(Utils.filer); - JavaFile.builder(packageName, ictype.build()).build().writeTo(Utils.filer); + JavaFile.builder(packageName, ichtype.build()).build().writeTo(BaseProcessor.filer); + JavaFile.builder(packageName, ictype.build()).build().writeTo(BaseProcessor.filer); type.addMethod(load.build()); type.addMethod(loadStyles.build()); - JavaFile.builder(packageName, type.build()).build().writeTo(Utils.filer); + JavaFile.builder(packageName, type.build()).build().writeTo(BaseProcessor.filer); } void processSounds(String classname, String path, String rtype) throws Exception{ @@ -104,7 +105,7 @@ public class AssetsAnnotationProcessor extends BaseProcessor{ String name = p.nameWithoutExtension(); if(names.contains(name)){ - Utils.messager.printMessage(Kind.ERROR, "Duplicate file name: " + p.toString() + "!"); + BaseProcessor.messager.printMessage(Kind.ERROR, "Duplicate file name: " + p.toString() + "!"); }else{ names.add(name); } @@ -130,7 +131,7 @@ public class AssetsAnnotationProcessor extends BaseProcessor{ type.addMethod(loadBegin.build()); type.addMethod(dispose.build()); - JavaFile.builder(packageName, type.build()).build().writeTo(Utils.filer); + JavaFile.builder(packageName, type.build()).build().writeTo(BaseProcessor.filer); } static String capitalize(String s){ diff --git a/annotations/src/main/java/mindustry/annotations/impl/CallSuperAnnotationProcessor.java b/annotations/src/main/java/mindustry/annotations/impl/CallSuperAnnotationProcessor.java new file mode 100644 index 0000000000..4815073331 --- /dev/null +++ b/annotations/src/main/java/mindustry/annotations/impl/CallSuperAnnotationProcessor.java @@ -0,0 +1,150 @@ +package mindustry.annotations.impl; + +import com.sun.source.tree.*; +import com.sun.source.util.*; +import com.sun.tools.javac.code.Scope; +import com.sun.tools.javac.code.*; +import com.sun.tools.javac.code.Symbol.*; +import com.sun.tools.javac.code.Type.*; +import com.sun.tools.javac.tree.*; +import com.sun.tools.javac.tree.JCTree.*; +import mindustry.annotations.Annotations.*; + +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; +import javax.tools.Diagnostic.*; +import java.lang.annotation.*; +import java.util.*; + +@SupportedAnnotationTypes({"java.lang.Override"}) +public class CallSuperAnnotationProcessor extends AbstractProcessor{ + private Trees trees; + + @Override + public void init(ProcessingEnvironment pe){ + super.init(pe); + trees = Trees.instance(pe); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv){ + for(Element e : roundEnv.getElementsAnnotatedWith(Override.class)){ + if(e.getAnnotation(OverrideCallSuper.class) != null) return false; + + CodeAnalyzerTreeScanner codeScanner = new CodeAnalyzerTreeScanner(); + codeScanner.methodName = e.getSimpleName().toString(); + + TreePath tp = trees.getPath(e.getEnclosingElement()); + codeScanner.scan(tp, trees); + + if(codeScanner.callSuperUsed){ + List list = codeScanner.method.getBody().getStatements(); + + if(!doesCallSuper(list, codeScanner.methodName)){ + processingEnv.getMessager().printMessage(Kind.ERROR, "Overriding method '" + codeScanner.methodName + "' must explicitly call super method from its parent class.", e); + } + } + } + + return false; + } + + private boolean doesCallSuper(List list, String methodName){ + for(Object object : list){ + if(object instanceof JCTree.JCExpressionStatement){ + JCTree.JCExpressionStatement expr = (JCExpressionStatement)object; + String exprString = expr.toString(); + if(exprString.startsWith("super." + methodName) && exprString.endsWith(");")) return true; + } + } + + return false; + } + + @Override + public SourceVersion getSupportedSourceVersion(){ + return SourceVersion.RELEASE_8; + } + + static class CodeAnalyzerTreeScanner extends TreePathScanner{ + private String methodName; + private MethodTree method; + private boolean callSuperUsed; + + @Override + public Object visitClass(ClassTree classTree, Trees trees){ + Tree extendTree = classTree.getExtendsClause(); + + if(extendTree instanceof JCTypeApply){ //generic classes case + JCTypeApply generic = (JCTypeApply)extendTree; + extendTree = generic.clazz; + } + + if(extendTree instanceof JCIdent){ + JCIdent tree = (JCIdent)extendTree; + com.sun.tools.javac.code.Scope members = tree.sym.members(); + + if(checkScope(members)) + return super.visitClass(classTree, trees); + + if(checkSuperTypes((ClassType)tree.type)) + return super.visitClass(classTree, trees); + + } + callSuperUsed = false; + + return super.visitClass(classTree, trees); + } + + public boolean checkSuperTypes(ClassType type){ + if(type.supertype_field != null && type.supertype_field.tsym != null){ + if(checkScope(type.supertype_field.tsym.members())) + return true; + else + return checkSuperTypes((ClassType)type.supertype_field); + } + + return false; + } + + @SuppressWarnings("unchecked") + public boolean checkScope(Scope members){ + Iterable it; + try{ + it = (Iterable)members.getClass().getMethod("getElements").invoke(members); + }catch(Throwable t){ + try{ + it = (Iterable)members.getClass().getMethod("getSymbols").invoke(members); + }catch(Exception e){ + throw new RuntimeException(e); + } + } + + for(Symbol s : it){ + if(s instanceof MethodSymbol){ + MethodSymbol ms = (MethodSymbol)s; + + if(ms.getSimpleName().toString().equals(methodName)){ + Annotation annotation = ms.getAnnotation(CallSuper.class); + if(annotation != null){ + callSuperUsed = true; + return true; + } + } + } + } + + return false; + } + + @Override + public Object visitMethod(MethodTree methodTree, Trees trees){ + if(methodTree.getName().toString().equals(methodName)) + method = methodTree; + + return super.visitMethod(methodTree, trees); + } + + } +} diff --git a/annotations/src/main/java/mindustry/annotations/SerializeAnnotationProcessor.java b/annotations/src/main/java/mindustry/annotations/impl/SerializeAnnotationProcessor.java similarity index 93% rename from annotations/src/main/java/mindustry/annotations/SerializeAnnotationProcessor.java rename to annotations/src/main/java/mindustry/annotations/impl/SerializeAnnotationProcessor.java index 16ebcc9ead..3d07b2abce 100644 --- a/annotations/src/main/java/mindustry/annotations/SerializeAnnotationProcessor.java +++ b/annotations/src/main/java/mindustry/annotations/impl/SerializeAnnotationProcessor.java @@ -1,14 +1,14 @@ -package mindustry.annotations; +package mindustry.annotations.impl; import com.squareup.javapoet.*; +import mindustry.annotations.*; import mindustry.annotations.Annotations.*; +import mindustry.annotations.remote.*; import javax.annotation.processing.*; -import javax.lang.model.*; import javax.lang.model.element.Modifier; import javax.lang.model.element.*; import javax.lang.model.util.*; -import javax.tools.Diagnostic.*; import java.io.*; import java.lang.reflect.*; import java.util.*; @@ -55,13 +55,13 @@ public class SerializeAnnotationProcessor extends BaseProcessor{ readMethod.addStatement("$L object = new $L()", type, type); - List fields = ElementFilter.fieldsIn(Utils.elementUtils.getAllMembers(elem)); + List fields = ElementFilter.fieldsIn(BaseProcessor.elementu.getAllMembers(elem)); for(VariableElement field : fields){ if(field.getModifiers().contains(Modifier.STATIC) || field.getModifiers().contains(Modifier.TRANSIENT) || field.getModifiers().contains(Modifier.PRIVATE)) continue; String name = field.getSimpleName().toString(); - String typeName = Utils.typeUtils.erasure(field.asType()).toString().replace('$', '.'); + String typeName = BaseProcessor.typeu.erasure(field.asType()).toString().replace('$', '.'); String capName = Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1); if(field.asType().getKind().isPrimitive()){ @@ -78,7 +78,7 @@ public class SerializeAnnotationProcessor extends BaseProcessor{ serializer.addMethod(writeMethod.build()); serializer.addMethod(readMethod.build()); - method.addStatement("arc.Core.settings.setSerializer($N, $L)", Utils.elementUtils.getBinaryName(elem).toString().replace('$', '.') + ".class", serializer.build()); + method.addStatement("arc.Core.settings.setSerializer($N, $L)", BaseProcessor.elementu.getBinaryName(elem).toString().replace('$', '.') + ".class", serializer.build()); name(writeMethod, "write" + simpleTypeName); name(readMethod, "read" + simpleTypeName); @@ -93,7 +93,7 @@ public class SerializeAnnotationProcessor extends BaseProcessor{ classBuilder.addMethod(method.build()); //write result - JavaFile.builder(packageName, classBuilder.build()).build().writeTo(Utils.filer); + JavaFile.builder(packageName, classBuilder.build()).build().writeTo(BaseProcessor.filer); } static void name(MethodSpec.Builder builder, String name){ diff --git a/annotations/src/main/java/mindustry/annotations/StructAnnotationProcessor.java b/annotations/src/main/java/mindustry/annotations/impl/StructAnnotationProcessor.java similarity index 95% rename from annotations/src/main/java/mindustry/annotations/StructAnnotationProcessor.java rename to annotations/src/main/java/mindustry/annotations/impl/StructAnnotationProcessor.java index 48d5cf33f0..e4387245c5 100644 --- a/annotations/src/main/java/mindustry/annotations/StructAnnotationProcessor.java +++ b/annotations/src/main/java/mindustry/annotations/impl/StructAnnotationProcessor.java @@ -1,11 +1,11 @@ -package mindustry.annotations; +package mindustry.annotations.impl; import com.squareup.javapoet.*; +import mindustry.annotations.*; import mindustry.annotations.Annotations.Struct; import mindustry.annotations.Annotations.StructField; import javax.annotation.processing.*; -import javax.lang.model.SourceVersion; import javax.lang.model.element.*; import javax.lang.model.type.TypeKind; import javax.lang.model.util.ElementFilter; @@ -29,7 +29,7 @@ public class StructAnnotationProcessor extends BaseProcessor{ for(TypeElement elem : elements){ if(!elem.getSimpleName().toString().endsWith("Struct")){ - Utils.messager.printMessage(Kind.ERROR, "All classes annotated with @Struct must have their class names end in 'Struct'.", elem); + BaseProcessor.messager.printMessage(Kind.ERROR, "All classes annotated with @Struct must have their class names end in 'Struct'.", elem); continue; } @@ -45,7 +45,7 @@ public class StructAnnotationProcessor extends BaseProcessor{ int structTotalSize = (structSize <= 8 ? 8 : structSize <= 16 ? 16 : structSize <= 32 ? 32 : 64); if(variables.size() == 0){ - Utils.messager.printMessage(Kind.ERROR, "making a struct with no fields is utterly pointles.", elem); + BaseProcessor.messager.printMessage(Kind.ERROR, "making a struct with no fields is utterly pointles.", elem); continue; } @@ -130,10 +130,10 @@ public class StructAnnotationProcessor extends BaseProcessor{ constructor.addStatement("return ($T)($L)", structType, cons.toString().substring(3)); classBuilder.addMethod(constructor.build()); - JavaFile.builder(packageName, classBuilder.build()).build().writeTo(Utils.filer); + JavaFile.builder(packageName, classBuilder.build()).build().writeTo(BaseProcessor.filer); }catch(IllegalArgumentException e){ e.printStackTrace(); - Utils.messager.printMessage(Kind.ERROR, e.getMessage(), elem); + BaseProcessor.messager.printMessage(Kind.ERROR, e.getMessage(), elem); } } diff --git a/annotations/src/main/java/mindustry/annotations/ClassEntry.java b/annotations/src/main/java/mindustry/annotations/remote/ClassEntry.java similarity index 90% rename from annotations/src/main/java/mindustry/annotations/ClassEntry.java rename to annotations/src/main/java/mindustry/annotations/remote/ClassEntry.java index 002dcac88c..3474eff468 100644 --- a/annotations/src/main/java/mindustry/annotations/ClassEntry.java +++ b/annotations/src/main/java/mindustry/annotations/remote/ClassEntry.java @@ -1,4 +1,4 @@ -package mindustry.annotations; +package mindustry.annotations.remote; import java.util.ArrayList; diff --git a/annotations/src/main/java/mindustry/annotations/IOFinder.java b/annotations/src/main/java/mindustry/annotations/remote/IOFinder.java similarity index 82% rename from annotations/src/main/java/mindustry/annotations/IOFinder.java rename to annotations/src/main/java/mindustry/annotations/remote/IOFinder.java index e586cbd4a8..16384f241a 100644 --- a/annotations/src/main/java/mindustry/annotations/IOFinder.java +++ b/annotations/src/main/java/mindustry/annotations/remote/IOFinder.java @@ -1,5 +1,6 @@ -package mindustry.annotations; +package mindustry.annotations.remote; +import mindustry.annotations.*; import mindustry.annotations.Annotations.ReadClass; import mindustry.annotations.Annotations.WriteClass; @@ -11,8 +12,8 @@ import java.util.HashMap; import java.util.Set; /** - * This class finds reader and writer methods annotated by the {@link Annotations.WriteClass} - * and {@link Annotations.ReadClass} annotations. + * This class finds reader and writer methods annotated by the {@link WriteClass} + * and {@link ReadClass} annotations. */ public class IOFinder{ @@ -34,21 +35,21 @@ public class IOFinder{ //make sure there's only one read method if(readers.stream().filter(elem -> getValue(elem.getAnnotation(ReadClass.class)).equals(typeName)).count() > 1){ - Utils.messager.printMessage(Kind.ERROR, "Multiple writer methods for type '" + typeName + "'", writer); + BaseProcessor.messager.printMessage(Kind.ERROR, "Multiple writer methods for type '" + typeName + "'", writer); } //make sure there's only one write method long count = readers.stream().filter(elem -> getValue(elem.getAnnotation(ReadClass.class)).equals(typeName)).count(); if(count == 0){ - Utils.messager.printMessage(Kind.ERROR, "Writer method does not have an accompanying reader: ", writer); + BaseProcessor.messager.printMessage(Kind.ERROR, "Writer method does not have an accompanying reader: ", writer); }else if(count > 1){ - Utils.messager.printMessage(Kind.ERROR, "Writer method has multiple reader for type: ", writer); + BaseProcessor.messager.printMessage(Kind.ERROR, "Writer method has multiple reader for type: ", writer); } Element reader = readers.stream().filter(elem -> getValue(elem.getAnnotation(ReadClass.class)).equals(typeName)).findFirst().get(); //add to result list - result.put(typeName, new ClassSerializer(Utils.getMethodName(reader), Utils.getMethodName(writer), typeName)); + result.put(typeName, new ClassSerializer(BaseProcessor.getMethodName(reader), BaseProcessor.getMethodName(writer), typeName)); } return result; diff --git a/annotations/src/main/java/mindustry/annotations/MethodEntry.java b/annotations/src/main/java/mindustry/annotations/remote/MethodEntry.java similarity index 98% rename from annotations/src/main/java/mindustry/annotations/MethodEntry.java rename to annotations/src/main/java/mindustry/annotations/remote/MethodEntry.java index 0010d4b4d4..68ea81dec0 100644 --- a/annotations/src/main/java/mindustry/annotations/MethodEntry.java +++ b/annotations/src/main/java/mindustry/annotations/remote/MethodEntry.java @@ -1,4 +1,4 @@ -package mindustry.annotations; +package mindustry.annotations.remote; import mindustry.annotations.Annotations.*; diff --git a/annotations/src/main/java/mindustry/annotations/RemoteMethodAnnotationProcessor.java b/annotations/src/main/java/mindustry/annotations/remote/RemoteMethodAnnotationProcessor.java similarity index 79% rename from annotations/src/main/java/mindustry/annotations/RemoteMethodAnnotationProcessor.java rename to annotations/src/main/java/mindustry/annotations/remote/RemoteMethodAnnotationProcessor.java index 2da9ddb35c..7f3acc0c86 100644 --- a/annotations/src/main/java/mindustry/annotations/RemoteMethodAnnotationProcessor.java +++ b/annotations/src/main/java/mindustry/annotations/remote/RemoteMethodAnnotationProcessor.java @@ -1,32 +1,28 @@ -package mindustry.annotations; +package mindustry.annotations.remote; import com.squareup.javapoet.*; -import mindustry.annotations.Annotations.Loc; -import mindustry.annotations.Annotations.Remote; -import mindustry.annotations.IOFinder.ClassSerializer; +import mindustry.annotations.*; +import mindustry.annotations.Annotations.*; +import mindustry.annotations.remote.IOFinder.*; import javax.annotation.processing.*; -import javax.lang.model.SourceVersion; import javax.lang.model.element.*; -import javax.tools.Diagnostic.Kind; +import javax.tools.Diagnostic.*; import java.util.*; -import java.util.stream.Collectors; +import java.util.stream.*; /** The annotation processor for generating remote method call code. */ -@SupportedSourceVersion(SourceVersion.RELEASE_8) @SupportedAnnotationTypes({ "mindustry.annotations.Annotations.Remote", "mindustry.annotations.Annotations.WriteClass", "mindustry.annotations.Annotations.ReadClass", }) -public class RemoteMethodAnnotationProcessor extends AbstractProcessor{ +public class RemoteMethodAnnotationProcessor extends BaseProcessor{ /** Maximum size of each event packet. */ public static final int maxPacketSize = 4096; /** Warning on top of each autogenerated file. */ public static final String autogenWarning = "Autogenerated file. Do not modify!\n"; - /** Name of the base package to put all the generated classes. */ - private static final String packageName = "mindustry.gen"; /** Name of class that handles reading and invoking packets on the server. */ private static final String readServerName = "RemoteReadServer"; @@ -35,9 +31,6 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor{ /** Simple class name of generated class name. */ private static final String callLocation = "Call"; - /** Processing round number. */ - private int round; - //class serializers private HashMap serializers; //all elements with the Remote annotation @@ -49,16 +42,6 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor{ //list of all method entries private ArrayList classes; - @Override - public synchronized void init(ProcessingEnvironment processingEnv){ - super.init(processingEnv); - //put all relevant utils into utils class - Utils.typeUtils = processingEnv.getTypeUtils(); - Utils.elementUtils = processingEnv.getElementUtils(); - Utils.filer = processingEnv.getFiler(); - Utils.messager = processingEnv.getMessager(); - } - @Override public boolean process(Set annotations, RoundEnvironment roundEnv){ if(round > 1) return false; //only process 2 rounds @@ -91,12 +74,12 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor{ //check for static if(!element.getModifiers().contains(Modifier.STATIC) || !element.getModifiers().contains(Modifier.PUBLIC)){ - Utils.messager.printMessage(Kind.ERROR, "All @Remote methods must be public and static: ", element); + BaseProcessor.messager.printMessage(Kind.ERROR, "All @Remote methods must be public and static: ", element); } //can't generate none methods if(annotation.targets() == Loc.none){ - Utils.messager.printMessage(Kind.ERROR, "A @Remote method's targets() cannot be equal to 'none':", element); + BaseProcessor.messager.printMessage(Kind.ERROR, "A @Remote method's targets() cannot be equal to 'none':", element); } //get and create class entry if needed @@ -109,7 +92,7 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor{ ClassEntry entry = classMap.get(callLocation); //create and add entry - MethodEntry method = new MethodEntry(entry.name, Utils.getMethodName(element), annotation.targets(), annotation.variants(), + MethodEntry method = new MethodEntry(entry.name, BaseProcessor.getMethodName(element), annotation.targets(), annotation.variants(), annotation.called(), annotation.unreliable(), annotation.forward(), lastMethodID++, (ExecutableElement)element, annotation.priority()); entry.methods.add(method); @@ -139,7 +122,7 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor{ //build and write resulting hash class TypeSpec spec = hashBuilder.build(); - JavaFile.builder(packageName, spec).build().writeTo(Utils.filer); + JavaFile.builder(packageName, spec).build().writeTo(BaseProcessor.filer); return true; } diff --git a/annotations/src/main/java/mindustry/annotations/RemoteReadGenerator.java b/annotations/src/main/java/mindustry/annotations/remote/RemoteReadGenerator.java similarity index 94% rename from annotations/src/main/java/mindustry/annotations/RemoteReadGenerator.java rename to annotations/src/main/java/mindustry/annotations/remote/RemoteReadGenerator.java index 166c7c5ce5..ab7abb2538 100644 --- a/annotations/src/main/java/mindustry/annotations/RemoteReadGenerator.java +++ b/annotations/src/main/java/mindustry/annotations/remote/RemoteReadGenerator.java @@ -1,7 +1,8 @@ -package mindustry.annotations; +package mindustry.annotations.remote; import com.squareup.javapoet.*; -import mindustry.annotations.IOFinder.ClassSerializer; +import mindustry.annotations.*; +import mindustry.annotations.remote.IOFinder.ClassSerializer; import javax.lang.model.element.*; import javax.tools.Diagnostic.Kind; @@ -82,7 +83,7 @@ public class RemoteReadGenerator{ String capName = typeName.equals("byte") ? "" : Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1); //write primitives automatically - if(Utils.isPrimitive(typeName)){ + if(BaseProcessor.isPrimitive(typeName)){ if(typeName.equals("boolean")){ readBlock.addStatement("boolean " + varName + " = buffer.get() == 1"); }else{ @@ -93,7 +94,7 @@ public class RemoteReadGenerator{ ClassSerializer ser = serializers.get(typeName); if(ser == null){ //make sure a serializer exists! - Utils.messager.printMessage(Kind.ERROR, "No @ReadClass method to read class type: '" + typeName + "'", var); + BaseProcessor.messager.printMessage(Kind.ERROR, "No @ReadClass method to read class type: '" + typeName + "'", var); return; } @@ -139,6 +140,6 @@ public class RemoteReadGenerator{ //build and write resulting class TypeSpec spec = classBuilder.build(); - JavaFile.builder(packageName, spec).build().writeTo(Utils.filer); + JavaFile.builder(packageName, spec).build().writeTo(BaseProcessor.filer); } } diff --git a/annotations/src/main/java/mindustry/annotations/RemoteWriteGenerator.java b/annotations/src/main/java/mindustry/annotations/remote/RemoteWriteGenerator.java similarity index 93% rename from annotations/src/main/java/mindustry/annotations/RemoteWriteGenerator.java rename to annotations/src/main/java/mindustry/annotations/remote/RemoteWriteGenerator.java index dfe3f1fa00..19c5d73df3 100644 --- a/annotations/src/main/java/mindustry/annotations/RemoteWriteGenerator.java +++ b/annotations/src/main/java/mindustry/annotations/remote/RemoteWriteGenerator.java @@ -1,8 +1,9 @@ -package mindustry.annotations; +package mindustry.annotations.remote; import com.squareup.javapoet.*; +import mindustry.annotations.*; import mindustry.annotations.Annotations.Loc; -import mindustry.annotations.IOFinder.ClassSerializer; +import mindustry.annotations.remote.IOFinder.ClassSerializer; import javax.lang.model.element.*; import javax.tools.Diagnostic.Kind; @@ -52,7 +53,7 @@ public class RemoteWriteGenerator{ //build and write resulting class TypeSpec spec = classBuilder.build(); - JavaFile.builder(packageName, spec).build().writeTo(Utils.filer); + JavaFile.builder(packageName, spec).build().writeTo(BaseProcessor.filer); } } @@ -73,12 +74,12 @@ public class RemoteWriteGenerator{ //validate client methods to make sure if(methodEntry.where.isClient){ if(elem.getParameters().isEmpty()){ - Utils.messager.printMessage(Kind.ERROR, "Client invoke methods must have a first parameter of type Player.", elem); + BaseProcessor.messager.printMessage(Kind.ERROR, "Client invoke methods must have a first parameter of type Player.", elem); return; } if(!elem.getParameters().get(0).asType().toString().equals("mindustry.entities.type.Player")){ - Utils.messager.printMessage(Kind.ERROR, "Client invoke methods should have a first parameter of type Player.", elem); + BaseProcessor.messager.printMessage(Kind.ERROR, "Client invoke methods should have a first parameter of type Player.", elem); return; } } @@ -162,7 +163,7 @@ public class RemoteWriteGenerator{ method.beginControlFlow("if(mindustry.Vars.net.server())"); } - if(Utils.isPrimitive(typeName)){ //check if it's a primitive, and if so write it + if(BaseProcessor.isPrimitive(typeName)){ //check if it's a primitive, and if so write it if(typeName.equals("boolean")){ //booleans are special method.addStatement("TEMP_BUFFER.put(" + varName + " ? (byte)1 : 0)"); }else{ @@ -174,7 +175,7 @@ public class RemoteWriteGenerator{ ClassSerializer ser = serializers.get(typeName); if(ser == null){ //make sure a serializer exists! - Utils.messager.printMessage(Kind.ERROR, "No @WriteClass method to write class type: '" + typeName + "'", var); + BaseProcessor.messager.printMessage(Kind.ERROR, "No @WriteClass method to write class type: '" + typeName + "'", var); return; } diff --git a/annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor index 0888df74ee..8bae50dbf8 100644 --- a/annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor +++ b/annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -1,5 +1,5 @@ -mindustry.annotations.RemoteMethodAnnotationProcessor -mindustry.annotations.SerializeAnnotationProcessor -mindustry.annotations.StructAnnotationProcessor -mindustry.annotations.CallSuperAnnotationProcessor -mindustry.annotations.AssetsAnnotationProcessor \ No newline at end of file +mindustry.annotations.remote.RemoteMethodAnnotationProcessor +mindustry.annotations.impl.StructAnnotationProcessor +mindustry.annotations.impl.SerializeAnnotationProcessor +mindustry.annotations.impl.AssetsAnnotationProcessor +mindustry.annotations.impl.CallSuperAnnotationProcessor diff --git a/build.gradle b/build.gradle index 57fcedcebd..2d86961911 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,10 @@ buildscript{ ext{ - arcExtVersion = "e287fdce0449a87fb15599c67b5167ac0273bcb6" + getArcHash = { + return new Properties().with{ p -> p.load(file('gradle.properties').newReader()); return p }["archash"] + } + + arcHash = getArcHash() } repositories{ @@ -15,8 +19,8 @@ buildscript{ dependencies{ classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.8' classpath "com.github.anuken:packr:-SNAPSHOT" - classpath "com.github.Anuken.Arc:packer:$arcExtVersion" - classpath "com.github.Anuken.Arc:arc-core:$arcExtVersion" + classpath "com.github.Anuken.Arc:packer:$arcHash" + classpath "com.github.Anuken.Arc:arc-core:$arcHash" } } @@ -33,7 +37,6 @@ allprojects{ gdxVersion = '1.9.10' roboVMVersion = '2.3.8' steamworksVersion = '891ed912791e01fe9ee6237a6497e5212b85c256' - arcHash = null loadVersionProps = { return new Properties().with{p -> p.load(file('../core/assets/version.properties').newReader()); return p } @@ -47,10 +50,6 @@ allprojects{ return !project.hasProperty("release") && new File(projectDir.parent, '../Arc').exists() } - getArcHash = { - return new Properties().with{ p -> p.load(file('gradle.properties').newReader()); return p }["archash"] - } - arcModule = { String name -> if(localArc()){ return project(":Arc:$name") @@ -133,6 +132,19 @@ allprojects{ props.store(pfile.newWriter(), "Autogenerated file. Do not modify.") } } + + writeProcessors = { + def processorFile = new File(rootDir, "annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor") + def text = new StringBuilder() + def files = new File(rootDir, "annotations/src/main/java") + files.eachFileRecurse(groovy.io.FileType.FILES){ file -> + if(file.name.endsWith(".java") && (file.text.contains(" extends BaseProcessor") || (file.text.contains(" extends AbstractProcessor") && !file.text.contains("abstract class")))){ + text.append(file.path.substring(files.path.length() + 1)).append("\n") + } + } + + processorFile.text = text.toString().replace(".java", "").replace("/", ".").replace("\\", ".") + } } repositories{ @@ -206,6 +218,7 @@ project(":core"){ outputs.upToDateWhen{ false } generateLocales() writeVersion() + writeProcessors() } task copyChangelog{ @@ -230,31 +243,6 @@ project(":core"){ } dependencies{ - if(System.properties["user.name"] == "anuke"){ - task cleanGen{ - doFirst{ - delete{ - delete "../core/src/mindustry/gen/" - } - } - } - - task copyGen{ - doLast{ - copy{ - from("../core/build/generated/sources/annotationProcessor/java/main/mindustry/gen"){ - include "**/*.java" - } - - into "../core/src/mindustry/gen" - } - } - } - - compileJava.dependsOn(cleanGen) - compileJava.finalizedBy(copyGen) - } - compileJava.dependsOn(preGen) compile "org.lz4:lz4-java:1.4.1" @@ -303,7 +291,7 @@ project(":tools"){ compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop" - compile "org.reflections:reflections:0.9.11" + compile "org.reflections:reflections:0.9.12" compile arcModule("backends:backend-sdl") } @@ -313,8 +301,8 @@ project(":annotations"){ apply plugin: "java" dependencies{ - compile 'com.squareup:javapoet:1.11.0' - compile "com.github.Anuken.Arc:arc-core:$arcExtVersion" + compile 'com.squareup:javapoet:1.12.1' + compile "com.github.Anuken.Arc:arc-core:$arcHash" compile files("${System.getProperty('java.home')}/../lib/tools.jar") } } diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index afb24e5f50..05e827d090 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -104,6 +104,7 @@ mods.none = [LIGHT_GRAY]No mods found! mods.guide = Modding Guide mods.report = Report Bug mods.openfolder = Open Mod Folder +mod.display = [gray]Mod:[orange] {0} mod.enabled = [lightgray]Enabled mod.disabled = [scarlet]Disabled mod.disable = Disable diff --git a/core/assets/bundles/bundle_cs.properties b/core/assets/bundles/bundle_cs.properties index cd22f0d91a..dd3759e71a 100644 --- a/core/assets/bundles/bundle_cs.properties +++ b/core/assets/bundles/bundle_cs.properties @@ -43,10 +43,10 @@ schematic.replace = Šablona tohoto jména již existuje. Chceš ji nahradit? schematic.import = Importuji šablonu... schematic.exportfile = Exportovat soubor schematic.importfile = Importovat soubor -schematic.browseworkshop = Procházet dílnu +schematic.browseworkshop = Procházet Workshop na Steamu schematic.copy = Zkopírovat do schránky schematic.copy.import = Importovat ze schránky -schematic.shareworkshop = Sdílet skrze Steam Workshop +schematic.shareworkshop = Sdílet skrze Workshop na Steamu schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Převrátit šablonu schematic.saved = Šablona byla uložena. schematic.delete.confirm = Šablona bude kompletně vyhlazena. @@ -123,8 +123,8 @@ mod.item.remove = Tato položka je součástí [accent]'{0}'[] modifikace. Pokud mod.remove.confirm = Tato modifikace bude odstraněna. mod.author = [lightgray]Autor:[] {0} mod.missing = Toto uložení hra obsahuje modifikace, které byly nedávno aktualizovány, nebo již nejsou nainstalovány. Použití tohoto uložení může vést k chybám. Jsi si jist, že chceš nahrát toto uložení hry?\n[lightgray]Modifikace:\n{0} -mod.preview.missing = Než vystavíš svou modifikaci v dílně, musíš přidat obrázek pro náhled.\nUmísti obrázek pojmenovaný [accent]preview.png[] do složky modifikace a zkus to znovu. -mod.folder.missing = V dílně mohou být vystaveny pouze modifikace ve formě složky.\nAbys převedl modifikaci na formu složky, jednoduše rozbal zip soubor do složky a smaž starý zip soubor. Potom znovu spusť hru nebo znovu načti modifikace. +mod.preview.missing = Než vystavíš svou modifikaci ve Workshopu na Steamu, musíš přidat obrázek pro náhled.\nUmísti obrázek pojmenovaný [accent]preview.png[] do složky modifikace a zkus to znovu. +mod.folder.missing = Ve Workshopu na Steamu mohou být vystaveny pouze modifikace ve formě složky.\nAbys převedl modifikaci na formu složky, jednoduše rozbal zip soubor do složky a smaž starý zip soubor. Potom znovu spusť hru nebo znovu načti modifikace. mod.scripts.unsupported = Tvoje zařízení nepodporuje skripty. Některé modifikace nemusí správně fungovat. about.button = O hře @@ -240,8 +240,8 @@ save.playtime = Herní čas: {0} warning = Varování. confirm = Potvrdit delete = Smazat -view.workshop = Prohlédnout v dílně -workshop.listing = Upravit popis v dílně +view.workshop = Prohlédnout ve Workshopu na Steamu +workshop.listing = Upravit popis ve Workshopu na Steamu ok = OK open = Otevřít customize = Přizpůsobit pravidla @@ -285,15 +285,15 @@ map.nospawn.pvp = Tato mapa nemá nepřátelská jádra, u kterých by se mohli map.nospawn.attack = Tato mapa nemá nepřátelská jádra, která by mohla být zničena. Přidej v editoru do této mapy aspoň jedno [SCARLET]červené[] jádro. map.invalid = Chyba v načítání mapy: poškozený nebo neplatný soubor mapy. workshop.update = Aktualizovat položku -workshop.error = Chyba při načítání podrobností z dílny: {0} -map.publish.confirm = Jsi si jistý, že chceš vystavit tuto mapu?\n\n[lightgray]Ujisti se nejprve, že souhlasíš se smluvními podmínkami dílny (EULA), jinak se Tvoje mapa nezobrazí.[] +workshop.error = Chyba při načítání podrobností z Workshopu na Steamu: {0} +map.publish.confirm = Jsi si jistý, že chceš vystavit tuto mapu?\n\n[lightgray]Ujisti se nejprve, že souhlasíš se smluvními podmínkami Workshopu na Steamu (EULA), jinak se Tvoje mapa nezobrazí.[] workshop.menu = Vyber si, co bys chtěl dělat s touto položkou. workshop.info = Informace o položce changelog = Seznam změn (volitelně): eula = Smluvní podmínky platformy Steam -missing = Tato položka byla smazána nebo přesunuta.\n[lightgray]Položka bude automaticky odebrána ze seznamu dílny. +missing = Tato položka byla smazána nebo přesunuta.\n[lightgray]Položka bude automaticky odebrána ze seznamu Workshopu na Steamu. publishing = [accent]Publikuji... -publish.confirm = Opravdu chceš toto vystavit?\n\n[lightgray]Ujisti se nejprve, že souhlasíš se smluvními podmínkami dílny (EULA), jinak se Tvoje položky nezobrazí.[] +publish.confirm = Opravdu chceš toto vystavit?\n\n[lightgray]Ujisti se nejprve, že souhlasíš se smluvními podmínkami Workshopu na Steamu (EULA), jinak se Tvoje položky nezobrazí.[] publish.error = Chyba při vystavování položky: {0} steam.error = Nepodařilo se inicializovat služby platformy Steam.\Chyba: {0} @@ -309,9 +309,9 @@ editor.waves = Vln: editor.rules = Pravidla: editor.generation = Generace: editor.ingame = Upravit ve hře -editor.publish.workshop = Vystavit v dílně +editor.publish.workshop = Vystavit ve Workshopu na Steamu editor.newmap = Nová mapa -workshop = Dílna +workshop = Workshop na Steamu waves.title = Vlny waves.remove = Odebrat waves.never = @@ -761,13 +761,13 @@ rules.blockhealthmultiplier = Násobek zdraví bloků rules.playerhealthmultiplier = Násobek zdraví hráče rules.playerdamagemultiplier = Násobek útoku hráče rules.unitdamagemultiplier = Násobek poškození jednotkami -rules.enemycorebuildradius = Poloměr, ve kterém se okolo nepřítelského jádra nesmí stavět: [lightgray](dlaždic)[] +rules.enemycorebuildradius = Poloměr, ve kterém se okolo nepřátelského jádra nesmí stavět: [lightgray](dlaždic)[] rules.respawntime = Čas znovuzrození: [lightgray](vteřin)[] rules.wavespacing = Čas rozestupu mezi vlnami: [lightgray](vteřin)[] rules.buildcostmultiplier = Násobek ceny stavění rules.buildspeedmultiplier = Násobek rychlosti stavění rules.waitForWaveToEnd = Vlny čekají na nepřátele -rules.dropzoneradius = Poloměr oblasti pro sestoupení: [lightgray](dlaždic)[] +rules.dropzoneradius = Poloměr oblasti pro vylíhnutí: [lightgray](dlaždic)[] rules.respawns = Maximální počet znovuvylíhnutí za vlnu rules.limitedRespawns = Maximální počet znovuzrození rules.title.waves = Vlny @@ -943,7 +943,8 @@ block.inverted-sorter.name = Obrácená třídička block.message.name = Zpráva block.illuminator.name = Osvětlovač block.illuminator.description = Malý, kompaktní, konfigurovatelný zdroj světla. Vyžaduje pro svoje fungování energii. -block.overflow-gate.name = Přepadová brána +block.overflow-gate.name = Brána s přepadem +block.underflow-gate.name = Brána s podtokem block.silicon-smelter.name = Křemíková huť block.phase-weaver.name = Tkalcovna pro fázovou tkaninu block.pulverizer.name = Rozmělňovač @@ -1034,8 +1035,8 @@ block.overdrive-projector.name = Urychlující projektor block.force-projector.name = Silový projektor block.arc.name = Oblouk block.rtg-generator.name = RTG -block.spectre.name = Duch -block.meltdown.name = Tavička +block.spectre.name = Spectre +block.meltdown.name = Meltdown block.container.name = Kontejnér block.launch-pad.name = Vysílací plošina block.launch-pad-large.name = Velká vysílací plošina @@ -1174,6 +1175,7 @@ block.inverted-sorter.description = Třídí předměty. Pokud je předmět shod block.router.description = Přijímá předměty z jednoho směru a posílá je rovnoměrně do zbylých tří směrů. Užitečný pro rozdělení předmětů z jednoho zdroje do různých cílů, jako odbočení z dopravníků a podobně.\n\n[scarlet]Pozor, nepoužívejte pro vstup do produkční budovy, jinak se bude ucpávat výstupními předměty[]. block.distributor.description = Pokročilý směrovač. Rozděluje předměty rovnoměrně až do 7 dalších směrů. block.overflow-gate.description = Předměty jsou poslány do strany, pokud je směr vpřed zablokován. Užitečné například pro zpracování přebytečného materiálu, pokud je primární příjemce saturován. +block.underflow-gate.description = Předměty jsou poslány vpřed, pokud je směr do strany zablokován. Užitečné například pro zpracování přebytečného materiálu, pokud je primární příjemce saturován. block.mass-driver.description = Ultimátní blok pro přepravu předmětů. Sebere několik předmětů a vystřelí je k dalšímu hromadnému distributoru přes několik dlaždic. Vyžaduje ke své funkci energii. block.mechanical-pump.description = Levné čerpadlo s pomalým průtokem, nevyžaduje však energii k provozu. block.rotary-pump.description = Pokročilé čerpadlo, které za pomoci energie vyčerpá větší množství kapalin, než standardní. @@ -1228,9 +1230,9 @@ block.salvo.description = Větší, pokročilejší verze střílny Duo. Pálí block.fuse.description = Velká střílna s krátkým dosahem. Pálí trojice energetických paprsků blízké nepřátele. block.ripple.description = Extrémně silná dělostřelecká střílna. Pálí na dálku shluky střel na nepřátelské jednotky. block.cyclone.description = Velká protiletecká a protipozemní střílna. Pálí explodující dávky na nepřítele v okolí. -block.spectre.description = Velká střílna s kanónem s dvěma hlavněmi. Střílí velké náboje, které pronikají brněním jak pozemních, tak vzdušných nepřítelských cílů. +block.spectre.description = Velká střílna s kanónem s dvěma hlavněmi. Střílí velké náboje, které pronikají brněním jak pozemních, tak vzdušných nepřátelských cílů. block.meltdown.description = Masivní laserový kanón. Nabije se a pak pálí nepřetržitý laserový paprsek na nepřátele v okolí. Vyžaduje ke své funkci chlazení. -block.command-center.description = Vydává příkazy spojeneckým jednotkám na mapě.\nInstruuje jednotky k útoku na nepřítelské jádro, návratu do jádra nebo továrny a ke shromáždění se. Pokud se na mapě nepřátelské jádro nenachází, jednotky budou v útočném režimu držet hlídku. +block.command-center.description = Vydává příkazy spojeneckým jednotkám na mapě.\nInstruuje jednotky k útoku na nepřátelské jádro, návratu do jádra nebo továrny a ke shromáždění se. Pokud se na mapě nepřátelské jádro nenachází, jednotky budou v útočném režimu držet hlídku. block.draug-factory.description = Vyrábí těžící drony Dragoun. block.spirit-factory.description = Vyrábí drony, které opravují budovy. block.phantom-factory.description = Vyrábí drony s pokročilou konstrukcí. diff --git a/core/assets/bundles/bundle_fi.properties b/core/assets/bundles/bundle_fi.properties index a4c189dca4..cefc5181ec 100644 --- a/core/assets/bundles/bundle_fi.properties +++ b/core/assets/bundles/bundle_fi.properties @@ -3,7 +3,7 @@ credits = Tekijät contributors = Kääntäjät ja avustajat discord = Liity Mindustryn Discordiin! link.discord.description = Mindustryn virallinen Discord-keskusteluhuone -link.reddit.description = The Mindustry subreddit +link.reddit.description = Mindustry subreddit link.github.description = Pelin lähdekoodi link.changelog.description = Lista päivityksien muutoksista link.dev-builds.description = Epävakaat kehitysversiot @@ -19,47 +19,47 @@ screenshot.invalid = Kartta liian laaja, kuvankaappaukselle ei mahdollisesti ole gameover = Peli ohi gameover.pvp = [accent] {0}[] joukkue voittaa! highscore = [accent]Uusi ennätys! -copied = Copied. +copied = Kopioitu. -load.sound = Sounds -load.map = Maps -load.image = Images -load.content = Content -load.system = System -load.mod = Mods -load.scripts = Scripts +load.sound = Ääni +load.map = Kartat +load.image = Kuvat +load.content = Sisältö +load.system = Systeemi +load.mod = Modit +load.scripts = Skriptit be.update = A new Bleeding Edge build is available: -be.update.confirm = Download it and restart now? -be.updating = Updating... -be.ignore = Ignore -be.noupdates = No updates found. -be.check = Check for updates +be.update.confirm = Lataa se ja käynnistä peli uudelleen? +be.updating = Päivitetään... +be.ignore = Sivuuta +be.noupdates = Ei päivityksiä saatavilla. +be.check = Tarkista päivityksiä -schematic = Schematic -schematic.add = Save Schematic... -schematics = Schematics -schematic.replace = A schematic by that name already exists. Replace it? -schematic.import = Import Schematic... -schematic.exportfile = Export File -schematic.importfile = Import File -schematic.browseworkshop = Browse Workshop -schematic.copy = Copy to Clipboard -schematic.copy.import = Import from Clipboard -schematic.shareworkshop = Share on Workshop -schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Flip Schematic -schematic.saved = Schematic saved. -schematic.delete.confirm = This schematic will be utterly eradicated. -schematic.rename = Rename Schematic -schematic.info = {0}x{1}, {2} blocks +schematic = Kaavio +schematic.add = Tallenna Kaavio... +schematics = Kaaviot +schematic.replace = Kaavio tällä nimellä on jo olemassa. Haluatko korvata sen? +schematic.import = Tuo Kaavio... +schematic.exportfile = Luo Tiedosto +schematic.importfile = Tuo Tiedosto +schematic.browseworkshop = Selaa Työpajaa +schematic.copy = Kopioi Leikepöydälle +schematic.copy.import = Tou Leikepöydälle +schematic.shareworkshop = Jaa työpajaan +schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Käännä Kaavio +schematic.saved = Kaavio tallennettu. +schematic.delete.confirm = Tämä kaavio poistetaan. +schematic.rename = Uudelleennimeä Kaavio +schematic.info = {0}x{1}, {2} palikkaa -stat.wave = Aaltoja voitettu:[accent] {0} +stat.wave = Tasoja voitettu:[accent] {0} stat.enemiesDestroyed = Vihollisia tuhottu:[accent] {0} stat.built = Rakennuksia rakennettu:[accent] {0} stat.destroyed = Rakennuksia tuhottu:[accent] {0} stat.deconstructed = Rakennuksia purettu:[accent] {0} stat.delivered = Resursseja laukaistu: -stat.rank = Lopullinen arvo: [accent]{0} +stat.rank = Lopullinen arvosana: [accent]{0} launcheditems = [accent]Laukaistut tavarat launchinfo = [unlaunched][[LAUNCH] your core to obtain the items indicated in blue. @@ -78,49 +78,49 @@ customgame = Mukautettu peli newgame = Uusi peli none = minimap = Pienoiskartta -position = Position +position = Sijainti close = Sulje website = Verkkosivu quit = Poistu -save.quit = Save & Quit +save.quit = Tallenna ja Poistu maps = Kartat -maps.browse = Browse Maps +maps.browse = Selaa Karttoja continue = Jatka maps.none = [lightgray]Karttoja ei löytynyt! -invalid = Invalid -pickcolor = Pick Color +invalid = Invalidi +pickcolor = Valitse väri preparingconfig = Preparing Config preparingcontent = Preparing Content uploadingcontent = Uploading Content uploadingpreviewfile = Uploading Preview File committingchanges = Comitting Changes -done = Done -feature.unsupported = Your device does not support this feature. +done = Valmis +feature.unsupported = Sinun laitteesi ei tue tätä toimintoa. -mods.alphainfo = Keep in mind that mods are in alpha, and[scarlet] may be very buggy[].\nReport any issues you find to the Mindustry GitHub or Discord. +mods.alphainfo = Pidä mielessä että modit ovat alpha-tilassa, ja[scarlet] ne voivat olla virheellisiä[].\nRaportoi kaikki virheet Mindustry GitHub-sivuille tai Discordiin. mods.alpha = [accent](Alpha) -mods = Mods -mods.none = [LIGHT_GRAY]No mods found! -mods.guide = Modding Guide -mods.report = Report Bug -mods.openfolder = Open Mod Folder -mod.enabled = [lightgray]Enabled -mod.disabled = [scarlet]Disabled -mod.disable = Disable -mod.delete.error = Unable to delete mod. File may be in use. -mod.requiresversion = [scarlet]Requires min game version: [accent]{0} -mod.missingdependencies = [scarlet]Missing dependencies: {0} -mod.erroredcontent = [scarlet]Content Errors -mod.errors = Errors have occurred loading content. -mod.noerrorplay = [scarlet]You have mods with errors.[] Either disable the affected mods or fix the errors before playing. +mods = Modit +mods.none = [LIGHT_GRAY]Modeja ei löytynyt! +mods.guide = Modaamisen opas +mods.report = Raportoi ohjelmistovirhe +mods.openfolder = Avaa Modikansio +mod.enabled = [lightgray]Käytössä +mod.disabled = [scarlet]Epäkäytössä +mod.disable = Laita pois päältä +mod.delete.error = Modia ei pystynyt poistamaan. Tiedosto voi olla käytössä. +mod.requiresversion = [scarlet]Tarvitsee vähintää pelin version: [accent]{0} +mod.missingdependencies = [scarlet]Tarvitsee nämä modit: {0} +mod.erroredcontent = [scarlet]Sisältö Virheet +mod.errors = Virheitä on tapahtunut pelin ladatessa. +mod.noerrorplay = [scarlet]Sinulla on virheellisiä modeja.[] Joko poista ne käytöstä tai korjaa virheet. mod.nowdisabled = [scarlet]Mod '{0}' is missing dependencies:[accent] {1}\n[lightgray]These mods need to be downloaded first.\nThis mod will be automatically disabled. -mod.enable = Enable -mod.requiresrestart = The game will now close to apply the mod changes. -mod.reloadrequired = [scarlet]Reload Required -mod.import = Import Mod +mod.enable = Käytä +mod.requiresrestart = Peli suljetaan jotta muutokset voisivat toteutua. +mod.reloadrequired = [scarlet]Vaatii Uudelleenkäynnistystä +mod.import = Tuo Modi mod.import.github = Import GitHub Mod mod.item.remove = This item is part of the[accent] '{0}'[] mod. To remove it, uninstall that mod. -mod.remove.confirm = This mod will be deleted. +mod.remove.confirm = Tämä modi poistetaan. mod.author = [LIGHT_GRAY]Author:[] {0} mod.missing = This save contains mods that you have recently updated or no longer have installed. Save corruption may occur. Are you sure you want to load it?\n[lightgray]Mods:\n{0} mod.preview.missing = Before publishing this mod in the workshop, you must add an image preview.\nPlace an image named[accent] preview.png[] into the mod's folder and try again. @@ -143,34 +143,34 @@ server.closing = [accent]Suljetaan palvelinta... server.kicked.kick = Sinut on potkittu palvelimelta! server.kicked.whitelist = You are not whitelisted here. server.kicked.serverClose = Palvelin suljettu. -server.kicked.vote = You have been vote-kicked. Goodbye. +server.kicked.vote = Sinut on äänetetty pois. Hyvästi. server.kicked.clientOutdated = Pelisi on vanhentunut! Päivitä se! -server.kicked.serverOutdated = Outdated server! Ask the host to update! +server.kicked.serverOutdated = Vanhentunut palvelin! Pyydä isäntää päivittämään! server.kicked.banned = Sinulla on portikielto tälle palvelimelle. server.kicked.typeMismatch = This server is not compatible with your build type. -server.kicked.playerLimit = This server is full. Wait for an empty slot. +server.kicked.playerLimit = Tämä palvelin on täynnä. Odota vapaata tilaa. server.kicked.recentKick = Sinut on potkittu äskettäin.\nOdota ennen kuin yhdistät uudestaan. server.kicked.nameInUse = Joku tuon niminen\non jo tällä palvelimella. server.kicked.nameEmpty = Valitsemasi nimi on virheellinen. server.kicked.idInUse = Olet jo tällä palvelimella! Kahdella käyttäjällä yhdistäminen ei ole sallittua. server.kicked.customClient = Tämä palvelin ei tue muokattuja versioita. Lataa virallinen versio. server.kicked.gameover = Peli ohi! -server.kicked.serverRestarting = The server is restarting. +server.kicked.serverRestarting = Tämä palvelin on uudelleenkäynnistymässä. server.versions = Versiosi:[accent] {0}[]\nPalvelimen versio:[accent] {1}[] host.info = The [accent]host[] button hosts a server on port [scarlet]6567[]. \nAnybody on the same [lightgray]wifi or local network[] should be able to see your server in their server list.\n\nIf you want people to be able to connect from anywhere by IP, [accent]port forwarding[] is required.\n\n[lightgray]Note: If someone is experiencing trouble connecting to your LAN game, make sure you have allowed Mindustry access to your local network in your firewall settings. Note that public networks sometimes do not allow server discovery. join.info = Here, you can enter a [accent]server IP[] to connect to, or discover [accent]local network[] servers to connect to.\nBoth LAN and WAN multiplayer is supported.\n\n[lightgray]Note: There is no automatic global server list; if you want to connect to someone by IP, you would need to ask the host for their IP. -hostserver = Host Multiplayer Game -invitefriends = Invite Friends +hostserver = Pidä yllä monipelaaja peliä +invitefriends = Pyydä Ystäviä hostserver.mobile = Host\nGame host = Host hosting = [accent]Avataan palvelinta... hosts.refresh = Päivitä -hosts.discovering = Discovering LAN games -hosts.discovering.any = Discovering games +hosts.discovering = Etsitään LAN pelejä +hosts.discovering.any = Etsitään Pelejä server.refreshing = Päivitetään palvelimen tietoja -hosts.none = [lightgray]No local games found! -host.invalid = [scarlet]Can't connect to host. -trace = Trace Player +hosts.none = [lightgray]Paikallisia pelejä ei löytynyt! +host.invalid = [scarlet]Isäntään ei voitu yhdistää. +trace = Seuraa Pelaajaa trace.playername = Pelaajanimi: [accent]{0} trace.ip = IP-osoite: [accent]{0} trace.id = Uniikki tunniste: [accent]{0} @@ -188,17 +188,17 @@ server.outdated = [crimson]Vanhentunut palvelin![] server.outdated.client = [crimson]Vanhentunut asiakasohjelma![] server.version = [gray]v{0} {1} server.custombuild = [yellow]Custom Build -confirmban = Are you sure you want to ban this player? -confirmkick = Are you sure you want to kick this player? -confirmvotekick = Are you sure you want to vote-kick this player? -confirmunban = Are you sure you want to unban this player? -confirmadmin = Are you sure you want to make this player an admin? +confirmban = Oletko varma että haluat potkia tämän pelaajan? +confirmkick = Oletko varma että haluat poistaa tämän pelaajan? +confirmvotekick = Oletko varma että haluat äänestää tämän pelaajan potkituksi? +confirmunban = Oletko varma että haluat päästää tämän pelaajan takaisin? +confirmadmin = Oletko varma että haluat antaa pelaajalle hallinto-oikeuksia? confirmunadmin = Are you sure you want to remove admin status from this player? joingame.title = Liity peliin joingame.ip = Osoite: -disconnect = Disconnected. -disconnect.error = Connection error. -disconnect.closed = Connection closed. +disconnect = Yhteys katkaistu. +disconnect.error = Yhteysvirhe. +disconnect.closed = Yhteys poistettu. disconnect.timeout = Timed out. disconnect.data = Failed to load world data! cantconnect = Unable to join game ([accent]{0}[]). @@ -212,7 +212,7 @@ save.new = New Save save.overwrite = Are you sure you want to overwrite\nthis save slot? overwrite = Overwrite save.none = No saves found! -saveload = Saving... +saveload = Tallennetaan... savefail = Failed to save game! save.delete.confirm = Are you sure you want to delete this save? save.delete = Delete @@ -220,7 +220,7 @@ save.export = Export Save save.import.invalid = [accent]This save is invalid! save.import.fail = [crimson]Failed to import save: [accent]{0} save.export.fail = [crimson]Failed to export save: [accent]{0} -save.import = Import Save +save.import = Tuo Tallennus save.newslot = Tallennuksen nimi: save.rename = Nimeä uudelleen save.rename.text = Uusi nimi: @@ -265,8 +265,8 @@ cancelbuilding = [accent][[{0}][] to clear plan selectschematic = [accent][[{0}][] to select+copy pausebuilding = [accent][[{0}][] to pause building resumebuilding = [scarlet][[{0}][] to resume building -wave = [accent]Aalto {0} -wave.waiting = [lightgray]Wave in {0} +wave = [accent]Taso {0} +wave.waiting = [lightgray]Seuraava taso {0} wave.waveInProgress = [lightgray]Wave in progress waiting = [lightgray]Odotetaan... waiting.players = Odotetaan pelaajia... @@ -275,7 +275,7 @@ wave.enemy = [lightgray]{0} vihollinen jäljellä loadimage = Lataa kuva saveimage = Tallenna kuva unknown = Tuntematon -custom = Custom +custom = Mukautettu builtin = Sisäänrakennettu map.delete.confirm = Oletko varma että haluat poistaa tämän kartan? Poistoa ei voi peruuttaa! map.random = [accent]Satunnainen kartta @@ -296,30 +296,30 @@ publish.confirm = Are you sure you want to publish this?\n\n[lightgray]Make sure publish.error = Error publishing item: {0} steam.error = Failed to initialize Steam services.\nError: {0} -editor.brush = Brush +editor.brush = Sivellin editor.openin = Avaa editorissa editor.oregen = Ore Generation editor.oregen.info = Ore Generation: editor.mapinfo = Kartan tiedot -editor.author = Author: +editor.author = Tekijä: editor.description = Kuvaus: -editor.nodescription = A map must have a description of at least 4 characters before being published. -editor.waves = Aallot: +editor.nodescription = Kartan kuvaksessa täytyy olla vähintään neljä kirjainta ennen julkaisua. +editor.waves = Tasot: editor.rules = Säännöt: -editor.generation = Generation: -editor.ingame = Edit In-Game -editor.publish.workshop = Publish On Workshop +editor.generation = Generaatio: +editor.ingame = Muokka pelin sisällä +editor.publish.workshop = Julkaise työpajaan editor.newmap = Uusi kartta -workshop = Workshop -waves.title = Aallot -waves.remove = Remove +workshop = Työpaja +waves.title = Tasot +waves.remove = Poista waves.never = waves.every = every waves.waves = wave(s) -waves.perspawn = per spawn +waves.perspawn = per spawni waves.to = to -waves.boss = Boss -waves.preview = Preview +waves.boss = Pomo +waves.preview = Esikatselu waves.edit = Muokkaa... waves.copy = Kopioi leikepöydälle waves.load = Lataa leikepöydältä @@ -327,11 +327,11 @@ waves.invalid = Invalid waves in clipboard. waves.copied = Aallot kopioitu. waves.none = No enemies defined.\nNote that empty wave layouts will automatically be replaced with the default layout. editor.default = [lightgray] -details = Details... +details = Yksityiskohdat... edit = Muokkaa... editor.name = Nimi: -editor.spawn = Spawn Unit -editor.removeunit = Remove Unit +editor.spawn = Spawni yksikkö +editor.removeunit = Poista yksikkö editor.teams = Joukkueet editor.errorload = Virhe ladattaessa tiedostoa:\n[accent]{0} editor.errorsave = Virhe tallennettaessa tiedostoa:\n[accent]{0} @@ -341,10 +341,10 @@ editor.errornot = This is not a map file. editor.errorheader = This map file is either not valid or corrupt. editor.errorname = Map has no name defined. Are you trying to load a save file? editor.update = Päivitä -editor.randomize = Randomize -editor.apply = Apply -editor.generate = Generate -editor.resize = Resize +editor.randomize = Satunnaista +editor.apply = Käytä +editor.generate = Generoi +editor.resize = Säädä kokoa editor.loadmap = Lataa kartta editor.savemap = Tallenna kartta editor.saved = Tallennettu! @@ -370,12 +370,12 @@ editor.resizemap = Resize Map editor.mapname = Kartan nimi: editor.overwrite = [accent]Warning!\nThis overwrites an existing map. editor.overwrite.confirm = [scarlet]Warning![] A map with this name already exists. Are you sure you want to overwrite it? -editor.exists = A map with this name already exists. -editor.selectmap = Select a map to load: +editor.exists = Kartta tällä nimellä on jo olemassa. +editor.selectmap = Valitse kartta ladattavaksi: -toolmode.replace = Replace +toolmode.replace = Korvaa toolmode.replace.description = Draws only on solid blocks. -toolmode.replaceall = Replace All +toolmode.replaceall = Korvaa kaikki toolmode.replaceall.description = Replace all blocks in map. toolmode.orthogonal = Orthogonal toolmode.orthogonal.description = Draws only orthogonal lines. @@ -424,48 +424,48 @@ width = Leveys: height = Korkeus: menu = Valikko play = Pelaa -campaign = Campaign +campaign = Polku load = Lataa save = Tallenna fps = FPS: {0} ping = Ping: {0}ms language.restart = Please restart your game for the language settings to take effect. settings = Asetukset -tutorial = Perehdytys -tutorial.retake = Re-Take Tutorial -editor = Editor -mapeditor = Map Editor +tutorial = Tutoriaali +tutorial.retake = Uusita Tutoriaali +editor = Editori +mapeditor = Kartan Editori abandon = Hylkää abandon.text = This zone and all its resources will be lost to the enemy. locked = Lukittu complete = [lightgray]Reach: -requirement.wave = Reach Wave {0} in {1} -requirement.core = Destroy Enemy Core in {0} -requirement.unlock = Unlock {0} +requirement.wave = Pääse Tasolle {0} kartassa {1} +requirement.core = Tuhoa vihollise ydin kartassa {0} +requirement.unlock = Avaa {0} resume = Resume Zone:\n[lightgray]{0} -bestwave = [lightgray]Best Wave: {0} +bestwave = [lightgray]Paras taso: {0} launch = < LAUNCH > -launch.title = Launch Successful +launch.title = Onnistunut laukaisu launch.next = [lightgray]next opportunity at wave {0} launch.unable2 = [scarlet]Unable to LAUNCH.[] -launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. -launch.skip.confirm = If you skip now, you will not be able to launch until later waves. -uncover = Uncover +launch.confirm = Tämä laukaisee kaikki resourssit ytimestäsi.\nEt voi enää palata takaisin. +launch.skip.confirm = Jos ohitat nyt, voit laukaista vasta myöhemmissä tasoissa. +uncover = Paljasta configure = Configure Loadout -bannedblocks = Banned Blocks -addall = Add All +bannedblocks = Kielletyt Palikat +addall = Lisää kaikki configure.locked = [lightgray]Unlock configuring loadout: Wave {0}. configure.invalid = Amount must be a number between 0 and {0}. zone.unlocked = [lightgray]{0} unlocked. zone.requirement.complete = Wave {0} reached:\n{1} zone requirements met. zone.config.unlocked = Loadout unlocked:[lightgray]\n{0} -zone.resources = [lightgray]Resources Detected: -zone.objective = [lightgray]Objective: [accent]{0} -zone.objective.survival = Survive +zone.resources = [lightgray]Resoursseja havaittu: +zone.objective = [lightgray]Objectiivi: [accent]{0} +zone.objective.survival = Selviydy zone.objective.attack = Destroy Enemy Core -add = Add... -boss.health = Boss Health +add = Lisää... +boss.health = Pomon elinpisteet connectfail = [crimson]Connection error:\n\n[accent]{0} error.unreachable = Server unreachable.\nIs the address spelled correctly? @@ -478,209 +478,209 @@ error.io = Network I/O error. error.any = Unknown network error. error.bloom = Failed to initialize bloom.\nYour device may not support it. -zone.groundZero.name = Ground Zero -zone.desertWastes.name = Desert Wastes -zone.craters.name = The Craters -zone.frozenForest.name = Frozen Forest -zone.ruinousShores.name = Ruinous Shores -zone.stainedMountains.name = Stained Mountains -zone.desolateRift.name = Desolate Rift -zone.nuclearComplex.name = Nuclear Production Complex -zone.overgrowth.name = Overgrowth -zone.tarFields.name = Tar Fields -zone.saltFlats.name = Salt Flats -zone.impact0078.name = Impact 0078 -zone.crags.name = Crags -zone.fungalPass.name = Fungal Pass +zone.groundZero.name = Vaara Alue +zone.desertWastes.name = Aavikon Jätteet +zone.craters.name = Kraatterit +zone.frozenForest.name = Jäätynyt Metsä +zone.ruinousShores.name = Tuhoisa Ranta +zone.stainedMountains.name = Tahravuoret +zone.desolateRift.name = Autio Syvänne +zone.nuclearComplex.name = Ydinvoima Kompleksi +zone.overgrowth.name = Liikakasvu +zone.tarFields.name = Terva Pellot +zone.saltFlats.name = Suolainen Tasanne +zone.impact0078.name = Isku 0078 +zone.crags.name = Kalliot +zone.fungalPass.name = Sienilaakso -zone.groundZero.description = The optimal location to begin once more. Low enemy threat. Few resources.\nGather as much lead and copper as possible.\nMove on. -zone.frozenForest.description = Even here, closer to mountains, the spores have spread. The frigid temperatures cannot contain them forever.\n\nBegin the venture into power. Build combustion generators. Learn to use menders. -zone.desertWastes.description = These wastes are vast, unpredictable, and criss-crossed with derelict sector structures.\nCoal is present in the region. Burn it for power, or synthesize graphite.\n\n[lightgray]This landing location cannot be guaranteed. -zone.saltFlats.description = On the outskirts of the desert lie the Salt Flats. Few resources can be found in this location.\n\nThe enemy has erected a resource storage complex here. Eradicate their core. Leave nothing standing. -zone.craters.description = Water has accumulated in this crater, relic of the old wars. Reclaim the area. Collect sand. Smelt metaglass. Pump water to cool turrets and drills. -zone.ruinousShores.description = Past the wastes, is the shoreline. Once, this location housed a coastal defense array. Not much of it remains. Only the most basic defense structures have remained unscathed, everything else reduced to scrap.\nContinue the expansion outwards. Rediscover the technology. -zone.stainedMountains.description = Further inland lie the mountains, yet untainted by spores.\nExtract the abundant titanium in this area. Learn how to use it.\n\nThe enemy presence is greater here. Do not give them time to send their strongest units. -zone.overgrowth.description = This area is overgrown, closer to the source of the spores.\nThe enemy has established an outpost here. Build Titan units. Destroy it. Reclaim that which was lost. -zone.tarFields.description = The outskirts of an oil production zone, between the mountains and desert. One of the few areas with usable tar reserves.\nAlthough abandoned, this area has some dangerous enemy forces nearby. Do not underestimate them.\n\n[lightgray]Research oil processing technology if possible. -zone.desolateRift.description = An extremely dangerous zone. Plentiful resources, but little space. High risk of destruction. Leave as soon as possible. Do not be fooled by the long spacing between enemy attacks. -zone.nuclearComplex.description = A former facility for the production and processing of thorium, reduced to ruins.\n[lightgray]Research the thorium and its many uses.\n\nThe enemy is present here in great numbers, constantly scouting for attackers. -zone.fungalPass.description = A transition area between high mountains and lower, spore-ridden lands. A small enemy reconnaissance base is located here.\nDestroy it.\nUse Dagger and Crawler units. Take out the two cores. +zone.groundZero.description = Suotuisa alue aloittaa peli. Matala vaarataso. Vähän resoursseja.\nKerää mahdollisimman paljon kuparia ja lyijyä.\nJatka eteenpäin. +zone.frozenForest.description = Jopa täällä, lähellä vuoria, asustaa itiöitä. Mutta ne eivöt voi elää ikuisesti jäätävässä ilmastossa.\n\nAloita matkasi energiaan. Rakenna polttogeneraattoreita. Opettele korjaajien käyttö. +zone.desertWastes.description = Valtavia määriä jätteitä ränsityneiden rakennuksien seassa.\nVoit löytää hiiltä. Polta se energiaksi, tai tiivistä siitä grafiittia.\n\n[lightgray]Laskeutumiskohta on epävarma. +zone.saltFlats.description = Aavikoiden reunoilla on suolainen tasanne. Vain vähän resoursse on saatavilla.\n\nVihollinen on rakentanut resurssi hankinnan. Hävitä vihollisen ydin. Älä jätä mitään jäljelle. +zone.craters.description = Vettä on kertynyt tähän kraatteriin vanhojen sotien jäänteinä. Ota alue itsellesi. Kerää hiekkaa. Sulata metallilasia. Pumppaa vettä jäähdyttääksesi kaivausporia ja tykkejä. +zone.ruinousShores.description = Jätteiden takaa, löydät rantaviivan. Kerran täma paikka asutti sotilasjoukkoja. Paljoa jäljella ei ole. Vain perus puolustus rekenteet ovat vahingoittumattomia, kaakki muu on romua.\nJatka laajentamista eteenpäin. Tutki teknologiaa. +zone.stainedMountains.description = Alankoa vuroien sisämaassa, löydät paljon itiöelämää.\nOta talteen runsas titaani jota täältä löytyy. Opi käyttämään sitä.\n\nVihollinen on läasnäoleva. Älä anna heille liikaa aikaa lähettää heidän vahvimpia aseitaan. +zone.overgrowth.description = Tämä alue on ylikasvanut, lähempänä itiöiden pesäkettä.\nVihollinen on muodostanut etuvartion. Rakenna titaani yksikköjä. Tuhoa vihollinen. Hanki se alue joka joskus on menetetty. +zone.tarFields.description = Öljytuotannon laitamia, vuorien ja aavikkojen välissä. Yksi ainoista paikosta joissa on tervalähde.\nLöydät vaarallisia vihollis joukkoja täältä hylätystä paikasta. Älä aliarvio niitä.\n\n[lightgray]Tutki öljyprosessointi mekanismeja jos mahdollista. +zone.desolateRift.description = Extremaalisen vaarallinen alue. Runsaasti resursseja, mutta vain vähän tilaa. Korke riski eliminaatiolle. Lähde mahdollisimman nopeasti. Älä tule huijatuksi pitkien taukojen vihollisten hyökkäyksien vällillä. +zone.nuclearComplex.description = Entinen laitos tehty toriumin tuotantoa ja prosessointia varten, nykyään vain rauniota.\n[lightgray]Tutki toriumin monia hyödyllisiä käyttötarkoituksia.\n\nVihollinen on läsnä isoin joukkoin kokoajan partioimassa tunkeilijoilta. +zone.fungalPass.description = Siirtymis alue korkeiden ja matalien vuorien välillä, itiöiden peitossa. Pieni vihollis tiedustelu tukikohta on täällä. Tuhoa se.\nKäytä Dagger- ja Crawler yksikköjä. Tuhoa kaksi vihollisydintä. zone.impact0078.description = zone.crags.description = -settings.language = Language -settings.data = Game Data -settings.reset = Reset to Defaults -settings.rebind = Rebind -settings.resetKey = Reset -settings.controls = Controls -settings.game = Game -settings.sound = Sound -settings.graphics = Graphics -settings.cleardata = Clear Game Data... -settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone! -settings.clearall.confirm = [scarlet]WARNING![]\nThis will clear all data, including saves, maps, unlocks and keybinds.\nOnce you press 'ok' the game will wipe all data and automatically exit. -paused = [accent]< Paused > -clear = Clear -banned = [scarlet]Banned -yes = Yes -no = No -info.title = Info +settings.language = Kieli +settings.data = Peli Data +settings.reset = Nollaa Asetukset +settings.rebind = Uudelleenaseta +settings.resetKey = Aseta Uudelleen +settings.controls = Kontrollit +settings.game = Peli +settings.sound = Ääni +settings.graphics = Grafiikat +settings.cleardata = Tyhjennä Pelin Data... +settings.clear.confirm = Oletko varma että haluat tyhjentää pelin datan?\nMitä on tehty ei voi peruuttaa! +settings.clearall.confirm = [scarlet]WARNING![]\nTämä poistaa kaiken datan, mukaanlukien kesken olevat pelit, kartat, avatut asiat ja kontrolliasetukset.\nKun painat 'ok' kaikki datasi poistetaan ja peli suljetaan. +paused = [accent]< Pysäytetty > +clear = Tyhjä +banned = [scarlet]Kielletty +yes = Kyllä +no = Ei +info.title = Informaatio error.title = [crimson]An error has occured error.crashtitle = An error has occured -blocks.input = Input -blocks.output = Output -blocks.booster = Booster +blocks.input = Sisääntulo +blocks.output = Ulostulo +blocks.booster = Boostaa block.unknown = [lightgray]??? -blocks.powercapacity = Power Capacity -blocks.powershot = Power/Shot -blocks.damage = Damage -blocks.targetsair = Targets Air -blocks.targetsground = Targets Ground -blocks.itemsmoved = Move Speed -blocks.launchtime = Time Between Launches -blocks.shootrange = Range -blocks.size = Size -blocks.liquidcapacity = Liquid Capacity -blocks.powerrange = Power Range -blocks.powerconnections = Max Connections -blocks.poweruse = Power Use -blocks.powerdamage = Power/Damage -blocks.itemcapacity = Item Capacity -blocks.basepowergeneration = Base Power Generation -blocks.productiontime = Production Time -blocks.repairtime = Block Full Repair Time -blocks.speedincrease = Speed Increase -blocks.range = Range -blocks.drilltier = Drillables -blocks.drillspeed = Base Drill Speed -blocks.boosteffect = Boost Effect -blocks.maxunits = Max Active Units -blocks.health = Health -blocks.buildtime = Build Time -blocks.buildcost = Build Cost -blocks.inaccuracy = Inaccuracy -blocks.shots = Shots -blocks.reload = Shots/Second -blocks.ammo = Ammo +blocks.powercapacity = Energiakapasiteetti +blocks.powershot = Energiaa/Ammus +blocks.damage = Vahinko +blocks.targetsair = Hyökkää Ilmaan +blocks.targetsground = Hyökkää Maahan +blocks.itemsmoved = Liikkumisnopeus +blocks.launchtime = Aika Laukaisujen Välillä +blocks.shootrange = Kantama +blocks.size = Koko +blocks.liquidcapacity = Neste Kapasiteetti +blocks.powerrange = Energia Kantama +blocks.powerconnections = Maksimi konnektio määrä +blocks.poweruse = Energian Käyttö +blocks.powerdamage = Energia/Vahinko +blocks.itemcapacity = Tavara Kapasiteetti +blocks.basepowergeneration = Kanta Enegian Generointi +blocks.productiontime = Produktion Aika +blocks.repairtime = Kokonaisen Palikan Korjaus Aika +blocks.speedincrease = Nopeuden Kasvu +blocks.range = Etäisyys +blocks.drilltier = Porattavat +blocks.drillspeed = Kanta Poran Nopeus +blocks.boosteffect = Boostaamisen Vaikutus +blocks.maxunits = Maksimi Määrä Yksikköjä +blocks.health = Elämäpisteet +blocks.buildtime = Rakentamisen Aika +blocks.buildcost = Rakentamisen Hinta +blocks.inaccuracy = Epätarkkuus +blocks.shots = Ammusta +blocks.reload = Ammusta/Sekunnissa +blocks.ammo = Ammus -bar.drilltierreq = Better Drill Required -bar.drillspeed = Drill Speed: {0}/s -bar.pumpspeed = Pump Speed: {0}/s -bar.efficiency = Efficiency: {0}% -bar.powerbalance = Power: {0}/s -bar.powerstored = Stored: {0}/{1} -bar.poweramount = Power: {0} -bar.poweroutput = Power Output: {0} -bar.items = Items: {0} -bar.capacity = Capacity: {0} -bar.liquid = Liquid -bar.heat = Heat -bar.power = Power -bar.progress = Build Progress -bar.spawned = Units: {0}/{1} -bar.input = Input -bar.output = Output +bar.drilltierreq = Parempi Pora Vaadittu +bar.drillspeed = Poran Nopeus: {0}/s +bar.pumpspeed = Pumpun Nopeus: {0}/s +bar.efficiency = Tehokkuus: {0}% +bar.powerbalance = Energia: {0}/s +bar.powerstored = Säilöttynä: {0}/{1} +bar.poweramount = Energia: {0} +bar.poweroutput = Energian Ulostulo: {0} +bar.items = Tavaroita: {0} +bar.capacity = Kapasiteetti: {0} +bar.liquid = Neste +bar.heat = Lämpö +bar.power = Energia +bar.progress = Rakennuksen Edistys +bar.spawned = Yksikköjä: {0}/{1} +bar.input = Sisääntulo +bar.output = Ulostulo -bullet.damage = [stat]{0}[lightgray] damage -bullet.splashdamage = [stat]{0}[lightgray] area dmg ~[stat] {1}[lightgray] tiles -bullet.incendiary = [stat]incendiary -bullet.homing = [stat]homing -bullet.shock = [stat]shock -bullet.frag = [stat]frag +bullet.damage = [stat]{0}[lightgray] Vahinko +bullet.splashdamage = [stat]{0}[lightgray] Alue vahinko ~[stat] {1}[lightgray] palikkaa +bullet.incendiary = [stat]sytyttävä +bullet.homing = [stat]itseohjautuva +bullet.shock = [stat]shokki +bullet.frag = [stat]sirpaloituva bullet.knockback = [stat]{0}[lightgray] knockback -bullet.freezing = [stat]freezing -bullet.tarred = [stat]tarred -bullet.multiplier = [stat]{0}[lightgray]x ammo multiplier -bullet.reload = [stat]{0}[lightgray]x fire rate +bullet.freezing = [stat]jäädyttävä +bullet.tarred = [stat]tervattu +bullet.multiplier = [stat]{0}[lightgray]x ammusten multiplikaatio +bullet.reload = [stat]{0}[lightgray]x ammunta nopeus -unit.blocks = blocks -unit.powersecond = power units/second -unit.liquidsecond = liquid units/second -unit.itemssecond = items/second -unit.liquidunits = liquid units -unit.powerunits = power units -unit.degrees = degrees -unit.seconds = seconds -unit.persecond = /sec -unit.timesspeed = x speed +unit.blocks = palikat +unit.powersecond = energia yksikköä/sekunti +unit.liquidsecond = neste yksikköä/sekunti +unit.itemssecond = esinettä/sekunti +unit.liquidunits = neste yksikköä +unit.powerunits = energia yksikköä +unit.degrees = astetta +unit.seconds = sekunttia +unit.persecond = /s +unit.timesspeed = x nopeus unit.percent = % -unit.items = items -unit.thousands = k +unit.items = esinettä +unit.thousands = t unit.millions = mil -category.general = General -category.power = Power -category.liquids = Liquids -category.items = Items -category.crafting = Input/Output -category.shooting = Shooting -category.optional = Optional Enhancements -setting.landscape.name = Lock Landscape -setting.shadows.name = Shadows -setting.blockreplace.name = Automatic Block Suggestions -setting.linear.name = Linear Filtering -setting.hints.name = Hints -setting.buildautopause.name = Auto-Pause Building -setting.animatedwater.name = Animated Water -setting.animatedshields.name = Animated Shields -setting.antialias.name = Antialias[lightgray] (requires restart)[] -setting.indicators.name = Enemy/Ally Indicators -setting.autotarget.name = Auto-Target -setting.keyboard.name = Mouse+Keyboard Controls -setting.touchscreen.name = Touchscreen Controls -setting.fpscap.name = Max FPS -setting.fpscap.none = None +category.general = Yleinen +category.power = Energia +category.liquids = Neste +category.items = Tavarat +category.crafting = Ulos/Sisääntulo +category.shooting = Ammunta +category.optional = Mahdolliset Lumoukset +setting.landscape.name = Lukitse tasavaakaan +setting.shadows.name = Varjot +setting.blockreplace.name = Automaattisia Palikka Suosituksia +setting.linear.name = Lineararien Filteeraus +setting.hints.name = Vihjeet +setting.buildautopause.name = Automaattisest Pysäytä Rakentaessa +setting.animatedwater.name = Animoitu Vesi +setting.animatedshields.name = Animoitu Kilpi +setting.antialias.name = Antialiaasi[lightgray] (vaatii uudelleenkäynnistyksen)[] +setting.indicators.name = Vihollis/Puolulais Indikaattorit +setting.autotarget.name = Automaatinen Tähtäys +setting.keyboard.name = Hiiri+Näppäimistö Kontrollit +setting.touchscreen.name = Kosketusnäyttö kontrollit +setting.fpscap.name = Maksimi FPS +setting.fpscap.none = Ei Mitään setting.fpscap.text = {0} FPS -setting.uiscale.name = UI Scaling[lightgray] (require restart)[] -setting.swapdiagonal.name = Always Diagonal Placement -setting.difficulty.training = Training -setting.difficulty.easy = Easy -setting.difficulty.normal = Normal -setting.difficulty.hard = Hard -setting.difficulty.insane = Insane -setting.difficulty.name = Difficulty: -setting.screenshake.name = Screen Shake -setting.effects.name = Display Effects -setting.destroyedblocks.name = Display Destroyed Blocks +setting.uiscale.name = UI Koko[lightgray] (vaatii uudelleenkäynnistyksen)[] +setting.swapdiagonal.name = Aina Vino Korvaus +setting.difficulty.training = Treeni +setting.difficulty.easy = Helppo +setting.difficulty.normal = Keskivaikea +setting.difficulty.hard = Haastava +setting.difficulty.insane = Järjetön +setting.difficulty.name = Vaikeustaso: +setting.screenshake.name = Näytön keikkuminen +setting.effects.name = Naytön Efektit +setting.destroyedblocks.name = Näytä Tuhoutuneet Palikat setting.conveyorpathfinding.name = Conveyor Placement Pathfinding setting.coreselect.name = Allow Schematic Cores -setting.sensitivity.name = Controller Sensitivity -setting.saveinterval.name = Save Interval -setting.seconds = {0} Seconds +setting.sensitivity.name = Kontrollin Herkkyys +setting.saveinterval.name = Tallennuksen Aikaväli +setting.seconds = {0} Sekunttia setting.blockselecttimeout.name = Block Select Timeout -setting.milliseconds = {0} milliseconds +setting.milliseconds = {0} millisekunttia setting.fullscreen.name = Fullscreen -setting.borderlesswindow.name = Borderless Window[lightgray] (may require restart) -setting.fps.name = Show FPS -setting.blockselectkeys.name = Show Block Select Keys +setting.borderlesswindow.name = Borderless Window[lightgray] (vaatii uudelleenkäynnistyksen) +setting.fps.name = Näytä FPS +setting.blockselectkeys.name = Bäytä Palikan Selektio Kontrollit setting.vsync.name = VSync -setting.pixelate.name = Pixelate[lightgray] (disables animations) -setting.minimap.name = Show Minimap -setting.position.name = Show Player Position -setting.musicvol.name = Music Volume -setting.ambientvol.name = Ambient Volume -setting.mutemusic.name = Mute Music -setting.sfxvol.name = SFX Volume -setting.mutesound.name = Mute Sound +setting.pixelate.name = Pixeloi[lightgray] (poistaa animaation käytöstä) +setting.minimap.name = Näytä Minimappi +setting.position.name = Näytä pelaajan sijainti +setting.musicvol.name = Musiikin Äänenvoimakkuus +setting.ambientvol.name = Tausta Äänet +setting.mutemusic.name = Sulje Musiikki +setting.sfxvol.name = SFX Volyymi +setting.mutesound.name = Sulje Äänet setting.crashreport.name = Send Anonymous Crash Reports -setting.savecreate.name = Auto-Create Saves +setting.savecreate.name = Luo Automaattisesti Tallennukset setting.publichost.name = Public Game Visibility -setting.chatopacity.name = Chat Opacity -setting.lasersopacity.name = Power Laser Opacity -setting.playerchat.name = Display In-Game Chat +setting.chatopacity.name = Chatin Läpinäkymättömyys +setting.lasersopacity.name = Energia Laaserin Läpinäkymattämyys +setting.playerchat.name = Näytä Pelinsisäinen Keskustelu public.confirm = Do you want to make your game public?\n[accent]Anyone will be able to join your games.\n[lightgray]This can be changed later in Settings->Game->Public Game Visibility. public.beta = Note that beta versions of the game cannot make public lobbies. uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] seconds... -uiscale.cancel = Cancel & Exit +uiscale.cancel = Peruuta ja Poistu setting.bloom.name = Bloom keybind.title = Rebind Keys keybinds.mobile = [scarlet]Most keybinds here are not functional on mobile. Only basic movement is supported. category.general.name = General category.view.name = View category.multiplayer.name = Multiplayer -command.attack = Attack -command.rally = Rally -command.retreat = Retreat +command.attack = Hyökkää +command.rally = Kutsu Koolle +command.retreat = Palaa placement.blockselectkeys = \n[lightgray]Key: [{0}, keybind.clear_building.name = Clear Building keybind.press = Press a key... @@ -692,7 +692,7 @@ keybind.move_y.name = Move y keybind.mouse_move.name = Follow Mouse keybind.dash.name = Dash keybind.schematic_select.name = Select Region -keybind.schematic_menu.name = Schematic Menu +keybind.schematic_menu.name = Kaavio Valikko keybind.schematic_flip_x.name = Flip Schematic X keybind.schematic_flip_y.name = Flip Schematic Y keybind.category_prev.name = Previous Category @@ -711,7 +711,7 @@ keybind.block_select_07.name = Category/Block Select 7 keybind.block_select_08.name = Category/Block Select 8 keybind.block_select_09.name = Category/Block Select 9 keybind.block_select_10.name = Category/Block Select 10 -keybind.fullscreen.name = Toggle Fullscreen +keybind.fullscreen.name = Vaihda Fullscreen keybind.select.name = Select/Shoot keybind.diagonal_placement.name = Diagonal Placement keybind.pick.name = Pick Block @@ -722,8 +722,8 @@ keybind.zoom.name = Zoom keybind.menu.name = Menu keybind.pause.name = Pause keybind.pause_building.name = Pause/Resume Building -keybind.minimap.name = Minimap -keybind.chat.name = Chat +keybind.minimap.name = Minimappi +keybind.chat.name = Chatti keybind.player_list.name = Player list keybind.console.name = Console keybind.rotate.name = Rotate @@ -736,20 +736,20 @@ keybind.drop_unit.name = Drop Unit keybind.zoom_minimap.name = Zoom minimap mode.help.title = Description of modes mode.survival.name = Survival -mode.survival.description = The normal mode. Limited resources and automatic incoming waves.\n[gray]Requires enemy spawns in the map to play. -mode.sandbox.name = Sandbox -mode.sandbox.description = Infinite resources and no timer for waves. -mode.editor.name = Editor +mode.survival.description = Normaali moodi. Rajoitettu määrä resursseja ja tasoilla on aika.\n[gray]Vaatii vihollis spawneja kartassa. +mode.sandbox.name = Hiekkalaatikko +mode.sandbox.description = Ikuisesti resursseja ja tasoilla ei ole aikaa. +mode.editor.name = Editori mode.pvp.name = PvP mode.pvp.description = Fight against other players locally.\n[gray]Requires at least 2 differently-colored cores in the map to play. mode.attack.name = Attack mode.attack.description = Destroy the enemy's base. No waves.\n[gray]Requires a red core in the map to play. mode.custom = Custom Rules -rules.infiniteresources = Infinite Resources -rules.reactorexplosions = Reactor Explosions -rules.wavetimer = Wave Timer -rules.waves = Waves +rules.infiniteresources = Ikuisesti Resursseja +rules.reactorexplosions = Reaktori Räjähdykset +rules.wavetimer = Tasojen Aikaraja +rules.waves = Tasot rules.attack = Attack Mode rules.enemyCheat = Infinite AI (Red Team) Resources rules.unitdrops = Unit Drops @@ -778,31 +778,31 @@ rules.title.experimental = Experimental rules.lighting = Lighting rules.ambientlight = Ambient Light -content.item.name = Items -content.liquid.name = Liquids -content.unit.name = Units -content.block.name = Blocks -content.mech.name = Mechs -item.copper.name = Copper -item.lead.name = Lead -item.coal.name = Coal -item.graphite.name = Graphite -item.titanium.name = Titanium -item.thorium.name = Thorium -item.silicon.name = Silicon -item.plastanium.name = Plastanium -item.phase-fabric.name = Phase Fabric -item.surge-alloy.name = Surge Alloy -item.spore-pod.name = Spore Pod +content.item.name = Tavarat +content.liquid.name = Nesteet +content.unit.name = Yksiköt +content.block.name = Palikat +content.mech.name = Yksikkö +item.copper.name = Kupari +item.lead.name = Lyijy +item.coal.name = Hiili +item.graphite.name = Grafiitti +item.titanium.name = Titaani +item.thorium.name = Torium +item.silicon.name = Pii +item.plastanium.name = Plastaniumi +item.phase-fabric.name = Kiihde Kuitu +item.surge-alloy.name = Taite Seos +item.spore-pod.name = Itiö Palko item.sand.name = Hiekka -item.blast-compound.name = Blast Compound -item.pyratite.name = Pyratite -item.metaglass.name = Metaglass -item.scrap.name = Scrap +item.blast-compound.name = Räjähde Yhdiste +item.pyratite.name = Pyratiitti +item.metaglass.name = Metallilasi +item.scrap.name = Romu liquid.water.name = Vesi -liquid.slag.name = Slag -liquid.oil.name = Oil -liquid.cryofluid.name = Cryofluid +liquid.slag.name = Kuona +liquid.oil.name = Öljy +liquid.cryofluid.name = Kryoneste mech.alpha-mech.name = Alpha mech.alpha-mech.weapon = Heavy Repeater mech.alpha-mech.ability = Regeneration @@ -824,22 +824,22 @@ mech.trident-ship.name = Trident mech.trident-ship.weapon = Bomb Bay mech.glaive-ship.name = Glaive mech.glaive-ship.weapon = Flame Repeater -item.corestorable = [lightgray]Storable in Core: {0} -item.explosiveness = [lightgray]Explosiveness: {0}% +item.corestorable = [lightgray]Säilöttävissä Ytimeen: {0} +item.explosiveness = [lightgray]Räjädysmäisyys: {0}% item.flammability = [lightgray]Flammability: {0}% item.radioactivity = [lightgray]Radioactivity: {0}% -unit.health = [lightgray]Health: {0} -unit.speed = [lightgray]Speed: {0} -mech.weapon = [lightgray]Weapon: {0} -mech.health = [lightgray]Health: {0} -mech.itemcapacity = [lightgray]Item Capacity: {0} -mech.minespeed = [lightgray]Mining Speed: {0}% -mech.minepower = [lightgray]Mining Power: {0} -mech.ability = [lightgray]Ability: {0} -mech.buildspeed = [lightgray]Building Speed: {0}% -liquid.heatcapacity = [lightgray]Heat Capacity: {0} -liquid.viscosity = [lightgray]Viscosity: {0} -liquid.temperature = [lightgray]Temperature: {0} +unit.health = [lightgray]Elämäpisteet: {0} +unit.speed = [lightgray]Nopeus: {0} +mech.weapon = [lightgray]Ase: {0} +mech.health = [lightgray]Elämäpisteet: {0} +mech.itemcapacity = [lightgray]Tavara Kapasiteetti: {0} +mech.minespeed = [lightgray]Louhimis Nopeus: {0}% +mech.minepower = [lightgray]Louhimis Voima: {0} +mech.ability = [lightgray]Spesiaalikyky: {0} +mech.buildspeed = [lightgray]Rakennus Nopeus: {0}% +liquid.heatcapacity = [lightgray]Lämpö Kapasiteetti: {0} +liquid.viscosity = [lightgray]Tahmeus: {0} +liquid.temperature = [lightgray]Lämpö: {0} block.sand-boulder.name = Sand Boulder block.grass.name = Grass @@ -865,24 +865,24 @@ block.scrap-wall-huge.name = Huge Scrap Wall block.scrap-wall-gigantic.name = Gigantic Scrap Wall block.thruster.name = Thruster block.kiln.name = Kiln -block.graphite-press.name = Graphite Press -block.multi-press.name = Multi-Press -block.constructing = {0} [lightgray](Constructing) -block.spawn.name = Enemy Spawn -block.core-shard.name = Core: Shard -block.core-foundation.name = Core: Foundation -block.core-nucleus.name = Core: Nucleus -block.deepwater.name = Deep Water -block.water.name = Water -block.tainted-water.name = Tainted Water +block.graphite-press.name = Grafiitti Puristin +block.multi-press.name = Multi-Puristin +block.constructing = {0} [lightgray](Rakentamassa) +block.spawn.name = Vihollis Spawni +block.core-shard.name = Ydin: Siru +block.core-foundation.name = Ydin: Pohjaus +block.core-nucleus.name = Ydin: Tuma +block.deepwater.name = Syvä Vesi +block.water.name = Vesi +block.tainted-water.name = Pilattu Vesi block.darksand-tainted-water.name = Dark Sand Tainted Water -block.tar.name = Tar -block.stone.name = Stone -block.sand.name = Sand -block.darksand.name = Dark Sand -block.ice.name = Ice -block.snow.name = Snow -block.craters.name = Craters +block.tar.name = Terva +block.stone.name = Kivi +block.sand.name = Hiekka +block.darksand.name = Tumma Hiekka +block.ice.name = Jää +block.snow.name = Lumi +block.craters.name = Kraatterit block.sand-water.name = Sand water block.darksand-water.name = Dark Sand Water block.char.name = Char diff --git a/core/assets/bundles/bundle_it.properties b/core/assets/bundles/bundle_it.properties index cba4075537..fd746bb659 100644 --- a/core/assets/bundles/bundle_it.properties +++ b/core/assets/bundles/bundle_it.properties @@ -40,7 +40,7 @@ schematic = Schematica schematic.add = Salva Schematica... schematics = Schematiche schematic.replace = Una schematica con questo nome esiste già. Sostituirla? -schematic.import = Importa schematica... +schematic.import = Importa schematica schematic.exportfile = Esporta File schematic.importfile = Importa File schematic.browseworkshop = Naviga nel Workshop @@ -79,7 +79,7 @@ newgame = Nuova partita none = minimap = Minimappa position = Posizione -close = Chiuso +close = Chiudi website = Sito Web quit = Esci save.quit = Salva ed Esci @@ -138,7 +138,7 @@ research.list = [lightgray]Ricerca: research = Ricerca researched = [lightgray]{0} cercati. players = {0} giocatori online -players.single = {0} giocatori online +players.single = {0} giocatore online server.closing = [accent]Chiusura server... server.kicked.kick = Sei stato cacciato dal server! server.kicked.whitelist = Non sei presente nella whitelist. @@ -157,7 +157,7 @@ server.kicked.customClient = Questo server non supporta i client personalizzati. server.kicked.gameover = Game over! server.kicked.serverRestarting = Il server si sta riavviando. server.versions = Versione client:[accent] {0}[]\nVersione server:[accent] {1}[] -host.info = Il pulsante [accent]Ospita[] ospita un server sulla porta [scarlet]6567[].[] Chiunque sulla stessa [lightgray]rete Wi-Fi o locale[] dovrebbe essere in grado di vedere il server nell'elenco server.\nSe vuoi che le persone siano in grado di connettersi ovunque tramite il tuo IP, è richiesto il [accent]port forwarding[].\n\n[lightgray]Nota: se qualcuno sta riscontrando problemi durante la connessione al gioco LAN, assicurati di aver consentito a Mindustry di accedere alla rete locale nelle impostazioni del firewall. +host.info = Il pulsante [accent]Ospita[] ospita un server sulla porta [scarlet]6567[].[] Chiunque sulla stessa [lightgray]rete Wi-Fi o locale[] dovrebbe essere in grado di vedere il server nell'elenco server.\nSe vuoi che le persone siano in grado di connettersi ovunque tramite il tuo IP, è necessario eseguire il [accent]port forwarding[].\n\n[lightgray]Nota: se qualcuno sta riscontrando problemi durante la connessione al gioco LAN, assicurati di aver consentito a Mindustry di accedere alla rete locale nelle impostazioni del firewall. join.info = Qui è possibile inserire l'[accent]IP del server[] a cui connettersi, o scoprire [accent]un server sulla rete locale[] disponibile.\nSono supportati sia il multiplayer LAN che WAN.\n\n[lightgray]Nota: non esiste un elenco automatico dei server globali; se desideri connetterti a qualcuno tramite il suo IP, è necessario chiedere all'host il proprio IP. hostserver = Ospita Server invitefriends = Invita Amici @@ -264,7 +264,7 @@ reloading = [accent]Ricaricamento delle mods... saving = [accent]Salvataggio in corso... cancelbuilding = [accent][[{0}][] per pulire la selezione selectschematic = [accent][[{0}][] per selezionare+copiare -pausebuilding = [accent][[{0}][] to pause building +pausebuilding = [accent][[{0}][] per smettere di costruire resumebuilding = [scarlet][[{0}][] per riprendere a costruire wave = [accent]Ondata {0} wave.waiting = [lightgray]Ondata tra {0} @@ -532,6 +532,8 @@ error.crashtitle = Si è verificato un errore blocks.input = Ingresso blocks.output = Uscita blocks.booster = Potenziamenti +blocks.tiles = Blocchi Richiesti +blocks.affinities = Affinità block.unknown = [lightgray]??? blocks.powercapacity = Capacità Energetica blocks.powershot = Danno/Colpo @@ -934,7 +936,6 @@ block.lancer.name = Lanciere block.conveyor.name = Nastro Trasportatore block.titanium-conveyor.name = Nastro Avanzato block.armored-conveyor.name = Nastro Corazzato -block.armored-conveyor.description = Trasporta gli oggetti alla stessa velocità del nastro avanzato, ma è più resistente. Accetta input dai lati solo da altri nastri. block.junction.name = Incrocio block.router.name = Distributore block.distributor.name = Distributore Grande @@ -1140,12 +1141,12 @@ block.spore-press.description = Comprime le spore in petrolio. block.pulverizer.description = Polverizza la pietra.\nUtile quando manca la sabbia naturale. block.coal-centrifuge.description = Solidifica il petrolio in pezzi di carbone. block.incinerator.description = Elimina qualsiasi oggetto o liquido in eccesso. -block.power-void.description = Elimina tutta l'energia che riceve, esiste solo nella modalità creativa. -block.power-source.description = Produce energia infinita, esiste solo nella modalità creativa. -block.item-source.description = Produce oggetti infiniti, esiste solo nella modalità creativa. -block.item-void.description = Elimina gli oggetti che vi entrano senza bisogno di energia, esiste solo nella modalità creativa. +block.power-void.description = Elimina tutta l'energia che riceve. Esiste solo nella modalità creativa. +block.power-source.description = Produce energia infinita. Esiste solo nella modalità creativa. +block.item-source.description = Produce oggetti infiniti. Esiste solo nella modalità creativa. +block.item-void.description = Elimina gli oggetti che vi entrano senza bisogno di energia. Esiste solo nella modalità creativa. block.liquid-source.description = Emette continuamente liquidi. Esiste solo nella modalità creativa. -block.liquid-void.description = Elimina i liquidi in entrata, esiste solo nella modalità creativa. +block.liquid-void.description = Elimina i liquidi in entrata. Esiste solo nella modalità creativa. block.copper-wall.description = Un blocco difensivo economico.\nUtile per proteggere il Nucleo e le torrette nelle prime ondate. block.copper-wall-large.description = Un blocco difensivo economico.\nUtile per proteggere il Nucleo e le torrette nelle prime ondate.\nOccupa più blocchi. block.titanium-wall.description = Un blocco difensivo moderatamente forte.\nFornisce una protezione moderata dai nemici. @@ -1165,18 +1166,19 @@ block.mend-projector.description = Ripara periodicamente blocchi nelle vicinanze block.overdrive-projector.description = Aumenta la velocità di edifici vicini come trivelle e nastri trasportatori. block.force-projector.description = Crea un campo di forza esagonale attorno a sé, proteggendo gli edifici e le unità all'interno da danni causati da proiettili. block.shock-mine.description = Danneggia i nemici che la calpestano. Quasi invisibile al nemico. -block.conveyor.description = Nastro di base. Sposta gli oggetti in avanti e li deposita automaticamente in altri blocchi. Ruotabile. +block.conveyor.description = Nastro di base. Sposta gli oggetti in avanti e li deposita automaticamente in altri blocchi. È rotabile. block.titanium-conveyor.description = Nastro avanzato. Sposta gli oggetti più velocemente dei nastri standard. +block.armored-conveyor.description = Trasporta gli oggetti alla stessa velocità del nastro avanzato, ma è più resistente. Accetta input dai lati solo da altri nastri. block.junction.description = Permette di incrociare nastri che trasportano materiali diversi in posizioni diverse. block.bridge-conveyor.description = Consente il trasporto di oggetti fino a 3 blocchi ad un altro nastro sopraelevato.\nPuò passare sopra ad altri blocchi od edifici. block.phase-conveyor.description = Nastro avanzato. Consuma energia per teletrasportare gli oggetti su un altro nastro di fase collegato. block.sorter.description = Divide gli oggetti. Se l'oggetto corrisponde a quello selezionato, Può passare. Altrimenti viene espulso sui lati. -block.inverted-sorter.description = Elabora gli oggetti come uno smistatore standard, ma in uscita dà gli elementi selezionati ai lati. +block.inverted-sorter.description = Elabora gli oggetti come uno filtro standard, ma in uscita dà gli elementi selezionati ai lati. block.router.description = Accetta gli elementi da una direzione e li emette fino a 3 altre direzioni allo stesso modo. Utile per suddividere i materiali da una fonte a più destinazioni. block.distributor.description = Un distributore avanzato che divide gli oggetti in altre 7 direzioni allo stesso modo. block.overflow-gate.description = Distribuisce gli oggetti ai lati se il nastro davanti a sé è saturo. block.underflow-gate.description = L'opposto di un separatore per eccesso. Distribuisce gli oggetti nel nastro davanti a sé se i nastri a destra e a sinistra sono saturi. -block.mass-driver.description = Ultimo blocco di trasporto di oggetti. Raccoglie diversi oggetti e poi li spara su un'altra Lìlancia materiali a lungo raggio. +block.mass-driver.description = Ultimo blocco di trasporto di oggetti. Raccoglie diversi oggetti e poi li spara su un'altra lancia materiali a lungo raggio. block.mechanical-pump.description = Una pompa economica a bassa efficienza, ma nessun consumo di energia. block.rotary-pump.description = Una pompa avanzata che raddoppia la velocità consumando energia. block.thermal-pump.description = La pompa migliore. Tre volte più veloce di una pompa meccanica e l'unica pompa in grado di recuperare la lava. diff --git a/core/assets/bundles/bundle_uk_UA.properties b/core/assets/bundles/bundle_uk_UA.properties index b78e537eff..3bfa58ede8 100644 --- a/core/assets/bundles/bundle_uk_UA.properties +++ b/core/assets/bundles/bundle_uk_UA.properties @@ -251,6 +251,7 @@ copylink = Скопіювати посилання back = Назад data.export = Вивантажити дані data.import = Завантажити дані +data.openfolder = Відкрити теку з даними data.exported = Дані вивантажено. data.invalid = Це не дійсні ігрові дані. data.import.confirm = Вивантаження зовнішніх даних перезапише[scarlet] ВСІ[] ваші поточні ігрові дані.\n[accent]Це неможливо скасувати![]\n\nЩойно дані імпортуються, гра негайно закриється. @@ -587,7 +588,7 @@ bullet.splashdamage = [stat]{0}[lightgray] шкода по ділянці ~[stat bullet.incendiary = [stat]запальний bullet.homing = [stat]самонаведення bullet.shock = [stat]шок -bullet.frag = [stat]осколкова граната +bullet.frag = [stat]шкода по ділянці bullet.knockback = [stat]{0}[lightgray] відкидання bullet.freezing = [stat]заморожування bullet.tarred = [stat]дьогтьовий @@ -667,6 +668,7 @@ setting.savecreate.name = Автоматичне створення збереж setting.publichost.name = Загальнодоступність гри setting.chatopacity.name = Непрозорість чату setting.lasersopacity.name = Непрозорість лазерів енергопостачання +setting.bridgeopacity.name = Місткість мостів setting.playerchat.name = Відображати хмару чата над гравцями public.confirm = Ви хочете зробити цю гру загальнодоступною?\n[lightgray]Це можна змінити у Налаштування→Гра→Загальнодоступність гри public.beta = Зауважте, що в бета-версії гри ви не можете робити публічні ігри. @@ -1033,7 +1035,7 @@ block.force-projector.name = Силовий проектор block.arc.name = Дуга block.rtg-generator.name = Радіоізотопний термоелектричний генератор block.spectre.name = Спектр -block.meltdown.name = Випалювач +block.meltdown.name = Розплавитель block.container.name = Склад block.launch-pad.name = Стартовий майданчик block.launch-pad-large.name = Великий стартовий майданчик @@ -1056,7 +1058,7 @@ unit.fortress.name = Фортеця unit.revenant.name = Потойбічний вбивця unit.eruptor.name = Вивиргатель unit.chaos-array.name = Масив хаосу -unit.eradicator.name = Випалювач +unit.eradicator.name = Викорінювач unit.lich.name = Лич unit.reaper.name = Жнець tutorial.next = [lightgray]<Натисніть для продовження> @@ -1198,7 +1200,7 @@ block.rtg-generator.description = Простий, надійний генера block.solar-panel.description = Забезпечує невелику кількість енергії від сонця. block.solar-panel-large.description = Значно ефективніша версія стандартної сонячної панелі. block.thorium-reactor.description = Виробляє значну кількість енергії з торію. Вимагає постійного охолодження. Вибухне сильно, якщо подаватиметься недостатньо кількості теплоносія. Вихідна потужність залежить від повноти, базова потужність генерується на повній потужності. -block.impact-reactor.description = Удосконалений генератор, здатний створювати величезну кількість енергії при максимальній ефективності. Для швидкого запуску процесу потрібно значне введення енергії. +block.impact-reactor.description = Удосконалений генератор, здатний створювати величезну кількість енергії при максимальній ефективності. Для запуску процесу потрібно значні обсяги енергії. block.mechanical-drill.description = Недорогий бур. Розміщуючи їх на відповідних плитках, виводить предмети повільним темпом нескінченно. Здатний видобувати лише мідь, свинець і вугілля. block.pneumatic-drill.description = Вдосконалений бур, здатний добувати титан. Шахти швидше, ніж механічна дриль. block.laser-drill.description = Дозволяє виконувати свердління ще швидше за допомогою лазерної технології, але вимагає енергії. Здатний до видобутку торію. diff --git a/core/build.gradle b/core/build.gradle index abcec6d8f6..ea07c810b3 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,4 +1,4 @@ apply plugin: "java" sourceCompatibility = 1.8 [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' -sourceSets.main.java.srcDirs = ["src/"] \ No newline at end of file +sourceSets.main.java.srcDirs = ["src/", "$buildDir/generated/sources/annotationProcessor/java/main"] \ No newline at end of file diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index 975cd87232..5159f8e7c5 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -103,9 +103,10 @@ public class UnitTypes implements ContentList{ shootSound = Sounds.explosion; bullet = new BombBulletType(2f, 3f, "clear"){{ hitEffect = Fx.pulverize; - lifetime = 2f; + lifetime = 30f; speed = 1.1f; splashDamageRadius = 55f; + instantDisappear = true; splashDamage = 30f; killShooter = true; }}; @@ -126,7 +127,6 @@ public class UnitTypes implements ContentList{ shootSound = Sounds.flame; length = 1f; reload = 14f; - range = 30f; alternate = true; recoil = 1f; ejectEffect = Fx.none; diff --git a/core/src/mindustry/core/NetClient.java b/core/src/mindustry/core/NetClient.java index 89d2a600f8..9508ad94e3 100644 --- a/core/src/mindustry/core/NetClient.java +++ b/core/src/mindustry/core/NetClient.java @@ -266,6 +266,11 @@ public class NetClient implements ApplicationListener{ ui.showText("", message); } + @Remote(variants = Variant.both) + public static void onInfoToast(String message, float duration){ + ui.showInfoToast(message, duration); + } + @Remote(variants = Variant.both) public static void onSetRules(Rules rules){ state.rules = rules; diff --git a/core/src/mindustry/core/NetServer.java b/core/src/mindustry/core/NetServer.java index 4a0564ce42..3f7e0d02ee 100644 --- a/core/src/mindustry/core/NetServer.java +++ b/core/src/mindustry/core/NetServer.java @@ -264,7 +264,7 @@ public class NetServer implements ApplicationListener{ page --; - if(page > pages || page < 0){ + if(page >= pages || page < 0){ player.sendMessage("[scarlet]'page' must be a number between[orange] 1[] and[orange] " + pages + "[scarlet]."); return; } @@ -472,7 +472,7 @@ public class NetServer implements ApplicationListener{ Call.onPlayerDisconnect(player.id); } - Log.info("&lm[{1}] &lc{0} has disconnected. &lg&fi({2})", player.name, player.uuid, reason); + if(Config.showConnectMessages.bool()) Log.info("&lm[{1}] &lc{0} has disconnected. &lg&fi({2})", player.name, player.uuid, reason); } player.remove(); @@ -620,8 +620,10 @@ public class NetServer implements ApplicationListener{ player.add(); player.con.hasConnected = true; - if(Config.showConnectMessages.bool()) Call.sendMessage("[accent]" + player.name + "[accent] has connected."); - Log.info("&lm[{1}] &y{0} has connected. ", player.name, player.uuid); + if(Config.showConnectMessages.bool()){ + Call.sendMessage("[accent]" + player.name + "[accent] has connected."); + Log.info("&lm[{1}] &y{0} has connected. ", player.name, player.uuid); + } if(!Config.motd.string().equalsIgnoreCase("off")){ player.sendMessage(Config.motd.string()); diff --git a/core/src/mindustry/core/UI.java b/core/src/mindustry/core/UI.java index 63a09aecc6..ab7587e9d5 100644 --- a/core/src/mindustry/core/UI.java +++ b/core/src/mindustry/core/UI.java @@ -289,6 +289,19 @@ public class UI implements ApplicationListener, Loadable{ Core.scene.add(table); } + public void showInfoToast(String info, float duration){ + Table table = new Table(); + table.setFillParent(true); + table.update(() -> { + if(state.is(State.menu)){ + table.remove(); + } + }); + table.actions(Actions.delay(duration * 0.9f), Actions.fadeOut(duration * 0.1f, Interpolation.fade), Actions.remove()); + table.top().table(Styles.black3, t -> t.margin(4).add(info).style(Styles.outlineLabel)).padTop(10); + Core.scene.add(table); + } + public void showInfo(String info){ new Dialog(""){{ getCell(cont).growX(); @@ -426,7 +439,6 @@ public class UI implements ApplicationListener, Loadable{ dialog.show(); } - public void showCustomConfirm(String title, String text, String yes, String no, Runnable confirmed, Runnable denied){ FloatingDialog dialog = new FloatingDialog(title); dialog.cont.add(text).width(mobile ? 400f : 500f).wrap().pad(4f).get().setAlignment(Align.center, Align.center); @@ -459,11 +471,11 @@ public class UI implements ApplicationListener, Loadable{ public String formatAmount(int number){ if(number >= 1000000){ - return Strings.fixed(number / 1000000f, 1) + "[gray]" + Core.bundle.getOrNull("unit.millions") + "[]"; + return Strings.fixed(number / 1000000f, 1) + "[gray]" + Core.bundle.get("unit.millions") + "[]"; }else if(number >= 10000){ - return number / 1000 + "[gray]k[]"; + return number / 1000 + "[gray]" + Core.bundle.get("unit.thousands") + "[]"; }else if(number >= 1000){ - return Strings.fixed(number / 1000f, 1) + "[gray]" + Core.bundle.getOrNull("unit.thousands") + "[]"; + return Strings.fixed(number / 1000f, 1) + "[gray]" + Core.bundle.get("unit.thousands") + "[]"; }else{ return number + ""; } diff --git a/core/src/mindustry/ctype/UnlockableContent.java b/core/src/mindustry/ctype/UnlockableContent.java index af194377bf..5261560399 100644 --- a/core/src/mindustry/ctype/UnlockableContent.java +++ b/core/src/mindustry/ctype/UnlockableContent.java @@ -1,6 +1,7 @@ package mindustry.ctype; import arc.*; +import arc.util.ArcAnnotate.*; import mindustry.annotations.Annotations.*; import arc.graphics.g2d.*; import arc.scene.ui.layout.*; @@ -13,7 +14,7 @@ public abstract class UnlockableContent extends MappableContent{ /** Localized, formal name. Never null. Set to block name if not found in bundle. */ public String localizedName; /** Localized description. May be null. */ - public String description; + public @Nullable String description; /** Icons by Cicon ID.*/ protected TextureRegion[] cicons = new TextureRegion[mindustry.ui.Cicon.all.length]; @@ -24,6 +25,10 @@ public abstract class UnlockableContent extends MappableContent{ this.description = Core.bundle.getOrNull(getContentType() + "." + this.name + ".description"); } + public String displayDescription(){ + return minfo.mod == null ? description : description + "\n" + Core.bundle.format("mod.display", minfo.mod.meta.displayName()); + } + /** Generate any special icons for this content. Called asynchronously.*/ @CallSuper public void createIcons(MultiPacker packer){ diff --git a/core/src/mindustry/entities/bullet/BulletType.java b/core/src/mindustry/entities/bullet/BulletType.java index 51e74cf383..65a399b121 100644 --- a/core/src/mindustry/entities/bullet/BulletType.java +++ b/core/src/mindustry/entities/bullet/BulletType.java @@ -3,8 +3,7 @@ package mindustry.entities.bullet; import arc.audio.*; import arc.math.*; import mindustry.content.*; -import mindustry.ctype.Content; -import mindustry.ctype.ContentType; +import mindustry.ctype.*; import mindustry.entities.*; import mindustry.entities.Effects.*; import mindustry.entities.effect.*; @@ -41,7 +40,9 @@ public abstract class BulletType extends Content{ public float recoil; /** Whether to kill the shooter when this is shot. For suicide bombers. */ public boolean killShooter; - + /** Whether to instantly make the bullet disappear. */ + public boolean instantDisappear; + /** Damage dealt in splash. 0 to disable.*/ public float splashDamage = 0f; /** Knockback in velocity. */ public float knockback; @@ -151,6 +152,10 @@ public abstract class BulletType extends Content{ if(killShooter && b.getOwner() instanceof HealthTrait){ ((HealthTrait)b.getOwner()).kill(); } + + if(instantDisappear){ + b.time(lifetime); + } } public void update(Bullet b){ diff --git a/core/src/mindustry/entities/type/base/GroundUnit.java b/core/src/mindustry/entities/type/base/GroundUnit.java index 56ba404a30..bf400dd24a 100644 --- a/core/src/mindustry/entities/type/base/GroundUnit.java +++ b/core/src/mindustry/entities/type/base/GroundUnit.java @@ -42,7 +42,6 @@ public class GroundUnit extends BaseUnit{ moveToCore(PathTarget.enemyCores); } }else{ - float dst = dst(core); if(dst < getWeapon().bullet.range() / 1.1f){ @@ -170,6 +169,7 @@ public class GroundUnit extends BaseUnit{ if(!Units.invalidateTarget(target, this)){ if(dst(target) < getWeapon().bullet.range()){ + rotate(angleTo(target)); if(Angles.near(angleTo(target), rotation, 13f)){ diff --git a/core/src/mindustry/graphics/Drawf.java b/core/src/mindustry/graphics/Drawf.java index 2fd9b48087..f3a31369da 100644 --- a/core/src/mindustry/graphics/Drawf.java +++ b/core/src/mindustry/graphics/Drawf.java @@ -43,6 +43,10 @@ public class Drawf{ } public static void arrow(float x, float y, float x2, float y2, float length, float radius){ + arrow(x, y, x2, y2, length, radius, Pal.accent); + } + + public static void arrow(float x, float y, float x2, float y2, float length, float radius, Color color){ float angle = Angles.angle(x, y, x2, y2); float space = 2f; Tmp.v1.set(x2, y2).sub(x, y).limit(length); @@ -50,7 +54,7 @@ public class Drawf{ Draw.color(Pal.gray); Fill.poly(vx, vy, 3, radius + space, angle); - Draw.color(Pal.accent); + Draw.color(color); Fill.poly(vx, vy, 3, radius, angle); Draw.color(); } diff --git a/core/src/mindustry/mod/Scripts.java b/core/src/mindustry/mod/Scripts.java index 546a3e7828..6d70437dbb 100644 --- a/core/src/mindustry/mod/Scripts.java +++ b/core/src/mindustry/mod/Scripts.java @@ -12,7 +12,7 @@ import org.mozilla.javascript.*; public class Scripts implements Disposable{ private final Array blacklist = Array.with("net", "files", "reflect", "javax", "rhino", "file", "channels", "jdk", "runtime", "util.os", "rmi", "security", "org.", "sun.", "beans", "sql", "http", "exec", "compiler", "process", "system", - ".awt", "socket", "mod.scripts", "classloader", "oracle"); + ".awt", "socket", "classloader", "oracle"); private final Array whitelist = Array.with("mindustry.net"); private final Context context; private final String wrapper; diff --git a/core/src/mindustry/ui/ContentDisplay.java b/core/src/mindustry/ui/ContentDisplay.java index b3e49040e0..4f4f800ec7 100644 --- a/core/src/mindustry/ui/ContentDisplay.java +++ b/core/src/mindustry/ui/ContentDisplay.java @@ -28,7 +28,7 @@ public class ContentDisplay{ table.row(); if(block.description != null){ - table.add(block.description).padLeft(5).padRight(5).width(400f).wrap().fillX(); + table.add(block.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX(); table.row(); table.addImage().height(3).color(Color.lightGray).pad(8).padLeft(0).padRight(0).fillX(); @@ -76,7 +76,7 @@ public class ContentDisplay{ table.row(); if(item.description != null){ - table.add(item.description).padLeft(5).padRight(5).width(400f).wrap().fillX(); + table.add(item.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX(); table.row(); table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX(); @@ -110,7 +110,7 @@ public class ContentDisplay{ table.row(); if(liquid.description != null){ - table.add(liquid.description).padLeft(5).padRight(5).width(400f).wrap().fillX(); + table.add(liquid.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX(); table.row(); table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX(); @@ -145,7 +145,7 @@ public class ContentDisplay{ table.row(); if(mech.description != null){ - table.add(mech.description).padLeft(5).padRight(5).width(400f).wrap().fillX(); + table.add(mech.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX(); table.row(); table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX(); @@ -192,7 +192,7 @@ public class ContentDisplay{ table.row(); if(unit.description != null){ - table.add(unit.description).padLeft(5).padRight(5).width(400f).wrap().fillX(); + table.add(unit.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX(); table.row(); table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX(); diff --git a/core/src/mindustry/ui/dialogs/TechTreeDialog.java b/core/src/mindustry/ui/dialogs/TechTreeDialog.java index f6a200fc06..c35a5899b3 100644 --- a/core/src/mindustry/ui/dialogs/TechTreeDialog.java +++ b/core/src/mindustry/ui/dialogs/TechTreeDialog.java @@ -377,7 +377,7 @@ public class TechTreeDialog extends FloatingDialog{ infoTable.row(); if(node.block.description != null){ - infoTable.table(t -> t.margin(3f).left().labelWrap(node.block.description).color(Color.lightGray).growX()).fillX(); + infoTable.table(t -> t.margin(3f).left().labelWrap(node.block.displayDescription()).color(Color.lightGray).growX()).fillX(); } addChild(infoTable); diff --git a/core/src/mindustry/ui/fragments/MenuFragment.java b/core/src/mindustry/ui/fragments/MenuFragment.java index e81f5014e2..eb3283e8df 100644 --- a/core/src/mindustry/ui/fragments/MenuFragment.java +++ b/core/src/mindustry/ui/fragments/MenuFragment.java @@ -171,7 +171,7 @@ public class MenuFragment extends Fragment{ new Buttoni("$loadgame", Icon.download, () -> checkPlay(ui.load::show)), new Buttoni("$tutorial", Icon.info, () -> checkPlay(control::playTutorial)) ), - new Buttoni("$editor", Icon.terrain, () -> checkPlay(ui.maps::show)), steam ? new Buttoni("$workshop", Icon.save, platform::openWorkshop) : null, + new Buttoni("$editor", Icon.terrain, () -> checkPlay(ui.maps::show)), steam ? new Buttoni("$workshop", Icon.book, platform::openWorkshop) : null, new Buttoni(Core.bundle.get("mods"), Icon.bookOpen, ui.mods::show), //not enough space for this button //new Buttoni("$schematics", Icon.paste, ui.schematics::show), diff --git a/core/src/mindustry/world/blocks/distribution/MassDriver.java b/core/src/mindustry/world/blocks/distribution/MassDriver.java index eacef7d0eb..e5fc8bd681 100644 --- a/core/src/mindustry/world/blocks/distribution/MassDriver.java +++ b/core/src/mindustry/world/blocks/distribution/MassDriver.java @@ -192,6 +192,11 @@ public class MassDriver extends Block{ MassDriverEntity entity = tile.ent(); + for(Tile shooter : entity.waitingShooters){ + Drawf.circles(shooter.drawx(), shooter.drawy(), (tile.block().size / 2f + 1) * tilesize + sin - 2f, Pal.place); + Drawf.arrow(shooter.drawx(), shooter.drawy(), tile.drawx(), tile.drawy(), size * tilesize + sin, 4f + sin, Pal.place); + } + if(linkValid(tile)){ Tile target = world.tile(entity.link); Drawf.circles(target.drawx(), target.drawy(), (target.block().size / 2f + 1) * tilesize + sin - 2f, Pal.place); diff --git a/core/src/mindustry/world/blocks/power/PowerNode.java b/core/src/mindustry/world/blocks/power/PowerNode.java index 7a267abeef..65de453319 100644 --- a/core/src/mindustry/world/blocks/power/PowerNode.java +++ b/core/src/mindustry/world/blocks/power/PowerNode.java @@ -182,8 +182,11 @@ public class PowerNode extends PowerBlock{ if(tile == other){ if(other.entity.power.links.size == 0){ + int[] total = {0}; getPotentialLinks(tile, link -> { - if(!insulated(tile, link)) tile.configure(link.pos()); + if(!insulated(tile, link) && total[0]++ < maxNodes){ + tile.configure(link.pos()); + } }); }else{ while(entity.power.links.size > 0){ diff --git a/core/src/mindustry/world/blocks/production/GenericCrafter.java b/core/src/mindustry/world/blocks/production/GenericCrafter.java index ee0e9a3c30..3dd94822be 100644 --- a/core/src/mindustry/world/blocks/production/GenericCrafter.java +++ b/core/src/mindustry/world/blocks/production/GenericCrafter.java @@ -134,8 +134,6 @@ public class GenericCrafter extends Block{ return outputItem != null; } - - @Override public boolean shouldConsume(Tile tile){ if(outputItem != null && tile.entity.items.get(outputItem.item) >= itemCapacity){ diff --git a/core/src/mindustry/world/blocks/production/SolidPump.java b/core/src/mindustry/world/blocks/production/SolidPump.java index 395420069e..13db9f2e2c 100644 --- a/core/src/mindustry/world/blocks/production/SolidPump.java +++ b/core/src/mindustry/world/blocks/production/SolidPump.java @@ -5,6 +5,7 @@ import arc.graphics.g2d.Draw; import arc.graphics.g2d.TextureRegion; import arc.math.Mathf; import arc.util.*; +import arc.util.ArcAnnotate.*; import mindustry.content.Fx; import mindustry.content.Liquids; import mindustry.entities.Effects; @@ -26,7 +27,7 @@ public class SolidPump extends Pump{ public float updateEffectChance = 0.02f; public float rotateSpeed = 1f; /** Attribute that is checked when calculating output. */ - public Attribute attribute; + public @Nullable Attribute attribute; public SolidPump(String name){ super(name); @@ -64,7 +65,9 @@ public class SolidPump extends Pump{ stats.remove(BlockStat.output); stats.add(BlockStat.output, result, 60f * pumpAmount, true); - stats.add(BlockStat.affinities, attribute); + if(attribute != null){ + stats.add(BlockStat.affinities, attribute); + } } @Override diff --git a/core/src/mindustry/world/blocks/units/CommandCenter.java b/core/src/mindustry/world/blocks/units/CommandCenter.java index e32abc7304..daf0d2c1a2 100644 --- a/core/src/mindustry/world/blocks/units/CommandCenter.java +++ b/core/src/mindustry/world/blocks/units/CommandCenter.java @@ -66,8 +66,10 @@ public class CommandCenter extends Block{ public void load(){ super.load(); - for(UnitCommand cmd : UnitCommand.all){ - commandRegions[cmd.ordinal()] = ui.getIcon("command" + Strings.capitalize(cmd.name())); + if(ui != null){ + for(UnitCommand cmd : UnitCommand.all){ + commandRegions[cmd.ordinal()] = ui.getIcon("command" + Strings.capitalize(cmd.name())); + } } } diff --git a/core/src/mindustry/world/modules/LiquidModule.java b/core/src/mindustry/world/modules/LiquidModule.java index 19ad109341..eaaa22a07f 100644 --- a/core/src/mindustry/world/modules/LiquidModule.java +++ b/core/src/mindustry/world/modules/LiquidModule.java @@ -102,6 +102,7 @@ public class LiquidModule extends BlockModule{ @Override public void read(DataInput stream) throws IOException{ Arrays.fill(liquids, 0); + total = 0f; byte count = stream.readByte(); for(int j = 0; j < count; j++){ diff --git a/desktop/src/mindustry/desktop/steam/SStats.java b/desktop/src/mindustry/desktop/steam/SStats.java index 950bffc249..3ada365289 100644 --- a/desktop/src/mindustry/desktop/steam/SStats.java +++ b/desktop/src/mindustry/desktop/steam/SStats.java @@ -283,7 +283,7 @@ public class SStats implements SteamUserStatsCallback{ if(result != SteamResult.OK){ Log.err("Failed to recieve steam stats: {0}", result); }else{ - Log.err("Recieved steam stats."); + Log.info("Recieved steam stats."); } } diff --git a/fastlane/metadata/android/cs-CZ/changelogs/102.1.txt b/fastlane/metadata/android/cs-CZ/changelogs/102.1.txt new file mode 100644 index 0000000000..01760ded80 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/102.1.txt @@ -0,0 +1,5 @@ +- Přidán nový pohled na mapu s rolováním a posouváním +- Přidáno pravidlo pro zdraví bloku +- Přidáno více interních týmů pro různé herní režimy +- Přidána vylepšená podpora pro modifikace +- Hlavní vnitřní změna: programový balík se teď jmenuje "mindustry" namísto dosavadního "io.anuke.mindustry" (toto rozbije staré pluginy) diff --git a/fastlane/metadata/android/cs-CZ/changelogs/102.2.txt b/fastlane/metadata/android/cs-CZ/changelogs/102.2.txt new file mode 100644 index 0000000000..01760ded80 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/102.2.txt @@ -0,0 +1,5 @@ +- Přidán nový pohled na mapu s rolováním a posouváním +- Přidáno pravidlo pro zdraví bloku +- Přidáno více interních týmů pro různé herní režimy +- Přidána vylepšená podpora pro modifikace +- Hlavní vnitřní změna: programový balík se teď jmenuje "mindustry" namísto dosavadního "io.anuke.mindustry" (toto rozbije staré pluginy) diff --git a/fastlane/metadata/android/cs-CZ/changelogs/102.txt b/fastlane/metadata/android/cs-CZ/changelogs/102.txt new file mode 100644 index 0000000000..01760ded80 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/changelogs/102.txt @@ -0,0 +1,5 @@ +- Přidán nový pohled na mapu s rolováním a posouváním +- Přidáno pravidlo pro zdraví bloku +- Přidáno více interních týmů pro různé herní režimy +- Přidána vylepšená podpora pro modifikace +- Hlavní vnitřní změna: programový balík se teď jmenuje "mindustry" namísto dosavadního "io.anuke.mindustry" (toto rozbije staré pluginy) diff --git a/fastlane/metadata/android/cs-CZ/full_description.txt b/fastlane/metadata/android/cs-CZ/full_description.txt new file mode 100644 index 0000000000..112ccaf515 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/full_description.txt @@ -0,0 +1,43 @@ +Vytvoř propracovaný výrobní řetězec dopravníků, abys naládoval munici do věží, vyrobil materiály pro stavění a ubránil své stavby před vlnami nepřátel. Hraj s Tvými přáteli kooperačně napříč platformami, nebo je vyzvi v týmové hře hráčů proti sobě. + +Hra: +- Vytvoř vrty a dopravníky pro přesun zdrojů do Tvého jádra. +- Použij výrobní bloky pro vytvoření pokročilých materiálů. +- Postav drony pro automatické těžení zdrojů, pomoc se stavěním a vybudování a ochraně své základny. +- Rozváděj kapaliny a bojuj s požárem. +- Posilni výrobu dodatečným chlazením a promaž obranné i výrobní bloky. + +Kampaň: +- Projdi skrz 12 znovuhratelných předpřipravených zón s náhodným místem startu. +- Sesbírej a vyšli zpět ze zón materiál. +- Vynalezni nové bloky, abys rozjel výrobu. +- Konfiguruj předměty, se kterými se vyšleš do zóny, abys byl lépe připraven. +- V jednotlivých zónách plň rozdílné cíle mise. +- Pozvi kamarády pro společné dokončení mise. +- 120+ technologických bloků, dokážeš je všechny využít? +- 19 různých typů dronů, mechů and lodí! + +Herní módy: +- Přežití: Postav věže k obraně Tvého jádra před nepřátelskými jednotkami. Přežij tak dlouho, jak jen dokážeš, a ideálně ještě odešli své jádro zpět se sesbíranými surovinami pro zaplacení výzkumu. Připrav svou základnu pro střídavý útok vzdušného Záporáka. +- Útok: Postav továrny na jednotky pro zničení nepřátelského jádra, zatímco zároveň ochraňuj svoji základnu před vlnami nepřátelských jednotek. Vytvoř různé typy podpůrných a obranných jednotek pro dosažení tohoto cíle. +- Hráči proti sobě: Soupeř s jinými hráči v až 4 různých týmech, s cílem zničit ostatní jádra. Vytvoř jednotky nebo útoč na cizí jádro rovnou ve svém mechu. +- Pískoviště: Vyzkoušej si hru s nekonečnými zdroji surovin a bez nepřátelských hrozeb. Použij bloky dostupné pouze v pískovišti aby sis otestoval svůj nový nápad a pokud budeš chtít, můžeš si na vyžádání nechat seslat nepřátelské jednotky. + +Vlastní hra a podpora napříč herními platformami: +- 12 vestavěných map pro vlastní hry, navíc ke kampani +- Hraj kooperativně, proti sobě nebo na pískovišti +- Připoj se k veřejnému serveru nebo pozvi přátele do svého vlastního soukromého sezení +- Nastavitelná herní pravidla: Změn cenu bloků, nepřátelské statistiky, počáteční předměty, časování vln atd. +- Mix herních režimů: Smíchej dohromady hru hráčů proti sobě (PvP) a hráčů proti prostředí (PvE) + +Editor map: +- Nakresli si novou mapu s vestavěným editorem +- Upravuj a dej si náhled staveb přímo ve hře +- Konfigurovatelné nástroje: Změň, jak se každý nástroj chová +- Silný systém pro generování map, s mnoha různými typy filtrů pro procedurální manipulaci s terénem - vytvoř úžasnou mapu za 5 minut! +- Přidej zašumění, zkreslení, vyhlazení, prolnutí, zrcadlení, rozptýlení, generování rud a náhodného terénu do svých map +- Konfiguruj náhodné generování rudy, řek a surovin +- Konfiguruj rozestavění nepřátelských vln +- Sdílej vyexportované mapy v dílně Steamu +- Nastav pravidla pro základní mapy +- Použij 75+ různých bloků diff --git a/fastlane/metadata/android/cs-CZ/short_description.txt b/fastlane/metadata/android/cs-CZ/short_description.txt new file mode 100644 index 0000000000..706cd5e9c8 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/short_description.txt @@ -0,0 +1 @@ +Hra typu tower-defense s otevřeným koncem, zaměřená na řízení zdrojů. diff --git a/fastlane/metadata/android/cs-CZ/summary.txt b/fastlane/metadata/android/cs-CZ/summary.txt new file mode 100644 index 0000000000..706cd5e9c8 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/summary.txt @@ -0,0 +1 @@ +Hra typu tower-defense s otevřeným koncem, zaměřená na řízení zdrojů. diff --git a/fastlane/metadata/android/cs-CZ/title.txt b/fastlane/metadata/android/cs-CZ/title.txt new file mode 100644 index 0000000000..2beb939017 --- /dev/null +++ b/fastlane/metadata/android/cs-CZ/title.txt @@ -0,0 +1 @@ +Mindustry \ No newline at end of file diff --git a/fastlane/metadata/android/en-US/changelogs/103.1.txt b/fastlane/metadata/android/en-US/changelogs/103.1.txt new file mode 100644 index 0000000000..fa41c882ac --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/103.1.txt @@ -0,0 +1,9 @@ +- Added new icons w/ smooth scaling +- Added liquid void (Contributed by @GioIacca9) +- Added bridge opacity slider (Contributed by @Quezler) +- Added "underflow" gate (opposite of overflow gate) +- Added "emojis" for most blocks and items into the font +- Added new tech tree layout w/ better mod support +- Added game log file, stored in data folder +- Added new separator sprite/animation +- Added list of affinity tiles to stats of certain blocks diff --git a/fastlane/metadata/android/en-US/changelogs/103.2.txt b/fastlane/metadata/android/en-US/changelogs/103.2.txt new file mode 100644 index 0000000000..fa41c882ac --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/103.2.txt @@ -0,0 +1,9 @@ +- Added new icons w/ smooth scaling +- Added liquid void (Contributed by @GioIacca9) +- Added bridge opacity slider (Contributed by @Quezler) +- Added "underflow" gate (opposite of overflow gate) +- Added "emojis" for most blocks and items into the font +- Added new tech tree layout w/ better mod support +- Added game log file, stored in data folder +- Added new separator sprite/animation +- Added list of affinity tiles to stats of certain blocks diff --git a/fastlane/metadata/android/en-US/changelogs/103.txt b/fastlane/metadata/android/en-US/changelogs/103.txt new file mode 100644 index 0000000000..fa41c882ac --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/103.txt @@ -0,0 +1,9 @@ +- Added new icons w/ smooth scaling +- Added liquid void (Contributed by @GioIacca9) +- Added bridge opacity slider (Contributed by @Quezler) +- Added "underflow" gate (opposite of overflow gate) +- Added "emojis" for most blocks and items into the font +- Added new tech tree layout w/ better mod support +- Added game log file, stored in data folder +- Added new separator sprite/animation +- Added list of affinity tiles to stats of certain blocks diff --git a/fastlane/metadata/android/en-US/changelogs/29584.txt b/fastlane/metadata/android/en-US/changelogs/29584.txt new file mode 100644 index 0000000000..fa41c882ac --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/29584.txt @@ -0,0 +1,9 @@ +- Added new icons w/ smooth scaling +- Added liquid void (Contributed by @GioIacca9) +- Added bridge opacity slider (Contributed by @Quezler) +- Added "underflow" gate (opposite of overflow gate) +- Added "emojis" for most blocks and items into the font +- Added new tech tree layout w/ better mod support +- Added game log file, stored in data folder +- Added new separator sprite/animation +- Added list of affinity tiles to stats of certain blocks diff --git a/fastlane/metadata/android/en-US/changelogs/29586.txt b/fastlane/metadata/android/en-US/changelogs/29586.txt new file mode 100644 index 0000000000..fa41c882ac --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/29586.txt @@ -0,0 +1,9 @@ +- Added new icons w/ smooth scaling +- Added liquid void (Contributed by @GioIacca9) +- Added bridge opacity slider (Contributed by @Quezler) +- Added "underflow" gate (opposite of overflow gate) +- Added "emojis" for most blocks and items into the font +- Added new tech tree layout w/ better mod support +- Added game log file, stored in data folder +- Added new separator sprite/animation +- Added list of affinity tiles to stats of certain blocks diff --git a/fastlane/metadata/android/en-US/changelogs/29589.txt b/fastlane/metadata/android/en-US/changelogs/29589.txt new file mode 100644 index 0000000000..fa41c882ac --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/29589.txt @@ -0,0 +1,9 @@ +- Added new icons w/ smooth scaling +- Added liquid void (Contributed by @GioIacca9) +- Added bridge opacity slider (Contributed by @Quezler) +- Added "underflow" gate (opposite of overflow gate) +- Added "emojis" for most blocks and items into the font +- Added new tech tree layout w/ better mod support +- Added game log file, stored in data folder +- Added new separator sprite/animation +- Added list of affinity tiles to stats of certain blocks diff --git a/fastlane/metadata/android/en-US/changelogs/29591.txt b/fastlane/metadata/android/en-US/changelogs/29591.txt new file mode 100644 index 0000000000..fa41c882ac --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/29591.txt @@ -0,0 +1,9 @@ +- Added new icons w/ smooth scaling +- Added liquid void (Contributed by @GioIacca9) +- Added bridge opacity slider (Contributed by @Quezler) +- Added "underflow" gate (opposite of overflow gate) +- Added "emojis" for most blocks and items into the font +- Added new tech tree layout w/ better mod support +- Added game log file, stored in data folder +- Added new separator sprite/animation +- Added list of affinity tiles to stats of certain blocks diff --git a/fastlane/metadata/android/en-US/changelogs/29594.txt b/fastlane/metadata/android/en-US/changelogs/29594.txt new file mode 100644 index 0000000000..fa41c882ac --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/29594.txt @@ -0,0 +1,9 @@ +- Added new icons w/ smooth scaling +- Added liquid void (Contributed by @GioIacca9) +- Added bridge opacity slider (Contributed by @Quezler) +- Added "underflow" gate (opposite of overflow gate) +- Added "emojis" for most blocks and items into the font +- Added new tech tree layout w/ better mod support +- Added game log file, stored in data folder +- Added new separator sprite/animation +- Added list of affinity tiles to stats of certain blocks diff --git a/fastlane/metadata/android/pt-PT/changelogs/102.txt b/fastlane/metadata/android/pt-PT/changelogs/102.txt new file mode 100644 index 0000000000..784f53ea20 --- /dev/null +++ b/fastlane/metadata/android/pt-PT/changelogs/102.txt @@ -0,0 +1,5 @@ +- Adicionado nova forma de ver mapas. Com panorâmica e rolagem +- Foi adicionada regra de integridade do bloco +- Adicionado mais equipes internas para modos de jogo alternativos +- Adicionado recursos para melhorar a modificação do servidor +-Grande mudança interna: o pacote agora é "mindustry" em vez de "io.anuke.mindustry" (irá quebrar os plugins) \ No newline at end of file diff --git a/fastlane/metadata/android/pt-PT/full_description.txt b/fastlane/metadata/android/pt-PT/full_description.txt new file mode 100644 index 0000000000..07cf8233b3 --- /dev/null +++ b/fastlane/metadata/android/pt-PT/full_description.txt @@ -0,0 +1,14 @@ +Cria e elabora e fornece correntes de correias transportadoras para aumentar a munição das tuas torretas, produz materiais para usar em construções, e defende as tuas estruturas de ondas de inimigos. Joga com os teus amigos em multiplataforma multijogador jogos cooperativos, ou desafia eles em batalhas em equipa modo PvP. + +Recursos incluidos: +- 24 mapas integrados +- Uma campanha completa com uma estrutura tecnológica em árvore e áreas para desbloquear +- 4 ondas de chefes poderosas para derrotar +- Sistema de transporte de Energias, Líquidos e Itens +- 19 tipos diferentes de drones, mechas e navios +- Mais de 120 blocos de tecnologia para dominar +- Mais de 75 diferentes blocos de ambiente +- Multijogador multiplataforma através de redes locais ou servidores dedicados +- Regras personalizadas do jogo: altere os custos de bloqueio, estatísticas do inimigo, itens iniciais, tempo das ondas e muito mais +- Um editor poderoso, com ferramentas para gerar aleatoriamente minérios, terrenos, decoração e aplicar simetria a mapas +- Layouts de rondas de mapa personalizáveis \ No newline at end of file diff --git a/fastlane/metadata/android/pt-PT/short_description.txt b/fastlane/metadata/android/pt-PT/short_description.txt new file mode 100644 index 0000000000..6ecbaf697a --- /dev/null +++ b/fastlane/metadata/android/pt-PT/short_description.txt @@ -0,0 +1 @@ +Um jogo de defesa de torre de sandbox baseado em construção. diff --git a/fastlane/metadata/android/pt-PT/summary.txt b/fastlane/metadata/android/pt-PT/summary.txt new file mode 100644 index 0000000000..24b4edd83d --- /dev/null +++ b/fastlane/metadata/android/pt-PT/summary.txt @@ -0,0 +1 @@ +Um jogo de defesa de torre de sandbox baseado em construção. \ No newline at end of file diff --git a/fastlane/metadata/android/pt-PT/title.txt b/fastlane/metadata/android/pt-PT/title.txt new file mode 100644 index 0000000000..2beb939017 --- /dev/null +++ b/fastlane/metadata/android/pt-PT/title.txt @@ -0,0 +1 @@ +Mindustry \ No newline at end of file diff --git a/fastlane/metadata/steam/czech/achievements.vdf b/fastlane/metadata/steam/czech/achievements.vdf new file mode 100644 index 0000000000..e7e80c47f2 --- /dev/null +++ b/fastlane/metadata/steam/czech/achievements.vdf @@ -0,0 +1,109 @@ +"lang" +{ + "Language" "czech" + "Tokens" + { + "NEW_ACHIEVEMENT_20_0_NAME" "Ověřen" + "NEW_ACHIEVEMENT_20_0_DESC" "Dokončena výuka." + "NEW_ACHIEVEMENT_20_1_NAME" "Šroťák" + "NEW_ACHIEVEMENT_20_1_DESC" "Znič 1000 nepřátelských jednotek." + "NEW_ACHIEVEMENT_20_2_NAME" "Čistič" + "NEW_ACHIEVEMENT_20_2_DESC" "Znič 100,000 nepřátelských jednotek." + "NEW_ACHIEVEMENT_20_3_NAME" "Přesun do atmosféry" + "NEW_ACHIEVEMENT_20_3_DESC" "Vyšli zpět celkem 10.000 předmětů." + "NEW_ACHIEVEMENT_20_5_NAME" "Nekonečné dodávky" + "NEW_ACHIEVEMENT_20_5_DESC" "Vyšli zpět celkem 1.000.000 předmětů." + "NEW_ACHIEVEMENT_20_6_NAME" "Dobyvatel" + "NEW_ACHIEVEMENT_20_6_DESC" "Vyhraj 10 zápasů v herním režimu Útok." + "NEW_ACHIEVEMENT_20_7_NAME" "Šampión" + "NEW_ACHIEVEMENT_20_7_DESC" "Vyhraj 10 zápasů v herním režimu Hráči proti sobě." + "NEW_ACHIEVEMENT_20_8_NAME" "Blesk" + "NEW_ACHIEVEMENT_20_8_DESC" "Znič nepřátelské jádro v útočné zóně v průběhu prvních 5 vln." + "NEW_ACHIEVEMENT_20_9_NAME" "Prší jádra" + "NEW_ACHIEVEMENT_20_9_DESC" "Vyšli Tvoje jádro do mapy 30x." + "NEW_ACHIEVEMENT_20_10_NAME" "Houževnatý" + "NEW_ACHIEVEMENT_20_10_DESC" "Přežij 100 vln." + "NEW_ACHIEVEMENT_20_11_NAME" "Neposkvrněný" + "NEW_ACHIEVEMENT_20_11_DESC" "Přežij 500 vln." + "NEW_ACHIEVEMENT_20_12_NAME" "Výzkumník" + "NEW_ACHIEVEMENT_20_12_DESC" "Vyzkoumej všechno." + "NEW_ACHIEVEMENT_20_13_NAME" "Měňavec" + "NEW_ACHIEVEMENT_20_13_DESC" "Odemkni každého mecha ve hře a transformuj se do něj." + "NEW_ACHIEVEMENT_20_14_NAME" "Přetížení" + "NEW_ACHIEVEMENT_20_14_DESC" "Zasáhni nepřítele pokrytého vodou energetickou zbraní." + "NEW_ACHIEVEMENT_20_15_NAME" "Odražení" + "NEW_ACHIEVEMENT_20_15_DESC" "Znič jednotku její vlastní odraženou kulkou." + "NEW_ACHIEVEMENT_20_17_NAME" "Distributor v zácviku" + "NEW_ACHIEVEMENT_20_17_DESC" "Vynalezni Směrovač." + "NEW_ACHIEVEMENT_20_18_NAME" "Stvořitel" + "NEW_ACHIEVEMENT_20_18_DESC" "Umísti 10.000 bloků." + "NEW_ACHIEVEMENT_20_19_NAME" "Viktor čistič" + "NEW_ACHIEVEMENT_20_19_DESC" "Znič 1.000 nepřátelských bloků." + "NEW_ACHIEVEMENT_20_20_NAME" "Velkolepá chyba" + "NEW_ACHIEVEMENT_20_20_DESC" "Způsob přetížení Thoriového reaktoru, následované explozí." + "NEW_ACHIEVEMENT_20_21_NAME" "Kartograf" + "NEW_ACHIEVEMENT_20_21_DESC" "Vytvoř 10 nových map." + "NEW_ACHIEVEMENT_20_22_NAME" "Sosač" + "NEW_ACHIEVEMENT_20_22_DESC" "Stáhni mapu z dílny." + "NEW_ACHIEVEMENT_20_23_NAME" "Tvůrce" + "NEW_ACHIEVEMENT_20_23_DESC" "Publikuj mapu do dílny." + "NEW_ACHIEVEMENT_20_24_NAME" "Řezník" + "NEW_ACHIEVEMENT_20_24_DESC" "Poraž Záporáka." + "NEW_ACHIEVEMENT_20_25_NAME" "Průzkumník" + "NEW_ACHIEVEMENT_20_25_DESC" "Odemkni všechny zóny v kampani." + "NEW_ACHIEVEMENT_20_26_NAME" "Perfekcionalista" + "NEW_ACHIEVEMENT_20_26_DESC" "Dosáhni požadavku pro vlastní výbavu ve všech zónách v kampani." + "NEW_ACHIEVEMENT_20_29_NAME" "Materiály II" + "NEW_ACHIEVEMENT_20_29_DESC" "Odemkni Thorium." + "NEW_ACHIEVEMENT_20_31_NAME" "Materiály I" + "NEW_ACHIEVEMENT_20_31_DESC" "Odemkni Titan." + "NEW_ACHIEVEMENT_21_0_NAME" "Kamikaze" + "NEW_ACHIEVEMENT_21_0_DESC" "Naplň svého mecha výbušným materiálem a zemři v explozi ." + "NEW_ACHIEVEMENT_21_1_NAME" "A tak to začíná" + "NEW_ACHIEVEMENT_21_1_DESC" "Vytvoř továrnu na mecha Dýka." + "NEW_ACHIEVEMENT_21_2_NAME" "Přímý útok" + "NEW_ACHIEVEMENT_21_2_DESC" "Vyšli příkaz k útoku z řídícího střediska." + "NEW_ACHIEVEMENT_21_3_NAME" "Roj" + "NEW_ACHIEVEMENT_21_3_DESC" "Měj v jeden ukamžil 100 aktivních jednotek." + "NEW_ACHIEVEMENT_21_4_NAME" "Stádo" + "NEW_ACHIEVEMENT_21_4_DESC" "Měj v jeden okamžik 10 aktivních dronů Fantóm ." + "NEW_ACHIEVEMENT_21_5_NAME" "Proměnlivá armáda" + "NEW_ACHIEVEMENT_21_5_DESC" "Měj v jeden okamžik 50 aktivních jednotek Slídič." + "NEW_ACHIEVEMENT_21_6_NAME" "Legie" + "NEW_ACHIEVEMENT_21_6_DESC" "Postav celkem 1.000 jednotek." + "NEW_ACHIEVEMENT_21_7_NAME" "Super" + "NEW_ACHIEVEMENT_21_7_DESC" "Dosáhni hodnocení S v jakékoliv zóně." + "NEW_ACHIEVEMENT_21_8_NAME" "Super Super" + "NEW_ACHIEVEMENT_21_8_DESC" "Dosáhni hodnocení SS v jakékoliv zóně." + "NEW_ACHIEVEMENT_21_9_NAME" "Měl jsi líp poslouchat" + "NEW_ACHIEVEMENT_21_9_DESC" "Zemři v zóně pro vylíhnutí nepřátelských jednotek." + "NEW_ACHIEVEMENT_21_10_NAME" "Prostě zmáčkni Shift" + "NEW_ACHIEVEMENT_21_10_DESC" "Nějak se utop." + "NEW_ACHIEVEMENT_21_11_NAME" "Sběratel" + "NEW_ACHIEVEMENT_21_11_DESC" "Naplň jádro do maximální kapacity každým typem materiálu." + "NEW_ACHIEVEMENT_21_12_NAME" "Dav" + "NEW_ACHIEVEMENT_21_12_DESC" "Hostuj server s aspoň 10 hráči." + "NEW_ACHIEVEMENT_21_13_NAME" "Nezranitelný" + "NEW_ACHIEVEMENT_21_13_DESC" "Postav drony Meltdown a Spectre." + "NEW_ACHIEVEMENT_21_14_NAME" "Odlet" + "NEW_ACHIEVEMENT_21_14_DESC" "Použij Vysílací plošinu." + "NEW_ACHIEVEMENT_21_15_NAME" "Samolibost" + "NEW_ACHIEVEMENT_21_15_DESC" "Přeskoč vyslání zpět dvakrát a pak si nech zničit jádro nepřítelem." + "NEW_ACHIEVEMENT_21_16_NAME" "Kacířství" + "NEW_ACHIEVEMENT_21_16_DESC" "Postav dva směrovače vedle sebe." + "NEW_ACHIEVEMENT_21_17_NAME" "Osamělý strážce" + "NEW_ACHIEVEMENT_21_17_DESC" "Přežij 10 vln v jakékoliv zóně bez položení bloku." + "NEW_ACHIEVEMENT_21_18_NAME" "Zpopelnění" + "NEW_ACHIEVEMENT_21_18_DESC" "Použij ve střílně pyratit." + "NEW_ACHIEVEMENT_21_19_NAME" "Účinnost" + "NEW_ACHIEVEMENT_21_19_DESC" "Chlaď střílnu vodou nebo chladící kapalinou." + "NEW_ACHIEVEMENT_21_20_NAME" "Klasický režim" + "NEW_ACHIEVEMENT_21_20_DESC" "Zapni rozpixlování." + "NEW_ACHIEVEMENT_21_21_NAME" "Školák" + "NEW_ACHIEVEMENT_21_21_DESC" "Otevři Wiki Mindustry ze hry." + "NEW_ACHIEVEMENT_21_22_NAME" "Náskok" + "NEW_ACHIEVEMENT_21_22_DESC" "Vyšli se do zóny s nejméně 10.000 předměty." + "NEW_ACHIEVEMENT_21_23_NAME" "Zážeh" + "NEW_ACHIEVEMENT_21_23_DESC" "Zažehni rázový reaktor." + } +} diff --git a/fastlane/metadata/steam/czech/description.txt b/fastlane/metadata/steam/czech/description.txt new file mode 100644 index 0000000000..7a7ac632ff --- /dev/null +++ b/fastlane/metadata/steam/czech/description.txt @@ -0,0 +1,61 @@ +Vytvoř propracovaný výrobní řetězec dopravníků, abys naládoval munici do věží, vyrobil materiály pro stavění a ubránil své stavby před vlnami nepřátel. Hraj s Tvými přáteli kooperačně napříč platformami, nebo je vyzvi v týmové hře hráčů proti sobě. + +[img]{STEAM_APP_IMAGE}/extras/ezgif-4-0e70c282f775.gif[/img] + +[h2]Hra[/h2] + +[list] +[*] Vytvoř vrty a dopravníky pro přesun zdrojů do Tvého jádra. +[*] Použij výrobní bloky pro vytvoření pokročilých materiálů. +[*] Postav drony pro automatické těžení zdrojů, pomoc se stavěním a vybudování a ochraně své základny. +[*] Rozváděj kapaliny a bojuj s požárem. +[*] Posilni výrobu dodatečným chlazením a promaž obranné i výrobní bloky. +[/list] + +[h2]Kampaň[/h2] + +[list] +[*] Projdi skrz 12 znovuhratelných předpřipravených zón s náhodným místem startu. +[*] Sesbírej a vyšli zpět ze zón materiál. +[*] Vynalezni nové bloky, abys rozjel výrobu. +[*] Konfiguruj předměty, se kterými se vyšleš do zóny, abys byl lépe připraven. +[*] V jednotlivých zónách plň rozdílné cíle mise. +[*] Pozvi kamarády pro společné dokončení mise. +[*] 120+ technologických bloků, dokážeš je všechny využít? +[*] 19 různých typů dronů, mechů and lodí! +[*] 50+ achievementů! +[/list] + +[h2][h2]Herní módy[/h2][/h2] + +[list] +[*] [b]Přežití[/b]: Postav věže k obraně Tvého jádra před nepřátelskými jednotkami. Přežij tak dlouho, jak jen dokážeš, a ideálně ještě odešli své jádro zpět se sesbíranými surovinami pro zaplacení výzkumu. Připrav svou základnu pro střídavý útok vzdušného Záporáka. +[*] [b]Útok[/b]: Postav továrny na jednotky pro zničení nepřátelského jádra, zatímco zároveň ochraňuj svoji základnu před vlnami nepřátelských jednotek. Vytvoř různé typy podpůrných a obranných jednotek pro dosažení tohoto cíle. +[*] [b]Hráči proti sobě[/b]: Soupeř s jinými hráči v až 4 různých týmech, s cílem zničit ostatní jádra. Vytvoř jednotky nebo útoč na cizí jádro rovnou ve svém mechu. +[*] [b]Pískoviště[/b]: Vyzkoušej si hru s nekonečnými zdroji surovin a bez nepřátelských hrozeb. Použij bloky dostupné pouze v pískovišti aby sis otestoval svůj nový nápad a pokud budeš chtít, můžeš si na vyžádání nechat seslat nepřátelské jednotky. +[/list] + +[h2]Vlastní hra a podpora napříč herními platformami[/h2] + +[list] +[*] 12 vestavěných map pro vlastní hry, navíc ke kampani +[*] Hraj kooperativně, proti sobě nebo na pískovišti +[*] Připoj se k veřejnému serveru nebo pozvi přátele do svého vlastního soukromého sezení +[*] Nastavitelná herní pravidla: Změn cenu bloků, nepřátelské statistiky, počáteční předměty, časování vln atd. +[*] Mix herních režimů: Smíchej dohromady hru hráčů proti sobě (PvP) a hráčů proti prostředí (PvE) +[/list] + +[h2]Editor map[/h2] + +[list] +[*] Nakresli si novou mapu s vestavěným editorem +[*] Upravuj a dej si náhled staveb přímo ve hře +[*] Konfigurovatelné nástroje: Změň, jak se každý nástroj chová +[*] Silný systém pro generování map, s mnoha různými typy filtrů pro procedurální manipulaci s terénem - vytvoř úžasnou mapu za 5 minut! +[*] Přidej zašumění, zkreslení, vyhlazení, prolnutí, zrcadlení, rozptýlení, generování rud a náhodného terénu do svých map +[*] Konfiguruj náhodné generování rudy, řek a surovin +[*] Konfiguruj rozestavění nepřátelských vln +[*] Sdílej vyexportované mapy v dílně Steamu +[*] Nastav pravidla pro základní mapy +[*] Použij 75+ různých bloků +[/list] diff --git a/fastlane/metadata/steam/czech/short-description.txt b/fastlane/metadata/steam/czech/short-description.txt new file mode 100644 index 0000000000..252ae989db --- /dev/null +++ b/fastlane/metadata/steam/czech/short-description.txt @@ -0,0 +1 @@ +Hra typu tower-defense s otevřeným koncem, zaměřená na řízení zdrojů. diff --git a/fastlane/metadata/steam/portuguese-brazil/description.txt b/fastlane/metadata/steam/portuguese-brazil/description.txt index 0efa240dc0..add86a6a2c 100644 --- a/fastlane/metadata/steam/portuguese-brazil/description.txt +++ b/fastlane/metadata/steam/portuguese-brazil/description.txt @@ -5,7 +5,7 @@ Crie correntes de suprimentos elaboradas com correias transportadoras para alime [h2]Gameplay[/h2] [list] -[*] Crie brocas e correntes transportadoras para mover recursos para o seu Núcleo. +[*] Crie brocas e esteiras transportadoras para mover recursos para o seu Núcleo. [*] Use blocos de produção para criar materiais avançados. [*] Construa drones para minerar recursos automaticamente, ajudar na construção e proteger a sua base. [*] Distribua líquidos e enfrente surtos de fogo. diff --git a/fastlane/metadata/steam/portuguese/achievements.vdf b/fastlane/metadata/steam/portuguese/achievements.vdf new file mode 100644 index 0000000000..caa3a26319 --- /dev/null +++ b/fastlane/metadata/steam/portuguese/achievements.vdf @@ -0,0 +1,109 @@ +"lang" +{ + "Language" "portuguese-brazil" + "Tokens" + { + "NEW_ACHIEVEMENT_20_0_NAME" "Verificado" + "NEW_ACHIEVEMENT_20_0_DESC" "Complete o tutorial" + "NEW_ACHIEVEMENT_20_1_NAME" "Sucateiro" + "NEW_ACHIEVEMENT_20_1_DESC" "Destrua 1000 unidades inimigas." + "NEW_ACHIEVEMENT_20_2_NAME" "Expurgo" + "NEW_ACHIEVEMENT_20_2_DESC" "Destrua 100.000 unidades inimigas." + "NEW_ACHIEVEMENT_20_3_NAME" "Transporte atmosférico" + "NEW_ACHIEVEMENT_20_3_DESC" "Lance 10.000 itens no total." + "NEW_ACHIEVEMENT_20_5_NAME" "Transportes Sem Fim" + "NEW_ACHIEVEMENT_20_5_DESC" "Lance 1.000.000 itens no total." + "NEW_ACHIEVEMENT_20_6_NAME" "Conquistador" + "NEW_ACHIEVEMENT_20_6_DESC" "Vença 10 partidas no modo de ataque." + "NEW_ACHIEVEMENT_20_7_NAME" "Campeão" + "NEW_ACHIEVEMENT_20_7_DESC" "Vença 10 partidas PvP multi-jogador." + "NEW_ACHIEVEMENT_20_8_NAME" "Blitz" + "NEW_ACHIEVEMENT_20_8_DESC" "Destrua o núcleo inimigo na zona de ataque em 5 hordas ou menos." + "NEW_ACHIEVEMENT_20_9_NAME" "Chuva de núcleos" + "NEW_ACHIEVEMENT_20_9_DESC" "Lance seu núcleo em uma zona 10 vezes." + "NEW_ACHIEVEMENT_20_10_NAME" "Persistente" + "NEW_ACHIEVEMENT_20_10_DESC" "Sobreviva 100 hordas" + "NEW_ACHIEVEMENT_20_11_NAME" "Invicto" + "NEW_ACHIEVEMENT_20_11_DESC" "Sobreviva 500 hordas." + "NEW_ACHIEVEMENT_20_12_NAME" "Pesquisador" + "NEW_ACHIEVEMENT_20_12_DESC" "Pesquise tudo." + "NEW_ACHIEVEMENT_20_13_NAME" "Metamorfose Ambulante" + "NEW_ACHIEVEMENT_20_13_DESC" "Desbloqueie e transforme-se em todos os mechas no jogo." + "NEW_ACHIEVEMENT_20_14_NAME" "Sobrecarga" + "NEW_ACHIEVEMENT_20_14_DESC" "Atinja um inimigo coberto de água com eletricidade." + "NEW_ACHIEVEMENT_20_15_NAME" "Deflexão" + "NEW_ACHIEVEMENT_20_15_DESC" "Destrua uma unidade com suas proprias balas refletidas." + "NEW_ACHIEVEMENT_20_17_NAME" "Um Erro Grave" + "NEW_ACHIEVEMENT_20_17_DESC" "Pesquise o roteador." + "NEW_ACHIEVEMENT_20_18_NAME" "Crie" + "NEW_ACHIEVEMENT_20_18_DESC" "Coloque 10.000 blocos." + "NEW_ACHIEVEMENT_20_19_NAME" "Arraso" + "NEW_ACHIEVEMENT_20_19_DESC" "Destrua 1.000 blocos inimigos." + "NEW_ACHIEVEMENT_20_20_NAME" "Um desastre espetacular." + "NEW_ACHIEVEMENT_20_20_DESC" "Faça com que um reator de tório superaqueça e exploda." + "NEW_ACHIEVEMENT_20_21_NAME" "Cartógrafo" + "NEW_ACHIEVEMENT_20_21_DESC" "Faça um mapa novo 10 vezes." + "NEW_ACHIEVEMENT_20_22_NAME" "Navegador" + "NEW_ACHIEVEMENT_20_22_DESC" "Baixe um mapa da Oficina." + "NEW_ACHIEVEMENT_20_23_NAME" "Criador" + "NEW_ACHIEVEMENT_20_23_DESC" "Publique um mapa na Oficina." + "NEW_ACHIEVEMENT_20_24_NAME" "Matador" + "NEW_ACHIEVEMENT_20_24_DESC" "Derrote um chefe." + "NEW_ACHIEVEMENT_20_25_NAME" "Explorador" + "NEW_ACHIEVEMENT_20_25_DESC" "Desbloqueie todas as zonas na campanha." + "NEW_ACHIEVEMENT_20_26_NAME" "Completador" + "NEW_ACHIEVEMENT_20_26_DESC" "Alcance a horda requerida para configuração em todas as zonas." + "NEW_ACHIEVEMENT_20_29_NAME" "Material II" + "NEW_ACHIEVEMENT_20_29_DESC" "Desbloqueie Tório." + "NEW_ACHIEVEMENT_20_31_NAME" "Material I" + "NEW_ACHIEVEMENT_20_31_DESC" "Desbloqueie Titânio." + "NEW_ACHIEVEMENT_21_0_NAME" "Kamikaze" + "NEW_ACHIEVEMENT_21_0_DESC" "Encha o seu mecha com materiais explosivos e morra, criando uma explosão." + "NEW_ACHIEVEMENT_21_1_NAME" "Assim Começa" + "NEW_ACHIEVEMENT_21_1_DESC" "Construa uma fábrica de Dagger." + "NEW_ACHIEVEMENT_21_2_NAME" "Ataque direto" + "NEW_ACHIEVEMENT_21_2_DESC" "Emita o comando de Ataque usando o Centro de Comando." + "NEW_ACHIEVEMENT_21_3_NAME" "Enchame" + "NEW_ACHIEVEMENT_21_3_DESC" "Tenha 100 unidades ativas ao mesmo tempo." + "NEW_ACHIEVEMENT_21_4_NAME" "Rebanho" + "NEW_ACHIEVEMENT_21_4_DESC" "Tenha 10 drones Phantom ativos ao mesmo tempo." + "NEW_ACHIEVEMENT_21_5_NAME" "Exército Volátil" + "NEW_ACHIEVEMENT_21_5_DESC" "Tenha 50 unidades Crawler ativas ao mesmo tempo." + "NEW_ACHIEVEMENT_21_6_NAME" "Legiões" + "NEW_ACHIEVEMENT_21_6_DESC" "Construa 1000 unidades no total." + "NEW_ACHIEVEMENT_21_7_NAME" "Super" + "NEW_ACHIEVEMENT_21_7_DESC" "Conquiste o rank S em qualquer zona." + "NEW_ACHIEVEMENT_21_8_NAME" "Super Super" + "NEW_ACHIEVEMENT_21_8_DESC" "Conquiste o rank SS em qualquer zona." + "NEW_ACHIEVEMENT_21_9_NAME" "Você Devia Ter Escutado" + "NEW_ACHIEVEMENT_21_9_DESC" "Morra na zona de exclusão do ponto de spawn." + "NEW_ACHIEVEMENT_21_10_NAME" "Só Aperte Shift" + "NEW_ACHIEVEMENT_21_10_DESC" "Afogue, de algum modo." + "NEW_ACHIEVEMENT_21_11_NAME" "Colecionador" + "NEW_ACHIEVEMENT_21_11_DESC" "Encha o núcleo até a capacidade máxima com todos os tipos de materiais." + "NEW_ACHIEVEMENT_21_12_NAME" "Galera" + "NEW_ACHIEVEMENT_21_12_DESC" "Hospede um servidor com 10 pessoas nele." + "NEW_ACHIEVEMENT_21_13_NAME" "Invulnerável" + "NEW_ACHIEVEMENT_21_13_DESC" "Construa o Meltdown e o Spectre." + "NEW_ACHIEVEMENT_21_14_NAME" "Decolagem" + "NEW_ACHIEVEMENT_21_14_DESC" "Use a Plataforma de Lançamento." + "NEW_ACHIEVEMENT_21_15_NAME" "Complacência" + "NEW_ACHIEVEMENT_21_15_DESC" "Pule o lançamento duas vezes, então tenha o seu núcleo destruído pelo inimigo." + "NEW_ACHIEVEMENT_21_16_NAME" "Heresia" + "NEW_ACHIEVEMENT_21_16_DESC" "Construa dois roteadores, um do lado do outro." + "NEW_ACHIEVEMENT_21_17_NAME" "Guardião Solitário" + "NEW_ACHIEVEMENT_21_17_DESC" "Sobreviva 10 hordas em qualquer zona, sem colocar qualquer bloco." + "NEW_ACHIEVEMENT_21_18_NAME" "Incinere" + "NEW_ACHIEVEMENT_21_18_DESC" "Use Piratita em qualquer torreta." + "NEW_ACHIEVEMENT_21_19_NAME" "Eficiência" + "NEW_ACHIEVEMENT_21_19_DESC" "Refirgere uma torreta com água ou crio fluido." + "NEW_ACHIEVEMENT_21_20_NAME" "Modo Clássico" + "NEW_ACHIEVEMENT_21_20_DESC" "Habilite pixelização." + "NEW_ACHIEVEMENT_21_21_NAME" "Sábio" + "NEW_ACHIEVEMENT_21_21_DESC" "Abra a Wiki do jogo." + "NEW_ACHIEVEMENT_21_22_NAME" "Vantagem" + "NEW_ACHIEVEMENT_21_22_DESC" "Entre em uma zona com 10.000 itens ou mais já configurados." + "NEW_ACHIEVEMENT_21_23_NAME" "Ignição" + "NEW_ACHIEVEMENT_21_23_DESC" "Ligue um Reator de Impacto." + } +} diff --git a/fastlane/metadata/steam/portuguese/description.txt b/fastlane/metadata/steam/portuguese/description.txt new file mode 100644 index 0000000000..0efa240dc0 --- /dev/null +++ b/fastlane/metadata/steam/portuguese/description.txt @@ -0,0 +1,61 @@ +Crie correntes de suprimentos elaboradas com correias transportadoras para alimentar suas torretas com munição, produza minerais para usar em construção, e defenda suas estruturas de hordas inimigas. Jogue com seus amigos em jogos cooperativos multi-jogadores multi-plataformas, ou desafie-os em partidas PvP de times. + +[img]{STEAM_APP_IMAGE}/extras/ezgif-4-0e70c282f775.gif[/img] + +[h2]Gameplay[/h2] + +[list] +[*] Crie brocas e correntes transportadoras para mover recursos para o seu Núcleo. +[*] Use blocos de produção para criar materiais avançados. +[*] Construa drones para minerar recursos automaticamente, ajudar na construção e proteger a sua base. +[*] Distribua líquidos e enfrente surtos de fogo. +[*] Melhore a produção suprimindo refrigerantes e lubrificantes opcionais para os seus blocos de defesa e produção. +[/list] + +[h2]Campanha[/h2] + +[list] +[*] Avance através de 12 zonas re-jogáveis com pontos de spawn aleatórios +[*] Colete e lance recursos +[*] Pesquise novos blocos para abastecer o progresso +[*] Configure loadout antes do lançamento para levar recursos para cada zona +[*] Variedade de missões com objetivos e metas +[*] Convide seus amigos para completar missões juntos +[*] Mais de 120 blocos de tecnologia para dominar +[*] 19 tipos de drones, mechas e naves diferentes +[*] Mais de 50 conquistas para completar +[/list] + +[h2][h2]Modos de jogo[/h2][/h2] + +[list] +[*] [b]Sobrevivência[/b]: Construa torretas para defender de inimigos no gameplay de tower-defense. Sobreviva o máximo possível, opcionalmente lançando o seu núcleo para usar os recursos coletados para pesquisa. Prepare a sua base para ataques intermitentes de chefes aéreos. +[*] [b]Ataque[/b]: Construa fábricas para unidades destruírem núcleos inimidos, enquanto simultaneamente defendendo sua base de hordas de unidades inimigas. Crie uma variedade de tipos diferentes de unidades de suporte o defesa para auxiliar você em seus objetivos. +[*] [b]PvP[/b]: Dispute com outros jogadores em até 4 times diferentes, para destruir o núcleo dos outros. Crie unidades, ou ataque outras bases diretamente com seus mechas. +[*] [b]Sandbox[/b]: Brinque com recursos infinitos e sem ameaça inimiga. Use itens específicos do modo e fontes de líquidos para testar designs, e sumone inimigos à vontade. +[/list] + +[h2]Jogos Personalizados & Multi-jogador Multi-plataforma[/h2] + +[list] +[*] 12 mapas embutidos para jogos personalizados, além da campanha +[*] Jogue Cooperativo, PvP, ou sandbox +[*] Entre em um servidor público dedicado, ou convide amigos para a sua própria sessão privada +[*] Regras do jogo personalizáveis: Mude custo dos blocos, estatísticas de inimigos, itens iniciais, tempo entre as hordas e mais +[*] Misture modos de jogo: Combine modos de jogo PvP e PvE +[/list] + +[h2]Editor de mapa[/h2] + +[list] +[*] Pinte terreno com um editor +[*] Edite e visualize estruturas em jogo +[*] Modos de ferramentas configuráveis: Mude como cada ferramenta funciona +[*] Sistema gerador de mapa poderoso, com muitos tipos diferentes de filtros para manipulação procedural de terreno +[*] Aplique ruído, distorção, suavização, erosão, simetria, geração de minérios e terreno aleatório aos seus mapas +[*] Aleatorize e configure geração de minérios, assim como localização de rios e recursos +[*] Configure o layout de hordas inimigas +[*] Compartilhe mapas exportados na Oficina da Steam +[*] Modifique regras básicas do mapa +[*] Use mais de 75 blocos de ambientação diferentes +[/list] diff --git a/fastlane/metadata/steam/portuguese/short-description.txt b/fastlane/metadata/steam/portuguese/short-description.txt new file mode 100644 index 0000000000..c6ad92da31 --- /dev/null +++ b/fastlane/metadata/steam/portuguese/short-description.txt @@ -0,0 +1 @@ +Um jogo de fim aberto de tower-defense com um foco em gerenciamento de recursos. diff --git a/server/src/mindustry/server/ServerControl.java b/server/src/mindustry/server/ServerControl.java index 566656b4a5..0ee88e19e2 100644 --- a/server/src/mindustry/server/ServerControl.java +++ b/server/src/mindustry/server/ServerControl.java @@ -829,7 +829,6 @@ public class ServerControl implements ApplicationListener{ }); mods.eachClass(p -> p.registerServerCommands(handler)); - mods.eachClass(p -> p.registerClientCommands(netServer.clientCommands)); } private void readCommands(){