Merge branch 'master' into master

This commit is contained in:
Vanguard
2020-01-25 15:03:05 +03:00
committed by GitHub
70 changed files with 1260 additions and 756 deletions

View File

@@ -150,10 +150,22 @@ public class AndroidLauncher extends AndroidApplication{
}}); }});
checkFiles(getIntent()); checkFiles(getIntent());
//new external folder //new external folder
Fi data = Core.files.absolute(getContext().getExternalFilesDir(null).getAbsolutePath()); 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()){ if(!Core.files.local("files_moved").exists()){
Log.info("Moving files to external storage..."); Log.info("Moving files to external storage...");
@@ -161,7 +173,7 @@ public class AndroidLauncher extends AndroidApplication{
//current local storage folder //current local storage folder
Fi src = Core.files.absolute(Core.files.getLocalStoragePath()); Fi src = Core.files.absolute(Core.files.getLocalStoragePath());
for(Fi fi : src.list()){ for(Fi fi : src.list()){
fi.copyTo(data.child(fi.name())); fi.copyTo(data);
} }
//create marker //create marker
Core.files.local("files_moved").writeString("files moved to " + data); 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!"); Log.err("Failed to move files!");
t.printStackTrace(); t.printStackTrace();
} }
}else{
Core.settings.setDataDirectory(data);
} }
} }

View File

@@ -3,6 +3,7 @@ package mindustry.annotations;
import javax.annotation.processing.*; import javax.annotation.processing.*;
import javax.lang.model.*; import javax.lang.model.*;
import javax.lang.model.element.*; import javax.lang.model.element.*;
import javax.lang.model.util.*;
import java.util.*; import java.util.*;
@SupportedSourceVersion(SourceVersion.RELEASE_8) @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. */ /** Name of the base package to put all the generated classes. */
public static final String packageName = "mindustry.gen"; 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 @Override
public synchronized void init(ProcessingEnvironment processingEnv){ public synchronized void init(ProcessingEnvironment processingEnv){
super.init(processingEnv); super.init(processingEnv);
//put all relevant utils into utils class
Utils.typeUtils = processingEnv.getTypeUtils(); typeu = processingEnv.getTypeUtils();
Utils.elementUtils = processingEnv.getElementUtils(); elementu = processingEnv.getElementUtils();
Utils.filer = processingEnv.getFiler(); filer = processingEnv.getFiler();
Utils.messager = processingEnv.getMessager(); messager = processingEnv.getMessager();
} }
@Override @Override
public final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
if(round++ != 0) return false; //only process 1 round if(round++ != 0) return false; //only process 1 round
try{ try{
process(roundEnv); process(roundEnv);
@@ -39,5 +54,7 @@ public abstract class BaseProcessor extends AbstractProcessor{
return SourceVersion.RELEASE_8; return SourceVersion.RELEASE_8;
} }
public abstract void process(RoundEnvironment env) throws Exception; public void process(RoundEnvironment env) throws Exception{
}
} }

View File

@@ -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<? extends TypeElement> 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;
}
}

View File

@@ -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<Object, Trees> {
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<Symbol> it;
try{
it = (Iterable<Symbol>)members.getClass().getMethod("getElements").invoke(members);
}catch(Throwable t){
try{
it = (Iterable<Symbol>)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;
}
}

View File

@@ -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");
}
}

View File

@@ -1,10 +1,11 @@
package mindustry.annotations; package mindustry.annotations.impl;
import arc.files.*; import arc.files.*;
import arc.scene.style.*; import arc.scene.style.*;
import arc.struct.*; import arc.struct.*;
import arc.util.serialization.*; import arc.util.serialization.*;
import com.squareup.javapoet.*; import com.squareup.javapoet.*;
import mindustry.annotations.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import javax.annotation.processing.*; import javax.annotation.processing.*;
@@ -20,7 +21,7 @@ public class AssetsAnnotationProcessor extends BaseProcessor{
@Override @Override
public void process(RoundEnvironment env) throws Exception{ 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())) .toUri().toURL().toString().substring(System.getProperty("os.name").contains("Windows") ? 6 : "file:".length()))
.parent().parent().parent().parent().parent().parent().toString(); .parent().parent().parent().parent().parent().parent().toString();
path = path.replace("%20", " "); path = path.replace("%20", " ");
@@ -85,12 +86,12 @@ public class AssetsAnnotationProcessor extends BaseProcessor{
} }
ictype.addMethod(icload.build()); ictype.addMethod(icload.build());
JavaFile.builder(packageName, ichtype.build()).build().writeTo(Utils.filer); JavaFile.builder(packageName, ichtype.build()).build().writeTo(BaseProcessor.filer);
JavaFile.builder(packageName, ictype.build()).build().writeTo(Utils.filer); JavaFile.builder(packageName, ictype.build()).build().writeTo(BaseProcessor.filer);
type.addMethod(load.build()); type.addMethod(load.build());
type.addMethod(loadStyles.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{ void processSounds(String classname, String path, String rtype) throws Exception{
@@ -104,7 +105,7 @@ public class AssetsAnnotationProcessor extends BaseProcessor{
String name = p.nameWithoutExtension(); String name = p.nameWithoutExtension();
if(names.contains(name)){ 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{ }else{
names.add(name); names.add(name);
} }
@@ -130,7 +131,7 @@ public class AssetsAnnotationProcessor extends BaseProcessor{
type.addMethod(loadBegin.build()); type.addMethod(loadBegin.build());
type.addMethod(dispose.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){ static String capitalize(String s){

View File

@@ -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<? extends TypeElement> 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<Object, Trees>{
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<Symbol> it;
try{
it = (Iterable<Symbol>)members.getClass().getMethod("getElements").invoke(members);
}catch(Throwable t){
try{
it = (Iterable<Symbol>)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);
}
}
}

View File

@@ -1,14 +1,14 @@
package mindustry.annotations; package mindustry.annotations.impl;
import com.squareup.javapoet.*; import com.squareup.javapoet.*;
import mindustry.annotations.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import mindustry.annotations.remote.*;
import javax.annotation.processing.*; import javax.annotation.processing.*;
import javax.lang.model.*;
import javax.lang.model.element.Modifier; import javax.lang.model.element.Modifier;
import javax.lang.model.element.*; import javax.lang.model.element.*;
import javax.lang.model.util.*; import javax.lang.model.util.*;
import javax.tools.Diagnostic.*;
import java.io.*; import java.io.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.util.*; import java.util.*;
@@ -55,13 +55,13 @@ public class SerializeAnnotationProcessor extends BaseProcessor{
readMethod.addStatement("$L object = new $L()", type, type); readMethod.addStatement("$L object = new $L()", type, type);
List<VariableElement> fields = ElementFilter.fieldsIn(Utils.elementUtils.getAllMembers(elem)); List<VariableElement> fields = ElementFilter.fieldsIn(BaseProcessor.elementu.getAllMembers(elem));
for(VariableElement field : fields){ for(VariableElement field : fields){
if(field.getModifiers().contains(Modifier.STATIC) || field.getModifiers().contains(Modifier.TRANSIENT) || field.getModifiers().contains(Modifier.PRIVATE)) if(field.getModifiers().contains(Modifier.STATIC) || field.getModifiers().contains(Modifier.TRANSIENT) || field.getModifiers().contains(Modifier.PRIVATE))
continue; continue;
String name = field.getSimpleName().toString(); 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); String capName = Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1);
if(field.asType().getKind().isPrimitive()){ if(field.asType().getKind().isPrimitive()){
@@ -78,7 +78,7 @@ public class SerializeAnnotationProcessor extends BaseProcessor{
serializer.addMethod(writeMethod.build()); serializer.addMethod(writeMethod.build());
serializer.addMethod(readMethod.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(writeMethod, "write" + simpleTypeName);
name(readMethod, "read" + simpleTypeName); name(readMethod, "read" + simpleTypeName);
@@ -93,7 +93,7 @@ public class SerializeAnnotationProcessor extends BaseProcessor{
classBuilder.addMethod(method.build()); classBuilder.addMethod(method.build());
//write result //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){ static void name(MethodSpec.Builder builder, String name){

View File

@@ -1,11 +1,11 @@
package mindustry.annotations; package mindustry.annotations.impl;
import com.squareup.javapoet.*; import com.squareup.javapoet.*;
import mindustry.annotations.*;
import mindustry.annotations.Annotations.Struct; import mindustry.annotations.Annotations.Struct;
import mindustry.annotations.Annotations.StructField; import mindustry.annotations.Annotations.StructField;
import javax.annotation.processing.*; import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*; import javax.lang.model.element.*;
import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeKind;
import javax.lang.model.util.ElementFilter; import javax.lang.model.util.ElementFilter;
@@ -29,7 +29,7 @@ public class StructAnnotationProcessor extends BaseProcessor{
for(TypeElement elem : elements){ for(TypeElement elem : elements){
if(!elem.getSimpleName().toString().endsWith("Struct")){ 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; continue;
} }
@@ -45,7 +45,7 @@ public class StructAnnotationProcessor extends BaseProcessor{
int structTotalSize = (structSize <= 8 ? 8 : structSize <= 16 ? 16 : structSize <= 32 ? 32 : 64); int structTotalSize = (structSize <= 8 ? 8 : structSize <= 16 ? 16 : structSize <= 32 ? 32 : 64);
if(variables.size() == 0){ 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; continue;
} }
@@ -130,10 +130,10 @@ public class StructAnnotationProcessor extends BaseProcessor{
constructor.addStatement("return ($T)($L)", structType, cons.toString().substring(3)); constructor.addStatement("return ($T)($L)", structType, cons.toString().substring(3));
classBuilder.addMethod(constructor.build()); 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){ }catch(IllegalArgumentException e){
e.printStackTrace(); e.printStackTrace();
Utils.messager.printMessage(Kind.ERROR, e.getMessage(), elem); BaseProcessor.messager.printMessage(Kind.ERROR, e.getMessage(), elem);
} }
} }

View File

@@ -1,4 +1,4 @@
package mindustry.annotations; package mindustry.annotations.remote;
import java.util.ArrayList; import java.util.ArrayList;

View File

@@ -1,5 +1,6 @@
package mindustry.annotations; package mindustry.annotations.remote;
import mindustry.annotations.*;
import mindustry.annotations.Annotations.ReadClass; import mindustry.annotations.Annotations.ReadClass;
import mindustry.annotations.Annotations.WriteClass; import mindustry.annotations.Annotations.WriteClass;
@@ -11,8 +12,8 @@ import java.util.HashMap;
import java.util.Set; import java.util.Set;
/** /**
* This class finds reader and writer methods annotated by the {@link Annotations.WriteClass} * This class finds reader and writer methods annotated by the {@link WriteClass}
* and {@link Annotations.ReadClass} annotations. * and {@link ReadClass} annotations.
*/ */
public class IOFinder{ public class IOFinder{
@@ -34,21 +35,21 @@ public class IOFinder{
//make sure there's only one read method //make sure there's only one read method
if(readers.stream().filter(elem -> getValue(elem.getAnnotation(ReadClass.class)).equals(typeName)).count() > 1){ 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 //make sure there's only one write method
long count = readers.stream().filter(elem -> getValue(elem.getAnnotation(ReadClass.class)).equals(typeName)).count(); long count = readers.stream().filter(elem -> getValue(elem.getAnnotation(ReadClass.class)).equals(typeName)).count();
if(count == 0){ 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){ }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(); Element reader = readers.stream().filter(elem -> getValue(elem.getAnnotation(ReadClass.class)).equals(typeName)).findFirst().get();
//add to result list //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; return result;

View File

@@ -1,4 +1,4 @@
package mindustry.annotations; package mindustry.annotations.remote;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;

View File

@@ -1,32 +1,28 @@
package mindustry.annotations; package mindustry.annotations.remote;
import com.squareup.javapoet.*; import com.squareup.javapoet.*;
import mindustry.annotations.Annotations.Loc; import mindustry.annotations.*;
import mindustry.annotations.Annotations.Remote; import mindustry.annotations.Annotations.*;
import mindustry.annotations.IOFinder.ClassSerializer; import mindustry.annotations.remote.IOFinder.*;
import javax.annotation.processing.*; import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*; import javax.lang.model.element.*;
import javax.tools.Diagnostic.Kind; import javax.tools.Diagnostic.*;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.*;
/** The annotation processor for generating remote method call code. */ /** The annotation processor for generating remote method call code. */
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes({ @SupportedAnnotationTypes({
"mindustry.annotations.Annotations.Remote", "mindustry.annotations.Annotations.Remote",
"mindustry.annotations.Annotations.WriteClass", "mindustry.annotations.Annotations.WriteClass",
"mindustry.annotations.Annotations.ReadClass", "mindustry.annotations.Annotations.ReadClass",
}) })
public class RemoteMethodAnnotationProcessor extends AbstractProcessor{ public class RemoteMethodAnnotationProcessor extends BaseProcessor{
/** Maximum size of each event packet. */ /** Maximum size of each event packet. */
public static final int maxPacketSize = 4096; public static final int maxPacketSize = 4096;
/** Warning on top of each autogenerated file. */ /** Warning on top of each autogenerated file. */
public static final String autogenWarning = "Autogenerated file. Do not modify!\n"; 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. */ /** Name of class that handles reading and invoking packets on the server. */
private static final String readServerName = "RemoteReadServer"; private static final String readServerName = "RemoteReadServer";
@@ -35,9 +31,6 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor{
/** Simple class name of generated class name. */ /** Simple class name of generated class name. */
private static final String callLocation = "Call"; private static final String callLocation = "Call";
/** Processing round number. */
private int round;
//class serializers //class serializers
private HashMap<String, ClassSerializer> serializers; private HashMap<String, ClassSerializer> serializers;
//all elements with the Remote annotation //all elements with the Remote annotation
@@ -49,16 +42,6 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor{
//list of all method entries //list of all method entries
private ArrayList<ClassEntry> classes; private ArrayList<ClassEntry> 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 @Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
if(round > 1) return false; //only process 2 rounds if(round > 1) return false; //only process 2 rounds
@@ -91,12 +74,12 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor{
//check for static //check for static
if(!element.getModifiers().contains(Modifier.STATIC) || !element.getModifiers().contains(Modifier.PUBLIC)){ 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 //can't generate none methods
if(annotation.targets() == Loc.none){ 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 //get and create class entry if needed
@@ -109,7 +92,7 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor{
ClassEntry entry = classMap.get(callLocation); ClassEntry entry = classMap.get(callLocation);
//create and add entry //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()); annotation.called(), annotation.unreliable(), annotation.forward(), lastMethodID++, (ExecutableElement)element, annotation.priority());
entry.methods.add(method); entry.methods.add(method);
@@ -139,7 +122,7 @@ public class RemoteMethodAnnotationProcessor extends AbstractProcessor{
//build and write resulting hash class //build and write resulting hash class
TypeSpec spec = hashBuilder.build(); TypeSpec spec = hashBuilder.build();
JavaFile.builder(packageName, spec).build().writeTo(Utils.filer); JavaFile.builder(packageName, spec).build().writeTo(BaseProcessor.filer);
return true; return true;
} }

View File

@@ -1,7 +1,8 @@
package mindustry.annotations; package mindustry.annotations.remote;
import com.squareup.javapoet.*; 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.lang.model.element.*;
import javax.tools.Diagnostic.Kind; 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); String capName = typeName.equals("byte") ? "" : Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1);
//write primitives automatically //write primitives automatically
if(Utils.isPrimitive(typeName)){ if(BaseProcessor.isPrimitive(typeName)){
if(typeName.equals("boolean")){ if(typeName.equals("boolean")){
readBlock.addStatement("boolean " + varName + " = buffer.get() == 1"); readBlock.addStatement("boolean " + varName + " = buffer.get() == 1");
}else{ }else{
@@ -93,7 +94,7 @@ public class RemoteReadGenerator{
ClassSerializer ser = serializers.get(typeName); ClassSerializer ser = serializers.get(typeName);
if(ser == null){ //make sure a serializer exists! 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; return;
} }
@@ -139,6 +140,6 @@ public class RemoteReadGenerator{
//build and write resulting class //build and write resulting class
TypeSpec spec = classBuilder.build(); TypeSpec spec = classBuilder.build();
JavaFile.builder(packageName, spec).build().writeTo(Utils.filer); JavaFile.builder(packageName, spec).build().writeTo(BaseProcessor.filer);
} }
} }

View File

@@ -1,8 +1,9 @@
package mindustry.annotations; package mindustry.annotations.remote;
import com.squareup.javapoet.*; import com.squareup.javapoet.*;
import mindustry.annotations.*;
import mindustry.annotations.Annotations.Loc; import mindustry.annotations.Annotations.Loc;
import mindustry.annotations.IOFinder.ClassSerializer; import mindustry.annotations.remote.IOFinder.ClassSerializer;
import javax.lang.model.element.*; import javax.lang.model.element.*;
import javax.tools.Diagnostic.Kind; import javax.tools.Diagnostic.Kind;
@@ -52,7 +53,7 @@ public class RemoteWriteGenerator{
//build and write resulting class //build and write resulting class
TypeSpec spec = classBuilder.build(); 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 //validate client methods to make sure
if(methodEntry.where.isClient){ if(methodEntry.where.isClient){
if(elem.getParameters().isEmpty()){ 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; return;
} }
if(!elem.getParameters().get(0).asType().toString().equals("mindustry.entities.type.Player")){ 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; return;
} }
} }
@@ -162,7 +163,7 @@ public class RemoteWriteGenerator{
method.beginControlFlow("if(mindustry.Vars.net.server())"); 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 if(typeName.equals("boolean")){ //booleans are special
method.addStatement("TEMP_BUFFER.put(" + varName + " ? (byte)1 : 0)"); method.addStatement("TEMP_BUFFER.put(" + varName + " ? (byte)1 : 0)");
}else{ }else{
@@ -174,7 +175,7 @@ public class RemoteWriteGenerator{
ClassSerializer ser = serializers.get(typeName); ClassSerializer ser = serializers.get(typeName);
if(ser == null){ //make sure a serializer exists! 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; return;
} }

View File

@@ -1,5 +1,5 @@
mindustry.annotations.RemoteMethodAnnotationProcessor mindustry.annotations.remote.RemoteMethodAnnotationProcessor
mindustry.annotations.SerializeAnnotationProcessor mindustry.annotations.impl.StructAnnotationProcessor
mindustry.annotations.StructAnnotationProcessor mindustry.annotations.impl.SerializeAnnotationProcessor
mindustry.annotations.CallSuperAnnotationProcessor mindustry.annotations.impl.AssetsAnnotationProcessor
mindustry.annotations.AssetsAnnotationProcessor mindustry.annotations.impl.CallSuperAnnotationProcessor

View File

@@ -1,6 +1,10 @@
buildscript{ buildscript{
ext{ ext{
arcExtVersion = "e287fdce0449a87fb15599c67b5167ac0273bcb6" getArcHash = {
return new Properties().with{ p -> p.load(file('gradle.properties').newReader()); return p }["archash"]
}
arcHash = getArcHash()
} }
repositories{ repositories{
@@ -15,8 +19,8 @@ buildscript{
dependencies{ dependencies{
classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.8' classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.8'
classpath "com.github.anuken:packr:-SNAPSHOT" classpath "com.github.anuken:packr:-SNAPSHOT"
classpath "com.github.Anuken.Arc:packer:$arcExtVersion" classpath "com.github.Anuken.Arc:packer:$arcHash"
classpath "com.github.Anuken.Arc:arc-core:$arcExtVersion" classpath "com.github.Anuken.Arc:arc-core:$arcHash"
} }
} }
@@ -33,7 +37,6 @@ allprojects{
gdxVersion = '1.9.10' gdxVersion = '1.9.10'
roboVMVersion = '2.3.8' roboVMVersion = '2.3.8'
steamworksVersion = '891ed912791e01fe9ee6237a6497e5212b85c256' steamworksVersion = '891ed912791e01fe9ee6237a6497e5212b85c256'
arcHash = null
loadVersionProps = { loadVersionProps = {
return new Properties().with{p -> p.load(file('../core/assets/version.properties').newReader()); return p } 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() 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 -> arcModule = { String name ->
if(localArc()){ if(localArc()){
return project(":Arc:$name") return project(":Arc:$name")
@@ -133,6 +132,19 @@ allprojects{
props.store(pfile.newWriter(), "Autogenerated file. Do not modify.") 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{ repositories{
@@ -206,6 +218,7 @@ project(":core"){
outputs.upToDateWhen{ false } outputs.upToDateWhen{ false }
generateLocales() generateLocales()
writeVersion() writeVersion()
writeProcessors()
} }
task copyChangelog{ task copyChangelog{
@@ -230,31 +243,6 @@ project(":core"){
} }
dependencies{ 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) compileJava.dependsOn(preGen)
compile "org.lz4:lz4-java:1.4.1" 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-platform:$gdxVersion:natives-desktop"
compile "com.badlogicgames.gdx:gdx-freetype-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") compile arcModule("backends:backend-sdl")
} }
@@ -313,8 +301,8 @@ project(":annotations"){
apply plugin: "java" apply plugin: "java"
dependencies{ dependencies{
compile 'com.squareup:javapoet:1.11.0' compile 'com.squareup:javapoet:1.12.1'
compile "com.github.Anuken.Arc:arc-core:$arcExtVersion" compile "com.github.Anuken.Arc:arc-core:$arcHash"
compile files("${System.getProperty('java.home')}/../lib/tools.jar") compile files("${System.getProperty('java.home')}/../lib/tools.jar")
} }
} }

View File

@@ -104,6 +104,7 @@ mods.none = [LIGHT_GRAY]No mods found!
mods.guide = Modding Guide mods.guide = Modding Guide
mods.report = Report Bug mods.report = Report Bug
mods.openfolder = Open Mod Folder mods.openfolder = Open Mod Folder
mod.display = [gray]Mod:[orange] {0}
mod.enabled = [lightgray]Enabled mod.enabled = [lightgray]Enabled
mod.disabled = [scarlet]Disabled mod.disabled = [scarlet]Disabled
mod.disable = Disable mod.disable = Disable

View File

@@ -43,10 +43,10 @@ schematic.replace = Šablona tohoto jména již existuje. Chceš ji nahradit?
schematic.import = Importuji šablonu... schematic.import = Importuji šablonu...
schematic.exportfile = Exportovat soubor schematic.exportfile = Exportovat soubor
schematic.importfile = Importovat 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 = Zkopírovat do schránky
schematic.copy.import = Importovat ze 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.flip = [accent][[{0}][]/[accent][[{1}][]: Převrátit šablonu
schematic.saved = Šablona byla uložena. schematic.saved = Šablona byla uložena.
schematic.delete.confirm = Šablona bude kompletně vyhlazena. 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.remove.confirm = Tato modifikace bude odstraněna.
mod.author = [lightgray]Autor:[] {0} 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.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.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 = 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.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. mod.scripts.unsupported = Tvoje zařízení nepodporuje skripty. Některé modifikace nemusí správně fungovat.
about.button = O hře about.button = O hře
@@ -240,8 +240,8 @@ save.playtime = Herní čas: {0}
warning = Varování. warning = Varování.
confirm = Potvrdit confirm = Potvrdit
delete = Smazat delete = Smazat
view.workshop = Prohlédnout v dílně view.workshop = Prohlédnout ve Workshopu na Steamu
workshop.listing = Upravit popis v dílně workshop.listing = Upravit popis ve Workshopu na Steamu
ok = OK ok = OK
open = Otevřít open = Otevřít
customize = Přizpůsobit pravidla 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.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. map.invalid = Chyba v načítání mapy: poškozený nebo neplatný soubor mapy.
workshop.update = Aktualizovat položku workshop.update = Aktualizovat položku
workshop.error = Chyba při načítání podrobností z dílny: {0} 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 dílny (EULA), jinak se Tvoje mapa nezobrazí.[] 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.menu = Vyber si, co bys chtěl dělat s touto položkou.
workshop.info = Informace o položce workshop.info = Informace o položce
changelog = Seznam změn (volitelně): changelog = Seznam změn (volitelně):
eula = Smluvní podmínky platformy Steam 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... 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} publish.error = Chyba při vystavování položky: {0}
steam.error = Nepodařilo se inicializovat služby platformy Steam.\Chyba: {0} steam.error = Nepodařilo se inicializovat služby platformy Steam.\Chyba: {0}
@@ -309,9 +309,9 @@ editor.waves = Vln:
editor.rules = Pravidla: editor.rules = Pravidla:
editor.generation = Generace: editor.generation = Generace:
editor.ingame = Upravit ve hře 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 editor.newmap = Nová mapa
workshop = Dílna workshop = Workshop na Steamu
waves.title = Vlny waves.title = Vlny
waves.remove = Odebrat waves.remove = Odebrat
waves.never = <Nikdy> waves.never = <Nikdy>
@@ -761,13 +761,13 @@ rules.blockhealthmultiplier = Násobek zdraví bloků
rules.playerhealthmultiplier = Násobek zdraví hráče rules.playerhealthmultiplier = Násobek zdraví hráče
rules.playerdamagemultiplier = Násobek útoku hráče rules.playerdamagemultiplier = Násobek útoku hráče
rules.unitdamagemultiplier = Násobek poškození jednotkami 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.respawntime = Čas znovuzrození: [lightgray](vteřin)[]
rules.wavespacing = Čas rozestupu mezi vlnami: [lightgray](vteřin)[] rules.wavespacing = Čas rozestupu mezi vlnami: [lightgray](vteřin)[]
rules.buildcostmultiplier = Násobek ceny stavění rules.buildcostmultiplier = Násobek ceny stavění
rules.buildspeedmultiplier = Násobek rychlosti stavění rules.buildspeedmultiplier = Násobek rychlosti stavění
rules.waitForWaveToEnd = Vlny čekají na nepřátele 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.respawns = Maximální počet znovuvylíhnutí za vlnu
rules.limitedRespawns = Maximální počet znovuzrození rules.limitedRespawns = Maximální počet znovuzrození
rules.title.waves = Vlny rules.title.waves = Vlny
@@ -943,7 +943,8 @@ block.inverted-sorter.name = Obrácená třídička
block.message.name = Zpráva block.message.name = Zpráva
block.illuminator.name = Osvětlovač block.illuminator.name = Osvětlovač
block.illuminator.description = Malý, kompaktní, konfigurovatelný zdroj světla. Vyžaduje pro svoje fungování energii. 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.silicon-smelter.name = Křemíková huť
block.phase-weaver.name = Tkalcovna pro fázovou tkaninu block.phase-weaver.name = Tkalcovna pro fázovou tkaninu
block.pulverizer.name = Rozmělňovač block.pulverizer.name = Rozmělňovač
@@ -1034,8 +1035,8 @@ block.overdrive-projector.name = Urychlující projektor
block.force-projector.name = Silový projektor block.force-projector.name = Silový projektor
block.arc.name = Oblouk block.arc.name = Oblouk
block.rtg-generator.name = RTG block.rtg-generator.name = RTG
block.spectre.name = Duch block.spectre.name = Spectre
block.meltdown.name = Tavička block.meltdown.name = Meltdown
block.container.name = Kontejnér block.container.name = Kontejnér
block.launch-pad.name = Vysílací plošina block.launch-pad.name = Vysílací plošina
block.launch-pad-large.name = Velká 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.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.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.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.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.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í. 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.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.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.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.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.draug-factory.description = Vyrábí těžící drony Dragoun.
block.spirit-factory.description = Vyrábí drony, které opravují budovy. block.spirit-factory.description = Vyrábí drony, které opravují budovy.
block.phantom-factory.description = Vyrábí drony s pokročilou konstrukcí. block.phantom-factory.description = Vyrábí drony s pokročilou konstrukcí.

View File

@@ -3,7 +3,7 @@ credits = Tekijät
contributors = Kääntäjät ja avustajat contributors = Kääntäjät ja avustajat
discord = Liity Mindustryn Discordiin! discord = Liity Mindustryn Discordiin!
link.discord.description = Mindustryn virallinen Discord-keskusteluhuone 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.github.description = Pelin lähdekoodi
link.changelog.description = Lista päivityksien muutoksista link.changelog.description = Lista päivityksien muutoksista
link.dev-builds.description = Epävakaat kehitysversiot link.dev-builds.description = Epävakaat kehitysversiot
@@ -19,47 +19,47 @@ screenshot.invalid = Kartta liian laaja, kuvankaappaukselle ei mahdollisesti ole
gameover = Peli ohi gameover = Peli ohi
gameover.pvp = [accent] {0}[] joukkue voittaa! gameover.pvp = [accent] {0}[] joukkue voittaa!
highscore = [accent]Uusi ennätys! highscore = [accent]Uusi ennätys!
copied = Copied. copied = Kopioitu.
load.sound = Sounds load.sound = Ääni
load.map = Maps load.map = Kartat
load.image = Images load.image = Kuvat
load.content = Content load.content = Sisältö
load.system = System load.system = Systeemi
load.mod = Mods load.mod = Modit
load.scripts = Scripts load.scripts = Skriptit
be.update = A new Bleeding Edge build is available: be.update = A new Bleeding Edge build is available:
be.update.confirm = Download it and restart now? be.update.confirm = Lataa se ja käynnistä peli uudelleen?
be.updating = Updating... be.updating = Päivitetään...
be.ignore = Ignore be.ignore = Sivuuta
be.noupdates = No updates found. be.noupdates = Ei päivityksiä saatavilla.
be.check = Check for updates be.check = Tarkista päivityksiä
schematic = Schematic schematic = Kaavio
schematic.add = Save Schematic... schematic.add = Tallenna Kaavio...
schematics = Schematics schematics = Kaaviot
schematic.replace = A schematic by that name already exists. Replace it? schematic.replace = Kaavio tällä nimellä on jo olemassa. Haluatko korvata sen?
schematic.import = Import Schematic... schematic.import = Tuo Kaavio...
schematic.exportfile = Export File schematic.exportfile = Luo Tiedosto
schematic.importfile = Import File schematic.importfile = Tuo Tiedosto
schematic.browseworkshop = Browse Workshop schematic.browseworkshop = Selaa Työpajaa
schematic.copy = Copy to Clipboard schematic.copy = Kopioi Leikepöydälle
schematic.copy.import = Import from Clipboard schematic.copy.import = Tou Leikepöydälle
schematic.shareworkshop = Share on Workshop schematic.shareworkshop = Jaa työpajaan
schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Flip Schematic schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Käännä Kaavio
schematic.saved = Schematic saved. schematic.saved = Kaavio tallennettu.
schematic.delete.confirm = This schematic will be utterly eradicated. schematic.delete.confirm = Tämä kaavio poistetaan.
schematic.rename = Rename Schematic schematic.rename = Uudelleennimeä Kaavio
schematic.info = {0}x{1}, {2} blocks 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.enemiesDestroyed = Vihollisia tuhottu:[accent] {0}
stat.built = Rakennuksia rakennettu:[accent] {0} stat.built = Rakennuksia rakennettu:[accent] {0}
stat.destroyed = Rakennuksia tuhottu:[accent] {0} stat.destroyed = Rakennuksia tuhottu:[accent] {0}
stat.deconstructed = Rakennuksia purettu:[accent] {0} stat.deconstructed = Rakennuksia purettu:[accent] {0}
stat.delivered = Resursseja laukaistu: stat.delivered = Resursseja laukaistu:
stat.rank = Lopullinen arvo: [accent]{0} stat.rank = Lopullinen arvosana: [accent]{0}
launcheditems = [accent]Laukaistut tavarat launcheditems = [accent]Laukaistut tavarat
launchinfo = [unlaunched][[LAUNCH] your core to obtain the items indicated in blue. launchinfo = [unlaunched][[LAUNCH] your core to obtain the items indicated in blue.
@@ -78,49 +78,49 @@ customgame = Mukautettu peli
newgame = Uusi peli newgame = Uusi peli
none = <ei mitään> none = <ei mitään>
minimap = Pienoiskartta minimap = Pienoiskartta
position = Position position = Sijainti
close = Sulje close = Sulje
website = Verkkosivu website = Verkkosivu
quit = Poistu quit = Poistu
save.quit = Save & Quit save.quit = Tallenna ja Poistu
maps = Kartat maps = Kartat
maps.browse = Browse Maps maps.browse = Selaa Karttoja
continue = Jatka continue = Jatka
maps.none = [lightgray]Karttoja ei löytynyt! maps.none = [lightgray]Karttoja ei löytynyt!
invalid = Invalid invalid = Invalidi
pickcolor = Pick Color pickcolor = Valitse väri
preparingconfig = Preparing Config preparingconfig = Preparing Config
preparingcontent = Preparing Content preparingcontent = Preparing Content
uploadingcontent = Uploading Content uploadingcontent = Uploading Content
uploadingpreviewfile = Uploading Preview File uploadingpreviewfile = Uploading Preview File
committingchanges = Comitting Changes committingchanges = Comitting Changes
done = Done done = Valmis
feature.unsupported = Your device does not support this feature. 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.alpha = [accent](Alpha)
mods = Mods mods = Modit
mods.none = [LIGHT_GRAY]No mods found! mods.none = [LIGHT_GRAY]Modeja ei löytynyt!
mods.guide = Modding Guide mods.guide = Modaamisen opas
mods.report = Report Bug mods.report = Raportoi ohjelmistovirhe
mods.openfolder = Open Mod Folder mods.openfolder = Avaa Modikansio
mod.enabled = [lightgray]Enabled mod.enabled = [lightgray]Käytössä
mod.disabled = [scarlet]Disabled mod.disabled = [scarlet]Epäkäytössä
mod.disable = Disable mod.disable = Laita pois päältä
mod.delete.error = Unable to delete mod. File may be in use. mod.delete.error = Modia ei pystynyt poistamaan. Tiedosto voi olla käytössä.
mod.requiresversion = [scarlet]Requires min game version: [accent]{0} mod.requiresversion = [scarlet]Tarvitsee vähintää pelin version: [accent]{0}
mod.missingdependencies = [scarlet]Missing dependencies: {0} mod.missingdependencies = [scarlet]Tarvitsee nämä modit: {0}
mod.erroredcontent = [scarlet]Content Errors mod.erroredcontent = [scarlet]Sisältö Virheet
mod.errors = Errors have occurred loading content. mod.errors = Virheitä on tapahtunut pelin ladatessa.
mod.noerrorplay = [scarlet]You have mods with errors.[] Either disable the affected mods or fix the errors before playing. 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.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.enable = Käytä
mod.requiresrestart = The game will now close to apply the mod changes. mod.requiresrestart = Peli suljetaan jotta muutokset voisivat toteutua.
mod.reloadrequired = [scarlet]Reload Required mod.reloadrequired = [scarlet]Vaatii Uudelleenkäynnistystä
mod.import = Import Mod mod.import = Tuo Modi
mod.import.github = Import GitHub Mod 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.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.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.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. 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.kick = Sinut on potkittu palvelimelta!
server.kicked.whitelist = You are not whitelisted here. server.kicked.whitelist = You are not whitelisted here.
server.kicked.serverClose = Palvelin suljettu. 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.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.banned = Sinulla on portikielto tälle palvelimelle.
server.kicked.typeMismatch = This server is not compatible with your build type. 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.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.nameInUse = Joku tuon niminen\non jo tällä palvelimella.
server.kicked.nameEmpty = Valitsemasi nimi on virheellinen. 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.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.customClient = Tämä palvelin ei tue muokattuja versioita. Lataa virallinen versio.
server.kicked.gameover = Peli ohi! 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}[] 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. 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. 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 hostserver = Pidä yllä monipelaaja peliä
invitefriends = Invite Friends invitefriends = Pyydä Ystäviä
hostserver.mobile = Host\nGame hostserver.mobile = Host\nGame
host = Host host = Host
hosting = [accent]Avataan palvelinta... hosting = [accent]Avataan palvelinta...
hosts.refresh = Päivitä hosts.refresh = Päivitä
hosts.discovering = Discovering LAN games hosts.discovering = Etsitään LAN pelejä
hosts.discovering.any = Discovering games hosts.discovering.any = Etsitään Pelejä
server.refreshing = Päivitetään palvelimen tietoja server.refreshing = Päivitetään palvelimen tietoja
hosts.none = [lightgray]No local games found! hosts.none = [lightgray]Paikallisia pelejä ei löytynyt!
host.invalid = [scarlet]Can't connect to host. host.invalid = [scarlet]Isäntään ei voitu yhdistää.
trace = Trace Player trace = Seuraa Pelaajaa
trace.playername = Pelaajanimi: [accent]{0} trace.playername = Pelaajanimi: [accent]{0}
trace.ip = IP-osoite: [accent]{0} trace.ip = IP-osoite: [accent]{0}
trace.id = Uniikki tunniste: [accent]{0} trace.id = Uniikki tunniste: [accent]{0}
@@ -188,17 +188,17 @@ server.outdated = [crimson]Vanhentunut palvelin![]
server.outdated.client = [crimson]Vanhentunut asiakasohjelma![] server.outdated.client = [crimson]Vanhentunut asiakasohjelma![]
server.version = [gray]v{0} {1} server.version = [gray]v{0} {1}
server.custombuild = [yellow]Custom Build server.custombuild = [yellow]Custom Build
confirmban = Are you sure you want to ban this player? confirmban = Oletko varma että haluat potkia tämän pelaajan?
confirmkick = Are you sure you want to kick this player? confirmkick = Oletko varma että haluat poistaa tämän pelaajan?
confirmvotekick = Are you sure you want to vote-kick this player? confirmvotekick = Oletko varma että haluat äänestää tämän pelaajan potkituksi?
confirmunban = Are you sure you want to unban this player? confirmunban = Oletko varma että haluat päästää tämän pelaajan takaisin?
confirmadmin = Are you sure you want to make this player an admin? confirmadmin = Oletko varma että haluat antaa pelaajalle hallinto-oikeuksia?
confirmunadmin = Are you sure you want to remove admin status from this player? confirmunadmin = Are you sure you want to remove admin status from this player?
joingame.title = Liity peliin joingame.title = Liity peliin
joingame.ip = Osoite: joingame.ip = Osoite:
disconnect = Disconnected. disconnect = Yhteys katkaistu.
disconnect.error = Connection error. disconnect.error = Yhteysvirhe.
disconnect.closed = Connection closed. disconnect.closed = Yhteys poistettu.
disconnect.timeout = Timed out. disconnect.timeout = Timed out.
disconnect.data = Failed to load world data! disconnect.data = Failed to load world data!
cantconnect = Unable to join game ([accent]{0}[]). 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? save.overwrite = Are you sure you want to overwrite\nthis save slot?
overwrite = Overwrite overwrite = Overwrite
save.none = No saves found! save.none = No saves found!
saveload = Saving... saveload = Tallennetaan...
savefail = Failed to save game! savefail = Failed to save game!
save.delete.confirm = Are you sure you want to delete this save? save.delete.confirm = Are you sure you want to delete this save?
save.delete = Delete save.delete = Delete
@@ -220,7 +220,7 @@ save.export = Export Save
save.import.invalid = [accent]This save is invalid! save.import.invalid = [accent]This save is invalid!
save.import.fail = [crimson]Failed to import save: [accent]{0} save.import.fail = [crimson]Failed to import save: [accent]{0}
save.export.fail = [crimson]Failed to export 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.newslot = Tallennuksen nimi:
save.rename = Nimeä uudelleen save.rename = Nimeä uudelleen
save.rename.text = Uusi nimi: save.rename.text = Uusi nimi:
@@ -265,8 +265,8 @@ cancelbuilding = [accent][[{0}][] to clear plan
selectschematic = [accent][[{0}][] to select+copy selectschematic = [accent][[{0}][] to select+copy
pausebuilding = [accent][[{0}][] to pause building pausebuilding = [accent][[{0}][] to pause building
resumebuilding = [scarlet][[{0}][] to resume building resumebuilding = [scarlet][[{0}][] to resume building
wave = [accent]Aalto {0} wave = [accent]Taso {0}
wave.waiting = [lightgray]Wave in {0} wave.waiting = [lightgray]Seuraava taso {0}
wave.waveInProgress = [lightgray]Wave in progress wave.waveInProgress = [lightgray]Wave in progress
waiting = [lightgray]Odotetaan... waiting = [lightgray]Odotetaan...
waiting.players = Odotetaan pelaajia... waiting.players = Odotetaan pelaajia...
@@ -275,7 +275,7 @@ wave.enemy = [lightgray]{0} vihollinen jäljellä
loadimage = Lataa kuva loadimage = Lataa kuva
saveimage = Tallenna kuva saveimage = Tallenna kuva
unknown = Tuntematon unknown = Tuntematon
custom = Custom custom = Mukautettu
builtin = Sisäänrakennettu builtin = Sisäänrakennettu
map.delete.confirm = Oletko varma että haluat poistaa tämän kartan? Poistoa ei voi peruuttaa! map.delete.confirm = Oletko varma että haluat poistaa tämän kartan? Poistoa ei voi peruuttaa!
map.random = [accent]Satunnainen kartta 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} publish.error = Error publishing item: {0}
steam.error = Failed to initialize Steam services.\nError: {0} steam.error = Failed to initialize Steam services.\nError: {0}
editor.brush = Brush editor.brush = Sivellin
editor.openin = Avaa editorissa editor.openin = Avaa editorissa
editor.oregen = Ore Generation editor.oregen = Ore Generation
editor.oregen.info = Ore Generation: editor.oregen.info = Ore Generation:
editor.mapinfo = Kartan tiedot editor.mapinfo = Kartan tiedot
editor.author = Author: editor.author = Tekijä:
editor.description = Kuvaus: editor.description = Kuvaus:
editor.nodescription = A map must have a description of at least 4 characters before being published. editor.nodescription = Kartan kuvaksessa täytyy olla vähintään neljä kirjainta ennen julkaisua.
editor.waves = Aallot: editor.waves = Tasot:
editor.rules = Säännöt: editor.rules = Säännöt:
editor.generation = Generation: editor.generation = Generaatio:
editor.ingame = Edit In-Game editor.ingame = Muokka pelin sisällä
editor.publish.workshop = Publish On Workshop editor.publish.workshop = Julkaise työpajaan
editor.newmap = Uusi kartta editor.newmap = Uusi kartta
workshop = Workshop workshop = Työpaja
waves.title = Aallot waves.title = Tasot
waves.remove = Remove waves.remove = Poista
waves.never = <ei koskaan> waves.never = <ei koskaan>
waves.every = every waves.every = every
waves.waves = wave(s) waves.waves = wave(s)
waves.perspawn = per spawn waves.perspawn = per spawni
waves.to = to waves.to = to
waves.boss = Boss waves.boss = Pomo
waves.preview = Preview waves.preview = Esikatselu
waves.edit = Muokkaa... waves.edit = Muokkaa...
waves.copy = Kopioi leikepöydälle waves.copy = Kopioi leikepöydälle
waves.load = Lataa leikepöydältä waves.load = Lataa leikepöydältä
@@ -327,11 +327,11 @@ waves.invalid = Invalid waves in clipboard.
waves.copied = Aallot kopioitu. waves.copied = Aallot kopioitu.
waves.none = No enemies defined.\nNote that empty wave layouts will automatically be replaced with the default layout. waves.none = No enemies defined.\nNote that empty wave layouts will automatically be replaced with the default layout.
editor.default = [lightgray]<Default> editor.default = [lightgray]<Default>
details = Details... details = Yksityiskohdat...
edit = Muokkaa... edit = Muokkaa...
editor.name = Nimi: editor.name = Nimi:
editor.spawn = Spawn Unit editor.spawn = Spawni yksikkö
editor.removeunit = Remove Unit editor.removeunit = Poista yksikkö
editor.teams = Joukkueet editor.teams = Joukkueet
editor.errorload = Virhe ladattaessa tiedostoa:\n[accent]{0} editor.errorload = Virhe ladattaessa tiedostoa:\n[accent]{0}
editor.errorsave = Virhe tallennettaessa 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.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.errorname = Map has no name defined. Are you trying to load a save file?
editor.update = Päivitä editor.update = Päivitä
editor.randomize = Randomize editor.randomize = Satunnaista
editor.apply = Apply editor.apply = Käytä
editor.generate = Generate editor.generate = Generoi
editor.resize = Resize editor.resize = Säädä kokoa
editor.loadmap = Lataa kartta editor.loadmap = Lataa kartta
editor.savemap = Tallenna kartta editor.savemap = Tallenna kartta
editor.saved = Tallennettu! editor.saved = Tallennettu!
@@ -370,12 +370,12 @@ editor.resizemap = Resize Map
editor.mapname = Kartan nimi: editor.mapname = Kartan nimi:
editor.overwrite = [accent]Warning!\nThis overwrites an existing map. 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.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.exists = Kartta tällä nimellä on jo olemassa.
editor.selectmap = Select a map to load: editor.selectmap = Valitse kartta ladattavaksi:
toolmode.replace = Replace toolmode.replace = Korvaa
toolmode.replace.description = Draws only on solid blocks. 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.replaceall.description = Replace all blocks in map.
toolmode.orthogonal = Orthogonal toolmode.orthogonal = Orthogonal
toolmode.orthogonal.description = Draws only orthogonal lines. toolmode.orthogonal.description = Draws only orthogonal lines.
@@ -424,48 +424,48 @@ width = Leveys:
height = Korkeus: height = Korkeus:
menu = Valikko menu = Valikko
play = Pelaa play = Pelaa
campaign = Campaign campaign = Polku
load = Lataa load = Lataa
save = Tallenna save = Tallenna
fps = FPS: {0} fps = FPS: {0}
ping = Ping: {0}ms ping = Ping: {0}ms
language.restart = Please restart your game for the language settings to take effect. language.restart = Please restart your game for the language settings to take effect.
settings = Asetukset settings = Asetukset
tutorial = Perehdytys tutorial = Tutoriaali
tutorial.retake = Re-Take Tutorial tutorial.retake = Uusita Tutoriaali
editor = Editor editor = Editori
mapeditor = Map Editor mapeditor = Kartan Editori
abandon = Hylkää abandon = Hylkää
abandon.text = This zone and all its resources will be lost to the enemy. abandon.text = This zone and all its resources will be lost to the enemy.
locked = Lukittu locked = Lukittu
complete = [lightgray]Reach: complete = [lightgray]Reach:
requirement.wave = Reach Wave {0} in {1} requirement.wave = Pääse Tasolle {0} kartassa {1}
requirement.core = Destroy Enemy Core in {0} requirement.core = Tuhoa vihollise ydin kartassa {0}
requirement.unlock = Unlock {0} requirement.unlock = Avaa {0}
resume = Resume Zone:\n[lightgray]{0} resume = Resume Zone:\n[lightgray]{0}
bestwave = [lightgray]Best Wave: {0} bestwave = [lightgray]Paras taso: {0}
launch = < LAUNCH > launch = < LAUNCH >
launch.title = Launch Successful launch.title = Onnistunut laukaisu
launch.next = [lightgray]next opportunity at wave {0} launch.next = [lightgray]next opportunity at wave {0}
launch.unable2 = [scarlet]Unable to LAUNCH.[] 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.confirm = Tämä laukaisee kaikki resourssit ytimestäsi.\nEt voi enää palata takaisin.
launch.skip.confirm = If you skip now, you will not be able to launch until later waves. launch.skip.confirm = Jos ohitat nyt, voit laukaista vasta myöhemmissä tasoissa.
uncover = Uncover uncover = Paljasta
configure = Configure Loadout configure = Configure Loadout
bannedblocks = Banned Blocks bannedblocks = Kielletyt Palikat
addall = Add All addall = Lisää kaikki
configure.locked = [lightgray]Unlock configuring loadout: Wave {0}. configure.locked = [lightgray]Unlock configuring loadout: Wave {0}.
configure.invalid = Amount must be a number between 0 and {0}. configure.invalid = Amount must be a number between 0 and {0}.
zone.unlocked = [lightgray]{0} unlocked. zone.unlocked = [lightgray]{0} unlocked.
zone.requirement.complete = Wave {0} reached:\n{1} zone requirements met. zone.requirement.complete = Wave {0} reached:\n{1} zone requirements met.
zone.config.unlocked = Loadout unlocked:[lightgray]\n{0} zone.config.unlocked = Loadout unlocked:[lightgray]\n{0}
zone.resources = [lightgray]Resources Detected: zone.resources = [lightgray]Resoursseja havaittu:
zone.objective = [lightgray]Objective: [accent]{0} zone.objective = [lightgray]Objectiivi: [accent]{0}
zone.objective.survival = Survive zone.objective.survival = Selviydy
zone.objective.attack = Destroy Enemy Core zone.objective.attack = Destroy Enemy Core
add = Add... add = Lisää...
boss.health = Boss Health boss.health = Pomon elinpisteet
connectfail = [crimson]Connection error:\n\n[accent]{0} connectfail = [crimson]Connection error:\n\n[accent]{0}
error.unreachable = Server unreachable.\nIs the address spelled correctly? 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.any = Unknown network error.
error.bloom = Failed to initialize bloom.\nYour device may not support it. error.bloom = Failed to initialize bloom.\nYour device may not support it.
zone.groundZero.name = Ground Zero zone.groundZero.name = Vaara Alue
zone.desertWastes.name = Desert Wastes zone.desertWastes.name = Aavikon Jätteet
zone.craters.name = The Craters zone.craters.name = Kraatterit
zone.frozenForest.name = Frozen Forest zone.frozenForest.name = Jäätynyt Metsä
zone.ruinousShores.name = Ruinous Shores zone.ruinousShores.name = Tuhoisa Ranta
zone.stainedMountains.name = Stained Mountains zone.stainedMountains.name = Tahravuoret
zone.desolateRift.name = Desolate Rift zone.desolateRift.name = Autio Syvänne
zone.nuclearComplex.name = Nuclear Production Complex zone.nuclearComplex.name = Ydinvoima Kompleksi
zone.overgrowth.name = Overgrowth zone.overgrowth.name = Liikakasvu
zone.tarFields.name = Tar Fields zone.tarFields.name = Terva Pellot
zone.saltFlats.name = Salt Flats zone.saltFlats.name = Suolainen Tasanne
zone.impact0078.name = Impact 0078 zone.impact0078.name = Isku 0078
zone.crags.name = Crags zone.crags.name = Kalliot
zone.fungalPass.name = Fungal Pass 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.groundZero.description = Suotuisa alue aloittaa peli. Matala vaarataso. Vähän resoursseja.\nKerää mahdollisimman paljon kuparia ja lyijyä.\nJatka eteenpäin.
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.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 = 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.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 = 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.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 = 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.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 = 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.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 = 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.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 = 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.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 = 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.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 = 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.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 = 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.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 = 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.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 = <insert description here> zone.impact0078.description = <insert description here>
zone.crags.description = <insert description here> zone.crags.description = <insert description here>
settings.language = Language settings.language = Kieli
settings.data = Game Data settings.data = Peli Data
settings.reset = Reset to Defaults settings.reset = Nollaa Asetukset
settings.rebind = Rebind settings.rebind = Uudelleenaseta
settings.resetKey = Reset settings.resetKey = Aseta Uudelleen
settings.controls = Controls settings.controls = Kontrollit
settings.game = Game settings.game = Peli
settings.sound = Sound settings.sound = Ääni
settings.graphics = Graphics settings.graphics = Grafiikat
settings.cleardata = Clear Game Data... settings.cleardata = Tyhjennä Pelin Data...
settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone! settings.clear.confirm = Oletko varma että haluat tyhjentää pelin datan?\nMitä on tehty ei voi peruuttaa!
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. 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]< Paused > paused = [accent]< Pysäytetty >
clear = Clear clear = Tyhjä
banned = [scarlet]Banned banned = [scarlet]Kielletty
yes = Yes yes = Kyllä
no = No no = Ei
info.title = Info info.title = Informaatio
error.title = [crimson]An error has occured error.title = [crimson]An error has occured
error.crashtitle = An error has occured error.crashtitle = An error has occured
blocks.input = Input blocks.input = Sisääntulo
blocks.output = Output blocks.output = Ulostulo
blocks.booster = Booster blocks.booster = Boostaa
block.unknown = [lightgray]??? block.unknown = [lightgray]???
blocks.powercapacity = Power Capacity blocks.powercapacity = Energiakapasiteetti
blocks.powershot = Power/Shot blocks.powershot = Energiaa/Ammus
blocks.damage = Damage blocks.damage = Vahinko
blocks.targetsair = Targets Air blocks.targetsair = Hyökkää Ilmaan
blocks.targetsground = Targets Ground blocks.targetsground = Hyökkää Maahan
blocks.itemsmoved = Move Speed blocks.itemsmoved = Liikkumisnopeus
blocks.launchtime = Time Between Launches blocks.launchtime = Aika Laukaisujen Välillä
blocks.shootrange = Range blocks.shootrange = Kantama
blocks.size = Size blocks.size = Koko
blocks.liquidcapacity = Liquid Capacity blocks.liquidcapacity = Neste Kapasiteetti
blocks.powerrange = Power Range blocks.powerrange = Energia Kantama
blocks.powerconnections = Max Connections blocks.powerconnections = Maksimi konnektio määrä
blocks.poweruse = Power Use blocks.poweruse = Energian Käyttö
blocks.powerdamage = Power/Damage blocks.powerdamage = Energia/Vahinko
blocks.itemcapacity = Item Capacity blocks.itemcapacity = Tavara Kapasiteetti
blocks.basepowergeneration = Base Power Generation blocks.basepowergeneration = Kanta Enegian Generointi
blocks.productiontime = Production Time blocks.productiontime = Produktion Aika
blocks.repairtime = Block Full Repair Time blocks.repairtime = Kokonaisen Palikan Korjaus Aika
blocks.speedincrease = Speed Increase blocks.speedincrease = Nopeuden Kasvu
blocks.range = Range blocks.range = Etäisyys
blocks.drilltier = Drillables blocks.drilltier = Porattavat
blocks.drillspeed = Base Drill Speed blocks.drillspeed = Kanta Poran Nopeus
blocks.boosteffect = Boost Effect blocks.boosteffect = Boostaamisen Vaikutus
blocks.maxunits = Max Active Units blocks.maxunits = Maksimi Määrä Yksikköjä
blocks.health = Health blocks.health = Elämäpisteet
blocks.buildtime = Build Time blocks.buildtime = Rakentamisen Aika
blocks.buildcost = Build Cost blocks.buildcost = Rakentamisen Hinta
blocks.inaccuracy = Inaccuracy blocks.inaccuracy = Epätarkkuus
blocks.shots = Shots blocks.shots = Ammusta
blocks.reload = Shots/Second blocks.reload = Ammusta/Sekunnissa
blocks.ammo = Ammo blocks.ammo = Ammus
bar.drilltierreq = Better Drill Required bar.drilltierreq = Parempi Pora Vaadittu
bar.drillspeed = Drill Speed: {0}/s bar.drillspeed = Poran Nopeus: {0}/s
bar.pumpspeed = Pump Speed: {0}/s bar.pumpspeed = Pumpun Nopeus: {0}/s
bar.efficiency = Efficiency: {0}% bar.efficiency = Tehokkuus: {0}%
bar.powerbalance = Power: {0}/s bar.powerbalance = Energia: {0}/s
bar.powerstored = Stored: {0}/{1} bar.powerstored = Säilöttynä: {0}/{1}
bar.poweramount = Power: {0} bar.poweramount = Energia: {0}
bar.poweroutput = Power Output: {0} bar.poweroutput = Energian Ulostulo: {0}
bar.items = Items: {0} bar.items = Tavaroita: {0}
bar.capacity = Capacity: {0} bar.capacity = Kapasiteetti: {0}
bar.liquid = Liquid bar.liquid = Neste
bar.heat = Heat bar.heat = Lämpö
bar.power = Power bar.power = Energia
bar.progress = Build Progress bar.progress = Rakennuksen Edistys
bar.spawned = Units: {0}/{1} bar.spawned = Yksikköjä: {0}/{1}
bar.input = Input bar.input = Sisääntulo
bar.output = Output bar.output = Ulostulo
bullet.damage = [stat]{0}[lightgray] damage bullet.damage = [stat]{0}[lightgray] Vahinko
bullet.splashdamage = [stat]{0}[lightgray] area dmg ~[stat] {1}[lightgray] tiles bullet.splashdamage = [stat]{0}[lightgray] Alue vahinko ~[stat] {1}[lightgray] palikkaa
bullet.incendiary = [stat]incendiary bullet.incendiary = [stat]sytyttävä
bullet.homing = [stat]homing bullet.homing = [stat]itseohjautuva
bullet.shock = [stat]shock bullet.shock = [stat]shokki
bullet.frag = [stat]frag bullet.frag = [stat]sirpaloituva
bullet.knockback = [stat]{0}[lightgray] knockback bullet.knockback = [stat]{0}[lightgray] knockback
bullet.freezing = [stat]freezing bullet.freezing = [stat]jäädyttävä
bullet.tarred = [stat]tarred bullet.tarred = [stat]tervattu
bullet.multiplier = [stat]{0}[lightgray]x ammo multiplier bullet.multiplier = [stat]{0}[lightgray]x ammusten multiplikaatio
bullet.reload = [stat]{0}[lightgray]x fire rate bullet.reload = [stat]{0}[lightgray]x ammunta nopeus
unit.blocks = blocks unit.blocks = palikat
unit.powersecond = power units/second unit.powersecond = energia yksikköä/sekunti
unit.liquidsecond = liquid units/second unit.liquidsecond = neste yksikköä/sekunti
unit.itemssecond = items/second unit.itemssecond = esinettä/sekunti
unit.liquidunits = liquid units unit.liquidunits = neste yksikköä
unit.powerunits = power units unit.powerunits = energia yksikköä
unit.degrees = degrees unit.degrees = astetta
unit.seconds = seconds unit.seconds = sekunttia
unit.persecond = /sec unit.persecond = /s
unit.timesspeed = x speed unit.timesspeed = x nopeus
unit.percent = % unit.percent = %
unit.items = items unit.items = esinettä
unit.thousands = k unit.thousands = t
unit.millions = mil unit.millions = mil
category.general = General category.general = Yleinen
category.power = Power category.power = Energia
category.liquids = Liquids category.liquids = Neste
category.items = Items category.items = Tavarat
category.crafting = Input/Output category.crafting = Ulos/Sisääntulo
category.shooting = Shooting category.shooting = Ammunta
category.optional = Optional Enhancements category.optional = Mahdolliset Lumoukset
setting.landscape.name = Lock Landscape setting.landscape.name = Lukitse tasavaakaan
setting.shadows.name = Shadows setting.shadows.name = Varjot
setting.blockreplace.name = Automatic Block Suggestions setting.blockreplace.name = Automaattisia Palikka Suosituksia
setting.linear.name = Linear Filtering setting.linear.name = Lineararien Filteeraus
setting.hints.name = Hints setting.hints.name = Vihjeet
setting.buildautopause.name = Auto-Pause Building setting.buildautopause.name = Automaattisest Pysäytä Rakentaessa
setting.animatedwater.name = Animated Water setting.animatedwater.name = Animoitu Vesi
setting.animatedshields.name = Animated Shields setting.animatedshields.name = Animoitu Kilpi
setting.antialias.name = Antialias[lightgray] (requires restart)[] setting.antialias.name = Antialiaasi[lightgray] (vaatii uudelleenkäynnistyksen)[]
setting.indicators.name = Enemy/Ally Indicators setting.indicators.name = Vihollis/Puolulais Indikaattorit
setting.autotarget.name = Auto-Target setting.autotarget.name = Automaatinen Tähtäys
setting.keyboard.name = Mouse+Keyboard Controls setting.keyboard.name = Hiiri+Näppäimistö Kontrollit
setting.touchscreen.name = Touchscreen Controls setting.touchscreen.name = Kosketusnäyttö kontrollit
setting.fpscap.name = Max FPS setting.fpscap.name = Maksimi FPS
setting.fpscap.none = None setting.fpscap.none = Ei Mitään
setting.fpscap.text = {0} FPS setting.fpscap.text = {0} FPS
setting.uiscale.name = UI Scaling[lightgray] (require restart)[] setting.uiscale.name = UI Koko[lightgray] (vaatii uudelleenkäynnistyksen)[]
setting.swapdiagonal.name = Always Diagonal Placement setting.swapdiagonal.name = Aina Vino Korvaus
setting.difficulty.training = Training setting.difficulty.training = Treeni
setting.difficulty.easy = Easy setting.difficulty.easy = Helppo
setting.difficulty.normal = Normal setting.difficulty.normal = Keskivaikea
setting.difficulty.hard = Hard setting.difficulty.hard = Haastava
setting.difficulty.insane = Insane setting.difficulty.insane = Järjetön
setting.difficulty.name = Difficulty: setting.difficulty.name = Vaikeustaso:
setting.screenshake.name = Screen Shake setting.screenshake.name = Näytön keikkuminen
setting.effects.name = Display Effects setting.effects.name = Naytön Efektit
setting.destroyedblocks.name = Display Destroyed Blocks setting.destroyedblocks.name = Näytä Tuhoutuneet Palikat
setting.conveyorpathfinding.name = Conveyor Placement Pathfinding setting.conveyorpathfinding.name = Conveyor Placement Pathfinding
setting.coreselect.name = Allow Schematic Cores setting.coreselect.name = Allow Schematic Cores
setting.sensitivity.name = Controller Sensitivity setting.sensitivity.name = Kontrollin Herkkyys
setting.saveinterval.name = Save Interval setting.saveinterval.name = Tallennuksen Aikaväli
setting.seconds = {0} Seconds setting.seconds = {0} Sekunttia
setting.blockselecttimeout.name = Block Select Timeout setting.blockselecttimeout.name = Block Select Timeout
setting.milliseconds = {0} milliseconds setting.milliseconds = {0} millisekunttia
setting.fullscreen.name = Fullscreen setting.fullscreen.name = Fullscreen
setting.borderlesswindow.name = Borderless Window[lightgray] (may require restart) setting.borderlesswindow.name = Borderless Window[lightgray] (vaatii uudelleenkäynnistyksen)
setting.fps.name = Show FPS setting.fps.name = Näytä FPS
setting.blockselectkeys.name = Show Block Select Keys setting.blockselectkeys.name = Bäytä Palikan Selektio Kontrollit
setting.vsync.name = VSync setting.vsync.name = VSync
setting.pixelate.name = Pixelate[lightgray] (disables animations) setting.pixelate.name = Pixeloi[lightgray] (poistaa animaation käytöstä)
setting.minimap.name = Show Minimap setting.minimap.name = Näytä Minimappi
setting.position.name = Show Player Position setting.position.name = Näytä pelaajan sijainti
setting.musicvol.name = Music Volume setting.musicvol.name = Musiikin Äänenvoimakkuus
setting.ambientvol.name = Ambient Volume setting.ambientvol.name = Tausta Äänet
setting.mutemusic.name = Mute Music setting.mutemusic.name = Sulje Musiikki
setting.sfxvol.name = SFX Volume setting.sfxvol.name = SFX Volyymi
setting.mutesound.name = Mute Sound setting.mutesound.name = Sulje Äänet
setting.crashreport.name = Send Anonymous Crash Reports 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.publichost.name = Public Game Visibility
setting.chatopacity.name = Chat Opacity setting.chatopacity.name = Chatin Läpinäkymättömyys
setting.lasersopacity.name = Power Laser Opacity setting.lasersopacity.name = Energia Laaserin Läpinäkymattämyys
setting.playerchat.name = Display In-Game Chat 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.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. 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.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 setting.bloom.name = Bloom
keybind.title = Rebind Keys keybind.title = Rebind Keys
keybinds.mobile = [scarlet]Most keybinds here are not functional on mobile. Only basic movement is supported. keybinds.mobile = [scarlet]Most keybinds here are not functional on mobile. Only basic movement is supported.
category.general.name = General category.general.name = General
category.view.name = View category.view.name = View
category.multiplayer.name = Multiplayer category.multiplayer.name = Multiplayer
command.attack = Attack command.attack = Hyökkää
command.rally = Rally command.rally = Kutsu Koolle
command.retreat = Retreat command.retreat = Palaa
placement.blockselectkeys = \n[lightgray]Key: [{0}, placement.blockselectkeys = \n[lightgray]Key: [{0},
keybind.clear_building.name = Clear Building keybind.clear_building.name = Clear Building
keybind.press = Press a key... keybind.press = Press a key...
@@ -692,7 +692,7 @@ keybind.move_y.name = Move y
keybind.mouse_move.name = Follow Mouse keybind.mouse_move.name = Follow Mouse
keybind.dash.name = Dash keybind.dash.name = Dash
keybind.schematic_select.name = Select Region 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_x.name = Flip Schematic X
keybind.schematic_flip_y.name = Flip Schematic Y keybind.schematic_flip_y.name = Flip Schematic Y
keybind.category_prev.name = Previous Category 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_08.name = Category/Block Select 8
keybind.block_select_09.name = Category/Block Select 9 keybind.block_select_09.name = Category/Block Select 9
keybind.block_select_10.name = Category/Block Select 10 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.select.name = Select/Shoot
keybind.diagonal_placement.name = Diagonal Placement keybind.diagonal_placement.name = Diagonal Placement
keybind.pick.name = Pick Block keybind.pick.name = Pick Block
@@ -722,8 +722,8 @@ keybind.zoom.name = Zoom
keybind.menu.name = Menu keybind.menu.name = Menu
keybind.pause.name = Pause keybind.pause.name = Pause
keybind.pause_building.name = Pause/Resume Building keybind.pause_building.name = Pause/Resume Building
keybind.minimap.name = Minimap keybind.minimap.name = Minimappi
keybind.chat.name = Chat keybind.chat.name = Chatti
keybind.player_list.name = Player list keybind.player_list.name = Player list
keybind.console.name = Console keybind.console.name = Console
keybind.rotate.name = Rotate keybind.rotate.name = Rotate
@@ -736,20 +736,20 @@ keybind.drop_unit.name = Drop Unit
keybind.zoom_minimap.name = Zoom minimap keybind.zoom_minimap.name = Zoom minimap
mode.help.title = Description of modes mode.help.title = Description of modes
mode.survival.name = Survival 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.survival.description = Normaali moodi. Rajoitettu määrä resursseja ja tasoilla on aika.\n[gray]Vaatii vihollis spawneja kartassa.
mode.sandbox.name = Sandbox mode.sandbox.name = Hiekkalaatikko
mode.sandbox.description = Infinite resources and no timer for waves. mode.sandbox.description = Ikuisesti resursseja ja tasoilla ei ole aikaa.
mode.editor.name = Editor mode.editor.name = Editori
mode.pvp.name = PvP 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.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.name = Attack
mode.attack.description = Destroy the enemy's base. No waves.\n[gray]Requires a red core in the map to play. 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 mode.custom = Custom Rules
rules.infiniteresources = Infinite Resources rules.infiniteresources = Ikuisesti Resursseja
rules.reactorexplosions = Reactor Explosions rules.reactorexplosions = Reaktori Räjähdykset
rules.wavetimer = Wave Timer rules.wavetimer = Tasojen Aikaraja
rules.waves = Waves rules.waves = Tasot
rules.attack = Attack Mode rules.attack = Attack Mode
rules.enemyCheat = Infinite AI (Red Team) Resources rules.enemyCheat = Infinite AI (Red Team) Resources
rules.unitdrops = Unit Drops rules.unitdrops = Unit Drops
@@ -778,31 +778,31 @@ rules.title.experimental = Experimental
rules.lighting = Lighting rules.lighting = Lighting
rules.ambientlight = Ambient Light rules.ambientlight = Ambient Light
content.item.name = Items content.item.name = Tavarat
content.liquid.name = Liquids content.liquid.name = Nesteet
content.unit.name = Units content.unit.name = Yksiköt
content.block.name = Blocks content.block.name = Palikat
content.mech.name = Mechs content.mech.name = Yksikkö
item.copper.name = Copper item.copper.name = Kupari
item.lead.name = Lead item.lead.name = Lyijy
item.coal.name = Coal item.coal.name = Hiili
item.graphite.name = Graphite item.graphite.name = Grafiitti
item.titanium.name = Titanium item.titanium.name = Titaani
item.thorium.name = Thorium item.thorium.name = Torium
item.silicon.name = Silicon item.silicon.name = Pii
item.plastanium.name = Plastanium item.plastanium.name = Plastaniumi
item.phase-fabric.name = Phase Fabric item.phase-fabric.name = Kiihde Kuitu
item.surge-alloy.name = Surge Alloy item.surge-alloy.name = Taite Seos
item.spore-pod.name = Spore Pod item.spore-pod.name = Itiö Palko
item.sand.name = Hiekka item.sand.name = Hiekka
item.blast-compound.name = Blast Compound item.blast-compound.name = Räjähde Yhdiste
item.pyratite.name = Pyratite item.pyratite.name = Pyratiitti
item.metaglass.name = Metaglass item.metaglass.name = Metallilasi
item.scrap.name = Scrap item.scrap.name = Romu
liquid.water.name = Vesi liquid.water.name = Vesi
liquid.slag.name = Slag liquid.slag.name = Kuona
liquid.oil.name = Oil liquid.oil.name = Öljy
liquid.cryofluid.name = Cryofluid liquid.cryofluid.name = Kryoneste
mech.alpha-mech.name = Alpha mech.alpha-mech.name = Alpha
mech.alpha-mech.weapon = Heavy Repeater mech.alpha-mech.weapon = Heavy Repeater
mech.alpha-mech.ability = Regeneration mech.alpha-mech.ability = Regeneration
@@ -824,22 +824,22 @@ mech.trident-ship.name = Trident
mech.trident-ship.weapon = Bomb Bay mech.trident-ship.weapon = Bomb Bay
mech.glaive-ship.name = Glaive mech.glaive-ship.name = Glaive
mech.glaive-ship.weapon = Flame Repeater mech.glaive-ship.weapon = Flame Repeater
item.corestorable = [lightgray]Storable in Core: {0} item.corestorable = [lightgray]Säilöttävissä Ytimeen: {0}
item.explosiveness = [lightgray]Explosiveness: {0}% item.explosiveness = [lightgray]Räjädysmäisyys: {0}%
item.flammability = [lightgray]Flammability: {0}% item.flammability = [lightgray]Flammability: {0}%
item.radioactivity = [lightgray]Radioactivity: {0}% item.radioactivity = [lightgray]Radioactivity: {0}%
unit.health = [lightgray]Health: {0} unit.health = [lightgray]Elämäpisteet: {0}
unit.speed = [lightgray]Speed: {0} unit.speed = [lightgray]Nopeus: {0}
mech.weapon = [lightgray]Weapon: {0} mech.weapon = [lightgray]Ase: {0}
mech.health = [lightgray]Health: {0} mech.health = [lightgray]Elämäpisteet: {0}
mech.itemcapacity = [lightgray]Item Capacity: {0} mech.itemcapacity = [lightgray]Tavara Kapasiteetti: {0}
mech.minespeed = [lightgray]Mining Speed: {0}% mech.minespeed = [lightgray]Louhimis Nopeus: {0}%
mech.minepower = [lightgray]Mining Power: {0} mech.minepower = [lightgray]Louhimis Voima: {0}
mech.ability = [lightgray]Ability: {0} mech.ability = [lightgray]Spesiaalikyky: {0}
mech.buildspeed = [lightgray]Building Speed: {0}% mech.buildspeed = [lightgray]Rakennus Nopeus: {0}%
liquid.heatcapacity = [lightgray]Heat Capacity: {0} liquid.heatcapacity = [lightgray]Lämpö Kapasiteetti: {0}
liquid.viscosity = [lightgray]Viscosity: {0} liquid.viscosity = [lightgray]Tahmeus: {0}
liquid.temperature = [lightgray]Temperature: {0} liquid.temperature = [lightgray]Lämpö: {0}
block.sand-boulder.name = Sand Boulder block.sand-boulder.name = Sand Boulder
block.grass.name = Grass 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.scrap-wall-gigantic.name = Gigantic Scrap Wall
block.thruster.name = Thruster block.thruster.name = Thruster
block.kiln.name = Kiln block.kiln.name = Kiln
block.graphite-press.name = Graphite Press block.graphite-press.name = Grafiitti Puristin
block.multi-press.name = Multi-Press block.multi-press.name = Multi-Puristin
block.constructing = {0} [lightgray](Constructing) block.constructing = {0} [lightgray](Rakentamassa)
block.spawn.name = Enemy Spawn block.spawn.name = Vihollis Spawni
block.core-shard.name = Core: Shard block.core-shard.name = Ydin: Siru
block.core-foundation.name = Core: Foundation block.core-foundation.name = Ydin: Pohjaus
block.core-nucleus.name = Core: Nucleus block.core-nucleus.name = Ydin: Tuma
block.deepwater.name = Deep Water block.deepwater.name = Syvä Vesi
block.water.name = Water block.water.name = Vesi
block.tainted-water.name = Tainted Water block.tainted-water.name = Pilattu Vesi
block.darksand-tainted-water.name = Dark Sand Tainted Water block.darksand-tainted-water.name = Dark Sand Tainted Water
block.tar.name = Tar block.tar.name = Terva
block.stone.name = Stone block.stone.name = Kivi
block.sand.name = Sand block.sand.name = Hiekka
block.darksand.name = Dark Sand block.darksand.name = Tumma Hiekka
block.ice.name = Ice block.ice.name = Jää
block.snow.name = Snow block.snow.name = Lumi
block.craters.name = Craters block.craters.name = Kraatterit
block.sand-water.name = Sand water block.sand-water.name = Sand water
block.darksand-water.name = Dark Sand Water block.darksand-water.name = Dark Sand Water
block.char.name = Char block.char.name = Char

View File

@@ -40,7 +40,7 @@ schematic = Schematica
schematic.add = Salva Schematica... schematic.add = Salva Schematica...
schematics = Schematiche schematics = Schematiche
schematic.replace = Una schematica con questo nome esiste già. Sostituirla? schematic.replace = Una schematica con questo nome esiste già. Sostituirla?
schematic.import = Importa schematica... schematic.import = Importa schematica
schematic.exportfile = Esporta File schematic.exportfile = Esporta File
schematic.importfile = Importa File schematic.importfile = Importa File
schematic.browseworkshop = Naviga nel Workshop schematic.browseworkshop = Naviga nel Workshop
@@ -79,7 +79,7 @@ newgame = Nuova partita
none = <niente> none = <niente>
minimap = Minimappa minimap = Minimappa
position = Posizione position = Posizione
close = Chiuso close = Chiudi
website = Sito Web website = Sito Web
quit = Esci quit = Esci
save.quit = Salva ed Esci save.quit = Salva ed Esci
@@ -138,7 +138,7 @@ research.list = [lightgray]Ricerca:
research = Ricerca research = Ricerca
researched = [lightgray]{0} cercati. researched = [lightgray]{0} cercati.
players = {0} giocatori online players = {0} giocatori online
players.single = {0} giocatori online players.single = {0} giocatore online
server.closing = [accent]Chiusura server... server.closing = [accent]Chiusura server...
server.kicked.kick = Sei stato cacciato dal server! server.kicked.kick = Sei stato cacciato dal server!
server.kicked.whitelist = Non sei presente nella whitelist. 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.gameover = Game over!
server.kicked.serverRestarting = Il server si sta riavviando. server.kicked.serverRestarting = Il server si sta riavviando.
server.versions = Versione client:[accent] {0}[]\nVersione server:[accent] {1}[] 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. 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 hostserver = Ospita Server
invitefriends = Invita Amici invitefriends = Invita Amici
@@ -264,7 +264,7 @@ reloading = [accent]Ricaricamento delle mods...
saving = [accent]Salvataggio in corso... saving = [accent]Salvataggio in corso...
cancelbuilding = [accent][[{0}][] per pulire la selezione cancelbuilding = [accent][[{0}][] per pulire la selezione
selectschematic = [accent][[{0}][] per selezionare+copiare 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 resumebuilding = [scarlet][[{0}][] per riprendere a costruire
wave = [accent]Ondata {0} wave = [accent]Ondata {0}
wave.waiting = [lightgray]Ondata tra {0} wave.waiting = [lightgray]Ondata tra {0}
@@ -532,6 +532,8 @@ error.crashtitle = Si è verificato un errore
blocks.input = Ingresso blocks.input = Ingresso
blocks.output = Uscita blocks.output = Uscita
blocks.booster = Potenziamenti blocks.booster = Potenziamenti
blocks.tiles = Blocchi Richiesti
blocks.affinities = Affinità
block.unknown = [lightgray]??? block.unknown = [lightgray]???
blocks.powercapacity = Capacità Energetica blocks.powercapacity = Capacità Energetica
blocks.powershot = Danno/Colpo blocks.powershot = Danno/Colpo
@@ -934,7 +936,6 @@ block.lancer.name = Lanciere
block.conveyor.name = Nastro Trasportatore block.conveyor.name = Nastro Trasportatore
block.titanium-conveyor.name = Nastro Avanzato block.titanium-conveyor.name = Nastro Avanzato
block.armored-conveyor.name = Nastro Corazzato 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.junction.name = Incrocio
block.router.name = Distributore block.router.name = Distributore
block.distributor.name = Distributore Grande 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.pulverizer.description = Polverizza la pietra.\nUtile quando manca la sabbia naturale.
block.coal-centrifuge.description = Solidifica il petrolio in pezzi di carbone. block.coal-centrifuge.description = Solidifica il petrolio in pezzi di carbone.
block.incinerator.description = Elimina qualsiasi oggetto o liquido in eccesso. 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-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.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-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.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-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.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.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. 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.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.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.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.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.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.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.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.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.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.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.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.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 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.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.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. 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.

View File

@@ -251,6 +251,7 @@ copylink = Скопіювати посилання
back = Назад back = Назад
data.export = Вивантажити дані data.export = Вивантажити дані
data.import = Завантажити дані data.import = Завантажити дані
data.openfolder = Відкрити теку з даними
data.exported = Дані вивантажено. data.exported = Дані вивантажено.
data.invalid = Це не дійсні ігрові дані. data.invalid = Це не дійсні ігрові дані.
data.import.confirm = Вивантаження зовнішніх даних перезапише[scarlet] ВСІ[] ваші поточні ігрові дані.\n[accent]Це неможливо скасувати![]\n\nЩойно дані імпортуються, гра негайно закриється. data.import.confirm = Вивантаження зовнішніх даних перезапише[scarlet] ВСІ[] ваші поточні ігрові дані.\n[accent]Це неможливо скасувати![]\n\nЩойно дані імпортуються, гра негайно закриється.
@@ -587,7 +588,7 @@ bullet.splashdamage = [stat]{0}[lightgray] шкода по ділянці ~[stat
bullet.incendiary = [stat]запальний bullet.incendiary = [stat]запальний
bullet.homing = [stat]самонаведення bullet.homing = [stat]самонаведення
bullet.shock = [stat]шок bullet.shock = [stat]шок
bullet.frag = [stat]осколкова граната bullet.frag = [stat]шкода по ділянці
bullet.knockback = [stat]{0}[lightgray] відкидання bullet.knockback = [stat]{0}[lightgray] відкидання
bullet.freezing = [stat]заморожування bullet.freezing = [stat]заморожування
bullet.tarred = [stat]дьогтьовий bullet.tarred = [stat]дьогтьовий
@@ -667,6 +668,7 @@ setting.savecreate.name = Автоматичне створення збереж
setting.publichost.name = Загальнодоступність гри setting.publichost.name = Загальнодоступність гри
setting.chatopacity.name = Непрозорість чату setting.chatopacity.name = Непрозорість чату
setting.lasersopacity.name = Непрозорість лазерів енергопостачання setting.lasersopacity.name = Непрозорість лазерів енергопостачання
setting.bridgeopacity.name = Місткість мостів
setting.playerchat.name = Відображати хмару чата над гравцями setting.playerchat.name = Відображати хмару чата над гравцями
public.confirm = Ви хочете зробити цю гру загальнодоступною?\n[lightgray]Це можна змінити у Налаштування→Гра→Загальнодоступність гри public.confirm = Ви хочете зробити цю гру загальнодоступною?\n[lightgray]Це можна змінити у Налаштування→Гра→Загальнодоступність гри
public.beta = Зауважте, що в бета-версії гри ви не можете робити публічні ігри. public.beta = Зауважте, що в бета-версії гри ви не можете робити публічні ігри.
@@ -1033,7 +1035,7 @@ block.force-projector.name = Силовий проектор
block.arc.name = Дуга block.arc.name = Дуга
block.rtg-generator.name = Радіоізотопний термоелектричний генератор block.rtg-generator.name = Радіоізотопний термоелектричний генератор
block.spectre.name = Спектр block.spectre.name = Спектр
block.meltdown.name = Випалювач block.meltdown.name = Розплавитель
block.container.name = Склад block.container.name = Склад
block.launch-pad.name = Стартовий майданчик block.launch-pad.name = Стартовий майданчик
block.launch-pad-large.name = Великий стартовий майданчик block.launch-pad-large.name = Великий стартовий майданчик
@@ -1056,7 +1058,7 @@ unit.fortress.name = Фортеця
unit.revenant.name = Потойбічний вбивця unit.revenant.name = Потойбічний вбивця
unit.eruptor.name = Вивиргатель unit.eruptor.name = Вивиргатель
unit.chaos-array.name = Масив хаосу unit.chaos-array.name = Масив хаосу
unit.eradicator.name = Випалювач unit.eradicator.name = Викорінювач
unit.lich.name = Лич unit.lich.name = Лич
unit.reaper.name = Жнець unit.reaper.name = Жнець
tutorial.next = [lightgray]<Натисніть для продовження> tutorial.next = [lightgray]<Натисніть для продовження>
@@ -1198,7 +1200,7 @@ block.rtg-generator.description = Простий, надійний генера
block.solar-panel.description = Забезпечує невелику кількість енергії від сонця. block.solar-panel.description = Забезпечує невелику кількість енергії від сонця.
block.solar-panel-large.description = Значно ефективніша версія стандартної сонячної панелі. block.solar-panel-large.description = Значно ефективніша версія стандартної сонячної панелі.
block.thorium-reactor.description = Виробляє значну кількість енергії з торію. Вимагає постійного охолодження. Вибухне сильно, якщо подаватиметься недостатньо кількості теплоносія. Вихідна потужність залежить від повноти, базова потужність генерується на повній потужності. block.thorium-reactor.description = Виробляє значну кількість енергії з торію. Вимагає постійного охолодження. Вибухне сильно, якщо подаватиметься недостатньо кількості теплоносія. Вихідна потужність залежить від повноти, базова потужність генерується на повній потужності.
block.impact-reactor.description = Удосконалений генератор, здатний створювати величезну кількість енергії при максимальній ефективності. Для швидкого запуску процесу потрібно значне введення енергії. block.impact-reactor.description = Удосконалений генератор, здатний створювати величезну кількість енергії при максимальній ефективності. Для запуску процесу потрібно значні обсяги енергії.
block.mechanical-drill.description = Недорогий бур. Розміщуючи їх на відповідних плитках, виводить предмети повільним темпом нескінченно. Здатний видобувати лише мідь, свинець і вугілля. block.mechanical-drill.description = Недорогий бур. Розміщуючи їх на відповідних плитках, виводить предмети повільним темпом нескінченно. Здатний видобувати лише мідь, свинець і вугілля.
block.pneumatic-drill.description = Вдосконалений бур, здатний добувати титан. Шахти швидше, ніж механічна дриль. block.pneumatic-drill.description = Вдосконалений бур, здатний добувати титан. Шахти швидше, ніж механічна дриль.
block.laser-drill.description = Дозволяє виконувати свердління ще швидше за допомогою лазерної технології, але вимагає енергії. Здатний до видобутку торію. block.laser-drill.description = Дозволяє виконувати свердління ще швидше за допомогою лазерної технології, але вимагає енергії. Здатний до видобутку торію.

View File

@@ -1,4 +1,4 @@
apply plugin: "java" apply plugin: "java"
sourceCompatibility = 1.8 sourceCompatibility = 1.8
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8' [compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
sourceSets.main.java.srcDirs = ["src/"] sourceSets.main.java.srcDirs = ["src/", "$buildDir/generated/sources/annotationProcessor/java/main"]

View File

@@ -103,9 +103,10 @@ public class UnitTypes implements ContentList{
shootSound = Sounds.explosion; shootSound = Sounds.explosion;
bullet = new BombBulletType(2f, 3f, "clear"){{ bullet = new BombBulletType(2f, 3f, "clear"){{
hitEffect = Fx.pulverize; hitEffect = Fx.pulverize;
lifetime = 2f; lifetime = 30f;
speed = 1.1f; speed = 1.1f;
splashDamageRadius = 55f; splashDamageRadius = 55f;
instantDisappear = true;
splashDamage = 30f; splashDamage = 30f;
killShooter = true; killShooter = true;
}}; }};
@@ -126,7 +127,6 @@ public class UnitTypes implements ContentList{
shootSound = Sounds.flame; shootSound = Sounds.flame;
length = 1f; length = 1f;
reload = 14f; reload = 14f;
range = 30f;
alternate = true; alternate = true;
recoil = 1f; recoil = 1f;
ejectEffect = Fx.none; ejectEffect = Fx.none;

View File

@@ -266,6 +266,11 @@ public class NetClient implements ApplicationListener{
ui.showText("", message); ui.showText("", message);
} }
@Remote(variants = Variant.both)
public static void onInfoToast(String message, float duration){
ui.showInfoToast(message, duration);
}
@Remote(variants = Variant.both) @Remote(variants = Variant.both)
public static void onSetRules(Rules rules){ public static void onSetRules(Rules rules){
state.rules = rules; state.rules = rules;

View File

@@ -264,7 +264,7 @@ public class NetServer implements ApplicationListener{
page --; 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]."); player.sendMessage("[scarlet]'page' must be a number between[orange] 1[] and[orange] " + pages + "[scarlet].");
return; return;
} }
@@ -472,7 +472,7 @@ public class NetServer implements ApplicationListener{
Call.onPlayerDisconnect(player.id); 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(); player.remove();
@@ -620,8 +620,10 @@ public class NetServer implements ApplicationListener{
player.add(); player.add();
player.con.hasConnected = true; player.con.hasConnected = true;
if(Config.showConnectMessages.bool()) Call.sendMessage("[accent]" + player.name + "[accent] has connected."); if(Config.showConnectMessages.bool()){
Log.info("&lm[{1}] &y{0} has connected. ", player.name, player.uuid); 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")){ if(!Config.motd.string().equalsIgnoreCase("off")){
player.sendMessage(Config.motd.string()); player.sendMessage(Config.motd.string());

View File

@@ -289,6 +289,19 @@ public class UI implements ApplicationListener, Loadable{
Core.scene.add(table); 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){ public void showInfo(String info){
new Dialog(""){{ new Dialog(""){{
getCell(cont).growX(); getCell(cont).growX();
@@ -426,7 +439,6 @@ public class UI implements ApplicationListener, Loadable{
dialog.show(); dialog.show();
} }
public void showCustomConfirm(String title, String text, String yes, String no, Runnable confirmed, Runnable denied){ public void showCustomConfirm(String title, String text, String yes, String no, Runnable confirmed, Runnable denied){
FloatingDialog dialog = new FloatingDialog(title); FloatingDialog dialog = new FloatingDialog(title);
dialog.cont.add(text).width(mobile ? 400f : 500f).wrap().pad(4f).get().setAlignment(Align.center, Align.center); 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){ public String formatAmount(int number){
if(number >= 1000000){ 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){ }else if(number >= 10000){
return number / 1000 + "[gray]k[]"; return number / 1000 + "[gray]" + Core.bundle.get("unit.thousands") + "[]";
}else if(number >= 1000){ }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{ }else{
return number + ""; return number + "";
} }

View File

@@ -1,6 +1,7 @@
package mindustry.ctype; package mindustry.ctype;
import arc.*; import arc.*;
import arc.util.ArcAnnotate.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import arc.graphics.g2d.*; import arc.graphics.g2d.*;
import arc.scene.ui.layout.*; 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. */ /** Localized, formal name. Never null. Set to block name if not found in bundle. */
public String localizedName; public String localizedName;
/** Localized description. May be null. */ /** Localized description. May be null. */
public String description; public @Nullable String description;
/** Icons by Cicon ID.*/ /** Icons by Cicon ID.*/
protected TextureRegion[] cicons = new TextureRegion[mindustry.ui.Cicon.all.length]; 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"); 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.*/ /** Generate any special icons for this content. Called asynchronously.*/
@CallSuper @CallSuper
public void createIcons(MultiPacker packer){ public void createIcons(MultiPacker packer){

View File

@@ -3,8 +3,7 @@ package mindustry.entities.bullet;
import arc.audio.*; import arc.audio.*;
import arc.math.*; import arc.math.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.ctype.Content; import mindustry.ctype.*;
import mindustry.ctype.ContentType;
import mindustry.entities.*; import mindustry.entities.*;
import mindustry.entities.Effects.*; import mindustry.entities.Effects.*;
import mindustry.entities.effect.*; import mindustry.entities.effect.*;
@@ -41,7 +40,9 @@ public abstract class BulletType extends Content{
public float recoil; public float recoil;
/** Whether to kill the shooter when this is shot. For suicide bombers. */ /** Whether to kill the shooter when this is shot. For suicide bombers. */
public boolean killShooter; public boolean killShooter;
/** Whether to instantly make the bullet disappear. */
public boolean instantDisappear;
/** Damage dealt in splash. 0 to disable.*/
public float splashDamage = 0f; public float splashDamage = 0f;
/** Knockback in velocity. */ /** Knockback in velocity. */
public float knockback; public float knockback;
@@ -151,6 +152,10 @@ public abstract class BulletType extends Content{
if(killShooter && b.getOwner() instanceof HealthTrait){ if(killShooter && b.getOwner() instanceof HealthTrait){
((HealthTrait)b.getOwner()).kill(); ((HealthTrait)b.getOwner()).kill();
} }
if(instantDisappear){
b.time(lifetime);
}
} }
public void update(Bullet b){ public void update(Bullet b){

View File

@@ -42,7 +42,6 @@ public class GroundUnit extends BaseUnit{
moveToCore(PathTarget.enemyCores); moveToCore(PathTarget.enemyCores);
} }
}else{ }else{
float dst = dst(core); float dst = dst(core);
if(dst < getWeapon().bullet.range() / 1.1f){ if(dst < getWeapon().bullet.range() / 1.1f){
@@ -170,6 +169,7 @@ public class GroundUnit extends BaseUnit{
if(!Units.invalidateTarget(target, this)){ if(!Units.invalidateTarget(target, this)){
if(dst(target) < getWeapon().bullet.range()){ if(dst(target) < getWeapon().bullet.range()){
rotate(angleTo(target)); rotate(angleTo(target));
if(Angles.near(angleTo(target), rotation, 13f)){ if(Angles.near(angleTo(target), rotation, 13f)){

View File

@@ -43,6 +43,10 @@ public class Drawf{
} }
public static void arrow(float x, float y, float x2, float y2, float length, float radius){ 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 angle = Angles.angle(x, y, x2, y2);
float space = 2f; float space = 2f;
Tmp.v1.set(x2, y2).sub(x, y).limit(length); Tmp.v1.set(x2, y2).sub(x, y).limit(length);
@@ -50,7 +54,7 @@ public class Drawf{
Draw.color(Pal.gray); Draw.color(Pal.gray);
Fill.poly(vx, vy, 3, radius + space, angle); Fill.poly(vx, vy, 3, radius + space, angle);
Draw.color(Pal.accent); Draw.color(color);
Fill.poly(vx, vy, 3, radius, angle); Fill.poly(vx, vy, 3, radius, angle);
Draw.color(); Draw.color();
} }

View File

@@ -12,7 +12,7 @@ import org.mozilla.javascript.*;
public class Scripts implements Disposable{ public class Scripts implements Disposable{
private final Array<String> blacklist = Array.with("net", "files", "reflect", "javax", "rhino", "file", "channels", "jdk", private final Array<String> 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", "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<String> whitelist = Array.with("mindustry.net"); private final Array<String> whitelist = Array.with("mindustry.net");
private final Context context; private final Context context;
private final String wrapper; private final String wrapper;

View File

@@ -28,7 +28,7 @@ public class ContentDisplay{
table.row(); table.row();
if(block.description != null){ 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.row();
table.addImage().height(3).color(Color.lightGray).pad(8).padLeft(0).padRight(0).fillX(); table.addImage().height(3).color(Color.lightGray).pad(8).padLeft(0).padRight(0).fillX();
@@ -76,7 +76,7 @@ public class ContentDisplay{
table.row(); table.row();
if(item.description != null){ 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.row();
table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX(); table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX();
@@ -110,7 +110,7 @@ public class ContentDisplay{
table.row(); table.row();
if(liquid.description != null){ 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.row();
table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX(); table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX();
@@ -145,7 +145,7 @@ public class ContentDisplay{
table.row(); table.row();
if(mech.description != null){ 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.row();
table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX(); table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX();
@@ -192,7 +192,7 @@ public class ContentDisplay{
table.row(); table.row();
if(unit.description != null){ 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.row();
table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX(); table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX();

View File

@@ -377,7 +377,7 @@ public class TechTreeDialog extends FloatingDialog{
infoTable.row(); infoTable.row();
if(node.block.description != null){ 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); addChild(infoTable);

View File

@@ -171,7 +171,7 @@ public class MenuFragment extends Fragment{
new Buttoni("$loadgame", Icon.download, () -> checkPlay(ui.load::show)), new Buttoni("$loadgame", Icon.download, () -> checkPlay(ui.load::show)),
new Buttoni("$tutorial", Icon.info, () -> checkPlay(control::playTutorial)) 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), new Buttoni(Core.bundle.get("mods"), Icon.bookOpen, ui.mods::show),
//not enough space for this button //not enough space for this button
//new Buttoni("$schematics", Icon.paste, ui.schematics::show), //new Buttoni("$schematics", Icon.paste, ui.schematics::show),

View File

@@ -192,6 +192,11 @@ public class MassDriver extends Block{
MassDriverEntity entity = tile.ent(); 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)){ if(linkValid(tile)){
Tile target = world.tile(entity.link); Tile target = world.tile(entity.link);
Drawf.circles(target.drawx(), target.drawy(), (target.block().size / 2f + 1) * tilesize + sin - 2f, Pal.place); Drawf.circles(target.drawx(), target.drawy(), (target.block().size / 2f + 1) * tilesize + sin - 2f, Pal.place);

View File

@@ -182,8 +182,11 @@ public class PowerNode extends PowerBlock{
if(tile == other){ if(tile == other){
if(other.entity.power.links.size == 0){ if(other.entity.power.links.size == 0){
int[] total = {0};
getPotentialLinks(tile, link -> { getPotentialLinks(tile, link -> {
if(!insulated(tile, link)) tile.configure(link.pos()); if(!insulated(tile, link) && total[0]++ < maxNodes){
tile.configure(link.pos());
}
}); });
}else{ }else{
while(entity.power.links.size > 0){ while(entity.power.links.size > 0){

View File

@@ -134,8 +134,6 @@ public class GenericCrafter extends Block{
return outputItem != null; return outputItem != null;
} }
@Override @Override
public boolean shouldConsume(Tile tile){ public boolean shouldConsume(Tile tile){
if(outputItem != null && tile.entity.items.get(outputItem.item) >= itemCapacity){ if(outputItem != null && tile.entity.items.get(outputItem.item) >= itemCapacity){

View File

@@ -5,6 +5,7 @@ import arc.graphics.g2d.Draw;
import arc.graphics.g2d.TextureRegion; import arc.graphics.g2d.TextureRegion;
import arc.math.Mathf; import arc.math.Mathf;
import arc.util.*; import arc.util.*;
import arc.util.ArcAnnotate.*;
import mindustry.content.Fx; import mindustry.content.Fx;
import mindustry.content.Liquids; import mindustry.content.Liquids;
import mindustry.entities.Effects; import mindustry.entities.Effects;
@@ -26,7 +27,7 @@ public class SolidPump extends Pump{
public float updateEffectChance = 0.02f; public float updateEffectChance = 0.02f;
public float rotateSpeed = 1f; public float rotateSpeed = 1f;
/** Attribute that is checked when calculating output. */ /** Attribute that is checked when calculating output. */
public Attribute attribute; public @Nullable Attribute attribute;
public SolidPump(String name){ public SolidPump(String name){
super(name); super(name);
@@ -64,7 +65,9 @@ public class SolidPump extends Pump{
stats.remove(BlockStat.output); stats.remove(BlockStat.output);
stats.add(BlockStat.output, result, 60f * pumpAmount, true); stats.add(BlockStat.output, result, 60f * pumpAmount, true);
stats.add(BlockStat.affinities, attribute); if(attribute != null){
stats.add(BlockStat.affinities, attribute);
}
} }
@Override @Override

View File

@@ -66,8 +66,10 @@ public class CommandCenter extends Block{
public void load(){ public void load(){
super.load(); super.load();
for(UnitCommand cmd : UnitCommand.all){ if(ui != null){
commandRegions[cmd.ordinal()] = ui.getIcon("command" + Strings.capitalize(cmd.name())); for(UnitCommand cmd : UnitCommand.all){
commandRegions[cmd.ordinal()] = ui.getIcon("command" + Strings.capitalize(cmd.name()));
}
} }
} }

View File

@@ -102,6 +102,7 @@ public class LiquidModule extends BlockModule{
@Override @Override
public void read(DataInput stream) throws IOException{ public void read(DataInput stream) throws IOException{
Arrays.fill(liquids, 0); Arrays.fill(liquids, 0);
total = 0f;
byte count = stream.readByte(); byte count = stream.readByte();
for(int j = 0; j < count; j++){ for(int j = 0; j < count; j++){

View File

@@ -283,7 +283,7 @@ public class SStats implements SteamUserStatsCallback{
if(result != SteamResult.OK){ if(result != SteamResult.OK){
Log.err("Failed to recieve steam stats: {0}", result); Log.err("Failed to recieve steam stats: {0}", result);
}else{ }else{
Log.err("Recieved steam stats."); Log.info("Recieved steam stats.");
} }
} }

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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ů

View File

@@ -0,0 +1 @@
Hra typu tower-defense s otevřeným koncem, zaměřená na řízení zdrojů.

View File

@@ -0,0 +1 @@
Hra typu tower-defense s otevřeným koncem, zaměřená na řízení zdrojů.

View File

@@ -0,0 +1 @@
Mindustry

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -0,0 +1 @@
Um jogo de defesa de torre de sandbox baseado em construção.

View File

@@ -0,0 +1 @@
Um jogo de defesa de torre de sandbox baseado em construção.

View File

@@ -0,0 +1 @@
Mindustry

View File

@@ -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."
}
}

View File

@@ -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]

View File

@@ -0,0 +1 @@
Hra typu tower-defense s otevřeným koncem, zaměřená na řízení zdrojů.

View File

@@ -5,7 +5,7 @@ Crie correntes de suprimentos elaboradas com correias transportadoras para alime
[h2]Gameplay[/h2] [h2]Gameplay[/h2]
[list] [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. [*] 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. [*] Construa drones para minerar recursos automaticamente, ajudar na construção e proteger a sua base.
[*] Distribua líquidos e enfrente surtos de fogo. [*] Distribua líquidos e enfrente surtos de fogo.

View File

@@ -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."
}
}

View File

@@ -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]

View File

@@ -0,0 +1 @@
Um jogo de fim aberto de tower-defense com um foco em gerenciamento de recursos.

View File

@@ -829,7 +829,6 @@ public class ServerControl implements ApplicationListener{
}); });
mods.eachClass(p -> p.registerServerCommands(handler)); mods.eachClass(p -> p.registerServerCommands(handler));
mods.eachClass(p -> p.registerClientCommands(netServer.clientCommands));
} }
private void readCommands(){ private void readCommands(){