Merge branches 'master' and 'mech-rework' of https://github.com/Anuken/Mindustry into mech-rework

# Conflicts:
#	android/src/mindustry/android/AndroidLauncher.java
#	annotations/src/main/java/mindustry/annotations/SerializeAnnotationProcessor.java
#	annotations/src/main/java/mindustry/annotations/impl/AssetsAnnotationProcessor.java
#	build.gradle
#	core/assets-raw/fontgen/config.json
#	core/assets/bundles/bundle_cs.properties
#	core/assets/bundles/bundle_it.properties
#	core/assets/fonts/font.ttf
#	core/assets/fonts/icon.ttf
#	core/assets/icons/icons.properties
#	core/assets/sprites/block_colors.png
#	core/assets/sprites/sprites.atlas
#	core/assets/sprites/sprites.png
#	core/assets/sprites/sprites3.png
#	core/assets/sprites/sprites5.png
#	core/src/mindustry/content/UnitTypes.java
#	core/src/mindustry/core/NetClient.java
#	core/src/mindustry/core/NetServer.java
#	core/src/mindustry/entities/bullet/BulletType.java
#	core/src/mindustry/entities/type/TileEntity.java
#	core/src/mindustry/maps/filters/FilterOption.java
#	core/src/mindustry/mod/Scripts.java
#	core/src/mindustry/ui/Fonts.java
#	core/src/mindustry/ui/dialogs/DeployDialog.java
#	core/src/mindustry/ui/fragments/HudFragment.java
#	core/src/mindustry/ui/fragments/MenuFragment.java
#	core/src/mindustry/world/blocks/production/Cultivator.java
#	core/src/mindustry/world/blocks/units/CommandCenter.java
#	gradle.properties
#	tools/src/mindustry/tools/FontGenerator.java
This commit is contained in:
Anuken
2020-01-27 15:51:02 -05:00
144 changed files with 4577 additions and 3085 deletions

1
.gitignore vendored
View File

@@ -30,6 +30,7 @@ steam_appid.txt
/android/assets/mindustry-maps/ /android/assets/mindustry-maps/
/android/assets/mindustry-saves/ /android/assets/mindustry-saves/
/core/assets/gifexport/ /core/assets/gifexport/
/annotations/src/main/resources/META-INF/services
/core/assets/version.properties /core/assets/version.properties
/core/assets/locales /core/assets/locales
/ios/src/mindustry/gen/ /ios/src/mindustry/gen/

25
SERVERLIST.md Normal file
View File

@@ -0,0 +1,25 @@
### Adding a server to the list
Mindustry now has a public list of servers that everyone can see and connect to.
This is done by letting clients `GET` a [JSON list of servers](https://github.com/Anuken/Mindustry/blob/master/servers.json) in this repository.
You may want to add your server to this list. The steps for getting this done are as follows:
1. **Ensure your server is properly moderated.** For the most part, this applies to survival servers, but PvP servers can be affected as well.
You'll need to either hire some moderators, or make use of (currently non-existent) anti-grief and anti-curse plugins.
*Consider enabling a rate limit:* `config messageRateLimit 2` will make it so that players can only send messages every 2 seconds, for example.
2. **Set an approppriate MOTD, name and description.** This is set with `config <name/desc/motd> <value>`. "Approppriate" means that:
- Your name or description must reflect the type of server you're hosting.
Since new players may be exposed to the server list early on, put in a phrase like "Co-op survival" or "PvP" so players know what they're getting into. Yes, this is also displayed in the server mode info text, but having extra info in the name doesn't hurt.
- Make sure players know where to refer to for server support. It should be fairly clear that the server owner is not me, but you.
- Try to be professional in your text; use common sense.
3. **Get some good maps** *(optional, but highly recommended)*. Add some maps to your server and set the map rotation to custom-only. You can get maps from the Steam workshop by subscribing and exporting them; using the `#maps` channel on Discord is also an option.
4. Finally, **submit a pull request** to add your server's IP to the list.
This should be fairly straightforward: Press the edit button on the [server file](https://github.com/Anuken/Mindustry/blob/master/servers.json), then add a JSON object with a single key, indicating your server address.
For example, if your server address is `google.com`, you would add a comma after the last entry and insert:
```json
{
"address": "google.com"
}
```
Then, press the *'submit pull request'* button and I'll take a look at your server. If I have any issues with it, I'll let you know in the PR comments.

View File

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

View File

@@ -0,0 +1,60 @@
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)
public abstract class BaseProcessor extends AbstractProcessor{
/** Name of the base package to put all the generated classes. */
public static final String packageName = "mindustry.gen";
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);
typeu = processingEnv.getTypeUtils();
elementu = processingEnv.getElementUtils();
filer = processingEnv.getFiler();
messager = processingEnv.getMessager();
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
if(round++ != 0) return false; //only process 1 round
try{
process(roundEnv);
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
return true;
}
@Override
public SourceVersion getSupportedSourceVersion(){
return SourceVersion.RELEASE_8;
}
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,131 +0,0 @@
package mindustry.annotations;
import com.squareup.javapoet.*;
import mindustry.annotations.Annotations.*;
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.*;
import java.util.zip.*;
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("mindustry.annotations.Annotations.Serialize")
public class SerializeAnnotationProcessor extends AbstractProcessor{
/** Target class name. */
private static final String className = "Serialization";
/** Name of the base package to put all the generated classes. */
private static final String packageName = "mindustry.gen";
private static final String data = "eJztV0tvGzcQvvfQ3zDRIeDCKhsbQVDUsgP5UViH2IHl9BIEBsUdSYxX3C3Jlawm+XH9Z53hUg/bkuOmOfRQwfDuDme++ebBWe6PfwU3/wTwUU2VLJQdSYfDAnWQvxkschjCAUyMzWtPetJikF2nzzG8deXU5OjkW6VvMPTRGVWYP0mgC+W9HGE4Qbp1mEcg0Zo5E9C1sn2AofQYulqj92ZQoAiuxqVc2Loo2iCU03JYWy2PS+v3OndJNF7bDW1rSnk0D3hUD4foDjNRtWGQwU+HQIGZoajAWB+U1VgOYROOZx+Wgm4eMzJ7ghpoyo14Cl5FsQ2I4PsPcE2/XXpssk7kOMw6mEJe9KXxXZu70uTM4Jjz2Hl9CJ79xCc5LN25mqBoqUZPVosy9DEEY0eebnTtMKZ5iaDddgRd2oA2MGO+XqIvi2mq0xJAqQ0ARHzA8dncywWar91QaZwanMkUS7eqCqNVMKW9x+qRuO6wug3R8GGLvsEwLnMYMZBS6z3XrIgWidYhLgYfyQ50IyKrkZbGTssbjHU4Lh1KVVWbvaUNEf8fUFXYX+rt7vnJ5UXv5Lp3Et30g6NagDK55RZpHrNoyUaxwx+PyA+XLtZCaYBabSpoOzlptttX0uM8oen7aJsqnhLkkixmyPlFjlLe1kL0a/ER6YVis4UXKO2YCbYyNkCBnBQv6ToKY5Gt9kauAveZxVkjYc2fYe8DT4bSCTY2tP5iny4dxuGbnQPY4+3Cxu9N1GdODJAJcTxWTmmaOzI3IxOEl5ok3SBM1obdVxl0OvAyA9iB7Zq0uNtoM9cvy9gpvLoIiXAjW+1mnwZi7Ht5pDy+enlc8k5Fq+kqmG8EpBnQIEn8o1aFp25a/C66B60sgzB25Sx6uaxtMBM8vdVYMbBoHakc3r3rnchYvjhdiBGDM1csPD4cMr3Sc8ZSGHVtuJ+X/e8Xk2TZcKLFOtR2rVYizM8EdDqpwlxkDJZKeCcnUfYLl4+f2MFEhbG8pE0uMhqXt4Gntk/hM3Ti8k0JTSgM8zCWqg7LKPiyWcurKYr1PDaYi0x+Wi08gVaOkdYT85paa+Enbubo4NTWE3QRvtO87eg1Qy/gWeluerQd47w9BCRSsHWdfd6XebGcGptMoKw58Dhe4IwrXJYFKkspEKnYfImdRB0R7+GAasezjRIXamdhSP2M+1/rjv7cB5xI5Zya67KaN2BteNFOFvE2CtPUYObJxbN/1Sxb9hw8f/7dgbsMnKoMcAbjlIezWAcecJRxkmHcGacFTmg48xrLuYBnyuUzerl185y8UPkW6YbPn+HZWFJhtmlmMSKUY+XfUC8m8NgBG52uDeXrVFnYhv3Py3u9sb7X9wu8eMUE9x1GArUoAW0rNyVw42r3WwfwanDQHx1+9FhcMYii4y6E/6fvf3T6UiaZLA3BtXO9Zvvf0Xn2MahNEfmv1unr42peYe9Cxk+chD6gU5qcNla8/GQbSwfhJyvXvslmpC2oxOXAUIe9TgegXfgVXizXOSxN4RSlW9nEnK4eGzsGolO9pw+6xXC6d/pa0yDBzs7db6ZHGEczPgSbO+88qBpVMYjSbH/Trgn0vUM8+oE+O67otMbt8uWHvwGqGwCj";
private int round;
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
if(round++ != 0) return false; //only process 1 round
try{
Set<TypeElement> elements = ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(Serialize.class));
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC);
classBuilder.addStaticBlock(CodeBlock.of(new DataInputStream(new InflaterInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(data)))).readUTF()));
classBuilder.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "\"unchecked\"").build());
classBuilder.addJavadoc(RemoteMethodAnnotationProcessor.autogenWarning);
MethodSpec.Builder method = MethodSpec.methodBuilder("init").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
for(TypeElement elem : elements){
TypeName type = TypeName.get(elem.asType());
String simpleTypeName = type.toString().substring(type.toString().lastIndexOf('.') + 1);
TypeSpec.Builder serializer = TypeSpec.anonymousClassBuilder("")
.addSuperinterface(ParameterizedTypeName.get(
ClassName.bestGuess("arc.Settings.TypeSerializer"), type));
MethodSpec.Builder writeMethod = MethodSpec.methodBuilder("write")
.returns(void.class)
.addParameter(DataOutput.class, "stream")
.addParameter(type, "object")
.addException(IOException.class)
.addModifiers(Modifier.PUBLIC);
MethodSpec.Builder readMethod = MethodSpec.methodBuilder("read")
.returns(type)
.addParameter(DataInput.class, "stream")
.addException(IOException.class)
.addModifiers(Modifier.PUBLIC);
readMethod.addStatement("$L object = new $L()", type, type);
List<VariableElement> fields = ElementFilter.fieldsIn(Utils.elementUtils.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 capName = Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1);
if(field.asType().getKind().isPrimitive()){
writeMethod.addStatement("stream.write" + capName + "(object." + name + ")");
readMethod.addStatement("object." + name + "= stream.read" + capName + "()");
}else{
writeMethod.addStatement("arc.Core.settings.getSerializer(" + typeName + ".class).write(stream, object." + name + ")");
readMethod.addStatement("object." + name + " = (" + typeName + ")arc.Core.settings.getSerializer(" + typeName + ".class).read(stream)");
}
}
readMethod.addStatement("return object");
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());
name(writeMethod, "write" + simpleTypeName);
name(readMethod, "read" + simpleTypeName);
writeMethod.addModifiers(Modifier.STATIC);
readMethod.addModifiers(Modifier.STATIC);
classBuilder.addMethod(writeMethod.build());
classBuilder.addMethod(readMethod.build());
}
classBuilder.addMethod(method.build());
//write result
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(Utils.filer);
return true;
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
}
@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();
}
static void name(MethodSpec.Builder builder, String name){
try{
Field field = builder.getClass().getDeclaredField("name");
field.setAccessible(true);
field.set(builder, name);
}catch(Exception e){
throw new RuntimeException(e);
}
}
}

View File

@@ -1,226 +0,0 @@
package mindustry.annotations;
import com.squareup.javapoet.*;
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;
import javax.tools.Diagnostic.Kind;
import java.util.List;
import java.util.Set;
/**
* Generates ""value types"" classes that are packed into integer primitives of the most aproppriate size.
* It would be nice if Java didn't make crazy hacks like this necessary.
*/
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes({
"mindustry.annotations.Annotations.Struct"
})
public class StructAnnotationProcessor extends AbstractProcessor{
/** Name of the base package to put all the generated classes. */
private static final String packageName = "mindustry.gen";
private int round;
@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++ != 0) return false; //only process 1 round
try{
Set<TypeElement> elements = ElementFilter.typesIn(roundEnv.getElementsAnnotatedWith(Struct.class));
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);
continue;
}
String structName = elem.getSimpleName().toString().substring(0, elem.getSimpleName().toString().length() - "Struct".length());
String structParam = structName.toLowerCase();
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(structName)
.addModifiers(Modifier.FINAL, Modifier.PUBLIC);
try{
List<VariableElement> variables = ElementFilter.fieldsIn(elem.getEnclosedElements());
int structSize = variables.stream().mapToInt(StructAnnotationProcessor::varSize).sum();
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);
continue;
}
//obtain type which will be stored
Class<?> structType = typeForSize(structSize);
//[constructor] get(fields...) : structType
MethodSpec.Builder constructor = MethodSpec.methodBuilder("get")
.addModifiers(Modifier.STATIC, Modifier.PUBLIC)
.returns(structType);
StringBuilder cons = new StringBuilder();
StringBuilder doc = new StringBuilder();
doc.append("Bits used: ").append(structSize).append(" / ").append(structTotalSize).append("\n");
int offset = 0;
for(VariableElement var : variables){
int size = varSize(var);
TypeName varType = TypeName.get(var.asType());
String varName = var.getSimpleName().toString();
//add val param to constructor
constructor.addParameter(varType, varName);
//[get] field(structType) : fieldType
MethodSpec.Builder getter = MethodSpec.methodBuilder(var.getSimpleName().toString())
.addModifiers(Modifier.STATIC, Modifier.PUBLIC)
.returns(varType)
.addParameter(structType, structParam);
//[set] field(structType, fieldType) : structType
MethodSpec.Builder setter = MethodSpec.methodBuilder(var.getSimpleName().toString())
.addModifiers(Modifier.STATIC, Modifier.PUBLIC)
.returns(structType)
.addParameter(structType, structParam).addParameter(varType, "value");
//[getter]
if(varType == TypeName.BOOLEAN){
//bools: single bit, is simplified
getter.addStatement("return ($L & (1L << $L)) != 0", structParam, offset);
}else if(varType == TypeName.FLOAT){
//floats: need conversion
getter.addStatement("return Float.intBitsToFloat((int)(($L >>> $L) & $L))", structParam, offset, bitString(size, structTotalSize));
}else{
//bytes, shorts, chars, ints
getter.addStatement("return ($T)(($L >>> $L) & $L)", varType, structParam, offset, bitString(size, structTotalSize));
}
//[setter] + [constructor building]
if(varType == TypeName.BOOLEAN){
cons.append(" | (").append(varName).append(" ? ").append("1L << ").append(offset).append("L : 0)");
//bools: single bit, needs special case to clear things
setter.beginControlFlow("if(value)");
setter.addStatement("return ($T)(($L & ~(1L << $LL)))", structType, structParam, offset);
setter.nextControlFlow("else");
setter.addStatement("return ($T)(($L & ~(1L << $LL)) | (1L << $LL))", structType, structParam, offset, offset);
setter.endControlFlow();
}else if(varType == TypeName.FLOAT){
cons.append(" | (").append("(").append(structType).append(")").append("Float.floatToIntBits(").append(varName).append(") << ").append(offset).append("L)");
//floats: need conversion
setter.addStatement("return ($T)(($L & $L) | (($T)Float.floatToIntBits(value) << $LL))", structType, structParam, bitString(offset, size, structTotalSize), structType, offset);
}else{
cons.append(" | (((").append(structType).append(")").append(varName).append(" << ").append(offset).append("L)").append(" & ").append(bitString(offset, size, structTotalSize)).append(")");
//bytes, shorts, chars, ints
setter.addStatement("return ($T)(($L & $L) | (($T)value << $LL))", structType, structParam, bitString(offset, size, structTotalSize), structType, offset);
}
doc.append("<br> ").append(varName).append(" [").append(offset).append("..").append(size + offset).append("]\n");
//add finished methods
classBuilder.addMethod(getter.build());
classBuilder.addMethod(setter.build());
offset += size;
}
classBuilder.addJavadoc(doc.toString());
//add constructor final statement + add to class and build
constructor.addStatement("return ($T)($L)", structType, cons.toString().substring(3));
classBuilder.addMethod(constructor.build());
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(Utils.filer);
}catch(IllegalArgumentException e){
e.printStackTrace();
Utils.messager.printMessage(Kind.ERROR, e.getMessage(), elem);
}
}
return true;
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
}
static String bitString(int offset, int size, int totalSize){
StringBuilder builder = new StringBuilder();
for(int i = 0; i < offset; i++) builder.append('0');
for(int i = 0; i < size; i++) builder.append('1');
for(int i = 0; i < totalSize - size - offset; i++) builder.append('0');
return "0b" + builder.reverse().toString() + "L";
}
static String bitString(int size, int totalSize){
StringBuilder builder = new StringBuilder();
for(int i = 0; i < size; i++) builder.append('1');
for(int i = 0; i < totalSize - size; i++) builder.append('0');
return "0b" + builder.reverse().toString() + "L";
}
static int varSize(VariableElement var) throws IllegalArgumentException{
if(!var.asType().getKind().isPrimitive()){
throw new IllegalArgumentException("All struct fields must be primitives: " + var);
}
StructField an = var.getAnnotation(StructField.class);
if(var.asType().getKind() == TypeKind.BOOLEAN && an != null && an.value() != 1){
throw new IllegalArgumentException("Booleans can only be one bit long... why would you do this?");
}
if(var.asType().getKind() == TypeKind.FLOAT && an != null && an.value() != 32){
throw new IllegalArgumentException("Float size can't be changed. Very sad.");
}
return an == null ? typeSize(var.asType().getKind()) : an.value();
}
static Class<?> typeForSize(int size) throws IllegalArgumentException{
if(size <= 8){
return byte.class;
}else if(size <= 16){
return short.class;
}else if(size <= 32){
return int.class;
}else if(size <= 64){
return long.class;
}
throw new IllegalArgumentException("Too many fields, must fit in 64 bits. Curent size: " + size);
}
/** returns a type's element size in bits. */
static int typeSize(TypeKind kind) throws IllegalArgumentException{
switch(kind){
case BOOLEAN:
return 1;
case BYTE:
return 8;
case SHORT:
return 16;
case FLOAT:
case CHAR:
case INT:
return 32;
default:
throw new IllegalArgumentException("Invalid type kind: " + kind + ". Note that doubles and longs are not supported.");
}
}
}

View File

@@ -1,24 +0,0 @@
package mindustry.annotations;
import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
public class Utils{
public static Types typeUtils;
public static Elements elementUtils;
public static Filer filer;
public static Messager messager;
public static String getMethodName(Element element){
return ((TypeElement)element.getEnclosingElement()).getQualifiedName().toString() + "." + element.getSimpleName();
}
public static boolean isPrimitive(String type){
return type.equals("boolean") || type.equals("byte") || type.equals("short") || type.equals("int")
|| type.equals("long") || type.equals("float") || type.equals("double") || type.equals("char");
}
}

View File

@@ -1,10 +1,11 @@
package mindustry.annotations; package mindustry.annotations.impl;
import arc.files.*; import arc.files.*;
import arc.scene.style.*; import arc.scene.style.*;
import arc.struct.*; import arc.struct.*;
import arc.util.serialization.*; import arc.util.serialization.*;
import com.squareup.javapoet.*; import com.squareup.javapoet.*;
import mindustry.annotations.*;
import mindustry.annotations.Annotations.*; import mindustry.annotations.Annotations.*;
import javax.annotation.processing.*; import javax.annotation.processing.*;
@@ -14,43 +15,20 @@ import javax.tools.Diagnostic.*;
import javax.tools.*; import javax.tools.*;
import java.util.*; import java.util.*;
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("mindustry.annotations.Annotations.StyleDefaults") @SupportedAnnotationTypes("mindustry.annotations.Annotations.StyleDefaults")
public class AssetsAnnotationProcessor extends AbstractProcessor{ public class AssetsAnnotationProcessor extends BaseProcessor{
/** Name of the base package to put all the generated classes. */
private static final String packageName = "mindustry.gen";
private String path; private String path;
private int round;
@Override @Override
public synchronized void init(ProcessingEnvironment processingEnv){ public void process(RoundEnvironment env) throws Exception{
super.init(processingEnv); path = Fi.get(BaseProcessor.filer.createResource(StandardLocation.CLASS_OUTPUT, "no", "no")
//put all relevant utils into utils class .toUri().toURL().toString().substring(System.getProperty("os.name").contains("Windows") ? 6 : "file:".length()))
Utils.typeUtils = processingEnv.getTypeUtils(); .parent().parent().parent().parent().parent().parent().toString();
Utils.elementUtils = processingEnv.getElementUtils(); path = path.replace("%20", " ");
Utils.filer = processingEnv.getFiler();
Utils.messager = processingEnv.getMessager();
}
@Override processSounds("Sounds", path + "/assets/sounds", "arc.audio.Sound");
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){ processSounds("Musics", path + "/assets/music", "arc.audio.Music");
if(round++ != 0) return false; //only process 1 round processUI(env.getElementsAnnotatedWith(StyleDefaults.class));
try{
path = Fi.get(Utils.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", " ");
processSounds("Sounds", path + "/assets/sounds", "arc.audio.Sound");
processSounds("Musics", path + "/assets/music", "arc.audio.Music");
processUI(roundEnv.getElementsAnnotatedWith(StyleDefaults.class));
return true;
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
} }
void processUI(Set<? extends Element> elements) throws Exception{ void processUI(Set<? extends Element> elements) throws Exception{
@@ -71,17 +49,18 @@ public class AssetsAnnotationProcessor extends AbstractProcessor{
int code = val.getInt("code", 0); int code = val.getInt("code", 0);
ichtype.addField(FieldSpec.builder(char.class, name, Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).initializer("(char)" + code).build()); ichtype.addField(FieldSpec.builder(char.class, name, Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).initializer("(char)" + code).build());
ictype.addField(TextureRegionDrawable.class, name + "Sm", Modifier.PUBLIC, Modifier.STATIC); ictype.addField(TextureRegionDrawable.class, name + "Small", Modifier.PUBLIC, Modifier.STATIC);
icload.addStatement(name + "Sm = mindustry.ui.Fonts.getGlyph(mindustry.ui.Fonts.def, (char)" + code + ")"); icload.addStatement(name + "Small = mindustry.ui.Fonts.getGlyph(mindustry.ui.Fonts.def, (char)" + code + ")");
ictype.addField(TextureRegionDrawable.class, name, Modifier.PUBLIC, Modifier.STATIC); ictype.addField(TextureRegionDrawable.class, name, Modifier.PUBLIC, Modifier.STATIC);
icload.addStatement(name + " = mindustry.ui.Fonts.getGlyph(mindustry.ui.Fonts.icon, (char)" + code + ")"); icload.addStatement(name + " = mindustry.ui.Fonts.getGlyph(mindustry.ui.Fonts.icon, (char)" + code + ")");
icload.addStatement("icons.put($S, " + name + ")", name); icload.addStatement("icons.put($S, " + name + ")", name);
icload.addStatement("icons.put($S, " + name + "Small)", name + "Small");
} }
Fi.get(resources).walk(p -> { Fi.get(resources).walk(p -> {
if(p.nameWithoutExtension().equals(".DS_Store")) return; if(!p.extEquals("png")) return;
String filename = p.name(); String filename = p.name();
filename = filename.substring(0, filename.indexOf(".")); filename = filename.substring(0, filename.indexOf("."));
@@ -107,12 +86,12 @@ public class AssetsAnnotationProcessor extends AbstractProcessor{
} }
ictype.addMethod(icload.build()); ictype.addMethod(icload.build());
JavaFile.builder(packageName, ichtype.build()).build().writeTo(Utils.filer); JavaFile.builder(packageName, ichtype.build()).build().writeTo(BaseProcessor.filer);
JavaFile.builder(packageName, ictype.build()).build().writeTo(Utils.filer); JavaFile.builder(packageName, ictype.build()).build().writeTo(BaseProcessor.filer);
type.addMethod(load.build()); type.addMethod(load.build());
type.addMethod(loadStyles.build()); type.addMethod(loadStyles.build());
JavaFile.builder(packageName, type.build()).build().writeTo(Utils.filer); JavaFile.builder(packageName, type.build()).build().writeTo(BaseProcessor.filer);
} }
void processSounds(String classname, String path, String rtype) throws Exception{ void processSounds(String classname, String path, String rtype) throws Exception{
@@ -126,7 +105,7 @@ public class AssetsAnnotationProcessor extends AbstractProcessor{
String name = p.nameWithoutExtension(); String name = p.nameWithoutExtension();
if(names.contains(name)){ if(names.contains(name)){
Utils.messager.printMessage(Kind.ERROR, "Duplicate file name: " + p.toString() + "!"); BaseProcessor.messager.printMessage(Kind.ERROR, "Duplicate file name: " + p.toString() + "!");
}else{ }else{
names.add(name); names.add(name);
} }
@@ -152,7 +131,7 @@ public class AssetsAnnotationProcessor extends AbstractProcessor{
type.addMethod(loadBegin.build()); type.addMethod(loadBegin.build());
type.addMethod(dispose.build()); type.addMethod(dispose.build());
JavaFile.builder(packageName, type.build()).build().writeTo(Utils.filer); JavaFile.builder(packageName, type.build()).build().writeTo(BaseProcessor.filer);
} }
static String capitalize(String s){ static String capitalize(String s){

View File

@@ -0,0 +1,150 @@
package mindustry.annotations.impl;
import com.sun.source.tree.*;
import com.sun.source.util.*;
import com.sun.tools.javac.code.Scope;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.tree.JCTree.*;
import mindustry.annotations.Annotations.*;
import javax.annotation.processing.*;
import javax.lang.model.*;
import javax.lang.model.element.*;
import javax.tools.Diagnostic.*;
import java.lang.annotation.*;
import java.util.*;
@SupportedAnnotationTypes({"java.lang.Override"})
public class CallSuperAnnotationProcessor extends AbstractProcessor{
private Trees trees;
@Override
public void init(ProcessingEnvironment pe){
super.init(pe);
trees = Trees.instance(pe);
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
for(Element e : roundEnv.getElementsAnnotatedWith(Override.class)){
if(e.getAnnotation(OverrideCallSuper.class) != null) return false;
CodeAnalyzerTreeScanner codeScanner = new CodeAnalyzerTreeScanner();
codeScanner.methodName = e.getSimpleName().toString();
TreePath tp = trees.getPath(e.getEnclosingElement());
codeScanner.scan(tp, trees);
if(codeScanner.callSuperUsed){
List list = codeScanner.method.getBody().getStatements();
if(!doesCallSuper(list, codeScanner.methodName)){
processingEnv.getMessager().printMessage(Kind.ERROR, "Overriding method '" + codeScanner.methodName + "' must explicitly call super method from its parent class.", e);
}
}
}
return false;
}
private boolean doesCallSuper(List list, String methodName){
for(Object object : list){
if(object instanceof JCTree.JCExpressionStatement){
JCTree.JCExpressionStatement expr = (JCExpressionStatement)object;
String exprString = expr.toString();
if(exprString.startsWith("super." + methodName) && exprString.endsWith(");")) return true;
}
}
return false;
}
@Override
public SourceVersion getSupportedSourceVersion(){
return SourceVersion.RELEASE_8;
}
static class CodeAnalyzerTreeScanner extends TreePathScanner<Object, Trees>{
private String methodName;
private MethodTree method;
private boolean callSuperUsed;
@Override
public Object visitClass(ClassTree classTree, Trees trees){
Tree extendTree = classTree.getExtendsClause();
if(extendTree instanceof JCTypeApply){ //generic classes case
JCTypeApply generic = (JCTypeApply)extendTree;
extendTree = generic.clazz;
}
if(extendTree instanceof JCIdent){
JCIdent tree = (JCIdent)extendTree;
com.sun.tools.javac.code.Scope members = tree.sym.members();
if(checkScope(members))
return super.visitClass(classTree, trees);
if(checkSuperTypes((ClassType)tree.type))
return super.visitClass(classTree, trees);
}
callSuperUsed = false;
return super.visitClass(classTree, trees);
}
public boolean checkSuperTypes(ClassType type){
if(type.supertype_field != null && type.supertype_field.tsym != null){
if(checkScope(type.supertype_field.tsym.members()))
return true;
else
return checkSuperTypes((ClassType)type.supertype_field);
}
return false;
}
@SuppressWarnings("unchecked")
public boolean checkScope(Scope members){
Iterable<Symbol> it;
try{
it = (Iterable<Symbol>)members.getClass().getMethod("getElements").invoke(members);
}catch(Throwable t){
try{
it = (Iterable<Symbol>)members.getClass().getMethod("getSymbols").invoke(members);
}catch(Exception e){
throw new RuntimeException(e);
}
}
for(Symbol s : it){
if(s instanceof MethodSymbol){
MethodSymbol ms = (MethodSymbol)s;
if(ms.getSimpleName().toString().equals(methodName)){
Annotation annotation = ms.getAnnotation(CallSuper.class);
if(annotation != null){
callSuperUsed = true;
return true;
}
}
}
}
return false;
}
@Override
public Object visitMethod(MethodTree methodTree, Trees trees){
if(methodTree.getName().toString().equals(methodName))
method = methodTree;
return super.visitMethod(methodTree, trees);
}
}
}

View File

@@ -0,0 +1,108 @@
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.element.Modifier;
import javax.lang.model.element.*;
import javax.lang.model.util.*;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.zip.*;
@SupportedAnnotationTypes("mindustry.annotations.Annotations.Serialize")
public class SerializeAnnotationProcessor extends BaseProcessor{
/** Target class name. */
private static final String className = "Serialization";
/** Name of the base package to put all the generated classes. */
private static final String data = "eJztV0tvGzcQvvfQ3zDRIeDCKhsbQVDUsgP5UViH2IHl9BIEBsUdSYxX3C3Jlawm+XH9Z53hUg/bkuOmOfRQwfDuDme++ebBWe6PfwU3/wTwUU2VLJQdSYfDAnWQvxkschjCAUyMzWtPetJikF2nzzG8deXU5OjkW6VvMPTRGVWYP0mgC+W9HGE4Qbp1mEcg0Zo5E9C1sn2AofQYulqj92ZQoAiuxqVc2Loo2iCU03JYWy2PS+v3OndJNF7bDW1rSnk0D3hUD4foDjNRtWGQwU+HQIGZoajAWB+U1VgOYROOZx+Wgm4eMzJ7ghpoyo14Cl5FsQ2I4PsPcE2/XXpssk7kOMw6mEJe9KXxXZu70uTM4Jjz2Hl9CJ79xCc5LN25mqBoqUZPVosy9DEEY0eebnTtMKZ5iaDddgRd2oA2MGO+XqIvi2mq0xJAqQ0ARHzA8dncywWar91QaZwanMkUS7eqCqNVMKW9x+qRuO6wug3R8GGLvsEwLnMYMZBS6z3XrIgWidYhLgYfyQ50IyKrkZbGTssbjHU4Lh1KVVWbvaUNEf8fUFXYX+rt7vnJ5UXv5Lp3Et30g6NagDK55RZpHrNoyUaxwx+PyA+XLtZCaYBabSpoOzlptttX0uM8oen7aJsqnhLkkixmyPlFjlLe1kL0a/ER6YVis4UXKO2YCbYyNkCBnBQv6ToKY5Gt9kauAveZxVkjYc2fYe8DT4bSCTY2tP5iny4dxuGbnQPY4+3Cxu9N1GdODJAJcTxWTmmaOzI3IxOEl5ok3SBM1obdVxl0OvAyA9iB7Zq0uNtoM9cvy9gpvLoIiXAjW+1mnwZi7Ht5pDy+enlc8k5Fq+kqmG8EpBnQIEn8o1aFp25a/C66B60sgzB25Sx6uaxtMBM8vdVYMbBoHakc3r3rnchYvjhdiBGDM1csPD4cMr3Sc8ZSGHVtuJ+X/e8Xk2TZcKLFOtR2rVYizM8EdDqpwlxkDJZKeCcnUfYLl4+f2MFEhbG8pE0uMhqXt4Gntk/hM3Ti8k0JTSgM8zCWqg7LKPiyWcurKYr1PDaYi0x+Wi08gVaOkdYT85paa+Enbubo4NTWE3QRvtO87eg1Qy/gWeluerQd47w9BCRSsHWdfd6XebGcGptMoKw58Dhe4IwrXJYFKkspEKnYfImdRB0R7+GAasezjRIXamdhSP2M+1/rjv7cB5xI5Zya67KaN2BteNFOFvE2CtPUYObJxbN/1Sxb9hw8f/7dgbsMnKoMcAbjlIezWAcecJRxkmHcGacFTmg48xrLuYBnyuUzerl185y8UPkW6YbPn+HZWFJhtmlmMSKUY+XfUC8m8NgBG52uDeXrVFnYhv3Py3u9sb7X9wu8eMUE9x1GArUoAW0rNyVw42r3WwfwanDQHx1+9FhcMYii4y6E/6fvf3T6UiaZLA3BtXO9Zvvf0Xn2MahNEfmv1unr42peYe9Cxk+chD6gU5qcNla8/GQbSwfhJyvXvslmpC2oxOXAUIe9TgegXfgVXizXOSxN4RSlW9nEnK4eGzsGolO9pw+6xXC6d/pa0yDBzs7db6ZHGEczPgSbO+88qBpVMYjSbH/Trgn0vUM8+oE+O67otMbt8uWHvwGqGwCj";
@Override
public void process(RoundEnvironment env) throws Exception{
Set<TypeElement> elements = ElementFilter.typesIn(env.getElementsAnnotatedWith(Serialize.class));
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC);
classBuilder.addStaticBlock(CodeBlock.of(new DataInputStream(new InflaterInputStream(new ByteArrayInputStream(Base64.getDecoder().decode(data)))).readUTF()));
classBuilder.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "\"unchecked\"").build());
classBuilder.addJavadoc(RemoteMethodAnnotationProcessor.autogenWarning);
MethodSpec.Builder method = MethodSpec.methodBuilder("init").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
for(TypeElement elem : elements){
TypeName type = TypeName.get(elem.asType());
String simpleTypeName = type.toString().substring(type.toString().lastIndexOf('.') + 1);
TypeSpec.Builder serializer = TypeSpec.anonymousClassBuilder("")
.addSuperinterface(ParameterizedTypeName.get(
ClassName.bestGuess("arc.Settings.TypeSerializer"), type));
MethodSpec.Builder writeMethod = MethodSpec.methodBuilder("write")
.returns(void.class)
.addParameter(DataOutput.class, "stream")
.addParameter(type, "object")
.addException(IOException.class)
.addModifiers(Modifier.PUBLIC);
MethodSpec.Builder readMethod = MethodSpec.methodBuilder("read")
.returns(type)
.addParameter(DataInput.class, "stream")
.addException(IOException.class)
.addModifiers(Modifier.PUBLIC);
readMethod.addStatement("$L object = new $L()", type, type);
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 = BaseProcessor.typeu.erasure(field.asType()).toString().replace('$', '.');
String capName = Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1);
if(field.asType().getKind().isPrimitive()){
writeMethod.addStatement("stream.write" + capName + "(object." + name + ")");
readMethod.addStatement("object." + name + "= stream.read" + capName + "()");
}else{
writeMethod.addStatement("arc.Core.settings.getSerializer(" + typeName + ".class).write(stream, object." + name + ")");
readMethod.addStatement("object." + name + " = (" + typeName + ")arc.Core.settings.getSerializer(" + typeName + ".class).read(stream)");
}
}
readMethod.addStatement("return object");
serializer.addMethod(writeMethod.build());
serializer.addMethod(readMethod.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);
writeMethod.addModifiers(Modifier.STATIC);
readMethod.addModifiers(Modifier.STATIC);
classBuilder.addMethod(writeMethod.build());
classBuilder.addMethod(readMethod.build());
}
classBuilder.addMethod(method.build());
//write result
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(BaseProcessor.filer);
}
static void name(MethodSpec.Builder builder, String name){
try{
Field field = builder.getClass().getDeclaredField("name");
field.setAccessible(true);
field.set(builder, name);
}catch(Exception e){
throw new RuntimeException(e);
}
}
}

View File

@@ -0,0 +1,204 @@
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.element.*;
import javax.lang.model.type.TypeKind;
import javax.lang.model.util.ElementFilter;
import javax.tools.Diagnostic.Kind;
import java.util.List;
import java.util.Set;
/**
* Generates ""value types"" classes that are packed into integer primitives of the most aproppriate size.
* It would be nice if Java didn't make crazy hacks like this necessary.
*/
@SupportedAnnotationTypes({
"mindustry.annotations.Annotations.Struct"
})
public class StructAnnotationProcessor extends BaseProcessor{
@Override
public void process(RoundEnvironment env) throws Exception{
Set<TypeElement> elements = ElementFilter.typesIn(env.getElementsAnnotatedWith(Struct.class));
for(TypeElement elem : elements){
if(!elem.getSimpleName().toString().endsWith("Struct")){
BaseProcessor.messager.printMessage(Kind.ERROR, "All classes annotated with @Struct must have their class names end in 'Struct'.", elem);
continue;
}
String structName = elem.getSimpleName().toString().substring(0, elem.getSimpleName().toString().length() - "Struct".length());
String structParam = structName.toLowerCase();
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(structName)
.addModifiers(Modifier.FINAL, Modifier.PUBLIC);
try{
List<VariableElement> variables = ElementFilter.fieldsIn(elem.getEnclosedElements());
int structSize = variables.stream().mapToInt(StructAnnotationProcessor::varSize).sum();
int structTotalSize = (structSize <= 8 ? 8 : structSize <= 16 ? 16 : structSize <= 32 ? 32 : 64);
if(variables.size() == 0){
BaseProcessor.messager.printMessage(Kind.ERROR, "making a struct with no fields is utterly pointles.", elem);
continue;
}
//obtain type which will be stored
Class<?> structType = typeForSize(structSize);
//[constructor] get(fields...) : structType
MethodSpec.Builder constructor = MethodSpec.methodBuilder("get")
.addModifiers(Modifier.STATIC, Modifier.PUBLIC)
.returns(structType);
StringBuilder cons = new StringBuilder();
StringBuilder doc = new StringBuilder();
doc.append("Bits used: ").append(structSize).append(" / ").append(structTotalSize).append("\n");
int offset = 0;
for(VariableElement var : variables){
int size = varSize(var);
TypeName varType = TypeName.get(var.asType());
String varName = var.getSimpleName().toString();
//add val param to constructor
constructor.addParameter(varType, varName);
//[get] field(structType) : fieldType
MethodSpec.Builder getter = MethodSpec.methodBuilder(var.getSimpleName().toString())
.addModifiers(Modifier.STATIC, Modifier.PUBLIC)
.returns(varType)
.addParameter(structType, structParam);
//[set] field(structType, fieldType) : structType
MethodSpec.Builder setter = MethodSpec.methodBuilder(var.getSimpleName().toString())
.addModifiers(Modifier.STATIC, Modifier.PUBLIC)
.returns(structType)
.addParameter(structType, structParam).addParameter(varType, "value");
//[getter]
if(varType == TypeName.BOOLEAN){
//bools: single bit, is simplified
getter.addStatement("return ($L & (1L << $L)) != 0", structParam, offset);
}else if(varType == TypeName.FLOAT){
//floats: need conversion
getter.addStatement("return Float.intBitsToFloat((int)(($L >>> $L) & $L))", structParam, offset, bitString(size, structTotalSize));
}else{
//bytes, shorts, chars, ints
getter.addStatement("return ($T)(($L >>> $L) & $L)", varType, structParam, offset, bitString(size, structTotalSize));
}
//[setter] + [constructor building]
if(varType == TypeName.BOOLEAN){
cons.append(" | (").append(varName).append(" ? ").append("1L << ").append(offset).append("L : 0)");
//bools: single bit, needs special case to clear things
setter.beginControlFlow("if(value)");
setter.addStatement("return ($T)(($L & ~(1L << $LL)))", structType, structParam, offset);
setter.nextControlFlow("else");
setter.addStatement("return ($T)(($L & ~(1L << $LL)) | (1L << $LL))", structType, structParam, offset, offset);
setter.endControlFlow();
}else if(varType == TypeName.FLOAT){
cons.append(" | (").append("(").append(structType).append(")").append("Float.floatToIntBits(").append(varName).append(") << ").append(offset).append("L)");
//floats: need conversion
setter.addStatement("return ($T)(($L & $L) | (($T)Float.floatToIntBits(value) << $LL))", structType, structParam, bitString(offset, size, structTotalSize), structType, offset);
}else{
cons.append(" | (((").append(structType).append(")").append(varName).append(" << ").append(offset).append("L)").append(" & ").append(bitString(offset, size, structTotalSize)).append(")");
//bytes, shorts, chars, ints
setter.addStatement("return ($T)(($L & $L) | (($T)value << $LL))", structType, structParam, bitString(offset, size, structTotalSize), structType, offset);
}
doc.append("<br> ").append(varName).append(" [").append(offset).append("..").append(size + offset).append("]\n");
//add finished methods
classBuilder.addMethod(getter.build());
classBuilder.addMethod(setter.build());
offset += size;
}
classBuilder.addJavadoc(doc.toString());
//add constructor final statement + add to class and build
constructor.addStatement("return ($T)($L)", structType, cons.toString().substring(3));
classBuilder.addMethod(constructor.build());
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(BaseProcessor.filer);
}catch(IllegalArgumentException e){
e.printStackTrace();
BaseProcessor.messager.printMessage(Kind.ERROR, e.getMessage(), elem);
}
}
}
static String bitString(int offset, int size, int totalSize){
StringBuilder builder = new StringBuilder();
for(int i = 0; i < offset; i++) builder.append('0');
for(int i = 0; i < size; i++) builder.append('1');
for(int i = 0; i < totalSize - size - offset; i++) builder.append('0');
return "0b" + builder.reverse().toString() + "L";
}
static String bitString(int size, int totalSize){
StringBuilder builder = new StringBuilder();
for(int i = 0; i < size; i++) builder.append('1');
for(int i = 0; i < totalSize - size; i++) builder.append('0');
return "0b" + builder.reverse().toString() + "L";
}
static int varSize(VariableElement var) throws IllegalArgumentException{
if(!var.asType().getKind().isPrimitive()){
throw new IllegalArgumentException("All struct fields must be primitives: " + var);
}
StructField an = var.getAnnotation(StructField.class);
if(var.asType().getKind() == TypeKind.BOOLEAN && an != null && an.value() != 1){
throw new IllegalArgumentException("Booleans can only be one bit long... why would you do this?");
}
if(var.asType().getKind() == TypeKind.FLOAT && an != null && an.value() != 32){
throw new IllegalArgumentException("Float size can't be changed. Very sad.");
}
return an == null ? typeSize(var.asType().getKind()) : an.value();
}
static Class<?> typeForSize(int size) throws IllegalArgumentException{
if(size <= 8){
return byte.class;
}else if(size <= 16){
return short.class;
}else if(size <= 32){
return int.class;
}else if(size <= 64){
return long.class;
}
throw new IllegalArgumentException("Too many fields, must fit in 64 bits. Curent size: " + size);
}
/** returns a type's element size in bits. */
static int typeSize(TypeKind kind) throws IllegalArgumentException{
switch(kind){
case BOOLEAN:
return 1;
case BYTE:
return 8;
case SHORT:
return 16;
case FLOAT:
case CHAR:
case INT:
return 32;
default:
throw new IllegalArgumentException("Invalid type kind: " + kind + ". Note that doubles and longs are not supported.");
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -164,12 +164,6 @@
"code": 59414, "code": 59414,
"src": "typicons" "src": "typicons"
}, },
{
"uid": "b90868gfogj970a1g0dnot6hm5r4uj55",
"css": "chat",
"code": 59415,
"src": "typicons"
},
{ {
"uid": "890649841b2c37d56ff90065872fecf3", "uid": "890649841b2c37d56ff90065872fecf3",
"css": "chart-bar", "css": "chart-bar",
@@ -182,12 +176,6 @@
"code": 59418, "code": 59418,
"src": "typicons" "src": "typicons"
}, },
{
"uid": "bczb7qup4axmc490xmuuv8qdhcnbgeyf",
"css": "user",
"code": 59420,
"src": "typicons"
},
{ {
"uid": "4109c474ff99cad28fd5a2c38af2ec6f", "uid": "4109c474ff99cad28fd5a2c38af2ec6f",
"css": "filter", "css": "filter",
@@ -296,12 +284,6 @@
"code": 59439, "code": 59439,
"src": "typicons" "src": "typicons"
}, },
{
"uid": "e45e9f27ce40ba9837cc984076d98067",
"css": "zoom",
"code": 59441,
"src": "elusive"
},
{ {
"uid": "0e26e70b4aa537cc206f41b21dcf2fcc", "uid": "0e26e70b4aa537cc206f41b21dcf2fcc",
"css": "lock", "css": "lock",
@@ -819,6 +801,124 @@
"search": [ "search": [
"pencil" "pencil"
] ]
},
{
"uid": "346f9aef245e0c2ded44e31ad7c66acb",
"css": "mode-pvp",
"code": 59477,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M305.8 0C296.1 0 286.4 1.6 276.7 4.9 257.3 11.3 244.3 24.3 237.9 43.7 231.4 63.1 231.4 82.5 237.9 101.9 244.3 121.4 254 137.5 267 150.5L305.8 189.3 344.7 228.2 383.5 267C396.4 279.9 409.4 286.4 422.3 286.4 435.3 286.4 448.2 279.9 461.2 267L500 228.2C512.9 215.2 519.4 202.3 519.4 189.3 519.4 176.4 512.9 163.4 500 150.5L461.2 111.7 422.3 72.8 383.5 34C370.6 21 354.4 11.3 335 4.9 325.2 1.6 315.5 0 305.8 0ZM927.2 0C917.5 0 907.8 1.6 898.1 4.9 878.6 11.3 862.5 21 849.5 34L810.7 72.8 771.8 111.7 733 150.5 694.2 189.3 655.3 228.2 616.5 267 577.7 305.8 538.8 344.7 500 383.5 461.2 422.3 422.3 461.2 383.5 500C370.6 512.9 354.4 522.7 335 529.1 315.5 535.6 296.1 535.6 276.7 529.1 257.3 522.7 241.1 512.9 228.2 500 215.2 487.1 199 477.3 179.6 470.9 160.2 464.4 140.8 464.4 121.4 470.9 101.9 477.3 89 490.3 82.5 509.7 76.1 529.1 76.1 548.5 82.5 568 89 587.4 98.7 603.6 111.7 616.5 124.6 629.5 134.3 645.6 140.8 665 147.2 684.5 147.2 703.9 140.8 723.3 134.3 742.7 124.6 758.9 111.7 771.8L72.8 810.7 34 849.5C21 862.5 11.3 878.6 4.9 898.1-1.6 917.5-1.6 936.9 4.9 956.3 11.3 975.7 24.3 988.7 43.7 995.1 63.1 1001.6 82.5 1001.6 101.9 995.1 121.4 988.7 137.5 979 150.5 966L189.3 927.2 228.2 888.3C241.1 875.4 257.3 865.7 276.7 859.2 296.1 852.8 315.5 852.8 335 859.2 354.4 865.7 370.6 875.4 383.5 888.3 396.4 901.3 412.6 911 432 917.5 451.5 923.9 470.9 923.9 490.3 917.5 509.7 911 522.7 898.1 529.1 878.6 535.6 859.2 535.6 839.8 529.1 820.4 522.7 801 512.9 784.8 500 771.8 487.1 758.9 477.3 742.7 470.9 723.3 464.4 703.9 464.4 684.5 470.9 665 477.3 645.6 487.1 629.5 500 616.5L538.8 577.7 577.7 538.8 616.5 500 655.3 461.2 694.2 422.3 733 383.5 771.8 344.7 810.7 305.8 849.5 267 888.3 228.2 927.2 189.3 966 150.5C979 137.5 988.7 121.4 995.1 101.9 1001.6 82.5 1001.6 63.1 995.1 43.7 988.7 24.3 975.7 11.3 956.3 4.9 946.6 1.6 936.9 0 927.2 0ZM1082.5 466C1072.8 466 1063.1 467.6 1053.4 470.9 1034 477.3 1017.8 487.1 1004.9 500 991.9 512.9 975.7 522.7 956.3 529.1 936.9 535.6 917.5 535.6 898.1 529.1 878.6 522.7 862.5 512.9 849.5 500 836.6 487.1 823.6 480.6 810.7 480.6 797.7 480.6 784.8 487.1 771.8 500L733 538.8C720.1 551.8 713.6 564.7 713.6 577.7 713.6 590.6 720.1 603.6 733 616.5 746 629.5 755.7 645.6 762.1 665 768.6 684.5 768.6 703.9 762.1 723.3 755.7 742.7 746 758.9 733 771.8 720.1 784.8 710.4 801 703.9 820.4 697.4 839.8 697.4 859.2 703.9 878.6 710.4 898.1 723.3 911 742.7 917.5 762.1 923.9 781.6 923.9 801 917.5 820.4 911 836.6 901.3 849.5 888.3 862.5 875.4 878.6 865.7 898.1 859.2 917.5 852.8 936.9 852.8 956.3 859.2 975.7 865.7 991.9 875.4 1004.9 888.3L1043.7 927.2 1082.5 966C1095.5 979 1111.7 988.7 1131.1 995.1 1150.5 1001.6 1169.9 1001.6 1189.3 995.1 1208.7 988.7 1221.7 975.7 1228.2 956.3 1234.6 936.9 1234.6 917.5 1228.2 898.1 1221.7 878.6 1212 862.5 1199 849.5L1160.2 810.7 1121.4 771.8C1108.4 758.9 1098.7 742.7 1092.2 723.3 1085.8 703.9 1085.8 684.5 1092.2 665 1098.7 645.6 1108.4 629.5 1121.4 616.5 1134.3 603.6 1144 587.4 1150.5 568 1157 548.5 1157 529.1 1150.5 509.7 1144 490.3 1131.1 477.3 1111.7 470.9 1101.9 467.6 1092.2 466 1082.5 466Z",
"width": 1233
},
"search": [
"mode-pvp"
]
},
{
"uid": "8d74cd519427de451b48df6554aaf593",
"css": "mode-attack",
"code": 59478,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M849.5 34Q868.9 14.6 898.1 4.9 927.2-4.9 956.3 4.9 985.4 14.6 995.1 43.7 1004.9 72.8 995.1 101.9 985.4 131.1 966 150.5 946.6 169.9 927.2 189.3 907.8 208.7 888.3 228.2 868.9 247.6 849.5 267 830.1 286.4 810.7 305.8 791.3 325.2 771.8 344.7 752.4 364.1 733 383.5 713.6 402.9 694.2 422.3 674.8 441.7 655.3 461.2 635.9 480.6 616.5 500 597.1 519.4 577.7 538.8 558.3 558.3 538.8 577.7 519.4 597.1 500 616.5 480.6 635.9 470.9 665 461.2 694.2 470.9 723.3 480.6 752.4 500 771.8 519.4 791.3 529.1 820.4 538.8 849.5 529.1 878.6 519.4 907.8 490.3 917.5 461.2 927.2 432 917.5 402.9 907.8 383.5 888.3 364.1 868.9 335 859.2 305.8 849.5 276.7 859.2 247.6 868.9 228.2 888.3 208.7 907.8 189.3 927.2 169.9 946.6 150.5 966 131.1 985.4 101.9 995.1 72.8 1004.9 43.7 995.1 14.6 985.4 4.9 956.3-4.9 927.2 4.9 898.1 14.6 868.9 34 849.5 53.4 830.1 72.8 810.7 92.2 791.3 111.7 771.8 131.1 752.4 140.8 723.3 150.5 694.2 140.8 665 131.1 635.9 111.7 616.5 92.2 597.1 82.5 568 72.8 538.8 82.5 509.7 92.2 480.6 121.4 470.9 150.5 461.2 179.6 470.9 208.7 480.6 228.2 500 247.6 519.4 276.7 529.1 305.8 538.8 335 529.1 364.1 519.4 383.5 500 402.9 480.6 422.3 461.2 441.7 441.7 461.2 422.3 480.6 402.9 500 383.5 519.4 364.1 538.8 344.7 558.3 325.2 577.7 305.8 597.1 286.4 616.5 267 635.9 247.6 655.3 228.2 674.8 208.7 694.2 189.3 713.6 169.9 733 150.5 752.4 131.1 771.8 111.7 791.3 92.2 810.7 72.8 830.1 53.4 849.5 34",
"width": 1000
},
"search": [
"mode-attack"
]
},
{
"uid": "09e5948ca30589e5baa8d27e1c509588",
"css": "mode-survival",
"code": 59479,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M9.7 43.5Q19.3 14.5 48.3 4.8 77.3-4.8 106.3 4.8 135.3 14.5 154.6 33.8 173.9 53.1 193.2 72.5 212.6 91.8 231.9 111.1 251.2 130.4 280.2 140.1 309.2 149.8 347.8 149.8 386.5 149.8 425.1 149.8 463.8 149.8 502.4 149.8 541.1 149.8 579.7 149.8 618.4 149.8 647.3 140.1 676.3 130.4 695.7 111.1 715 91.8 734.3 72.5 753.6 53.1 772.9 33.8 792.3 14.5 821.3 4.8 850.2-4.8 879.2 4.8 908.2 14.5 917.9 43.5 927.5 72.5 927.5 111.1 927.5 149.8 927.5 188.4 927.5 227.1 927.5 265.7 927.5 304.3 927.5 343 927.5 381.6 927.5 420.3 927.5 458.9 927.5 497.6 927.5 536.2 927.5 574.9 927.5 613.5 917.9 642.5 908.2 671.5 888.9 690.8 869.6 710.1 850.2 729.5 830.9 748.8 811.6 768.1 792.3 787.4 772.9 806.8 753.6 826.1 734.3 845.4 715 864.7 695.7 884.1 676.3 903.4 657 922.7 637.7 942 618.4 961.4 599 980.7 570 990.3 541.1 1000 502.4 1000 463.8 1000 425.1 1000 386.5 1000 357.5 990.3 328.5 980.7 309.2 961.4 289.9 942 270.5 922.7 251.2 903.4 231.9 884.1 212.6 864.7 193.2 845.4 173.9 826.1 154.6 806.8 135.3 787.4 115.9 768.1 96.6 748.8 77.3 729.5 58 710.1 38.6 690.8 19.3 671.5 9.7 642.5 0 613.5 0 574.9 0 536.2 0 497.6 0 458.9 0 420.3 0 381.6 0 343 0 304.3 0 265.7 0 227.1 0 188.4 0 149.8 0 111.1 0 72.5 9.7 43.5",
"width": 928
},
"search": [
"mode-survival"
]
},
{
"uid": "3a617b3ed2fe766baec5b723b1d9502f",
"css": "command-rally",
"code": 59480,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M166.7 83.3Q208.3 41.7 270.8 20.8 333.3 0 416.7 0 500 0 583.3 0 666.7 0 729.2 20.8 791.7 41.7 833.3 83.3 875 125 916.7 166.7 958.3 208.3 979.2 270.8 1000 333.3 1000 416.7 1000 500 1000 583.3 1000 666.7 979.2 729.2 958.3 791.7 916.7 833.3 875 875 833.3 916.7 791.7 958.3 729.2 979.2 666.7 1000 583.3 1000 500 1000 416.7 1000 333.3 1000 270.8 979.2 208.3 958.3 166.7 916.7 125 875 83.3 833.3 41.7 791.7 20.8 729.2 0 666.7 0 583.3 0 500 0 416.7 0 333.3 20.8 270.8 41.7 208.3 83.3 166.7 125 125 166.7 83.3M437.5 812.5Q500 833.3 562.5 812.5 625 791.7 666.7 750 708.3 708.3 750 666.7 791.7 625 812.5 562.5 833.3 500 812.5 437.5 791.7 375 750 333.3 708.3 291.7 666.7 250 625 208.3 562.5 187.5 500 166.7 437.5 187.5 375 208.3 333.3 250 291.7 291.7 250 333.3 208.3 375 187.5 437.5 166.7 500 187.5 562.5 208.3 625 250 666.7 291.7 708.3 333.3 750 375 791.7 437.5 812.5",
"width": 1000
},
"search": [
"command-rally"
]
},
{
"uid": "90fb5a431ca95c46a446c8f4a481d5ce",
"css": "command-attack",
"code": 59481,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M670.2 74.5Q712.8 31.9 776.6 10.6 840.4-10.6 904.3 10.6 968.1 31.9 989.4 95.7 1010.6 159.6 989.4 223.4 968.1 287.2 925.5 329.8 883 372.3 840.4 414.9 797.9 457.4 755.3 500 712.8 542.6 670.2 585.1 627.7 627.7 585.1 670.2 542.6 712.8 542.6 755.3 542.6 797.9 585.1 840.4 627.7 883 627.7 925.5 627.7 968.1 585.1 968.1 542.6 968.1 500 925.5 457.4 883 414.9 883 372.3 883 329.8 925.5 287.2 968.1 223.4 989.4 159.6 1010.6 95.7 989.4 31.9 968.1 10.6 904.3-10.6 840.4 10.6 776.6 31.9 712.8 74.5 670.2 117 627.7 117 585.1 117 542.6 74.5 500 31.9 457.4 31.9 414.9 31.9 372.3 74.5 372.3 117 372.3 159.6 414.9 202.1 457.4 244.7 457.4 287.2 457.4 329.8 414.9 372.3 372.3 414.9 329.8 457.4 287.2 500 244.7 542.6 202.1 585.1 159.6 627.7 117 670.2 74.5",
"width": 1000
},
"search": [
"command-attack"
]
},
{
"uid": "17ef812a059c83b5ea3612f860f9569a",
"css": "command-retreat",
"code": 59482,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M352.3 45.5Q397.7 0 443.2 0 488.6 0 511.4 68.2 534.1 136.4 556.8 204.5 579.5 272.7 647.7 295.5 715.9 318.2 806.8 318.2 897.7 318.2 965.9 340.9 1034.1 363.6 1056.8 431.8 1079.5 500 1056.8 568.2 1034.1 636.4 965.9 659.1 897.7 681.8 806.8 681.8 715.9 681.8 647.7 704.5 579.5 727.3 556.8 795.5 534.1 863.6 511.4 931.8 488.6 1000 443.2 1000 397.7 1000 352.3 954.5 306.8 909.1 261.4 863.6 215.9 818.2 170.5 772.7 125 727.3 79.5 681.8 34.1 636.4 11.4 568.2-11.4 500 11.4 431.8 34.1 363.6 79.5 318.2 125 272.7 170.5 227.3 215.9 181.8 261.4 136.4 306.8 90.9 352.3 45.5",
"width": 1068
},
"search": [
"command-retreat"
]
},
{
"uid": "1bc31b80669cb5edc2ee5d1370554bc9",
"css": "players",
"code": 59483,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M370.1 55.1Q401.6 23.6 448.8 7.9 496.1-7.9 543.3 7.9 590.6 23.6 622 55.1 653.5 86.6 685 118.1 716.5 149.6 732.3 196.9 748 244.1 732.3 291.3 716.5 338.6 685 370.1 653.5 401.6 653.5 433.1 653.5 464.6 685 496.1 716.5 527.6 748 559.1 779.5 590.6 811 622 842.5 653.5 874 685 905.5 716.5 937 748 968.5 779.5 984.3 826.8 1000 874 984.3 921.3 968.5 968.5 921.3 984.3 874 1000 811 1000 748 1000 685 1000 622 1000 559.1 1000 496.1 1000 433.1 1000 370.1 1000 307.1 1000 244.1 1000 181.1 1000 118.1 1000 70.9 984.3 23.6 968.5 7.9 921.3-7.9 874 7.9 826.8 23.6 779.5 55.1 748 86.6 716.5 118.1 685 149.6 653.5 181.1 622 212.6 590.6 244.1 559.1 275.6 527.6 307.1 496.1 338.6 464.6 338.6 433.1 338.6 401.6 307.1 370.1 275.6 338.6 259.8 291.3 244.1 244.1 259.8 196.9 275.6 149.6 307.1 118.1 338.6 86.6 370.1 55.1",
"width": 992
},
"search": [
"players"
]
},
{
"uid": "2073dbd997e5d8e1ffc1322d13ba5585",
"css": "chat",
"code": 59484,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M129 64.5Q161.3 32.3 209.7 16.1 258.1 0 322.6 0 387.1 0 451.6 0 516.1 0 580.6 0 645.2 0 709.7 0 774.2 0 822.6 16.1 871 32.3 903.2 64.5 935.5 96.8 967.7 129 1000 161.3 1016.1 209.7 1032.3 258.1 1032.3 322.6 1032.3 387.1 1032.3 451.6 1032.3 516.1 1016.1 564.5 1000 612.9 967.7 645.2 935.5 677.4 903.2 709.7 871 741.9 822.6 758.1 774.2 774.2 709.7 774.2 645.2 774.2 580.6 774.2 516.1 774.2 451.6 774.2 387.1 774.2 338.7 790.3 290.3 806.5 274.2 854.8 258.1 903.2 241.9 951.6 225.8 1000 193.5 1000 161.3 1000 129 967.7 96.8 935.5 64.5 903.2 32.3 871 16.1 822.6 0 774.2 0 709.7 0 645.2 0 580.6 0 516.1 0 451.6 0 387.1 0 322.6 0 258.1 16.1 209.7 32.3 161.3 64.5 129 96.8 96.8 129 64.5",
"width": 1032
},
"search": [
"chat"
]
},
{
"uid": "9dd9e835aebe1060ba7190ad2b2ed951",
"css": "zoom",
"code": 59415,
"src": "fontawesome"
} }
] ]
} }

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg2"
width="8"
height="7.75"
viewBox="0 0 8 7.75"
sodipodi:docname="chat.svg"
inkscape:version="0.92.4 (f8dce91, 2019-08-02)">
<metadata
id="metadata8">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6" />
<sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2560"
inkscape:window-height="1318"
id="namedview4"
showgrid="false"
inkscape:zoom="23.6"
inkscape:cx="-8.033898"
inkscape:cy="4.0042373"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="g16" />
<g
id="g16"
transform="translate(-1,-1)">
<path
style="fill:#ffffff;fill-opacity:1"
d="M 2,1.5 Q 2.25,1.25 2.625,1.125 3,1 3.5,1 4,1 4.5,1 5,1 5.5,1 6,1 6.5,1 7,1 7.375,1.125 7.75,1.25 8,1.5 8.25,1.75 8.5,2 8.75,2.25 8.875,2.625 9,3 9,3.5 9,4 9,4.5 9,5 8.875,5.375 8.75,5.75 8.5,6 8.25,6.25 8,6.5 7.75,6.75 7.375,6.875 7,7 6.5,7 6,7 5.5,7 5,7 4.5,7 4,7 3.625,7.125 3.25,7.25 3.125,7.625 3,8 2.875,8.375 2.75,8.75 2.5,8.75 2.25,8.75 2,8.5 1.75,8.25 1.5,8 1.25,7.75 1.125,7.375 1,7 1,6.5 1,6 1,5.5 1,5 1,4.5 1,4 1,3.5 1,3 1.125,2.625 1.25,2.25 1.5,2 1.75,1.75 2,1.5"
id="path14"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg12"
width="5.875"
height="5.875"
viewBox="0 0 5.875 5.875"
sodipodi:docname="command-attack.svg"
inkscape:version="0.92.4 (f8dce91, 2019-08-02)">
<metadata
id="metadata18">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs16" />
<sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2560"
inkscape:window-height="1318"
id="namedview14"
showgrid="false"
inkscape:zoom="29.5"
inkscape:cx="-7.706568"
inkscape:cy="1.5137712"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="g61" />
<g
id="g61"
transform="translate(-1.0625,-1.0625)">
<path
style="fill:#ffffff;fill-opacity:1"
d="M 5,1.5 Q 5.25,1.25 5.625,1.125 6,1 6.375,1.125 6.75,1.25 6.875,1.625 7,2 6.875,2.375 6.75,2.75 6.5,3 6.25,3.25 6,3.5 5.75,3.75 5.5,4 5.25,4.25 5,4.5 4.75,4.75 4.5,5 4.25,5.25 4.25,5.5 4.25,5.75 4.5,6 4.75,6.25 4.75,6.5 4.75,6.75 4.5,6.75 4.25,6.75 4,6.5 3.75,6.25 3.5,6.25 3.25,6.25 3,6.5 2.75,6.75 2.375,6.875 2,7 1.625,6.875 1.25,6.75 1.125,6.375 1,6 1.125,5.625 1.25,5.25 1.5,5 1.75,4.75 1.75,4.5 1.75,4.25 1.5,4 1.25,3.75 1.25,3.5 1.25,3.25 1.5,3.25 1.75,3.25 2,3.5 2.25,3.75 2.5,3.75 2.75,3.75 3,3.5 3.25,3.25 3.5,3 3.75,2.75 4,2.5 4.25,2.25 4.5,2 4.75,1.75 5,1.5"
id="path59"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg2"
width="6"
height="6"
viewBox="0 0 6 6"
sodipodi:docname="command-rally.svg"
inkscape:version="0.92.4 (f8dce91, 2019-08-02)">
<metadata
id="metadata8">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6" />
<sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2560"
inkscape:window-height="1318"
id="namedview4"
showgrid="false"
inkscape:zoom="29.5"
inkscape:cx="-12.118644"
inkscape:cy="2.7966102"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="g88" />
<g
id="g88"
transform="translate(-1,-1)">
<path
style="fill:#ffffff;fill-opacity:1"
d="M 2,1.5 Q 2.25,1.25 2.625,1.125 3,1 3.5,1 4,1 4.5,1 5,1 5.375,1.125 5.75,1.25 6,1.5 6.25,1.75 6.5,2 6.75,2.25 6.875,2.625 7,3 7,3.5 7,4 7,4.5 7,5 6.875,5.375 6.75,5.75 6.5,6 6.25,6.25 6,6.5 5.75,6.75 5.375,6.875 5,7 4.5,7 4,7 3.5,7 3,7 2.625,6.875 2.25,6.75 2,6.5 1.75,6.25 1.5,6 1.25,5.75 1.125,5.375 1,5 1,4.5 1,4 1,3.5 1,3 1.125,2.625 1.25,2.25 1.5,2 1.75,1.75 2,1.5 M 3.625,5.875 Q 4,6 4.375,5.875 4.75,5.75 5,5.5 5.25,5.25 5.5,5 5.75,4.75 5.875,4.375 6,4 5.875,3.625 5.75,3.25 5.5,3 5.25,2.75 5,2.5 4.75,2.25 4.375,2.125 4,2 3.625,2.125 3.25,2.25 3,2.5 2.75,2.75 2.5,3 2.25,3.25 2.125,3.625 2,4 2.125,4.375 2.25,4.75 2.5,5 2.75,5.25 3,5.5 3.25,5.75 3.625,5.875"
id="path84"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg22"
width="5.875"
height="5.5"
viewBox="0 0 5.875 5.5"
sodipodi:docname="command-retreat.svg"
inkscape:version="0.92.4 (f8dce91, 2019-08-02)">
<metadata
id="metadata28">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs26" />
<sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2560"
inkscape:window-height="1318"
id="namedview24"
showgrid="false"
inkscape:zoom="29.5"
inkscape:cx="-14.520127"
inkscape:cy="1.4618644"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="g36" />
<g
id="g36"
transform="translate(-1.0625,-1.25)">
<path
style="fill:#ffffff;fill-opacity:1"
d="M 3,1.5 Q 3.25,1.25 3.5,1.25 3.75,1.25 3.875,1.625 4,2 4.125,2.375 4.25,2.75 4.625,2.875 5,3 5.5,3 6,3 6.375,3.125 6.75,3.25 6.875,3.625 7,4 6.875,4.375 6.75,4.75 6.375,4.875 6,5 5.5,5 5,5 4.625,5.125 4.25,5.25 4.125,5.625 4,6 3.875,6.375 3.75,6.75 3.5,6.75 3.25,6.75 3,6.5 2.75,6.25 2.5,6 2.25,5.75 2,5.5 1.75,5.25 1.5,5 1.25,4.75 1.125,4.375 1,4 1.125,3.625 1.25,3.25 1.5,3 1.75,2.75 2,2.5 2.25,2.25 2.5,2 2.75,1.75 3,1.5"
id="path34"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg12"
width="12.875"
height="12.875"
viewBox="0 0 12.875 12.875"
sodipodi:docname="mode-attack.svg"
inkscape:version="0.92.4 (f8dce91, 2019-08-02)">
<metadata
id="metadata18">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs16" />
<sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2560"
inkscape:window-height="1318"
id="namedview14"
showgrid="false"
inkscape:zoom="46.093751"
inkscape:cx="1.4974999"
inkscape:cy="12.3775"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="g869" />
<g
id="g869"
transform="translate(-1.0625,-2.0625)">
<path
style="fill:#ffffff;fill-opacity:1"
d="M 12,2.5 Q 12.25,2.25 12.625,2.125 13,2 13.375,2.125 13.75,2.25 13.875,2.625 14,3 13.875,3.375 13.75,3.75 13.5,4 13.25,4.25 13,4.5 12.75,4.75 12.5,5 12.25,5.25 12,5.5 11.75,5.75 11.5,6 11.25,6.25 11,6.5 10.75,6.75 10.5,7 10.25,7.25 10,7.5 9.75,7.75 9.5,8 9.25,8.25 9,8.5 8.75,8.75 8.5,9 8.25,9.25 8,9.5 7.75,9.75 7.5,10 7.25,10.25 7.125,10.625 7,11 7.125,11.375 7.25,11.75 7.5,12 7.75,12.25 7.875,12.625 8,13 7.875,13.375 7.75,13.75 7.375,13.875 7,14 6.625,13.875 6.25,13.75 6,13.5 5.75,13.25 5.375,13.125 5,13 4.625,13.125 4.25,13.25 4,13.5 3.75,13.75 3.5,14 3.25,14.25 3,14.5 2.75,14.75 2.375,14.875 2,15 1.625,14.875 1.25,14.75 1.125,14.375 1,14 1.125,13.625 1.25,13.25 1.5,13 1.75,12.75 2,12.5 2.25,12.25 2.5,12 2.75,11.75 2.875,11.375 3,11 2.875,10.625 2.75,10.25 2.5,10 2.25,9.75 2.125,9.375 2,9 2.125,8.625 2.25,8.25 2.625,8.125 3,8 3.375,8.125 3.75,8.25 4,8.5 4.25,8.75 4.625,8.875 5,9 5.375,8.875 5.75,8.75 6,8.5 6.25,8.25 6.5,8 6.75,7.75 7,7.5 7.25,7.25 7.5,7 7.75,6.75 8,6.5 8.25,6.25 8.5,6 8.75,5.75 9,5.5 9.25,5.25 9.5,5 9.75,4.75 10,4.5 10.25,4.25 10.5,4 10.75,3.75 11,3.5 11.25,3.25 11.5,3 11.75,2.75 12,2.5"
id="path867"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg2"
width="15.874997"
height="12.874997"
viewBox="0 0 15.874997 12.874997"
sodipodi:docname="mode-pvp.svg"
inkscape:version="0.92.4 (f8dce91, 2019-08-02)">
<metadata
id="metadata8">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6" />
<sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2560"
inkscape:window-height="1318"
id="namedview4"
showgrid="false"
inkscape:zoom="40.972221"
inkscape:cx="-1.9533477"
inkscape:cy="12.95987"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="g20" />
<g
id="g20"
transform="translate(-1.0625002,-3.0625)">
<path
style="fill:#ffffff;fill-opacity:1"
d="m 5,3.0625 c -0.125,0 -0.25,0.020833 -0.375,0.0625 -0.25,0.083333 -0.4166667,0.25 -0.5,0.5 -0.083333,0.25 -0.083333,0.5 0,0.75 C 4.2083333,4.625 4.3333333,4.8333333 4.5,5 L 5,5.5 5.5,6 6,6.5 C 6.1666667,6.6666667 6.3333333,6.75 6.5,6.75 6.6666667,6.75 6.8333333,6.6666667 7,6.5 L 7.5,6 C 7.6666667,5.8333333 7.75,5.6666667 7.75,5.5 7.75,5.3333333 7.6666667,5.1666667 7.5,5 L 7,4.5 6.5,4 6,3.5 C 5.8333333,3.3333333 5.625,3.2083333 5.375,3.125 5.25,3.0833333 5.125,3.0625 5,3.0625 Z m 8,0 c -0.125,0 -0.25,0.020833 -0.375,0.0625 C 12.375,3.2083333 12.166667,3.3333333 12,3.5 L 11.5,4 11,4.5 10.5,5 10,5.5 9.5,6 9,6.5 8.5,7 8,7.5 7.5,8 7,8.5 6.5,9 6,9.5 C 5.8333333,9.6666667 5.625,9.7916667 5.375,9.875 c -0.25,0.083333 -0.5,0.083333 -0.75,0 C 4.375,9.7916667 4.1666667,9.6666667 4,9.5 3.8333333,9.3333333 3.625,9.2083333 3.375,9.125 c -0.25,-0.083333 -0.5,-0.083333 -0.75,0 -0.25,0.083333 -0.4166667,0.25 -0.5,0.5 -0.083333,0.25 -0.083333,0.5 0,0.75 0.083333,0.25 0.2083333,0.458333 0.375,0.625 0.1666667,0.166667 0.2916667,0.375 0.375,0.625 0.083333,0.25 0.083333,0.5 0,0.75 C 2.7916667,12.625 2.6666667,12.833333 2.5,13 L 2,13.5 1.5,14 c -0.1666667,0.166667 -0.2916667,0.375 -0.375,0.625 -0.083333,0.25 -0.083333,0.5 0,0.75 0.083333,0.25 0.25,0.416667 0.5,0.5 0.25,0.08333 0.5,0.08333 0.75,0 C 2.625,15.791667 2.8333333,15.666667 3,15.5 L 3.5,15 4,14.5 c 0.1666667,-0.166667 0.375,-0.291667 0.625,-0.375 0.25,-0.08333 0.5,-0.08333 0.75,0 0.25,0.08333 0.4583333,0.208333 0.625,0.375 0.1666667,0.166667 0.375,0.291667 0.625,0.375 0.25,0.08333 0.5,0.08333 0.75,0 0.25,-0.08333 0.4166667,-0.25 0.5,-0.5 0.083333,-0.25 0.083333,-0.5 0,-0.75 C 7.7916667,13.375 7.6666667,13.166667 7.5,13 7.3333333,12.833333 7.2083333,12.625 7.125,12.375 c -0.083333,-0.25 -0.083333,-0.5 0,-0.75 C 7.2083333,11.375 7.3333333,11.166667 7.5,11 L 8,10.5 8.5,10 9,9.5 9.5,9 10,8.5 10.5,8 11,7.5 11.5,7 12,6.5 12.5,6 13,5.5 13.5,5 c 0.166667,-0.1666667 0.291667,-0.375 0.375,-0.625 0.08333,-0.25 0.08333,-0.5 0,-0.75 -0.08333,-0.25 -0.25,-0.4166667 -0.5,-0.5 C 13.25,3.0833333 13.125,3.0625 13,3.0625 Z m 2,6 c -0.125,0 -0.25,0.020833 -0.375,0.0625 C 14.375,9.208333 14.166667,9.3333333 14,9.5 c -0.166667,0.1666667 -0.375,0.2916667 -0.625,0.375 -0.25,0.083333 -0.5,0.083333 -0.75,0 C 12.375,9.7916667 12.166667,9.6666667 12,9.5 11.833333,9.3333333 11.666667,9.25 11.5,9.25 11.333333,9.25 11.166667,9.3333333 11,9.5 L 10.5,10 c -0.166667,0.166667 -0.25,0.333333 -0.25,0.5 0,0.166667 0.08333,0.333333 0.25,0.5 0.166667,0.166667 0.291667,0.375 0.375,0.625 0.08333,0.25 0.08333,0.5 0,0.75 -0.08333,0.25 -0.208333,0.458333 -0.375,0.625 -0.166667,0.166667 -0.291667,0.375 -0.375,0.625 -0.08333,0.25 -0.08333,0.5 0,0.75 0.08333,0.25 0.25,0.416667 0.5,0.5 0.25,0.08333 0.5,0.08333 0.75,0 0.25,-0.08333 0.458333,-0.208333 0.625,-0.375 0.166667,-0.166667 0.375,-0.291667 0.625,-0.375 0.25,-0.08333 0.5,-0.08333 0.75,0 0.25,0.08333 0.458333,0.208333 0.625,0.375 l 0.5,0.5 0.5,0.5 c 0.166667,0.166667 0.375,0.291667 0.625,0.375 0.25,0.08333 0.5,0.08333 0.75,0 0.25,-0.08333 0.416667,-0.25 0.5,-0.5 0.08333,-0.25 0.08333,-0.5 0,-0.75 C 16.791667,14.375 16.666667,14.166667 16.5,14 L 16,13.5 15.5,13 c -0.166667,-0.166667 -0.291667,-0.375 -0.375,-0.625 -0.08333,-0.25 -0.08333,-0.5 0,-0.75 0.08333,-0.25 0.208333,-0.458333 0.375,-0.625 0.166667,-0.166667 0.291667,-0.375 0.375,-0.625 0.08333,-0.25 0.08333,-0.5 0,-0.75 -0.08333,-0.25 -0.25,-0.4166667 -0.5,-0.5 C 15.25,9.0833333 15.125,9.0625 15,9.0625 Z"
id="path14"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg22"
width="12"
height="12.9375"
viewBox="0 0 12 12.9375"
sodipodi:docname="mode-survival.svg"
inkscape:version="0.92.4 (f8dce91, 2019-08-02)">
<metadata
id="metadata28">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs26" />
<sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2560"
inkscape:window-height="1318"
id="namedview24"
showgrid="false"
inkscape:zoom="46.093751"
inkscape:cx="0.55999994"
inkscape:cy="12.44"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="g844" />
<g
id="g844"
inkscape:label="g844"
transform="translate(-2,-2.0625)">
<path
style="fill:#ffffff;fill-opacity:1"
d="M 2.125,2.625 Q 2.25,2.25 2.625,2.125 3,2 3.375,2.125 3.75,2.25 4,2.5 4.25,2.75 4.5,3 4.75,3.25 5,3.5 5.25,3.75 5.625,3.875 6,4 6.5,4 7,4 7.5,4 8,4 8.5,4 9,4 9.5,4 10,4 10.375,3.875 10.75,3.75 11,3.5 11.25,3.25 11.5,3 11.75,2.75 12,2.5 12.25,2.25 12.625,2.125 13,2 13.375,2.125 13.75,2.25 13.875,2.625 14,3 14,3.5 q 0,0.5 0,1 0,0.5 0,1 0,0.5 0,1 0,0.5 0,1 0,0.5 0,1 0,0.5 0,1 0,0.5 -0.125,0.875 Q 13.75,10.75 13.5,11 13.25,11.25 13,11.5 12.75,11.75 12.5,12 12.25,12.25 12,12.5 11.75,12.75 11.5,13 11.25,13.25 11,13.5 10.75,13.75 10.5,14 10.25,14.25 10,14.5 9.75,14.75 9.375,14.875 9,15 8.5,15 8,15 7.5,15 7,15 6.625,14.875 6.25,14.75 6,14.5 5.75,14.25 5.5,14 5.25,13.75 5,13.5 4.75,13.25 4.5,13 4.25,12.75 4,12.5 3.75,12.25 3.5,12 3.25,11.75 3,11.5 2.75,11.25 2.5,11 2.25,10.75 2.125,10.375 2,10 2,9.5 2,9 2,8.5 2,8 2,7.5 2,7 2,6.5 2,6 2,5.5 2,5 2,4.5 2,4 2,3.5 2,3 2.125,2.625"
id="path842"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="svg2"
width="7.875"
height="7.9375"
viewBox="0 0 7.875 7.9375"
sodipodi:docname="players.svg"
inkscape:version="0.92.4 (f8dce91, 2019-08-02)">
<metadata
id="metadata8">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs6" />
<sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2560"
inkscape:window-height="1318"
id="namedview4"
showgrid="false"
inkscape:zoom="23.6"
inkscape:cx="-14.960805"
inkscape:cy="3.4067797"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="g16" />
<g
id="g16"
transform="translate(-1.0625,-1.0625)">
<path
style="fill:#ffffff;fill-opacity:1"
d="M 4,1.5 Q 4.25,1.25 4.625,1.125 5,1 5.375,1.125 5.75,1.25 6,1.5 6.25,1.75 6.5,2 6.75,2.25 6.875,2.625 7,3 6.875,3.375 6.75,3.75 6.5,4 6.25,4.25 6.25,4.5 6.25,4.75 6.5,5 6.75,5.25 7,5.5 7.25,5.75 7.5,6 7.75,6.25 8,6.5 8.25,6.75 8.5,7 8.75,7.25 8.875,7.625 9,8 8.875,8.375 8.75,8.75 8.375,8.875 8,9 7.5,9 7,9 6.5,9 6,9 5.5,9 5,9 4.5,9 4,9 3.5,9 3,9 2.5,9 2,9 1.625,8.875 1.25,8.75 1.125,8.375 1,8 1.125,7.625 1.25,7.25 1.5,7 1.75,6.75 2,6.5 2.25,6.25 2.5,6 2.75,5.75 3,5.5 3.25,5.25 3.5,5 3.75,4.75 3.75,4.5 3.75,4.25 3.5,4 3.25,3.75 3.125,3.375 3,3 3.125,2.625 3.25,2.25 3.5,2 3.75,1.75 4,1.5"
id="path14"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 677 B

View File

@@ -104,6 +104,7 @@ mods.none = [LIGHT_GRAY]No mods found!
mods.guide = Modding Guide mods.guide = Modding Guide
mods.report = Report Bug mods.report = Report Bug
mods.openfolder = Open Mod Folder mods.openfolder = Open Mod Folder
mod.display = [gray]Mod:[orange] {0}
mod.enabled = [lightgray]Enabled mod.enabled = [lightgray]Enabled
mod.disabled = [scarlet]Disabled mod.disabled = [scarlet]Disabled
mod.disable = Disable mod.disable = Disable
@@ -532,6 +533,8 @@ error.crashtitle = An error has occured
blocks.input = Input blocks.input = Input
blocks.output = Output blocks.output = Output
blocks.booster = Booster blocks.booster = Booster
blocks.tiles = Required Tiles
blocks.affinities = Affinities
block.unknown = [lightgray]??? block.unknown = [lightgray]???
blocks.powercapacity = Power Capacity blocks.powercapacity = Power Capacity
blocks.powershot = Power/Shot blocks.powershot = Power/Shot
@@ -666,6 +669,7 @@ setting.mutesound.name = Mute Sound
setting.crashreport.name = Send Anonymous Crash Reports setting.crashreport.name = Send Anonymous Crash Reports
setting.savecreate.name = Auto-Create Saves setting.savecreate.name = Auto-Create Saves
setting.publichost.name = Public Game Visibility setting.publichost.name = Public Game Visibility
setting.playerlimit.name = Player Limit
setting.chatopacity.name = Chat Opacity setting.chatopacity.name = Chat Opacity
setting.lasersopacity.name = Power Laser Opacity setting.lasersopacity.name = Power Laser Opacity
setting.bridgeopacity.name = Bridge Opacity setting.bridgeopacity.name = Bridge Opacity
@@ -944,6 +948,7 @@ block.message.name = Message
block.illuminator.name = Illuminator block.illuminator.name = Illuminator
block.illuminator.description = A small, compact, configurable light source. Requires power to function. block.illuminator.description = A small, compact, configurable light source. Requires power to function.
block.overflow-gate.name = Overflow Gate block.overflow-gate.name = Overflow Gate
block.underflow-gate.name = Underflow Gate
block.silicon-smelter.name = Silicon Smelter block.silicon-smelter.name = Silicon Smelter
block.phase-weaver.name = Phase Weaver block.phase-weaver.name = Phase Weaver
block.pulverizer.name = Pulverizer block.pulverizer.name = Pulverizer
@@ -1175,6 +1180,7 @@ block.inverted-sorter.description = Processes items like a standard sorter, but
block.router.description = Accepts items, then outputs them to up to 3 other directions equally. Useful for splitting the materials from one source to multiple targets.\n\n[scarlet]Never use next to production inputs, as they will get clogged by output.[] block.router.description = Accepts items, then outputs them to up to 3 other directions equally. Useful for splitting the materials from one source to multiple targets.\n\n[scarlet]Never use next to production inputs, as they will get clogged by output.[]
block.distributor.description = An advanced router. Splits items to up to 7 other directions equally. block.distributor.description = An advanced router. Splits items to up to 7 other directions equally.
block.overflow-gate.description = Only outputs to the left and right if the front path is blocked. block.overflow-gate.description = Only outputs to the left and right if the front path is blocked.
block.underflow-gate.description = The opposite of an overflow gate. Outputs to the front if the left and right paths are blocked.
block.mass-driver.description = The ultimate item transport block. Collects several items and then shoots them to another mass driver over a long range. Requires power to operate. block.mass-driver.description = The ultimate item transport block. Collects several items and then shoots them to another mass driver over a long range. Requires power to operate.
block.mechanical-pump.description = A cheap pump with slow output, but no power consumption. block.mechanical-pump.description = A cheap pump with slow output, but no power consumption.
block.rotary-pump.description = An advanced pump. Pumps more liquid, but requires power. block.rotary-pump.description = An advanced pump. Pumps more liquid, but requires power.

View File

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

View File

@@ -141,14 +141,14 @@ players = {0} Spieler online
players.single = {0} Spieler online players.single = {0} Spieler online
server.closing = [accent]Schließe den Server ... server.closing = [accent]Schließe den Server ...
server.kicked.kick = Du wurdest vom Server gekickt! server.kicked.kick = Du wurdest vom Server gekickt!
server.kicked.whitelist = Du bist nicht auf der Whitelist. server.kicked.whitelist = Du bist hier nicht auf der Whitelist.
server.kicked.serverClose = Server geschlossen. server.kicked.serverClose = Server geschlossen.
server.kicked.vote = Es wurde abgestimmt, dich zu kicken. Tschüss. server.kicked.vote = Es wurde abgestimmt, dich zu kicken. Tschüss.
server.kicked.clientOutdated = Veralteter Client! Aktualisiere dein Spiel! server.kicked.clientOutdated = Veralteter Client! Aktualisiere dein Spiel!
server.kicked.serverOutdated = Veralteter Server! Bitte den Host um ein Update! server.kicked.serverOutdated = Veralteter Server! Bitte den Host um ein Update!
server.kicked.banned = Du wurdest vom Server verbannt. server.kicked.banned = Du wurdest vom Server verbannt.
server.kicked.typeMismatch = Der Server ist nicht mit deinem Versionstyp kompatibel. server.kicked.typeMismatch = Der Server ist nicht mit deinem Versionstyp kompatibel.
server.kicked.playerLimit = Der Server ist voll.\nWarte für einen freien Platz. server.kicked.playerLimit = Dieser Server ist voll. Warte auf einen freien Platz.
server.kicked.recentKick = Du wurdest gerade gekickt.\nWarte bevor du dich wieder verbindest. server.kicked.recentKick = Du wurdest gerade gekickt.\nWarte bevor du dich wieder verbindest.
server.kicked.nameInUse = Es ist bereits ein Spieler \nmit diesem Namen auf dem Server. server.kicked.nameInUse = Es ist bereits ein Spieler \nmit diesem Namen auf dem Server.
server.kicked.nameEmpty = Dein Name muss mindestens einen Buchstaben oder eine Zahl enthalten. server.kicked.nameEmpty = Dein Name muss mindestens einen Buchstaben oder eine Zahl enthalten.
@@ -190,7 +190,7 @@ server.version = [lightgray]Version: {0}
server.custombuild = [yellow]Benutzerdefinierter Build server.custombuild = [yellow]Benutzerdefinierter Build
confirmban = Bist du sicher, dass du diesen Spieler verbannen möchtest? confirmban = Bist du sicher, dass du diesen Spieler verbannen möchtest?
confirmkick = Bist du sicher, dass du diesen Spieler kicken willst? confirmkick = Bist du sicher, dass du diesen Spieler kicken willst?
confirmvotekick = Willst du wirklich eine Abstimmung zum kicken des spielers machen? confirmvotekick = Bist du sicher diesen Spieler mit einer Abstimmung rauszuwerfen?
confirmunban = Bist du sicher, dass du die Verbannung des Spielers rückgängig machen willst? confirmunban = Bist du sicher, dass du die Verbannung des Spielers rückgängig machen willst?
confirmadmin = Bist du sicher, dass du diesen Spieler zu einem Admin machen möchtest? confirmadmin = Bist du sicher, dass du diesen Spieler zu einem Admin machen möchtest?
confirmunadmin = Bis du sicher, dass dieser Spieler kein Admin mehr sein soll? confirmunadmin = Bis du sicher, dass dieser Spieler kein Admin mehr sein soll?
@@ -199,9 +199,9 @@ joingame.ip = IP:
disconnect = Verbindung unterbrochen. disconnect = Verbindung unterbrochen.
disconnect.error = Verbindungsfehler. disconnect.error = Verbindungsfehler.
disconnect.closed = Verbindung geschlossen. disconnect.closed = Verbindung geschlossen.
disconnect.timeout = Zu langer Verbindungsversuch. disconnect.timeout = Zeit Überschreitung.
disconnect.data = Fehler beim Laden der Welt! disconnect.data = Fehler beim Laden der Welt!
cantconnect = Unfähig, dem Spiel beizutreten ([accent]{0}[]). cantconnect = Nicht möglich beizutreten ([accent]{0}[]).
connecting = [accent] Verbinde... connecting = [accent] Verbinde...
connecting.data = [accent] Welt wird geladen... connecting.data = [accent] Welt wird geladen...
server.port = Port: server.port = Port:
@@ -226,7 +226,7 @@ save.rename = Umbenennen
save.rename.text = Neuer Name save.rename.text = Neuer Name
selectslot = Wähle einen Spielstand selectslot = Wähle einen Spielstand
slot = [accent] Platz {0} slot = [accent] Platz {0}
editmessage = Edit Message editmessage = Nachricht bearbeiten
save.corrupted = [accent] Datei beschädigt oder ungültig! save.corrupted = [accent] Datei beschädigt oder ungültig!
empty = <leer> empty = <leer>
on = An on = An
@@ -392,7 +392,7 @@ filters.empty = [LIGHT_GRAY]Keine Filter! Füge einen mit dem unteren Knopf hinz
filter.distort = Verzerren filter.distort = Verzerren
filter.noise = Rauschen filter.noise = Rauschen
filter.median = Mittelwert filter.median = Mittelwert
filter.oremedian = Ore Median filter.oremedian =Erz Median
filter.blend = Mischen filter.blend = Mischen
filter.defaultores = Standard Erze filter.defaultores = Standard Erze
filter.ore = Erz filter.ore = Erz
@@ -569,11 +569,11 @@ bar.drillspeed = Bohrgeschwindigkeit: {0}/s
bar.pumpspeed = Pump Speed: {0}/s bar.pumpspeed = Pump Speed: {0}/s
bar.efficiency = Effizienz: {0}% bar.efficiency = Effizienz: {0}%
bar.powerbalance = Strom: {0} bar.powerbalance = Strom: {0}
bar.powerstored = Stored: {0}/{1} bar.powerstored = Gespeichert: {0}/{1}
bar.poweramount = Strom: {0} bar.poweramount = Strom: {0}
bar.poweroutput = Stromgeneration: {0} bar.poweroutput = Stromgeneration: {0}
bar.items = Items: {0} bar.items = Items: {0}
bar.capacity = Capacity: {0} bar.capacity = Kapazität: {0}
bar.liquid = Flüssigkeit bar.liquid = Flüssigkeit
bar.heat = Hitze bar.heat = Hitze
bar.power = Strom bar.power = Strom
@@ -800,7 +800,7 @@ item.pyratite.name = Pyratit
item.metaglass.name = Metaglass item.metaglass.name = Metaglass
item.scrap.name = Schrott item.scrap.name = Schrott
liquid.water.name = Wasser liquid.water.name = Wasser
liquid.slag.name = Schlacke liquid.slag.name = Lava
liquid.oil.name = Öl liquid.oil.name = Öl
liquid.cryofluid.name = Kryoflüssigkeit liquid.cryofluid.name = Kryoflüssigkeit
mech.alpha-mech.name = Alpha mech.alpha-mech.name = Alpha
@@ -820,7 +820,7 @@ mech.dart-ship.weapon = Mehrlader
mech.javelin-ship.name = Javelin mech.javelin-ship.name = Javelin
mech.javelin-ship.weapon = Raketensalve mech.javelin-ship.weapon = Raketensalve
mech.javelin-ship.ability = Statische Entladung mech.javelin-ship.ability = Statische Entladung
mech.trident-ship.name = Trident mech.trident-ship.name = Dreizack
mech.trident-ship.weapon = Bombenschacht mech.trident-ship.weapon = Bombenschacht
mech.glaive-ship.name = Glaive mech.glaive-ship.name = Glaive
mech.glaive-ship.weapon = Flammen-Mehrlader mech.glaive-ship.weapon = Flammen-Mehrlader
@@ -924,9 +924,9 @@ block.thorium-wall.name = Thorium-Mauer
block.thorium-wall-large.name = Große Thorium-Mauer block.thorium-wall-large.name = Große Thorium-Mauer
block.door.name = Tor block.door.name = Tor
block.door-large.name = Großes Tor block.door-large.name = Großes Tor
block.duo.name = Duo block.duo.name = Doppelgeschütz
block.scorch.name = Flammenwerfer block.scorch.name = Scatter
block.scatter.name = Scatter block.scatter.name = Luftgeschütz
block.hail.name = Streuer block.hail.name = Streuer
block.lancer.name = Lanzer block.lancer.name = Lanzer
block.conveyor.name = Förderband block.conveyor.name = Förderband
@@ -938,7 +938,7 @@ block.router.name = Verteiler
block.distributor.name = Großer Verteiler block.distributor.name = Großer Verteiler
block.sorter.name = Sortierer block.sorter.name = Sortierer
block.inverted-sorter.name = Inverted Sorter block.inverted-sorter.name = Inverted Sorter
block.message.name = Message block.message.name = Nachricht
block.illuminator.name = Illuminator block.illuminator.name = Illuminator
block.illuminator.description = A small, compact, configurable light source. Requires power to function. block.illuminator.description = A small, compact, configurable light source. Requires power to function.
block.overflow-gate.name = Überlauftor block.overflow-gate.name = Überlauftor
@@ -969,7 +969,7 @@ block.cultivator.name = Kultivierer
block.dart-mech-pad.name = Dart Mech-Pad block.dart-mech-pad.name = Dart Mech-Pad
block.delta-mech-pad.name = Delta Mech-Pad block.delta-mech-pad.name = Delta Mech-Pad
block.javelin-ship-pad.name = Javelin Luftschiff-Pad block.javelin-ship-pad.name = Javelin Luftschiff-Pad
block.trident-ship-pad.name = Trident Luftschiff-Pad block.trident-ship-pad.name = Dreizack Luftschiff-Pad
block.glaive-ship-pad.name = Glaive Luftschiff-Pad block.glaive-ship-pad.name = Glaive Luftschiff-Pad
block.omega-mech-pad.name = Omega Mech-Pad block.omega-mech-pad.name = Omega Mech-Pad
block.tau-mech-pad.name = Tau Mech-Pad block.tau-mech-pad.name = Tau Mech-Pad
@@ -986,7 +986,7 @@ block.vault.name = Tresor
block.wave.name = Welle block.wave.name = Welle
block.swarmer.name = Schwärmer block.swarmer.name = Schwärmer
block.salvo.name = Salve block.salvo.name = Salve
block.ripple.name = Riffel block.ripple.name = Zerstörer
block.phase-conveyor.name = Phasen-Transportband block.phase-conveyor.name = Phasen-Transportband
block.bridge-conveyor.name = Brücken-Transportband block.bridge-conveyor.name = Brücken-Transportband
block.plastanium-compressor.name = Plastanium-Verdichter block.plastanium-compressor.name = Plastanium-Verdichter
@@ -995,7 +995,7 @@ block.blast-mixer.name = Sprengmixer
block.solar-panel.name = Solarpanel block.solar-panel.name = Solarpanel
block.solar-panel-large.name = Großes Solarpanel block.solar-panel-large.name = Großes Solarpanel
block.oil-extractor.name = Öl-Extraktor block.oil-extractor.name = Öl-Extraktor
block.command-center.name = Command Center block.command-center.name = Kommandozentrum
block.draug-factory.name = Draug Miner-Drohnenfactory block.draug-factory.name = Draug Miner-Drohnenfactory
block.spirit-factory.name = Spirit-Drohnenfabrik block.spirit-factory.name = Spirit-Drohnenfabrik
block.phantom-factory.name = Phantom-Drohnenfabrik block.phantom-factory.name = Phantom-Drohnenfabrik
@@ -1010,7 +1010,7 @@ block.repair-point.name = Reparaturpunkt
block.pulse-conduit.name = Impulskanal block.pulse-conduit.name = Impulskanal
block.plated-conduit.name = Plated Conduit block.plated-conduit.name = Plated Conduit
block.phase-conduit.name = Phasenkanal block.phase-conduit.name = Phasenkanal
block.liquid-router.name = Flüssigkeits-Router block.liquid-router.name = Flüssigkeits-Verteiler
block.liquid-tank.name = Flüssigkeitstank block.liquid-tank.name = Flüssigkeitstank
block.liquid-junction.name = Flüssigkeits-Kreuzung block.liquid-junction.name = Flüssigkeits-Kreuzung
block.bridge-conduit.name = Kanalbrücke block.bridge-conduit.name = Kanalbrücke
@@ -1120,7 +1120,7 @@ unit.eruptor.description = Ein schwerer Mech, der Strukturen abbaut. Feuert eine
unit.wraith.description = Eine schneller Abfangjäger. unit.wraith.description = Eine schneller Abfangjäger.
unit.ghoul.description = Ein schwerer Flächenbomber. unit.ghoul.description = Ein schwerer Flächenbomber.
unit.revenant.description = Eine schwere, schwebende Raketengruppe. unit.revenant.description = Eine schwere, schwebende Raketengruppe.
block.message.description = Stores a message. Used for communication between allies. block.message.description = Benutzt um Nachrichten mit Verbündeten auszutauschen.
block.graphite-press.description = Komprimiert Kohlestücke zu reinen Graphitplatten. block.graphite-press.description = Komprimiert Kohlestücke zu reinen Graphitplatten.
block.multi-press.description = Eine aktualisierte Version der Graphitpresse. Setzt Wasser und Strom ein, um Kohle schnell und effizient zu verarbeiten. block.multi-press.description = Eine aktualisierte Version der Graphitpresse. Setzt Wasser und Strom ein, um Kohle schnell und effizient zu verarbeiten.
block.silicon-smelter.description = Reduziert Sand mit hochreinem Kohlenstoff, um Silizium zu produzieren. block.silicon-smelter.description = Reduziert Sand mit hochreinem Kohlenstoff, um Silizium zu produzieren.
@@ -1236,7 +1236,7 @@ block.wraith-factory.description = Produziert schnelle Abfangjäger.
block.ghoul-factory.description = Produziert schwere Flächenbomber. block.ghoul-factory.description = Produziert schwere Flächenbomber.
block.revenant-factory.description = Produziert schwere Raketen basierte Flugeinheiten. block.revenant-factory.description = Produziert schwere Raketen basierte Flugeinheiten.
block.dagger-factory.description = Produziert Standard-Bodeneinheiten. block.dagger-factory.description = Produziert Standard-Bodeneinheiten.
block.crawler-factory.description = Produziert schnelle selbstzerstörende Schwarmeinheiten. block.crawler-factory.description = Produziert schnelle, selbstzerstörende Schwarmeinheiten.
block.titan-factory.description = Produziert fortgeschrittene, gepanzerte Bodeneinheiten. block.titan-factory.description = Produziert fortgeschrittene, gepanzerte Bodeneinheiten.
block.fortress-factory.description = Produziert schwere Artillerie-Bodeneinheiten. block.fortress-factory.description = Produziert schwere Artillerie-Bodeneinheiten.
block.repair-point.description = Heilt durchgehend die nächste befreundete, beschädigte Einheit in der Umgebung. block.repair-point.description = Heilt durchgehend die nächste befreundete, beschädigte Einheit in der Umgebung.

View File

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

View File

@@ -3,7 +3,7 @@ credits = Crediti
contributors = Traduttori e Contributori contributors = Traduttori e Contributori
discord = Entra nel server Discord di Mindustry! discord = Entra nel server Discord di Mindustry!
link.discord.description = La chatroom ufficiale del server Discord di Mindustry link.discord.description = La chatroom ufficiale del server Discord di Mindustry
link.reddit.description = The Mindustry subreddit link.reddit.description = Il subreddit di Mindustry!
link.github.description = Codice sorgente del gioco link.github.description = Codice sorgente del gioco
link.changelog.description = Elenco delle modifiche del gioco link.changelog.description = Elenco delle modifiche del gioco
link.dev-builds.description = Build di sviluppo versioni instabili link.dev-builds.description = Build di sviluppo versioni instabili
@@ -40,12 +40,12 @@ schematic = Schematica
schematic.add = Salva Schematica... schematic.add = Salva Schematica...
schematics = Schematiche schematics = Schematiche
schematic.replace = Una schematica con questo nome esiste già. Sostituirla? schematic.replace = Una schematica con questo nome esiste già. Sostituirla?
schematic.import = Importa schematica... schematic.import = Importa schematica
schematic.exportfile = Esporta File schematic.exportfile = Esporta File
schematic.importfile = Importa File schematic.importfile = Importa File
schematic.browseworkshop = Naviga nel Workshop schematic.browseworkshop = Naviga nel Workshop
schematic.copy = Copia negli Appunti schematic.copy = Copia negli Appunti
schematic.copy.import = Importa dagli Appunti schematic.copy.import = Incolla dagli Appunti
schematic.shareworkshop = Condividi nel Workshop schematic.shareworkshop = Condividi nel Workshop
schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Ruota Schematica schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Ruota Schematica
schematic.saved = Schematica salvata. schematic.saved = Schematica salvata.
@@ -69,7 +69,7 @@ level.select = Selezione del Livello
level.mode = Modalità di Gioco: level.mode = Modalità di Gioco:
showagain = Non mostrare più showagain = Non mostrare più
coreattack = < Il Nucleo è sotto attacco! > coreattack = < Il Nucleo è sotto attacco! >
nearpoint = [[ [scarlet]LASCIA LA ZONA NEMICA IMMEDIATAMENTE[] ]\nautodistruzione imminente nearpoint = [[ [scarlet]LASCIA LA ZONA NEMICA IMMEDIATAMENTE[] ]\autodistruzione imminente
database = Database Nucleo database = Database Nucleo
savegame = Salva savegame = Salva
loadgame = Carica loadgame = Carica
@@ -79,7 +79,7 @@ newgame = Nuova partita
none = <niente> none = <niente>
minimap = Minimappa minimap = Minimappa
position = Posizione position = Posizione
close = Chiuso close = Chiudi
website = Sito Web website = Sito Web
quit = Esci quit = Esci
save.quit = Salva ed Esci save.quit = Salva ed Esci
@@ -138,12 +138,12 @@ research.list = [lightgray]Ricerca:
research = Ricerca research = Ricerca
researched = [lightgray]{0} cercati. researched = [lightgray]{0} cercati.
players = {0} giocatori online players = {0} giocatori online
players.single = {0} giocatori online players.single = {0} giocatore online
server.closing = [accent]Chiusura server... server.closing = [accent]Chiusura server...
server.kicked.kick = Sei stato cacciato dal server! server.kicked.kick = Sei stato espulso dal server!
server.kicked.whitelist = Non sei presente nella whitelist. server.kicked.whitelist = Non sei presente nella whitelist.
server.kicked.serverClose = Server chiuso. server.kicked.serverClose = Server chiuso.
server.kicked.vote = Sei stato cacciato su richiesta dei giocatori. Tanti saluti. server.kicked.vote = Sei stato esplso su richiesta dei giocatori. Tanti saluti.
server.kicked.clientOutdated = Versione del client obsoleta! Aggiorna il gioco! server.kicked.clientOutdated = Versione del client obsoleta! Aggiorna il gioco!
server.kicked.serverOutdated = Server obsoleto! Chiedi all'host di aggiornare la versione del server! server.kicked.serverOutdated = Server obsoleto! Chiedi all'host di aggiornare la versione del server!
server.kicked.banned = Sei stato bandito da questo server. server.kicked.banned = Sei stato bandito da questo server.
@@ -157,7 +157,7 @@ server.kicked.customClient = Questo server non supporta i client personalizzati.
server.kicked.gameover = Game over! server.kicked.gameover = Game over!
server.kicked.serverRestarting = Il server si sta riavviando. server.kicked.serverRestarting = Il server si sta riavviando.
server.versions = Versione client:[accent] {0}[]\nVersione server:[accent] {1}[] server.versions = Versione client:[accent] {0}[]\nVersione server:[accent] {1}[]
host.info = Il pulsante [accent]Ospita[] ospita un server sulla porta [scarlet]6567[].[] Chiunque sulla stessa [lightgray]rete Wi-Fi o locale[] dovrebbe essere in grado di vedere il server nell'elenco server.\nSe vuoi che le persone siano in grado di connettersi ovunque tramite il tuo IP, è richiesto il [accent]port forwarding[].\n\n[lightgray]Nota: se qualcuno sta riscontrando problemi durante la connessione al gioco LAN, assicurati di aver consentito a Mindustry di accedere alla rete locale nelle impostazioni del firewall. host.info = Il pulsante [accent]Ospita[] ospita un server sulla porta [scarlet]6567[].[] Chiunque sulla stessa [lightgray]rete Wi-Fi o locale[] dovrebbe essere in grado di vedere il server nell'elenco server.\nSe vuoi che le persone siano in grado di connettersi ovunque tramite il tuo IP, è necessario eseguire il [accent]port forwarding[].\n\n[lightgray]Nota: se qualcuno sta riscontrando problemi durante la connessione al gioco LAN, assicurati di aver consentito a Mindustry di accedere alla rete locale nelle impostazioni del firewall.
join.info = Qui è possibile inserire l'[accent]IP del server[] a cui connettersi, o scoprire [accent]un server sulla rete locale[] disponibile.\nSono supportati sia il multiplayer LAN che WAN.\n\n[lightgray]Nota: non esiste un elenco automatico dei server globali; se desideri connetterti a qualcuno tramite il suo IP, è necessario chiedere all'host il proprio IP. join.info = Qui è possibile inserire l'[accent]IP del server[] a cui connettersi, o scoprire [accent]un server sulla rete locale[] disponibile.\nSono supportati sia il multiplayer LAN che WAN.\n\n[lightgray]Nota: non esiste un elenco automatico dei server globali; se desideri connetterti a qualcuno tramite il suo IP, è necessario chiedere all'host il proprio IP.
hostserver = Ospita Server hostserver = Ospita Server
invitefriends = Invita Amici invitefriends = Invita Amici
@@ -199,7 +199,7 @@ joingame.ip = Indirizzo:
disconnect = Disconnesso. disconnect = Disconnesso.
disconnect.error = Errore di connessione. disconnect.error = Errore di connessione.
disconnect.closed = Connessione chiusa. disconnect.closed = Connessione chiusa.
disconnect.timeout = Timed out. disconnect.timeout = Connessione scaduta.
disconnect.data = Errore durante il caricamento del mondo! disconnect.data = Errore durante il caricamento del mondo!
cantconnect = Impossibile unirsi alla partita ([accent]{0}[]). cantconnect = Impossibile unirsi alla partita ([accent]{0}[]).
connecting = [accent]Connessione in corso... connecting = [accent]Connessione in corso...
@@ -251,6 +251,7 @@ copylink = Copia link
back = Indietro back = Indietro
data.export = Esporta Salvataggio data.export = Esporta Salvataggio
data.import = Importa Salvataggio data.import = Importa Salvataggio
data.openfolder = Apri Cartella\nSalvataggi
data.exported = Dati esportati. data.exported = Dati esportati.
data.invalid = Questi non sono dati di gioco validi. data.invalid = Questi non sono dati di gioco validi.
data.import.confirm = Importare dati di gioco esterni sovrascriverà[scarlet] tutti[] i tuoi progressi attuali.\n[accent]L'operazione è irreversibile![]\n\nUna volta importati i dati, il gioco si chiuderà immediatamente. data.import.confirm = Importare dati di gioco esterni sovrascriverà[scarlet] tutti[] i tuoi progressi attuali.\n[accent]L'operazione è irreversibile![]\n\nUna volta importati i dati, il gioco si chiuderà immediatamente.
@@ -263,7 +264,7 @@ reloading = [accent]Ricaricamento delle mods...
saving = [accent]Salvataggio in corso... saving = [accent]Salvataggio in corso...
cancelbuilding = [accent][[{0}][] per pulire la selezione cancelbuilding = [accent][[{0}][] per pulire la selezione
selectschematic = [accent][[{0}][] per selezionare+copiare selectschematic = [accent][[{0}][] per selezionare+copiare
pausebuilding = [accent][[{0}][] to pause building pausebuilding = [accent][[{0}][] per smettere di costruire
resumebuilding = [scarlet][[{0}][] per riprendere a costruire resumebuilding = [scarlet][[{0}][] per riprendere a costruire
wave = [accent]Ondata {0} wave = [accent]Ondata {0}
wave.waiting = [lightgray]Ondata tra {0} wave.waiting = [lightgray]Ondata tra {0}
@@ -279,7 +280,7 @@ custom = Personalizzato
builtin = Incluso builtin = Incluso
map.delete.confirm = Sei sicuro di voler eliminare questa mappa? L'operazione è irreversibile! map.delete.confirm = Sei sicuro di voler eliminare questa mappa? L'operazione è irreversibile!
map.random = [accent]Mappa casuale map.random = [accent]Mappa casuale
map.nospawn = Questa mappa non possiede un Nucleo in cui spawnare! Aggiungine uno nell'editor. map.nospawn = Questa mappa non possiede un Nucleo in cui generare! Aggiungine uno nell'editor.
map.nospawn.pvp = Questa mappa non ha un Nucleo Nemico! Aggiungi dei Nuclei nell'editor per poter giocare. map.nospawn.pvp = Questa mappa non ha un Nucleo Nemico! Aggiungi dei Nuclei nell'editor per poter giocare.
map.nospawn.attack = Questa mappa non ha nessun Nucleo Nemico da poter attaccare! Aggiungi dei Nuclei Nemici nell'editor per poter giocare. map.nospawn.attack = Questa mappa non ha nessun Nucleo Nemico da poter attaccare! Aggiungi dei Nuclei Nemici nell'editor per poter giocare.
map.invalid = Errore nel caricamento della mappa: file mappa corrotto o non valido. map.invalid = Errore nel caricamento della mappa: file mappa corrotto o non valido.
@@ -464,7 +465,7 @@ zone.resources = [lightgray]Risorse Trovate:
zone.objective = [lightgray]Obiettivo: [accent]{0} zone.objective = [lightgray]Obiettivo: [accent]{0}
zone.objective.survival = Sopravvivere zone.objective.survival = Sopravvivere
zone.objective.attack = Distruggere il Nucleo Nemico zone.objective.attack = Distruggere il Nucleo Nemico
add = Aggiungi... add = Aggiungi
boss.health = Vita del Boss boss.health = Vita del Boss
connectfail = [crimson]Impossibile connettersi al server:\n\n[accent] {0} connectfail = [crimson]Impossibile connettersi al server:\n\n[accent] {0}
@@ -531,6 +532,8 @@ error.crashtitle = Si è verificato un errore
blocks.input = Ingresso blocks.input = Ingresso
blocks.output = Uscita blocks.output = Uscita
blocks.booster = Potenziamenti blocks.booster = Potenziamenti
blocks.tiles = Blocchi Richiesti
blocks.affinities = Affinità
block.unknown = [lightgray]??? block.unknown = [lightgray]???
blocks.powercapacity = Capacità Energetica blocks.powercapacity = Capacità Energetica
blocks.powershot = Danno/Colpo blocks.powershot = Danno/Colpo
@@ -642,7 +645,7 @@ setting.difficulty.name = Difficoltà:
setting.screenshake.name = Movimento dello Schermo setting.screenshake.name = Movimento dello Schermo
setting.effects.name = Visualizza Effetti setting.effects.name = Visualizza Effetti
setting.destroyedblocks.name = Mostra Blocchi Distrutti setting.destroyedblocks.name = Mostra Blocchi Distrutti
setting.conveyorpathfinding.name = Conveyor Placement Pathfinding setting.conveyorpathfinding.name = Posizionamento Nastri Trasportatori Intelligente
setting.coreselect.name = Consenti Schematiche dei Nuclei setting.coreselect.name = Consenti Schematiche dei Nuclei
setting.sensitivity.name = Sensibilità del Controller setting.sensitivity.name = Sensibilità del Controller
setting.saveinterval.name = Intervallo di Salvataggio Automatico setting.saveinterval.name = Intervallo di Salvataggio Automatico
@@ -668,7 +671,7 @@ setting.publichost.name = Gioco Visibile Pubblicamente
setting.chatopacity.name = Opacità Chat setting.chatopacity.name = Opacità Chat
setting.lasersopacity.name = Opacità Raggi Energetici setting.lasersopacity.name = Opacità Raggi Energetici
setting.bridgeopacity.name = Opacità Nastri e Condotti Sopraelevati setting.bridgeopacity.name = Opacità Nastri e Condotti Sopraelevati
setting.playerchat.name = Mostra Chat in-game setting.playerchat.name = Mostra Chat
public.confirm = Vuoi rendere la tua partita pubblica?\n[accent]Chiunque sarà in grado di accedere alle tue partite.\n[lightgray]Questo può essere modificato più tardi in Impostazioni->Gioco->Partite Pubbliche. public.confirm = Vuoi rendere la tua partita pubblica?\n[accent]Chiunque sarà in grado di accedere alle tue partite.\n[lightgray]Questo può essere modificato più tardi in Impostazioni->Gioco->Partite Pubbliche.
public.beta = Nota che le versioni beta del gioco non possono creare lobby pubbliche. public.beta = Nota che le versioni beta del gioco non possono creare lobby pubbliche.
uiscale.reset = La scala dell'interfaccia utente è stata modificata.\nPremere 'OK' per confermare questa scala.\n[scarlet]Ripristina ed esci in [accent] {0}[] secondi... uiscale.reset = La scala dell'interfaccia utente è stata modificata.\nPremere 'OK' per confermare questa scala.\n[scarlet]Ripristina ed esci in [accent] {0}[] secondi...
@@ -933,7 +936,6 @@ block.lancer.name = Lanciere
block.conveyor.name = Nastro Trasportatore block.conveyor.name = Nastro Trasportatore
block.titanium-conveyor.name = Nastro Avanzato block.titanium-conveyor.name = Nastro Avanzato
block.armored-conveyor.name = Nastro Corazzato block.armored-conveyor.name = Nastro Corazzato
block.armored-conveyor.description = Trasporta gli oggetti alla stessa velocità del nastro avanzato, ma è più resistente. Accetta input dai lati solo da altri nastri.
block.junction.name = Incrocio block.junction.name = Incrocio
block.router.name = Distributore block.router.name = Distributore
block.distributor.name = Distributore Grande block.distributor.name = Distributore Grande
@@ -943,6 +945,7 @@ block.message.name = Messaggio
block.illuminator.name = Lanterna block.illuminator.name = Lanterna
block.illuminator.description = Una piccola, compatta sorgente di luce. Richiede energia per funzionare. block.illuminator.description = Una piccola, compatta sorgente di luce. Richiede energia per funzionare.
block.overflow-gate.name = Separatore per Eccesso block.overflow-gate.name = Separatore per Eccesso
block.underflow-gate.name = Separatore per Eccesso Inverso
block.silicon-smelter.name = Fonderia block.silicon-smelter.name = Fonderia
block.phase-weaver.name = Tessitore di Fase block.phase-weaver.name = Tessitore di Fase
block.pulverizer.name = Polverizzatore block.pulverizer.name = Polverizzatore
@@ -1138,12 +1141,12 @@ block.spore-press.description = Comprime le spore in petrolio.
block.pulverizer.description = Polverizza la pietra.\nUtile quando manca la sabbia naturale. block.pulverizer.description = Polverizza la pietra.\nUtile quando manca la sabbia naturale.
block.coal-centrifuge.description = Solidifica il petrolio in pezzi di carbone. block.coal-centrifuge.description = Solidifica il petrolio in pezzi di carbone.
block.incinerator.description = Elimina qualsiasi oggetto o liquido in eccesso. block.incinerator.description = Elimina qualsiasi oggetto o liquido in eccesso.
block.power-void.description = Elimina tutta l'energia che riceve, esiste solo nella modalità creativa. block.power-void.description = Elimina tutta l'energia che riceve. Esiste solo nella modalità creativa.
block.power-source.description = Produce energia infinita, esiste solo nella modalità creativa. block.power-source.description = Produce energia infinita. Esiste solo nella modalità creativa.
block.item-source.description = Produce oggetti infiniti, esiste solo nella modalità creativa. block.item-source.description = Produce oggetti infiniti. Esiste solo nella modalità creativa.
block.item-void.description = Elimina gli oggetti che vi entrano senza bisogno di energia, esiste solo nella modalità creativa. block.item-void.description = Elimina gli oggetti che vi entrano senza bisogno di energia. Esiste solo nella modalità creativa.
block.liquid-source.description = Emette continuamente liquidi. Esiste solo nella modalità creativa. block.liquid-source.description = Emette continuamente liquidi. Esiste solo nella modalità creativa.
block.liquid-void.description = Elimina i liquidi in entrata, esiste solo nella modalità creativa. block.liquid-void.description = Elimina i liquidi in entrata. Esiste solo nella modalità creativa.
block.copper-wall.description = Un blocco difensivo economico.\nUtile per proteggere il Nucleo e le torrette nelle prime ondate. block.copper-wall.description = Un blocco difensivo economico.\nUtile per proteggere il Nucleo e le torrette nelle prime ondate.
block.copper-wall-large.description = Un blocco difensivo economico.\nUtile per proteggere il Nucleo e le torrette nelle prime ondate.\nOccupa più blocchi. block.copper-wall-large.description = Un blocco difensivo economico.\nUtile per proteggere il Nucleo e le torrette nelle prime ondate.\nOccupa più blocchi.
block.titanium-wall.description = Un blocco difensivo moderatamente forte.\nFornisce una protezione moderata dai nemici. block.titanium-wall.description = Un blocco difensivo moderatamente forte.\nFornisce una protezione moderata dai nemici.
@@ -1163,17 +1166,19 @@ block.mend-projector.description = Ripara periodicamente blocchi nelle vicinanze
block.overdrive-projector.description = Aumenta la velocità di edifici vicini come trivelle e nastri trasportatori. block.overdrive-projector.description = Aumenta la velocità di edifici vicini come trivelle e nastri trasportatori.
block.force-projector.description = Crea un campo di forza esagonale attorno a sé, proteggendo gli edifici e le unità all'interno da danni causati da proiettili. block.force-projector.description = Crea un campo di forza esagonale attorno a sé, proteggendo gli edifici e le unità all'interno da danni causati da proiettili.
block.shock-mine.description = Danneggia i nemici che la calpestano. Quasi invisibile al nemico. block.shock-mine.description = Danneggia i nemici che la calpestano. Quasi invisibile al nemico.
block.conveyor.description = Nastro di base. Sposta gli oggetti in avanti e li deposita automaticamente in altri blocchi. Ruotabile. block.conveyor.description = Nastro di base. Sposta gli oggetti in avanti e li deposita automaticamente in altri blocchi. È rotabile.
block.titanium-conveyor.description = Nastro avanzato. Sposta gli oggetti più velocemente dei nastri standard. block.titanium-conveyor.description = Nastro avanzato. Sposta gli oggetti più velocemente dei nastri standard.
block.armored-conveyor.description = Trasporta gli oggetti alla stessa velocità del nastro avanzato, ma è più resistente. Accetta input dai lati solo da altri nastri.
block.junction.description = Permette di incrociare nastri che trasportano materiali diversi in posizioni diverse. block.junction.description = Permette di incrociare nastri che trasportano materiali diversi in posizioni diverse.
block.bridge-conveyor.description = Consente il trasporto di oggetti fino a 3 blocchi ad un altro nastro sopraelevato.\nPuò passare sopra ad altri blocchi od edifici. block.bridge-conveyor.description = Consente il trasporto di oggetti fino a 3 blocchi ad un altro nastro sopraelevato.\nPuò passare sopra ad altri blocchi od edifici.
block.phase-conveyor.description = Nastro avanzato. Consuma energia per teletrasportare gli oggetti su un altro nastro di fase collegato. block.phase-conveyor.description = Nastro avanzato. Consuma energia per teletrasportare gli oggetti su un altro nastro di fase collegato.
block.sorter.description = Divide gli oggetti. Se l'oggetto corrisponde a quello selezionato, Può passare. Altrimenti viene espulso sui lati. block.sorter.description = Divide gli oggetti. Se l'oggetto corrisponde a quello selezionato, Può passare. Altrimenti viene espulso sui lati.
block.inverted-sorter.description = Elabora gli oggetti come uno smistatore standard, ma in uscita dà gli elementi selezionati ai lati. block.inverted-sorter.description = Elabora gli oggetti come uno filtro standard, ma in uscita dà gli elementi selezionati ai lati.
block.router.description = Accetta gli elementi da una direzione e li emette fino a 3 altre direzioni allo stesso modo. Utile per suddividere i materiali da una fonte a più destinazioni. block.router.description = Accetta gli elementi da una direzione e li emette fino a 3 altre direzioni allo stesso modo. Utile per suddividere i materiali da una fonte a più destinazioni.
block.distributor.description = Un distributore avanzato che divide gli oggetti in altre 7 direzioni allo stesso modo. block.distributor.description = Un distributore avanzato che divide gli oggetti in altre 7 direzioni allo stesso modo.
block.overflow-gate.description = Una combinazione di un incrocio e di un distributore, che distribuisce sui suoi lati se in nastro difronte si satura. block.overflow-gate.description = Distribuisce gli oggetti ai lati se il nastro davanti a sé è saturo.
block.mass-driver.description = Ultimo blocco di trasporto di oggetti. Raccoglie diversi oggetti e poi li spara su un'altra Lìlancia materiali a lungo raggio. block.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.mechanical-pump.description = Una pompa economica a bassa efficienza, ma nessun consumo di energia. block.mechanical-pump.description = Una pompa economica a bassa efficienza, ma nessun consumo di energia.
block.rotary-pump.description = Una pompa avanzata che raddoppia la velocità consumando energia. block.rotary-pump.description = Una pompa avanzata che raddoppia la velocità consumando energia.
block.thermal-pump.description = La pompa migliore. Tre volte più veloce di una pompa meccanica e l'unica pompa in grado di recuperare la lava. block.thermal-pump.description = La pompa migliore. Tre volte più veloce di una pompa meccanica e l'unica pompa in grado di recuperare la lava.

View File

@@ -29,12 +29,12 @@ load.system = 시스템
load.mod = 모드 load.mod = 모드
load.scripts = 스크립트 load.scripts = 스크립트
be.update = A new Bleeding Edge build is available: be.update = 새로운 블리딩 엣지 버전이 출시되었습니다.
be.update.confirm = Download it and restart now? be.update.confirm = 다운로드 후 게임을 재시작하시겠습니까?
be.updating = Updating... be.updating = 업데이트 중...
be.ignore = Ignore be.ignore = 무시
be.noupdates = No updates found. be.noupdates = 새로운 업데이트가 발견되지 않았습니다.
be.check = Check for updates be.check = 업데이트 확인
schematic = 설계도 schematic = 설계도
schematic.add = 설계도 저장하기 schematic.add = 설계도 저장하기
@@ -98,15 +98,15 @@ done = 완료
feature.unsupported = 당신의 기기는 이 기능을 지원하지 않습니다. feature.unsupported = 당신의 기기는 이 기능을 지원하지 않습니다.
mods.alphainfo = 현재의 모드는 첫 번째 시도이며, 그리고[scarlet] 버그가 매우 많음을 명심하십시오[].\n만약 버그를 발견할경우 Mindustry 깃허브 또는 디스코드로 제보해주세요. mods.alphainfo = 현재의 모드는 첫 번째 시도이며, 그리고[scarlet] 버그가 매우 많음을 명심하십시오[].\n만약 버그를 발견할경우 Mindustry 깃허브 또는 디스코드로 제보해주세요.
mods.alpha = [scarlet](Alpha) mods.alpha=[accent](시험적 기능)
mods = 모드 mods = 모드
mods.none = [LIGHT_GRAY]추가한 모드가 없습니다! mods.none = [LIGHT_GRAY]추가한 모드가 없습니다!
mods.guide = 모드 가이드 mods.guide = 모드 가이드
mods.report = 문제 신고 mods.report = 문제 신고
mods.openfolder = 모드 폴더 열기 mods.openfolder = 모드 폴더 열기
mod.enabled = [lightgray]활성화 mod.enabled=[blue]활성화
mod.disabled = [scarlet]비활성화 mod.disabled=[scarlet]적용 안됨
mod.disable = 비활성화 mod.disable=[lightgray]비활성화
mod.delete.error = 모드를 삭제할 수 없습니다. 아마도 해당 모드가 사용중인 것 같습니다. mod.delete.error = 모드를 삭제할 수 없습니다. 아마도 해당 모드가 사용중인 것 같습니다.
mod.requiresversion = [scarlet]게임의 버전이 낮아 모드를 활성화할 수 없습니다!\n[scarlet]요구되는 게임 버전 : [accent]{0} mod.requiresversion = [scarlet]게임의 버전이 낮아 모드를 활성화할 수 없습니다!\n[scarlet]요구되는 게임 버전 : [accent]{0}
mod.missingdependencies = [scarlet]의존되는 모드: {0} mod.missingdependencies = [scarlet]의존되는 모드: {0}
@@ -114,7 +114,7 @@ mod.erroredcontent = [scarlet]컨텐츠 오류
mod.errors = 컨텐츠를 불러오는 중 오류가 발생하였습니다. mod.errors = 컨텐츠를 불러오는 중 오류가 발생하였습니다.
mod.noerrorplay = [scarlet]모드에 오류가 존재합니다.[] 해당 오류가 발생하는 모드를 비활성화하거나 모드의 오류를 고친 후 플레이가 가능합니다. mod.noerrorplay = [scarlet]모드에 오류가 존재합니다.[] 해당 오류가 발생하는 모드를 비활성화하거나 모드의 오류를 고친 후 플레이가 가능합니다.
mod.nowdisabled = [scarlet]모드 '{0}'는 다음의 모드에 의존합니다 : [accent] {1}\n[lightgray]이 모드를 먼저 다운로드해야합니다.\n이 모드는 자동으로 비활성화됩니다. mod.nowdisabled = [scarlet]모드 '{0}'는 다음의 모드에 의존합니다 : [accent] {1}\n[lightgray]이 모드를 먼저 다운로드해야합니다.\n이 모드는 자동으로 비활성화됩니다.
mod.enable = 활성화 mod.enable=활성화
mod.requiresrestart = 모드 변경사항을 적용하기 위해 게임을 종료합니다. mod.requiresrestart = 모드 변경사항을 적용하기 위해 게임을 종료합니다.
mod.reloadrequired = [scarlet]새로고침 예정됨 mod.reloadrequired = [scarlet]새로고침 예정됨
mod.import = 모드 추가 mod.import = 모드 추가
@@ -123,8 +123,8 @@ mod.item.remove = 이것은 모드[accent] '{0}'[]의 자원입니다. 이 자
mod.remove.confirm = 이 모드를 삭제하시겠습니까? mod.remove.confirm = 이 모드를 삭제하시겠습니까?
mod.author = [LIGHT_GRAY]제작자 : [] {0} mod.author = [LIGHT_GRAY]제작자 : [] {0}
mod.missing = 이 세이브파일에는 설치하지 않은 모드 혹은 현재 버전에 속해있지 않은 데이터가 포함되어 있습니다. 이 파일을 불러올 경우 세이브파일의 데이터가 손상될 수 있습니다. 정말로 이 파일을 불러오시겠습니까?\n[lightgray]모드 :\n{0} mod.missing = 이 세이브파일에는 설치하지 않은 모드 혹은 현재 버전에 속해있지 않은 데이터가 포함되어 있습니다. 이 파일을 불러올 경우 세이브파일의 데이터가 손상될 수 있습니다. 정말로 이 파일을 불러오시겠습니까?\n[lightgray]모드 :\n{0}
mod.preview.missing = 워크샵에 당신의 모드를 업로드하기 전에 미리보기 이미지를 먼저 추가해야합니다.\n[accent] preview.png[]라는 이름으로 미리보기 이미지를 당신의 모드 폴더안에 준비한 후 다시 시도해주세요. mod.preview.missing=Workshop에 당신의 모드를 업로드하기 전에 미리보기 이미지를 먼저 추가해야합니다.\n[accent] preview.png[]라는 이름으로 미리보기 이미지를 당신의 모드 폴더안에 준비한 후 다시 시도해주세요.
mod.folder.missing = 워크샵에는 폴더 형태의 모드만 게시할 수 있습니다.\n모드를 폴더 형태로 바꾸려면 파일을 폴더에 압축 해제하고 이전 압축파일을 제거한 후, 게임을 재시작하거나 모드를 다시 로드하십시오. mod.folder.missing=Workshop에는 폴더 형태의 모드만 게시할 수 있습니다.\n모드를 폴더 형태로 바꾸려면 파일을 폴더에 압축 해제하고 이전 압축파일을 제거한 후, 게임을 재시작하거나 모드를 다시 로드하십시오.
mod.scripts.unsupported = 당신의 기기는 모드스크립트를 지원하지 않습니다. 모드의 일부 기능이 작동하지 않을 수 있습니다. mod.scripts.unsupported = 당신의 기기는 모드스크립트를 지원하지 않습니다. 모드의 일부 기능이 작동하지 않을 수 있습니다.
about.button = 정보 about.button = 정보
@@ -155,10 +155,10 @@ server.kicked.nameEmpty = 당신의 닉네임이 비어있습니다.
server.kicked.idInUse = 이미 서버에 접속중입니다! 다중 계정은 허용되지 않습니다. server.kicked.idInUse = 이미 서버에 접속중입니다! 다중 계정은 허용되지 않습니다.
server.kicked.customClient = 이 서버는 직접 빌드한 버전을 지원하지 않습니다. 공식 버전을 사용하세요. server.kicked.customClient = 이 서버는 직접 빌드한 버전을 지원하지 않습니다. 공식 버전을 사용하세요.
server.kicked.gameover = 코어가 파괴되었습니다... server.kicked.gameover = 코어가 파괴되었습니다...
server.kicked.serverRestarting = The server is restarting. server.kicked.serverRestarting = 서버가 재시작합니다.
server.versions = 클라이언트 버전 : [accent] {0}[]\n서버 버전 : [accent] {1}[] server.versions = 클라이언트 버전 : [accent] {0}[]\n서버 버전 : [accent] {1}[]
host.info = [accent]호스트[] 버튼은 현재 네트워크의 [scarlet]6567[] 포트를 사용합니다.\n[LIGHT_GRAY]같은 Wi-Fi 또는 로컬 네트워크[] 에서 서버 목록을 볼 수 있습니다.\n\n만약 플레이어들이 이 IP를 통해 어디에서나 연결할 수 있게 하고 싶다면, 공유기 설정에서 [accent]포트 포워딩[]을 하시거나 VPN을 사용하셔야 합니다.\n\n[LIGHT_GRAY]참고: LAN 게임 연결에 문제가 있는 사람이 있다면, 방화벽 설정에서 Mindustry 가 로컬 네트워크에 액세스하도록 허용했는지 확인해주세요. host.info = [accent]호스트[] 버튼은 현재 네트워크의 [scarlet]6567[] 포트를 사용합니다.\n[LIGHT_GRAY]같은 Wi-Fi 또는 로컬 네트워크[] 에서 서버 목록을 볼 수 있습니다.\n\n만약 플레이어들이 이 IP를 통해 어디에서나 연결할 수 있게 하고 싶다면, 공유기 설정에서 [accent]포트 포워딩[]을 하시거나 VPN을 사용하셔야 합니다.\n\n[LIGHT_GRAY]참고: LAN 게임 연결에 문제가 있는 사람이 있다면, 방화벽 설정에서 Mindustry 가 로컬 네트워크에 액세스하도록 허용했는지 확인해주세요.
join.info = 여기서 서버 추가를 누르신 후, [accent]서버 IP[]를 입력하여 다른 서버에 접속할 수 있습니다.\n또는 [accent]로컬 네트워크(LAN)[] 서버를 검색하여 접속할 수 있습니다.\nLAN 및 WAN 멀티 플레이어 모두 지원합니다.\n\n[LIGHT_GRAY]참고:여기에서는 자동으로 글로벌 서버를 추가하지 않습니다. IP로 다른 사람의 서버에 접속하려면 직접 서버 주소를 찾아서 적으셔야합니다.[]\n\n[ROYAL]한국의 서버로는 [accent]mindustry.kr[]의 6567, 6568포트와 [accent]server1.mindustry.r-e.kr[]의 8000, 8002 포트가 있습니다.\n서버 주소 입력방법은 < 주소:포트 >의 형식입니다.\n[royal]포트가 없을 시에는 그냥 주소만 입력하시면 됩니다.\n\n[royal]예시) mindustry.kr의 6567포트\nmindustry.kr:6567\n포트가 6567일 경우에는 :6567을 생략할 수 있습니다. join.info = 여기서 서버 추가를 누르신 후, [accent]서버 IP[]를 입력하여 다른 서버에 접속할 수 있습니다.\n또는 [accent]로컬 네트워크(LAN)[] 서버를 검색하여 접속할 수 있습니다.\nLAN 및 WAN 멀티 플레이어 모두 지원합니다.\n\n[LIGHT_GRAY]참고:여기에서는 자동으로 글로벌 서버를 추가하지 않습니다. IP로 다른 사람의 서버에 접속하려면 직접 서버 주소를 찾아서 적으셔야합니다.[]\n\n[ROYAL]한국의 서버로는 [accent]mindustry.kr[]가 있습니다.\n서버 주소 입력방법은 < 주소:포트 >의 형식입니다.\n[royal]포트가 없을 시에는 그냥 주소만 입력하시면 됩니다.\n\n[royal]예시) mindustry.kr의 6567포트\nmindustry.kr:6567\n포트가 6567일 경우에는 :6567을 생략할 수 있습니다.
hostserver = 서버 열기 hostserver = 서버 열기
invitefriends = 친구 초대 invitefriends = 친구 초대
hostserver.mobile = 서버\n열기 hostserver.mobile = 서버\n열기
@@ -240,8 +240,8 @@ save.playtime = 플레이타임 : {0}
warning = 경고. warning = 경고.
confirm = 확인 confirm = 확인
delete = 삭제 delete = 삭제
view.workshop = 워크샵에서 보기 view.workshop=Workshop에서 보기
workshop.listing = 워크샵 목록 편집하기 workshop.listing=Workshop 목록 편집하기
ok = 확인 ok = 확인
open = 열기 open = 열기
customize = 맞춤설정 customize = 맞춤설정
@@ -310,7 +310,7 @@ editor.generation = 맵 생성 설정 :
editor.ingame = 인게임 편집 editor.ingame = 인게임 편집
editor.publish.workshop = 워크샵 업로드 editor.publish.workshop = 워크샵 업로드
editor.newmap = 신규 맵 editor.newmap = 신규 맵
workshop = 워크샵 workshop=Workshop
waves.title = 단계 waves.title = 단계
waves.remove = 삭제 waves.remove = 삭제
waves.never = 여기까지 유닛생성 waves.never = 여기까지 유닛생성
@@ -377,15 +377,15 @@ toolmode.replace = 재배치
toolmode.replace.description = 블록을 배치합니다. toolmode.replace.description = 블록을 배치합니다.
toolmode.replaceall = 모두 재배치 toolmode.replaceall = 모두 재배치
toolmode.replaceall.description = 맵에 있는 모든 블록을 재배치합니다. toolmode.replaceall.description = 맵에 있는 모든 블록을 재배치합니다.
toolmode.orthogonal = toolmode.orthogonal=
toolmode.orthogonal.description = 로 블록을 배치합니다. toolmode.orthogonal.description=각으로 블록을 배치합니다.
toolmode.square = 정사각형 toolmode.square = 정사각형
toolmode.square.description = 정사각형 형태의 브러시. toolmode.square.description = 정사각형 형태의 브러시.
toolmode.eraseores = 자원 초기화 toolmode.eraseores = 자원 초기화
toolmode.eraseores.description = 자원만 초기화합니다. toolmode.eraseores.description = 자원만 초기화합니다.
toolmode.fillteams = 팀 채우기 toolmode.fillteams = 팀 채우기
toolmode.fillteams.description = 블록 대신 팀 건물로 채웁니다. toolmode.fillteams.description = 블록 대신 팀 건물로 채웁니다.
toolmode.drawteams = 팀 그리기 toolmode.drawteams= 색상으로 그리기
toolmode.drawteams.description = 블록 대신 팀 건물을 배치합니다. toolmode.drawteams.description = 블록 대신 팀 건물을 배치합니다.
filters.empty = [LIGHT_GRAY]필터가 없습니다!! 아래 버튼을 눌러 추가하세요. filters.empty = [LIGHT_GRAY]필터가 없습니다!! 아래 버튼을 눌러 추가하세요.
@@ -580,7 +580,7 @@ bar.power = 전력
bar.progress = 생산 진행도 bar.progress = 생산 진행도
bar.spawned = 최대 {1}기 중 {0}기 생산됨 bar.spawned = 최대 {1}기 중 {0}기 생산됨
bar.input = 입력 bar.input = 입력
bar.output = Output bar.output =
bullet.damage = [lightgray]피해량 : [stat]{0}[] bullet.damage = [lightgray]피해량 : [stat]{0}[]
bullet.splashdamage = [lightgray]범위 피해량 : [stat]{0}[] / [lightgray]피해 범위 : [stat]{1}[lightgray] 타일 bullet.splashdamage = [lightgray]범위 피해량 : [stat]{0}[] / [lightgray]피해 범위 : [stat]{1}[lightgray] 타일
@@ -643,7 +643,7 @@ setting.screenshake.name = 화면 흔들기
setting.effects.name = 화면 효과 setting.effects.name = 화면 효과
setting.destroyedblocks.name = 부서진 블럭 표시 setting.destroyedblocks.name = 부서진 블럭 표시
setting.conveyorpathfinding.name = 교차기 자동 설치 setting.conveyorpathfinding.name = 교차기 자동 설치
setting.coreselect.name = Allow Schematic Cores setting.coreselect.name = Schematic Cores 켜기
setting.sensitivity.name = 컨트롤러 감도 setting.sensitivity.name = 컨트롤러 감도
setting.saveinterval.name = 저장 간격 setting.saveinterval.name = 저장 간격
setting.seconds = {0} 초 setting.seconds = {0} 초
@@ -690,7 +690,7 @@ keybind.toggle_power_lines.name = 전력 라인 허용
keybind.move_x.name = 오른쪽 / 왼쪽 이동 keybind.move_x.name = 오른쪽 / 왼쪽 이동
keybind.move_y.name = 위 / 아래 이동 keybind.move_y.name = 위 / 아래 이동
keybind.mouse_move.name = 커서를 따라서 이동 keybind.mouse_move.name = 커서를 따라서 이동
keybind.dash.name = 달리기 keybind.dash.name = 부스터
keybind.schematic_select.name = 영역 설정 keybind.schematic_select.name = 영역 설정
keybind.schematic_menu.name = 설계도 메뉴 keybind.schematic_menu.name = 설계도 메뉴
keybind.schematic_flip_x.name = 설계도 X축 뒤집기 keybind.schematic_flip_x.name = 설계도 X축 뒤집기
@@ -755,7 +755,7 @@ rules.enemyCheat = 무한한 적 자원
rules.unitdrops = 유닛 처치시 자원 약탈 rules.unitdrops = 유닛 처치시 자원 약탈
rules.unitbuildspeedmultiplier = 유닛 제조속도 배수 rules.unitbuildspeedmultiplier = 유닛 제조속도 배수
rules.unithealthmultiplier = 유닛 체력 배수 rules.unithealthmultiplier = 유닛 체력 배수
rules.blockhealthmultiplier = Block Health Multiplier rules.blockhealthmultiplier = 건물 체력 배수
rules.playerhealthmultiplier = 플레이어 체력 배수 rules.playerhealthmultiplier = 플레이어 체력 배수
rules.playerdamagemultiplier = 플레이어 공격력 배수 rules.playerdamagemultiplier = 플레이어 공격력 배수
rules.unitdamagemultiplier = 유닛 공격력 배수 rules.unitdamagemultiplier = 유닛 공격력 배수
@@ -978,7 +978,6 @@ block.mechanical-pump.name = 기계식 펌프
block.item-source.name = 아이템 소스 block.item-source.name = 아이템 소스
block.item-void.name = 아이템 삭제 장치 block.item-void.name = 아이템 삭제 장치
block.liquid-source.name = 무한 액체공급 장치 block.liquid-source.name = 무한 액체공급 장치
block.liquid-void.name = Liquid Void
block.power-void.name = 방전장치 block.power-void.name = 방전장치
block.power-source.name = 무한 전력공급 장치 block.power-source.name = 무한 전력공급 장치
block.unloader.name = 언로더 block.unloader.name = 언로더
@@ -1142,7 +1141,6 @@ block.power-source.description = 무한한 전력을 공급해주는 블록입
block.item-source.description = 자원을 선택하면 그 자원이 무한하게 생성되는 블록입니다.\n샌드박스에서만 건설가능. block.item-source.description = 자원을 선택하면 그 자원이 무한하게 생성되는 블록입니다.\n샌드박스에서만 건설가능.
block.item-void.description = 자원을 사라지게 만듭니다.\n샌드박스에서만 건설가능. block.item-void.description = 자원을 사라지게 만듭니다.\n샌드박스에서만 건설가능.
block.liquid-source.description = 무한한 액체를 출력합니다.\n샌드박스에서만 건설가능. block.liquid-source.description = 무한한 액체를 출력합니다.\n샌드박스에서만 건설가능.
block.liquid-void.description = Removes any liquids. Sandbox only.
block.copper-wall.description = 게임 시작 초기에 방어용으로 적합합니다. block.copper-wall.description = 게임 시작 초기에 방어용으로 적합합니다.
block.copper-wall-large.description = 구리 벽 4개를 뭉친 블럭입니다. block.copper-wall-large.description = 구리 벽 4개를 뭉친 블럭입니다.
block.titanium-wall.description = 흑연이 생산될 즈음에 사용하기 적합합니다. block.titanium-wall.description = 흑연이 생산될 즈음에 사용하기 적합합니다.

View File

@@ -12,7 +12,7 @@ link.itch.io.description = Pagina da Itch.io com os Descarregamentos
link.google-play.description = Listamento do google play store link.google-play.description = Listamento do google play store
link.f-droid.description = F-Droid catalogue listing link.f-droid.description = F-Droid catalogue listing
link.wiki.description = Wiki oficial do Mindustry link.wiki.description = Wiki oficial do Mindustry
link.feathub.description = Suggest new features link.feathub.description = Sugerir novas funcionalidades
linkfail = Falha ao abrir a ligação\nO Url foi copiado linkfail = Falha ao abrir a ligação\nO Url foi copiado
screenshot = Screenshot gravado para {0} screenshot = Screenshot gravado para {0}
screenshot.invalid = Mapa grande demais, Potencialmente sem memória suficiente para captura. screenshot.invalid = Mapa grande demais, Potencialmente sem memória suficiente para captura.
@@ -29,12 +29,12 @@ load.system = Sistema
load.mod = Mods load.mod = Mods
load.scripts = Scripts load.scripts = Scripts
be.update = A new Bleeding Edge build is available: be.update = Uma nova versão do Bleeding Edge está disponível:
be.update.confirm = Download it and restart now? be.update.confirm = Transferir e reiniciar agora?
be.updating = Updating... be.updating = A atualizar...
be.ignore = Ignore be.ignore = Ignora
be.noupdates = No updates found. be.noupdates = Atualizações não encontradas.
be.check = Check for updates be.check = A Verificar por atualizações
schematic = Esquema schematic = Esquema
schematic.add = Gravar Esquema... schematic.add = Gravar Esquema...
@@ -62,7 +62,7 @@ stat.delivered = Recursos lançados:
stat.rank = Rank Final: [accent]{0} stat.rank = Rank Final: [accent]{0}
launcheditems = [accent]Itens lançados launcheditems = [accent]Itens lançados
launchinfo = [unlaunched][[LAUNCH] your core to obtain the items indicated in blue. launchinfo = [unlaunched][[LAUNCH] seu núcleo para obter os itens indicados em azul.
map.delete = Certeza que quer deletar o mapa "[accent]{0}[]"? map.delete = Certeza que quer deletar o mapa "[accent]{0}[]"?
level.highscore = Melhor\npontuação: [accent] {0} level.highscore = Melhor\npontuação: [accent] {0}
level.select = Seleção de Fase level.select = Seleção de Fase
@@ -108,18 +108,18 @@ mod.enabled = [lightgray]Ativado
mod.disabled = [scarlet]Desativado mod.disabled = [scarlet]Desativado
mod.disable = Desativar mod.disable = Desativar
mod.delete.error = Incapaz de apagar o mod. Ficheiro já em uso. mod.delete.error = Incapaz de apagar o mod. Ficheiro já em uso.
mod.requiresversion = [scarlet]Requires min game version: [accent]{0} mod.requiresversion = [scarlet]Requer versão minima de jogo: [accent]{0}
mod.missingdependencies = [scarlet]Dependências ausentes: {0} mod.missingdependencies = [scarlet]Dependências ausentes: {0}
mod.erroredcontent = [scarlet]Content Errors mod.erroredcontent = [scarlet]Erros de conteudo
mod.errors = Errors have occurred loading content. mod.errors = Ocorreram erros ao carregar o conteúdo.
mod.noerrorplay = [scarlet]You have mods with errors.[] Either disable the affected mods or fix the errors before playing. mod.noerrorplay = [scarlet]Tens mods com erros.[] Desative os mods afetados ou corrija os erros antes de jogar.
mod.nowdisabled = [scarlet]Mod '{0}' está faltando dependências:[accent] {1}\n[lightgray]Esses mods precisam ser baixados primeiro. NEste mod será automaticamente desativado mod.nowdisabled = [scarlet]Mod '{0}' está faltando dependências:[accent] {1}\n[lightgray]Esses mods precisam ser baixados primeiro. NEste mod será automaticamente desativado
mod.enable = Ativar mod.enable = Ativar
mod.requiresrestart = O jogo será fechado agora para aplicar as alterações no mod. mod.requiresrestart = O jogo será fechado agora para aplicar as alterações no mod.
mod.reloadrequired = [scarlet]Reload Required mod.reloadrequired = [scarlet]É necessario recarregar
mod.import = Importar Mod mod.import = Importar Mod
mod.import.github = Importar Mod pelo GitHub mod.import.github = Importar Mod pelo GitHub
mod.item.remove = This item is part of the[accent] '{0}'[] mod. To remove it, uninstall that mod. mod.item.remove = Este item faz parte do [accent] '{0}'[] mod. Para lhe remover, desinstala o mod.
mod.remove.confirm = Este mod irá ser apagado. mod.remove.confirm = Este mod irá ser apagado.
mod.author = [LIGHT_GRAY]Autor:[] {0} mod.author = [LIGHT_GRAY]Autor:[] {0}
mod.missing = Este save contém mods que foram recentemente atualizados ou que não estão mais instalados. Ao guardar pode ocorreu corrupção. Tem certeza de que deseja carregá-lo?\n[lightgray]Mods:\n{0} mod.missing = Este save contém mods que foram recentemente atualizados ou que não estão mais instalados. Ao guardar pode ocorreu corrupção. Tem certeza de que deseja carregá-lo?\n[lightgray]Mods:\n{0}

View File

@@ -251,6 +251,7 @@ copylink = Скопировать ссылку
back = Назад back = Назад
data.export = Экспортировать данные data.export = Экспортировать данные
data.import = Импортировать данные data.import = Импортировать данные
data.openfolder = Открыть папку с данными
data.exported = Данные экспортированы. data.exported = Данные экспортированы.
data.invalid = Эти игровые данные являются недействительными. data.invalid = Эти игровые данные являются недействительными.
data.import.confirm = Импорт внешних данных сотрёт[scarlet] все[] Ваши игровые данные.\n[accent]Это не может быть отменено![]\n\nКак только данные импортированы, Ваша игра немедленно закроется. data.import.confirm = Импорт внешних данных сотрёт[scarlet] все[] Ваши игровые данные.\n[accent]Это не может быть отменено![]\n\nКак только данные импортированы, Ваша игра немедленно закроется.
@@ -531,6 +532,8 @@ error.crashtitle = Произошла ошибка
blocks.input = Вход blocks.input = Вход
blocks.output = Выход blocks.output = Выход
blocks.booster = Ускоритель blocks.booster = Ускоритель
blocks.tiles = Необходимые плитки
blocks.affinities = Увеличение эффективности
block.unknown = [lightgray]??? block.unknown = [lightgray]???
blocks.powercapacity = Вместимость энергии blocks.powercapacity = Вместимость энергии
blocks.powershot = Энергия/Выстрел blocks.powershot = Энергия/Выстрел
@@ -607,7 +610,7 @@ unit.timesspeed = x скорость
unit.percent = % unit.percent = %
unit.items = предметов unit.items = предметов
unit.thousands = тыс unit.thousands = тыс
unit.millions = мил unit.millions = млн
category.general = Основные category.general = Основные
category.power = Энергия category.power = Энергия
category.liquids = Жидкости category.liquids = Жидкости
@@ -666,7 +669,9 @@ setting.crashreport.name = Отправлять анонимные отчёты
setting.savecreate.name = Автоматическое создание сохранений setting.savecreate.name = Автоматическое создание сохранений
setting.publichost.name = Общедоступность игры setting.publichost.name = Общедоступность игры
setting.chatopacity.name = Непрозрачность чата setting.chatopacity.name = Непрозрачность чата
setting.playerlimit.name = Лимит игроков
setting.lasersopacity.name = Непрозрачность лазеров энергоснабжения setting.lasersopacity.name = Непрозрачность лазеров энергоснабжения
setting.bridgeopacity.name = Непрозрачность мостов
setting.playerchat.name = Отображать облака чата над игроками setting.playerchat.name = Отображать облака чата над игроками
public.confirm = Вы хотите, чтобы Ваша игра стала публичной?\n[accent] Любой игрок сможет присоединиться к Вашем играм.\n[lightgray]Позже, это можно будет изменить в Настройки->Игра->Общедоступность игры. public.confirm = Вы хотите, чтобы Ваша игра стала публичной?\n[accent] Любой игрок сможет присоединиться к Вашем играм.\n[lightgray]Позже, это можно будет изменить в Настройки->Игра->Общедоступность игры.
public.beta = Имейте в виду, что бета-версия игры не может делать игры публичными. public.beta = Имейте в виду, что бета-версия игры не может делать игры публичными.
@@ -942,6 +947,7 @@ block.message.name = Сообщение
block.illuminator.name = Осветитель block.illuminator.name = Осветитель
block.illuminator.description = Маленький, компактный, настраиваемый источник света. Требуется энергия для работы. block.illuminator.description = Маленький, компактный, настраиваемый источник света. Требуется энергия для работы.
block.overflow-gate.name = Избыточный затвор block.overflow-gate.name = Избыточный затвор
block.underflow-gate.name = Избыточный шлюз
block.silicon-smelter.name = Кремниевый плавильный завод block.silicon-smelter.name = Кремниевый плавильный завод
block.phase-weaver.name = Фазовый ткач block.phase-weaver.name = Фазовый ткач
block.pulverizer.name = Измельчитель block.pulverizer.name = Измельчитель
@@ -978,7 +984,7 @@ block.mechanical-pump.name = Механическая помпа
block.item-source.name = Источник предметов block.item-source.name = Источник предметов
block.item-void.name = Предметный вакуум block.item-void.name = Предметный вакуум
block.liquid-source.name = Источник жидкостей block.liquid-source.name = Источник жидкостей
block.liquid-void.name = Liquid Void block.liquid-void.name = Жидкостный вакуум
block.power-void.name = Энергетический вакуум block.power-void.name = Энергетический вакуум
block.power-source.name = Источник энергии block.power-source.name = Источник энергии
block.unloader.name = Разгрузчик block.unloader.name = Разгрузчик
@@ -1128,7 +1134,7 @@ block.kiln.description = Выплавляет песок и свинец в со
block.plastanium-compressor.description = Производит пластан из нефти и титана. block.plastanium-compressor.description = Производит пластан из нефти и титана.
block.phase-weaver.description = Синтезирует фазовую ткань из радиоактивного тория и песка. Требуется огромное количество энергии для работы. block.phase-weaver.description = Синтезирует фазовую ткань из радиоактивного тория и песка. Требуется огромное количество энергии для работы.
block.alloy-smelter.description = Объединяет титан, свинец, кремний и медь для производства кинетического сплава. block.alloy-smelter.description = Объединяет титан, свинец, кремний и медь для производства кинетического сплава.
block.cryofluidmixer.description = Смешивает воду и мелкий титановый порошок титана в криогеннную жидкость. Неотъемлемая часть при использования ториевого реактора block.cryofluidmixer.description = Смешивает воду и мелкий титановый порошок в криогеннную жидкость. Неотъемлемая часть при использования ториевого реактора
block.blast-mixer.description = Раздавливает и смешивает скопления спор с пиротитом для получения взрывчатого вещества. block.blast-mixer.description = Раздавливает и смешивает скопления спор с пиротитом для получения взрывчатого вещества.
block.pyratite-mixer.description = Смешивает уголь, свинец и песок в легковоспламеняющийся пиротит. block.pyratite-mixer.description = Смешивает уголь, свинец и песок в легковоспламеняющийся пиротит.
block.melter.description = Плавит металлолом в шлак для дальнейшей обработки или использования в турелях «Волна». block.melter.description = Плавит металлолом в шлак для дальнейшей обработки или использования в турелях «Волна».
@@ -1142,7 +1148,7 @@ block.power-source.description = Бесконечно выводит энерг
block.item-source.description = Бесконечно выводит элементы. Только песочница. block.item-source.description = Бесконечно выводит элементы. Только песочница.
block.item-void.description = Уничтожает любые предметы. Только песочница. block.item-void.description = Уничтожает любые предметы. Только песочница.
block.liquid-source.description = Бесконечно выводит жидкости. Только песочница. block.liquid-source.description = Бесконечно выводит жидкости. Только песочница.
block.liquid-void.description = Removes any liquids. Sandbox only. block.liquid-void.description = Уничтожает любые жидкости. Только песочница.
block.copper-wall.description = Дешёвый защитный блок.\nПолезен для защиты ядра и турелей в первые несколько волн. block.copper-wall.description = Дешёвый защитный блок.\nПолезен для защиты ядра и турелей в первые несколько волн.
block.copper-wall-large.description = Дешёвый защитный блок.\nПолезен для защиты ядра и турелей в первые несколько волн.\nРазмещается на нескольких плитках. block.copper-wall-large.description = Дешёвый защитный блок.\nПолезен для защиты ядра и турелей в первые несколько волн.\nРазмещается на нескольких плитках.
block.titanium-wall.description = Умеренно сильный защитный блок.\nОбеспечивает умеренную защиту от врагов. block.titanium-wall.description = Умеренно сильный защитный блок.\nОбеспечивает умеренную защиту от врагов.
@@ -1172,6 +1178,7 @@ block.inverted-sorter.description = Работает с предметами т
block.router.description = Принимает предмет в одном направлении и выводит их до 3 других направлений в равной степени. Полезен для разделения материалов из одного источника на несколько целей.\n\n[scarlet]Никогда не используйте рядом с заводами и т.п., так как маршрутизатор будет забит выходными предметами.[] block.router.description = Принимает предмет в одном направлении и выводит их до 3 других направлений в равной степени. Полезен для разделения материалов из одного источника на несколько целей.\n\n[scarlet]Никогда не используйте рядом с заводами и т.п., так как маршрутизатор будет забит выходными предметами.[]
block.distributor.description = Расширенный маршрутизатор. Разделяет предметы до 7 других направлений в равной степени. block.distributor.description = Расширенный маршрутизатор. Разделяет предметы до 7 других направлений в равной степени.
block.overflow-gate.description = Выводит предметы влево и вправо, только если передний путь заблокирован. block.overflow-gate.description = Выводит предметы влево и вправо, только если передний путь заблокирован.
block.underflow-gate.description = Противоположность избыточного затвора. Выводит предметы вперёд только в том случае, если левый и правый пути заблокированы.
block.mass-driver.description = Самый продвинутый транспортный блок. Собирает несколько предметов и затем стреляет ими в другую катапульту на большом расстоянии. Требуется энергия для работы. block.mass-driver.description = Самый продвинутый транспортный блок. Собирает несколько предметов и затем стреляет ими в другую катапульту на большом расстоянии. Требуется энергия для работы.
block.mechanical-pump.description = Дешёвый насос с низкой производительностью, но без энергопотребления. block.mechanical-pump.description = Дешёвый насос с низкой производительностью, но без энергопотребления.
block.rotary-pump.description = Продвинутый насос. Качает больше жидкости, но требуют энергию. block.rotary-pump.description = Продвинутый насос. Качает больше жидкости, но требуют энергию.

View File

@@ -1,23 +1,23 @@
credits.text = Створив [ROYAL]Anuken[] — [SKY]anukendev@gmail.com[]\n\nЄ питання по грі або проблеми з перекладом?\nЙдіть в офіційний сервер discord Mindustrу\nу канал #український.\nПерекладач: [blue]Prosta4ok_ua[green]#[yellow]6336 credits.text = Створив [ROYAL]Anuken[] — [SKY]anukendev@gmail.com[]\n\nЄ ігрові питання або помилки в перекладі?\nЗавітайте до офіційного Discord-сервера Mindustrу\nв канал #український.\nПереклав українською: [blue]Prosta4ok_ua[green]#[yellow]6336
credits = Творці credits = Творці
contributors = Перекладачі та помічники contributors = Перекладачі та помічники
discord = Приєднуйтесь до Mindustry Discord! discord = Офіційний сервер Mindustry в Discord
link.discord.description = Офіційний Discord сервер Mindustry link.discord.description = Приєднуйтесь до Discord-сервера Mindustrу!
link.reddit.description = Спільнота Mindustry на Reddit link.reddit.description = Спільнота Mindustry на Reddit
link.github.description = Вихідний код гри link.github.description = Вихідний код гри
link.changelog.description = Список змін link.changelog.description = Змінопис
link.dev-builds.description = Нестабільні версії link.dev-builds.description = Нестабільні версії
link.trello.description = Офіційна дошка Trello для запланованих функцій link.trello.description = Офіційна дошка Trello для запланованих функцій
link.itch.io.description = Itch.io сторінка, на якій можна завантажити гру link.itch.io.description = Завантажити гру з Itch.io (окрім IOS)
link.google-play.description = Завантажити для Android з Google Play link.google-play.description = Завантажити для Android з Google Play
link.f-droid.description = Завантажити для Android з F-Droid link.f-droid.description = Завантажити для Android з F-Droid
link.wiki.description = Офіційна Mindustry wiki link.wiki.description = Офіційна ігрова Wiki
link.feathub.description = Запропонувати нові функції link.feathub.description = Запропонувати нові функції
linkfail = Не вдалося відкрити посилання!\nURL-адреса скопійована в буфер обміну. linkfail = Не вдалося відкрити посилання!\nURL-адреса скопійована в буфер обміну.
screenshot = Зняток мапи збережено в {0} screenshot = Зняток мапи збережено до {0}
screenshot.invalid = Мапа занадто велика, тому, мабуть, не вистачає пам’яті для знятку мапи. screenshot.invalid = Мапа занадто велика, тому, мабуть, не вистачає пам’яті для знятку мапи.
gameover = Гра завершена gameover = Гра завершена
gameover.pvp = [accent] {0}[] команда перемогла! gameover.pvp = [accent]{0}[] команда перемогла!
highscore = [YELLOW]Новий рекорд! highscore = [YELLOW]Новий рекорд!
copied = Скопійовано. copied = Скопійовано.
@@ -47,9 +47,9 @@ schematic.browseworkshop = Переглянути в Майстерні
schematic.copy = Копіювати в буфер обміну schematic.copy = Копіювати в буфер обміну
schematic.copy.import = Імпортувати з клавіатури schematic.copy.import = Імпортувати з клавіатури
schematic.shareworkshop = Поширити в Майстерню schematic.shareworkshop = Поширити в Майстерню
schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Відобразити схему schematic.flip = [accent][[{0}][]/[accent][[{1}][]: Обернути схему
schematic.saved = Схема збережена. schematic.saved = Схема збережена.
schematic.delete.confirm = Ця схема буде повністю випалена. schematic.delete.confirm = Ця схема буде повністю випалена Викорінювачем.
schematic.rename = Перейменувати схему. schematic.rename = Перейменувати схему.
schematic.info = {0}x{1}, {2} блоків schematic.info = {0}x{1}, {2} блоків
@@ -57,19 +57,19 @@ stat.wave = Хвиль відбито:[accent] {0}
stat.enemiesDestroyed = Ворогів знищено:[accent] {0} stat.enemiesDestroyed = Ворогів знищено:[accent] {0}
stat.built = Будівель збудувано:[accent] {0} stat.built = Будівель збудувано:[accent] {0}
stat.destroyed = Будівель знищено:[accent] {0} stat.destroyed = Будівель знищено:[accent] {0}
stat.deconstructed = Будівель декоструйовано[accent] {0} stat.deconstructed = Будівель деконструйовано:[accent] {0}
stat.delivered = Ресурсів запущено: stat.delivered = Ресурсів запущено:
stat.rank = Фінальний рахунок: [accent]{0} stat.rank = Фінальний рахунок: [accent]{0}
launcheditems = [accent]Запущені предмети launcheditems = [accent]Запущені предмети
launchinfo = [unlaunched]Натисніть на кнопку «[[ЗАПУСК]», щоб ваше ядро отримало предмети, які виділені синім кольором. launchinfo = [unlaunched]Натисніть на кнопку [[ЗАПУСК], щоб ваше ядро отримало предмети, які виділені синім кольором.
map.delete = Ви впевнені, що хочете видалити мапу «[accent]{0}[]»? map.delete = Ви впевнені, що хочете видалити мапу «[accent]{0}[]»?
level.highscore = Рекорд: [accent]{0} level.highscore = Рекорд: [accent]{0}
level.select = Вибір мапи level.select = Вибір мапи
level.mode = Режим гри: level.mode = Режим гри:
showagain = Не показувати знову до наступного сеансу showagain = Не показувати знову до наступного сеансу
coreattack = < Ядро знаходиться під атакою! > coreattack = < Ядро знаходиться під атакою! >
nearpoint = [[ [scarlet]ЗАЛИШТЕ ЗОНУ ВИСАДКИ НЕГАЙНО[] ]\nАннігіляція неминуча. nearpoint = [[ [scarlet]ЗАЛИШТЕ ЗОНУ ВИСАДКИ НЕГАЙНО[] ]\nаннігіляція неминуча.
database = База даних ядра database = База даних ядра
savegame = Зберегти гру savegame = Зберегти гру
loadgame = Завантажити гру loadgame = Завантажити гру
@@ -80,7 +80,7 @@ none = <нічого>
minimap = Мінімапа minimap = Мінімапа
position = Місцерозташування position = Місцерозташування
close = Закрити close = Закрити
website = Веб-сайт website = Вебсайт
quit = Вихід quit = Вихід
save.quit = Зберегти & Вийти save.quit = Зберегти & Вийти
maps = Мапи maps = Мапи
@@ -89,48 +89,49 @@ continue = Продовжити
maps.none = [lightgray]Мап не знайдено! maps.none = [lightgray]Мап не знайдено!
invalid = Недійсне invalid = Недійсне
pickcolor = Вибрати колір pickcolor = Вибрати колір
preparingconfig = Підготовка конфігурації preparingconfig = Підготовка налаштувань
preparingcontent = Підготовка вмісту preparingcontent = Підготовка вмісту
uploadingcontent = Вивантаження вмісту uploadingcontent = Вивантаження вмісту
uploadingpreviewfile = Вивантаження файлу передперегляду uploadingpreviewfile = Вивантаження файлу попереднього перегляду
committingchanges = Здійснення змін committingchanges = Здійснення змін
done = Зроблено done = Зроблено
feature.unsupported = Your device does not support this feature. feature.unsupported = Ваш пристрій не підтримує цю функцію
mods.alphainfo = Майте на увазі, що модифікації знаходяться в альфі, і [scarlet]може бути дуже глючними[].\nПовідомте про будь-які проблеми, які ви знайдете до Mindustry Github або Discord. mods.alphainfo = Майте на увазі, що модифікації знаходяться в альфі, і [scarlet]можуть бути дуже глючними[].\nПовідомте про будь-які проблеми, які ви знайдете до Mindustry Github або Discord.
mods.alpha = [scarlet](Альфа) mods.alpha = [scarlet](Альфа)
mods = Модифікації mods = Модифікації
mods.none = [LIGHT_GRAY]Модифікацій не знайдено! mods.none = [LIGHT_GRAY]Модифікацій не знайдено!
mods.guide = Посібник з модифицій mods.guide = Посібник з модифікацій
mods.report = Повідомити про ваду mods.report = Повідомити про ваду
mods.openfolder = Відкрити теку модифікацій mods.openfolder = Відкрити мод. теку
mod.display = [gray]Модифікація:[orange] {0}
mod.enabled = [lightgray]Увімкнено mod.enabled = [lightgray]Увімкнено
mod.disabled = [scarlet]Вимкнено mod.disabled = [scarlet]Вимкнено
mod.disable = Вимкн. mod.disable = Вимкнути
mod.delete.error = Неможливо видалити модифікацію. Файл, можливо, використовується. mod.delete.error = Неможливо видалити модифікацію. Файл, можливо, використовується.
mod.requiresversion = [scarlet]Необхідна мінімальна версія гри: [accent]{0} mod.requiresversion = [scarlet]Необхідна мінімальна версія гри: [accent]{0}
mod.missingdependencies = [scarlet]Відсутні залежності: {0} mod.missingdependencies = [scarlet]Відсутні залежності: {0}
mod.erroredcontent = [scarlet]Помилки при завантаженнні mod.erroredcontent = [scarlet]Помилки при завантаженнні
mod.errors = Сталася помилка при завантаження змісту. mod.errors = Виникли помилки при завантаження змісту.
mod.noerrorplay = [scarlet]Ви маєте модифікації з помилками.[] Або вимкніть проблемні модифікації, або виправте їх. mod.noerrorplay = [scarlet]Ви маєте модифікації з помилками.[] Або вимкніть проблемні модифікації, або виправте їх.
mod.nowdisabled = [scarlet]Модифікації «{0}» не вистачає залежних модифікацій:[accent] {1}\n[lightgray]Ці модифікації потрібно завантажити спочатку.\nЦя модифікація буде автоматично вимкнена. mod.nowdisabled = [scarlet]Модифікації «{0}» не вистачає залежних модифікацій:[accent] {1}\n[lightgray]Ці модифікації потрібно завантажити спочатку.\nЦя модифікація буде автоматично вимкнена.
mod.enable = Увімк. mod.enable = Увімкнути
mod.requiresrestart = А тепер гра закриється, щоб застосувати зміни модифікацій. mod.requiresrestart = А тепер гра закриється, щоб застосувати зміни модифікацій.
mod.reloadrequired = [scarlet]Потрібно перезавантаження mod.reloadrequired = [scarlet]Потрібно перезавантаження
mod.import = Імпортувати модифікацію mod.import = Імпортувати модифікацію
mod.import.github = Завантажити мод з GitHub mod.import.github = Завантажити мод. з GitHub
mod.item.remove = Цей предмет є частиною модифікації [accent] «{0}»[]. Щоб видалити його, видаліть цю модифікацію. mod.item.remove = Цей предмет є частиною модифікації [accent] «{0}»[]. Щоб видалити його, видаліть цю модифікацію.
mod.remove.confirm = Цю модифікацію буде видалено. mod.remove.confirm = Цю модифікацію буде видалено.
mod.author = [LIGHT_GRAY]Автор:[] {0} mod.author = [LIGHT_GRAY]Автор:[] {0}
mod.missing = Це збереження містить модифікації, які ви нещодавно оновили або більше не встановлювали. Збереження може зіпсуватися. Ви впевнені, що хочете завантажити його?\n[lightgray]Модифікації:\n{0} mod.missing = Це збереження містить модифікації, які ви нещодавно оновили або більше не встановлювали. Збереження може зіпсуватися. Ви впевнені, що хочете завантажити його?\n[lightgray]Модифікації:\n{0}
mod.preview.missing = До публікації цієї модифікації в Майстерні, ви повинні додати зображення попереднього перегляду.\nПомістіть зображення з назвою [accent] preview.png[] у теку з модификаціями і спробуйте знову. mod.preview.missing = До публікації цієї модифікації в Майстерні, ви повинні додати зображення попереднього перегляду.\nПомістіть зображення з назвою [accent] preview.png[] у теку з модификаціями і спробуйте знову.
mod.folder.missing = Тільки модификації у формі теці можуть бути опубліковані в Майстерні.\nЩоб перетворити будь-яку модификацію у теку, просто розархівуйте цей файлу теку та видаліть старий архів, і потім перезапустіть гру або перезавантажте ваші модификації. mod.folder.missing = Тільки модификації у формі теці можуть бути опубліковані в Майстерні.\nЩоб перетворити будь-яку модификацію у теку, просто розархівуйте цей файлу теку та видаліть старий архів, і потім перезапустіть гру або перезавантажте ваші модификації.
mod.scripts.unsupported = Ваш пристрій не підтримує скрипти модифікацій. Деякі модифифікаціх не будуть працювати правильно. mod.scripts.unsupported = Ваш пристрій не підтримує скрипти модифікацій. Деякі модифікації не будуть працювати правильно.
about.button = Про гру about.button = Про гру
name = Ім’я: name = Ім’я:
noname = Спочатку придумайте[accent] собі ім’я[]. noname = Спочатку придумайте[accent] собі ім’я[].
filename = Ім’я файлу: filename = Назва файлу:
unlocked = Доступний новий вміст! unlocked = Доступний новий вміст!
completed = [accent]Завершено completed = [accent]Завершено
techtree = Дерево технологій techtree = Дерево технологій
@@ -141,35 +142,35 @@ players = Гравців: {0}
players.single = {0} гравець на сервері players.single = {0} гравець на сервері
server.closing = [accent]Закриття сервера… server.closing = [accent]Закриття сервера…
server.kicked.kick = Ви були вигнані з сервера! server.kicked.kick = Ви були вигнані з сервера!
server.kicked.whitelist = Ви не в білому спискі сервера! server.kicked.whitelist = Ви не в білому списку сервера!
server.kicked.serverClose = Сервер закрито. server.kicked.serverClose = Сервер закрито.
server.kicked.vote = Вас було вигнано із сервера за допомогою голосування. Прощавайте. server.kicked.vote = Вас було вигнано із сервера за допомогою голосування. Прощавайте.
server.kicked.clientOutdated = Застарілий клієнт! Оновіть свою гру! server.kicked.clientOutdated = Застарілий клієнт! Оновіть свою гру!
server.kicked.serverOutdated = Застарілий сервер! Попросіть адміністратора сервера оновити сервер/гру! server.kicked.serverOutdated = Застарілий сервер! Попрохайте адміністратора сервера оновити сервер/гру!
server.kicked.banned = Ви заблоковані на цьому сервері. server.kicked.banned = Ви заблоковані на цьому сервері.
server.kicked.typeMismatch = Цей сервер не сумісний з вашим типом збірки. server.kicked.typeMismatch = Цей сервер не сумісний з вашим типом збірки.
server.kicked.playerLimit = Цей сервер — заповнений. Дочекайтесь вільного слота. server.kicked.playerLimit = Цей сервер — заповнений. Дочекайтесь вільного місця.
server.kicked.recentKick = Нещодавно вас вигнали. \nПочекайте трохи перед наступним підключенням. server.kicked.recentKick = Нещодавно вас вигнали. \nПочекайте трохи перед наступним під’єднанням.
server.kicked.nameInUse = На цьому сервері є хтось з таким ім’ям. server.kicked.nameInUse = На цьому сервері вже є хтось з таким ім’ям.
server.kicked.nameEmpty = Ваше ім’я має містити принаймні один символ або цифру. server.kicked.nameEmpty = Ваше ім’я має містити принаймні один символ або цифру.
server.kicked.idInUse = Ви вже на цьому сервері! Підключення двох облікових записів не дозволяється. server.kicked.idInUse = Ви вже на цьому сервері! Під’єднанням двох облікових записів не дозволяється.
server.kicked.customClient = Цей сервер не підтримує користувацькі збірки. Завантажте офіційну версію. server.kicked.customClient = Цей сервер не підтримує користувацькі збірки. Завантажте офіційну версію.
server.kicked.gameover = Гра завершена! server.kicked.gameover = Гра завершена!
server.kicked.serverRestarting = Сервер перезавантажується server.kicked.serverRestarting = Сервер перезавантажується
server.versions = Ваша версія:[accent] {0}[]\nВерсія на сервері:[accent] {1}[] server.versions = Ваша версія:[accent] {0}[]\nВерсія на сервері:[accent] {1}[]
host.info = Кнопка [accent]Сервер[] розміщує сервер на порті [scarlet]6567[]. \nКористувачі, які знаходяться у тій же [lightgray]WiFi або локальній мережі[], повинні бачити ваш сервер у своєму списку серверів.\n\nЯкщо ви хочете, щоб люди могли приєднуватися з будь-якої точки через IP, то[accent] переадресація порту []обов’язкова.\n\n[lightgray]Примітка. Якщо у вас виникли проблеми з підключенням до вашої локальної гри, переконайтеся, що ви дозволили Mindustry доступ до вашої локальної мережі в налаштуваннях брандмауера. Зауважте, що публічні мережі іноді не дозволяють виявити сервер. host.info = Кнопка [accent]Сервер[] розміщує сервер на порті [scarlet]6567[]. \nКористувачі, які знаходяться у тій же [lightgray]WiFi або локальній мережах[], повинні побачити ваш сервер у своєму списку серверів.\n\nЯкщо ви хочете, щоб люди могли приєднуватися з будь-якої точки планети через IP, то потрібно зробити[accent] переадресація порту[].\n\n[lightgray]Примітка. Якщо у вас виникли проблеми з приєднанням до вашої локальної гри, переконайтеся, що ви дозволили Mindustry доступ до вашої локальної мережі в налаштуваннях брандмауера. Зауважте, що публічні мережі іноді не дозволяють виявити сервер.
join.info = Тут ви можете ввести [accent]IP сервера[] для підключення або знайти сервери у [accent]локальній мережі[] для підключення до них.\nПідтримується локальна мережа(LAN) і широкосмугова мережа(WAN).\n\n[lightgray] Примітка. Тут немає автоматичного глобального списку серверів; якщо ви хочете підключитися до когось через IP, вам доведеться попросити створювача сервера дати свій ip. join.info = Тут ви можете ввести [accent]IP сервера[] для під’єднання або знайти сервери у [accent]локальній мережі[] для приєднання до них.\nПідтримується локальна мережа(LAN) і широкосмугова мережа(WAN).\n\n[lightgray] Примітка. Це не є автоматичним глобальним списком серверів; якщо ви хочете приєднатися до когось через IP, вам доведеться попросити власникасервера дати свій ip.
hostserver = Запустити багатокористувацький сервер hostserver = Запустити багатокористувацький сервер
invitefriends = Запросити друзів invitefriends = Запросити друзів
hostserver.mobile = Запустити\nсервер hostserver.mobile = Запустити\nсервер
host = Сервер host = Запустити
hosting = [accent]Відкриття сервера… hosting = [accent]Відкриття сервера…
hosts.refresh = Оновити hosts.refresh = Оновити
hosts.discovering = Пошук локальних ігор hosts.discovering = Пошук локальних ігор
hosts.discovering.any = Пошук ігор hosts.discovering.any = Пошук ігор
server.refreshing = Оновлення сервера server.refreshing = Оновлення сервера
hosts.none = [lightgray]Локальних ігр не знайдено hosts.none = [lightgray]Локальних ігр не знайдено
host.invalid = [scarlet]Не вдалося підключитися до сервера. host.invalid = [scarlet]Не вдалося під’єднатися до сервера.
trace = Стежити за гравцем trace = Стежити за гравцем
trace.playername = Ім’я гравця: [accent]{0} trace.playername = Ім’я гравця: [accent]{0}
trace.ip = IP: [accent]{0} trace.ip = IP: [accent]{0}
@@ -182,14 +183,14 @@ server.bans.none = Заблокованих гравців немає!
server.admins = Адміністратори server.admins = Адміністратори
server.admins.none = Адміністраторів немає! server.admins.none = Адміністраторів немає!
server.add = Додати сервер server.add = Додати сервер
server.delete = Ви впевнені, що хочете видалити цей сервер? server.delete = Ви дійсно хочете видалити цей сервер?
server.edit = Редагувати сервер server.edit = Редагувати сервер
server.outdated = [crimson]Застарілий сервер![] server.outdated = [crimson]Застарілий сервер![]
server.outdated.client = [crimson]Застарілий клієнт![] server.outdated.client = [crimson]Застарілий клієнт![]
server.version = [lightgray]Версія: {0} server.version = [lightgray]Версія: {0}
server.custombuild = [yellow]Користувацька збірка server.custombuild = [yellow]Користувацька збірка
confirmban = Ви дійсно хочете заблокувати цього гравця? confirmban = Ви дійсно хочете заблокувати цього гравця?
confirmkick = Ви дійсно хочете викинути цього гравця? confirmkick = Ви дійсно хочете вигнати цього гравця?
confirmvotekick = Ви дійсно хочете вигнати цього гравця за допомогою голосуванняr? confirmvotekick = Ви дійсно хочете вигнати цього гравця за допомогою голосуванняr?
confirmunban = Ви дійсно хочете розблокувати цього гравця? confirmunban = Ви дійсно хочете розблокувати цього гравця?
confirmadmin = Ви дійсно хочете зробити цього гравця адміністратором? confirmadmin = Ви дійсно хочете зробити цього гравця адміністратором?
@@ -200,23 +201,23 @@ disconnect = Відключено.
disconnect.error = Помилка з’єднання. disconnect.error = Помилка з’єднання.
disconnect.closed = З'єднання закрито. disconnect.closed = З'єднання закрито.
disconnect.timeout = Час вийшов. disconnect.timeout = Час вийшов.
disconnect.data = Не вдалося завантажити дані світу! disconnect.data = Не вдалося завантажити світові дані!
cantconnect = Не вдалося під’єднатися до гри ([accent]{0}[]). cantconnect = Не вдалося під’єднатися до гри ([accent]{0}[]).
connecting = [accent]Підключення… connecting = [accent]Приєднання…
connecting.data = [accent]Завантаження даних світу… connecting.data = [accent]Завантаження даних світу…
server.port = Порт: server.port = Порт:
server.addressinuse = Ця адреса вже використовується! server.addressinuse = Ця адреса вже використовується!
server.invalidport = Недійсний номер порту! server.invalidport = Недійсний номер порту!
server.error = [crimson]Помилка створення сервера: [accent]{0} server.error = [crimson]Помилка створення сервера: [accent]{0}
save.new = Нове збереження save.new = Нове збереження
save.overwrite = Ви впевнені, що хочете перезаписати цей слот для збереження? save.overwrite = Ви дійсно хочете перезаписати це місце збереження?
overwrite = Перезаписати overwrite = Перезаписати
save.none = Збережень не знайдено! save.none = Збережень не знайдено!
saveload = [accent]Збереження… saveload = [accent]Збереження…
savefail = Не вдалося зберегти гру! savefail = Не вдалося зберегти гру!
save.delete.confirm = Ви дійсно хочете видалити це збереження? save.delete.confirm = Ви дійсно хочете видалити це збереження?
save.delete = Видалити save.delete = Видалити
save.export = Експортувати збереження save.export = Вивантажити збереження
save.import.invalid = [accent]Це збереження недійсне! save.import.invalid = [accent]Це збереження недійсне!
save.import.fail = [crimson]Не вдалося завантажити збереження: [accent]{0} save.import.fail = [crimson]Не вдалося завантажити збереження: [accent]{0}
save.export.fail = [crimson]Не вдалося вивантажити збереження: [accent]{0} save.export.fail = [crimson]Не вдалося вивантажити збереження: [accent]{0}
@@ -224,18 +225,18 @@ save.import = Імпортувати збереження
save.newslot = Ім’я збереження: save.newslot = Ім’я збереження:
save.rename = Перейменувати save.rename = Перейменувати
save.rename.text = Нова назва: save.rename.text = Нова назва:
selectslot = Виберіть збереження. selectslot = Виберіть збережений файл.
slot = [accent]Слот {0} slot = [accent]Місце збережання{0}
editmessage = Редагувати повідомлення editmessage = Редагувати повідомлення
save.corrupted = [accent]Збережений файл пошкоджено або недійсний! \nЯкщо ви щойно оновили свою гру, це, мабуть, є зміною формату збереження та [scarlet] не є[] помилкою. save.corrupted = [accent]Збережений файл пошкоджено або він є недійсним! \nЯкщо ви щойно оновили свою гру, це, мабуть, є зміною формату збереження та [scarlet] не є[] помилкою.
empty = <Порожньо> empty = <порожньо>
on = Увімкнено on = Увімкнено
off = Вимкнено off = Вимкнено
save.autosave = Автозбереження: {0} save.autosave = Автозбереження: {0}
save.map = Мапа: {0} save.map = Мапа: {0}
save.wave = Хвиля {0} save.wave = Хвиля {0}
save.mode = Режим гри: {0} save.mode = Режим гри: {0}
save.date = Останнє збереження save.date = Останнє збереження: {0}
save.playtime = Час гри: {0} save.playtime = Час гри: {0}
warning = Попередження warning = Попередження
confirm = Підтвердження confirm = Підтвердження
@@ -251,13 +252,14 @@ copylink = Скопіювати посилання
back = Назад back = Назад
data.export = Вивантажити дані data.export = Вивантажити дані
data.import = Завантажити дані data.import = Завантажити дані
data.openfolder = Відкрити теку з даними
data.exported = Дані вивантажено. data.exported = Дані вивантажено.
data.invalid = Це не дійсні ігрові дані. data.invalid = Це не дійсні ігрові дані.
data.import.confirm = Вивантаження зовнішніх даних перезапише[scarlet] ВСІ[] ваші поточні ігрові дані.\n[accent]Це неможливо скасувати![]\n\nЩойно дані імпортуються, гра негайно закриється. data.import.confirm = Вивантаження зовнішніх даних перезапише[scarlet] ВСІ[] ваші поточні ігрові дані.\n[accent]Це неможливо скасувати![]\n\nЩойно дані імпортуються, гра негайно закриється.
classic.export = Вивантажити класичні дані classic.export = Вивантажити класичні дані
classic.export.text = Класичне (версія 3.5 збірка 40) збереження або мапа були знайдені. Ви хочете експортувати ці дані в домашню теку телефону, для використання у застосунку Mindustry Classic? classic.export.text = Класичне (версія 3.5 збірка 40) збереження або мапа були знайдені. Ви хочете експортувати ці дані в домашню теку телефону, для використання у застосунку Mindustry Classic?
quit.confirm = Ви впевнені, що хочете вийти? quit.confirm = Ви дійсно хочете вийти?
quit.confirm.tutorial = Ви впевнені, що хочете вийти з навчання? quit.confirm.tutorial = Ви дійсно хочете вийти з навчання?
loading = [accent]Завантаження… loading = [accent]Завантаження…
reloading = [accent]Перезавантаження модифікацій… reloading = [accent]Перезавантаження модифікацій…
saving = [accent]Збереження… saving = [accent]Збереження…
@@ -270,14 +272,14 @@ wave.waiting = Хвиля через {0}
wave.waveInProgress = [lightgray]Хвиля триває wave.waveInProgress = [lightgray]Хвиля триває
waiting = Очікування… waiting = Очікування…
waiting.players = Очікування гравців… waiting.players = Очікування гравців…
wave.enemies = [lightgray]{0} ворог. залишилося wave.enemies = Залишилося [lightgray]{0} ворог.
wave.enemy = [lightgray]{0} ворог залишився wave.enemy = Залишився [lightgray]{0} ворог
loadimage = Завантажити зображення loadimage = Завантажити зображення
saveimage = Зберегти зображення saveimage = Зберегти зображення
unknown = Невідомо unknown = Невідомо
custom = Користувацька custom = Користувацька
builtin = Вбудована builtin = Вбудована
map.delete.confirm = Ви дійсно хочете видалити цю мапу? Це неможливо буде скасувати! map.delete.confirm = Ви дійсно хочете видалити цю мапу? Цю дію неможливо буде скасувати!
map.random = [accent]Випадкова мапа map.random = [accent]Випадкова мапа
map.nospawn = Ця мапа не має жодного ядра для появи гравця! Додайте [ROYAL]помаранчеве[] ядро до цієї мапи в редакторі. map.nospawn = Ця мапа не має жодного ядра для появи гравця! Додайте [ROYAL]помаранчеве[] ядро до цієї мапи в редакторі.
map.nospawn.pvp = У цієї мапи немає ворожих ядер, в яких гравець може з’явитися! Додайте [SCARLET]не помаранчеве[] ядро до цієї мапи в редакторі. map.nospawn.pvp = У цієї мапи немає ворожих ядер, в яких гравець може з’явитися! Додайте [SCARLET]не помаранчеве[] ядро до цієї мапи в редакторі.
@@ -285,15 +287,15 @@ map.nospawn.attack = У цієї мапи немає ворожих ядер, в
map.invalid = Помилка завантаження мапи: пошкоджений або невірний файл мапи. map.invalid = Помилка завантаження мапи: пошкоджений або невірний файл мапи.
workshop.update = Оновити предмет workshop.update = Оновити предмет
workshop.error = Помилка при отриманні інформації з Майстерні: {0} workshop.error = Помилка при отриманні інформації з Майстерні: {0}
map.publish.confirm = Ви дійсно хочете опублікувати цю мапу?\n\n[lightgray]Переконайтеся, що спершу ви згодні з Ліцензійною угодою Steam, або ваші мапи не з’являться! map.publish.confirm = Ви дійсно хочете опублікувати цю мапу?\n\n[lightgray]Спершу переконайтеся, що ви згодні з Ліцензійною угодою Steam, або ваші мапи не з’являться!
workshop.menu = Виберіть, що ви хочете зробити з цим предметом. workshop.menu = Виберіть, що ви хочете зробити з цим предметом.
workshop.info = Інформація про предмет workshop.info = Інформація про предмет
changelog = Журнал змін (за бажанням): changelog = Змінопис (за бажанням):
eula = Ліцензійна угода eula = Ліцензійна угода Steam
missing = Цей предмет було видалено або переміщено.\n[lightgray]Список Майстерні тепер автоматично від’єднано. missing = Цей предмет було видалено або переміщено.\n[lightgray]Список Майстерні тепер автоматично від’єднано.
publishing = [accent]Публікація… publishing = [accent]Публікація…
publish.confirm = Ви дійсно хочете опублікувати це?\n\n[lightgray]Переконайтеся, що ви спочатку погоджуєтеся з EULA Майстерні, або ваші предмети не з’являться! publish.confirm = Ви дійсно хочете опублікувати це?\n\n[lightgray]Переконайтеся, що ви спочатку погоджуєтеся з EULA Майстерні, або ваші предмети не з’являться!
publish.error = Сталася помилка при публікації предмета: {0} publish.error = Виникла помилка при публікації предмета: {0}
steam.error = Не вдалося ініціалізувати сервіси Steam.\nПомилка: {0} steam.error = Не вдалося ініціалізувати сервіси Steam.\nПомилка: {0}
editor.brush = Пензлик editor.brush = Пензлик
@@ -320,8 +322,8 @@ waves.perspawn = за появу
waves.to = до waves.to = до
waves.boss = Бос waves.boss = Бос
waves.preview = Попередній перегляд waves.preview = Попередній перегляд
waves.edit = Редагувати waves.edit = Редагувати…
waves.copy = Копіювати у буфер обміну waves.copy = Копіювати в буфер обміну
waves.load = Завантажити з буфера обміну waves.load = Завантажити з буфера обміну
waves.invalid = Недійсні хвилі у буфері обміну. waves.invalid = Недійсні хвилі у буфері обміну.
waves.copied = Хвилі скопійовані. waves.copied = Хвилі скопійовані.
@@ -335,11 +337,11 @@ editor.removeunit = Видалити бойову одиницю
editor.teams = Команди editor.teams = Команди
editor.errorload = Помилка завантаження зображення:\n[accent] {0} editor.errorload = Помилка завантаження зображення:\n[accent] {0}
editor.errorsave = Помилка збереження зображення:\n[accent]{0} editor.errorsave = Помилка збереження зображення:\n[accent]{0}
editor.errorimage = Це зображення, а не мапа. Не змінюйте розширення, очікуючи, що це запрацює.\n\nЯкщо ви хочете імпортувати застарілку мапу, то використовуйте кнопку «Імпортувати застаріле зображення» у редакторі. editor.errorimage = Це зображення, а не мапа. Не змінюйте розширення, очікуючи, що це спрацює.\n\nЯкщо ви хочете імпортувати застарілу мапу, то використовуйте кнопку «Імпортувати застаріле зображення» у редакторі.
editor.errorlegacy = Ця мапа занадто стара і використовує попередній формат мапи, який більше не підтримується. editor.errorlegacy = Ця мапа занадто стара і використовує попередній формат мапи, який більше не підтримується.
editor.errornot = Це не мапа. editor.errornot = Це не мапа.
editor.errorheader = Цей файл мапи недійсний або пошкоджений. editor.errorheader = Цей файл мапи недійсний або пошкоджений.
editor.errorname = Мапа не має імені. Може Ви намагаєтеся завантажити збереження? editor.errorname = Мапа не має назви. Може Ви намагаєтеся завантажити збереження?
editor.update = Оновити editor.update = Оновити
editor.randomize = Випадково editor.randomize = Випадково
editor.apply = Застосувати editor.apply = Застосувати
@@ -348,8 +350,8 @@ editor.resize = Змінити\nрозмір
editor.loadmap = Завантажити мапу editor.loadmap = Завантажити мапу
editor.savemap = Зберегти мапу editor.savemap = Зберегти мапу
editor.saved = Збережено! editor.saved = Збережено!
editor.save.noname = Ваша мапа не має імені! Встановіть його в «Інформація про мапу». editor.save.noname = Ваша мапа не має назви! Установіть його в «Інформація про мапу».
editor.save.overwrite = Ваша мапа перезаписує вбудовану мапу! Виберіть інше ім’я в «Інформація про мапу». editor.save.overwrite = Ваша мапа перезаписує вбудовану мапу! Виберіть іншу назву в «Інформація про мапу».
editor.import.exists = [scarlet]Неможливо імпортувати:[] вбудована мапа з назвою «{0}» вже існує! editor.import.exists = [scarlet]Неможливо імпортувати:[] вбудована мапа з назвою «{0}» вже існує!
editor.import = Імпорт… editor.import = Імпорт…
editor.importmap = Імпортувати мапу editor.importmap = Імпортувати мапу
@@ -362,7 +364,7 @@ editor.export = Експорт…
editor.exportfile = Експорт файлу editor.exportfile = Експорт файлу
editor.exportfile.description = Експортувати файл мапи editor.exportfile.description = Експортувати файл мапи
editor.exportimage = Експорт зображення місцевості editor.exportimage = Експорт зображення місцевості
editor.exportimage.description = Експорт файла з зображенням мапи editor.exportimage.description = Експорт файлу з зображенням мапи
editor.loadimage = Завантажити\nзображення editor.loadimage = Завантажити\nзображення
editor.saveimage = Зберегти\nзображення editor.saveimage = Зберегти\nзображення
editor.unsaved = [scarlet]У вас є незбережені зміни![]\nВи впевнені, що хочете вийти? editor.unsaved = [scarlet]У вас є незбережені зміни![]\nВи впевнені, що хочете вийти?
@@ -370,13 +372,13 @@ editor.resizemap = Змінити розмір мапи
editor.mapname = Назва мапи: editor.mapname = Назва мапи:
editor.overwrite = [accent]Попередження!\nЦе перезаписує існуючу мапу. editor.overwrite = [accent]Попередження!\nЦе перезаписує існуючу мапу.
editor.overwrite.confirm = [scarlet]Попередження![] Мапа з такою назвою вже існує. Ви впевнені, що хочете переписати її? editor.overwrite.confirm = [scarlet]Попередження![] Мапа з такою назвою вже існує. Ви впевнені, що хочете переписати її?
editor.exists = Мапа за такою назвою вже існує. editor.exists = Мапа з такою назвою вже існує.
editor.selectmap = Виберіть мапу для завантаження: editor.selectmap = Виберіть мапу для завантаження:
toolmode.replace = Замінити toolmode.replace = Замінити
toolmode.replace.description = Малює тільки\nна суцільних блоках. toolmode.replace.description = Малює тільки\nна суцільних блоках.
toolmode.replaceall = Замінити все toolmode.replaceall = Замінити все
toolmode.replaceall.description = Замінює усі блоки на мапі. toolmode.replaceall.description = Замінює всі блоки на мапі.
toolmode.orthogonal = Ортогональна toolmode.orthogonal = Ортогональна
toolmode.orthogonal.description = Малює лише\nортогональні лінії. toolmode.orthogonal.description = Малює лише\nортогональні лінії.
toolmode.square = Прямокутник toolmode.square = Прямокутник
@@ -428,16 +430,16 @@ campaign = Кампанія
load = Завантажити load = Завантажити
save = Зберегти save = Зберегти
fps = FPS: {0} fps = FPS: {0}
ping = Пінг: {0} мс ping = Затримка: {0} мс
language.restart = Будь ласка, перезапустіть свою гру, щоб налаштування мови набули чинності. language.restart = Будь ласка, перезапустіть свою гру, щоб налаштування мови набули чинності.
settings = Налаштування settings = Налаштування
tutorial = Навчання tutorial = Навчання
tutorial.retake = Відкрити навчання tutorial.retake = Пройти навчання ще раз
editor = Редактор editor = Редактор
mapeditor = Редактор мап mapeditor = Редактор мап
abandon = Покинути abandon = Покинути
abandon.text = Ця зона і всі її ресурси будуть втрачені. abandon.text = Ця зона і всі її ресурси будуть утрачені.
locked = Заблоковано locked = Заблоковано
complete = [lightgray]Досягнута: complete = [lightgray]Досягнута:
requirement.wave = Досягніть хвилі {0} у зоні «{1}» requirement.wave = Досягніть хвилі {0} у зоні «{1}»
@@ -449,41 +451,41 @@ launch = < ЗАПУСК >
launch.title = Запуск вдалий launch.title = Запуск вдалий
launch.next = [lightgray]наступна можливість на {0}-тій хвилі launch.next = [lightgray]наступна можливість на {0}-тій хвилі
launch.unable2 = [scarlet]ЗАПУСК неможливий.[] launch.unable2 = [scarlet]ЗАПУСК неможливий.[]
launch.confirm = Це видалить всі ресурси у Вашому ядрі.\nВи не зможете повернутися до цієї бази. launch.confirm = Це видалить всі ресурси у вашому ядрі.\nВи не зможете повернутися до цієї бази.
launch.skip.confirm = Якщо ви пропустите зараз, Ви не зможете не запускати до більш пізніх хвиль. launch.skip.confirm = Якщо ви пропустите зараз, ви не зможете не запускати до більш пізніх хвиль.
uncover = Розкрити uncover = Розкрити
configure = Вивантажити конфігурацію configure = Налаштувати вивантаження
bannedblocks = Заборонені блоки bannedblocks = Заборонені блоки
addall = Додати все addall = Додати все
configure.locked = {0}[lightgray]Тільки після цього можливість розблокувати вивантаження ресурсів буде доступна. configure.locked = {0}[lightgray]Тільки після цього можливість розблокувати вивантаження ресурсів буде доступна.
configure.invalid = Кількість повинна бути числом між 0 та {0}. configure.invalid = Кількість повинна бути числом між 0 та {0}.
zone.unlocked = Зона «[lightgray]{0}» тепер розблокована. zone.unlocked = Зона «[lightgray]{0}» тепер розблокована.
zone.requirement.complete = Ви досягли {0}-тої хвилі. \nВимоги до зони «{1}» виконані. zone.requirement.complete = Ви досягли {0}-тої хвилі.\nВимоги до зони «{1}» виконані.
zone.config.unlocked = Вивантаження розблоковано:[lightgray]\n{0} zone.config.unlocked = Вивантаження розблоковано:[lightgray]\n{0}
zone.resources = Виявлені ресурси: zone.resources = Виявлені ресурси:
zone.objective = [lightgray]Мета: [accent]{0} zone.objective = [lightgray]Мета: [accent]{0}
zone.objective.survival = Вижити zone.objective.survival = вижити.
zone.objective.attack = Знищити вороже ядро zone.objective.attack = знищити вороже ядро.
add = Додати… add = Додати…
boss.health = Здоров’я босу boss.health = Здоров’я босу
connectfail = [crimson]Помилка підключення: [accent]{0} connectfail = [crimson]Помилка з’єднання: [accent]{0}
error.unreachable = Сервер не доступний. error.unreachable = Сервер не є доступним.\nЧи правильно написана адреса?
error.invalidaddress = Некоректна адреса. error.invalidaddress = Некоректна адреса.
error.timedout = Час очікування вийшов.\nПереконайтеся, що адреса коректна і що власник сервера налаштував переадресацію порту! error.timedout = Час очікування вийшов.\nПереконайтеся, що адреса коректна і що власник сервера налаштував переадресацію порту!
error.mismatch = Помилка пакету:\nможливе невідповідність версії клієнта/сервера.\nПереконайтеся, що у вас та у володара сервера встановлена остання версія Mindustry! error.mismatch = Помилка пакету:\nможлива невідповідність версії клієнта/сервера.\nПереконайтеся, що у вас та у власника сервера встановлена остання версія Mindustry!
error.alreadyconnected = Ви вже підключилися. error.alreadyconnected = Ви вже під’єдналися.
error.mapnotfound = Файл мапи не знайдено error.mapnotfound = Файл мапи не знайдено!
error.io = Мережева помилка введення-виведення error.io = Мережева помилка введення-виведення.
error.any = Невідома мережева помилка error.any = Невідома мережева помилка
error.bloom = Не вдалося ініціалізувати цвітіння.\nВаш пристрій, мабуть, не підтримує це. error.bloom = Не вдалося ініціалізувати світіння.\nВаш пристрій, мабуть, не підтримує це.
zone.groundZero.name = Відправний пункт zone.groundZero.name = Відправний пункт
zone.desertWastes.name = Пустельні відходи zone.desertWastes.name = Пустельні відходи
zone.craters.name = Кратери zone.craters.name = Кратери
zone.frozenForest.name = Крижаний ліс zone.frozenForest.name = Крижаний ліс
zone.ruinousShores.name = Зруйновані берега zone.ruinousShores.name = Зруйновані береги
zone.stainedMountains.name = Пофарбовані гори zone.stainedMountains.name = Забруднені гори
zone.desolateRift.name = Пустельний розлом zone.desolateRift.name = Пустельний розлом
zone.nuclearComplex.name = Ядерний виробничий комплекс zone.nuclearComplex.name = Ядерний виробничий комплекс
zone.overgrowth.name = Зарості zone.overgrowth.name = Зарості
@@ -493,24 +495,24 @@ zone.impact0078.name = Імпульс 0078
zone.crags.name = Скелі zone.crags.name = Скелі
zone.fungalPass.name = Грибний перевал zone.fungalPass.name = Грибний перевал
zone.groundZero.description = Оптимальне місце для повторних ігор. Низька ворожа загроза. Мало ресурсів. \nЗбирайте якомога більше свинцю та міді. \nЙдіть далі. zone.groundZero.description = Оптимальне місце для повторних ігор. Низька ворожа загроза. Мало ресурсів. \nЗбирайте якомога більше свинцю та міді. \nНе затримуйтесь і йдіть далі.
zone.frozenForest.description = Навіть тут, ближче до гір, спори поширилися. Холодна температура не може їх утримувати тут завжди.\nЗважтесь створити енергію. Побудуйте генератори внутрішнього згорання. Навчіться користуватися регенераторами. zone.frozenForest.description = Спори поширилися навіть тут, ближче до гір. Холодна температура не може стримувати їх завжди.\nЗважтесь створити енергію. Побудуйте генератори внутрішнього згорання. Навчіться користуватися регенераторами.
zone.desertWastes.description = Ці відходи є величезними, непередбачуваними і перетинаються з занедбаними секторальними структурами.\nВугілля присутнє в регіоні. Спаліть його для енергії або синтезуйте у графіт.\n\n[lightgray]Це місце посадки не можна гарантувати. zone.desertWastes.description = Ці відходи є величезними, непередбачуваними і перетинаються з занедбаними секторальними структурами.\nВугілля присутнє в регіоні. Спаліть його для енергії або синтезуйте у графіт.\n\n[lightgray]Є декілька варіантів для місць посадок.
zone.saltFlats.description = На околиці пустелі лежать соляні рівнини. У цьому місці можна знайти небагато ресурсів.\n\nТут вороги спорудили комплекс сховищ ресурсів. Викорініть їх ядро. Не залишайте нічого цінного. zone.saltFlats.description = На околицях пустелі лежать Соляні рівнини. У цьому місці можна знайти небагато ресурсів.\n\nСаме тут вороги спорудили комплекс сховищ ресурсів. Викорініть їхнє ядро. Не залишайте нічого цінного.
zone.craters.description = У цьому кратері накопичилася вода, пережиток старих воєн. Відновіть місцевість. Зберіть пісок. Виплавіть метакскло. Накачайте воду, щоб охолодити турелі і бури. zone.craters.description = У цьому кратері накопичилася вода, пережиток старих воєн. Відновіть місцевість. Зберіть пісок. Виплавте метаскло. Качайте воду, щоб охолодити турелі і бури.
zone.ruinousShores.description = Минулі відходи - це берегова лінія. Колись у цьому місці розташувався береговий оборонний масив. Залишилося не так багато чого. Тільки найосновніші оборонні споруди залишилися непошкодженими, все інше зводиться до брухту.\nПродовжуйте експансію назовні. Повторно розкрийте технологію. zone.ruinousShores.description = Саме берегова лінія є минулим цих відходів. Колись у цьому місці розташувався береговий оборонний масив, проте залишилося не так багато чого. Тільки основні оборонні споруди залишилися неушкодженими, а все інше перетворилося на металобрухт.\nПродовжуйте експансію назовні. Повторно розкрийте технології.
zone.stainedMountains.description = Далі у вглиб материка лежать гори, ще не заражені спорами.\nВидобудьте надлишковий титан у цій місцевості. Дізнайтеся, як використовувати його.\n\nТут ворожа присутність більша. Не дайте їм часу відправити свої найсильніші одиниці. zone.stainedMountains.description = Якщо йти далі у вглиб материка, то можна побачити гори, які ще не заражені спорами.\nВидобудьте надлишковий титан у цій місцевості. Дізнайтеся, як використовувати його.\n\nНа жаль, тут більше ворогів ніж в інших місцевостях. Не дайте їм часу надіслати свої найсильніші одиниці.
zone.overgrowth.description = Ця територія заросла, ближче до джерела спор.\nВорог тут встановив форпост. Побудуйте бойові одиниці Кинджал. Знищте його. Поверніть те, що було втрачено. zone.overgrowth.description = Ближче до джерела спор є територія, що заросла.\nНе дивуйтеся, що ворог встановив тут свій форпост. Побудуйте бойові одиниці під кодовою назвою «Титан». Зруйнуйте вщент супротивника. Поверніть те, що колись належало нам.
zone.tarFields.description = Окраїна зони видобутку нафти, між горами та пустелею. Один з небагатьох районів із корисними запасами смоли.\nНезважаючи на те, що покинута, ця територія має поблизу небезпечні сили противника. Не варто їх недооцінювати.\n\n[lightgray]Якщо можливо, дослідіть технологію переробки нафти. zone.tarFields.description = Між горами та пустелею простягається окраїна зони видобутку нафти. Це один з небагатьох районів із корисними для використання запасами смоли.\nНезважаючи на те, що територія покинута, вона має поблизу небезпечні сили противника. Не варто їх недооцінювати.\n\n[lightgray]Якщо можливо, дослідіть технологію переробки нафти.
zone.desolateRift.description = Надзвичайно небезпечна зона. Багато ресурсів, але мало місця. Евакуюватися потрібно якомога швидше. Не розслабляйтеся між ворожими атаками. zone.desolateRift.description = Надзвичайно небезпечна зона. Багато ресурсів, але мало місця. Евакуюватися потрібно якомога швидше. Не розслабляйтеся між ворожими атаками та знайдіть ахіллесову п'яту супротивника.
zone.nuclearComplex.description = Колишній об’єкт для виробництва та переробки торію, зведений до руїн.\n[lightgray]Дослідіть торій та його безліч застосувань.\n\nВраг присутній тут у великій кількості, постійно шукаючи нападників. zone.nuclearComplex.description = Колишній об’єкт для виробництва та переробки торію було зведено до руїн.\n[lightgray]Дослідіть торій та його нескінченну кількість застосувань.\n\nВорог, який постійно шукає нападників, присутній тут у великій кількості, тому не баріться з евакуацією!
zone.fungalPass.description = Перехідна зона між високими і низькими горами, земля яких покрита спорами. Тут знаходиться невелика розвідувальна база ворога.\nЗнижте її.\nВикористовуйте одиниці Кинджал і Камікадзе. zone.fungalPass.description = Перехідна зона між високими і низькими горами, земля яких вкрита спорами. Тут знаходиться невелика розвідувальна база ворога.\nЗнищте її.\nВикористовуйте одиниці з кодовими назвами «Кинджал» і «Камікадзе» для повного знищення двох ворожих ядер.
zone.impact0078.description = <вставити опис тут> zone.impact0078.description = <вставити опис тут>
zone.crags.description = <вставити опис тут> zone.crags.description = <вставити опис тут>
settings.language = Мова settings.language = Мова
settings.data = Ігрові дані settings.data = Ігрові дані
settings.reset = Скинути за замовчуванням settings.reset =За замовчуванням
settings.rebind = Змінити settings.rebind = Змінити
settings.resetKey = Скинути settings.resetKey = Скинути
settings.controls = Керування settings.controls = Керування
@@ -518,9 +520,9 @@ settings.game = Гра
settings.sound = Звук settings.sound = Звук
settings.graphics = Графіка settings.graphics = Графіка
settings.cleardata = Очистити дані… settings.cleardata = Очистити дані…
settings.clear.confirm = Ви впевнені, що хочете очистити ці дані?\nЦя дія не може бути скасовано! settings.clear.confirm = Ви дійсно хочете очистити ці дані?\nЦю дію не можна скасовати!
settings.clearall.confirm = [scarlet]УВАГА![]\nЦе очистить всі дані, включаючи збереження, мапи, розблоковане та налаштування керування.\nПісля того, як ви натиснете ОК, гра видалить усі дані та автоматично закриється. settings.clearall.confirm = [scarlet]УВАГА![]\nЦе очистить усі дані, включаючи збереження, мапи, розблоковане та налаштування керування.\nПісля натискання ОК гра видалить усі дані та автоматично закриється.
paused = Пауза paused = [accent]< Пауза>
clear = Очистити clear = Очистити
banned = [scarlet]Заблоковано banned = [scarlet]Заблоковано
yes = Так yes = Так
@@ -531,21 +533,23 @@ error.crashtitle = Виникла помилка
blocks.input = Вхід blocks.input = Вхід
blocks.output = Вихід blocks.output = Вихід
blocks.booster = Прискорювач blocks.booster = Прискорювач
blocks.tiles = Необхідні плитки
blocks.affinities = Збільшення ефективності
block.unknown = [lightgray]??? block.unknown = [lightgray]???
blocks.powercapacity = Місткість енергії blocks.powercapacity = Місткість енергії
blocks.powershot = Енергія за постріл blocks.powershot = Енергія за постріл
blocks.damage = Шкода blocks.damage = Шкода
blocks.targetsair = Повітряні мішені blocks.targetsair = Повітряні вороги
blocks.targetsground = Наземні мішені blocks.targetsground = Наземні вороги
blocks.itemsmoved = Швидкість переміщення blocks.itemsmoved = Швидкість переміщення
blocks.launchtime = Час між запусками blocks.launchtime = Час між запусками
blocks.shootrange = Діапазон дії blocks.shootrange = Діапазон дії
blocks.size = Розмір blocks.size = Розмір
blocks.liquidcapacity = Місткість рідини blocks.liquidcapacity = Рідинна місткість
blocks.powerrange = Діапазон передачі енергії blocks.powerrange = Діапазон передачі енергії
blocks.powerconnections = Максимальна кількість з’єднань blocks.powerconnections = Максимальна кількість з’єднань
blocks.poweruse = Енергії використовує blocks.poweruse = Енергії використовує
blocks.powerdamage = Енергія/шкода blocks.powerdamage = Енергії за од. шкоди
blocks.itemcapacity = Місткість предметів blocks.itemcapacity = Місткість предметів
blocks.basepowergeneration = Базова генерація енергії blocks.basepowergeneration = Базова генерація енергії
blocks.productiontime = Час виробництва blocks.productiontime = Час виробництва
@@ -583,11 +587,11 @@ bar.input = Ввід
bar.output = Вивід bar.output = Вивід
bullet.damage = [stat]{0}[lightgray] шкода bullet.damage = [stat]{0}[lightgray] шкода
bullet.splashdamage = [stat]{0}[lightgray] шкода по ділянці ~[stat] {1}[lightgray] блок. bullet.splashdamage = [stat]{0}[lightgray] шкода по ділянці ~[stat] {1}[lightgray] плиток.
bullet.incendiary = [stat]запальний bullet.incendiary = [stat]запальний
bullet.homing = [stat]самонаведення bullet.homing = [stat]самонаведення
bullet.shock = [stat]шок bullet.shock = [stat]шок
bullet.frag = [stat]осколкова граната bullet.frag = [stat]шкода по ділянці
bullet.knockback = [stat]{0}[lightgray] відкидання bullet.knockback = [stat]{0}[lightgray] відкидання
bullet.freezing = [stat]заморожування bullet.freezing = [stat]заморожування
bullet.tarred = [stat]дьогтьовий bullet.tarred = [stat]дьогтьовий
@@ -629,9 +633,9 @@ setting.autotarget.name = Авто-стрільба
setting.keyboard.name = Миш+Керування з клавіатури setting.keyboard.name = Миш+Керування з клавіатури
setting.touchscreen.name = Керування сенсорним екраном setting.touchscreen.name = Керування сенсорним екраном
setting.fpscap.name = Максимальний FPS setting.fpscap.name = Максимальний FPS
setting.fpscap.none = Необмежений setting.fpscap.none = Жодне
setting.fpscap.text = {0} FPS setting.fpscap.text = {0} FPS
setting.uiscale.name = Масштаб користувальницького інтерфейсу[lightgray] (потребує перезапуск)[] setting.uiscale.name = Масштаб користувацького інтерфейсу[lightgray] (потребує перезапуск)[]
setting.swapdiagonal.name = Завжди діагональне розміщення setting.swapdiagonal.name = Завжди діагональне розміщення
setting.difficulty.training = Навчання setting.difficulty.training = Навчання
setting.difficulty.easy = Легка setting.difficulty.easy = Легка
@@ -646,7 +650,7 @@ setting.conveyorpathfinding.name = Пошук шляху для встановл
setting.coreselect.name = Дозволити схематичні ядра setting.coreselect.name = Дозволити схематичні ядра
setting.sensitivity.name = Чутливість контролера setting.sensitivity.name = Чутливість контролера
setting.saveinterval.name = Інтервал збереження setting.saveinterval.name = Інтервал збереження
setting.seconds = {0} с setting.seconds = {0} секунд
setting.blockselecttimeout.name = Час вибору блока setting.blockselecttimeout.name = Час вибору блока
setting.milliseconds = {0} мілісекунд setting.milliseconds = {0} мілісекунд
setting.fullscreen.name = Повноекранний режим setting.fullscreen.name = Повноекранний режим
@@ -665,12 +669,14 @@ setting.mutesound.name = Заглушити звук
setting.crashreport.name = Відсилати анонімні звіти про аварійне завершення гри setting.crashreport.name = Відсилати анонімні звіти про аварійне завершення гри
setting.savecreate.name = Автоматичне створення збережень setting.savecreate.name = Автоматичне створення збережень
setting.publichost.name = Загальнодоступність гри setting.publichost.name = Загальнодоступність гри
setting.playerlimit.name = Обмеження гравців
setting.chatopacity.name = Непрозорість чату setting.chatopacity.name = Непрозорість чату
setting.lasersopacity.name = Непрозорість лазерів енергопостачання setting.lasersopacity.name = Непрозорість лазерів енергопостачання
setting.bridgeopacity.name = Місткість мостів
setting.playerchat.name = Відображати хмару чата над гравцями setting.playerchat.name = Відображати хмару чата над гравцями
public.confirm = Ви хочете зробити цю гру загальнодоступною?\n[lightgray]Це можна змінити у Налаштування→Гра→Загальнодоступність гри public.confirm = Ви хочете зробити цю гру загальнодоступною?\n[lightgray]Це можна змінити у Налаштування→Гра→Загальнодоступність гри
public.beta = Зауважте, що в бета-версії гри ви не можете робити публічні ігри. public.beta = Зауважте, що в бета-версії гри ви не можете робити публічні ігри.
uiscale.reset = Масштаб користувальницького інтерфейсу було змінено.\nНатисніть «ОК» для підтверждення цього масшатабу.\n[scarlet]Повернення налаштувань і вихід через[accent] {0}[] … uiscale.reset = Масштаб користувацького інтерфейсу було змінено.\nНатисніть «ОК» для підтвердження цього масштабу.\n[scarlet]Повернення налаштувань і вихід через[accent] {0}[] секунд
uiscale.cancel = Скасувати & Вийти uiscale.cancel = Скасувати & Вийти
setting.bloom.name = Світіння setting.bloom.name = Світіння
keybind.title = Налаштування керування keybind.title = Налаштування керування
@@ -698,7 +704,7 @@ keybind.schematic_flip_y.name = Відобразити по осі Y
keybind.category_prev.name = Попередня категорія keybind.category_prev.name = Попередня категорія
keybind.category_next.name = Наступна категорія keybind.category_next.name = Наступна категорія
keybind.block_select_left.name = Вибрати блок ліворуч keybind.block_select_left.name = Вибрати блок ліворуч
keybind.block_select_right.name = Вибрати блок ліворуч праворуч keybind.block_select_right.name = Вибрати блок праворуч
keybind.block_select_up.name = Вибрати блок зверху keybind.block_select_up.name = Вибрати блок зверху
keybind.block_select_down.name = Вибрати блок знизу keybind.block_select_down.name = Вибрати блок знизу
keybind.block_select_01.name = Категорія/Вибрати перший блок keybind.block_select_01.name = Категорія/Вибрати перший блок
@@ -733,39 +739,39 @@ keybind.chat_history_prev.name = Попередня історія чату
keybind.chat_history_next.name = Наступна історія чату keybind.chat_history_next.name = Наступна історія чату
keybind.chat_scroll.name = Прокрутка чату keybind.chat_scroll.name = Прокрутка чату
keybind.drop_unit.name = Скинути бойову одиницю keybind.drop_unit.name = Скинути бойову одиницю
keybind.zoom_minimap.name = Збільшити міні-мапу keybind.zoom_minimap.name = Збільшити мінімапу
mode.help.title = Опис режимів mode.help.title = Опис режимів гри
mode.survival.name = Хвилі mode.survival.name = Виживання
mode.survival.description = Звичайний режим. В цьому режимі треба самим добувати ресурси та хвилі йдуть автоматично.\n[gray]Потребуються точки появи ворогів для гри. mode.survival.description = Звичайний режим. В цьому режимі треба самим видобувати ресурси та хвилі йдуть автоматично.\n[gray]Потребуються точки появи ворогів для гри.
mode.sandbox.name = Пісочниця mode.sandbox.name = Пісочниця
mode.sandbox.description = В режимі «Пісочниця» незкінченні ресурси(але їх все одно можно добувати) та хвилі йдуть за вашим бажанням. mode.sandbox.description = Нескінченні ресурси та хвилі йдуть за вашим бажанням.
mode.editor.name = Редактор mode.editor.name = Редактор
mode.pvp.name = PVP mode.pvp.name = PVP
mode.pvp.description = боріться проти інших гравців.\n[gray]Для гри потрібно принаймні 2 ядра різного кольору на мапі. mode.pvp.description = Боріться проти інших гравців.\n[gray]Для гри потрібно принаймні 2 ядра різного кольору на мапі.
mode.attack.name = Атака mode.attack.name = Атака
mode.attack.description = Зруйнуйте ворожу базу.\n[gray]Потрібно червоне ядро на мапі для гри. mode.attack.description = Зруйнуйте ворожу базу.\n[gray]Потрібно червоне ядро на мапі для гри.
mode.custom = Користувацькі правила mode.custom = Користувацькі правила
rules.infiniteresources = Нескінченні ресурси rules.infiniteresources = Нескінченні ресурси
rules.reactorexplosions = Вибухи реактора rules.reactorexplosions = Вибухи реактора
rules.wavetimer = Таймер хвиль rules.wavetimer = Таймер для хвиль
rules.waves = Хвилі rules.waves = Хвилі
rules.attack = Режим атаки rules.attack = Режим атаки
rules.enemyCheat = Нескінченні ресурси для ШІ rules.enemyCheat = Нескінченні ресурси для червоної команди ШІ
rules.unitdrops = Ресурс бойових одиниць rules.unitdrops = Випадіння ресурсів з бойових одиниць
rules.unitbuildspeedmultiplier = Множник швидкості виробництва бойових одиниць rules.unitbuildspeedmultiplier = Множник швидкості виробництва бойових одиниць
rules.unithealthmultiplier = Множник здоров’я бойових одиниць rules.unithealthmultiplier = Множник здоров’я бойових одиниць
rules.blockhealthmultiplier = Множник здоров’я блоків rules.blockhealthmultiplier = Множник здоров’я блоків
rules.playerhealthmultiplier = Множник здоров’я гравця rules.playerhealthmultiplier = Множник здоров’я гравця
rules.playerdamagemultiplier = Множник шкоди гравця rules.playerdamagemultiplier = Множник шкоди гравця
rules.unitdamagemultiplier = Множник шкоди бойових одиниць rules.unitdamagemultiplier = Множник шкоди бойових одиниць
rules.enemycorebuildradius = Радіус захисту для ворожого ядра:[lightgray] (блоків) rules.enemycorebuildradius = Радіус захисту для ворожого ядра:[lightgray] (плитки)
rules.respawntime = Час відродження:[lightgray] (sec) rules.respawntime = Час відродження:[lightgray] (секунди)
rules.wavespacing = Інтервал хвиль:[lightgray] (sec) rules.wavespacing = Інтервал хвиль:[lightgray] (секунди)
rules.buildcostmultiplier = Множник затрат на будування rules.buildcostmultiplier = Множник затрат на будування
rules.buildspeedmultiplier = Множник швидкості будування rules.buildspeedmultiplier = Множник швидкості будування
rules.waitForWaveToEnd = Хвилі чекають на ворогів rules.waitForWaveToEnd = Хвилі чекають на смерть усіх ворогів
rules.dropzoneradius = Радіус зони висадки:[lightgray] (блоків) rules.dropzoneradius = Радіус зони висадки:[lightgray] (плитки)
rules.respawns = Максимальна кількість відроджень за хвилю rules.respawns = Максимальна кількість відроджень за хвилю
rules.limitedRespawns = Обмеження відроджень rules.limitedRespawns = Обмеження відроджень
rules.title.waves = Хвилі rules.title.waves = Хвилі
@@ -773,7 +779,7 @@ rules.title.respawns = Відродження
rules.title.resourcesbuilding = Ресурси & будування rules.title.resourcesbuilding = Ресурси & будування
rules.title.player = Гравці rules.title.player = Гравці
rules.title.enemy = Вороги rules.title.enemy = Вороги
rules.title.unit = Бойов. од. rules.title.unit = Бойові одиниці
rules.title.experimental = Есперементальне! rules.title.experimental = Есперементальне!
rules.lighting = Світлотінь rules.lighting = Світлотінь
rules.ambientlight = Навколишнє світло rules.ambientlight = Навколишнє світло
@@ -885,7 +891,7 @@ block.snow.name = Сніг
block.craters.name = Кратери block.craters.name = Кратери
block.sand-water.name = Пісок з водою block.sand-water.name = Пісок з водою
block.darksand-water.name = Темний пісок з водою block.darksand-water.name = Темний пісок з водою
block.char.name = Випалена Земля block.char.name = Випалена земля
block.holostone.name = Голографічний камінь block.holostone.name = Голографічний камінь
block.ice-snow.name = Крижаний сніг block.ice-snow.name = Крижаний сніг
block.rocks.name = Камені block.rocks.name = Камені
@@ -896,11 +902,11 @@ block.pine.name = Сосна
block.white-tree-dead.name = Мертве біле дерево block.white-tree-dead.name = Мертве біле дерево
block.white-tree.name = Біле дерево block.white-tree.name = Біле дерево
block.spore-cluster.name = Скупчення спор block.spore-cluster.name = Скупчення спор
block.metal-floor.name = Металевий пол 1 block.metal-floor.name = Металева підлога 1
block.metal-floor-2.name = Металевий пол 2 block.metal-floor-2.name = Металева підлога 2
block.metal-floor-3.name = Металевий пол 3 block.metal-floor-3.name = Металева підлога 3
block.metal-floor-5.name = Металевий пол 4 block.metal-floor-5.name = Металева підлога 4
block.metal-floor-damaged.name = Пошкоджений иеталевий пол block.metal-floor-damaged.name = Пошкоджена металевий підлога
block.dark-panel-1.name = Темна панель 1 block.dark-panel-1.name = Темна панель 1
block.dark-panel-2.name = Темна панель 2 block.dark-panel-2.name = Темна панель 2
block.dark-panel-3.name = Темна панель 3 block.dark-panel-3.name = Темна панель 3
@@ -928,11 +934,11 @@ block.duo.name = Подвійна турель
block.scorch.name = Випалювач block.scorch.name = Випалювач
block.scatter.name = Розсіювач block.scatter.name = Розсіювач
block.hail.name = Град block.hail.name = Град
block.lancer.name = Списоносець block.lancer.name = Списник
block.conveyor.name = Конвеєр block.conveyor.name = Конвеєр
block.titanium-conveyor.name = Титановий конвеєр block.titanium-conveyor.name = Титановий конвеєр
block.armored-conveyor.name = Броньований конвеєр block.armored-conveyor.name = Броньований конвеєр
block.armored-conveyor.description = Переміщує предмети з тією ж швидкістю, як і титанові конвеєри, але має більше міцності. Не приймає введення з боків ні з чого, крім інших конвеєрних стрічок. block.armored-conveyor.description = Переміщує предмети з тією ж швидкістю, що і титанові конвеєри, але має більше міцності. Не приймає введення з боків ні з чого, крім інших конвеєрних стрічок.
block.junction.name = Перехрестя block.junction.name = Перехрестя
block.router.name = Маршрутизатор block.router.name = Маршрутизатор
block.distributor.name = Розподілювач block.distributor.name = Розподілювач
@@ -940,15 +946,16 @@ block.sorter.name = Сортувальник
block.inverted-sorter.name = Зворотній сортувальник block.inverted-sorter.name = Зворотній сортувальник
block.message.name = Повідомлення block.message.name = Повідомлення
block.illuminator.name = Освітлювач block.illuminator.name = Освітлювач
block.illuminator.description = Невелике, компактне, джерело світла, яку можна налаштувати. Для функціонування потрібна енергія. block.illuminator.description = Невелике, компактне, джерело світла, яку можна налаштувати. Для роботи потребує енергії.
block.overflow-gate.name = Надмірний затвор block.overflow-gate.name = Надмірний затвір
block.underflow-gate.name = Інвертований затвір
block.silicon-smelter.name = Кремнієвий плавильний завод block.silicon-smelter.name = Кремнієвий плавильний завод
block.phase-weaver.name = Фазовий ткач block.phase-weaver.name = Фазовий ткач
block.pulverizer.name = Подрібнювач block.pulverizer.name = Подрібнювач
block.cryofluidmixer.name = Змішувач кріогенної рідини block.cryofluidmixer.name = Змішувач кріогенної рідини
block.melter.name = Плавильня block.melter.name = Плавильня
block.incinerator.name = Сміттєспалювальний завод block.incinerator.name = Сміттєспалювальний завод
block.spore-press.name = Споровий Прес block.spore-press.name = Споровий прес
block.separator.name = Відокремлювач block.separator.name = Відокремлювач
block.coal-centrifuge.name = Вугільна центрифуга block.coal-centrifuge.name = Вугільна центрифуга
block.power-node.name = Енергійний вузол block.power-node.name = Енергійний вузол
@@ -978,7 +985,7 @@ block.mechanical-pump.name = Механічна помпа
block.item-source.name = Нескінченне джерело предметів block.item-source.name = Нескінченне джерело предметів
block.item-void.name = Предметний вакуум block.item-void.name = Предметний вакуум
block.liquid-source.name = Нескінченне джерело рідин block.liquid-source.name = Нескінченне джерело рідин
block.liquid-void.name = Liquid Void block.liquid-void.name = Рідинний вакуум
block.power-void.name = Енергетичний вакуум block.power-void.name = Енергетичний вакуум
block.power-source.name = Нескінченне джерело енергії block.power-source.name = Нескінченне джерело енергії
block.unloader.name = Розвантажувач block.unloader.name = Розвантажувач
@@ -986,11 +993,11 @@ block.vault.name = Сховище
block.wave.name = Хвиля block.wave.name = Хвиля
block.swarmer.name = Роєвик block.swarmer.name = Роєвик
block.salvo.name = Залп block.salvo.name = Залп
block.ripple.name = Рябь block.ripple.name = Ряб
block.phase-conveyor.name = Фазовий конвеєр block.phase-conveyor.name = Фазовий конвеєр
block.bridge-conveyor.name = Мостовий конвеєр block.bridge-conveyor.name = Мостовий конвеєр
block.plastanium-compressor.name = Пластиновий компресор block.plastanium-compressor.name = Пластинієвий компресор
block.pyratite-mixer.name = Змішувач піротиту block.pyratite-mixer.name = Змішувач піротита
block.blast-mixer.name = Мішалка вибухонебезпечного з’єднання block.blast-mixer.name = Мішалка вибухонебезпечного з’єднання
block.solar-panel.name = Сонячна панель block.solar-panel.name = Сонячна панель
block.solar-panel-large.name = Велика сонячна панель block.solar-panel-large.name = Велика сонячна панель
@@ -1007,12 +1014,12 @@ block.titan-factory.name = Завод мехів «Титан»
block.fortress-factory.name = Завод мехів «Фортеця» block.fortress-factory.name = Завод мехів «Фортеця»
block.revenant-factory.name = Завод бомбардувальників «Потойбічний вбивця» block.revenant-factory.name = Завод бомбардувальників «Потойбічний вбивця»
block.repair-point.name = Ремонтний пункт block.repair-point.name = Ремонтний пункт
block.pulse-conduit.name = Імпульсний водопровід block.pulse-conduit.name = Імпульсний трубопровід
block.plated-conduit.name = Зміцнений водопровід block.plated-conduit.name = Зміцнений трубопровід
block.phase-conduit.name = Фазовий водопровід block.phase-conduit.name = Фазовий трубопровід
block.liquid-router.name = Рідкий маршрутизатор block.liquid-router.name = Рідинний маршрутизатор
block.liquid-tank.name = Рідкий резервуар block.liquid-tank.name = Рідинний резервуар
block.liquid-junction.name = Рідке перехрестя block.liquid-junction.name = Рідинне перехрестя
block.bridge-conduit.name = Мостовий водопровід block.bridge-conduit.name = Мостовий водопровід
block.rotary-pump.name = Роторний насос block.rotary-pump.name = Роторний насос
block.thorium-reactor.name = Торієвий реактор block.thorium-reactor.name = Торієвий реактор
@@ -1022,18 +1029,18 @@ block.thermal-pump.name = Тепловий насос
block.thermal-generator.name = Тепловий генератор block.thermal-generator.name = Тепловий генератор
block.alloy-smelter.name = Сплавовий завод block.alloy-smelter.name = Сплавовий завод
block.mender.name = Регенератор block.mender.name = Регенератор
block.mend-projector.name = Ремонтувальний гранатомет block.mend-projector.name = Відновлювальна установка
block.surge-wall.name = Кінетична стіна block.surge-wall.name = Кінетична стіна
block.surge-wall-large.name = Велика кінетична стіна block.surge-wall-large.name = Велика кінетична стіна
block.cyclone.name = Циклон block.cyclone.name = Циклон
block.fuse.name = Підривник block.fuse.name = Підривник
block.shock-mine.name = Шокуюча міна block.shock-mine.name = Шокуюча міна
block.overdrive-projector.name = Сверхприводний проектор block.overdrive-projector.name = Швидкісна пускова установка
block.force-projector.name = Силовий проектор block.force-projector.name = Силова пускова установка
block.arc.name = Дуга block.arc.name = Дуга
block.rtg-generator.name = Радіоізотопний термоелектричний генератор block.rtg-generator.name = Радіоізотопний термоелектричний генератор
block.spectre.name = Спектр block.spectre.name = Спектр
block.meltdown.name = Випалювач block.meltdown.name = Розплавлювач
block.container.name = Склад block.container.name = Склад
block.launch-pad.name = Стартовий майданчик block.launch-pad.name = Стартовий майданчик
block.launch-pad-large.name = Великий стартовий майданчик block.launch-pad-large.name = Великий стартовий майданчик
@@ -1056,43 +1063,43 @@ unit.fortress.name = Фортеця
unit.revenant.name = Потойбічний вбивця unit.revenant.name = Потойбічний вбивця
unit.eruptor.name = Вивиргатель unit.eruptor.name = Вивиргатель
unit.chaos-array.name = Масив хаосу unit.chaos-array.name = Масив хаосу
unit.eradicator.name = Випалювач unit.eradicator.name = Викорінювач
unit.lich.name = Лич unit.lich.name = Лич
unit.reaper.name = Жнець unit.reaper.name = Жнець
tutorial.next = [lightgray]<Натисніть для продовження> tutorial.next = [lightgray]<Натисніть для продовження>
tutorial.intro = Ви розпочали[scarlet] навчання по Mindustry.[]\nРозпочніть з [accent]видобутку міді[]. Використовуйте [[WASD] для руху.\n[accent]Прокручуйте миш[] для приближення і віддалення. Наблизьтесь до мідної жили біля вашого ядра, а потім натисніть на неї, щоб розпочати видобуток.\n\n[accent]{0}/{1} міді tutorial.intro = Ви розпочали[scarlet] навчання по Mindustry.[]\nРозпочніть з [accent]видобутку міді[]. Використовуйте [[WASD] для руху.\n[accent]Прокручуйте миш[] для приближення і віддалення. Наблизьтесь до мідної жили біля вашого ядра, а потім натисніть на неї, щоб розпочати видобуток.\n\n[accent]{0}/{1} міді
tutorial.intro.mobile = Ви розпочали[scarlet] навчання по Mindustry.[]\nПроведіть екраном, щоб рухатися.\n[accent] Зведіть або розведіть 2 пальця [] для приближення і віддалення відповідно.\nз[accent] видобування міді.[] Наблизьтесь, а потім натисність на мідну жилу біля вашого ядра, щоб зробити це.\n\n[accent]{0}/{1} міді tutorial.intro.mobile = Ви розпочали[scarlet] навчання по Mindustry.[]\nПроведіть екраном, щоб рухатися.\n[accent] Зведіть або розведіть 2 пальця [] для приближення і віддалення відповідно.\nз[accent] видобування міді.[] Наблизьтесь, а потім натисніть на мідну жилу біля вашого ядра, щоб зробити це.\n\n[accent]{0}/{1} міді
tutorial.drill = Добування вручну не є ефективним.\n[accent]Бури []можуть добувати автоматично.\nНатисніть на вкладку із зображенням свердла знизу праворуч.\nВиберіть[accent] механічний бур[]. Розмістіть його на мідній жилі натисканням.\nВи також можете вибрати бур, натиснувши [accent][[2][], а потім швидко натиснути [accent][[1][], незалежно від того, яка вкладка відкрита.\n[accent]Натисніть ПКМ[], щоб зупинити будування. tutorial.drill = Добування вручну не є ефективним.\n[accent]Бури []можуть добувати автоматично.\nНатисніть на вкладку із зображенням свердла праворуч знизу.\nВиберіть[accent] механічний бур[]. Розмістіть його на мідній жилі натисканням.\nВи також можете вибрати бур, натиснувши [accent][[2][], а потім швидко натиснувши [accent][[1][], незалежно від відкритої вкладки.\n[accent]Натисніть ПКМ[], щоб зупинити будування.
tutorial.drill.mobile = Добування вручну неефективне.\n[accent]Бури []можуть добувати автоматично.\nНатисність на вкладку із зображенням сведла знизу зправа.\nВиберіть[accent] механічний бур[]. Розмістіть його на мідній жилі натисканням, потім натисність на [accent]галочку[] нижче, щоб підтвердити розміщення .\nНатисніть [accent]кнопку X[], щоб скасувати розміщення. tutorial.drill.mobile = Добування вручну неефективне.\n[accent]Бури []можуть добувати автоматично.\nНатисніть на вкладку із зображенням свердла праворуч знизу.\nВиберіть[accent] механічний бур[]. Розмістіть його на мідній жилі натисканням, потім натисніть на [accent]галочку[] нижче, щоб підтвердити розміщення .\nНатисніть [accent]кнопку X[], щоб скасувати розміщення.
tutorial.blockinfo = Кожен блок має різні характеристики. Кожний бур може видобувати тільки певні руди.\nЩоб переглянути інформацію та характеристики блока,[accent] натисність на кнопку «?», коли ви вибрали блок у меню будування.[]\n\n[accent]Перегляньте характеристику Механічного бура прямо зараз.[] tutorial.blockinfo = Кожний блок має різні характеристики. Кожний бур може видобувати тільки певні руди.\nЩоб переглянути інформацію та характеристики блока,[accent] натисність на кнопку «?», коли ви вибрали блок у меню будування.[]\n\n[accent]Перегляньте характеристику Механічного бура негайно[]
tutorial.conveyor = [accent]Конвеєри[] використовуються для транспортування предметів до ядра.\nЗробіть лінію конвеєрів від бура до ядра.\n[accent]Утримуйте миш, щоб розмістити у лінію.[]\nУтримуйте[accent] CTRL[] під час вибору лінії для розміщення по діагоналі.\\nПрокручуйте, щоб обертати блоки до їх установлення.\n[accent]Розмістіть 2 конвеєри у лінію, а потім доставте предмет в ядро.tutorial.conveyor.mobile = [accent]Конвеєри[] використовується для транспортування предметів до ядра.\nЗробіть лінію конвеєрів від бура до ядра.\n[accent] Розмістить у лінію, утримуючи палець кілька секунд[] і тягніть у напрямку, який Ви вибрали.\nВикористовуйте колесо прокрутки, щоб обертати блоки перед їх розміщенням\n[accent]{0}/{1} конвеєрів, які розміщені в лінію\n[accent]0/1 предмет доставлено tutorial.conveyor = [accent]Конвеєри[] використовуються для транспортування предметів до ядра.\nЗробіть лінію конвеєрів від бура до ядра.\n[accent]Утримуйте миш для розміщення у лінію.[]\nУтримуйте[accent] CTRL[] під час вибору лінії для розміщення по діагоналі.\\nПрокручуйте, щоб обертати блоки до їх установлення.\n[accent]Розмістіть 2 конвеєри у лінію, а потім доставте предмет в ядро.
tutorial.conveyor.mobile = [accent]Conveyors[] are used to transport items to the core.\nMake a line of conveyors from the drill to the core.\n[accent] Place in a line by holding down your finger for a few seconds[] and dragging in a direction.\n\n[accent]Place 2 conveyors with the line tool, then deliver an item into the core. tutorial.conveyor.mobile =[accent]Конвеєри[] використовується для транспортування предметів до ядра.\nЗробіть лінію конвеєрів від бура до ядра.\n[accent] Розмістить у лінію, утримуючи палець кілька секунд[] і тягніть у напрямку, який Ви вибрали.\nВикористовуйте колесо прокрутки, щоб обертати блоки перед їх розміщенням\n[accent]{0}/{1} конвеєрів, які розміщені в лінію\n[accent]0/1 предмет доставлено
tutorial.turret = Оборонні споруди повинні бути побудовані для відбиття[lightgray] ворогів[].\nПобудуйте[accent] башту «Подвійна»[] біля вашої бази. tutorial.turret = Оборонні споруди повинні бути побудовані для відбиття[lightgray] ворогів[].\nПобудуйте[accent] башту «Подвійна»[] біля вашої бази.
tutorial.drillturret = «Подвійна» потребує [accent]мідні боєприпаси[] для стрільби.\nРозмістіть бур біля башточки\nПроведіть конвеєри до башточки, щоб заповнити її боєприпасами.\n\n[accent]Доставлено боєприпасів: 0/1 tutorial.drillturret = «Подвійна» потребує [accent]мідні боєприпаси[] для стрільби.\nРозмістіть бур біля башти\nПроведіть конвеєри до башти, щоб заповнити її боєприпасами.\n\n[accent]Доставлено боєприпасів: 0/1
tutorial.pause = Під час бою ви можете[accent] поставити на павзу гру.[]\nВи можете зробити чергу на будування під час паузи.\n\n[accent]Натисність пробіл для павзи. tutorial.pause = Під час гри ви можете[accent] поставити на павзу.[]\nВи можете зробити чергу на будування під час паузи.\n\n[accent]Натисніть пробіл для павзи.
tutorial.pause.mobile = Під час бою ви можете[accent] поставити на павзу гру.[]\nВи можете зробити чергу на будування під час паузи.\n\n[accent]Натисніть кнопку вгорі ліворуч для павзи. tutorial.pause.mobile = Під час гри ви можете[accent] поставити на павзу.[]\nВи можете зробити чергу на будування під час паузи.\n\n[accent]Натисніть кнопку вгорі ліворуч для павзи.
tutorial.unpause = Тепер натисність пробіл, щоб зняти павзу. tutorial.unpause = Призупиніть гру, натиснувши на пробіл.
tutorial.unpause.mobile = Тепер натисність туди ще раз, щоб зняти павзу. tutorial.unpause.mobile = Тепер натисність туди ще раз, щоб зняти павзу.
tutorial.breaking = Блоки часто повинні бути знищені.\n[accent]Утримуючи ПКМ[] ви знищите всі виділені блоки.[]\n\n[accent]Необхідно знищити всі стіни з металобрухту ліворуч від вашого ядра використовуючи видалення у зоні. tutorial.breaking = Блоки часто треба знищувати.\n[accent]Утримуючи ПКМ[] ви знищите всі виділені блоки.[]\n\n[accent]Необхідно знищити всі стіни з металобрухту ліворуч від вашого ядра використовуючи видалення у зоні.
tutorial.breaking.mobile = Блоки часто повинні бути знищені.\n[accent]Виберіть режим руйнування[], потім натисніть на блок, щоб зламати його.\nЗнищіть область, утримуючи палець протягом декількох секунд [] і потягнувши в потрібному напрямку.\nНатисніть кнопку галочки, щоб підтвердити руйнування.\n\n[accent]Необхідно знищити всі стіни з металобрухту ліворуч від вашого ядра використовуючи видалення у зоні. tutorial.breaking.mobile = Блоки часто треба знищувати.\n[accent]Виберіть режим руйнування[], потім натисніть на блок, щоб зламати його.\nЗнищте область, утримуючи палець протягом декількох секунд [] і потягнувши в потрібному напрямку.\nНатисніть кнопку галочки, щоб підтвердити руйнування.\n\n[accent]Необхідно знищити всі стіни з металобрухту ліворуч від вашого ядра використовуючи видалення у зоні.
tutorial.withdraw = У деяких ситуаціях потрібно брати предмети безпосередньо з блоків.\nЩоб зробити це, [accent]натисність на блок[] з предметами, і потім [accent]натисніть на предмет[] в інвентарі.\nМожна вилучити кілька предметів [accent]натискаючи та утримуючи[].\n\n[accent]Вилучіть трохи міді з ядра.[] tutorial.withdraw = У деяких ситуаціях потрібно брати предмети безпосередньо з блоків.\nЩоб зробити це, [accent]натисність на блок[] з предметами, і потім [accent]натисніть на предмет[] в інвентарі.\nМожна вилучити кілька предметів [accent]натискаючи та утримуючи[].\n\n[accent]Вилучіть трохи міді з ядра.[]
tutorial.deposit = Покладіть предмети в блоки, перетягнувши з вашого корабля в потрібний блок.\n\n[accent]Покладіть мідь назад у ядро.[] tutorial.deposit = Покладіть предмети в блок, перетягнувши з вашого корабля в потрібний блок.\n\n[accent]Покладіть мідь назад у ядро.[]
tutorial.waves = [lightgray] Ворог[] з’явився.\n\nЗахистіть ядро від двух хвиль.[accent] Натисніть ЛКМ[], щоб стріляти.\nСтворіть більше башт і бурів. Добудьте більше міді. tutorial.waves = [lightgray] Ворог[] з’явився.\n\nЗахистіть ядро від двух хвиль.[accent] Натисніть ЛКМ[], щоб стріляти.\nПобудуйте більше башт і бурів. Добудьте більше міді.
tutorial.waves.mobile = [lightgray] Ворог[] з’явився.\n\nЗахистіть ядро від двух хвиль. Ваш корабель буде автоматично атакувати ворогів.\nСтворіть більше башт і бурів. Добудьте більше міді. tutorial.waves.mobile = [lightgray] Ворог[] з’явився.\n\nЗахистіть ядро від двух хвиль. Ваш корабель буде автоматично атакувати ворогів.\nПобудуйте більше башт і бурів. Добудьте більше міді.
tutorial.launch = Як тільки ви досягнете певної хвилі, ви зможете[accent] запустити ядро[], залишивши захисні сили позаду та [accent]отримати всі ресурси у вашому ядрі.[]\nЦі отримані ресурси можуть бути використані для дослідження нових технологій.\n\n[accent]Натисніть кнопку запуску. tutorial.launch = Як тільки ви досягнете певної хвилі, ви зможете[accent] запустити ядро[], залишивши свою базу позаду, та [accent]отримати всі ресурси у вашому ядрі.[]\nЦі отримані ресурси можуть бути використані для дослідження нових технологій.\n\n[accent]Натисніть кнопку запуску.
item.copper.description = Найбільш базовий будівельний матеріал. Широко використовується у всіх типах блоків. item.copper.description = Початковий будівельний матеріал. Широко використовується у всіх типах блоків.
item.lead.description = Основний стартовий матеріал. Широко застосовується в електроніці та транспортуванні рідин. item.lead.description = Основний стартовий матеріал. Широко застосовується в електроніці та у транспортуванні рідин.
item.metaglass.description = Супер жорсткий склад скла. Широко застосовується для розподілу та зберігання рідини. item.metaglass.description = Дуже жорсткий склад скла. Широко застосовується для розподілу та зберігання рідини.
item.graphite.description = Мінералізований вуглець, що використовується для боєприпасів та як компонент. item.graphite.description = Мінералізований вуглець, що використовується для боєприпасів та як електричний компонент.
item.sand.description = Поширений матеріал, який широко використовується при виплавці, як при сплавленні, так і в якості відходів. item.sand.description = Поширений матеріал, який широко використовується при виплавці, як при сплавленні, так і в якості відходів.
item.coal.description = Окам’янілі рослинні речовини, що утворюються задовго до посіву. Широко використовується для виробництва пального та ресурсів. item.coal.description = Окам’янілі рослинні речовини, що утворюються задовго до посіву. Широко використовується для виробництва пального та ресурсів.
item.titanium.description = Рідкісний надлегкий метал, який широко використовується для транспортування рідини, бурів і літаків. item.titanium.description = Рідкісний надлегкий метал, який широко використовується для транспортування рідини, бурів і літаків.
item.thorium.description = Щільний, радіоактивний метал, що використовується в якості конструкційної опори та ядерного палива. item.thorium.description = Щільний радіоактивний метал, що використовується в якості конструкційної опори та ядерного палива.
item.scrap.description = Залишилися залишки старих споруд та підрозділів. Містить мікроелементи багатьох різних металів. item.scrap.description = Залишки старих споруд та підрозділів. Містить мікроелементи багатьох різних металів.
item.silicon.description = Надзвичайно корисний напівпровідник. Застосовується в сонячних батареях, складній електроніці та бойових боєприпасах. item.silicon.description = Надзвичайно корисний напівпровідник. Має застосування в сонячних батареях, складній електроніці та баштових боєприпасах.
item.plastanium.description = Легкий, пластичний матеріал, що використовується в сучасних літальних апаратах та у роздроблених боєприпасах. item.plastanium.description = Легкий пластичний матеріал, що використовується в сучасних літальних апаратах та у фрагментованих боєприпасах.
item.phase-fabric.description = Майже невагома речовина, що застосовується в передовій електроніці та технології саморемонту. item.phase-fabric.description = Майже невагома речовина, що застосовується в передовій електроніці та у технології самовідновлення.
item.surge-alloy.description = Удосконалений сплав з унікальними електричними властивостями. item.surge-alloy.description = Удосконалений сплав з унікальними електричними властивостями.
item.spore-pod.description = Струмок синтетичних спор, синтезований з атмосферних концентрацій для промислових цілей. Використовується для перетворення на нафту, вибухівку та паливо. item.spore-pod.description = Струмок синтетичних спор, синтезований з атмосферних концентрацій для промислових цілей. Використовується для перетворення на нафту, вибухівку та паливо.
item.blast-compound.description = Нестабільна сполука, яка використовується в бомбах і вибухівках. Синтезується із спорових стручків та інших летких речовин. Використовувати як паливо не рекомендується. item.blast-compound.description = Нестабільна сполука, яка використовується в бомбах і вибухівках. Синтезується із спорових стручків та інших летких речовин. Використовувати як паливо не рекомендується.
@@ -1143,7 +1150,7 @@ block.item-source.description = Нескінченно виводить пред
block.item-void.description = Знищує будь-які предмети. block.item-void.description = Знищує будь-які предмети.
block.liquid-source.description = Нескінченно виводить рідини. block.liquid-source.description = Нескінченно виводить рідини.
block.liquid-void.description = Removes any liquids. Sandbox only. block.liquid-void.description = Removes any liquids. Sandbox only.
block.copper-wall.description = Дешевий захисний блок.\nКорисна для захисту ядра та башто у перші кілька хвиль. block.copper-wall.description = Дешевий захисний блок.\nКорисна для захисту ядра та башти у перші кілька хвиль.
block.copper-wall-large.description = Дешевий захисний блок.\nКорисна для захисту ядра та башт у перші кілька хвиль.\nОхоплює кілька плиток. block.copper-wall-large.description = Дешевий захисний блок.\nКорисна для захисту ядра та башт у перші кілька хвиль.\nОхоплює кілька плиток.
block.titanium-wall.description = Відносно сильний захисний блок.\nЗабезпечує помірний захист від ворогів. block.titanium-wall.description = Відносно сильний захисний блок.\nЗабезпечує помірний захист від ворогів.
block.titanium-wall-large.description = Відносно сильний захисний блок.\nЗабезпечує помірний захист від ворогів.\nОхоплює кілька плиток. block.titanium-wall-large.description = Відносно сильний захисний блок.\nЗабезпечує помірний захист від ворогів.\nОхоплює кілька плиток.
@@ -1157,7 +1164,7 @@ block.surge-wall.description = Надзвичайно міцний захисн
block.surge-wall-large.description = Надзвичайно міцний захисний блок.\nЗбільшує заряд при контакті з кулями, вивільняючи його випадковим чином.\nОхоплює кілька плиток. block.surge-wall-large.description = Надзвичайно міцний захисний блок.\nЗбільшує заряд при контакті з кулями, вивільняючи його випадковим чином.\nОхоплює кілька плиток.
block.door.description = Невеликі двері. Можна відкрити або закрити, натиснувши. block.door.description = Невеликі двері. Можна відкрити або закрити, натиснувши.
block.door-large.description = Великі двері. Можна відкрити або закрити, натиснувши.\nОхоплює кілька плиток. block.door-large.description = Великі двері. Можна відкрити або закрити, натиснувши.\nОхоплює кілька плиток.
block.mender.description = Періодично ремонтує блоки у його радіусі дії. Захищає башточки та стіни.\nЗа бажанням, можна використати кремній для підвищення дальності та ефективності. block.mender.description = Періодично ремонтує блоки у його радіусі дії. Захищає башти та стіни.\nЗа бажанням, можна використати кремній для підвищення дальності та ефективності.
block.mend-projector.description = Покращена версія «Регенератора». Періодично ремонтує блоки у його радіусі дії.\nЗа бажанням, можна використати фазова тканина для підвищення дальності та ефективності. block.mend-projector.description = Покращена версія «Регенератора». Періодично ремонтує блоки у його радіусі дії.\nЗа бажанням, можна використати фазова тканина для підвищення дальності та ефективності.
block.overdrive-projector.description = Збільшує швидкість прилеглих будівель.\nЗа бажанням, можна використати фазова тканина для підвищення дальності та ефективності. block.overdrive-projector.description = Збільшує швидкість прилеглих будівель.\nЗа бажанням, можна використати фазова тканина для підвищення дальності та ефективності.
block.force-projector.description = Створює навколо себе шестикутне силове поле, захищаючи будівлі та блоки всередині від пошкоджень.\nПерегрівається, якщо завдано занадто великої шкоди. За бажанням, можна використати теплоносій для запобігання перегріву. Для збільшення розміру щита можна використовувати фазову тканину. block.force-projector.description = Створює навколо себе шестикутне силове поле, захищаючи будівлі та блоки всередині від пошкоджень.\nПерегрівається, якщо завдано занадто великої шкоди. За бажанням, можна використати теплоносій для запобігання перегріву. Для збільшення розміру щита можна використовувати фазову тканину.
@@ -1166,12 +1173,13 @@ block.conveyor.description = Базовий транспортний блок.
block.titanium-conveyor.description = Покращений блок транспорту елементів. Переміщує предмети швидше, ніж звичайні конвеєри. block.titanium-conveyor.description = Покращений блок транспорту елементів. Переміщує предмети швидше, ніж звичайні конвеєри.
block.junction.description = Діє як міст для двох перехресних конвеєрних стрічок. Корисно в ситуаціях, коли два різних конвеєри перевозять різні матеріали в різні місця. block.junction.description = Діє як міст для двох перехресних конвеєрних стрічок. Корисно в ситуаціях, коли два різних конвеєри перевозять різні матеріали в різні місця.
block.bridge-conveyor.description = Покращений блок транспорту елементів. Дозволяє транспортувати предмети до 3-ох плиток з будь-якої місцевості чи будівлі. block.bridge-conveyor.description = Покращений блок транспорту елементів. Дозволяє транспортувати предмети до 3-ох плиток з будь-якої місцевості чи будівлі.
block.phase-conveyor.description = Покращений блок транспорту елементів. Використовує енергію для телепортування елементів на підключений фазовий конвеєр через кілька плиток. block.phase-conveyor.description = Покращений блок транспорту елементів. Використовує енергію для телепортування елементів на під’єднаний фазовий конвеєр через кілька плиток.
block.sorter.description = Сортує предмети. Якщо елемент відповідає вибраному, його можна передати. В іншому випадку елемент виводиться зліва та справа. block.sorter.description = Сортує предмети. Якщо елемент відповідає вибраному, його можна передати. В іншому випадку елемент виводиться зліва та справа.
block.inverted-sorter.description = Обробляє елементи, як звичайний сортувальник, але виводить обрані елементи на сторони. block.inverted-sorter.description = Обробляє елементи, як звичайний сортувальник, але виводить обрані елементи на сторони.
block.router.description = Приймає елементи з одного напрямку та виводить їх до трьох інших напрямків порівну. Корисно для поділу матеріалів від одного джерела до кількох цілей.\n\n[scarlet]Ніколи не використовуйте поруч із входами до механізмів, оскільки вони будуть забиті вихідними предметами.[] block.router.description = Приймає елементи з одного напрямку та виводить їх до трьох інших напрямків порівну. Корисно для поділу матеріалів від одного джерела до кількох цілей.\n\n[scarlet]Ніколи не використовуйте поруч із входами до механізмів, оскільки вони будуть забиті вихідними предметами.[]
block.distributor.description = Розширений маршрутизатор. Розділяє предмети до 7 інших напрямків порівну. block.distributor.description = Розширений маршрутизатор. Розділяє предмети до 7 інших напрямків порівну.
block.overflow-gate.description = Виходи лише вліво і вправо, якщо передній шлях заблокований. block.overflow-gate.description = Виходи лише вліво і вправо, якщо передній шлях заблокований.
block.underflow-gate.description = Повна протилежність надмірному затвору. Виводить предмет прямо, якщо лівий і/чи правий шлях заблоковано.
block.mass-driver.description = Кінцевий елемент транспортного блоку. Збирає кілька предметів, а потім вистрілює їх до іншої електромагнитної катапульти на великій відстані. Для роботи потрібна енергія. block.mass-driver.description = Кінцевий елемент транспортного блоку. Збирає кілька предметів, а потім вистрілює їх до іншої електромагнитної катапульти на великій відстані. Для роботи потрібна енергія.
block.mechanical-pump.description = Недорогий насос з повільним виходом, але без енергоспоживання. block.mechanical-pump.description = Недорогий насос з повільним виходом, але без енергоспоживання.
block.rotary-pump.description = Удосконалений насос. Насоси більше викачують, але потребують енергію. block.rotary-pump.description = Удосконалений насос. Насоси більше викачують, але потребують енергію.
@@ -1183,8 +1191,8 @@ block.liquid-router.description = Приймає рідини з одного н
block.liquid-tank.description = Зберігає велику кількість рідини. Використовуйте для створення буферів у ситуаціях з непостійним попитом на матеріали або як гарантію охолодження життєво важливих блоків. block.liquid-tank.description = Зберігає велику кількість рідини. Використовуйте для створення буферів у ситуаціях з непостійним попитом на матеріали або як гарантію охолодження життєво важливих блоків.
block.liquid-junction.description = Діє як міст для двох каналів перетину. Корисно в ситуаціях, коли два різні трубопроводи перевозять різні рідини в різні місця. block.liquid-junction.description = Діє як міст для двох каналів перетину. Корисно в ситуаціях, коли два різні трубопроводи перевозять різні рідини в різні місця.
block.bridge-conduit.description = Розширений блок транспортування рідини. Дозволяє транспортувати рідину до 3 плиток будь-якої місцевості чи будівлі. block.bridge-conduit.description = Розширений блок транспортування рідини. Дозволяє транспортувати рідину до 3 плиток будь-якої місцевості чи будівлі.
block.phase-conduit.description = Розширений блок транспортування рідини. Використовує енергію для транспортування рідин до підключеного фазового каналу через декілька плиток. block.phase-conduit.description = Розширений блок транспортування рідини. Використовує енергію для транспортування рідин до приєднаного фазового каналу через декілька плиток.
block.power-node.description = Передає живлення на підключені вузли. Вузол буде отримувати живлення від будь-яких сусідніх блоків або подавати живлення до них. block.power-node.description = Передає живлення на приєднані вузли. Вузол буде отримувати живлення від будь-яких сусідніх блоків або подавати живлення до них.
block.power-node-large.description = Удосконалений вузол живлення з більшим діапазоном. block.power-node-large.description = Удосконалений вузол живлення з більшим діапазоном.
block.surge-tower.description = Надзвичайно дальний вузол живлення з меншою кількістю доступних з’єднань. block.surge-tower.description = Надзвичайно дальний вузол живлення з меншою кількістю доступних з’єднань.
block.diode.description = Живлення акумулятора може протікати через цей блок лише в одному напрямку, але лише в тому випадку, якщо інша сторона має менше енергії. block.diode.description = Живлення акумулятора може протікати через цей блок лише в одному напрямку, але лише в тому випадку, якщо інша сторона має менше енергії.
@@ -1198,7 +1206,7 @@ block.rtg-generator.description = Простий, надійний генера
block.solar-panel.description = Забезпечує невелику кількість енергії від сонця. block.solar-panel.description = Забезпечує невелику кількість енергії від сонця.
block.solar-panel-large.description = Значно ефективніша версія стандартної сонячної панелі. block.solar-panel-large.description = Значно ефективніша версія стандартної сонячної панелі.
block.thorium-reactor.description = Виробляє значну кількість енергії з торію. Вимагає постійного охолодження. Вибухне сильно, якщо подаватиметься недостатньо кількості теплоносія. Вихідна потужність залежить від повноти, базова потужність генерується на повній потужності. block.thorium-reactor.description = Виробляє значну кількість енергії з торію. Вимагає постійного охолодження. Вибухне сильно, якщо подаватиметься недостатньо кількості теплоносія. Вихідна потужність залежить від повноти, базова потужність генерується на повній потужності.
block.impact-reactor.description = Удосконалений генератор, здатний створювати величезну кількість енергії при максимальній ефективності. Для швидкого запуску процесу потрібно значне введення енергії. block.impact-reactor.description = Удосконалений генератор, здатний створювати величезну кількість енергії при максимальній ефективності. Для запуску процесу потрібно значні обсяги енергії.
block.mechanical-drill.description = Недорогий бур. Розміщуючи їх на відповідних плитках, виводить предмети повільним темпом нескінченно. Здатний видобувати лише мідь, свинець і вугілля. block.mechanical-drill.description = Недорогий бур. Розміщуючи їх на відповідних плитках, виводить предмети повільним темпом нескінченно. Здатний видобувати лише мідь, свинець і вугілля.
block.pneumatic-drill.description = Вдосконалений бур, здатний добувати титан. Шахти швидше, ніж механічна дриль. block.pneumatic-drill.description = Вдосконалений бур, здатний добувати титан. Шахти швидше, ніж механічна дриль.
block.laser-drill.description = Дозволяє виконувати свердління ще швидше за допомогою лазерної технології, але вимагає енергії. Здатний до видобутку торію. block.laser-drill.description = Дозволяє виконувати свердління ще швидше за допомогою лазерної технології, але вимагає енергії. Здатний до видобутку торію.
@@ -1233,17 +1241,17 @@ block.draug-factory.description = Виробляє дронів, які видо
block.spirit-factory.description = Виробляє дронів, які ремонтують блоки. block.spirit-factory.description = Виробляє дронів, які ремонтують блоки.
block.phantom-factory.description = Виробляє дронів, які допомогають у будівництві. block.phantom-factory.description = Виробляє дронів, які допомогають у будівництві.
block.wraith-factory.description = Виробляє швидких перехоплювачів, які використовують тактику «стріляй і біжи». block.wraith-factory.description = Виробляє швидких перехоплювачів, які використовують тактику «стріляй і біжи».
block.ghoul-factory.description = Виробляє важкі килимові бомбардувальники. block.ghoul-factory.description = Виробляє важкокилимових бомбардувальників.
block.revenant-factory.description = Випускає важкі ракетні одиниці. block.revenant-factory.description = Виробляє важких ракетних одиниць.
block.dagger-factory.description = Виробляє елементарні наземні одиниці. block.dagger-factory.description = Виробляє початкових наземних одиниць.
block.crawler-factory.description = Виробляє швидкі саморуйнуючі бойові одиниці. block.crawler-factory.description = Виробляє швидких і самовибухових одиниць.
block.titan-factory.description = Виробляє поліпшених наземних бойових одиниць. block.titan-factory.description = Виробляє поліпшених наземних одиниць.
block.fortress-factory.description = Виробляє наземних бойових одиници, які схожі на важку артилерію. block.fortress-factory.description = Виробляє важкоартилерійних наземних одиниць.
block.repair-point.description = Безперервно лікує найближчий пошкоджену бойову одиницю чи мех, що знаходиться поруч. block.repair-point.description = Безперервно лікує найближчу пошкоджену бойову одиницю, що знаходиться поруч.
block.dart-mech-pad.description = Забезпечує перетворення в основий атакуючий мех.\nВикористовуйте, натискаючи, стоячи на ньому. block.dart-mech-pad.description = Забезпечує перетворення в основий атакуючий мех.\nВикористовуйте, натиснувши, коли стоїте на ньому.
block.delta-mech-pad.description = Забезпечує перетворення в легкоброньований атакуючий мех.\nВикористовуйте, натискаючи, стоячи на ньому. block.delta-mech-pad.description = Забезпечує перетворення в легкоброньований атакуючий мех.\nВикористовуйте, натиснувши, коли стоїте на ньому.
block.tau-mech-pad.description = Забезпечує перетворення в поліпшений мех підтримки.\nВикористовуйте, натискаючи, стоячи на ньому. block.tau-mech-pad.description = Забезпечує перетворення в поліпшений мех підтримки.\nВикористовуйте, натиснувши, коли стоїте на ньому.
block.omega-mech-pad.description = Забезпечує перетворення в тяжкоброньований ракетний мех.\nВикористовуйте, натискаючи, стоячи на ньому. block.omega-mech-pad.description = Забезпечує перетворення в тяжкоброньований ракетний мех.\nВикористовуйте, натиснувши, коли стоїте на ньому.
block.javelin-ship-pad.description = Забезпечує перетворення в швидкий, легкоброньований перехоплювач.\nВикористовуйте, натискаючи, стоячи на ньому. block.javelin-ship-pad.description = Забезпечує перетворення в швидкий, легкоброньований перехоплювач.\nВикористовуйте, натиснувши, коли стоїте на ньому.
block.trident-ship-pad.description = Забезпечує перетворення в тяжкий бомбардувальник.\nВикористовуйте, натискаючи, стоячи на ньому. block.trident-ship-pad.description = Забезпечує перетворення в тяжкий бомбардувальник.\nВикористовуйте, натискаючи, стоячи на ньому.
block.glaive-ship-pad.description = Забезпечує перетворення в великий, добреброньований корабель.\nВикористовуйте, натискаючи, стоячи на ньому. block.glaive-ship-pad.description = Забезпечує перетворення в великий добреброньований корабель зі зроєю.\nВикористовуйте, натиснувши, коли стоїте на ньому.

View File

@@ -12,7 +12,7 @@ link.itch.io.description = itch.io 上的 PC 版下载
link.google-play.description = Google Play 页面 link.google-play.description = Google Play 页面
link.f-droid.description = F-Droid 页面 link.f-droid.description = F-Droid 页面
link.wiki.description = Mindustry 官方 Wiki link.wiki.description = Mindustry 官方 Wiki
link.feathub.description = Suggest new features link.feathub.description = 提出新特性的建议
linkfail = 打开链接失败!\n网址已复制到您的剪贴板。 linkfail = 打开链接失败!\n网址已复制到您的剪贴板。
screenshot = 屏幕截图已保存到 {0} screenshot = 屏幕截图已保存到 {0}
screenshot.invalid = 地图太大,可能没有足够的内存用于截图。 screenshot.invalid = 地图太大,可能没有足够的内存用于截图。
@@ -29,12 +29,13 @@ load.system = 系统加载中
load.mod = 模组加载中 load.mod = 模组加载中
load.scripts = Scripts load.scripts = Scripts
be.update = A new Bleeding Edge build is available:
be.update.confirm = Download it and restart now? be.update = 发现游戏最新版本:
be.updating = Updating... be.update.confirm = 现在下载并重启游戏?
be.ignore = Ignore be.updating = 更新...
be.noupdates = No updates found. be.ignore = 忽略
be.check = Check for updates be.noupdates = 未发现更新。
be.check = 检测更新
schematic = 蓝图 schematic = 蓝图
schematic.add = 保存蓝图… schematic.add = 保存蓝图…
@@ -110,22 +111,22 @@ mod.disable = 禁用
mod.delete.error = 无法删除模组。可能文件被占用。 mod.delete.error = 无法删除模组。可能文件被占用。
mod.requiresversion = [scarlet]所需的游戏版本:[accent]{0} mod.requiresversion = [scarlet]所需的游戏版本:[accent]{0}
mod.missingdependencies = [scarlet]缺少依赖条件:{0} mod.missingdependencies = [scarlet]缺少依赖条件:{0}
mod.erroredcontent = [scarlet]Content Errors mod.erroredcontent = [scarlet]内容content)错误
mod.errors = Errors have occurred loading content. mod.errors = 读取内容(content)时发生错误.
mod.noerrorplay = [scarlet]You have mods with errors.[] Either disable the affected mods or fix the errors before playing. mod.noerrorplay = [scarlet]你的模组发生了错误.[] 禁用相关模组或修复错误后才能进入游戏.
mod.nowdisabled = [scarlet]“{0}”模组缺少依赖条件:[accent] {1}\n[lightgray]需要先下载上述模组。\n此模组现在将自动禁用。 mod.nowdisabled = [scarlet]“{0}”模组缺少依赖条件:[accent] {1}\n[lightgray]需要先下载上述模组。\n此模组现在将自动禁用。
mod.enable = 启用 mod.enable = 启用
mod.requiresrestart = 需要重启使模组生效。 mod.requiresrestart = 需要重启使模组生效。
mod.reloadrequired = [scarlet]需要重启 mod.reloadrequired = [scarlet]需要重启
mod.import = 导入模组 mod.import = 导入模组
mod.import.github = 导入 GitHub 模组 mod.import.github = 导入 GitHub 模组
mod.item.remove = This item is part of the[accent] '{0}'[] mod. To remove it, uninstall that mod. mod.item.remove = 这个物品是[accent] '{0}'[]模组的一部分. 删除物品需要先卸载此模组.
mod.remove.confirm = 此模组将被删除。 mod.remove.confirm = 此模组将被删除。
mod.author = [LIGHT_GRAY]作者:[] {0} mod.author = [LIGHT_GRAY]作者:[] {0}
mod.missing = 此存档包含您最近已更新或者现在未安装的模组。存档可能会损坏。确定要加载它吗?\n[lightgray]模组:\n{0} mod.missing = 此存档包含您最近已更新或者现在未安装的模组。存档可能会损坏。确定要加载它吗?\n[lightgray]模组:\n{0}
mod.preview.missing = 在创意工坊中发布此模组前,您必须添加一则预览图像。\n请将名为[accent] preview.png[] 的图像放入模组文件夹,然后重试。 mod.preview.missing = 在创意工坊中发布此模组前,您必须添加一则预览图像。\n请将名为[accent] preview.png[] 的图像放入模组文件夹,然后重试。
mod.folder.missing = 只有文件夹形式的模组能在创意工坊上发布。\n若要将任何模组转换为文件夹只需将其文件解压缩到文件夹中并删除旧压缩包然后重新启动游戏或重新加载模组。 mod.folder.missing = 只有文件夹形式的模组能在创意工坊上发布。\n若要将任何模组转换为文件夹只需将其文件解压缩到文件夹中并删除旧压缩包然后重新启动游戏或重新加载模组。
mod.scripts.unsupported = Your device does not support mod scripts. Some mods will not function correctly. mod.scripts.unsupported = 你的设备不支持模组脚本,一些模组可能不会正确工作。
about.button = 关于 about.button = 关于
name = 名字: name = 名字:
@@ -155,7 +156,7 @@ server.kicked.nameEmpty = 无效的名字!
server.kicked.idInUse = 你已在这个服务器上!不允许用两个账号连接。 server.kicked.idInUse = 你已在这个服务器上!不允许用两个账号连接。
server.kicked.customClient = 这个服务器不支持自定义版本。请下载官方版本。 server.kicked.customClient = 这个服务器不支持自定义版本。请下载官方版本。
server.kicked.gameover = 游戏结束! server.kicked.gameover = 游戏结束!
server.kicked.serverRestarting = The server is restarting. server.kicked.serverRestarting = 服务器正在重启.
server.versions = 客户端版本:[accent] {0}[]\n服务器版本[accent] {1}[] server.versions = 客户端版本:[accent] {0}[]\n服务器版本[accent] {1}[]
host.info = [accent]创建局域网游戏[]按钮会在[scarlet] 6567 []端口运行一个服务器。[]\n任何在同一个[lightgray] Wi-Fi 或本地网络[]下的人应该都可以在服务器列表中看到你的服务器。\n\n如果你想让别人在任何地方都能通过 IP 地址连接,你需要设定[accent]端口转发[]。\n\n[lightgray]注意:如果某人无法连接到你的局域网游戏,请确保你在防火墙设置里允许了 Mindustry 访问本地网络。 host.info = [accent]创建局域网游戏[]按钮会在[scarlet] 6567 []端口运行一个服务器。[]\n任何在同一个[lightgray] Wi-Fi 或本地网络[]下的人应该都可以在服务器列表中看到你的服务器。\n\n如果你想让别人在任何地方都能通过 IP 地址连接,你需要设定[accent]端口转发[]。\n\n[lightgray]注意:如果某人无法连接到你的局域网游戏,请确保你在防火墙设置里允许了 Mindustry 访问本地网络。
join.info = 您可以输入[accent]服务器的 IP 地址[]来连接,或寻找[accent]本地网络[]中的服务器来连接。\n支持局域网或广域网的多人游戏。\n\n[lightgray]注意:没有全球服务器列表;如果你想通过 IP 地址连接某个服务器,你需要向房主询问 IP 地址。 join.info = 您可以输入[accent]服务器的 IP 地址[]来连接,或寻找[accent]本地网络[]中的服务器来连接。\n支持局域网或广域网的多人游戏。\n\n[lightgray]注意:没有全球服务器列表;如果你想通过 IP 地址连接某个服务器,你需要向房主询问 IP 地址。
@@ -325,7 +326,7 @@ waves.copy = 复制到剪贴板
waves.load = 从剪贴板读取 waves.load = 从剪贴板读取
waves.invalid = 剪贴板中的波次信息无效。 waves.invalid = 剪贴板中的波次信息无效。
waves.copied = 波次信息已复制。 waves.copied = 波次信息已复制。
waves.none = 没有定义敌人。\n请注意空布局将自动替换为默认布局 waves.none = 没有定义敌人。\n请注意将自动替换为默认的敌人列表
editor.default = [lightgray]<默认> editor.default = [lightgray]<默认>
details = 详情… details = 详情…
edit = 编辑… edit = 编辑…
@@ -453,7 +454,7 @@ launch.confirm = 您将装载并发射核心中的所有资源。\n此地图将
launch.skip.confirm = 如果现在跳过,在下一个发射窗口到来前,您都无法发射。 launch.skip.confirm = 如果现在跳过,在下一个发射窗口到来前,您都无法发射。
uncover = 解锁 uncover = 解锁
configure = 设定装运的数量 configure = 设定装运的数量
bannedblocks = 禁用方块 bannedblocks = 禁用建筑
addall = 添加所有 addall = 添加所有
configure.locked = [lightgray]完成{0}\n解锁装运配置。 configure.locked = [lightgray]完成{0}\n解锁装运配置。
configure.invalid = 数量必须是0到{0}之间的数字。 configure.invalid = 数量必须是0到{0}之间的数字。
@@ -512,7 +513,7 @@ settings.language = 语言
settings.data = 游戏数据 settings.data = 游戏数据
settings.reset = 恢复默认设置 settings.reset = 恢复默认设置
settings.rebind = 重新绑定 settings.rebind = 重新绑定
settings.resetKey = Reset settings.resetKey = 重置按键
settings.controls = 控制 settings.controls = 控制
settings.game = 游戏 settings.game = 游戏
settings.sound = 声音 settings.sound = 声音
@@ -549,7 +550,7 @@ blocks.powerdamage = 功率/损伤
blocks.itemcapacity = 物品容量 blocks.itemcapacity = 物品容量
blocks.basepowergeneration = 基础能源输出 blocks.basepowergeneration = 基础能源输出
blocks.productiontime = 生产时间 blocks.productiontime = 生产时间
blocks.repairtime = 方块完全修复时间 blocks.repairtime = 建筑完全修复时间
blocks.speedincrease = 提速 blocks.speedincrease = 提速
blocks.range = 范围 blocks.range = 范围
blocks.drilltier = 可钻探矿物 blocks.drilltier = 可钻探矿物
@@ -591,8 +592,8 @@ bullet.frag = [stat] 分裂
bullet.knockback = [stat]{0}[lightgray] 击退 bullet.knockback = [stat]{0}[lightgray] 击退
bullet.freezing = [stat] 冰冻 bullet.freezing = [stat] 冰冻
bullet.tarred = [stat] 减速 bullet.tarred = [stat] 减速
bullet.multiplier = [stat]{0}[lightgray]x 弹数量 bullet.multiplier = [stat]{0}[lightgray]x 弹数量
bullet.reload = [stat]{0}[lightgray]x 装弹 bullet.reload = [stat]{0}[lightgray]x 装弹速度
unit.blocks = 方块 unit.blocks = 方块
unit.powersecond = 能量/秒 unit.powersecond = 能量/秒
@@ -617,7 +618,7 @@ category.shooting = 发射
category.optional = 可选的增强 category.optional = 可选的增强
setting.landscape.name = 锁定横屏 setting.landscape.name = 锁定横屏
setting.shadows.name = 影子 setting.shadows.name = 影子
setting.blockreplace.name = 自动推荐 setting.blockreplace.name = 自动推荐合适的建筑
setting.linear.name = 抗锯齿 setting.linear.name = 抗锯齿
setting.hints.name = 提示 setting.hints.name = 提示
setting.buildautopause.name = 自动暂停建造 setting.buildautopause.name = 自动暂停建造
@@ -632,7 +633,7 @@ setting.fpscap.name = 最大FPS
setting.fpscap.none = setting.fpscap.none =
setting.fpscap.text = {0} FPS setting.fpscap.text = {0} FPS
setting.uiscale.name = UI缩放比例[lightgray](需要重新启动)[] setting.uiscale.name = UI缩放比例[lightgray](需要重新启动)[]
setting.swapdiagonal.name = 自动铺设 setting.swapdiagonal.name = 自动斜线建造
setting.difficulty.training = 训练 setting.difficulty.training = 训练
setting.difficulty.easy = 简单 setting.difficulty.easy = 简单
setting.difficulty.normal = 普通 setting.difficulty.normal = 普通
@@ -641,18 +642,18 @@ setting.difficulty.insane = 疯狂
setting.difficulty.name = 难度: setting.difficulty.name = 难度:
setting.screenshake.name = 屏幕抖动 setting.screenshake.name = 屏幕抖动
setting.effects.name = 显示效果 setting.effects.name = 显示效果
setting.destroyedblocks.name = 显示摧毁的 setting.destroyedblocks.name = 显示摧毁的建筑
setting.conveyorpathfinding.name = 传送带放置寻路 setting.conveyorpathfinding.name = 传送带自动寻路
setting.coreselect.name = Allow Schematic Cores setting.coreselect.name = 允许蓝图包含核心
setting.sensitivity.name = 控制器灵敏度 setting.sensitivity.name = 控制器灵敏度
setting.saveinterval.name = 自动保存间隔 setting.saveinterval.name = 自动保存间隔
setting.seconds = {0} 秒 setting.seconds = {0} 秒
setting.blockselecttimeout.name = 选择超时 setting.blockselecttimeout.name = 建筑选择超时
setting.milliseconds = {0} 毫秒 setting.milliseconds = {0} 毫秒
setting.fullscreen.name = 全屏 setting.fullscreen.name = 全屏
setting.borderlesswindow.name = 无边框窗口[lightgray](可能需要重启) setting.borderlesswindow.name = 无边框窗口[lightgray](可能需要重启)
setting.fps.name = 显示 FPS 和网络延迟 setting.fps.name = 显示 FPS 和网络延迟
setting.blockselectkeys.name = 显示选择按键 setting.blockselectkeys.name = 显示建筑选择按键
setting.vsync.name = 垂直同步 setting.vsync.name = 垂直同步
setting.pixelate.name = 像素画面 [lightgray](禁用动画) setting.pixelate.name = 像素画面 [lightgray](禁用动画)
setting.minimap.name = 显示小地图 setting.minimap.name = 显示小地图
@@ -667,6 +668,7 @@ setting.savecreate.name = 自动创建存档
setting.publichost.name = 游戏公开可见 setting.publichost.name = 游戏公开可见
setting.chatopacity.name = 聊天界面不透明度 setting.chatopacity.name = 聊天界面不透明度
setting.lasersopacity.name = 能量激光不透明度 setting.lasersopacity.name = 能量激光不透明度
setting.bridgeopacity.name = 桥梁不透明度
setting.playerchat.name = 显示玩家聊天气泡 setting.playerchat.name = 显示玩家聊天气泡
public.confirm = 确定使您的游戏公开可见?\n[accent]其他人将可以加入到您的游戏。\n[lightgray]您之后可以在 设置->游戏->游戏公开可见 更改。 public.confirm = 确定使您的游戏公开可见?\n[accent]其他人将可以加入到您的游戏。\n[lightgray]您之后可以在 设置->游戏->游戏公开可见 更改。
public.beta = 请注意,测试版的游戏不能公开可见。 public.beta = 请注意,测试版的游戏不能公开可见。
@@ -697,25 +699,25 @@ keybind.schematic_flip_x.name = 水平翻转
keybind.schematic_flip_y.name = 竖直翻转 keybind.schematic_flip_y.name = 竖直翻转
keybind.category_prev.name = 上一分类 keybind.category_prev.name = 上一分类
keybind.category_next.name = 下一分类 keybind.category_next.name = 下一分类
keybind.block_select_left.name = 块选择向左 keybind.block_select_left.name = 建筑朝向向左
keybind.block_select_right.name = 块选择向右 keybind.block_select_right.name = 建筑朝向向右
keybind.block_select_up.name = 块选择向上 keybind.block_select_up.name = 建筑朝向向上
keybind.block_select_down.name = 块选择向下 keybind.block_select_down.name = 建筑朝向向下
keybind.block_select_01.name = 分类/选择 1 keybind.block_select_01.name = 分类/建筑选择 1
keybind.block_select_02.name = 分类/选择 2 keybind.block_select_02.name = 分类/建筑选择 2
keybind.block_select_03.name = 分类/选择 3 keybind.block_select_03.name = 分类/建筑选择 3
keybind.block_select_04.name = 分类/选择 4 keybind.block_select_04.name = 分类/建筑选择 4
keybind.block_select_05.name = 分类/选择 5 keybind.block_select_05.name = 分类/建筑选择 5
keybind.block_select_06.name = 分类/选择 6 keybind.block_select_06.name = 分类/建筑选择 6
keybind.block_select_07.name = 分类/选择 7 keybind.block_select_07.name = 分类/建筑选择 7
keybind.block_select_08.name = 分类/选择 8 keybind.block_select_08.name = 分类/建筑选择 8
keybind.block_select_09.name = 分类/选择 9 keybind.block_select_09.name = 分类/建筑选择 9
keybind.block_select_10.name = 分类/选择 10 keybind.block_select_10.name = 分类/建筑选择 10
keybind.fullscreen.name = 切换全屏 keybind.fullscreen.name = 切换全屏
keybind.select.name = 选择/射击 keybind.select.name = 选择/射击
keybind.diagonal_placement.name = 自动铺设 keybind.diagonal_placement.name = 斜线建造
keybind.pick.name = 选择方块 keybind.pick.name = 选择建筑
keybind.break_block.name = 破坏方块 keybind.break_block.name = 破坏建筑
keybind.deselect.name = 取消选择 keybind.deselect.name = 取消选择
keybind.shoot.name = 射击 keybind.shoot.name = 射击
keybind.zoom.name = 缩放 keybind.zoom.name = 缩放
@@ -755,7 +757,7 @@ rules.enemyCheat = 敌人(红队)无限资源
rules.unitdrops = 敌人出生点 rules.unitdrops = 敌人出生点
rules.unitbuildspeedmultiplier = 单位生产速度倍数 rules.unitbuildspeedmultiplier = 单位生产速度倍数
rules.unithealthmultiplier = 单位生命倍数 rules.unithealthmultiplier = 单位生命倍数
rules.blockhealthmultiplier = Block Health Multiplier rules.blockhealthmultiplier = 建筑生命倍数
rules.playerhealthmultiplier = 玩家生命倍数 rules.playerhealthmultiplier = 玩家生命倍数
rules.playerdamagemultiplier = 玩家伤害倍数 rules.playerdamagemultiplier = 玩家伤害倍数
rules.unitdamagemultiplier = 单位伤害倍数 rules.unitdamagemultiplier = 单位伤害倍数
@@ -824,7 +826,7 @@ mech.trident-ship.name = Trident
mech.trident-ship.weapon = 炸弹 mech.trident-ship.weapon = 炸弹
mech.glaive-ship.name = Glaive mech.glaive-ship.name = Glaive
mech.glaive-ship.weapon = 火焰机枪 mech.glaive-ship.weapon = 火焰机枪
item.corestorable = [lightgray]Storable in Core: {0} item.corestorable = [lightgray]核心可存储: {0}
item.explosiveness = [lightgray]爆炸性:{0}% item.explosiveness = [lightgray]爆炸性:{0}%
item.flammability = [lightgray]易燃性:{0}% item.flammability = [lightgray]易燃性:{0}%
item.radioactivity = [lightgray]放射性:{0}% item.radioactivity = [lightgray]放射性:{0}%
@@ -933,7 +935,7 @@ block.conveyor.name = 传送带
block.titanium-conveyor.name = 钛传送带 block.titanium-conveyor.name = 钛传送带
block.armored-conveyor.name = 装甲传送带 block.armored-conveyor.name = 装甲传送带
block.armored-conveyor.description = 运送物品,与钛传送带一样的速度,但有更强的装甲。除其他传送带,不接受任何边的输入。 block.armored-conveyor.description = 运送物品,与钛传送带一样的速度,但有更强的装甲。除其他传送带,不接受任何边的输入。
block.junction.name = 交叉 block.junction.name = 连接
block.router.name = 路由器 block.router.name = 路由器
block.distributor.name = 分配器 block.distributor.name = 分配器
block.sorter.name = 分类器 block.sorter.name = 分类器
@@ -942,6 +944,7 @@ block.message.name = 信息板
block.illuminator.name = 照明器 block.illuminator.name = 照明器
block.illuminator.description = 小型、紧凑、可配置的光源。需要能量运行。 block.illuminator.description = 小型、紧凑、可配置的光源。需要能量运行。
block.overflow-gate.name = 溢流门 block.overflow-gate.name = 溢流门
block.underflow-gate.name = 反向溢流门
block.silicon-smelter.name = 硅冶炼厂 block.silicon-smelter.name = 硅冶炼厂
block.phase-weaver.name = 相织布编织器 block.phase-weaver.name = 相织布编织器
block.pulverizer.name = 粉碎机 block.pulverizer.name = 粉碎机
@@ -978,7 +981,7 @@ block.mechanical-pump.name = 机械泵
block.item-source.name = 无限物品 block.item-source.name = 无限物品
block.item-void.name = 物品黑洞 block.item-void.name = 物品黑洞
block.liquid-source.name = 无限液体 block.liquid-source.name = 无限液体
block.liquid-void.name = Liquid Void block.liquid-void.name = 液体黑洞
block.power-void.name = 能源黑洞 block.power-void.name = 能源黑洞
block.power-source.name = 无限能源 block.power-source.name = 无限能源
block.unloader.name = 装卸器 block.unloader.name = 装卸器
@@ -1057,14 +1060,14 @@ unit.revenant.name = 亡魂
unit.eruptor.name = 暴君 unit.eruptor.name = 暴君
unit.chaos-array.name = 混沌者 unit.chaos-array.name = 混沌者
unit.eradicator.name = 根除者 unit.eradicator.name = 根除者
unit.lich.name = 尸鬼 unit.lich.name = 巫妖
unit.reaper.name = 死神 unit.reaper.name = 死神
tutorial.next = [lightgray]<点击以继续> tutorial.next = [lightgray]<点击以继续>
tutorial.intro = 您已进入[scarlet] Mindustry 教程[]。[]\n使用[accent][[WASD][]键移动主角和视角。\n[accent]按住[[Ctrl]并转动鼠标滚轮[]缩放视野。\n让我们从[accent]采集铜矿[]开始。先移动到铜矿旁边,然后点按矿脉附近散落的矿物。\n\n[accent]{0}/{1} 铜 tutorial.intro = 您已进入[scarlet] Mindustry 教程[]。[]\n使用[accent][[WASD][]键移动主角和视角。\n[accent]按住[[Ctrl]并转动鼠标滚轮[]缩放视野。\n让我们从[accent]采集铜矿[]开始。先移动到铜矿旁边,然后点按矿脉附近散落的矿物。\n\n[accent]{0}/{1} 铜
tutorial.intro.mobile = 您已进入[scarlet] Mindustry 教程[]。\n在屏幕上滑动来继续。\n[accent]双指捏合[] 来缩小和放大。\n让我们从[accent]采集铜矿[]开始。先移动到铜矿旁边,然后点按矿脉附近散落的矿物。\n\n[accent]铜 {0}/{1} tutorial.intro.mobile = 您已进入[scarlet] Mindustry 教程[]。\n在屏幕上滑动来继续。\n[accent]双指捏合[] 来缩小和放大。\n让我们从[accent]采集铜矿[]开始。先移动到铜矿旁边,然后点按矿脉附近散落的矿物。\n\n[accent]铜 {0}/{1}
tutorial.drill = 手动采矿效率不高。\n[accent]钻头[]可以自动采矿。\n让我们在在铜矿上放一个。\n点击右下角的钻头菜单。\n选择[accent]机械钻头[]。\n单击将其放置在铜矿上。\n[accent]右键单击[]来停止。 tutorial.drill = 手动采矿效率不高。\n[accent]钻头[]可以自动采矿。\n让我们在在铜矿上放一个。\n点击右下角的钻头菜单。\n选择[accent]机械钻头[]。\n单击将其放置在铜矿上。\n[accent]右键单击[]来停止。
tutorial.drill.mobile = 手动采矿效率不高。\n[accent]钻头[]可以自动采矿。\n点右下角的钻头菜单。\n选择[accent]机械钻头[]。\n点一下将其放在铜矿上点[accent]对号[]来确定。\n点[accent]叉号[]来取消。 tutorial.drill.mobile = 手动采矿效率不高。\n[accent]钻头[]可以自动采矿。\n点右下角的钻头菜单。\n选择[accent]机械钻头[]。\n点一下将其放在铜矿上点[accent]对号[]来确定。\n点[accent]叉号[]来取消。
tutorial.blockinfo = 每种方块都有其独特的数据。每个钻头只能开采部分矿石。\n若要查看块的信息和统计信息,[accent]在菜单中点击问号。[]\n\n[accent]现在查看机械钻头的数据吧。[] tutorial.blockinfo = 每种钻头都有其独特的数据。每个钻头只能开采部分矿石。\n若要查看建筑的详细信息,[accent]在菜单中点击问号。[]\n\n[accent]现在查看机械钻头的数据吧。[]
tutorial.conveyor = [accent]传送带[]可以把物资传送到核心。\n请在钻头到核心间建造一条传送带。 tutorial.conveyor = [accent]传送带[]可以把物资传送到核心。\n请在钻头到核心间建造一条传送带。
tutorial.conveyor.mobile = [accent]传送带[]可以把物资传送到核心。\n请在钻头到核心间建造一条传送带。\n[accent]长按数秒[]并向一个方向拖动来直线放置。\n\n[accent]{0}/{1} 条传送带\n[accent]0/1 物品 tutorial.conveyor.mobile = [accent]传送带[]可以把物资传送到核心。\n请在钻头到核心间建造一条传送带。\n[accent]长按数秒[]并向一个方向拖动来直线放置。\n\n[accent]{0}/{1} 条传送带\n[accent]0/1 物品
tutorial.turret = 必须建造防御建筑来击退[lightgray]敌人[]。\n请在核心附近造一个双管炮。 tutorial.turret = 必须建造防御建筑来击退[lightgray]敌人[]。\n请在核心附近造一个双管炮。
@@ -1073,20 +1076,20 @@ tutorial.pause = 在战斗中,您可以[accent]暂停游戏[]。\n暂停时您
tutorial.pause.mobile = 在战斗中,您可以[accent]暂停游戏[]。\n暂停时您可以规划建筑物。\n\n[accent]点击左上角的按钮以暂停。 tutorial.pause.mobile = 在战斗中,您可以[accent]暂停游戏[]。\n暂停时您可以规划建筑物。\n\n[accent]点击左上角的按钮以暂停。
tutorial.unpause = 现在再次按空格以继续。 tutorial.unpause = 现在再次按空格以继续。
tutorial.unpause.mobile = 现在再次点按以继续。 tutorial.unpause.mobile = 现在再次点按以继续。
tutorial.breaking = 方块经常需要拆除。\n[accent]按住鼠标右键[]来拆除选中的方块。[]\n\n[accent]使用范围拆除来拆除核心左侧的废墙。 tutorial.breaking = 建筑经常需要拆除。\n[accent]按住鼠标右键[]来拆除选中的建筑。[]\n\n[accent]使用范围拆除来拆除核心左侧的废墙。
tutorial.breaking.mobile = 方块经常需要拆除。\n[accent]选择拆除模式[],点击方块以拆除。\n[accent]长按几秒[]并拖动来范围拆除。\n点击对号来确定。\n\n[accent]使用范围拆除来拆除核心左侧的废墙。 tutorial.breaking.mobile = 建筑经常需要拆除。\n[accent]选择拆除模式[],点击建筑以拆除。\n[accent]长按几秒[]并拖动来范围拆除。\n点击对号来确定。\n\n[accent]使用范围拆除来拆除核心左侧的废墙。
tutorial.withdraw = 有时,从方块中取出物品是必要的。\n[accent]点击物品的方块[],然后[accent]点击在方框中的物品[]。\n可以通过[accent]点击或长按[]来取出物品。\n\n[accent]从核心中取出一些铜[]。 tutorial.withdraw = 有时,从建筑中取出物品是必要的。\n[accent]点击包含物品的建筑[],然后[accent]点击在方框中的物品[]。\n可以通过[accent]点击或长按[]来取出物品。\n\n[accent]从核心中取出一些铜[]。
tutorial.deposit = 将物品从机甲拖向方块来放下物品。\n\n[accent]将铜放回核心[]。 tutorial.deposit = 将物品从机甲拖向建筑来放下物品。\n\n[accent]将铜放回核心[]。
tutorial.waves = [lightgray]敌人[]来了。\n\n保护核心防御两波攻击。造更多的炮塔。[accent]点击[]以射击。\n建造更多的炮塔和钻头并采更多的矿。 tutorial.waves = [lightgray]敌人[]来了。\n\n保护核心防御两波攻击。造更多的炮塔。[accent]点击[]以射击。\n建造更多的炮塔和钻头并采更多的矿。
tutorial.waves.mobile = [lightgray]敌人[]来了。\n\n保护核心防御两波攻击。造更多的炮塔。你的机甲将对敌人自动开火。\n建造更多的炮塔和钻头并采更多的矿。 tutorial.waves.mobile = [lightgray]敌人[]来了。\n\n保护核心防御两波攻击。造更多的炮塔。你的机甲将对敌人自动开火。\n建造更多的炮塔和钻头并采更多的矿。
tutorial.launch = 进入特定波次后,你可以[accent]发射核心(起飞)[][accent]带走核心中的所有资源[]并抛下所有的建筑。\n装运的资源可用于研究科技。\n\n[accent]点击发射按钮。 tutorial.launch = 进入特定波次后,你可以[accent]发射核心(起飞)[][accent]带走核心中的所有资源[]并抛下所有的建筑。\n装运的资源可用于研究科技。\n\n[accent]点击发射按钮。
item.copper.description = 最基本的的结构材料。在各种类型的方块中被广泛使用。 item.copper.description = 最基本的的建筑材料。在各种类型的建筑中被广泛使用。
item.lead.description = 一种基本的电力材料。广泛用于电子设备和液体输送模块。 item.lead.description = 一种基本的电力材料。广泛用于电子设备和液体输送模块。
item.metaglass.description = 一种致密坚硬的复合玻璃。广泛用于液体输送和存储。 item.metaglass.description = 一种致密坚硬的复合玻璃。广泛用于液体输送和存储。
item.graphite.description = 矿化碳,用于弹药和电路绝缘 item.graphite.description = 一种高密度的碳材料,用于弹药和电器元件
item.sand.description = 一种常见的材料,广泛用于冶炼,包括制作合金和助熔剂。 item.sand.description = 一种常见的材料,广泛用于冶炼,包括制作合金和助熔剂。
item.coal.description = 植物化石,常见且容易获得,常用作燃料或其他资源的生产。 item.coal.description = 在农耕文明前就形成的植物化石,常见且容易获得,常用作燃料或其他资源的生产。
item.titanium.description = 一种罕见的超轻金属,被广泛运用于液体运输、钻头和飞机。 item.titanium.description = 一种罕见的超轻金属,被广泛运用于液体运输、钻头和飞机。
item.thorium.description = 一种致密的放射性金属,用作结构支撑和核燃料。 item.thorium.description = 一种致密的放射性金属,用作结构支撑和核燃料。
item.scrap.description = 一种废弃的建筑物及废弃单位的残骸,富含多种金属元素。 item.scrap.description = 一种废弃的建筑物及废弃单位的残骸,富含多种金属元素。
@@ -1110,7 +1113,7 @@ mech.javelin-ship.description = 一艘一击即退的攻击船。虽然最初很
mech.trident-ship.description = 为建造和摧毁敌人防御工事而建造的重型轰炸机。有相当好的装甲。 mech.trident-ship.description = 为建造和摧毁敌人防御工事而建造的重型轰炸机。有相当好的装甲。
mech.glaive-ship.description = 一种大型的装甲厚重的武装直升机。配备火焰机枪。有优秀的加速能力和最快的速度。 mech.glaive-ship.description = 一种大型的装甲厚重的武装直升机。配备火焰机枪。有优秀的加速能力和最快的速度。
unit.draug.description = 一种原始的采矿机。生产成本低,消耗品。在附近自动开采铜和铅。将开采的资源输送到最近的核心。 unit.draug.description = 一种原始的采矿机。生产成本低,消耗品。在附近自动开采铜和铅。将开采的资源输送到最近的核心。
unit.spirit.description = 一种改进的德鲁格无人机,设计用于维修而不是采矿。自动修复该区域中任何损坏的 unit.spirit.description = 采矿机的改进版本,用于维修而不是采矿。自动修复该区域中任何损坏的建筑
unit.phantom.description = 一种先进的无人机。跟随玩家并协助建造。 unit.phantom.description = 一种先进的无人机。跟随玩家并协助建造。
unit.dagger.description = 一种最基本的地面机甲。生产成本低。集群使用时比较有用。 unit.dagger.description = 一种最基本的地面机甲。生产成本低。集群使用时比较有用。
unit.crawler.description = 一种地面装置,由一个框架和绑在上面的烈性炸药组成。不是特别耐用。与敌人接触后爆炸。 unit.crawler.description = 一种地面装置,由一个框架和绑在上面的烈性炸药组成。不是特别耐用。与敌人接触后爆炸。
@@ -1120,14 +1123,14 @@ unit.eruptor.description = 一种用来拆除建筑物的重型机甲。在敌
unit.wraith.description = 一种快速、一击即退的拦截器机甲。目标是发电机。 unit.wraith.description = 一种快速、一击即退的拦截器机甲。目标是发电机。
unit.ghoul.description = 一种重型地毯式轰炸机。瞄准关键的基础设施来击溃敌人的基地。 unit.ghoul.description = 一种重型地毯式轰炸机。瞄准关键的基础设施来击溃敌人的基地。
unit.revenant.description = 一种发射导弹的重型飞行机甲。 unit.revenant.description = 一种发射导弹的重型飞行机甲。
block.message.description = 存一条息。用于盟友间的交流。 block.message.description = 存一条文字信息。用于队友之间进行交流。
block.graphite-press.description = 将煤块压缩成纯石墨片材料。 block.graphite-press.description = 将煤块压缩成纯石墨片材料。
block.multi-press.description = 石墨压缩机的升级版。利用水和电力快速高效地处理煤炭。 block.multi-press.description = 石墨压缩机的升级版。利用水和电力快速高效地处理煤炭。
block.silicon-smelter.description = 用高纯度的焦炭来加工沙子以生产硅。 block.silicon-smelter.description = 用高纯度的焦炭来加工沙子以生产硅。
block.kiln.description = 将铅和沙子熔炼成钢化玻璃,需要少量电力。 block.kiln.description = 将铅和沙子熔炼成钢化玻璃,需要少量电力。
block.plastanium-compressor.description = 用石油和钛生产塑钢。 block.plastanium-compressor.description = 用石油和钛生产塑钢。
block.phase-weaver.description = 用放射性钍和大量沙子生产相织物。 block.phase-weaver.description = 用放射性钍和大量沙子生产相织物。
block.alloy-smelter.description = 用钛、铅、硅和铜生产浪合金。 block.alloy-smelter.description = 用钛、铅、硅和铜生产浪合金。
block.cryofluidmixer.description = 将水和细的钛粉混成冷却液。钍反应堆的必备之物。 block.cryofluidmixer.description = 将水和细的钛粉混成冷却液。钍反应堆的必备之物。
block.blast-mixer.description = 用油料将硫转化为不易燃但更具爆炸性的爆炸化合物。 block.blast-mixer.description = 用油料将硫转化为不易燃但更具爆炸性的爆炸化合物。
block.pyratite-mixer.description = 将煤、铅和沙子混合成高度易燃的硫。 block.pyratite-mixer.description = 将煤、铅和沙子混合成高度易燃的硫。
@@ -1142,56 +1145,57 @@ block.power-source.description = 无限输出能量。仅限沙盒。
block.item-source.description = 无限输出物品。仅限沙盒。 block.item-source.description = 无限输出物品。仅限沙盒。
block.item-void.description = 销毁输入的所有物品。仅限沙盒。 block.item-void.description = 销毁输入的所有物品。仅限沙盒。
block.liquid-source.description = 无限输出液体。仅限沙盒。 block.liquid-source.description = 无限输出液体。仅限沙盒。
block.liquid-void.description = Removes any liquids. Sandbox only. block.liquid-void.description = 销毁输入的所有液体。仅限沙盒
block.copper-wall.description = 廉价的防御方块。\n适合在前几个波次中保护核心和炮塔。 block.copper-wall.description = 廉价的防御建筑。\n适合在前几个波次中保护核心和炮塔。
block.copper-wall-large.description = 廉价的防御方块。\n适合在前几个波次中保护核心和炮塔。\n占多个方格。 block.copper-wall-large.description = 廉价的防御建筑。\n适合在前几个波次中保护核心和炮塔。\n占多个方格。
block.titanium-wall.description = 中等强度的防御方块。\n提供中等强度的防御以抵御敌人。 block.titanium-wall.description = 中等强度的防御建筑。\n提供中等强度的防御以抵御敌人。
block.titanium-wall-large.description = 中等强度的防御方块。\n提供中等强度的防御以防敌人攻击。\n占多个方格。 block.titanium-wall-large.description = 中等强度的防御建筑。\n提供中等强度的防御以防敌人攻击。\n占多个方格。
block.plastanium-wall.description = 一种特殊的防御方块,能吸收电弧、自动与能量节点连接。 block.plastanium-wall.description = 一种特殊的防御建筑,能吸收电弧、自动与能量节点连接。
block.plastanium-wall-large.description = 一种特殊的防御方块,能吸收电弧、自动与能量节点连接。\n占多个方格。 block.plastanium-wall-large.description = 一种特殊的防御建筑,能吸收电弧、自动与能量节点连接。\n占多个方格。
block.thorium-wall.description = 强大的防御方块。\n可以很好的防御敌人。 block.thorium-wall.description = 强大的防御建筑。\n可以很好的防御敌人。
block.thorium-wall-large.description = 强大的防御方块。\n很好地防御敌人。\n占多个方格。 block.thorium-wall-large.description = 强大的防御建筑。\n很好地防御敌人。\n占多个方格。
block.phase-wall.description = 没有钍墙那样坚固,但是它可以使不太强的弹药发生偏转。 block.phase-wall.description = 没有钍墙那样坚固,但是它可以使不太强的弹药发生偏转。
block.phase-wall-large.description = 没有钍墙那样坚固,但是它可以使不太强的弹药发生偏转。\n占多个方格。 block.phase-wall-large.description = 没有钍墙那样坚固,但是它可以使不太强的弹药发生偏转。\n占多个方格。
block.surge-wall.description = 强大的防御方块。\n有很小的机会向攻击者发射闪电。 block.surge-wall.description = 强大的防御建筑。\n被攻击时有很小的机会向攻击者发射闪电。
block.surge-wall-large.description = 强大的防御方块。\n有很小的机会向攻击者发射闪电。\n占多个方格。 block.surge-wall-large.description = 强大的防御建筑。\n被攻击时有很小的机会向攻击者发射闪电。\n占多个方格。
block.door.description = 一扇门。点按切换它的打开/关闭状态。 block.door.description = 一扇门。点按切换它的打开/关闭状态。
block.door-large.description = 一扇大门。点按切换它的打开/关闭状态。\n占多个方格。 block.door-large.description = 一扇大门。点按切换它的打开/关闭状态。\n占多个方格。
block.mender.description = 定期修理附近的方块,使防御系统在波次之间得到修复。\n可选使用硅来提高修复范围和修复效率。 block.mender.description = 定期修理附近的建筑,使防御系统在波次之间得到修复。\n可选使用硅来提高修复范围和修复效率。
block.mend-projector.description = 修理者的升级版,定期修复附近的建筑物。 block.mend-projector.description = 修理者的升级版,定期修复附近的建筑物。
block.overdrive-projector.description = 提高附近建筑物的速度,如钻头和传送带。 block.overdrive-projector.description = 提高附近建筑物的速度,如钻头和传送带。
block.force-projector.description = 在自身周围创建一个六角形力场,使里面的建筑物和单位免受伤害。\n持续承受高伤害会导致过热可以使用冷却液降温。相织物可用于增加屏障大小。 block.force-projector.description = 在自身周围创建一个六角形力场,使里面的建筑物和单位免受伤害。\n持续承受高伤害会导致过热可以使用冷却液降温。相织物可用于增加屏障大小。
block.shock-mine.description = 伤害踩到它的敌人。敌人几乎看不到它。 block.shock-mine.description = 伤害踩到它的敌人。敌人几乎看不到它。
block.conveyor.description = 初级物传送带。将物品向前输送并在可能时运入建筑。可旋转方向。 block.conveyor.description = 初级物传送带。将物品向前输送并在可能时运入建筑。可旋转方向。
block.titanium-conveyor.description = 高级物传送带。运送物品的速度于初级传送带。 block.titanium-conveyor.description = 高级物传送带。运送物品的速度于初级传送带。
block.junction.description = 两条传送带的交叉桥连接。适用于两条不同方向的传送带要分别将不同的物品运送到不同的位置 block.junction.description = 两条交叉传送带的桥梁。用于连接两条不同的传输线路使其互不影响
block.bridge-conveyor.description = 先进的物品运输方块。允许跨越任意地形或建筑物运输物品最多跨越3格。 block.bridge-conveyor.description = 先进的物品运输方块。允许跨越任意地形或建筑物运输物品最多跨越3格。
block.phase-conveyor.description = 先进的传送带,使用电力将物品传送到距离几个块的相位传送带上。 block.phase-conveyor.description = 先进的传送带,使用电力将物品传送到距离几个块的相位传送带上。
block.sorter.description = 对物品进行分类,如果物品与所选种类相同,则允许其通过。否则,物品将从左边和右边输出。 block.sorter.description = 对物品进行分类,如果物品与所选种类相同,则允许其通过。否则,物品将从左边和右边输出。
block.inverted-sorter.description = 分类器一样分类物品,但所选物品输出到左边和右边 block.inverted-sorter.description = 分类器一样处理物品,但却是向两侧输出选定的物品
block.router.description = 从一个方向接受物品并将它们平均输出到其他3个方向。可以将材料分成多份。 block.router.description = 从一个方向接受物品并将它们平均输出到其他3个方向。可以将材料分成多份\n\n[scarlet]永远不要把它与生产建筑相连,因为它会被产出的产品阻塞[]
block.distributor.description = 改进的路由器可将物品输出到周围的最多7个其他方向。 block.distributor.description = 大型路由器可将物品输出到周围的最多7个其他方向。
block.overflow-gate.description = 仅在前路被阻塞时向左和右输出。 block.overflow-gate.description = 当前方被阻塞时才会向左和右输出,用于处理多余的物品
block.mass-driver.description = 终极传送带,收集若干物品后将其射到远处的另一个质量驱动器 block.underflow-gate.description = 与溢流门相反。 当左右均堵塞时才向前方运输
block.mechanical-pump.description = 一种廉价泵,输出速度慢,但无需能量 block.mass-driver.description = 终极物品传输器,收集若干物品后将其射到远处的另一个质量驱动器
block.mechanical-pump.description = 一种廉价液体泵,输出速度慢,但无需能量。
block.rotary-pump.description = 先进液泵。泵送更多液体,但需要能量。 block.rotary-pump.description = 先进液泵。泵送更多液体,但需要能量。
block.thermal-pump.description = 终级液泵。 block.thermal-pump.description = 终级液泵。
block.conduit.description = 基本液体传输管道。像传送带一样工作,但仅适用于液体。用于从泵或其他导管中提取液体。 block.conduit.description = 基本液体传输管道。像传送带一样工作,但仅适用于液体。用于从泵或其他导管中提取液体。
block.pulse-conduit.description = 高级液体传输管道。比普通导管更快地输送液体且能储存更多液体。 block.pulse-conduit.description = 高级液体传输管道。比普通导管更快地输送液体且能储存更多液体。
block.plated-conduit.description = 转移液体的速度与脉冲导管相同,但护甲更强。两侧只接受通过导管传入液体。\n更少泄漏 block.plated-conduit.description = 转移液体的速度与脉冲导管相同,但护甲更强。两侧只接受通过导管传入液体。\n发生泄漏时泄漏较少
block.liquid-router.description = 接受一个方向的液体并将它们平均输出到其他3个方向。同时可以储存一定量的液体。用于将液体从一个源分往多个目标。 block.liquid-router.description = 接受一个方向的液体并将它们平均输出到其他3个方向。同时可以储存一定量的液体。用于将液体从一个源分往多个目标。
block.liquid-tank.description = 存储大量液体,可在材料需求不恒定作为缓冲区,或作为供给冷却液体的保障设施。 block.liquid-tank.description = 存储大量液体,可在材料需求不恒定作为缓冲区,或作为供给冷却液体的保障设施。
block.liquid-junction.description = 两条管道的交叉桥连接。适用两条不同方向的导管要将不同的液体输送到不同的位置 block.liquid-junction.description = 两条交叉管道的桥梁。适用连接两条不同方向的导管线路
block.bridge-conduit.description = 先进的液体传输方块。可以跨越任何地形或建筑物最多跨越3格来传输液体。 block.bridge-conduit.description = 先进的液体传输建筑。可以跨越任何地形或建筑物最多跨越3格来传输液体。
block.phase-conduit.description = 先进的液体传输方块。使用电力将液体传送到多个块上的连接管道。 block.phase-conduit.description = 先进的液体传输建筑。使用电力将液体传送到多个块上的连接管道。
block.power-node.description = 将电源传输到连接的节点上。节点将接收来自任何方块的能量或向任何方块供给能量。 block.power-node.description = 将电源传输到连接的节点上。节点将接收来自任何方块的能量或向任何方块供给能量。
block.power-node-large.description = 更大范围、更多连接点的高级能量节点。 block.power-node-large.description = 更大范围、更多连接点的高级能量节点。
block.surge-tower.description = 连接数低但范围很远的能量节点。 block.surge-tower.description = 连接数低但范围很远的能量节点。
block.diode.description = 此方块上的电能只能单向流动,仅当对方的储能更低时流动 block.diode.description = 此方块上的电能只能单向流动,仅当另一侧的电池储能更低时输送电力
block.battery.description = 存储能量作为缓冲,在能源亏空时提供。 block.battery.description = 存储能量作为缓冲,在发电量不足时提供保障
block.battery-large.description = 比普通电池容量更大。 block.battery-large.description = 比普通电池容量更大。
block.combustion-generator.description = 燃烧煤等材料发电。 block.combustion-generator.description = 燃烧煤等材料发电。
block.thermal-generator.description = 放置在炽热的地发电。 block.thermal-generator.description = 放置在炽热的地形上能够发电。
block.turbine-generator.description = 先进的火力发电机,效率更高,但需要水来产生蒸汽。 block.turbine-generator.description = 先进的火力发电机,效率更高,但需要水来产生蒸汽。
block.differential-generator.description = 利用低温流体与燃烧的硫之间的温差产生大量能量。 block.differential-generator.description = 利用低温流体与燃烧的硫之间的温差产生大量能量。
block.rtg-generator.description = 一种简单可靠的发电机。利用放射性化合物的衰变产生的热量,以缓慢的速度产生能量。 block.rtg-generator.description = 一种简单可靠的发电机。利用放射性化合物的衰变产生的热量,以缓慢的速度产生能量。
@@ -1206,9 +1210,9 @@ block.blast-drill.description = 终极钻头,需要大量能量。
block.water-extractor.description = 从地下提取水。当附近没有水源时使用它。 block.water-extractor.description = 从地下提取水。当附近没有水源时使用它。
block.cultivator.description = 将微小的孢子培养成工业用的孢子荚。 block.cultivator.description = 将微小的孢子培养成工业用的孢子荚。
block.oil-extractor.description = 使用大量能量、沙子和水提炼石油。 block.oil-extractor.description = 使用大量能量、沙子和水提炼石油。
block.core-shard.description = 初代核心。一旦被摧毁,与该地区的所有连接都将断开。不要让它被摧毁。 block.core-shard.description = 小型核心。一旦被摧毁,与该地区的所有连接都将断开。不要让它被摧毁。
block.core-foundation.description = 二代核心。血量更高。可以存储更多资源。 block.core-foundation.description = 中型核心。血量更高。可以存储更多资源。
block.core-nucleus.description = 三代核心,也是最新一代,血量非常高。能存储大量资源。 block.core-nucleus.description = 大型核心,也是最强大的,血量非常高。能存储大量资源。
block.vault.description = 存储大量物品。当存在非恒定的材料需求时,使用它来创建缓冲区。[lightgray]卸载器[]可从仓库中提取物品。 block.vault.description = 存储大量物品。当存在非恒定的材料需求时,使用它来创建缓冲区。[lightgray]卸载器[]可从仓库中提取物品。
block.container.description = 存储少量物品。当存在非恒定的材料需求时,使用它来创建缓冲区。[lightgray]卸载器[]可从容器中提取物品。 block.container.description = 存储少量物品。当存在非恒定的材料需求时,使用它来创建缓冲区。[lightgray]卸载器[]可从容器中提取物品。
block.unloader.description = 将物品从容器、仓库或你的核心中提取到传送带或直接提取到相邻的方块。点击卸载器本身更改所要卸载的物品类型。 block.unloader.description = 将物品从容器、仓库或你的核心中提取到传送带或直接提取到相邻的方块。点击卸载器本身更改所要卸载的物品类型。
@@ -1218,9 +1222,9 @@ block.duo.description = 小而便宜的炮塔,对地很有效。
block.scatter.description = 基本型防空炮塔。向空中敌人喷出一团铅或废料。 block.scatter.description = 基本型防空炮塔。向空中敌人喷出一团铅或废料。
block.scorch.description = 小型炮塔,点燃任何靠近它的地面敌人。近距离非常有效。 block.scorch.description = 小型炮塔,点燃任何靠近它的地面敌人。近距离非常有效。
block.hail.description = 小型远程炮台。 block.hail.description = 小型远程炮台。
block.wave.description = 中型快速炮塔,射出液体泡泡。有液体输入时自动灭火。 block.wave.description = 中型快速炮塔,射出液体泡泡。使用水或者冷却液时能够自动灭火。
block.lancer.description = 中型对地炮塔。会充能并发射强力的的能量束。 block.lancer.description = 中型对地炮塔。会充能并发射强力的的能量束。
block.arc.description = 小型炮塔,发射电弧。 block.arc.description = 小型炮塔,发射电弧。电弧无法穿过塑钢墙。
block.swarmer.description = 中型炮塔,对空对地,发射跟踪爆炸导弹。 block.swarmer.description = 中型炮塔,对空对地,发射跟踪爆炸导弹。
block.salvo.description = 双管炮的升级版。中型,快速射出一串子弹。 block.salvo.description = 双管炮的升级版。中型,快速射出一串子弹。
block.fuse.description = 大型近程炮塔,发射三道刺穿敌人的短程光束。 block.fuse.description = 大型近程炮塔,发射三道刺穿敌人的短程光束。
@@ -1228,7 +1232,7 @@ block.ripple.description = 大型远程炮台,非常强力,向远处的敌
block.cyclone.description = 大型炮塔,对空对地,发射在敌人周围引爆的爆炸物。 block.cyclone.description = 大型炮塔,对空对地,发射在敌人周围引爆的爆炸物。
block.spectre.description = 超大型炮塔,对空对地,一次射出两颗强大的穿甲弹药。 block.spectre.description = 超大型炮塔,对空对地,一次射出两颗强大的穿甲弹药。
block.meltdown.description = 超大型激光炮塔,充能之后持续发射光束,需要冷却剂。 block.meltdown.description = 超大型激光炮塔,充能之后持续发射光束,需要冷却剂。
block.command-center.description = 在地图上向联盟单位发出移动命令。\n使部队巡逻、攻击一个敌人核心,或者撤退到核心/工厂。当没有敌人核心时,得到攻击命令的部队默认执行巡逻 block.command-center.description = 在地图上向联盟单位发出移动命令。\n使部队攻击一个敌人核心或者撤退到核心/工厂或者集合。当没有敌人核心时,得到攻击命令的部队默认向最近的敌人出现的地方集结
block.draug-factory.description = 生产德鲁格釆矿机。 block.draug-factory.description = 生产德鲁格釆矿机。
block.spirit-factory.description = 生产幽灵修理机。 block.spirit-factory.description = 生产幽灵修理机。
block.phantom-factory.description = 生产幻影建造机。 block.phantom-factory.description = 生产幻影建造机。

View File

@@ -104,6 +104,7 @@ mods.none = [lightgray]找不到模組!
mods.guide = 模組指南 mods.guide = 模組指南
mods.report = 回報錯誤 mods.report = 回報錯誤
mods.openfolder = 開啟模組資料夾 mods.openfolder = 開啟模組資料夾
mod.display = [gray]模組:[orange]{0}
mod.enabled = [lightgray]已啟用 mod.enabled = [lightgray]已啟用
mod.disabled = [scarlet]已禁用 mod.disabled = [scarlet]已禁用
mod.disable = 禁用 mod.disable = 禁用
@@ -251,7 +252,8 @@ copylink = 複製連結
back = 返回 back = 返回
data.export = 匯出數據 data.export = 匯出數據
data.import = 匯入數據 data.import = 匯入數據
data.exported = 數據已匯出. data.openfolder = 開啟檔案資料夾
data.exported = 數據已匯出。
data.invalid = 這不是有效的遊戲資料。 data.invalid = 這不是有效的遊戲資料。
data.import.confirm = 導入外部數據將覆蓋您當前[scarlet]所有的[]遊戲數據,\n[accent]這個動作不能撤銷![]\n\n匯入數據後您的遊戲將立即退出。 data.import.confirm = 導入外部數據將覆蓋您當前[scarlet]所有的[]遊戲數據,\n[accent]這個動作不能撤銷![]\n\n匯入數據後您的遊戲將立即退出。
classic.export = 匯出 Classic 數據 classic.export = 匯出 Classic 數據
@@ -530,7 +532,9 @@ error.title = [crimson]發生錯誤
error.crashtitle = 發生錯誤 error.crashtitle = 發生錯誤
blocks.input = 輸入 blocks.input = 輸入
blocks.output = 輸出 blocks.output = 輸出
blocks.booster = 加速器 blocks.booster = 強化
blocks.tiles = 需求方塊
blocks.affinities = 親和方塊
block.unknown = [lightgray] block.unknown = [lightgray]
blocks.powercapacity = 蓄電量 blocks.powercapacity = 蓄電量
blocks.powershot = 能量/射擊 blocks.powershot = 能量/射擊
@@ -665,8 +669,10 @@ setting.mutesound.name = 靜音
setting.crashreport.name = 發送匿名崩潰報告 setting.crashreport.name = 發送匿名崩潰報告
setting.savecreate.name = 自動建立存檔 setting.savecreate.name = 自動建立存檔
setting.publichost.name = 公開遊戲可見度 setting.publichost.name = 公開遊戲可見度
setting.playerlimit.name = 玩家數限制
setting.chatopacity.name = 聊天框不透明度 setting.chatopacity.name = 聊天框不透明度
setting.lasersopacity.name = 激光不透明度 setting.lasersopacity.name = 激光不透明度
setting.bridgeopacity.name = 橋透明度
setting.playerchat.name = 在遊戲中顯示聊天框 setting.playerchat.name = 在遊戲中顯示聊天框
public.confirm = 您想公開遊戲嗎?\n[accent]任何人都可以加入您的遊戲。\n[lightgray]以後可以在“設置”->“遊戲”->“公開遊戲可見度”中進行更改。 public.confirm = 您想公開遊戲嗎?\n[accent]任何人都可以加入您的遊戲。\n[lightgray]以後可以在“設置”->“遊戲”->“公開遊戲可見度”中進行更改。
public.beta = 請注意該遊戲的Beta版本無法公開遊戲大廳。 public.beta = 請注意該遊戲的Beta版本無法公開遊戲大廳。
@@ -942,6 +948,7 @@ block.message.name = 訊息板
block.illuminator.name = 照明燈 block.illuminator.name = 照明燈
block.illuminator.description = 小、緊湊而且可調整的光源。需要能源來運作。 block.illuminator.description = 小、緊湊而且可調整的光源。需要能源來運作。
block.overflow-gate.name = 溢流器 block.overflow-gate.name = 溢流器
block.underflow-gate.name = 反向溢流器
block.silicon-smelter.name = 煉矽廠 block.silicon-smelter.name = 煉矽廠
block.phase-weaver.name = 相織布編織器 block.phase-weaver.name = 相織布編織器
block.pulverizer.name = 粉碎機 block.pulverizer.name = 粉碎機
@@ -978,7 +985,7 @@ block.mechanical-pump.name = 機械泵
block.item-source.name = 物品源 block.item-source.name = 物品源
block.item-void.name = 物品虛空 block.item-void.name = 物品虛空
block.liquid-source.name = 液體源 block.liquid-source.name = 液體源
block.liquid-void.name = Liquid Void block.liquid-void.name = 液體虛空
block.power-void.name = 能量虛空 block.power-void.name = 能量虛空
block.power-source.name = 無限能量源 block.power-source.name = 無限能量源
block.unloader.name = 裝卸器 block.unloader.name = 裝卸器
@@ -1078,7 +1085,7 @@ tutorial.breaking.mobile = 方塊經常需要被拆除。\n[accent]選擇拆除
tutorial.withdraw = 在某些情況下,直接從方塊中取出物品是必要的。\n[accent]點擊有物品的方塊[],然後[accent]點擊在方框中的物品[]以將其取出。\n可以通過[accent]點擊或長按[]來取出物品。\n\n[accent]從核心中取出一些銅。[] tutorial.withdraw = 在某些情況下,直接從方塊中取出物品是必要的。\n[accent]點擊有物品的方塊[],然後[accent]點擊在方框中的物品[]以將其取出。\n可以通過[accent]點擊或長按[]來取出物品。\n\n[accent]從核心中取出一些銅。[]
tutorial.deposit = 通過將物品從船上拖到目標方塊,將物品放入方塊中。\n\n[accent]將您的銅放到核心中。[] tutorial.deposit = 通過將物品從船上拖到目標方塊,將物品放入方塊中。\n\n[accent]將您的銅放到核心中。[]
tutorial.waves = [lightgray]敵人[]來臨。\n\n保護核心抵抗兩波攻擊。\n建造更多的砲塔和鑽頭。開採更多的銅。 tutorial.waves = [lightgray]敵人[]來臨。\n\n保護核心抵抗兩波攻擊。\n建造更多的砲塔和鑽頭。開採更多的銅。
tutorial.waves.mobile = The[lightgray] enemy[] approaches.\n\nDefend the core for 2 waves. Your ship will automatically fire at enemies.\nBuild more turrets and drills. Mine more copper. tutorial.waves.mobile = [lightgray]敵人[]來臨。\n\n保護核心抵抗兩波攻擊。您的飛船會自動向敵人開火。\n建造更多的砲塔和鑽頭。開採更多的銅。
tutorial.launch = 一旦您達到特定的波數, 您就可以[accent] 發射核心[],放棄防禦並[accent]獲取核心中的所有資源。[]\n這些資源可以用於研究新科技。\n\n[accent]按下發射按鈕。 tutorial.launch = 一旦您達到特定的波數, 您就可以[accent] 發射核心[],放棄防禦並[accent]獲取核心中的所有資源。[]\n這些資源可以用於研究新科技。\n\n[accent]按下發射按鈕。
item.copper.description = 最基本的結構材料。在各種類型的方塊中廣泛使用。 item.copper.description = 最基本的結構材料。在各種類型的方塊中廣泛使用。
@@ -1142,7 +1149,7 @@ block.power-source.description = 無限輸出能量。僅限沙盒。
block.item-source.description = 無限輸出物品。僅限沙盒。 block.item-source.description = 無限輸出物品。僅限沙盒。
block.item-void.description = 不使用能量銷毀任何進入它的物品。僅限沙盒。 block.item-void.description = 不使用能量銷毀任何進入它的物品。僅限沙盒。
block.liquid-source.description = 無限輸出液體。僅限沙盒。 block.liquid-source.description = 無限輸出液體。僅限沙盒。
block.liquid-void.description = Removes any liquids. Sandbox only. block.liquid-void.description = 銷毀所有輸入的液體。僅限沙盒。
block.copper-wall.description = 一種便宜的防禦方塊。\n用於前幾波防衛核心和砲塔。 block.copper-wall.description = 一種便宜的防禦方塊。\n用於前幾波防衛核心和砲塔。
block.copper-wall-large.description = 一種便宜的防禦方塊。\n用於前幾波防禦核心和砲塔\n佔據多個方塊。 block.copper-wall-large.description = 一種便宜的防禦方塊。\n用於前幾波防禦核心和砲塔\n佔據多個方塊。
block.titanium-wall.description = 一個中等強度的防禦方塊。\n提供對敵人的適度保護。 block.titanium-wall.description = 一個中等強度的防禦方塊。\n提供對敵人的適度保護。
@@ -1169,9 +1176,10 @@ block.bridge-conveyor.description = 高級的物品運輸方塊。允許跨過
block.phase-conveyor.description = 高級物品傳輸方塊。使用能量將物品傳送到幾個方塊外連接的相織輸送帶。 block.phase-conveyor.description = 高級物品傳輸方塊。使用能量將物品傳送到幾個方塊外連接的相織輸送帶。
block.sorter.description = 對物品進行分類。如果物品與所選種類匹配,則允許其通過。否則,物品將從左邊和右邊輸出。 block.sorter.description = 對物品進行分類。如果物品與所選種類匹配,則允許其通過。否則,物品將從左邊和右邊輸出。
block.inverted-sorter.description = 處理物品的方式類似於分類器,但將所選擇的物品輸出到側面。 block.inverted-sorter.description = 處理物品的方式類似於分類器,但將所選擇的物品輸出到側面。
block.router.description = 接受來自一個方向的物品並將它們平均輸出到最多3個其他方向。用於將物品從一個來源分割為多個目標。 block.router.description = 接受來自一個方向的物品並將它們平均輸出到最多3個其他方向。用於將物品從一個來源分割為多個目標。\n\n[[scarlet]]不建議緊貼在生產型方塊旁使用,可能導致其被產出堵塞。[]
block.distributor.description = 高級的分配器可將物品均分到最多7個其他方向。 block.distributor.description = 高級的分配器可將物品均分到最多7個其他方向。
block.overflow-gate.description = 如果前面被擋,則向左邊和右邊輸出物品。 block.overflow-gate.description = 如果前面被擋,則向左邊和右邊輸出物品。
block.underflow-gate.description = 反向的溢流器。如果側面被阻擋,則向前方輸出物品。
block.mass-driver.description = 終極物品運輸方塊。收集大量物品,然後將它們射向另一個質量驅動器。需要能源以運作。 block.mass-driver.description = 終極物品運輸方塊。收集大量物品,然後將它們射向另一個質量驅動器。需要能源以運作。
block.mechanical-pump.description = 一種便宜的泵,輸出速度慢,但不使用能量。 block.mechanical-pump.description = 一種便宜的泵,輸出速度慢,但不使用能量。
block.rotary-pump.description = 高級的泵。抽更多液體,但需要能量。 block.rotary-pump.description = 高級的泵。抽更多液體,但需要能量。

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -217,3 +217,4 @@
63527=slag|liquid-slag-icon 63527=slag|liquid-slag-icon
63526=oil|liquid-oil-icon 63526=oil|liquid-oil-icon
63525=cryofluid|liquid-cryofluid-icon 63525=cryofluid|liquid-cryofluid-icon
63524=underflow-gate|block-underflow-gate-medium

Binary file not shown.

Before

Width:  |  Height:  |  Size: 748 B

After

Width:  |  Height:  |  Size: 758 B

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 722 KiB

After

Width:  |  Height:  |  Size: 723 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 261 KiB

After

Width:  |  Height:  |  Size: 262 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 896 KiB

After

Width:  |  Height:  |  Size: 900 KiB

View File

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

View File

@@ -32,7 +32,6 @@ import java.util.*;
import static arc.Core.settings; import static arc.Core.settings;
@SuppressWarnings("unchecked")
public class Vars implements Loadable{ public class Vars implements Loadable{
/** Whether to load locales.*/ /** Whether to load locales.*/
public static boolean loadLocales = true; public static boolean loadLocales = true;
@@ -60,7 +59,7 @@ public class Vars implements Loadable{
public static final String serverJsonURL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers.json"; public static final String serverJsonURL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers.json";
/** URL to the JSON file containing all the BE servers. Only queried in BE. */ /** URL to the JSON file containing all the BE servers. Only queried in BE. */
public static final String serverJsonBeURL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers_be.json"; public static final String serverJsonBeURL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers_be.json";
/** URL the links to the wiki's modding guide.*/ /** URL of the github issue report template.*/
public static final String reportIssueURL = "https://github.com/Anuken/Mindustry/issues/new?template=bug_report.md"; public static final String reportIssueURL = "https://github.com/Anuken/Mindustry/issues/new?template=bug_report.md";
/** list of built-in servers.*/ /** list of built-in servers.*/
public static final Array<String> defaultServers = Array.with(); public static final Array<String> defaultServers = Array.with();

View File

@@ -57,7 +57,7 @@ public class Blocks implements ContentList{
scrapWall, scrapWallLarge, scrapWallHuge, scrapWallGigantic, thruster, //ok, these names are getting ridiculous, but at least I don't have humongous walls yet scrapWall, scrapWallLarge, scrapWallHuge, scrapWallGigantic, thruster, //ok, these names are getting ridiculous, but at least I don't have humongous walls yet
//transport //transport
conveyor, titaniumConveyor, armoredConveyor, distributor, junction, itemBridge, phaseConveyor, sorter, invertedSorter, router, overflowGate, massDriver, conveyor, titaniumConveyor, armoredConveyor, distributor, junction, itemBridge, phaseConveyor, sorter, invertedSorter, router, overflowGate, underflowGate, massDriver,
//liquids //liquids
mechanicalPump, rotaryPump, thermalPump, conduit, pulseConduit, platedConduit, liquidRouter, liquidTank, liquidJunction, bridgeConduit, phaseConduit, mechanicalPump, rotaryPump, thermalPump, conduit, pulseConduit, platedConduit, liquidRouter, liquidTank, liquidJunction, bridgeConduit, phaseConduit,
@@ -396,12 +396,37 @@ public class Blocks implements ContentList{
//endregion //endregion
//region ore //region ore
oreCopper = new OreBlock(Items.copper); oreCopper = new OreBlock(Items.copper){{
oreLead = new OreBlock(Items.lead); oreDefault = true;
oreThreshold = 0.81f;
oreScale = 23.47619f;
}};
oreLead = new OreBlock(Items.lead){{
oreDefault = true;
oreThreshold = 0.828f;
oreScale = 23.952381f;
}};
oreScrap = new OreBlock(Items.scrap); oreScrap = new OreBlock(Items.scrap);
oreCoal = new OreBlock(Items.coal);
oreTitanium = new OreBlock(Items.titanium); oreCoal = new OreBlock(Items.coal){{
oreThorium = new OreBlock(Items.thorium); oreDefault = true;
oreThreshold = 0.846f;
oreScale = 24.428572f;
}};
oreTitanium = new OreBlock(Items.titanium){{
oreDefault = true;
oreThreshold = 0.864f;
oreScale = 24.904762f;
}};
oreThorium = new OreBlock(Items.thorium){{
oreDefault = true;
oreThreshold = 0.882f;
oreScale = 25.380953f;
}};
//endregion //endregion
//region crafting //region crafting
@@ -651,7 +676,6 @@ public class Blocks implements ContentList{
int topRegion = reg("-top"); int topRegion = reg("-top");
drawIcons = () -> new TextureRegion[]{Core.atlas.find(name), Core.atlas.find(name + "-top")}; drawIcons = () -> new TextureRegion[]{Core.atlas.find(name), Core.atlas.find(name + "-top")};
drawer = tile -> { drawer = tile -> {
GenericCrafterEntity entity = tile.ent(); GenericCrafterEntity entity = tile.ent();
@@ -943,6 +967,12 @@ public class Blocks implements ContentList{
buildCostMultiplier = 3f; buildCostMultiplier = 3f;
}}; }};
underflowGate = new OverflowGate("underflow-gate"){{
requirements(Category.distribution, ItemStack.with(Items.lead, 2, Items.copper, 4));
buildCostMultiplier = 3f;
invert = true;
}};
massDriver = new MassDriver("mass-driver"){{ massDriver = new MassDriver("mass-driver"){{
requirements(Category.distribution, ItemStack.with(Items.titanium, 125, Items.silicon, 75, Items.lead, 125, Items.thorium, 50)); requirements(Category.distribution, ItemStack.with(Items.titanium, 125, Items.silicon, 75, Items.lead, 125, Items.thorium, 50));
size = 3; size = 3;

View File

@@ -22,7 +22,6 @@ public class TechTree implements ContentList{
node(conveyor, () -> { node(conveyor, () -> {
node(junction, () -> { node(junction, () -> {
node(itemBridge);
node(router, () -> { node(router, () -> {
node(launchPad, () -> { node(launchPad, () -> {
node(launchPadLarge, () -> { node(launchPadLarge, () -> {
@@ -34,7 +33,9 @@ public class TechTree implements ContentList{
node(sorter, () -> { node(sorter, () -> {
node(invertedSorter); node(invertedSorter);
node(message); node(message);
node(overflowGate); node(overflowGate, () -> {
node(underflowGate);
});
}); });
node(container, () -> { node(container, () -> {
node(unloader); node(unloader);
@@ -43,16 +44,18 @@ public class TechTree implements ContentList{
}); });
}); });
node(titaniumConveyor, () -> { node(itemBridge, () -> {
node(phaseConveyor, () -> { node(titaniumConveyor, () -> {
node(massDriver, () -> { node(phaseConveyor, () -> {
node(massDriver, () -> {
});
});
node(armoredConveyor, () -> {
}); });
}); });
node(armoredConveyor, () -> {
});
}); });
}); });
}); });
@@ -100,23 +103,25 @@ public class TechTree implements ContentList{
node(copperWall, () -> { node(copperWall, () -> {
node(copperWallLarge); node(copperWallLarge, () -> {
node(titaniumWall, () -> { node(titaniumWall, () -> {
node(door, () -> { node(titaniumWallLarge);
node(doorLarge);
});
node(plastaniumWall, () -> {
node(plastaniumWallLarge, () -> {
node(door, () -> {
node(doorLarge);
}); });
}); node(plastaniumWall, () -> {
node(titaniumWallLarge); node(plastaniumWallLarge, () -> {
node(thoriumWall, () -> {
node(thoriumWallLarge); });
node(surgeWall, () -> { });
node(surgeWallLarge); node(thoriumWall, () -> {
node(phaseWall, () -> { node(thoriumWallLarge);
node(phaseWallLarge); node(surgeWall, () -> {
node(surgeWallLarge);
node(phaseWall, () -> {
node(phaseWallLarge);
});
}); });
}); });
}); });
@@ -196,6 +201,8 @@ public class TechTree implements ContentList{
node(liquidRouter, () -> { node(liquidRouter, () -> {
node(liquidTank); node(liquidTank);
node(bridgeConduit);
node(pulseConduit, () -> { node(pulseConduit, () -> {
node(phaseConduit, () -> { node(phaseConduit, () -> {
@@ -212,7 +219,6 @@ public class TechTree implements ContentList{
}); });
}); });
}); });
node(bridgeConduit);
}); });
}); });
}); });

View File

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

View File

@@ -1,29 +1,29 @@
package mindustry.core; package mindustry.core;
import arc.*; import arc.*;
import mindustry.annotations.Annotations.*;
import arc.struct.*;
import arc.graphics.*; import arc.graphics.*;
import arc.math.*; import arc.math.*;
import arc.util.CommandHandler.*; import arc.struct.*;
import arc.util.*; import arc.util.*;
import arc.util.CommandHandler.*;
import arc.util.io.*; import arc.util.io.*;
import arc.util.serialization.*; import arc.util.serialization.*;
import mindustry.*; import mindustry.*;
import mindustry.annotations.Annotations.*;
import mindustry.core.GameState.*; import mindustry.core.GameState.*;
import mindustry.ctype.ContentType; import mindustry.ctype.*;
import mindustry.entities.*; import mindustry.entities.*;
import mindustry.entities.traits.BuilderTrait.*; import mindustry.entities.traits.BuilderTrait.*;
import mindustry.entities.traits.*; import mindustry.entities.traits.*;
import mindustry.entities.type.*; import mindustry.entities.type.*;
import mindustry.game.*;
import mindustry.game.EventType.*; import mindustry.game.EventType.*;
import mindustry.game.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.net.Administration.*; import mindustry.net.Administration.*;
import mindustry.net.Net.*; import mindustry.net.Net.*;
import mindustry.net.*; import mindustry.net.*;
import mindustry.net.Packets.*; import mindustry.net.Packets.*;
import mindustry.type.TypeID; import mindustry.type.*;
import mindustry.world.*; import mindustry.world.*;
import mindustry.world.modules.*; import mindustry.world.modules.*;
@@ -172,8 +172,8 @@ public class NetClient implements ApplicationListener{
} }
//special case; graphical server needs to see its message //special case; graphical server needs to see its message
if(!headless && player == Vars.player){ if(!headless){
Vars.ui.chatfrag.addMessage(message, colorizeName(player.id, player.name)); sendMessage(message, colorizeName(player.id, player.name), player);
} }
//server console logging //server console logging
@@ -266,6 +266,34 @@ public class NetClient implements ApplicationListener{
ui.showText("", message); ui.showText("", message);
} }
//TODO these are commented out to enforce compatibility with 103! uncomment before 104 release
/*
@Remote(variants = Variant.both)
public static void onInfoPopup(String message, float duration, int align, int top, int left, int bottom, int right){
ui.showInfoPopup(message, duration, align, top, left, bottom, right);
}
@Remote(variants = Variant.both)
public static void onLabel(String info, float duration, float worldx, float worldy){
ui.showLabel(info, duration, worldx, worldy);
}
@Remote(variants = Variant.both, unreliable = true)
public static void onEffect(Effect effect, float x, float y, float rotation, Color color){
Effects.effect(effect, color, x, y, rotation);
}
@Remote(variants = Variant.both)
public static void onEffectReliable(Effect effect, float x, float y, float rotation, Color color){
Effects.effect(effect, color, x, y, rotation);
}*/
@Remote(variants = Variant.both)
public static void onInfoToast(String message, float duration){
ui.showInfoToast(message, duration);
}
@Remote(variants = Variant.both) @Remote(variants = Variant.both)
public static void onSetRules(Rules rules){ public static void onSetRules(Rules rules){
state.rules = rules; state.rules = rules;
@@ -387,7 +415,7 @@ public class NetClient implements ApplicationListener{
netClient.byteStream.setBytes(net.decompressSnapshot(coreData, coreDataLen)); netClient.byteStream.setBytes(net.decompressSnapshot(coreData, coreDataLen));
DataInputStream input = netClient.dataStream; DataInputStream input = netClient.dataStream;
int cores = input.readInt(); byte cores = input.readByte();
for(int i = 0; i < cores; i++){ for(int i = 0; i < cores; i++){
int pos = input.readInt(); int pos = input.readInt();
Tile tile = world.tile(pos); Tile tile = world.tile(pos);

View File

@@ -234,6 +234,13 @@ public class NetServer implements ApplicationListener{
RemoteReadServer.readPacket(packet.writeBuffer, packet.type, con.player); RemoteReadServer.readPacket(packet.writeBuffer, packet.type, con.player);
}catch(ValidateException e){ }catch(ValidateException e){
Log.debug("Validation failed for '{0}': {1}", e.player, e.getMessage()); Log.debug("Validation failed for '{0}': {1}", e.player, e.getMessage());
}catch(RuntimeException e){
if(e.getCause() instanceof ValidateException){
ValidateException v = (ValidateException)e.getCause();
Log.debug("Validation failed for '{0}': {1}", v.player, v.getMessage());
}else{
throw e;
}
} }
}); });
@@ -257,7 +264,7 @@ public class NetServer implements ApplicationListener{
page --; page --;
if(page > pages || page < 0){ if(page >= pages || page < 0){
player.sendMessage("[scarlet]'page' must be a number between[orange] 1[] and[orange] " + pages + "[scarlet]."); player.sendMessage("[scarlet]'page' must be a number between[orange] 1[] and[orange] " + pages + "[scarlet].");
return; return;
} }
@@ -277,7 +284,11 @@ public class NetServer implements ApplicationListener{
}); });
//duration of a a kick in seconds //duration of a a kick in seconds
int kickDuration = 15 * 60; int kickDuration = 60 * 60;
//voting round duration in seconds
float voteDuration = 0.5f * 60;
//cooldown between votes
int voteCooldown = 60 * 1;
class VoteSession{ class VoteSession{
Player target; Player target;
@@ -295,17 +306,15 @@ public class NetServer implements ApplicationListener{
map[0] = null; map[0] = null;
task.cancel(); task.cancel();
} }
}, 60 * 1); }, voteDuration);
} }
void vote(Player player, int d){ void vote(Player player, int d){
votes += d; votes += d;
voted.addAll(player.uuid, admins.getInfo(player.uuid).lastIP); voted.addAll(player.uuid, admins.getInfo(player.uuid).lastIP);
if(!checkPass()){ Call.sendMessage(Strings.format("[orange]{0}[lightgray] has voted to kick[orange] {1}[].[accent] ({2}/{3})\n[lightgray]Type[orange] /vote <y/n>[] to agree.",
Call.sendMessage(Strings.format("[orange]{0}[lightgray] has voted to kick[orange] {1}[].[accent] ({2}/{3})\n[lightgray]Type[orange] /vote <y/n>[] to agree.", player.name, target.name, votes, votesRequired()));
player.name, target.name, votes, votesRequired()));
}
} }
boolean checkPass(){ boolean checkPass(){
@@ -321,9 +330,7 @@ public class NetServer implements ApplicationListener{
} }
} }
//cooldown between votes Timekeeper vtime = new Timekeeper(voteCooldown);
int voteTime = 60 * 3;
Timekeeper vtime = new Timekeeper(voteTime);
//current kick sessions //current kick sessions
VoteSession[] currentlyKicking = {null}; VoteSession[] currentlyKicking = {null};
@@ -370,7 +377,7 @@ public class NetServer implements ApplicationListener{
player.sendMessage("[scarlet]Only players on your team can be kicked."); player.sendMessage("[scarlet]Only players on your team can be kicked.");
}else{ }else{
if(!vtime.get()){ if(!vtime.get()){
player.sendMessage("[scarlet]You must wait " + voteTime/60 + " minutes between votekicks."); player.sendMessage("[scarlet]You must wait " + voteCooldown/60 + " minutes between votekicks.");
return; return;
} }
@@ -465,7 +472,7 @@ public class NetServer implements ApplicationListener{
Call.onPlayerDisconnect(player.id); Call.onPlayerDisconnect(player.id);
} }
Log.info("&lm[{1}] &lc{0} has disconnected. &lg&fi({2})", player.name, player.uuid, reason); if(Config.showConnectMessages.bool()) Log.info("&lm[{1}] &lc{0} has disconnected. &lg&fi({2})", player.name, player.uuid, reason);
} }
player.remove(); player.remove();
@@ -613,8 +620,10 @@ public class NetServer implements ApplicationListener{
player.add(); player.add();
player.con.hasConnected = true; player.con.hasConnected = true;
if(Config.showConnectMessages.bool()) Call.sendMessage("[accent]" + player.name + "[accent] has connected."); if(Config.showConnectMessages.bool()){
Log.info("&lm[{1}] &y{0} has connected. ", player.name, player.uuid); Call.sendMessage("[accent]" + player.name + "[accent] has connected.");
Log.info("&lm[{1}] &y{0} has connected. ", player.name, player.uuid);
}
if(!Config.motd.string().equalsIgnoreCase("off")){ if(!Config.motd.string().equalsIgnoreCase("off")){
player.sendMessage(Config.motd.string()); player.sendMessage(Config.motd.string());
@@ -706,7 +715,7 @@ public class NetServer implements ApplicationListener{
syncStream.reset(); syncStream.reset();
Array<CoreEntity> cores = state.teams.cores(player.getTeam()); Array<CoreEntity> cores = state.teams.cores(player.getTeam());
dataStream.writeInt(cores.size); dataStream.writeByte(cores.size);
for(CoreEntity entity : cores){ for(CoreEntity entity : cores){
dataStream.writeInt(entity.tile.pos()); dataStream.writeInt(entity.tile.pos());

View File

@@ -9,6 +9,7 @@ import arc.graphics.*;
import arc.graphics.g2d.*; import arc.graphics.g2d.*;
import arc.input.*; import arc.input.*;
import arc.math.*; import arc.math.*;
import arc.math.geom.*;
import arc.scene.*; import arc.scene.*;
import arc.scene.actions.*; import arc.scene.actions.*;
import arc.scene.event.*; import arc.scene.event.*;
@@ -289,6 +290,49 @@ public class UI implements ApplicationListener, Loadable{
Core.scene.add(table); Core.scene.add(table);
} }
/** Shows a fading label at the top of the screen. */
public void showInfoToast(String info, float duration){
Table table = new Table();
table.setFillParent(true);
table.touchable(Touchable.disabled);
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);
}
/** Shows a label at some position on the screen. Does not fade. */
public void showInfoPopup(String info, float duration, int align, int top, int left, int bottom, int right){
Table table = new Table();
table.setFillParent(true);
table.touchable(Touchable.disabled);
table.update(() -> {
if(state.is(State.menu)) table.remove();
});
table.actions(Actions.delay(duration), Actions.remove());
table.align(align).table(Styles.black3, t -> t.margin(4).add(info).style(Styles.outlineLabel)).pad(top, left, bottom, right);
Core.scene.add(table);
}
/** Shows a label in the world. This label is behind everything. Does not fade. */
public void showLabel(String info, float duration, float worldx, float worldy){
Table table = new Table();
table.setFillParent(true);
table.touchable(Touchable.disabled);
table.update(() -> {
if(state.is(State.menu)) table.remove();
});
table.actions(Actions.delay(duration), Actions.remove());
table.align(Align.center).table(Styles.black3, t -> t.margin(4).add(info).style(Styles.outlineLabel)).update(t -> {
Vec2 v = Core.camera.project(worldx, worldy);
t.setPosition(v.x, v.y, Align.center);
});
//make sure it's at the back
Core.scene.root.addChildAt(0, table);
}
public void showInfo(String info){ public void showInfo(String info){
new Dialog(""){{ new Dialog(""){{
getCell(cont).growX(); getCell(cont).growX();
@@ -426,7 +470,6 @@ public class UI implements ApplicationListener, Loadable{
dialog.show(); dialog.show();
} }
public void showCustomConfirm(String title, String text, String yes, String no, Runnable confirmed, Runnable denied){ public void showCustomConfirm(String title, String text, String yes, String no, Runnable confirmed, Runnable denied){
FloatingDialog dialog = new FloatingDialog(title); FloatingDialog dialog = new FloatingDialog(title);
dialog.cont.add(text).width(mobile ? 400f : 500f).wrap().pad(4f).get().setAlignment(Align.center, Align.center); dialog.cont.add(text).width(mobile ? 400f : 500f).wrap().pad(4f).get().setAlignment(Align.center, Align.center);
@@ -459,11 +502,11 @@ public class UI implements ApplicationListener, Loadable{
public String formatAmount(int number){ public String formatAmount(int number){
if(number >= 1000000){ if(number >= 1000000){
return Strings.fixed(number / 1000000f, 1) + "[gray]" + Core.bundle.getOrNull("unit.millions") + "[]"; return Strings.fixed(number / 1000000f, 1) + "[gray]" + Core.bundle.get("unit.millions") + "[]";
}else if(number >= 10000){ }else if(number >= 10000){
return number / 1000 + "[gray]k[]"; return number / 1000 + "[gray]" + Core.bundle.get("unit.thousands") + "[]";
}else if(number >= 1000){ }else if(number >= 1000){
return Strings.fixed(number / 1000f, 1) + "[gray]" + Core.bundle.getOrNull("unit.thousands") + "[]"; return Strings.fixed(number / 1000f, 1) + "[gray]" + Core.bundle.get("unit.thousands") + "[]";
}else{ }else{
return number + ""; return number + "";
} }

View File

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

View File

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

View File

@@ -38,4 +38,9 @@ public class RubbleDecal extends Decal{
} }
Draw.rect(region, x, y, Mathf.randomSeed(id, 0, 4) * 90); Draw.rect(region, x, y, Mathf.randomSeed(id, 0, 4) * 90);
} }
@Override
public float drawSize(){
return region.getWidth() * 3f;
}
} }

View File

@@ -367,9 +367,9 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
if(isAdmin){ if(isAdmin){
float s = 3f; float s = 3f;
Draw.color(color.r * 0.5f, color.g * 0.5f, color.b * 0.5f, 1f); Draw.color(color.r * 0.5f, color.g * 0.5f, color.b * 0.5f, 1f);
Draw.rect(Core.atlas.find("icon-admin-badge"), x + layout.width / 2f + 2 + 1, y + nameHeight - 1.5f, s, s); Draw.rect(Icon.adminSmall.getRegion(), x + layout.width / 2f + 2 + 1, y + nameHeight - 1.5f, s, s);
Draw.color(color); Draw.color(color);
Draw.rect(Core.atlas.find("icon-admin-badge"), x + layout.width / 2f + 2 + 1, y + nameHeight - 1f, s, s); Draw.rect(Icon.adminSmall.getRegion(), x + layout.width / 2f + 2 + 1, y + nameHeight - 1f, s, s);
} }
} }

View File

@@ -9,12 +9,11 @@ import arc.math.geom.Point2;
import arc.math.geom.Vec2; import arc.math.geom.Vec2;
import arc.util.*; import arc.util.*;
import arc.util.ArcAnnotate.*; import arc.util.ArcAnnotate.*;
import arc.util.*; import mindustry.entities.EntityGroup;
import mindustry.annotations.Annotations.*; import mindustry.entities.traits.HealthTrait;
import mindustry.entities.*; import mindustry.entities.traits.TargetTrait;
import mindustry.entities.traits.*;
import mindustry.game.EventType.*;
import mindustry.game.*; import mindustry.game.*;
import mindustry.game.EventType.BlockDestroyEvent;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.world.*; import mindustry.world.*;
import mindustry.world.consumers.*; import mindustry.world.consumers.*;
@@ -24,8 +23,8 @@ import java.io.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait, TeamTrait{ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
public static final float timeToSleep = 60f * 4; //4 seconds to fall asleep public static final float timeToSleep = 60f * 1; //1 second to fall asleep
private static final ObjectSet<Tile> tmpTiles = new ObjectSet<>(); private static final ObjectSet<Tile> tmpTiles = new ObjectSet<>();
/** This value is only used for debugging. */ /** This value is only used for debugging. */
public static int sleepingEntities = 0; public static int sleepingEntities = 0;
@@ -85,11 +84,6 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait,
return this; return this;
} }
public void applyBoost(float intensity, float duration){
timeScaleDuration = Math.max(timeScaleDuration, duration);
timeScale = Math.max(timeScale, intensity);
}
/** Scaled delta. */ /** Scaled delta. */
public float delta(){ public float delta(){
return Time.delta() * timeScale; return Time.delta() * timeScale;

View File

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

View File

@@ -125,7 +125,7 @@ public class Teams{
} }
private void updateEnemies(){ private void updateEnemies(){
if(!active.contains(get(state.rules.waveTeam))){ if(state.rules.waves && !active.contains(get(state.rules.waveTeam))){
active.add(get(state.rules.waveTeam)); active.add(get(state.rules.waveTeam));
} }

View File

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

View File

@@ -704,7 +704,8 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
} }
public void add(){ public void add(){
Core.input.addProcessor(detector = new GestureDetector(20, 0.5f, 0.4f, 0.15f, this)); Core.input.getInputProcessors().remove(i -> i instanceof InputHandler || (i instanceof GestureDetector && ((GestureDetector)i).getListener() instanceof InputHandler));
Core.input.addProcessor(detector = new GestureDetector(20, 0.5f, 0.3f, 0.15f, this));
Core.input.addProcessor(this); Core.input.addProcessor(this);
if(Core.scene != null){ if(Core.scene != null){
Table table = (Table)Core.scene.find("inputTable"); Table table = (Table)Core.scene.find("inputTable");

View File

@@ -258,7 +258,7 @@ public class MobileInput extends InputHandler implements GestureListener{
selectRequests.clear(); selectRequests.clear();
mode = none; mode = none;
block = null; block = null;
}).width(155f); }).width(155f).margin(12f);
}); });
group.fill(t -> { group.fill(t -> {

View File

@@ -338,11 +338,11 @@ public class Maps{
} }
public void addDefaultOres(Array<GenerateFilter> filters){ public void addDefaultOres(Array<GenerateFilter> filters){
int index = 0; Array<Block> ores = content.blocks().select(b -> b.isOverlay() && b.asFloor().oreDefault);
for(Block block : new Block[]{Blocks.oreCopper, Blocks.oreLead, Blocks.oreCoal, Blocks.oreTitanium, Blocks.oreThorium}){ for(Block block : ores){
OreFilter filter = new OreFilter(); OreFilter filter = new OreFilter();
filter.threshold += index ++ * 0.018f; filter.threshold = block.asFloor().oreThreshold;
filter.scl += index/2.1f; filter.scl = block.asFloor().oreScale;
filter.ore = block; filter.ore = block;
filters.add(filter); filters.add(filter);
} }

View File

@@ -8,7 +8,8 @@ import arc.scene.ui.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
import mindustry.*; import mindustry.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.ui.Cicon; import mindustry.gen.*;
import mindustry.ui.*;
import mindustry.ui.dialogs.*; import mindustry.ui.dialogs.*;
import mindustry.world.*; import mindustry.world.*;
import mindustry.world.blocks.*; import mindustry.world.blocks.*;
@@ -77,14 +78,14 @@ public abstract class FilterOption{
@Override @Override
public void build(Table table){ public void build(Table table){
table.addButton(b -> b.addImage(supplier.get().icon(Cicon.small)).update(i -> ((TextureRegionDrawable)i.getDrawable()) table.addButton(b -> b.addImage(supplier.get().icon(Cicon.small)).update(i -> ((TextureRegionDrawable)i.getDrawable())
.setRegion(supplier.get() == Blocks.air ? Core.atlas.find("Icon.none") : supplier.get().icon(Cicon.small))).size(8 * 3), () -> { .setRegion(supplier.get() == Blocks.air ? Icon.block.getRegion() : supplier.get().icon(Cicon.small))).size(8 * 3), () -> {
FloatingDialog dialog = new FloatingDialog(""); FloatingDialog dialog = new FloatingDialog("");
dialog.setFillParent(false); dialog.setFillParent(false);
int i = 0; int i = 0;
for(Block block : Vars.content.blocks()){ for(Block block : Vars.content.blocks()){
if(!filter.get(block)) continue; if(!filter.get(block)) continue;
dialog.cont.addImage(block == Blocks.air ? Core.atlas.find("Icon.none-") : block.icon(Cicon.medium)).size(8 * 4).pad(3).get().clicked(() -> { dialog.cont.addImage(block == Blocks.air ? Icon.block.getRegion() : block.icon(Cicon.medium)).size(8 * 4).pad(3).get().clicked(() -> {
consumer.get(block); consumer.get(block);
dialog.hide(); dialog.hide();
changed.run(); changed.run();

View File

@@ -246,7 +246,7 @@ public class Mods implements Loadable{
try{ try{
LoadedMod mod = loadMod(file); LoadedMod mod = loadMod(file);
mods.add(mod); mods.add(mod);
}catch(Exception e){ }catch(Throwable e){
Log.err("Failed to load mod file {0}. Skipping.", file); Log.err("Failed to load mod file {0}. Skipping.", file);
Log.err(e); Log.err(e);
} }
@@ -258,7 +258,7 @@ public class Mods implements Loadable{
LoadedMod mod = loadMod(file); LoadedMod mod = loadMod(file);
mods.add(mod); mods.add(mod);
mod.addSteamID(file.name()); mod.addSteamID(file.name());
}catch(Exception e){ }catch(Throwable e){
Log.err("Failed to load mod workshop file {0}. Skipping.", file); Log.err("Failed to load mod workshop file {0}. Skipping.", file);
Log.err(e); Log.err(e);
} }
@@ -354,7 +354,7 @@ public class Mods implements Loadable{
for(Fi file : bundles.getOr(locale, Array::new)){ for(Fi file : bundles.getOr(locale, Array::new)){
try{ try{
PropertiesUtils.load(bundle.getProperties(), file.reader()); PropertiesUtils.load(bundle.getProperties(), file.reader());
}catch(Exception e){ }catch(Throwable e){
Log.err("Error loading bundle: " + file + "/" + locale, e); Log.err("Error loading bundle: " + file + "/" + locale, e);
} }
} }

View File

@@ -11,7 +11,8 @@ import org.mozilla.javascript.*;
public class Scripts implements Disposable{ public class Scripts implements Disposable{
private final Array<String> blacklist = Array.with("net", "files", "reflect", "javax", "rhino", "file", "channels", "jdk", private final Array<String> blacklist = Array.with("net", "files", "reflect", "javax", "rhino", "file", "channels", "jdk",
"runtime", "util.os", "rmi", "security", "org.", "sun.", "beans", "sql", "http", "exec", "compiler", "process", "system", ".awt", "socket"); "runtime", "util.os", "rmi", "security", "org.", "sun.", "beans", "sql", "http", "exec", "compiler", "process", "system",
".awt", "socket", "classloader", "oracle");
private final Array<String> whitelist = Array.with("mindustry.net"); private final Array<String> whitelist = Array.with("mindustry.net");
private final Context context; private final Context context;
private final String wrapper; private final String wrapper;

View File

@@ -420,7 +420,7 @@ public class Administration{
crashReport("Whether to send crash reports.", false, "crashreport"), crashReport("Whether to send crash reports.", false, "crashreport"),
logging("Whether to log everything to files.", true), logging("Whether to log everything to files.", true),
strict("Whether strict mode is on - corrects positions and prevents duplicate UUIDs.", true), strict("Whether strict mode is on - corrects positions and prevents duplicate UUIDs.", true),
antiSpam("Whether spammers are automatically kicked and rate-limited.", true), antiSpam("Whether spammers are automatically kicked and rate-limited.", headless),
messageRateLimit("Message rate limit in seconds. 0 to disable.", 0), messageRateLimit("Message rate limit in seconds. 0 to disable.", 0),
messageSpamKick("How many times a player must send a message before the cooldown to get kicked. 0 to disable.", 3), messageSpamKick("How many times a player must send a message before the cooldown to get kicked. 0 to disable.", 3),
socketInput("Allows a local application to control this server through a local TCP socket.", false, "socket", () -> Events.fire(Trigger.socketConfigChanged)), socketInput("Allows a local application to control this server through a local TCP socket.", false, "socket", () -> Events.fire(Trigger.socketConfigChanged)),

View File

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

View File

@@ -54,8 +54,9 @@ public class Fonts{
Core.assets.load("default", BitmapFont.class, new FreeTypeFontLoaderParameter(fontName, param)).loaded = f -> Fonts.def = (BitmapFont)f; Core.assets.load("default", BitmapFont.class, new FreeTypeFontLoaderParameter(fontName, param)).loaded = f -> Fonts.def = (BitmapFont)f;
Core.assets.load("chat", BitmapFont.class, new FreeTypeFontLoaderParameter(fontName, param)).loaded = f -> Fonts.chat = (BitmapFont)f; Core.assets.load("chat", BitmapFont.class, new FreeTypeFontLoaderParameter(fontName, param)).loaded = f -> Fonts.chat = (BitmapFont)f;
Core.assets.load("icon", BitmapFont.class, new FreeTypeFontLoaderParameter("fonts/icon.ttf", new FreeTypeFontParameter(){{ Core.assets.load("icon", BitmapFont.class, new FreeTypeFontLoaderParameter("fonts/icon.ttf", new FreeTypeFontParameter(){{
size = (int)(Scl.scl(30f)); size = 30;
incremental = true; incremental = true;
characters = "\0";
}})).loaded = f -> Fonts.icon = (BitmapFont)f; }})).loaded = f -> Fonts.icon = (BitmapFont)f;
} }
@@ -104,12 +105,19 @@ public class Fonts{
FileHandleResolver resolver = new InternalFileHandleResolver(); FileHandleResolver resolver = new InternalFileHandleResolver();
Core.assets.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(resolver)); Core.assets.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(resolver));
Core.assets.setLoader(BitmapFont.class, null, new FreetypeFontLoader(resolver){ Core.assets.setLoader(BitmapFont.class, null, new FreetypeFontLoader(resolver){
ObjectSet<FreeTypeFontParameter> scaled = new ObjectSet<>();
@Override @Override
public BitmapFont loadSync(AssetManager manager, String fileName, Fi file, FreeTypeFontLoaderParameter parameter){ public BitmapFont loadSync(AssetManager manager, String fileName, Fi file, FreeTypeFontLoaderParameter parameter){
if(fileName.equals("outline")){ if(fileName.equals("outline")){
parameter.fontParameters.borderWidth = Scl.scl(2f); parameter.fontParameters.borderWidth = Scl.scl(2f);
parameter.fontParameters.spaceX -= parameter.fontParameters.borderWidth; parameter.fontParameters.spaceX -= parameter.fontParameters.borderWidth;
} }
if(!scaled.contains(parameter.fontParameters)){
parameter.fontParameters.size = (int)(Scl.scl(parameter.fontParameters.size));
scaled.add(parameter.fontParameters);
}
parameter.fontParameters.magFilter = TextureFilter.Linear; parameter.fontParameters.magFilter = TextureFilter.Linear;
parameter.fontParameters.minFilter = TextureFilter.Linear; parameter.fontParameters.minFilter = TextureFilter.Linear;
parameter.fontParameters.packer = UI.packer; parameter.fontParameters.packer = UI.packer;
@@ -119,8 +127,8 @@ public class Fonts{
FreeTypeFontParameter param = new FreeTypeFontParameter(){{ FreeTypeFontParameter param = new FreeTypeFontParameter(){{
borderColor = Color.darkGray; borderColor = Color.darkGray;
size = (int)(Scl.scl(18f));
incremental = true; incremental = true;
size = 18;
}}; }};
Core.assets.load("outline", BitmapFont.class, new FreeTypeFontLoaderParameter("fonts/font.ttf", param)).loaded = t -> Fonts.outline = (BitmapFont)t; Core.assets.load("outline", BitmapFont.class, new FreeTypeFontLoaderParameter("fonts/font.ttf", param)).loaded = t -> Fonts.outline = (BitmapFont)t;
@@ -162,7 +170,6 @@ public class Fonts{
if(g == null) throw new IllegalArgumentException("No glyph: " + glyph + " (" + (int)glyph + ")"); if(g == null) throw new IllegalArgumentException("No glyph: " + glyph + " (" + (int)glyph + ")");
float size = Math.max(g.width, g.height); float size = Math.max(g.width, g.height);
float aspect = (float)g.height / g.width;
TextureRegionDrawable draw = new TextureRegionDrawable(new TextureRegion(font.getRegion().getTexture(), g.u, g.v2, g.u2, g.v)){ TextureRegionDrawable draw = new TextureRegionDrawable(new TextureRegion(font.getRegion().getTexture(), g.u, g.v2, g.u2, g.v)){
@Override @Override
public void draw(float x, float y, float width, float height){ public void draw(float x, float y, float width, float height){
@@ -173,6 +180,19 @@ public class Fonts{
Draw.rect(region, cx + g.width/2f, cy + g.height/2f, g.width, g.height); Draw.rect(region, cx + g.width/2f, cy + g.height/2f, g.width, g.height);
} }
@Override
public void draw(float x, float y, float originX, float originY, float width, float height, float scaleX, float scaleY, float rotation){
width *= scaleX;
height *= scaleY;
Draw.color(Tmp.c1.set(tint).mul(Draw.getColor()).toFloatBits());
float cx = x + width/2f - g.width/2f, cy = y + height/2f - g.height/2f;
cx = (int)cx;
cy = (int)cy;
originX = g.width/2f;
originY = g.height/2f;
Draw.rect(region, cx + g.width/2f, cy + g.height/2f, g.width, g.height, originX, originY, rotation);
}
@Override @Override
public float imageSize(){ public float imageSize(){
return size; return size;
@@ -186,7 +206,7 @@ public class Fonts{
static FreeTypeFontParameter fontParameter(){ static FreeTypeFontParameter fontParameter(){
return new FreeTypeFontParameter(){{ return new FreeTypeFontParameter(){{
size = (int)(Scl.scl(18f)); size = 18;
shadowColor = Color.darkGray; shadowColor = Color.darkGray;
shadowOffsetY = 2; shadowOffsetY = 2;
incremental = true; incremental = true;

View File

@@ -1,6 +1,7 @@
package mindustry.ui; package mindustry.ui;
import arc.graphics.*; import arc.graphics.*;
import arc.scene.ui.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
import mindustry.core.GameState.*; import mindustry.core.GameState.*;
import mindustry.gen.*; import mindustry.gen.*;
@@ -21,18 +22,31 @@ public class ItemsDisplay extends Table{
top().left(); top().left();
margin(0); margin(0);
table(Tex.button,t -> { table(Tex.button, c -> {
t.margin(10).marginLeft(15).marginTop(15f); c.margin(10).marginLeft(12).marginTop(15f);
t.label(() -> state.is(State.menu) ? "$launcheditems" : "$launchinfo").colspan(3).padBottom(4).left().colspan(3).width(210f).wrap(); c.marginRight(12f);
t.row(); c.left();
for(Item item : content.items()){
if(item.type == ItemType.material && data.isUnlocked(item)){ Collapser col = new Collapser(base -> base.pane(t -> {
t.label(() -> format(item)).left(); t.marginRight(30f);
t.addImage(item.icon(Cicon.small)).size(8 * 3).padLeft(4).padRight(4); t.left();
t.add(item.localizedName).color(Color.lightGray).left(); for(Item item : content.items()){
t.row(); if(item.type == ItemType.material && data.isUnlocked(item)){
t.label(() -> format(item)).left();
t.addImage(item.icon(Cicon.small)).size(8 * 3).padLeft(4).padRight(4);
t.add(item.localizedName).color(Color.lightGray).left();
t.row();
}
} }
} }).get().setScrollingDisabled(true, false), false).setDuration(0.3f);
c.addImageTextButton("$launcheditems", Icon.downOpen, Styles.clearTogglet, col::toggle).update(t -> {
t.setText(state.is(State.menu) ? "$launcheditems" : "$launchinfo");
t.setChecked(col.isCollapsed());
((Image)t.getChildren().get(1)).setDrawable(col.isCollapsed() ? Icon.upOpen : Icon.downOpen);
}).padBottom(4).left().fillX().margin(12f);
c.row();
c.add(col);
}); });
} }

View File

@@ -3,6 +3,7 @@ package mindustry.ui.dialogs;
import arc.*; import arc.*;
import arc.graphics.g2d.*; import arc.graphics.g2d.*;
import arc.math.*; import arc.math.*;
import arc.scene.style.*;
import arc.scene.ui.*; import arc.scene.ui.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
import arc.util.*; import arc.util.*;
@@ -59,8 +60,9 @@ public class CustomGameDialog extends FloatingDialog{
image.table(t -> { image.table(t -> {
t.left(); t.left();
for(Gamemode mode : Gamemode.all){ for(Gamemode mode : Gamemode.all){
if(mode.valid(map) && Core.atlas.has("icon-mode-" + mode.name())){ TextureRegionDrawable icon = Vars.ui.getIcon("mode" + Strings.capitalize(mode.name()) + "Small");
t.addImage(Core.atlas.drawable("icon-mode-" + mode.name())).size(16f).pad(4f); if(mode.valid(map) && Core.atlas.isFound(icon.getRegion())){
t.addImage(icon).size(16f).pad(4f);
} }
} }
}).left(); }).left();

View File

@@ -122,7 +122,7 @@ public class DeployDialog extends FloatingDialog{
setFilter(TextureFilter.Linear); setFilter(TextureFilter.Linear);
}}){{ }}){{
float[] time = {0}; float[] time = {0};
setColor(Color.gray(0.3f)); setColor(Color.grays(0.3f));
setScale(1.5f); setScale(1.5f);
update(() -> { update(() -> {
setOrigin(Align.center); setOrigin(Align.center);
@@ -140,7 +140,7 @@ public class DeployDialog extends FloatingDialog{
Stack sub = new Stack(); Stack sub = new Stack();
if(slot.getZone() != null){ if(slot.getZone() != null){
sub.add(new Table(f -> f.margin(4f).add(new Image()).color(Color.gray(0.1f)).grow())); sub.add(new Table(f -> f.margin(4f).add(new Image()).color(Color.grays(0.1f)).grow()));
sub.add(new Table(f -> f.margin(4f).add(new Image(slot.getZone().preview).setScaling(Scaling.fit)).update(img -> { sub.add(new Table(f -> f.margin(4f).add(new Image(slot.getZone().preview).setScaling(Scaling.fit)).update(img -> {
TextureRegionDrawable draw = (TextureRegionDrawable)img.getDrawable(); TextureRegionDrawable draw = (TextureRegionDrawable)img.getDrawable();
@@ -254,7 +254,7 @@ public class DeployDialog extends FloatingDialog{
} }
stack.setSize(Tmp.v1.x, Tmp.v1.y); stack.setSize(Tmp.v1.x, Tmp.v1.y);
stack.add(new Table(t -> t.margin(4f).add(new Image(node.zone.preview).setScaling(Scaling.stretch)).color(node.zone.unlocked() ? Color.darkGray : Color.gray(0.2f)).grow())); stack.add(new Table(t -> t.margin(4f).add(new Image(node.zone.preview).setScaling(Scaling.stretch)).color(node.zone.unlocked() ? Color.darkGray : Color.grays(0.2f)).grow()));
stack.update(() -> stack.setPosition(node.x + panX + width / 2f, node.y + panY + height / 2f, Align.center)); stack.update(() -> stack.setPosition(node.x + panX + width / 2f, node.y + panY + height / 2f, Align.center));
Button button = new Button(Styles.squaret); Button button = new Button(Styles.squaret);

View File

@@ -95,11 +95,16 @@ public class JoinDialog extends FloatingDialog{
} }
}); });
onResize(this::setup); onResize(() -> {
setup();
refreshLocal();
refreshRemote();
});
} }
void setupRemote(){ void setupRemote(){
remote.clear(); remote.clear();
for(Server server : servers){ for(Server server : servers){
//why are java lambdas this bad //why are java lambdas this bad
TextButton[] buttons = {null}; TextButton[] buttons = {null};
@@ -266,7 +271,7 @@ public class JoinDialog extends FloatingDialog{
cont.addCenteredImageTextButton("$server.add", Icon.add, () -> { cont.addCenteredImageTextButton("$server.add", Icon.add, () -> {
renaming = null; renaming = null;
add.show(); add.show();
}).marginLeft(6).width(w).height(80f).update(button -> { }).marginLeft(10).width(w).height(80f).update(button -> {
float pw = w; float pw = w;
float pad = 0f; float pad = 0f;
if(pane.getChildren().first().getPrefHeight() > pane.getHeight()){ if(pane.getChildren().first().getPrefHeight() > pane.getHeight()){
@@ -363,7 +368,7 @@ public class JoinDialog extends FloatingDialog{
} }
float targetWidth(){ float targetWidth(){
return Core.graphics.isPortrait() ? 350f : 500f; return Math.min(Core.graphics.getWidth() / Scl.scl() * 0.9f, 500f);//Core.graphics.isPortrait() ? 350f : 500f;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@@ -1,7 +1,6 @@
package mindustry.ui.dialogs; package mindustry.ui.dialogs;
import arc.*; import arc.*;
import arc.struct.*;
import arc.files.*; import arc.files.*;
import arc.graphics.*; import arc.graphics.*;
import arc.graphics.Texture.*; import arc.graphics.Texture.*;
@@ -12,6 +11,7 @@ import arc.scene.ui.*;
import arc.scene.ui.SettingsDialog.SettingsTable.*; import arc.scene.ui.SettingsDialog.SettingsTable.*;
import arc.scene.ui.TextButton.*; import arc.scene.ui.TextButton.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*; import arc.util.*;
import mindustry.core.GameState.*; import mindustry.core.GameState.*;
import mindustry.core.*; import mindustry.core.*;
@@ -240,10 +240,17 @@ public class SettingsMenuDialog extends SettingsDialog{
game.checkPref("buildautopause", false); game.checkPref("buildautopause", false);
} }
if(steam && !Version.modifier.contains("beta")){ if(steam){
game.checkPref("publichost", false, i -> { game.sliderPref("playerlimit", 16, 2, 32, i -> {
platform.updateLobby(); platform.updateLobby();
return i + "";
}); });
if(!Version.modifier.contains("beta")){
game.checkPref("publichost", false, i -> {
platform.updateLobby();
});
}
} }
game.pref(new Setting(){ game.pref(new Setting(){

View File

@@ -1,6 +1,7 @@
package mindustry.ui.dialogs; package mindustry.ui.dialogs;
import arc.*; import arc.*;
import arc.scene.ui.layout.Stack;
import arc.struct.*; import arc.struct.*;
import arc.graphics.*; import arc.graphics.*;
import arc.graphics.g2d.*; import arc.graphics.g2d.*;
@@ -25,6 +26,8 @@ import mindustry.ui.Cicon;
import mindustry.ui.layout.*; import mindustry.ui.layout.*;
import mindustry.ui.layout.TreeLayout.*; import mindustry.ui.layout.TreeLayout.*;
import java.util.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
public class TechTreeDialog extends FloatingDialog{ public class TechTreeDialog extends FloatingDialog{
@@ -110,9 +113,25 @@ public class TechTreeDialog extends FloatingDialog{
} }
void treeLayout(){ void treeLayout(){
RadialTreeLayout layout = new RadialTreeLayout(); float spacing = 20f;
LayoutNode node = new LayoutNode(root, null); LayoutNode node = new LayoutNode(root, null);
layout.layout(node); LayoutNode[] children = node.children;
LayoutNode[] leftHalf = Arrays.copyOfRange(node.children, 0, Mathf.ceil(node.children.length/2f));
LayoutNode[] rightHalf = Arrays.copyOfRange(node.children, Mathf.ceil(node.children.length/2f), node.children.length);
node.children = leftHalf;
new BranchTreeLayout(){{
gapBetweenLevels = gapBetweenNodes = spacing;
rootLocation = TreeLocation.top;
}}.layout(node);
node.children = rightHalf;
new BranchTreeLayout(){{
gapBetweenLevels = gapBetweenNodes = spacing;
rootLocation = TreeLocation.bottom;
}}.layout(node);
node.children = children;
float minx = 0f, miny = 0f, maxx = 0f, maxy = 0f; float minx = 0f, miny = 0f, maxx = 0f, maxy = 0f;
copyInfo(node); copyInfo(node);
@@ -252,7 +271,7 @@ public class TechTreeDialog extends FloatingDialog{
button.setPosition(node.x + panX + width / 2f, node.y + panY + height / 2f + offset, Align.center); button.setPosition(node.x + panX + width / 2f, node.y + panY + height / 2f + offset, Align.center);
button.getStyle().up = !locked(node.node) ? Tex.buttonOver : !data.hasItems(node.node.requirements) ? Tex.buttonRed : Tex.button; button.getStyle().up = !locked(node.node) ? Tex.buttonOver : !data.hasItems(node.node.requirements) ? Tex.buttonRed : Tex.button;
((TextureRegionDrawable)button.getStyle().imageUp) ((TextureRegionDrawable)button.getStyle().imageUp)
.setRegion(node.visible ? node.node.block.icon(Cicon.medium) : Core.atlas.find("icon-locked")); .setRegion(node.visible ? node.node.block.icon(Cicon.medium) : Icon.lock.getRegion());
button.getImage().setColor(!locked(node.node) ? Color.white : Color.gray); button.getImage().setColor(!locked(node.node) ? Color.white : Color.gray);
}); });
addChild(button); addChild(button);
@@ -358,7 +377,7 @@ public class TechTreeDialog extends FloatingDialog{
infoTable.row(); infoTable.row();
if(node.block.description != null){ if(node.block.description != null){
infoTable.table(t -> t.margin(3f).left().labelWrap(node.block.description).color(Color.lightGray).growX()).fillX(); infoTable.table(t -> t.margin(3f).left().labelWrap(node.block.displayDescription()).color(Color.lightGray).growX()).fillX();
} }
addChild(infoTable); addChild(infoTable);
@@ -378,7 +397,12 @@ public class TechTreeDialog extends FloatingDialog{
Lines.stroke(Scl.scl(4f), locked(node.node) || locked(child.node) ? Pal.gray : Pal.accent); Lines.stroke(Scl.scl(4f), locked(node.node) || locked(child.node) ? Pal.gray : Pal.accent);
Draw.alpha(parentAlpha); Draw.alpha(parentAlpha);
Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY); if(Mathf.equal(Math.abs(node.y - child.y), Math.abs(node.x - child.x), 1f) && Mathf.dstm(node.x, node.y, child.x, child.y) <= node.width*3){
Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY);
}else{
Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, node.y + offsetY);
Lines.line(child.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY);
}
} }
} }

View File

@@ -75,7 +75,7 @@ public class HudFragment extends Fragment{
} }
}).name("pause").update(i -> { }).name("pause").update(i -> {
if(net.active()){ if(net.active()){
i.getStyle().imageUp = Icon.user; i.getStyle().imageUp = Icon.players;
}else{ }else{
i.setDisabled(false); i.setDisabled(false);
i.getStyle().imageUp = state.is(State.paused) ? Icon.play : Icon.pause; i.getStyle().imageUp = state.is(State.paused) ? Icon.play : Icon.pause;
@@ -256,7 +256,7 @@ public class HudFragment extends Fragment{
t.add(new Minimap()); t.add(new Minimap());
t.row(); t.row();
//position //position
t.label(() -> world.toTile(player.x) + "," + world.toTile(player.y)).style(Styles.outlineLabel) t.label(() -> world.toTile(player.x) + "," + world.toTile(player.y))
.visible(() -> Core.settings.getBool("position") && !state.rules.tutorial); .visible(() -> Core.settings.getBool("position") && !state.rules.tutorial);
t.top().right(); t.top().right();
}); });
@@ -352,7 +352,7 @@ public class HudFragment extends Fragment{
} }
@Remote(targets = Loc.both, called = Loc.server) @Remote(targets = Loc.both, called = Loc.server)
public static void spawnUnitEditor(Player player, UnitDef type){ public static void spawnUnitEditor(Player player, UnitType type){
if(state.isEditor()){ if(state.isEditor()){
BaseUnit unit = type.create(player.getTeam()); BaseUnit unit = type.create(player.getTeam());
unit.set(player.x, player.y); unit.set(player.x, player.y);

View File

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

View File

@@ -31,11 +31,13 @@ public class PlacementFragment extends Fragment{
Array<Block> returnArray = new Array<>(); Array<Block> returnArray = new Array<>();
Array<Category> returnCatArray = new Array<>(); Array<Category> returnCatArray = new Array<>();
boolean[] categoryEmpty = new boolean[Category.all.length]; boolean[] categoryEmpty = new boolean[Category.all.length];
ObjectMap<Category,Block> selectedBlocks = new ObjectMap<Category,Block>(); ObjectMap<Category,Block> selectedBlocks = new ObjectMap<>();
ObjectFloatMap<Category> scrollPositions = new ObjectFloatMap<>();
Block hovered, lastDisplay; Block hovered, lastDisplay;
Tile lastHover; Tile lastHover;
Tile hoverTile; Tile hoverTile;
Table blockTable, toggler, topTable; Table blockTable, toggler, topTable;
ScrollPane blockPane;
boolean lastGround; boolean lastGround;
boolean blockSelectEnd; boolean blockSelectEnd;
int blockSelectSeq; int blockSelectSeq;
@@ -86,6 +88,8 @@ public class PlacementFragment extends Fragment{
} }
boolean gridUpdate(InputHandler input){ boolean gridUpdate(InputHandler input){
scrollPositions.put(currentCategory, blockPane.getScrollY());
if(Core.input.keyDown(Binding.pick)){ //mouse eyedropper select if(Core.input.keyDown(Binding.pick)){ //mouse eyedropper select
Tile tile = world.ltileWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y); Tile tile = world.ltileWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y);
Block tryRecipe = tile == null ? null : tile.block(); Block tryRecipe = tile == null ? null : tile.block();
@@ -240,6 +244,12 @@ public class PlacementFragment extends Fragment{
} }
} }
blockTable.act(0f); blockTable.act(0f);
blockPane.setScrollYForce(scrollPositions.get(currentCategory, 0));
Core.app.post(() -> {
blockPane.setScrollYForce(scrollPositions.get(currentCategory, 0));
blockPane.act(0f);
blockPane.layout();
});
}; };
//top table with hover info //top table with hover info
@@ -343,14 +353,15 @@ public class PlacementFragment extends Fragment{
frame.row(); frame.row();
frame.table(Tex.pane2, blocksSelect -> { frame.table(Tex.pane2, blocksSelect -> {
blocksSelect.margin(4).marginTop(0); blocksSelect.margin(4).marginTop(0);
blocksSelect.pane(blocks -> blockTable = blocks).height(194f).update(pane -> { blockPane = blocksSelect.pane(blocks -> blockTable = blocks).height(194f).update(pane -> {
if(pane.hasScroll()){ if(pane.hasScroll()){
Element result = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true); Element result = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true);
if(result == null || !result.isDescendantOf(pane)){ if(result == null || !result.isDescendantOf(pane)){
Core.scene.setScrollFocus(null); Core.scene.setScrollFocus(null);
} }
} }
}).grow().get().setStyle(Styles.smallPane); }).grow().get();
blockPane.setStyle(Styles.smallPane);
blocksSelect.row(); blocksSelect.row();
blocksSelect.table(control.input::buildPlacementUI).name("inputTable").growX(); blocksSelect.table(control.input::buildPlacementUI).name("inputTable").growX();
}).fillY().bottom().touchable(Touchable.enabled); }).fillY().bottom().touchable(Touchable.enabled);

View File

@@ -148,8 +148,7 @@ public class BranchTreeLayout implements TreeLayout{
wPlus.mode = wPlus.mode + shift; wPlus.mode = wPlus.mode + shift;
} }
private TreeNode apportion(TreeNode v, TreeNode defaultAncestor, private TreeNode apportion(TreeNode v, TreeNode defaultAncestor, TreeNode leftSibling, TreeNode parentOfV){
TreeNode leftSibling, TreeNode parentOfV){
if(leftSibling == null){ if(leftSibling == null){
return defaultAncestor; return defaultAncestor;
} }

View File

@@ -12,7 +12,7 @@ public class RadialTreeLayout implements TreeLayout{
@Override @Override
public void layout(TreeNode root){ public void layout(TreeNode root){
startRadius = root.height * 2.4f; startRadius = root.height * 2.4f;
delta = root.height * 2.4f; delta = root.height * 20.4f;
bfs(root, true); bfs(root, true);

View File

@@ -0,0 +1,36 @@
package mindustry.ui.layout;
import arc.struct.*;
public class RowTreeLayout implements TreeLayout{
@Override
public void layout(TreeNode root){
layout(root, 0, new IntArray());
/*
def minimum_ws(tree, depth=0):
tree.x = nexts[depth]
tree.y = depth
nexts[depth] += 1
for c in tree.children:
minimum_ws(tree, c)
*/
}
void layout(TreeNode node, int depth, IntArray nexts){
float size = node.height * 5f;
if(nexts.size < depth + 1){
nexts.ensureCapacity(depth + 1);
nexts.size = depth + 1;
}
node.x = size * nexts.get(depth);
node.y = size * depth;
nexts.incr(depth, 1);
for(TreeNode child : node.children){
layout(child, depth + 1, nexts);
}
}
}

View File

@@ -274,8 +274,7 @@ public abstract class BlockStorage extends UnlockableContent{
/** Try offloading an item to a nearby container in its facing direction. Returns true if success. */ /** Try offloading an item to a nearby container in its facing direction. Returns true if success. */
public boolean offloadDir(Tile tile, Item item){ public boolean offloadDir(Tile tile, Item item){
Tile other = tile.getNearby(tile.rotation()); Tile other = tile.front();
if(other != null) other = other.link();
if(other != null && other.getTeam() == tile.getTeam() && other.block().acceptItem(item, other, tile)){ if(other != null && other.getTeam() == tile.getTeam() && other.block().acceptItem(item, other, tile)){
other.block().handleItem(item, other, tile); other.block().handleItem(item, other, tile);
return true; return true;

View File

@@ -57,8 +57,8 @@ public class BuildBlock extends Block{
public static void onDeconstructFinish(Tile tile, Block block, int builderID){ public static void onDeconstructFinish(Tile tile, Block block, int builderID){
Team team = tile.getTeam(); Team team = tile.getTeam();
Effects.effect(Fx.breakBlock, tile.drawx(), tile.drawy(), block.size); Effects.effect(Fx.breakBlock, tile.drawx(), tile.drawy(), block.size);
tile.remove();
Events.fire(new BlockBuildEndEvent(tile, playerGroup.getByID(builderID), team, true)); Events.fire(new BlockBuildEndEvent(tile, playerGroup.getByID(builderID), team, true));
tile.remove();
if(shouldPlay()) Sounds.breaks.at(tile, calcPitch(false)); if(shouldPlay()) Sounds.breaks.at(tile, calcPitch(false));
} }

View File

@@ -52,6 +52,10 @@ public class Floor extends Block{
public Effect updateEffect = Fx.none; public Effect updateEffect = Fx.none;
/** Array of affinities to certain things. */ /** Array of affinities to certain things. */
public Attributes attributes = new Attributes(); public Attributes attributes = new Attributes();
/** Whether this ore generates in maps by default. */
public boolean oreDefault = false;
/** Ore generation params. */
public float oreScale = 24f, oreThreshold = 0.828f;
protected TextureRegion[][] edges; protected TextureRegion[][] edges;
protected byte eq = 0; protected byte eq = 0;

View File

@@ -1,11 +1,12 @@
package mindustry.world.blocks.distribution; package mindustry.world.blocks.distribution;
import arc.*; import arc.*;
import arc.struct.*;
import arc.func.*; import arc.func.*;
import arc.graphics.g2d.*; import arc.graphics.g2d.*;
import arc.math.*; import arc.math.*;
import arc.math.geom.*; import arc.math.geom.*;
import arc.struct.*;
import arc.util.ArcAnnotate.*;
import arc.util.*; import arc.util.*;
import mindustry.content.*; import mindustry.content.*;
import mindustry.entities.traits.BuilderTrait.*; import mindustry.entities.traits.BuilderTrait.*;
@@ -24,10 +25,8 @@ import static mindustry.Vars.*;
public class Conveyor extends Block implements Autotiler{ public class Conveyor extends Block implements Autotiler{
private static final float itemSpace = 0.4f; private static final float itemSpace = 0.4f;
private static final float minmove = 1f / (Short.MAX_VALUE - 2); private static final int capacity = 4;
private static ItemPos drawpos = new ItemPos();
private static ItemPos pos1 = new ItemPos();
private static ItemPos pos2 = new ItemPos();
private final Vec2 tr1 = new Vec2(); private final Vec2 tr1 = new Vec2();
private final Vec2 tr2 = new Vec2(); private final Vec2 tr2 = new Vec2();
private TextureRegion[][] regions = new TextureRegion[7][4]; private TextureRegion[][] regions = new TextureRegion[7][4];
@@ -51,12 +50,6 @@ public class Conveyor extends Block implements Autotiler{
unloadable = false; unloadable = false;
} }
private static int compareItems(long a, long b){
pos1.set(a, ItemPos.packShorts);
pos2.set(b, ItemPos.packShorts);
return Float.compare(pos1.y, pos2.y);
}
@Override @Override
public void setStats(){ public void setStats(){
super.setStats(); super.setStats();
@@ -100,6 +93,12 @@ public class Conveyor extends Block implements Autotiler{
entity.blendbits = bits[0]; entity.blendbits = bits[0];
entity.blendsclx = bits[1]; entity.blendsclx = bits[1];
entity.blendscly = bits[2]; entity.blendscly = bits[2];
if(tile.front() != null && tile.front().entity != null){
entity.next = tile.front().entity;
entity.nextc = entity.next instanceof ConveyorEntity && entity.next.getTeam() == tile.getTeam() ? (ConveyorEntity)entity.next : null;
entity.aligned = entity.nextc != null && tile.rotation() == entity.next.tile.rotation();
}
} }
@Override @Override
@@ -124,27 +123,17 @@ public class Conveyor extends Block implements Autotiler{
@Override @Override
public void drawLayer(Tile tile){ public void drawLayer(Tile tile){
ConveyorEntity entity = tile.ent(); ConveyorEntity e = tile.ent();
byte rotation = tile.rotation(); byte rotation = tile.rotation();
try{ for(int i = 0; i < e.len; i++){
Item item = e.ids[i];
tr1.trns(rotation * 90, tilesize, 0);
tr2.trns(rotation * 90, -tilesize / 2f, e.xs[i] * tilesize / 2f);
for(int i = 0; i < entity.convey.size; i++){ Draw.rect(item.icon(Cicon.medium),
ItemPos pos = drawpos.set(entity.convey.get(i), ItemPos.drawShorts); (tile.x * tilesize + tr1.x * e.ys[i] + tr2.x),
(tile.y * tilesize + tr1.y * e.ys[i] + tr2.y), itemSize, itemSize);
if(pos.item == null) continue;
tr1.trns(rotation * 90, tilesize, 0);
tr2.trns(rotation * 90, -tilesize / 2f, pos.x * tilesize / 2f);
Draw.rect(pos.item.icon(Cicon.medium),
(tile.x * tilesize + tr1.x * pos.y + tr2.x),
(tile.y * tilesize + tr1.y * pos.y + tr2.y), itemSize, itemSize);
}
}catch(IndexOutOfBoundsException e){
Log.err(e);
} }
} }
@@ -173,79 +162,56 @@ public class Conveyor extends Block implements Autotiler{
if(Math.abs(tile.worldx() - unit.x) < 1f) centerx = 0f; if(Math.abs(tile.worldx() - unit.x) < 1f) centerx = 0f;
} }
if(entity.convey.size * itemSpace < 0.9f){ if(entity.len * itemSpace < 0.9f){
unit.applyImpulse((tx * speed + centerx) * entity.delta(), (ty * speed + centery) * entity.delta()); unit.applyImpulse((tx * speed + centerx) * entity.delta(), (ty * speed + centery) * entity.delta());
} }
} }
@Override @Override
public void update(Tile tile){ public void update(Tile tile){
ConveyorEntity entity = tile.ent(); ConveyorEntity e = tile.ent();
entity.minitem = 1f; e.minitem = 1f;
Tile next = tile.getNearby(tile.rotation()); e.mid = 0;
if(next != null) next = next.link();
float nextMax = next != null && next.block() instanceof Conveyor && next.block().acceptItem(null, next, tile) ? 1f - Math.max(itemSpace - next.<ConveyorEntity>ent().minitem, 0) : 1f; //skip updates if possible
int minremove = Integer.MAX_VALUE; if(e.len == 0){
e.clogHeat = 0f;
e.sleep();
return;
}
for(int i = entity.convey.size - 1; i >= 0; i--){ float nextMax = e.nextc != null && tile.rotation() == e.nextc.tile.rotation() ? 1f - Math.max(itemSpace - e.nextc.minitem, 0) : 1f;
long value = entity.convey.get(i);
ItemPos pos = pos1.set(value, ItemPos.updateShorts);
//..this should never happen, but in case it does, remove it and stop here for(int i = e.len - 1; i >= 0; i--){
if(pos.item == null){ float nextpos = (i == e.len - 1 ? 100f : e.ys[i + 1]) - itemSpace;
entity.convey.removeValue(value); float maxmove = Mathf.clamp(nextpos - e.ys[i], 0, speed * e.delta());
break;
}
float nextpos = (i == entity.convey.size - 1 ? 100f : pos2.set(entity.convey.get(i + 1), ItemPos.updateShorts).y) - itemSpace; e.ys[i] += maxmove;
float maxmove = Math.min(nextpos - pos.y, speed * entity.delta());
if(maxmove > minmove){ if(e.ys[i] > nextMax) e.ys[i] = nextMax;
pos.y += maxmove; if(e.ys[i] > 0.5 && i > 0) e.mid = i - 1;
if(Mathf.equal(pos.x, 0, 0.1f)){ e.xs[i] = Mathf.approachDelta(e.xs[i], 0, 0.1f);
pos.x = 0f;
if(e.ys[i] >= 1f && offloadDir(tile, e.ids[i])){
//align X position if passing forwards
if(e.aligned){
e.nextc.xs[e.nextc.lastInserted] = e.xs[i];
} }
pos.x = Mathf.lerpDelta(pos.x, 0, 0.1f); //remove last item
} e.items.remove(e.ids[i], e.len - i);
e.len = Math.min(i, e.len);
pos.y = Mathf.clamp(pos.y, 0, nextMax); }else if(e.ys[i] < e.minitem){
e.minitem = e.ys[i];
if(pos.y >= 0.9999f && offloadDir(tile, pos.item)){
if(next != null && next.block() instanceof Conveyor){
ConveyorEntity othere = next.ent();
ItemPos ni = pos2.set(othere.convey.get(othere.lastInserted), ItemPos.updateShorts);
if(next.rotation() == tile.rotation()){
ni.x = pos.x;
}
othere.convey.set(othere.lastInserted, ni.pack());
}
minremove = Math.min(i, minremove);
tile.entity.items.remove(pos.item, 1);
}else{
value = pos.pack();
if(pos.y < entity.minitem)
entity.minitem = pos.y;
entity.convey.set(i, value);
} }
} }
if(entity.minitem < itemSpace){ if(e.minitem < itemSpace + (e.blendbits == 1 ? 0.5f : 0f)){
entity.clogHeat = Mathf.lerpDelta(entity.clogHeat, 1f, 0.02f); e.clogHeat = Mathf.lerpDelta(e.clogHeat, 1f, 0.02f);
}else{ }else{
entity.clogHeat = Mathf.lerpDelta(entity.clogHeat, 0f, 1f); e.clogHeat = 0f;
} }
if(entity.items.total() == 0){ e.noSleep();
entity.sleep();
}else{
entity.noSleep();
}
if(minremove != Integer.MAX_VALUE) entity.convey.truncate(minremove);
} }
@Override @Override
@@ -265,22 +231,22 @@ public class Conveyor extends Block implements Autotiler{
@Override @Override
public int removeStack(Tile tile, Item item, int amount){ public int removeStack(Tile tile, Item item, int amount){
ConveyorEntity entity = tile.ent(); ConveyorEntity e = tile.ent();
entity.noSleep(); e.noSleep();
int removed = 0; int removed = 0;
for(int j = 0; j < amount; j++){ for(int j = 0; j < amount; j++){
for(int i = 0; i < entity.convey.size; i++){ for(int i = 0; i < e.len; i++){
long val = entity.convey.get(i); if(e.ids[i] == item){
ItemPos pos = pos1.set(val, ItemPos.drawShorts); e.remove(i);
if(pos.item == item){ removed ++;
entity.convey.removeValue(val);
entity.items.remove(item, 1);
removed++;
break; break;
} }
} }
} }
e.items.remove(item, removed);
return removed; return removed;
} }
@@ -297,58 +263,66 @@ public class Conveyor extends Block implements Autotiler{
@Override @Override
public void handleStack(Item item, int amount, Tile tile, Unit source){ public void handleStack(Item item, int amount, Tile tile, Unit source){
ConveyorEntity entity = tile.ent(); ConveyorEntity e = tile.ent();
for(int i = amount - 1; i >= 0; i--){ for(int i = amount - 1; i >= 0; i--){
long result = ItemPos.packItem(item, 0f, i * itemSpace); e.add(0);
entity.convey.insert(0, result); e.xs[0] = 0;
entity.items.add(item, 1); e.ys[0] = i * itemSpace;
e.ids[0] = item;
e.items.add(item, 1);
} }
entity.noSleep(); e.noSleep();
} }
@Override @Override
public boolean acceptItem(Item item, Tile tile, Tile source){ public boolean acceptItem(Item item, Tile tile, Tile source){
ConveyorEntity e = tile.ent();
if(e.len >= capacity) return false;
int direction = source == null ? 0 : Math.abs(source.relativeTo(tile.x, tile.y) - tile.rotation()); int direction = source == null ? 0 : Math.abs(source.relativeTo(tile.x, tile.y) - tile.rotation());
float minitem = tile.<ConveyorEntity>ent().minitem; return (((direction == 0) && e.minitem >= itemSpace) || ((direction % 2 == 1) && e.minitem > 0.5f)) && (source == null || !(source.block().rotate && (source.rotation() + 2) % 4 == tile.rotation()));
return (((direction == 0) && minitem > itemSpace) ||
((direction % 2 == 1) && minitem > 0.52f)) && (source == null || !(source.block().rotate && (source.rotation() + 2) % 4 == tile.rotation()));
} }
@Override @Override
public void handleItem(Item item, Tile tile, Tile source){ public void handleItem(Item item, Tile tile, Tile source){
byte rotation = tile.rotation(); ConveyorEntity e = tile.ent();
if(e.len >= capacity) return;
int ch = Math.abs(source.relativeTo(tile.x, tile.y) - rotation); byte r = tile.rotation();
int ang = ((source.relativeTo(tile.x, tile.y) - rotation)); int ang = ((source.relativeTo(tile.x, tile.y) - r));
float x = (ang == -1 || ang == 3) ? 1 : (ang == 1 || ang == -3) ? -1 : 0;
float pos = ch == 0 ? 0 : ch % 2 == 1 ? 0.5f : 1f; e.noSleep();
float y = (ang == -1 || ang == 3) ? 1 : (ang == 1 || ang == -3) ? -1 : 0; e.items.add(item, 1);
ConveyorEntity entity = tile.ent(); if(Math.abs(source.relativeTo(tile.x, tile.y) - r) == 0){ //idx = 0
entity.noSleep(); e.add(0);
long result = ItemPos.packItem(item, y * 0.9f, pos); e.xs[0] = x;
e.ys[0] = 0;
tile.entity.items.add(item, 1); e.ids[0] = item;
}else{ //idx = mid
for(int i = 0; i < entity.convey.size; i++){ e.add(e.mid);
if(compareItems(result, entity.convey.get(i)) < 0){ e.xs[e.mid] = x;
entity.convey.insert(i, result); e.ys[e.mid] = 0.5f;
entity.lastInserted = (byte)i; e.ids[e.mid] = item;
return;
}
} }
//this item must be greater than anything there...
entity.convey.add(result);
entity.lastInserted = (byte)(entity.convey.size - 1);
} }
public static class ConveyorEntity extends TileEntity{ public static class ConveyorEntity extends TileEntity{
//parallel array data
Item[] ids = new Item[capacity];
float[] xs = new float[capacity];
float[] ys = new float[capacity];
//amount of items, always < capacity
int len = 0;
//next entity
@Nullable TileEntity next;
@Nullable ConveyorEntity nextc;
//whether the next conveyor's rotation == tile rotation
boolean aligned;
LongArray convey = new LongArray(); int lastInserted, mid;
byte lastInserted;
float minitem = 1; float minitem = 1;
int blendbits; int blendbits;
@@ -356,96 +330,53 @@ public class Conveyor extends Block implements Autotiler{
float clogHeat = 0f; float clogHeat = 0f;
final void add(int o){
for(int i = Math.max(o + 1, len); i > o; i--){
ids[i] = ids[i - 1];
xs[i] = xs[i - 1];
ys[i] = ys[i - 1];
}
len++;
}
final void remove(int o){
for(int i = o; i < len - 1; i++){
ids[i] = ids[i + 1];
xs[i] = xs[i + 1];
ys[i] = ys[i + 1];
}
len--;
}
@Override @Override
public void write(DataOutput stream) throws IOException{ public void write(DataOutput stream) throws IOException{
super.write(stream); super.write(stream);
stream.writeInt(convey.size); stream.writeInt(len);
for(int i = 0; i < convey.size; i++){ for(int i = 0; i < len; i++){
stream.writeInt(ItemPos.toInt(convey.get(i))); stream.writeInt(Pack.intBytes((byte)ids[i].id, (byte)(xs[i] * 127), (byte)(ys[i] * 255 - 128), (byte)0));
} }
} }
@Override @Override
public void read(DataInput stream, byte revision) throws IOException{ public void read(DataInput stream, byte revision) throws IOException{
super.read(stream, revision); super.read(stream, revision);
convey.clear();
int amount = stream.readInt(); int amount = stream.readInt();
convey.ensureCapacity(Math.min(amount, 10)); len = Math.min(amount, capacity);
for(int i = 0; i < amount; i++){ for(int i = 0; i < amount; i++){
convey.add(ItemPos.toLong(stream.readInt())); int val = stream.readInt();
byte id = (byte)(val >> 24);
float x = (float)((byte)(val >> 16)) / 127f;
float y = ((float)((byte)(val >> 8)) + 128f) / 255f;
if(i < capacity){
ids[i] = content.item(id);
xs[i] = x;
ys[i] = y;
}
} }
} }
} }
//Container class. Do not instantiate.
static class ItemPos{
private static short[] writeShort = new short[4];
private static byte[] writeByte = new byte[4];
private static short[] packShorts = new short[4];
private static short[] drawShorts = new short[4];
private static short[] updateShorts = new short[4];
Item item;
float x, y;
private ItemPos(){
}
static long packItem(Item item, float x, float y){
short[] shorts = packShorts;
shorts[0] = (short)item.id;
shorts[1] = (short)(x * Short.MAX_VALUE);
shorts[2] = (short)((y - 1f) * Short.MAX_VALUE);
return Pack.longShorts(shorts);
}
static int toInt(long value){
short[] values = Pack.shorts(value, writeShort);
short itemid = values[0];
float x = values[1] / (float)Short.MAX_VALUE;
float y = ((float)values[2]) / Short.MAX_VALUE + 1f;
byte[] bytes = writeByte;
bytes[0] = (byte)itemid;
bytes[1] = (byte)(x * 127);
bytes[2] = (byte)(y * 255 - 128);
return Pack.intBytes(bytes);
}
static long toLong(int value){
byte[] values = Pack.bytes(value, writeByte);
short itemid = content.item(values[0]).id;
float x = values[1] / 127f;
float y = ((int)values[2] + 128) / 255f;
short[] shorts = writeShort;
shorts[0] = itemid;
shorts[1] = (short)(x * Short.MAX_VALUE);
shorts[2] = (short)((y - 1f) * Short.MAX_VALUE);
return Pack.longShorts(shorts);
}
ItemPos set(long lvalue, short[] values){
Pack.shorts(lvalue, values);
if(values[0] >= content.items().size || values[0] < 0)
item = null;
else
item = content.items().get(values[0]);
x = values[1] / (float)Short.MAX_VALUE;
y = ((float)values[2]) / Short.MAX_VALUE + 1f;
return this;
}
long pack(){
return packItem(item, x, y);
}
}
} }

View File

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

View File

@@ -11,6 +11,7 @@ import java.io.*;
public class OverflowGate extends Block{ public class OverflowGate extends Block{
public float speed = 1f; public float speed = 1f;
public boolean invert = false;
public OverflowGate(String name){ public OverflowGate(String name){
super(name); super(name);
@@ -72,23 +73,26 @@ public class OverflowGate extends Block{
entity.lastItem = item; entity.lastItem = item;
entity.time = 0f; entity.time = 0f;
entity.lastInput = source; entity.lastInput = source;
update(tile);
} }
Tile getTileTarget(Tile tile, Item item, Tile src, boolean flip){ public Tile getTileTarget(Tile tile, Item item, Tile src, boolean flip){
int from = tile.relativeTo(src.x, src.y); int from = tile.relativeTo(src.x, src.y);
if(from == -1) return null; if(from == -1) return null;
Tile to = tile.getNearby((from + 2) % 4); Tile to = tile.getNearby((from + 2) % 4);
if(to == null) return null; if(to == null) return null;
Tile edge = Edges.getFacingEdge(tile, to); Tile edge = Edges.getFacingEdge(tile, to);
boolean canForward = to.block().acceptItem(item, to, edge) && to.getTeam() == tile.getTeam() && !(to.block() instanceof OverflowGate);
if(!to.block().acceptItem(item, to, edge) || to.getTeam() != tile.getTeam() || (to.block() instanceof OverflowGate)){ if(!canForward || invert){
Tile a = tile.getNearby(Mathf.mod(from - 1, 4)); Tile a = tile.getNearby(Mathf.mod(from - 1, 4));
Tile b = tile.getNearby(Mathf.mod(from + 1, 4)); Tile b = tile.getNearby(Mathf.mod(from + 1, 4));
boolean ac = a != null && a.block().acceptItem(item, a, edge) && !(a.block() instanceof OverflowGate) && a.getTeam() == tile.getTeam(); boolean ac = a != null && a.block().acceptItem(item, a, edge) && !(a.block() instanceof OverflowGate) && a.getTeam() == tile.getTeam();
boolean bc = b != null && b.block().acceptItem(item, b, edge) && !(b.block() instanceof OverflowGate) && b.getTeam() == tile.getTeam(); boolean bc = b != null && b.block().acceptItem(item, b, edge) && !(b.block() instanceof OverflowGate) && b.getTeam() == tile.getTeam();
if(!ac && !bc){ if(!ac && !bc){
return null; return invert && canForward ? to : null;
} }
if(ac && !bc){ if(ac && !bc){

View File

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

View File

@@ -13,11 +13,19 @@ import static mindustry.Vars.renderer;
public class ThermalGenerator extends PowerGenerator{ public class ThermalGenerator extends PowerGenerator{
public Effect generateEffect = Fx.none; public Effect generateEffect = Fx.none;
public Attribute attribute = Attribute.heat;
public ThermalGenerator(String name){ public ThermalGenerator(String name){
super(name); super(name);
} }
@Override
public void setStats(){
super.setStats();
stats.add(BlockStat.tiles, attribute);
}
@Override @Override
public void update(Tile tile){ public void update(Tile tile){
GeneratorEntity entity = tile.ent(); GeneratorEntity entity = tile.ent();
@@ -29,7 +37,7 @@ public class ThermalGenerator extends PowerGenerator{
@Override @Override
public void drawPlace(int x, int y, int rotation, boolean valid){ public void drawPlace(int x, int y, int rotation, boolean valid){
drawPlaceText(Core.bundle.formatFloat("bar.efficiency", sumAttribute(Attribute.heat, x, y) * 100, 1), x, y, valid); drawPlaceText(Core.bundle.formatFloat("bar.efficiency", sumAttribute(attribute, x, y) * 100, 1), x, y, valid);
} }
@Override @Override
@@ -43,7 +51,7 @@ public class ThermalGenerator extends PowerGenerator{
super.onProximityAdded(tile); super.onProximityAdded(tile);
GeneratorEntity entity = tile.ent(); GeneratorEntity entity = tile.ent();
entity.productionEfficiency = sumAttribute(Attribute.heat, tile.x, tile.y); entity.productionEfficiency = sumAttribute(attribute, tile.x, tile.y);
} }
@Override @Override
@@ -56,6 +64,6 @@ public class ThermalGenerator extends PowerGenerator{
@Override @Override
public boolean canPlaceOn(Tile tile){ public boolean canPlaceOn(Tile tile){
//make sure there's heat at this location //make sure there's heat at this location
return tile.getLinkedTilesAs(this, tempTiles).sumf(other -> other.floor().attributes.get(Attribute.heat)) > 0.01f; return tile.getLinkedTilesAs(this, tempTiles).sumf(other -> other.floor().attributes.get(attribute)) > 0.01f;
} }
} }

View File

@@ -1,17 +1,16 @@
package mindustry.world.blocks.production; package mindustry.world.blocks.production;
import arc.Core; import arc.*;
import arc.graphics.Color; import arc.graphics.*;
import arc.graphics.g2d.*; import arc.graphics.g2d.*;
import arc.math.Mathf; import arc.math.*;
import arc.math.Rand; import arc.util.*;
import arc.util.Time; import mindustry.content.*;
import mindustry.content.Fx; import mindustry.entities.type.*;
import mindustry.entities.type.TileEntity; import mindustry.graphics.*;
import mindustry.graphics.Pal; import mindustry.ui.*;
import mindustry.ui.Bar; import mindustry.world.*;
import mindustry.world.Tile; import mindustry.world.meta.*;
import mindustry.world.meta.Attribute;
import java.io.*; import java.io.*;
@@ -57,6 +56,13 @@ public class Cultivator extends GenericCrafter{
() -> ((CultivatorEntity)entity).warmup)); () -> ((CultivatorEntity)entity).warmup));
} }
@Override
public void setStats(){
super.setStats();
stats.add(BlockStat.affinities, attribute);
}
@Override @Override
public void drawPlace(int x, int y, int rotation, boolean valid){ public void drawPlace(int x, int y, int rotation, boolean valid){
drawPlaceText(Core.bundle.formatFloat("bar.efficiency", (1 + sumAttribute(attribute, x, y)) * 100, 1), x, y, valid); drawPlaceText(Core.bundle.formatFloat("bar.efficiency", (1 + sumAttribute(attribute, x, y)) * 100, 1), x, y, valid);

View File

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

View File

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

View File

@@ -99,7 +99,7 @@ public class CoreBlock extends StorageBlock{
for(TileEntity other : state.teams.cores(tile.getTeam())){ for(TileEntity other : state.teams.cores(tile.getTeam())){
if(other.tile == tile) continue; if(other.tile == tile) continue;
entity.storageCapacity += other.block.itemCapacity + entity.proximity().sum(e -> isContainer(e) ? e.block().itemCapacity : 0); entity.storageCapacity += other.block.itemCapacity + other.proximity().sum(e -> isContainer(e) ? e.block().itemCapacity : 0);
} }
if(!world.isGenerating()){ if(!world.isGenerating()){

Some files were not shown because too many files have changed in this diff Show More