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());
//new external folder
Fi data = Core.files.absolute(getContext().getExternalFilesDir(null).getAbsolutePath());
Core.settings.setDataDirectory(data);
//moved to internal storage if there's no file indicating that it moved
//delete old external files due to screwup
if(Core.files.local("files_moved").exists() && !Core.files.local("files_moved_103").exists()){
for(Fi fi : data.list()){
fi.deleteDirectory();
}
Core.files.local("files_moved").delete();
Core.files.local("files_moved_103").writeString("files moved again");
}
//move to internal storage if there's no file indicating that it moved
if(!Core.files.local("files_moved").exists()){
Log.info("Moving files to external storage...");
@@ -161,7 +173,7 @@ public class AndroidLauncher extends AndroidApplication{
//current local storage folder
Fi src = Core.files.absolute(Core.files.getLocalStoragePath());
for(Fi fi : src.list()){
fi.copyTo(data.child(fi.name()));
fi.copyTo(data);
}
//create marker
Core.files.local("files_moved").writeString("files moved to " + data);
@@ -170,8 +182,6 @@ public class AndroidLauncher extends AndroidApplication{
Log.err("Failed to move files!");
t.printStackTrace();
}
}else{
Core.settings.setDataDirectory(data);
}
}

View File

@@ -3,6 +3,7 @@ package mindustry.annotations;
import javax.annotation.processing.*;
import javax.lang.model.*;
import javax.lang.model.element.*;
import javax.lang.model.util.*;
import java.util.*;
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@@ -10,20 +11,34 @@ public abstract class BaseProcessor extends AbstractProcessor{
/** Name of the base package to put all the generated classes. */
public static final String packageName = "mindustry.gen";
private int round;
public static Types typeu;
public static Elements elementu;
public static Filer filer;
public static Messager messager;
protected int round;
public static String getMethodName(Element element){
return ((TypeElement)element.getEnclosingElement()).getQualifiedName().toString() + "." + element.getSimpleName();
}
public static boolean isPrimitive(String type){
return type.equals("boolean") || type.equals("byte") || type.equals("short") || type.equals("int")
|| type.equals("long") || type.equals("float") || type.equals("double") || type.equals("char");
}
@Override
public synchronized void init(ProcessingEnvironment processingEnv){
super.init(processingEnv);
//put all relevant utils into utils class
Utils.typeUtils = processingEnv.getTypeUtils();
Utils.elementUtils = processingEnv.getElementUtils();
Utils.filer = processingEnv.getFiler();
Utils.messager = processingEnv.getMessager();
typeu = processingEnv.getTypeUtils();
elementu = processingEnv.getElementUtils();
filer = processingEnv.getFiler();
messager = processingEnv.getMessager();
}
@Override
public final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
if(round++ != 0) return false; //only process 1 round
try{
process(roundEnv);
@@ -39,5 +54,7 @@ public abstract class BaseProcessor extends AbstractProcessor{
return SourceVersion.RELEASE_8;
}
public abstract void process(RoundEnvironment env) throws Exception;
public void process(RoundEnvironment env) throws Exception{
}
}

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

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

View File

@@ -1,11 +1,11 @@
package mindustry.annotations;
package mindustry.annotations.impl;
import com.squareup.javapoet.*;
import mindustry.annotations.*;
import mindustry.annotations.Annotations.Struct;
import mindustry.annotations.Annotations.StructField;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*;
import javax.lang.model.type.TypeKind;
import javax.lang.model.util.ElementFilter;
@@ -29,7 +29,7 @@ public class StructAnnotationProcessor extends BaseProcessor{
for(TypeElement elem : elements){
if(!elem.getSimpleName().toString().endsWith("Struct")){
Utils.messager.printMessage(Kind.ERROR, "All classes annotated with @Struct must have their class names end in 'Struct'.", elem);
BaseProcessor.messager.printMessage(Kind.ERROR, "All classes annotated with @Struct must have their class names end in 'Struct'.", elem);
continue;
}
@@ -45,7 +45,7 @@ public class StructAnnotationProcessor extends BaseProcessor{
int structTotalSize = (structSize <= 8 ? 8 : structSize <= 16 ? 16 : structSize <= 32 ? 32 : 64);
if(variables.size() == 0){
Utils.messager.printMessage(Kind.ERROR, "making a struct with no fields is utterly pointles.", elem);
BaseProcessor.messager.printMessage(Kind.ERROR, "making a struct with no fields is utterly pointles.", elem);
continue;
}
@@ -130,10 +130,10 @@ public class StructAnnotationProcessor extends BaseProcessor{
constructor.addStatement("return ($T)($L)", structType, cons.toString().substring(3));
classBuilder.addMethod(constructor.build());
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(Utils.filer);
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(BaseProcessor.filer);
}catch(IllegalArgumentException e){
e.printStackTrace();
Utils.messager.printMessage(Kind.ERROR, e.getMessage(), elem);
BaseProcessor.messager.printMessage(Kind.ERROR, e.getMessage(), elem);
}
}

View File

@@ -1,4 +1,4 @@
package mindustry.annotations;
package mindustry.annotations.remote;
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.WriteClass;
@@ -11,8 +12,8 @@ import java.util.HashMap;
import java.util.Set;
/**
* This class finds reader and writer methods annotated by the {@link Annotations.WriteClass}
* and {@link Annotations.ReadClass} annotations.
* This class finds reader and writer methods annotated by the {@link WriteClass}
* and {@link ReadClass} annotations.
*/
public class IOFinder{
@@ -34,21 +35,21 @@ public class IOFinder{
//make sure there's only one read method
if(readers.stream().filter(elem -> getValue(elem.getAnnotation(ReadClass.class)).equals(typeName)).count() > 1){
Utils.messager.printMessage(Kind.ERROR, "Multiple writer methods for type '" + typeName + "'", writer);
BaseProcessor.messager.printMessage(Kind.ERROR, "Multiple writer methods for type '" + typeName + "'", writer);
}
//make sure there's only one write method
long count = readers.stream().filter(elem -> getValue(elem.getAnnotation(ReadClass.class)).equals(typeName)).count();
if(count == 0){
Utils.messager.printMessage(Kind.ERROR, "Writer method does not have an accompanying reader: ", writer);
BaseProcessor.messager.printMessage(Kind.ERROR, "Writer method does not have an accompanying reader: ", writer);
}else if(count > 1){
Utils.messager.printMessage(Kind.ERROR, "Writer method has multiple reader for type: ", writer);
BaseProcessor.messager.printMessage(Kind.ERROR, "Writer method has multiple reader for type: ", writer);
}
Element reader = readers.stream().filter(elem -> getValue(elem.getAnnotation(ReadClass.class)).equals(typeName)).findFirst().get();
//add to result list
result.put(typeName, new ClassSerializer(Utils.getMethodName(reader), Utils.getMethodName(writer), typeName));
result.put(typeName, new ClassSerializer(BaseProcessor.getMethodName(reader), BaseProcessor.getMethodName(writer), typeName));
}
return result;

View File

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

View File

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

View File

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

View File

@@ -1,8 +1,9 @@
package mindustry.annotations;
package mindustry.annotations.remote;
import com.squareup.javapoet.*;
import mindustry.annotations.*;
import mindustry.annotations.Annotations.Loc;
import mindustry.annotations.IOFinder.ClassSerializer;
import mindustry.annotations.remote.IOFinder.ClassSerializer;
import javax.lang.model.element.*;
import javax.tools.Diagnostic.Kind;
@@ -52,7 +53,7 @@ public class RemoteWriteGenerator{
//build and write resulting class
TypeSpec spec = classBuilder.build();
JavaFile.builder(packageName, spec).build().writeTo(Utils.filer);
JavaFile.builder(packageName, spec).build().writeTo(BaseProcessor.filer);
}
}
@@ -73,12 +74,12 @@ public class RemoteWriteGenerator{
//validate client methods to make sure
if(methodEntry.where.isClient){
if(elem.getParameters().isEmpty()){
Utils.messager.printMessage(Kind.ERROR, "Client invoke methods must have a first parameter of type Player.", elem);
BaseProcessor.messager.printMessage(Kind.ERROR, "Client invoke methods must have a first parameter of type Player.", elem);
return;
}
if(!elem.getParameters().get(0).asType().toString().equals("mindustry.entities.type.Player")){
Utils.messager.printMessage(Kind.ERROR, "Client invoke methods should have a first parameter of type Player.", elem);
BaseProcessor.messager.printMessage(Kind.ERROR, "Client invoke methods should have a first parameter of type Player.", elem);
return;
}
}
@@ -162,7 +163,7 @@ public class RemoteWriteGenerator{
method.beginControlFlow("if(mindustry.Vars.net.server())");
}
if(Utils.isPrimitive(typeName)){ //check if it's a primitive, and if so write it
if(BaseProcessor.isPrimitive(typeName)){ //check if it's a primitive, and if so write it
if(typeName.equals("boolean")){ //booleans are special
method.addStatement("TEMP_BUFFER.put(" + varName + " ? (byte)1 : 0)");
}else{
@@ -174,7 +175,7 @@ public class RemoteWriteGenerator{
ClassSerializer ser = serializers.get(typeName);
if(ser == null){ //make sure a serializer exists!
Utils.messager.printMessage(Kind.ERROR, "No @WriteClass method to write class type: '" + typeName + "'", var);
BaseProcessor.messager.printMessage(Kind.ERROR, "No @WriteClass method to write class type: '" + typeName + "'", var);
return;
}

View File

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

View File

@@ -1,6 +1,10 @@
buildscript{
ext{
arcExtVersion = "e287fdce0449a87fb15599c67b5167ac0273bcb6"
getArcHash = {
return new Properties().with{ p -> p.load(file('gradle.properties').newReader()); return p }["archash"]
}
arcHash = getArcHash()
}
repositories{
@@ -15,8 +19,8 @@ buildscript{
dependencies{
classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.8'
classpath "com.github.anuken:packr:-SNAPSHOT"
classpath "com.github.Anuken.Arc:packer:$arcExtVersion"
classpath "com.github.Anuken.Arc:arc-core:$arcExtVersion"
classpath "com.github.Anuken.Arc:packer:$arcHash"
classpath "com.github.Anuken.Arc:arc-core:$arcHash"
}
}
@@ -33,7 +37,6 @@ allprojects{
gdxVersion = '1.9.10'
roboVMVersion = '2.3.8'
steamworksVersion = '891ed912791e01fe9ee6237a6497e5212b85c256'
arcHash = null
loadVersionProps = {
return new Properties().with{p -> p.load(file('../core/assets/version.properties').newReader()); return p }
@@ -47,10 +50,6 @@ allprojects{
return !project.hasProperty("release") && new File(projectDir.parent, '../Arc').exists()
}
getArcHash = {
return new Properties().with{ p -> p.load(file('gradle.properties').newReader()); return p }["archash"]
}
arcModule = { String name ->
if(localArc()){
return project(":Arc:$name")
@@ -133,6 +132,19 @@ allprojects{
props.store(pfile.newWriter(), "Autogenerated file. Do not modify.")
}
}
writeProcessors = {
def processorFile = new File(rootDir, "annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor")
def text = new StringBuilder()
def files = new File(rootDir, "annotations/src/main/java")
files.eachFileRecurse(groovy.io.FileType.FILES){ file ->
if(file.name.endsWith(".java") && (file.text.contains(" extends BaseProcessor") || (file.text.contains(" extends AbstractProcessor") && !file.text.contains("abstract class")))){
text.append(file.path.substring(files.path.length() + 1)).append("\n")
}
}
processorFile.text = text.toString().replace(".java", "").replace("/", ".").replace("\\", ".")
}
}
repositories{
@@ -206,6 +218,7 @@ project(":core"){
outputs.upToDateWhen{ false }
generateLocales()
writeVersion()
writeProcessors()
}
task copyChangelog{
@@ -230,31 +243,6 @@ project(":core"){
}
dependencies{
if(System.properties["user.name"] == "anuke"){
task cleanGen{
doFirst{
delete{
delete "../core/src/mindustry/gen/"
}
}
}
task copyGen{
doLast{
copy{
from("../core/build/generated/sources/annotationProcessor/java/main/mindustry/gen"){
include "**/*.java"
}
into "../core/src/mindustry/gen"
}
}
}
compileJava.dependsOn(cleanGen)
compileJava.finalizedBy(copyGen)
}
compileJava.dependsOn(preGen)
compile "org.lz4:lz4-java:1.4.1"
@@ -303,7 +291,7 @@ project(":tools"){
compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop"
compile "org.reflections:reflections:0.9.11"
compile "org.reflections:reflections:0.9.12"
compile arcModule("backends:backend-sdl")
}
@@ -313,8 +301,8 @@ project(":annotations"){
apply plugin: "java"
dependencies{
compile 'com.squareup:javapoet:1.11.0'
compile "com.github.Anuken.Arc:arc-core:$arcExtVersion"
compile 'com.squareup:javapoet:1.12.1'
compile "com.github.Anuken.Arc:arc-core:$arcHash"
compile files("${System.getProperty('java.home')}/../lib/tools.jar")
}
}

View File

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

View File

@@ -43,10 +43,10 @@ schematic.replace = Šablona tohoto jména již existuje. Chceš ji nahradit?
schematic.import = Importuji šablonu...
schematic.exportfile = Exportovat soubor
schematic.importfile = Importovat soubor
schematic.browseworkshop = Procházet dílnu
schematic.browseworkshop = Procházet Workshop na Steamu
schematic.copy = Zkopírovat do schránky
schematic.copy.import = Importovat ze schránky
schematic.shareworkshop = Sdílet skrze Steam Workshop
schematic.shareworkshop = Sdílet skrze Workshop na Steamu
schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Převrátit šablonu
schematic.saved = Šablona byla uložena.
schematic.delete.confirm = Šablona bude kompletně vyhlazena.
@@ -123,8 +123,8 @@ mod.item.remove = Tato položka je součástí [accent]'{0}'[] modifikace. Pokud
mod.remove.confirm = Tato modifikace bude odstraněna.
mod.author = [lightgray]Autor:[] {0}
mod.missing = Toto uložení hra obsahuje modifikace, které byly nedávno aktualizovány, nebo již nejsou nainstalovány. Použití tohoto uložení může vést k chybám. Jsi si jist, že chceš nahrát toto uložení hry?\n[lightgray]Modifikace:\n{0}
mod.preview.missing = Než vystavíš svou modifikaci v dílně, musíš přidat obrázek pro náhled.\nUmísti obrázek pojmenovaný [accent]preview.png[] do složky modifikace a zkus to znovu.
mod.folder.missing = V dílně mohou být vystaveny pouze modifikace ve formě složky.\nAbys převedl modifikaci na formu složky, jednoduše rozbal zip soubor do složky a smaž starý zip soubor. Potom znovu spusť hru nebo znovu načti modifikace.
mod.preview.missing = Než vystavíš svou modifikaci ve Workshopu na Steamu, musíš přidat obrázek pro náhled.\nUmísti obrázek pojmenovaný [accent]preview.png[] do složky modifikace a zkus to znovu.
mod.folder.missing = Ve Workshopu na Steamu mohou být vystaveny pouze modifikace ve formě složky.\nAbys převedl modifikaci na formu složky, jednoduše rozbal zip soubor do složky a smaž starý zip soubor. Potom znovu spusť hru nebo znovu načti modifikace.
mod.scripts.unsupported = Tvoje zařízení nepodporuje skripty. Některé modifikace nemusí správně fungovat.
about.button = O hře
@@ -240,8 +240,8 @@ save.playtime = Herní čas: {0}
warning = Varování.
confirm = Potvrdit
delete = Smazat
view.workshop = Prohlédnout v dílně
workshop.listing = Upravit popis v dílně
view.workshop = Prohlédnout ve Workshopu na Steamu
workshop.listing = Upravit popis ve Workshopu na Steamu
ok = OK
open = Otevřít
customize = Přizpůsobit pravidla
@@ -285,15 +285,15 @@ map.nospawn.pvp = Tato mapa nemá nepřátelská jádra, u kterých by se mohli
map.nospawn.attack = Tato mapa nemá nepřátelská jádra, která by mohla být zničena. Přidej v editoru do této mapy aspoň jedno [SCARLET]červené[] jádro.
map.invalid = Chyba v načítání mapy: poškozený nebo neplatný soubor mapy.
workshop.update = Aktualizovat položku
workshop.error = Chyba při načítání podrobností z dílny: {0}
map.publish.confirm = Jsi si jistý, že chceš vystavit tuto mapu?\n\n[lightgray]Ujisti se nejprve, že souhlasíš se smluvními podmínkami dílny (EULA), jinak se Tvoje mapa nezobrazí.[]
workshop.error = Chyba při načítání podrobností z Workshopu na Steamu: {0}
map.publish.confirm = Jsi si jistý, že chceš vystavit tuto mapu?\n\n[lightgray]Ujisti se nejprve, že souhlasíš se smluvními podmínkami Workshopu na Steamu (EULA), jinak se Tvoje mapa nezobrazí.[]
workshop.menu = Vyber si, co bys chtěl dělat s touto položkou.
workshop.info = Informace o položce
changelog = Seznam změn (volitelně):
eula = Smluvní podmínky platformy Steam
missing = Tato položka byla smazána nebo přesunuta.\n[lightgray]Položka bude automaticky odebrána ze seznamu dílny.
missing = Tato položka byla smazána nebo přesunuta.\n[lightgray]Položka bude automaticky odebrána ze seznamu Workshopu na Steamu.
publishing = [accent]Publikuji...
publish.confirm = Opravdu chceš toto vystavit?\n\n[lightgray]Ujisti se nejprve, že souhlasíš se smluvními podmínkami dílny (EULA), jinak se Tvoje položky nezobrazí.[]
publish.confirm = Opravdu chceš toto vystavit?\n\n[lightgray]Ujisti se nejprve, že souhlasíš se smluvními podmínkami Workshopu na Steamu (EULA), jinak se Tvoje položky nezobrazí.[]
publish.error = Chyba při vystavování položky: {0}
steam.error = Nepodařilo se inicializovat služby platformy Steam.\Chyba: {0}
@@ -309,9 +309,9 @@ editor.waves = Vln:
editor.rules = Pravidla:
editor.generation = Generace:
editor.ingame = Upravit ve hře
editor.publish.workshop = Vystavit v dílně
editor.publish.workshop = Vystavit ve Workshopu na Steamu
editor.newmap = Nová mapa
workshop = Dílna
workshop = Workshop na Steamu
waves.title = Vlny
waves.remove = Odebrat
waves.never = <Nikdy>
@@ -761,13 +761,13 @@ rules.blockhealthmultiplier = Násobek zdraví bloků
rules.playerhealthmultiplier = Násobek zdraví hráče
rules.playerdamagemultiplier = Násobek útoku hráče
rules.unitdamagemultiplier = Násobek poškození jednotkami
rules.enemycorebuildradius = Poloměr, ve kterém se okolo nepřítelského jádra nesmí stavět: [lightgray](dlaždic)[]
rules.enemycorebuildradius = Poloměr, ve kterém se okolo nepřátelského jádra nesmí stavět: [lightgray](dlaždic)[]
rules.respawntime = Čas znovuzrození: [lightgray](vteřin)[]
rules.wavespacing = Čas rozestupu mezi vlnami: [lightgray](vteřin)[]
rules.buildcostmultiplier = Násobek ceny stavění
rules.buildspeedmultiplier = Násobek rychlosti stavění
rules.waitForWaveToEnd = Vlny čekají na nepřátele
rules.dropzoneradius = Poloměr oblasti pro sestoupení: [lightgray](dlaždic)[]
rules.dropzoneradius = Poloměr oblasti pro vylíhnutí: [lightgray](dlaždic)[]
rules.respawns = Maximální počet znovuvylíhnutí za vlnu
rules.limitedRespawns = Maximální počet znovuzrození
rules.title.waves = Vlny
@@ -943,7 +943,8 @@ block.inverted-sorter.name = Obrácená třídička
block.message.name = Zpráva
block.illuminator.name = Osvětlovač
block.illuminator.description = Malý, kompaktní, konfigurovatelný zdroj světla. Vyžaduje pro svoje fungování energii.
block.overflow-gate.name = Přepadová brána
block.overflow-gate.name = Brána s přepadem
block.underflow-gate.name = Brána s podtokem
block.silicon-smelter.name = Křemíková huť
block.phase-weaver.name = Tkalcovna pro fázovou tkaninu
block.pulverizer.name = Rozmělňovač
@@ -1034,8 +1035,8 @@ block.overdrive-projector.name = Urychlující projektor
block.force-projector.name = Silový projektor
block.arc.name = Oblouk
block.rtg-generator.name = RTG
block.spectre.name = Duch
block.meltdown.name = Tavička
block.spectre.name = Spectre
block.meltdown.name = Meltdown
block.container.name = Kontejnér
block.launch-pad.name = Vysílací plošina
block.launch-pad-large.name = Velká vysílací plošina
@@ -1174,6 +1175,7 @@ block.inverted-sorter.description = Třídí předměty. Pokud je předmět shod
block.router.description = Přijímá předměty z jednoho směru a posílá je rovnoměrně do zbylých tří směrů. Užitečný pro rozdělení předmětů z jednoho zdroje do různých cílů, jako odbočení z dopravníků a podobně.\n\n[scarlet]Pozor, nepoužívejte pro vstup do produkční budovy, jinak se bude ucpávat výstupními předměty[].
block.distributor.description = Pokročilý směrovač. Rozděluje předměty rovnoměrně až do 7 dalších směrů.
block.overflow-gate.description = Předměty jsou poslány do strany, pokud je směr vpřed zablokován. Užitečné například pro zpracování přebytečného materiálu, pokud je primární příjemce saturován.
block.underflow-gate.description = Předměty jsou poslány vpřed, pokud je směr do strany zablokován. Užitečné například pro zpracování přebytečného materiálu, pokud je primární příjemce saturován.
block.mass-driver.description = Ultimátní blok pro přepravu předmětů. Sebere několik předmětů a vystřelí je k dalšímu hromadnému distributoru přes několik dlaždic. Vyžaduje ke své funkci energii.
block.mechanical-pump.description = Levné čerpadlo s pomalým průtokem, nevyžaduje však energii k provozu.
block.rotary-pump.description = Pokročilé čerpadlo, které za pomoci energie vyčerpá větší množství kapalin, než standardní.
@@ -1228,9 +1230,9 @@ block.salvo.description = Větší, pokročilejší verze střílny Duo. Pálí
block.fuse.description = Velká střílna s krátkým dosahem. Pálí trojice energetických paprsků blízké nepřátele.
block.ripple.description = Extrémně silná dělostřelecká střílna. Pálí na dálku shluky střel na nepřátelské jednotky.
block.cyclone.description = Velká protiletecká a protipozemní střílna. Pálí explodující dávky na nepřítele v okolí.
block.spectre.description = Velká střílna s kanónem s dvěma hlavněmi. Střílí velké náboje, které pronikají brněním jak pozemních, tak vzdušných nepřítelských cílů.
block.spectre.description = Velká střílna s kanónem s dvěma hlavněmi. Střílí velké náboje, které pronikají brněním jak pozemních, tak vzdušných nepřátelských cílů.
block.meltdown.description = Masivní laserový kanón. Nabije se a pak pálí nepřetržitý laserový paprsek na nepřátele v okolí. Vyžaduje ke své funkci chlazení.
block.command-center.description = Vydává příkazy spojeneckým jednotkám na mapě.\nInstruuje jednotky k útoku na nepřítelské jádro, návratu do jádra nebo továrny a ke shromáždění se. Pokud se na mapě nepřátelské jádro nenachází, jednotky budou v útočném režimu držet hlídku.
block.command-center.description = Vydává příkazy spojeneckým jednotkám na mapě.\nInstruuje jednotky k útoku na nepřátelské jádro, návratu do jádra nebo továrny a ke shromáždění se. Pokud se na mapě nepřátelské jádro nenachází, jednotky budou v útočném režimu držet hlídku.
block.draug-factory.description = Vyrábí těžící drony Dragoun.
block.spirit-factory.description = Vyrábí drony, které opravují budovy.
block.phantom-factory.description = Vyrábí drony s pokročilou konstrukcí.

View File

@@ -3,7 +3,7 @@ credits = Tekijät
contributors = Kääntäjät ja avustajat
discord = Liity Mindustryn Discordiin!
link.discord.description = Mindustryn virallinen Discord-keskusteluhuone
link.reddit.description = The Mindustry subreddit
link.reddit.description = Mindustry subreddit
link.github.description = Pelin lähdekoodi
link.changelog.description = Lista päivityksien muutoksista
link.dev-builds.description = Epävakaat kehitysversiot
@@ -19,47 +19,47 @@ screenshot.invalid = Kartta liian laaja, kuvankaappaukselle ei mahdollisesti ole
gameover = Peli ohi
gameover.pvp = [accent] {0}[] joukkue voittaa!
highscore = [accent]Uusi ennätys!
copied = Copied.
copied = Kopioitu.
load.sound = Sounds
load.map = Maps
load.image = Images
load.content = Content
load.system = System
load.mod = Mods
load.scripts = Scripts
load.sound = Ääni
load.map = Kartat
load.image = Kuvat
load.content = Sisältö
load.system = Systeemi
load.mod = Modit
load.scripts = Skriptit
be.update = A new Bleeding Edge build is available:
be.update.confirm = Download it and restart now?
be.updating = Updating...
be.ignore = Ignore
be.noupdates = No updates found.
be.check = Check for updates
be.update.confirm = Lataa se ja käynnistä peli uudelleen?
be.updating = Päivitetään...
be.ignore = Sivuuta
be.noupdates = Ei päivityksiä saatavilla.
be.check = Tarkista päivityksiä
schematic = Schematic
schematic.add = Save Schematic...
schematics = Schematics
schematic.replace = A schematic by that name already exists. Replace it?
schematic.import = Import Schematic...
schematic.exportfile = Export File
schematic.importfile = Import File
schematic.browseworkshop = Browse Workshop
schematic.copy = Copy to Clipboard
schematic.copy.import = Import from Clipboard
schematic.shareworkshop = Share on Workshop
schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Flip Schematic
schematic.saved = Schematic saved.
schematic.delete.confirm = This schematic will be utterly eradicated.
schematic.rename = Rename Schematic
schematic.info = {0}x{1}, {2} blocks
schematic = Kaavio
schematic.add = Tallenna Kaavio...
schematics = Kaaviot
schematic.replace = Kaavio tällä nimellä on jo olemassa. Haluatko korvata sen?
schematic.import = Tuo Kaavio...
schematic.exportfile = Luo Tiedosto
schematic.importfile = Tuo Tiedosto
schematic.browseworkshop = Selaa Työpajaa
schematic.copy = Kopioi Leikepöydälle
schematic.copy.import = Tou Leikepöydälle
schematic.shareworkshop = Jaa työpajaan
schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Käännä Kaavio
schematic.saved = Kaavio tallennettu.
schematic.delete.confirm = Tämä kaavio poistetaan.
schematic.rename = Uudelleennimeä Kaavio
schematic.info = {0}x{1}, {2} palikkaa
stat.wave = Aaltoja voitettu:[accent] {0}
stat.wave = Tasoja voitettu:[accent] {0}
stat.enemiesDestroyed = Vihollisia tuhottu:[accent] {0}
stat.built = Rakennuksia rakennettu:[accent] {0}
stat.destroyed = Rakennuksia tuhottu:[accent] {0}
stat.deconstructed = Rakennuksia purettu:[accent] {0}
stat.delivered = Resursseja laukaistu:
stat.rank = Lopullinen arvo: [accent]{0}
stat.rank = Lopullinen arvosana: [accent]{0}
launcheditems = [accent]Laukaistut tavarat
launchinfo = [unlaunched][[LAUNCH] your core to obtain the items indicated in blue.
@@ -78,49 +78,49 @@ customgame = Mukautettu peli
newgame = Uusi peli
none = <ei mitään>
minimap = Pienoiskartta
position = Position
position = Sijainti
close = Sulje
website = Verkkosivu
quit = Poistu
save.quit = Save & Quit
save.quit = Tallenna ja Poistu
maps = Kartat
maps.browse = Browse Maps
maps.browse = Selaa Karttoja
continue = Jatka
maps.none = [lightgray]Karttoja ei löytynyt!
invalid = Invalid
pickcolor = Pick Color
invalid = Invalidi
pickcolor = Valitse väri
preparingconfig = Preparing Config
preparingcontent = Preparing Content
uploadingcontent = Uploading Content
uploadingpreviewfile = Uploading Preview File
committingchanges = Comitting Changes
done = Done
feature.unsupported = Your device does not support this feature.
done = Valmis
feature.unsupported = Sinun laitteesi ei tue tätä toimintoa.
mods.alphainfo = Keep in mind that mods are in alpha, and[scarlet] may be very buggy[].\nReport any issues you find to the Mindustry GitHub or Discord.
mods.alphainfo = Pidä mielessä että modit ovat alpha-tilassa, ja[scarlet] ne voivat olla virheellisiä[].\nRaportoi kaikki virheet Mindustry GitHub-sivuille tai Discordiin.
mods.alpha = [accent](Alpha)
mods = Mods
mods.none = [LIGHT_GRAY]No mods found!
mods.guide = Modding Guide
mods.report = Report Bug
mods.openfolder = Open Mod Folder
mod.enabled = [lightgray]Enabled
mod.disabled = [scarlet]Disabled
mod.disable = Disable
mod.delete.error = Unable to delete mod. File may be in use.
mod.requiresversion = [scarlet]Requires min game version: [accent]{0}
mod.missingdependencies = [scarlet]Missing dependencies: {0}
mod.erroredcontent = [scarlet]Content Errors
mod.errors = Errors have occurred loading content.
mod.noerrorplay = [scarlet]You have mods with errors.[] Either disable the affected mods or fix the errors before playing.
mods = Modit
mods.none = [LIGHT_GRAY]Modeja ei löytynyt!
mods.guide = Modaamisen opas
mods.report = Raportoi ohjelmistovirhe
mods.openfolder = Avaa Modikansio
mod.enabled = [lightgray]Käytössä
mod.disabled = [scarlet]Epäkäytössä
mod.disable = Laita pois päältä
mod.delete.error = Modia ei pystynyt poistamaan. Tiedosto voi olla käytössä.
mod.requiresversion = [scarlet]Tarvitsee vähintää pelin version: [accent]{0}
mod.missingdependencies = [scarlet]Tarvitsee nämä modit: {0}
mod.erroredcontent = [scarlet]Sisältö Virheet
mod.errors = Virheitä on tapahtunut pelin ladatessa.
mod.noerrorplay = [scarlet]Sinulla on virheellisiä modeja.[] Joko poista ne käytöstä tai korjaa virheet.
mod.nowdisabled = [scarlet]Mod '{0}' is missing dependencies:[accent] {1}\n[lightgray]These mods need to be downloaded first.\nThis mod will be automatically disabled.
mod.enable = Enable
mod.requiresrestart = The game will now close to apply the mod changes.
mod.reloadrequired = [scarlet]Reload Required
mod.import = Import Mod
mod.enable = Käytä
mod.requiresrestart = Peli suljetaan jotta muutokset voisivat toteutua.
mod.reloadrequired = [scarlet]Vaatii Uudelleenkäynnistystä
mod.import = Tuo Modi
mod.import.github = Import GitHub Mod
mod.item.remove = This item is part of the[accent] '{0}'[] mod. To remove it, uninstall that mod.
mod.remove.confirm = This mod will be deleted.
mod.remove.confirm = Tämä modi poistetaan.
mod.author = [LIGHT_GRAY]Author:[] {0}
mod.missing = This save contains mods that you have recently updated or no longer have installed. Save corruption may occur. Are you sure you want to load it?\n[lightgray]Mods:\n{0}
mod.preview.missing = Before publishing this mod in the workshop, you must add an image preview.\nPlace an image named[accent] preview.png[] into the mod's folder and try again.
@@ -143,34 +143,34 @@ server.closing = [accent]Suljetaan palvelinta...
server.kicked.kick = Sinut on potkittu palvelimelta!
server.kicked.whitelist = You are not whitelisted here.
server.kicked.serverClose = Palvelin suljettu.
server.kicked.vote = You have been vote-kicked. Goodbye.
server.kicked.vote = Sinut on äänetetty pois. Hyvästi.
server.kicked.clientOutdated = Pelisi on vanhentunut! Päivitä se!
server.kicked.serverOutdated = Outdated server! Ask the host to update!
server.kicked.serverOutdated = Vanhentunut palvelin! Pyydä isäntää päivittämään!
server.kicked.banned = Sinulla on portikielto tälle palvelimelle.
server.kicked.typeMismatch = This server is not compatible with your build type.
server.kicked.playerLimit = This server is full. Wait for an empty slot.
server.kicked.playerLimit = Tämä palvelin on täynnä. Odota vapaata tilaa.
server.kicked.recentKick = Sinut on potkittu äskettäin.\nOdota ennen kuin yhdistät uudestaan.
server.kicked.nameInUse = Joku tuon niminen\non jo tällä palvelimella.
server.kicked.nameEmpty = Valitsemasi nimi on virheellinen.
server.kicked.idInUse = Olet jo tällä palvelimella! Kahdella käyttäjällä yhdistäminen ei ole sallittua.
server.kicked.customClient = Tämä palvelin ei tue muokattuja versioita. Lataa virallinen versio.
server.kicked.gameover = Peli ohi!
server.kicked.serverRestarting = The server is restarting.
server.kicked.serverRestarting = Tämä palvelin on uudelleenkäynnistymässä.
server.versions = Versiosi:[accent] {0}[]\nPalvelimen versio:[accent] {1}[]
host.info = The [accent]host[] button hosts a server on port [scarlet]6567[]. \nAnybody on the same [lightgray]wifi or local network[] should be able to see your server in their server list.\n\nIf you want people to be able to connect from anywhere by IP, [accent]port forwarding[] is required.\n\n[lightgray]Note: If someone is experiencing trouble connecting to your LAN game, make sure you have allowed Mindustry access to your local network in your firewall settings. Note that public networks sometimes do not allow server discovery.
join.info = Here, you can enter a [accent]server IP[] to connect to, or discover [accent]local network[] servers to connect to.\nBoth LAN and WAN multiplayer is supported.\n\n[lightgray]Note: There is no automatic global server list; if you want to connect to someone by IP, you would need to ask the host for their IP.
hostserver = Host Multiplayer Game
invitefriends = Invite Friends
hostserver = Pidä yllä monipelaaja peliä
invitefriends = Pyydä Ystäviä
hostserver.mobile = Host\nGame
host = Host
hosting = [accent]Avataan palvelinta...
hosts.refresh = Päivitä
hosts.discovering = Discovering LAN games
hosts.discovering.any = Discovering games
hosts.discovering = Etsitään LAN pelejä
hosts.discovering.any = Etsitään Pelejä
server.refreshing = Päivitetään palvelimen tietoja
hosts.none = [lightgray]No local games found!
host.invalid = [scarlet]Can't connect to host.
trace = Trace Player
hosts.none = [lightgray]Paikallisia pelejä ei löytynyt!
host.invalid = [scarlet]Isäntään ei voitu yhdistää.
trace = Seuraa Pelaajaa
trace.playername = Pelaajanimi: [accent]{0}
trace.ip = IP-osoite: [accent]{0}
trace.id = Uniikki tunniste: [accent]{0}
@@ -188,17 +188,17 @@ server.outdated = [crimson]Vanhentunut palvelin![]
server.outdated.client = [crimson]Vanhentunut asiakasohjelma![]
server.version = [gray]v{0} {1}
server.custombuild = [yellow]Custom Build
confirmban = Are you sure you want to ban this player?
confirmkick = Are you sure you want to kick this player?
confirmvotekick = Are you sure you want to vote-kick this player?
confirmunban = Are you sure you want to unban this player?
confirmadmin = Are you sure you want to make this player an admin?
confirmban = Oletko varma että haluat potkia tämän pelaajan?
confirmkick = Oletko varma että haluat poistaa tämän pelaajan?
confirmvotekick = Oletko varma että haluat äänestää tämän pelaajan potkituksi?
confirmunban = Oletko varma että haluat päästää tämän pelaajan takaisin?
confirmadmin = Oletko varma että haluat antaa pelaajalle hallinto-oikeuksia?
confirmunadmin = Are you sure you want to remove admin status from this player?
joingame.title = Liity peliin
joingame.ip = Osoite:
disconnect = Disconnected.
disconnect.error = Connection error.
disconnect.closed = Connection closed.
disconnect = Yhteys katkaistu.
disconnect.error = Yhteysvirhe.
disconnect.closed = Yhteys poistettu.
disconnect.timeout = Timed out.
disconnect.data = Failed to load world data!
cantconnect = Unable to join game ([accent]{0}[]).
@@ -212,7 +212,7 @@ save.new = New Save
save.overwrite = Are you sure you want to overwrite\nthis save slot?
overwrite = Overwrite
save.none = No saves found!
saveload = Saving...
saveload = Tallennetaan...
savefail = Failed to save game!
save.delete.confirm = Are you sure you want to delete this save?
save.delete = Delete
@@ -220,7 +220,7 @@ save.export = Export Save
save.import.invalid = [accent]This save is invalid!
save.import.fail = [crimson]Failed to import save: [accent]{0}
save.export.fail = [crimson]Failed to export save: [accent]{0}
save.import = Import Save
save.import = Tuo Tallennus
save.newslot = Tallennuksen nimi:
save.rename = Nimeä uudelleen
save.rename.text = Uusi nimi:
@@ -265,8 +265,8 @@ cancelbuilding = [accent][[{0}][] to clear plan
selectschematic = [accent][[{0}][] to select+copy
pausebuilding = [accent][[{0}][] to pause building
resumebuilding = [scarlet][[{0}][] to resume building
wave = [accent]Aalto {0}
wave.waiting = [lightgray]Wave in {0}
wave = [accent]Taso {0}
wave.waiting = [lightgray]Seuraava taso {0}
wave.waveInProgress = [lightgray]Wave in progress
waiting = [lightgray]Odotetaan...
waiting.players = Odotetaan pelaajia...
@@ -275,7 +275,7 @@ wave.enemy = [lightgray]{0} vihollinen jäljellä
loadimage = Lataa kuva
saveimage = Tallenna kuva
unknown = Tuntematon
custom = Custom
custom = Mukautettu
builtin = Sisäänrakennettu
map.delete.confirm = Oletko varma että haluat poistaa tämän kartan? Poistoa ei voi peruuttaa!
map.random = [accent]Satunnainen kartta
@@ -296,30 +296,30 @@ publish.confirm = Are you sure you want to publish this?\n\n[lightgray]Make sure
publish.error = Error publishing item: {0}
steam.error = Failed to initialize Steam services.\nError: {0}
editor.brush = Brush
editor.brush = Sivellin
editor.openin = Avaa editorissa
editor.oregen = Ore Generation
editor.oregen.info = Ore Generation:
editor.mapinfo = Kartan tiedot
editor.author = Author:
editor.author = Tekijä:
editor.description = Kuvaus:
editor.nodescription = A map must have a description of at least 4 characters before being published.
editor.waves = Aallot:
editor.nodescription = Kartan kuvaksessa täytyy olla vähintään neljä kirjainta ennen julkaisua.
editor.waves = Tasot:
editor.rules = Säännöt:
editor.generation = Generation:
editor.ingame = Edit In-Game
editor.publish.workshop = Publish On Workshop
editor.generation = Generaatio:
editor.ingame = Muokka pelin sisällä
editor.publish.workshop = Julkaise työpajaan
editor.newmap = Uusi kartta
workshop = Workshop
waves.title = Aallot
waves.remove = Remove
workshop = Työpaja
waves.title = Tasot
waves.remove = Poista
waves.never = <ei koskaan>
waves.every = every
waves.waves = wave(s)
waves.perspawn = per spawn
waves.perspawn = per spawni
waves.to = to
waves.boss = Boss
waves.preview = Preview
waves.boss = Pomo
waves.preview = Esikatselu
waves.edit = Muokkaa...
waves.copy = Kopioi leikepöydälle
waves.load = Lataa leikepöydältä
@@ -327,11 +327,11 @@ waves.invalid = Invalid waves in clipboard.
waves.copied = Aallot kopioitu.
waves.none = No enemies defined.\nNote that empty wave layouts will automatically be replaced with the default layout.
editor.default = [lightgray]<Default>
details = Details...
details = Yksityiskohdat...
edit = Muokkaa...
editor.name = Nimi:
editor.spawn = Spawn Unit
editor.removeunit = Remove Unit
editor.spawn = Spawni yksikkö
editor.removeunit = Poista yksikkö
editor.teams = Joukkueet
editor.errorload = Virhe ladattaessa tiedostoa:\n[accent]{0}
editor.errorsave = Virhe tallennettaessa tiedostoa:\n[accent]{0}
@@ -341,10 +341,10 @@ editor.errornot = This is not a map file.
editor.errorheader = This map file is either not valid or corrupt.
editor.errorname = Map has no name defined. Are you trying to load a save file?
editor.update = Päivitä
editor.randomize = Randomize
editor.apply = Apply
editor.generate = Generate
editor.resize = Resize
editor.randomize = Satunnaista
editor.apply = Käytä
editor.generate = Generoi
editor.resize = Säädä kokoa
editor.loadmap = Lataa kartta
editor.savemap = Tallenna kartta
editor.saved = Tallennettu!
@@ -370,12 +370,12 @@ editor.resizemap = Resize Map
editor.mapname = Kartan nimi:
editor.overwrite = [accent]Warning!\nThis overwrites an existing map.
editor.overwrite.confirm = [scarlet]Warning![] A map with this name already exists. Are you sure you want to overwrite it?
editor.exists = A map with this name already exists.
editor.selectmap = Select a map to load:
editor.exists = Kartta tällä nimellä on jo olemassa.
editor.selectmap = Valitse kartta ladattavaksi:
toolmode.replace = Replace
toolmode.replace = Korvaa
toolmode.replace.description = Draws only on solid blocks.
toolmode.replaceall = Replace All
toolmode.replaceall = Korvaa kaikki
toolmode.replaceall.description = Replace all blocks in map.
toolmode.orthogonal = Orthogonal
toolmode.orthogonal.description = Draws only orthogonal lines.
@@ -424,48 +424,48 @@ width = Leveys:
height = Korkeus:
menu = Valikko
play = Pelaa
campaign = Campaign
campaign = Polku
load = Lataa
save = Tallenna
fps = FPS: {0}
ping = Ping: {0}ms
language.restart = Please restart your game for the language settings to take effect.
settings = Asetukset
tutorial = Perehdytys
tutorial.retake = Re-Take Tutorial
editor = Editor
mapeditor = Map Editor
tutorial = Tutoriaali
tutorial.retake = Uusita Tutoriaali
editor = Editori
mapeditor = Kartan Editori
abandon = Hylkää
abandon.text = This zone and all its resources will be lost to the enemy.
locked = Lukittu
complete = [lightgray]Reach:
requirement.wave = Reach Wave {0} in {1}
requirement.core = Destroy Enemy Core in {0}
requirement.unlock = Unlock {0}
requirement.wave = Pääse Tasolle {0} kartassa {1}
requirement.core = Tuhoa vihollise ydin kartassa {0}
requirement.unlock = Avaa {0}
resume = Resume Zone:\n[lightgray]{0}
bestwave = [lightgray]Best Wave: {0}
bestwave = [lightgray]Paras taso: {0}
launch = < LAUNCH >
launch.title = Launch Successful
launch.title = Onnistunut laukaisu
launch.next = [lightgray]next opportunity at wave {0}
launch.unable2 = [scarlet]Unable to LAUNCH.[]
launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base.
launch.skip.confirm = If you skip now, you will not be able to launch until later waves.
uncover = Uncover
launch.confirm = Tämä laukaisee kaikki resourssit ytimestäsi.\nEt voi enää palata takaisin.
launch.skip.confirm = Jos ohitat nyt, voit laukaista vasta myöhemmissä tasoissa.
uncover = Paljasta
configure = Configure Loadout
bannedblocks = Banned Blocks
addall = Add All
bannedblocks = Kielletyt Palikat
addall = Lisää kaikki
configure.locked = [lightgray]Unlock configuring loadout: Wave {0}.
configure.invalid = Amount must be a number between 0 and {0}.
zone.unlocked = [lightgray]{0} unlocked.
zone.requirement.complete = Wave {0} reached:\n{1} zone requirements met.
zone.config.unlocked = Loadout unlocked:[lightgray]\n{0}
zone.resources = [lightgray]Resources Detected:
zone.objective = [lightgray]Objective: [accent]{0}
zone.objective.survival = Survive
zone.resources = [lightgray]Resoursseja havaittu:
zone.objective = [lightgray]Objectiivi: [accent]{0}
zone.objective.survival = Selviydy
zone.objective.attack = Destroy Enemy Core
add = Add...
boss.health = Boss Health
add = Lisää...
boss.health = Pomon elinpisteet
connectfail = [crimson]Connection error:\n\n[accent]{0}
error.unreachable = Server unreachable.\nIs the address spelled correctly?
@@ -478,209 +478,209 @@ error.io = Network I/O error.
error.any = Unknown network error.
error.bloom = Failed to initialize bloom.\nYour device may not support it.
zone.groundZero.name = Ground Zero
zone.desertWastes.name = Desert Wastes
zone.craters.name = The Craters
zone.frozenForest.name = Frozen Forest
zone.ruinousShores.name = Ruinous Shores
zone.stainedMountains.name = Stained Mountains
zone.desolateRift.name = Desolate Rift
zone.nuclearComplex.name = Nuclear Production Complex
zone.overgrowth.name = Overgrowth
zone.tarFields.name = Tar Fields
zone.saltFlats.name = Salt Flats
zone.impact0078.name = Impact 0078
zone.crags.name = Crags
zone.fungalPass.name = Fungal Pass
zone.groundZero.name = Vaara Alue
zone.desertWastes.name = Aavikon Jätteet
zone.craters.name = Kraatterit
zone.frozenForest.name = Jäätynyt Metsä
zone.ruinousShores.name = Tuhoisa Ranta
zone.stainedMountains.name = Tahravuoret
zone.desolateRift.name = Autio Syvänne
zone.nuclearComplex.name = Ydinvoima Kompleksi
zone.overgrowth.name = Liikakasvu
zone.tarFields.name = Terva Pellot
zone.saltFlats.name = Suolainen Tasanne
zone.impact0078.name = Isku 0078
zone.crags.name = Kalliot
zone.fungalPass.name = Sienilaakso
zone.groundZero.description = The optimal location to begin once more. Low enemy threat. Few resources.\nGather as much lead and copper as possible.\nMove on.
zone.frozenForest.description = Even here, closer to mountains, the spores have spread. The frigid temperatures cannot contain them forever.\n\nBegin the venture into power. Build combustion generators. Learn to use menders.
zone.desertWastes.description = These wastes are vast, unpredictable, and criss-crossed with derelict sector structures.\nCoal is present in the region. Burn it for power, or synthesize graphite.\n\n[lightgray]This landing location cannot be guaranteed.
zone.saltFlats.description = On the outskirts of the desert lie the Salt Flats. Few resources can be found in this location.\n\nThe enemy has erected a resource storage complex here. Eradicate their core. Leave nothing standing.
zone.craters.description = Water has accumulated in this crater, relic of the old wars. Reclaim the area. Collect sand. Smelt metaglass. Pump water to cool turrets and drills.
zone.ruinousShores.description = Past the wastes, is the shoreline. Once, this location housed a coastal defense array. Not much of it remains. Only the most basic defense structures have remained unscathed, everything else reduced to scrap.\nContinue the expansion outwards. Rediscover the technology.
zone.stainedMountains.description = Further inland lie the mountains, yet untainted by spores.\nExtract the abundant titanium in this area. Learn how to use it.\n\nThe enemy presence is greater here. Do not give them time to send their strongest units.
zone.overgrowth.description = This area is overgrown, closer to the source of the spores.\nThe enemy has established an outpost here. Build Titan units. Destroy it. Reclaim that which was lost.
zone.tarFields.description = The outskirts of an oil production zone, between the mountains and desert. One of the few areas with usable tar reserves.\nAlthough abandoned, this area has some dangerous enemy forces nearby. Do not underestimate them.\n\n[lightgray]Research oil processing technology if possible.
zone.desolateRift.description = An extremely dangerous zone. Plentiful resources, but little space. High risk of destruction. Leave as soon as possible. Do not be fooled by the long spacing between enemy attacks.
zone.nuclearComplex.description = A former facility for the production and processing of thorium, reduced to ruins.\n[lightgray]Research the thorium and its many uses.\n\nThe enemy is present here in great numbers, constantly scouting for attackers.
zone.fungalPass.description = A transition area between high mountains and lower, spore-ridden lands. A small enemy reconnaissance base is located here.\nDestroy it.\nUse Dagger and Crawler units. Take out the two cores.
zone.groundZero.description = Suotuisa alue aloittaa peli. Matala vaarataso. Vähän resoursseja.\nKerää mahdollisimman paljon kuparia ja lyijyä.\nJatka eteenpäin.
zone.frozenForest.description = Jopa täällä, lähellä vuoria, asustaa itiöitä. Mutta ne eivöt voi elää ikuisesti jäätävässä ilmastossa.\n\nAloita matkasi energiaan. Rakenna polttogeneraattoreita. Opettele korjaajien käyttö.
zone.desertWastes.description = Valtavia määriä jätteitä ränsityneiden rakennuksien seassa.\nVoit löytää hiiltä. Polta se energiaksi, tai tiivistä siitä grafiittia.\n\n[lightgray]Laskeutumiskohta on epävarma.
zone.saltFlats.description = Aavikoiden reunoilla on suolainen tasanne. Vain vähän resoursse on saatavilla.\n\nVihollinen on rakentanut resurssi hankinnan. Hävitä vihollisen ydin. Älä jätä mitään jäljelle.
zone.craters.description = Vettä on kertynyt tähän kraatteriin vanhojen sotien jäänteinä. Ota alue itsellesi. Kerää hiekkaa. Sulata metallilasia. Pumppaa vettä jäähdyttääksesi kaivausporia ja tykkejä.
zone.ruinousShores.description = Jätteiden takaa, löydät rantaviivan. Kerran täma paikka asutti sotilasjoukkoja. Paljoa jäljella ei ole. Vain perus puolustus rekenteet ovat vahingoittumattomia, kaakki muu on romua.\nJatka laajentamista eteenpäin. Tutki teknologiaa.
zone.stainedMountains.description = Alankoa vuroien sisämaassa, löydät paljon itiöelämää.\nOta talteen runsas titaani jota täältä löytyy. Opi käyttämään sitä.\n\nVihollinen on läasnäoleva. Älä anna heille liikaa aikaa lähettää heidän vahvimpia aseitaan.
zone.overgrowth.description = Tämä alue on ylikasvanut, lähempänä itiöiden pesäkettä.\nVihollinen on muodostanut etuvartion. Rakenna titaani yksikköjä. Tuhoa vihollinen. Hanki se alue joka joskus on menetetty.
zone.tarFields.description = Öljytuotannon laitamia, vuorien ja aavikkojen välissä. Yksi ainoista paikosta joissa on tervalähde.\nLöydät vaarallisia vihollis joukkoja täältä hylätystä paikasta. Älä aliarvio niitä.\n\n[lightgray]Tutki öljyprosessointi mekanismeja jos mahdollista.
zone.desolateRift.description = Extremaalisen vaarallinen alue. Runsaasti resursseja, mutta vain vähän tilaa. Korke riski eliminaatiolle. Lähde mahdollisimman nopeasti. Älä tule huijatuksi pitkien taukojen vihollisten hyökkäyksien vällillä.
zone.nuclearComplex.description = Entinen laitos tehty toriumin tuotantoa ja prosessointia varten, nykyään vain rauniota.\n[lightgray]Tutki toriumin monia hyödyllisiä käyttötarkoituksia.\n\nVihollinen on läsnä isoin joukkoin kokoajan partioimassa tunkeilijoilta.
zone.fungalPass.description = Siirtymis alue korkeiden ja matalien vuorien välillä, itiöiden peitossa. Pieni vihollis tiedustelu tukikohta on täällä. Tuhoa se.\nKäytä Dagger- ja Crawler yksikköjä. Tuhoa kaksi vihollisydintä.
zone.impact0078.description = <insert description here>
zone.crags.description = <insert description here>
settings.language = Language
settings.data = Game Data
settings.reset = Reset to Defaults
settings.rebind = Rebind
settings.resetKey = Reset
settings.controls = Controls
settings.game = Game
settings.sound = Sound
settings.graphics = Graphics
settings.cleardata = Clear Game Data...
settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone!
settings.clearall.confirm = [scarlet]WARNING![]\nThis will clear all data, including saves, maps, unlocks and keybinds.\nOnce you press 'ok' the game will wipe all data and automatically exit.
paused = [accent]< Paused >
clear = Clear
banned = [scarlet]Banned
yes = Yes
no = No
info.title = Info
settings.language = Kieli
settings.data = Peli Data
settings.reset = Nollaa Asetukset
settings.rebind = Uudelleenaseta
settings.resetKey = Aseta Uudelleen
settings.controls = Kontrollit
settings.game = Peli
settings.sound = Ääni
settings.graphics = Grafiikat
settings.cleardata = Tyhjennä Pelin Data...
settings.clear.confirm = Oletko varma että haluat tyhjentää pelin datan?\nMitä on tehty ei voi peruuttaa!
settings.clearall.confirm = [scarlet]WARNING![]\nTämä poistaa kaiken datan, mukaanlukien kesken olevat pelit, kartat, avatut asiat ja kontrolliasetukset.\nKun painat 'ok' kaikki datasi poistetaan ja peli suljetaan.
paused = [accent]< Pysäytetty >
clear = Tyhjä
banned = [scarlet]Kielletty
yes = Kyllä
no = Ei
info.title = Informaatio
error.title = [crimson]An error has occured
error.crashtitle = An error has occured
blocks.input = Input
blocks.output = Output
blocks.booster = Booster
blocks.input = Sisääntulo
blocks.output = Ulostulo
blocks.booster = Boostaa
block.unknown = [lightgray]???
blocks.powercapacity = Power Capacity
blocks.powershot = Power/Shot
blocks.damage = Damage
blocks.targetsair = Targets Air
blocks.targetsground = Targets Ground
blocks.itemsmoved = Move Speed
blocks.launchtime = Time Between Launches
blocks.shootrange = Range
blocks.size = Size
blocks.liquidcapacity = Liquid Capacity
blocks.powerrange = Power Range
blocks.powerconnections = Max Connections
blocks.poweruse = Power Use
blocks.powerdamage = Power/Damage
blocks.itemcapacity = Item Capacity
blocks.basepowergeneration = Base Power Generation
blocks.productiontime = Production Time
blocks.repairtime = Block Full Repair Time
blocks.speedincrease = Speed Increase
blocks.range = Range
blocks.drilltier = Drillables
blocks.drillspeed = Base Drill Speed
blocks.boosteffect = Boost Effect
blocks.maxunits = Max Active Units
blocks.health = Health
blocks.buildtime = Build Time
blocks.buildcost = Build Cost
blocks.inaccuracy = Inaccuracy
blocks.shots = Shots
blocks.reload = Shots/Second
blocks.ammo = Ammo
blocks.powercapacity = Energiakapasiteetti
blocks.powershot = Energiaa/Ammus
blocks.damage = Vahinko
blocks.targetsair = Hyökkää Ilmaan
blocks.targetsground = Hyökkää Maahan
blocks.itemsmoved = Liikkumisnopeus
blocks.launchtime = Aika Laukaisujen Välillä
blocks.shootrange = Kantama
blocks.size = Koko
blocks.liquidcapacity = Neste Kapasiteetti
blocks.powerrange = Energia Kantama
blocks.powerconnections = Maksimi konnektio määrä
blocks.poweruse = Energian Käyttö
blocks.powerdamage = Energia/Vahinko
blocks.itemcapacity = Tavara Kapasiteetti
blocks.basepowergeneration = Kanta Enegian Generointi
blocks.productiontime = Produktion Aika
blocks.repairtime = Kokonaisen Palikan Korjaus Aika
blocks.speedincrease = Nopeuden Kasvu
blocks.range = Etäisyys
blocks.drilltier = Porattavat
blocks.drillspeed = Kanta Poran Nopeus
blocks.boosteffect = Boostaamisen Vaikutus
blocks.maxunits = Maksimi Määrä Yksikköjä
blocks.health = Elämäpisteet
blocks.buildtime = Rakentamisen Aika
blocks.buildcost = Rakentamisen Hinta
blocks.inaccuracy = Epätarkkuus
blocks.shots = Ammusta
blocks.reload = Ammusta/Sekunnissa
blocks.ammo = Ammus
bar.drilltierreq = Better Drill Required
bar.drillspeed = Drill Speed: {0}/s
bar.pumpspeed = Pump Speed: {0}/s
bar.efficiency = Efficiency: {0}%
bar.powerbalance = Power: {0}/s
bar.powerstored = Stored: {0}/{1}
bar.poweramount = Power: {0}
bar.poweroutput = Power Output: {0}
bar.items = Items: {0}
bar.capacity = Capacity: {0}
bar.liquid = Liquid
bar.heat = Heat
bar.power = Power
bar.progress = Build Progress
bar.spawned = Units: {0}/{1}
bar.input = Input
bar.output = Output
bar.drilltierreq = Parempi Pora Vaadittu
bar.drillspeed = Poran Nopeus: {0}/s
bar.pumpspeed = Pumpun Nopeus: {0}/s
bar.efficiency = Tehokkuus: {0}%
bar.powerbalance = Energia: {0}/s
bar.powerstored = Säilöttynä: {0}/{1}
bar.poweramount = Energia: {0}
bar.poweroutput = Energian Ulostulo: {0}
bar.items = Tavaroita: {0}
bar.capacity = Kapasiteetti: {0}
bar.liquid = Neste
bar.heat = Lämpö
bar.power = Energia
bar.progress = Rakennuksen Edistys
bar.spawned = Yksikköjä: {0}/{1}
bar.input = Sisääntulo
bar.output = Ulostulo
bullet.damage = [stat]{0}[lightgray] damage
bullet.splashdamage = [stat]{0}[lightgray] area dmg ~[stat] {1}[lightgray] tiles
bullet.incendiary = [stat]incendiary
bullet.homing = [stat]homing
bullet.shock = [stat]shock
bullet.frag = [stat]frag
bullet.damage = [stat]{0}[lightgray] Vahinko
bullet.splashdamage = [stat]{0}[lightgray] Alue vahinko ~[stat] {1}[lightgray] palikkaa
bullet.incendiary = [stat]sytyttävä
bullet.homing = [stat]itseohjautuva
bullet.shock = [stat]shokki
bullet.frag = [stat]sirpaloituva
bullet.knockback = [stat]{0}[lightgray] knockback
bullet.freezing = [stat]freezing
bullet.tarred = [stat]tarred
bullet.multiplier = [stat]{0}[lightgray]x ammo multiplier
bullet.reload = [stat]{0}[lightgray]x fire rate
bullet.freezing = [stat]jäädyttävä
bullet.tarred = [stat]tervattu
bullet.multiplier = [stat]{0}[lightgray]x ammusten multiplikaatio
bullet.reload = [stat]{0}[lightgray]x ammunta nopeus
unit.blocks = blocks
unit.powersecond = power units/second
unit.liquidsecond = liquid units/second
unit.itemssecond = items/second
unit.liquidunits = liquid units
unit.powerunits = power units
unit.degrees = degrees
unit.seconds = seconds
unit.persecond = /sec
unit.timesspeed = x speed
unit.blocks = palikat
unit.powersecond = energia yksikköä/sekunti
unit.liquidsecond = neste yksikköä/sekunti
unit.itemssecond = esinettä/sekunti
unit.liquidunits = neste yksikköä
unit.powerunits = energia yksikköä
unit.degrees = astetta
unit.seconds = sekunttia
unit.persecond = /s
unit.timesspeed = x nopeus
unit.percent = %
unit.items = items
unit.thousands = k
unit.items = esinettä
unit.thousands = t
unit.millions = mil
category.general = General
category.power = Power
category.liquids = Liquids
category.items = Items
category.crafting = Input/Output
category.shooting = Shooting
category.optional = Optional Enhancements
setting.landscape.name = Lock Landscape
setting.shadows.name = Shadows
setting.blockreplace.name = Automatic Block Suggestions
setting.linear.name = Linear Filtering
setting.hints.name = Hints
setting.buildautopause.name = Auto-Pause Building
setting.animatedwater.name = Animated Water
setting.animatedshields.name = Animated Shields
setting.antialias.name = Antialias[lightgray] (requires restart)[]
setting.indicators.name = Enemy/Ally Indicators
setting.autotarget.name = Auto-Target
setting.keyboard.name = Mouse+Keyboard Controls
setting.touchscreen.name = Touchscreen Controls
setting.fpscap.name = Max FPS
setting.fpscap.none = None
category.general = Yleinen
category.power = Energia
category.liquids = Neste
category.items = Tavarat
category.crafting = Ulos/Sisääntulo
category.shooting = Ammunta
category.optional = Mahdolliset Lumoukset
setting.landscape.name = Lukitse tasavaakaan
setting.shadows.name = Varjot
setting.blockreplace.name = Automaattisia Palikka Suosituksia
setting.linear.name = Lineararien Filteeraus
setting.hints.name = Vihjeet
setting.buildautopause.name = Automaattisest Pysäytä Rakentaessa
setting.animatedwater.name = Animoitu Vesi
setting.animatedshields.name = Animoitu Kilpi
setting.antialias.name = Antialiaasi[lightgray] (vaatii uudelleenkäynnistyksen)[]
setting.indicators.name = Vihollis/Puolulais Indikaattorit
setting.autotarget.name = Automaatinen Tähtäys
setting.keyboard.name = Hiiri+Näppäimistö Kontrollit
setting.touchscreen.name = Kosketusnäyttö kontrollit
setting.fpscap.name = Maksimi FPS
setting.fpscap.none = Ei Mitään
setting.fpscap.text = {0} FPS
setting.uiscale.name = UI Scaling[lightgray] (require restart)[]
setting.swapdiagonal.name = Always Diagonal Placement
setting.difficulty.training = Training
setting.difficulty.easy = Easy
setting.difficulty.normal = Normal
setting.difficulty.hard = Hard
setting.difficulty.insane = Insane
setting.difficulty.name = Difficulty:
setting.screenshake.name = Screen Shake
setting.effects.name = Display Effects
setting.destroyedblocks.name = Display Destroyed Blocks
setting.uiscale.name = UI Koko[lightgray] (vaatii uudelleenkäynnistyksen)[]
setting.swapdiagonal.name = Aina Vino Korvaus
setting.difficulty.training = Treeni
setting.difficulty.easy = Helppo
setting.difficulty.normal = Keskivaikea
setting.difficulty.hard = Haastava
setting.difficulty.insane = Järjetön
setting.difficulty.name = Vaikeustaso:
setting.screenshake.name = Näytön keikkuminen
setting.effects.name = Naytön Efektit
setting.destroyedblocks.name = Näytä Tuhoutuneet Palikat
setting.conveyorpathfinding.name = Conveyor Placement Pathfinding
setting.coreselect.name = Allow Schematic Cores
setting.sensitivity.name = Controller Sensitivity
setting.saveinterval.name = Save Interval
setting.seconds = {0} Seconds
setting.sensitivity.name = Kontrollin Herkkyys
setting.saveinterval.name = Tallennuksen Aikaväli
setting.seconds = {0} Sekunttia
setting.blockselecttimeout.name = Block Select Timeout
setting.milliseconds = {0} milliseconds
setting.milliseconds = {0} millisekunttia
setting.fullscreen.name = Fullscreen
setting.borderlesswindow.name = Borderless Window[lightgray] (may require restart)
setting.fps.name = Show FPS
setting.blockselectkeys.name = Show Block Select Keys
setting.borderlesswindow.name = Borderless Window[lightgray] (vaatii uudelleenkäynnistyksen)
setting.fps.name = Näytä FPS
setting.blockselectkeys.name = Bäytä Palikan Selektio Kontrollit
setting.vsync.name = VSync
setting.pixelate.name = Pixelate[lightgray] (disables animations)
setting.minimap.name = Show Minimap
setting.position.name = Show Player Position
setting.musicvol.name = Music Volume
setting.ambientvol.name = Ambient Volume
setting.mutemusic.name = Mute Music
setting.sfxvol.name = SFX Volume
setting.mutesound.name = Mute Sound
setting.pixelate.name = Pixeloi[lightgray] (poistaa animaation käytöstä)
setting.minimap.name = Näytä Minimappi
setting.position.name = Näytä pelaajan sijainti
setting.musicvol.name = Musiikin Äänenvoimakkuus
setting.ambientvol.name = Tausta Äänet
setting.mutemusic.name = Sulje Musiikki
setting.sfxvol.name = SFX Volyymi
setting.mutesound.name = Sulje Äänet
setting.crashreport.name = Send Anonymous Crash Reports
setting.savecreate.name = Auto-Create Saves
setting.savecreate.name = Luo Automaattisesti Tallennukset
setting.publichost.name = Public Game Visibility
setting.chatopacity.name = Chat Opacity
setting.lasersopacity.name = Power Laser Opacity
setting.playerchat.name = Display In-Game Chat
setting.chatopacity.name = Chatin Läpinäkymättömyys
setting.lasersopacity.name = Energia Laaserin Läpinäkymattämyys
setting.playerchat.name = Näytä Pelinsisäinen Keskustelu
public.confirm = Do you want to make your game public?\n[accent]Anyone will be able to join your games.\n[lightgray]This can be changed later in Settings->Game->Public Game Visibility.
public.beta = Note that beta versions of the game cannot make public lobbies.
uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] seconds...
uiscale.cancel = Cancel & Exit
uiscale.cancel = Peruuta ja Poistu
setting.bloom.name = Bloom
keybind.title = Rebind Keys
keybinds.mobile = [scarlet]Most keybinds here are not functional on mobile. Only basic movement is supported.
category.general.name = General
category.view.name = View
category.multiplayer.name = Multiplayer
command.attack = Attack
command.rally = Rally
command.retreat = Retreat
command.attack = Hyökkää
command.rally = Kutsu Koolle
command.retreat = Palaa
placement.blockselectkeys = \n[lightgray]Key: [{0},
keybind.clear_building.name = Clear Building
keybind.press = Press a key...
@@ -692,7 +692,7 @@ keybind.move_y.name = Move y
keybind.mouse_move.name = Follow Mouse
keybind.dash.name = Dash
keybind.schematic_select.name = Select Region
keybind.schematic_menu.name = Schematic Menu
keybind.schematic_menu.name = Kaavio Valikko
keybind.schematic_flip_x.name = Flip Schematic X
keybind.schematic_flip_y.name = Flip Schematic Y
keybind.category_prev.name = Previous Category
@@ -711,7 +711,7 @@ keybind.block_select_07.name = Category/Block Select 7
keybind.block_select_08.name = Category/Block Select 8
keybind.block_select_09.name = Category/Block Select 9
keybind.block_select_10.name = Category/Block Select 10
keybind.fullscreen.name = Toggle Fullscreen
keybind.fullscreen.name = Vaihda Fullscreen
keybind.select.name = Select/Shoot
keybind.diagonal_placement.name = Diagonal Placement
keybind.pick.name = Pick Block
@@ -722,8 +722,8 @@ keybind.zoom.name = Zoom
keybind.menu.name = Menu
keybind.pause.name = Pause
keybind.pause_building.name = Pause/Resume Building
keybind.minimap.name = Minimap
keybind.chat.name = Chat
keybind.minimap.name = Minimappi
keybind.chat.name = Chatti
keybind.player_list.name = Player list
keybind.console.name = Console
keybind.rotate.name = Rotate
@@ -736,20 +736,20 @@ keybind.drop_unit.name = Drop Unit
keybind.zoom_minimap.name = Zoom minimap
mode.help.title = Description of modes
mode.survival.name = Survival
mode.survival.description = The normal mode. Limited resources and automatic incoming waves.\n[gray]Requires enemy spawns in the map to play.
mode.sandbox.name = Sandbox
mode.sandbox.description = Infinite resources and no timer for waves.
mode.editor.name = Editor
mode.survival.description = Normaali moodi. Rajoitettu määrä resursseja ja tasoilla on aika.\n[gray]Vaatii vihollis spawneja kartassa.
mode.sandbox.name = Hiekkalaatikko
mode.sandbox.description = Ikuisesti resursseja ja tasoilla ei ole aikaa.
mode.editor.name = Editori
mode.pvp.name = PvP
mode.pvp.description = Fight against other players locally.\n[gray]Requires at least 2 differently-colored cores in the map to play.
mode.attack.name = Attack
mode.attack.description = Destroy the enemy's base. No waves.\n[gray]Requires a red core in the map to play.
mode.custom = Custom Rules
rules.infiniteresources = Infinite Resources
rules.reactorexplosions = Reactor Explosions
rules.wavetimer = Wave Timer
rules.waves = Waves
rules.infiniteresources = Ikuisesti Resursseja
rules.reactorexplosions = Reaktori Räjähdykset
rules.wavetimer = Tasojen Aikaraja
rules.waves = Tasot
rules.attack = Attack Mode
rules.enemyCheat = Infinite AI (Red Team) Resources
rules.unitdrops = Unit Drops
@@ -778,31 +778,31 @@ rules.title.experimental = Experimental
rules.lighting = Lighting
rules.ambientlight = Ambient Light
content.item.name = Items
content.liquid.name = Liquids
content.unit.name = Units
content.block.name = Blocks
content.mech.name = Mechs
item.copper.name = Copper
item.lead.name = Lead
item.coal.name = Coal
item.graphite.name = Graphite
item.titanium.name = Titanium
item.thorium.name = Thorium
item.silicon.name = Silicon
item.plastanium.name = Plastanium
item.phase-fabric.name = Phase Fabric
item.surge-alloy.name = Surge Alloy
item.spore-pod.name = Spore Pod
content.item.name = Tavarat
content.liquid.name = Nesteet
content.unit.name = Yksiköt
content.block.name = Palikat
content.mech.name = Yksikkö
item.copper.name = Kupari
item.lead.name = Lyijy
item.coal.name = Hiili
item.graphite.name = Grafiitti
item.titanium.name = Titaani
item.thorium.name = Torium
item.silicon.name = Pii
item.plastanium.name = Plastaniumi
item.phase-fabric.name = Kiihde Kuitu
item.surge-alloy.name = Taite Seos
item.spore-pod.name = Itiö Palko
item.sand.name = Hiekka
item.blast-compound.name = Blast Compound
item.pyratite.name = Pyratite
item.metaglass.name = Metaglass
item.scrap.name = Scrap
item.blast-compound.name = Räjähde Yhdiste
item.pyratite.name = Pyratiitti
item.metaglass.name = Metallilasi
item.scrap.name = Romu
liquid.water.name = Vesi
liquid.slag.name = Slag
liquid.oil.name = Oil
liquid.cryofluid.name = Cryofluid
liquid.slag.name = Kuona
liquid.oil.name = Öljy
liquid.cryofluid.name = Kryoneste
mech.alpha-mech.name = Alpha
mech.alpha-mech.weapon = Heavy Repeater
mech.alpha-mech.ability = Regeneration
@@ -824,22 +824,22 @@ mech.trident-ship.name = Trident
mech.trident-ship.weapon = Bomb Bay
mech.glaive-ship.name = Glaive
mech.glaive-ship.weapon = Flame Repeater
item.corestorable = [lightgray]Storable in Core: {0}
item.explosiveness = [lightgray]Explosiveness: {0}%
item.corestorable = [lightgray]Säilöttävissä Ytimeen: {0}
item.explosiveness = [lightgray]Räjädysmäisyys: {0}%
item.flammability = [lightgray]Flammability: {0}%
item.radioactivity = [lightgray]Radioactivity: {0}%
unit.health = [lightgray]Health: {0}
unit.speed = [lightgray]Speed: {0}
mech.weapon = [lightgray]Weapon: {0}
mech.health = [lightgray]Health: {0}
mech.itemcapacity = [lightgray]Item Capacity: {0}
mech.minespeed = [lightgray]Mining Speed: {0}%
mech.minepower = [lightgray]Mining Power: {0}
mech.ability = [lightgray]Ability: {0}
mech.buildspeed = [lightgray]Building Speed: {0}%
liquid.heatcapacity = [lightgray]Heat Capacity: {0}
liquid.viscosity = [lightgray]Viscosity: {0}
liquid.temperature = [lightgray]Temperature: {0}
unit.health = [lightgray]Elämäpisteet: {0}
unit.speed = [lightgray]Nopeus: {0}
mech.weapon = [lightgray]Ase: {0}
mech.health = [lightgray]Elämäpisteet: {0}
mech.itemcapacity = [lightgray]Tavara Kapasiteetti: {0}
mech.minespeed = [lightgray]Louhimis Nopeus: {0}%
mech.minepower = [lightgray]Louhimis Voima: {0}
mech.ability = [lightgray]Spesiaalikyky: {0}
mech.buildspeed = [lightgray]Rakennus Nopeus: {0}%
liquid.heatcapacity = [lightgray]Lämpö Kapasiteetti: {0}
liquid.viscosity = [lightgray]Tahmeus: {0}
liquid.temperature = [lightgray]Lämpö: {0}
block.sand-boulder.name = Sand Boulder
block.grass.name = Grass
@@ -865,24 +865,24 @@ block.scrap-wall-huge.name = Huge Scrap Wall
block.scrap-wall-gigantic.name = Gigantic Scrap Wall
block.thruster.name = Thruster
block.kiln.name = Kiln
block.graphite-press.name = Graphite Press
block.multi-press.name = Multi-Press
block.constructing = {0} [lightgray](Constructing)
block.spawn.name = Enemy Spawn
block.core-shard.name = Core: Shard
block.core-foundation.name = Core: Foundation
block.core-nucleus.name = Core: Nucleus
block.deepwater.name = Deep Water
block.water.name = Water
block.tainted-water.name = Tainted Water
block.graphite-press.name = Grafiitti Puristin
block.multi-press.name = Multi-Puristin
block.constructing = {0} [lightgray](Rakentamassa)
block.spawn.name = Vihollis Spawni
block.core-shard.name = Ydin: Siru
block.core-foundation.name = Ydin: Pohjaus
block.core-nucleus.name = Ydin: Tuma
block.deepwater.name = Syvä Vesi
block.water.name = Vesi
block.tainted-water.name = Pilattu Vesi
block.darksand-tainted-water.name = Dark Sand Tainted Water
block.tar.name = Tar
block.stone.name = Stone
block.sand.name = Sand
block.darksand.name = Dark Sand
block.ice.name = Ice
block.snow.name = Snow
block.craters.name = Craters
block.tar.name = Terva
block.stone.name = Kivi
block.sand.name = Hiekka
block.darksand.name = Tumma Hiekka
block.ice.name = Jää
block.snow.name = Lumi
block.craters.name = Kraatterit
block.sand-water.name = Sand water
block.darksand-water.name = Dark Sand Water
block.char.name = Char

View File

@@ -40,7 +40,7 @@ schematic = Schematica
schematic.add = Salva Schematica...
schematics = Schematiche
schematic.replace = Una schematica con questo nome esiste già. Sostituirla?
schematic.import = Importa schematica...
schematic.import = Importa schematica
schematic.exportfile = Esporta File
schematic.importfile = Importa File
schematic.browseworkshop = Naviga nel Workshop
@@ -79,7 +79,7 @@ newgame = Nuova partita
none = <niente>
minimap = Minimappa
position = Posizione
close = Chiuso
close = Chiudi
website = Sito Web
quit = Esci
save.quit = Salva ed Esci
@@ -138,7 +138,7 @@ research.list = [lightgray]Ricerca:
research = Ricerca
researched = [lightgray]{0} cercati.
players = {0} giocatori online
players.single = {0} giocatori online
players.single = {0} giocatore online
server.closing = [accent]Chiusura server...
server.kicked.kick = Sei stato cacciato dal server!
server.kicked.whitelist = Non sei presente nella whitelist.
@@ -157,7 +157,7 @@ server.kicked.customClient = Questo server non supporta i client personalizzati.
server.kicked.gameover = Game over!
server.kicked.serverRestarting = Il server si sta riavviando.
server.versions = Versione client:[accent] {0}[]\nVersione server:[accent] {1}[]
host.info = Il pulsante [accent]Ospita[] ospita un server sulla porta [scarlet]6567[].[] Chiunque sulla stessa [lightgray]rete Wi-Fi o locale[] dovrebbe essere in grado di vedere il server nell'elenco server.\nSe vuoi che le persone siano in grado di connettersi ovunque tramite il tuo IP, è richiesto il [accent]port forwarding[].\n\n[lightgray]Nota: se qualcuno sta riscontrando problemi durante la connessione al gioco LAN, assicurati di aver consentito a Mindustry di accedere alla rete locale nelle impostazioni del firewall.
host.info = Il pulsante [accent]Ospita[] ospita un server sulla porta [scarlet]6567[].[] Chiunque sulla stessa [lightgray]rete Wi-Fi o locale[] dovrebbe essere in grado di vedere il server nell'elenco server.\nSe vuoi che le persone siano in grado di connettersi ovunque tramite il tuo IP, è necessario eseguire il [accent]port forwarding[].\n\n[lightgray]Nota: se qualcuno sta riscontrando problemi durante la connessione al gioco LAN, assicurati di aver consentito a Mindustry di accedere alla rete locale nelle impostazioni del firewall.
join.info = Qui è possibile inserire l'[accent]IP del server[] a cui connettersi, o scoprire [accent]un server sulla rete locale[] disponibile.\nSono supportati sia il multiplayer LAN che WAN.\n\n[lightgray]Nota: non esiste un elenco automatico dei server globali; se desideri connetterti a qualcuno tramite il suo IP, è necessario chiedere all'host il proprio IP.
hostserver = Ospita Server
invitefriends = Invita Amici
@@ -264,7 +264,7 @@ reloading = [accent]Ricaricamento delle mods...
saving = [accent]Salvataggio in corso...
cancelbuilding = [accent][[{0}][] per pulire la selezione
selectschematic = [accent][[{0}][] per selezionare+copiare
pausebuilding = [accent][[{0}][] to pause building
pausebuilding = [accent][[{0}][] per smettere di costruire
resumebuilding = [scarlet][[{0}][] per riprendere a costruire
wave = [accent]Ondata {0}
wave.waiting = [lightgray]Ondata tra {0}
@@ -532,6 +532,8 @@ error.crashtitle = Si è verificato un errore
blocks.input = Ingresso
blocks.output = Uscita
blocks.booster = Potenziamenti
blocks.tiles = Blocchi Richiesti
blocks.affinities = Affinità
block.unknown = [lightgray]???
blocks.powercapacity = Capacità Energetica
blocks.powershot = Danno/Colpo
@@ -934,7 +936,6 @@ block.lancer.name = Lanciere
block.conveyor.name = Nastro Trasportatore
block.titanium-conveyor.name = Nastro Avanzato
block.armored-conveyor.name = Nastro Corazzato
block.armored-conveyor.description = Trasporta gli oggetti alla stessa velocità del nastro avanzato, ma è più resistente. Accetta input dai lati solo da altri nastri.
block.junction.name = Incrocio
block.router.name = Distributore
block.distributor.name = Distributore Grande
@@ -1140,12 +1141,12 @@ block.spore-press.description = Comprime le spore in petrolio.
block.pulverizer.description = Polverizza la pietra.\nUtile quando manca la sabbia naturale.
block.coal-centrifuge.description = Solidifica il petrolio in pezzi di carbone.
block.incinerator.description = Elimina qualsiasi oggetto o liquido in eccesso.
block.power-void.description = Elimina tutta l'energia che riceve, esiste solo nella modalità creativa.
block.power-source.description = Produce energia infinita, esiste solo nella modalità creativa.
block.item-source.description = Produce oggetti infiniti, esiste solo nella modalità creativa.
block.item-void.description = Elimina gli oggetti che vi entrano senza bisogno di energia, esiste solo nella modalità creativa.
block.power-void.description = Elimina tutta l'energia che riceve. Esiste solo nella modalità creativa.
block.power-source.description = Produce energia infinita. Esiste solo nella modalità creativa.
block.item-source.description = Produce oggetti infiniti. Esiste solo nella modalità creativa.
block.item-void.description = Elimina gli oggetti che vi entrano senza bisogno di energia. Esiste solo nella modalità creativa.
block.liquid-source.description = Emette continuamente liquidi. Esiste solo nella modalità creativa.
block.liquid-void.description = Elimina i liquidi in entrata, esiste solo nella modalità creativa.
block.liquid-void.description = Elimina i liquidi in entrata. Esiste solo nella modalità creativa.
block.copper-wall.description = Un blocco difensivo economico.\nUtile per proteggere il Nucleo e le torrette nelle prime ondate.
block.copper-wall-large.description = Un blocco difensivo economico.\nUtile per proteggere il Nucleo e le torrette nelle prime ondate.\nOccupa più blocchi.
block.titanium-wall.description = Un blocco difensivo moderatamente forte.\nFornisce una protezione moderata dai nemici.
@@ -1165,18 +1166,19 @@ block.mend-projector.description = Ripara periodicamente blocchi nelle vicinanze
block.overdrive-projector.description = Aumenta la velocità di edifici vicini come trivelle e nastri trasportatori.
block.force-projector.description = Crea un campo di forza esagonale attorno a sé, proteggendo gli edifici e le unità all'interno da danni causati da proiettili.
block.shock-mine.description = Danneggia i nemici che la calpestano. Quasi invisibile al nemico.
block.conveyor.description = Nastro di base. Sposta gli oggetti in avanti e li deposita automaticamente in altri blocchi. Ruotabile.
block.conveyor.description = Nastro di base. Sposta gli oggetti in avanti e li deposita automaticamente in altri blocchi. È rotabile.
block.titanium-conveyor.description = Nastro avanzato. Sposta gli oggetti più velocemente dei nastri standard.
block.armored-conveyor.description = Trasporta gli oggetti alla stessa velocità del nastro avanzato, ma è più resistente. Accetta input dai lati solo da altri nastri.
block.junction.description = Permette di incrociare nastri che trasportano materiali diversi in posizioni diverse.
block.bridge-conveyor.description = Consente il trasporto di oggetti fino a 3 blocchi ad un altro nastro sopraelevato.\nPuò passare sopra ad altri blocchi od edifici.
block.phase-conveyor.description = Nastro avanzato. Consuma energia per teletrasportare gli oggetti su un altro nastro di fase collegato.
block.sorter.description = Divide gli oggetti. Se l'oggetto corrisponde a quello selezionato, Può passare. Altrimenti viene espulso sui lati.
block.inverted-sorter.description = Elabora gli oggetti come uno smistatore standard, ma in uscita dà gli elementi selezionati ai lati.
block.inverted-sorter.description = Elabora gli oggetti come uno filtro standard, ma in uscita dà gli elementi selezionati ai lati.
block.router.description = Accetta gli elementi da una direzione e li emette fino a 3 altre direzioni allo stesso modo. Utile per suddividere i materiali da una fonte a più destinazioni.
block.distributor.description = Un distributore avanzato che divide gli oggetti in altre 7 direzioni allo stesso modo.
block.overflow-gate.description = Distribuisce gli oggetti ai lati se il nastro davanti a sé è saturo.
block.underflow-gate.description = L'opposto di un separatore per eccesso. Distribuisce gli oggetti nel nastro davanti a sé se i nastri a destra e a sinistra sono saturi.
block.mass-driver.description = Ultimo blocco di trasporto di oggetti. Raccoglie diversi oggetti e poi li spara su un'altra lancia materiali a lungo raggio.
block.mass-driver.description = Ultimo blocco di trasporto di oggetti. Raccoglie diversi oggetti e poi li spara su un'altra lancia materiali a lungo raggio.
block.mechanical-pump.description = Una pompa economica a bassa efficienza, ma nessun consumo di energia.
block.rotary-pump.description = Una pompa avanzata che raddoppia la velocità consumando energia.
block.thermal-pump.description = La pompa migliore. Tre volte più veloce di una pompa meccanica e l'unica pompa in grado di recuperare la lava.

View File

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

View File

@@ -1,4 +1,4 @@
apply plugin: "java"
sourceCompatibility = 1.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;
bullet = new BombBulletType(2f, 3f, "clear"){{
hitEffect = Fx.pulverize;
lifetime = 2f;
lifetime = 30f;
speed = 1.1f;
splashDamageRadius = 55f;
instantDisappear = true;
splashDamage = 30f;
killShooter = true;
}};
@@ -126,7 +127,6 @@ public class UnitTypes implements ContentList{
shootSound = Sounds.flame;
length = 1f;
reload = 14f;
range = 30f;
alternate = true;
recoil = 1f;
ejectEffect = Fx.none;

View File

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

View File

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

View File

@@ -289,6 +289,19 @@ public class UI implements ApplicationListener, Loadable{
Core.scene.add(table);
}
public void showInfoToast(String info, float duration){
Table table = new Table();
table.setFillParent(true);
table.update(() -> {
if(state.is(State.menu)){
table.remove();
}
});
table.actions(Actions.delay(duration * 0.9f), Actions.fadeOut(duration * 0.1f, Interpolation.fade), Actions.remove());
table.top().table(Styles.black3, t -> t.margin(4).add(info).style(Styles.outlineLabel)).padTop(10);
Core.scene.add(table);
}
public void showInfo(String info){
new Dialog(""){{
getCell(cont).growX();
@@ -426,7 +439,6 @@ public class UI implements ApplicationListener, Loadable{
dialog.show();
}
public void showCustomConfirm(String title, String text, String yes, String no, Runnable confirmed, Runnable denied){
FloatingDialog dialog = new FloatingDialog(title);
dialog.cont.add(text).width(mobile ? 400f : 500f).wrap().pad(4f).get().setAlignment(Align.center, Align.center);
@@ -459,11 +471,11 @@ public class UI implements ApplicationListener, Loadable{
public String formatAmount(int number){
if(number >= 1000000){
return Strings.fixed(number / 1000000f, 1) + "[gray]" + Core.bundle.getOrNull("unit.millions") + "[]";
return Strings.fixed(number / 1000000f, 1) + "[gray]" + Core.bundle.get("unit.millions") + "[]";
}else if(number >= 10000){
return number / 1000 + "[gray]k[]";
return number / 1000 + "[gray]" + Core.bundle.get("unit.thousands") + "[]";
}else if(number >= 1000){
return Strings.fixed(number / 1000f, 1) + "[gray]" + Core.bundle.getOrNull("unit.thousands") + "[]";
return Strings.fixed(number / 1000f, 1) + "[gray]" + Core.bundle.get("unit.thousands") + "[]";
}else{
return number + "";
}

View File

@@ -1,6 +1,7 @@
package mindustry.ctype;
import arc.*;
import arc.util.ArcAnnotate.*;
import mindustry.annotations.Annotations.*;
import arc.graphics.g2d.*;
import arc.scene.ui.layout.*;
@@ -13,7 +14,7 @@ public abstract class UnlockableContent extends MappableContent{
/** Localized, formal name. Never null. Set to block name if not found in bundle. */
public String localizedName;
/** Localized description. May be null. */
public String description;
public @Nullable String description;
/** Icons by Cicon ID.*/
protected TextureRegion[] cicons = new TextureRegion[mindustry.ui.Cicon.all.length];
@@ -24,6 +25,10 @@ public abstract class UnlockableContent extends MappableContent{
this.description = Core.bundle.getOrNull(getContentType() + "." + this.name + ".description");
}
public String displayDescription(){
return minfo.mod == null ? description : description + "\n" + Core.bundle.format("mod.display", minfo.mod.meta.displayName());
}
/** Generate any special icons for this content. Called asynchronously.*/
@CallSuper
public void createIcons(MultiPacker packer){

View File

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

View File

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

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

View File

@@ -12,7 +12,7 @@ import org.mozilla.javascript.*;
public class Scripts implements Disposable{
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",
".awt", "socket", "mod.scripts", "classloader", "oracle");
".awt", "socket", "classloader", "oracle");
private final Array<String> whitelist = Array.with("mindustry.net");
private final Context context;
private final String wrapper;

View File

@@ -28,7 +28,7 @@ public class ContentDisplay{
table.row();
if(block.description != null){
table.add(block.description).padLeft(5).padRight(5).width(400f).wrap().fillX();
table.add(block.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX();
table.row();
table.addImage().height(3).color(Color.lightGray).pad(8).padLeft(0).padRight(0).fillX();
@@ -76,7 +76,7 @@ public class ContentDisplay{
table.row();
if(item.description != null){
table.add(item.description).padLeft(5).padRight(5).width(400f).wrap().fillX();
table.add(item.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX();
table.row();
table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX();
@@ -110,7 +110,7 @@ public class ContentDisplay{
table.row();
if(liquid.description != null){
table.add(liquid.description).padLeft(5).padRight(5).width(400f).wrap().fillX();
table.add(liquid.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX();
table.row();
table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX();
@@ -145,7 +145,7 @@ public class ContentDisplay{
table.row();
if(mech.description != null){
table.add(mech.description).padLeft(5).padRight(5).width(400f).wrap().fillX();
table.add(mech.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX();
table.row();
table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX();
@@ -192,7 +192,7 @@ public class ContentDisplay{
table.row();
if(unit.description != null){
table.add(unit.description).padLeft(5).padRight(5).width(400f).wrap().fillX();
table.add(unit.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX();
table.row();
table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX();

View File

@@ -377,7 +377,7 @@ public class TechTreeDialog extends FloatingDialog{
infoTable.row();
if(node.block.description != null){
infoTable.table(t -> t.margin(3f).left().labelWrap(node.block.description).color(Color.lightGray).growX()).fillX();
infoTable.table(t -> t.margin(3f).left().labelWrap(node.block.displayDescription()).color(Color.lightGray).growX()).fillX();
}
addChild(infoTable);

View File

@@ -171,7 +171,7 @@ public class MenuFragment extends Fragment{
new Buttoni("$loadgame", Icon.download, () -> checkPlay(ui.load::show)),
new Buttoni("$tutorial", Icon.info, () -> checkPlay(control::playTutorial))
),
new Buttoni("$editor", Icon.terrain, () -> checkPlay(ui.maps::show)), steam ? new Buttoni("$workshop", Icon.save, platform::openWorkshop) : null,
new Buttoni("$editor", Icon.terrain, () -> checkPlay(ui.maps::show)), steam ? new Buttoni("$workshop", Icon.book, platform::openWorkshop) : null,
new Buttoni(Core.bundle.get("mods"), Icon.bookOpen, ui.mods::show),
//not enough space for this button
//new Buttoni("$schematics", Icon.paste, ui.schematics::show),

View File

@@ -192,6 +192,11 @@ public class MassDriver extends Block{
MassDriverEntity entity = tile.ent();
for(Tile shooter : entity.waitingShooters){
Drawf.circles(shooter.drawx(), shooter.drawy(), (tile.block().size / 2f + 1) * tilesize + sin - 2f, Pal.place);
Drawf.arrow(shooter.drawx(), shooter.drawy(), tile.drawx(), tile.drawy(), size * tilesize + sin, 4f + sin, Pal.place);
}
if(linkValid(tile)){
Tile target = world.tile(entity.link);
Drawf.circles(target.drawx(), target.drawy(), (target.block().size / 2f + 1) * tilesize + sin - 2f, Pal.place);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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]
[list]
[*] Crie brocas e correntes transportadoras para mover recursos para o seu Núcleo.
[*] Crie brocas e esteiras transportadoras para mover recursos para o seu Núcleo.
[*] Use blocos de produção para criar materiais avançados.
[*] Construa drones para minerar recursos automaticamente, ajudar na construção e proteger a sua base.
[*] Distribua líquidos e enfrente surtos de fogo.

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.registerClientCommands(netServer.clientCommands));
}
private void readCommands(){