Fuse with conveyor optimization
# Conflicts: # core/src/mindustry/world/blocks/distribution/ItemConveyor.java
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -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
25
SERVERLIST.md
Normal 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 aproppriate MOTD, name and description.** This is set with `config <name/desc/motd> <value>`. "Aproppriate" 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.
|
||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package mindustry.annotations;
|
|||||||
import javax.annotation.processing.*;
|
import javax.annotation.processing.*;
|
||||||
import javax.lang.model.*;
|
import javax.lang.model.*;
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
|
import javax.lang.model.util.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
||||||
@@ -10,20 +11,34 @@ public abstract class BaseProcessor extends AbstractProcessor{
|
|||||||
/** Name of the base package to put all the generated classes. */
|
/** Name of the base package to put all the generated classes. */
|
||||||
public static final String packageName = "mindustry.gen";
|
public static final String packageName = "mindustry.gen";
|
||||||
|
|
||||||
private int round;
|
public static Types typeu;
|
||||||
|
public static Elements elementu;
|
||||||
|
public static Filer filer;
|
||||||
|
public static Messager messager;
|
||||||
|
|
||||||
|
protected int round;
|
||||||
|
|
||||||
|
public static String getMethodName(Element element){
|
||||||
|
return ((TypeElement)element.getEnclosingElement()).getQualifiedName().toString() + "." + element.getSimpleName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isPrimitive(String type){
|
||||||
|
return type.equals("boolean") || type.equals("byte") || type.equals("short") || type.equals("int")
|
||||||
|
|| type.equals("long") || type.equals("float") || type.equals("double") || type.equals("char");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void init(ProcessingEnvironment processingEnv){
|
public synchronized void init(ProcessingEnvironment processingEnv){
|
||||||
super.init(processingEnv);
|
super.init(processingEnv);
|
||||||
//put all relevant utils into utils class
|
|
||||||
Utils.typeUtils = processingEnv.getTypeUtils();
|
typeu = processingEnv.getTypeUtils();
|
||||||
Utils.elementUtils = processingEnv.getElementUtils();
|
elementu = processingEnv.getElementUtils();
|
||||||
Utils.filer = processingEnv.getFiler();
|
filer = processingEnv.getFiler();
|
||||||
Utils.messager = processingEnv.getMessager();
|
messager = processingEnv.getMessager();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
|
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
|
||||||
if(round++ != 0) return false; //only process 1 round
|
if(round++ != 0) return false; //only process 1 round
|
||||||
try{
|
try{
|
||||||
process(roundEnv);
|
process(roundEnv);
|
||||||
@@ -39,5 +54,7 @@ public abstract class BaseProcessor extends AbstractProcessor{
|
|||||||
return SourceVersion.RELEASE_8;
|
return SourceVersion.RELEASE_8;
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void process(RoundEnvironment env) throws Exception;
|
public void process(RoundEnvironment env) throws Exception{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
package mindustry.annotations;
|
package mindustry.annotations.impl;
|
||||||
|
|
||||||
import arc.files.*;
|
import arc.files.*;
|
||||||
import arc.scene.style.*;
|
import arc.scene.style.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.serialization.*;
|
import arc.util.serialization.*;
|
||||||
import com.squareup.javapoet.*;
|
import com.squareup.javapoet.*;
|
||||||
|
import mindustry.annotations.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
|
|
||||||
import javax.annotation.processing.*;
|
import javax.annotation.processing.*;
|
||||||
@@ -20,7 +21,7 @@ public class AssetsAnnotationProcessor extends BaseProcessor{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(RoundEnvironment env) throws Exception{
|
public void process(RoundEnvironment env) throws Exception{
|
||||||
path = Fi.get(Utils.filer.createResource(StandardLocation.CLASS_OUTPUT, "no", "no")
|
path = Fi.get(BaseProcessor.filer.createResource(StandardLocation.CLASS_OUTPUT, "no", "no")
|
||||||
.toUri().toURL().toString().substring(System.getProperty("os.name").contains("Windows") ? 6 : "file:".length()))
|
.toUri().toURL().toString().substring(System.getProperty("os.name").contains("Windows") ? 6 : "file:".length()))
|
||||||
.parent().parent().parent().parent().parent().parent().toString();
|
.parent().parent().parent().parent().parent().parent().toString();
|
||||||
path = path.replace("%20", " ");
|
path = path.replace("%20", " ");
|
||||||
@@ -85,12 +86,12 @@ public class AssetsAnnotationProcessor extends BaseProcessor{
|
|||||||
}
|
}
|
||||||
|
|
||||||
ictype.addMethod(icload.build());
|
ictype.addMethod(icload.build());
|
||||||
JavaFile.builder(packageName, ichtype.build()).build().writeTo(Utils.filer);
|
JavaFile.builder(packageName, ichtype.build()).build().writeTo(BaseProcessor.filer);
|
||||||
JavaFile.builder(packageName, ictype.build()).build().writeTo(Utils.filer);
|
JavaFile.builder(packageName, ictype.build()).build().writeTo(BaseProcessor.filer);
|
||||||
|
|
||||||
type.addMethod(load.build());
|
type.addMethod(load.build());
|
||||||
type.addMethod(loadStyles.build());
|
type.addMethod(loadStyles.build());
|
||||||
JavaFile.builder(packageName, type.build()).build().writeTo(Utils.filer);
|
JavaFile.builder(packageName, type.build()).build().writeTo(BaseProcessor.filer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void processSounds(String classname, String path, String rtype) throws Exception{
|
void processSounds(String classname, String path, String rtype) throws Exception{
|
||||||
@@ -104,7 +105,7 @@ public class AssetsAnnotationProcessor extends BaseProcessor{
|
|||||||
String name = p.nameWithoutExtension();
|
String name = p.nameWithoutExtension();
|
||||||
|
|
||||||
if(names.contains(name)){
|
if(names.contains(name)){
|
||||||
Utils.messager.printMessage(Kind.ERROR, "Duplicate file name: " + p.toString() + "!");
|
BaseProcessor.messager.printMessage(Kind.ERROR, "Duplicate file name: " + p.toString() + "!");
|
||||||
}else{
|
}else{
|
||||||
names.add(name);
|
names.add(name);
|
||||||
}
|
}
|
||||||
@@ -130,7 +131,7 @@ public class AssetsAnnotationProcessor extends BaseProcessor{
|
|||||||
|
|
||||||
type.addMethod(loadBegin.build());
|
type.addMethod(loadBegin.build());
|
||||||
type.addMethod(dispose.build());
|
type.addMethod(dispose.build());
|
||||||
JavaFile.builder(packageName, type.build()).build().writeTo(Utils.filer);
|
JavaFile.builder(packageName, type.build()).build().writeTo(BaseProcessor.filer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static String capitalize(String s){
|
static String capitalize(String s){
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
package mindustry.annotations;
|
package mindustry.annotations.impl;
|
||||||
|
|
||||||
import com.squareup.javapoet.*;
|
import com.squareup.javapoet.*;
|
||||||
|
import mindustry.annotations.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.annotations.remote.*;
|
||||||
|
|
||||||
import javax.annotation.processing.*;
|
import javax.annotation.processing.*;
|
||||||
import javax.lang.model.*;
|
|
||||||
import javax.lang.model.element.Modifier;
|
import javax.lang.model.element.Modifier;
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
import javax.lang.model.util.*;
|
import javax.lang.model.util.*;
|
||||||
import javax.tools.Diagnostic.*;
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@@ -55,13 +55,13 @@ public class SerializeAnnotationProcessor extends BaseProcessor{
|
|||||||
|
|
||||||
readMethod.addStatement("$L object = new $L()", type, type);
|
readMethod.addStatement("$L object = new $L()", type, type);
|
||||||
|
|
||||||
List<VariableElement> fields = ElementFilter.fieldsIn(Utils.elementUtils.getAllMembers(elem));
|
List<VariableElement> fields = ElementFilter.fieldsIn(BaseProcessor.elementu.getAllMembers(elem));
|
||||||
for(VariableElement field : fields){
|
for(VariableElement field : fields){
|
||||||
if(field.getModifiers().contains(Modifier.STATIC) || field.getModifiers().contains(Modifier.TRANSIENT) || field.getModifiers().contains(Modifier.PRIVATE))
|
if(field.getModifiers().contains(Modifier.STATIC) || field.getModifiers().contains(Modifier.TRANSIENT) || field.getModifiers().contains(Modifier.PRIVATE))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
String name = field.getSimpleName().toString();
|
String name = field.getSimpleName().toString();
|
||||||
String typeName = Utils.typeUtils.erasure(field.asType()).toString().replace('$', '.');
|
String typeName = BaseProcessor.typeu.erasure(field.asType()).toString().replace('$', '.');
|
||||||
String capName = Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1);
|
String capName = Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1);
|
||||||
|
|
||||||
if(field.asType().getKind().isPrimitive()){
|
if(field.asType().getKind().isPrimitive()){
|
||||||
@@ -78,7 +78,7 @@ public class SerializeAnnotationProcessor extends BaseProcessor{
|
|||||||
serializer.addMethod(writeMethod.build());
|
serializer.addMethod(writeMethod.build());
|
||||||
serializer.addMethod(readMethod.build());
|
serializer.addMethod(readMethod.build());
|
||||||
|
|
||||||
method.addStatement("arc.Core.settings.setSerializer($N, $L)", Utils.elementUtils.getBinaryName(elem).toString().replace('$', '.') + ".class", serializer.build());
|
method.addStatement("arc.Core.settings.setSerializer($N, $L)", BaseProcessor.elementu.getBinaryName(elem).toString().replace('$', '.') + ".class", serializer.build());
|
||||||
|
|
||||||
name(writeMethod, "write" + simpleTypeName);
|
name(writeMethod, "write" + simpleTypeName);
|
||||||
name(readMethod, "read" + simpleTypeName);
|
name(readMethod, "read" + simpleTypeName);
|
||||||
@@ -93,7 +93,7 @@ public class SerializeAnnotationProcessor extends BaseProcessor{
|
|||||||
classBuilder.addMethod(method.build());
|
classBuilder.addMethod(method.build());
|
||||||
|
|
||||||
//write result
|
//write result
|
||||||
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(Utils.filer);
|
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(BaseProcessor.filer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void name(MethodSpec.Builder builder, String name){
|
static void name(MethodSpec.Builder builder, String name){
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
package mindustry.annotations;
|
package mindustry.annotations.impl;
|
||||||
|
|
||||||
import com.squareup.javapoet.*;
|
import com.squareup.javapoet.*;
|
||||||
|
import mindustry.annotations.*;
|
||||||
import mindustry.annotations.Annotations.Struct;
|
import mindustry.annotations.Annotations.Struct;
|
||||||
import mindustry.annotations.Annotations.StructField;
|
import mindustry.annotations.Annotations.StructField;
|
||||||
|
|
||||||
import javax.annotation.processing.*;
|
import javax.annotation.processing.*;
|
||||||
import javax.lang.model.SourceVersion;
|
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
import javax.lang.model.type.TypeKind;
|
import javax.lang.model.type.TypeKind;
|
||||||
import javax.lang.model.util.ElementFilter;
|
import javax.lang.model.util.ElementFilter;
|
||||||
@@ -29,7 +29,7 @@ public class StructAnnotationProcessor extends BaseProcessor{
|
|||||||
for(TypeElement elem : elements){
|
for(TypeElement elem : elements){
|
||||||
|
|
||||||
if(!elem.getSimpleName().toString().endsWith("Struct")){
|
if(!elem.getSimpleName().toString().endsWith("Struct")){
|
||||||
Utils.messager.printMessage(Kind.ERROR, "All classes annotated with @Struct must have their class names end in 'Struct'.", elem);
|
BaseProcessor.messager.printMessage(Kind.ERROR, "All classes annotated with @Struct must have their class names end in 'Struct'.", elem);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ public class StructAnnotationProcessor extends BaseProcessor{
|
|||||||
int structTotalSize = (structSize <= 8 ? 8 : structSize <= 16 ? 16 : structSize <= 32 ? 32 : 64);
|
int structTotalSize = (structSize <= 8 ? 8 : structSize <= 16 ? 16 : structSize <= 32 ? 32 : 64);
|
||||||
|
|
||||||
if(variables.size() == 0){
|
if(variables.size() == 0){
|
||||||
Utils.messager.printMessage(Kind.ERROR, "making a struct with no fields is utterly pointles.", elem);
|
BaseProcessor.messager.printMessage(Kind.ERROR, "making a struct with no fields is utterly pointles.", elem);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,10 +130,10 @@ public class StructAnnotationProcessor extends BaseProcessor{
|
|||||||
constructor.addStatement("return ($T)($L)", structType, cons.toString().substring(3));
|
constructor.addStatement("return ($T)($L)", structType, cons.toString().substring(3));
|
||||||
classBuilder.addMethod(constructor.build());
|
classBuilder.addMethod(constructor.build());
|
||||||
|
|
||||||
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(Utils.filer);
|
JavaFile.builder(packageName, classBuilder.build()).build().writeTo(BaseProcessor.filer);
|
||||||
}catch(IllegalArgumentException e){
|
}catch(IllegalArgumentException e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Utils.messager.printMessage(Kind.ERROR, e.getMessage(), elem);
|
BaseProcessor.messager.printMessage(Kind.ERROR, e.getMessage(), elem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package mindustry.annotations;
|
package mindustry.annotations.remote;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
@@ -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;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package mindustry.annotations;
|
package mindustry.annotations.remote;
|
||||||
|
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
|
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
package mindustry.annotations;
|
package mindustry.annotations.remote;
|
||||||
|
|
||||||
import com.squareup.javapoet.*;
|
import com.squareup.javapoet.*;
|
||||||
|
import mindustry.annotations.*;
|
||||||
import mindustry.annotations.Annotations.Loc;
|
import mindustry.annotations.Annotations.Loc;
|
||||||
import mindustry.annotations.IOFinder.ClassSerializer;
|
import mindustry.annotations.remote.IOFinder.ClassSerializer;
|
||||||
|
|
||||||
import javax.lang.model.element.*;
|
import javax.lang.model.element.*;
|
||||||
import javax.tools.Diagnostic.Kind;
|
import javax.tools.Diagnostic.Kind;
|
||||||
@@ -52,7 +53,7 @@ public class RemoteWriteGenerator{
|
|||||||
|
|
||||||
//build and write resulting class
|
//build and write resulting class
|
||||||
TypeSpec spec = classBuilder.build();
|
TypeSpec spec = classBuilder.build();
|
||||||
JavaFile.builder(packageName, spec).build().writeTo(Utils.filer);
|
JavaFile.builder(packageName, spec).build().writeTo(BaseProcessor.filer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,12 +74,12 @@ public class RemoteWriteGenerator{
|
|||||||
//validate client methods to make sure
|
//validate client methods to make sure
|
||||||
if(methodEntry.where.isClient){
|
if(methodEntry.where.isClient){
|
||||||
if(elem.getParameters().isEmpty()){
|
if(elem.getParameters().isEmpty()){
|
||||||
Utils.messager.printMessage(Kind.ERROR, "Client invoke methods must have a first parameter of type Player.", elem);
|
BaseProcessor.messager.printMessage(Kind.ERROR, "Client invoke methods must have a first parameter of type Player.", elem);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!elem.getParameters().get(0).asType().toString().equals("mindustry.entities.type.Player")){
|
if(!elem.getParameters().get(0).asType().toString().equals("mindustry.entities.type.Player")){
|
||||||
Utils.messager.printMessage(Kind.ERROR, "Client invoke methods should have a first parameter of type Player.", elem);
|
BaseProcessor.messager.printMessage(Kind.ERROR, "Client invoke methods should have a first parameter of type Player.", elem);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,7 +163,7 @@ public class RemoteWriteGenerator{
|
|||||||
method.beginControlFlow("if(mindustry.Vars.net.server())");
|
method.beginControlFlow("if(mindustry.Vars.net.server())");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Utils.isPrimitive(typeName)){ //check if it's a primitive, and if so write it
|
if(BaseProcessor.isPrimitive(typeName)){ //check if it's a primitive, and if so write it
|
||||||
if(typeName.equals("boolean")){ //booleans are special
|
if(typeName.equals("boolean")){ //booleans are special
|
||||||
method.addStatement("TEMP_BUFFER.put(" + varName + " ? (byte)1 : 0)");
|
method.addStatement("TEMP_BUFFER.put(" + varName + " ? (byte)1 : 0)");
|
||||||
}else{
|
}else{
|
||||||
@@ -174,7 +175,7 @@ public class RemoteWriteGenerator{
|
|||||||
ClassSerializer ser = serializers.get(typeName);
|
ClassSerializer ser = serializers.get(typeName);
|
||||||
|
|
||||||
if(ser == null){ //make sure a serializer exists!
|
if(ser == null){ //make sure a serializer exists!
|
||||||
Utils.messager.printMessage(Kind.ERROR, "No @WriteClass method to write class type: '" + typeName + "'", var);
|
BaseProcessor.messager.printMessage(Kind.ERROR, "No @WriteClass method to write class type: '" + typeName + "'", var);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
mindustry.annotations.RemoteMethodAnnotationProcessor
|
|
||||||
mindustry.annotations.SerializeAnnotationProcessor
|
|
||||||
mindustry.annotations.StructAnnotationProcessor
|
|
||||||
mindustry.annotations.CallSuperAnnotationProcessor
|
|
||||||
mindustry.annotations.AssetsAnnotationProcessor
|
|
||||||
40
build.gradle
40
build.gradle
@@ -132,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{
|
||||||
@@ -205,6 +219,7 @@ project(":core"){
|
|||||||
outputs.upToDateWhen{ false }
|
outputs.upToDateWhen{ false }
|
||||||
generateLocales()
|
generateLocales()
|
||||||
writeVersion()
|
writeVersion()
|
||||||
|
writeProcessors()
|
||||||
}
|
}
|
||||||
|
|
||||||
task copyChangelog{
|
task copyChangelog{
|
||||||
@@ -229,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"
|
||||||
|
|||||||
@@ -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í
|
||||||
@@ -1251,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.
|
||||||
|
|
||||||
@@ -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
|
||||||
@@ -45,7 +45,7 @@ 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
|
||||||
@@ -140,10 +140,10 @@ researched = [lightgray]{0} cercati.
|
|||||||
players = {0} giocatori online
|
players = {0} giocatori online
|
||||||
players.single = {0} giocatore 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.
|
||||||
@@ -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...
|
||||||
@@ -280,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.
|
||||||
|
|||||||
@@ -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 = Підтвердження
|
||||||
@@ -257,8 +258,8 @@ 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]Збереження…
|
||||||
@@ -271,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]не помаранчеве[] ядро до цієї мапи в редакторі.
|
||||||
@@ -286,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 = Пензлик
|
||||||
@@ -321,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 = Хвилі скопійовані.
|
||||||
@@ -336,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 = Застосувати
|
||||||
@@ -349,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 = Імпортувати мапу
|
||||||
@@ -363,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Ви впевнені, що хочете вийти?
|
||||||
@@ -371,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 = Прямокутник
|
||||||
@@ -429,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}»
|
||||||
@@ -450,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 = Зарості
|
||||||
@@ -494,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 = Керування
|
||||||
@@ -519,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 = Так
|
||||||
@@ -532,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 = Час виробництва
|
||||||
@@ -584,7 +587,7 @@ 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]шок
|
||||||
@@ -630,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 = Легка
|
||||||
@@ -647,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 = Повноекранний режим
|
||||||
@@ -666,13 +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.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 = Налаштування керування
|
||||||
@@ -700,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 = Категорія/Вибрати перший блок
|
||||||
@@ -735,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 = Хвилі
|
||||||
@@ -775,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 = Навколишнє світло
|
||||||
@@ -887,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 = Камені
|
||||||
@@ -898,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
|
||||||
@@ -930,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 = Розподілювач
|
||||||
@@ -942,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 = Енергійний вузол
|
||||||
@@ -980,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 = Розвантажувач
|
||||||
@@ -988,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 = Велика сонячна панель
|
||||||
@@ -1009,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 = Торієвий реактор
|
||||||
@@ -1024,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 = Великий стартовий майданчик
|
||||||
@@ -1063,38 +1068,38 @@ 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 = Нестабільна сполука, яка використовується в бомбах і вибухівках. Синтезується із спорових стручків та інших летких речовин. Використовувати як паливо не рекомендується.
|
||||||
@@ -1145,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Охоплює кілька плиток.
|
||||||
@@ -1159,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Перегрівається, якщо завдано занадто великої шкоди. За бажанням, можна використати теплоносій для запобігання перегріву. Для збільшення розміру щита можна використовувати фазову тканину.
|
||||||
@@ -1168,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 = Удосконалений насос. Насоси більше викачують, але потребують енергію.
|
||||||
@@ -1185,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 = Живлення акумулятора може протікати через цей блок лише в одному напрямку, але лише в тому випадку, якщо інша сторона має менше енергії.
|
||||||
@@ -1235,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Використовуйте, натиснувши, коли стоїте на ньому.
|
||||||
|
|||||||
@@ -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 = 禁用
|
||||||
@@ -531,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 = 能量/射擊
|
||||||
@@ -666,6 +669,7 @@ 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.bridgeopacity.name = 橋透明度
|
||||||
|
|||||||
Binary file not shown.
BIN
core/assets/fonts/fontello.ttf
Normal file
BIN
core/assets/fonts/fontello.ttf
Normal file
Binary file not shown.
@@ -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"]
|
||||||
@@ -678,7 +678,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();
|
||||||
|
|
||||||
|
|||||||
@@ -103,9 +103,10 @@ public class UnitTypes implements ContentList{
|
|||||||
shootSound = Sounds.explosion;
|
shootSound = Sounds.explosion;
|
||||||
bullet = new BombBulletType(2f, 3f, "clear"){{
|
bullet = new BombBulletType(2f, 3f, "clear"){{
|
||||||
hitEffect = Fx.pulverize;
|
hitEffect = Fx.pulverize;
|
||||||
lifetime = 2f;
|
lifetime = 30f;
|
||||||
speed = 1.1f;
|
speed = 1.1f;
|
||||||
splashDamageRadius = 55f;
|
splashDamageRadius = 55f;
|
||||||
|
instantDisappear = true;
|
||||||
splashDamage = 30f;
|
splashDamage = 30f;
|
||||||
killShooter = true;
|
killShooter = true;
|
||||||
}};
|
}};
|
||||||
@@ -126,7 +127,6 @@ public class UnitTypes implements ContentList{
|
|||||||
shootSound = Sounds.flame;
|
shootSound = Sounds.flame;
|
||||||
length = 1f;
|
length = 1f;
|
||||||
reload = 14f;
|
reload = 14f;
|
||||||
range = 30f;
|
|
||||||
alternate = true;
|
alternate = true;
|
||||||
recoil = 1f;
|
recoil = 1f;
|
||||||
ejectEffect = Fx.none;
|
ejectEffect = Fx.none;
|
||||||
|
|||||||
@@ -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,29 @@ 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)
|
@Remote(variants = Variant.both)
|
||||||
public static void onInfoToast(String message, float duration){
|
public static void onInfoToast(String message, float duration){
|
||||||
ui.showInfoToast(message, duration);
|
ui.showInfoToast(message, duration);
|
||||||
|
|||||||
@@ -472,7 +472,7 @@ public class NetServer implements ApplicationListener{
|
|||||||
Call.onPlayerDisconnect(player.id);
|
Call.onPlayerDisconnect(player.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.info("&lm[{1}] &lc{0} has disconnected. &lg&fi({2})", player.name, player.uuid, reason);
|
if(Config.showConnectMessages.bool()) Log.info("&lm[{1}] &lc{0} has disconnected. &lg&fi({2})", player.name, player.uuid, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
player.remove();
|
player.remove();
|
||||||
@@ -620,8 +620,10 @@ public class NetServer implements ApplicationListener{
|
|||||||
|
|
||||||
player.add();
|
player.add();
|
||||||
player.con.hasConnected = true;
|
player.con.hasConnected = true;
|
||||||
if(Config.showConnectMessages.bool()) Call.sendMessage("[accent]" + player.name + "[accent] has connected.");
|
if(Config.showConnectMessages.bool()){
|
||||||
Log.info("&lm[{1}] &y{0} has connected. ", player.name, player.uuid);
|
Call.sendMessage("[accent]" + player.name + "[accent] has connected.");
|
||||||
|
Log.info("&lm[{1}] &y{0} has connected. ", player.name, player.uuid);
|
||||||
|
}
|
||||||
|
|
||||||
if(!Config.motd.string().equalsIgnoreCase("off")){
|
if(!Config.motd.string().equalsIgnoreCase("off")){
|
||||||
player.sendMessage(Config.motd.string());
|
player.sendMessage(Config.motd.string());
|
||||||
|
|||||||
@@ -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,19 +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){
|
public void showInfoToast(String info, float duration){
|
||||||
Table table = new Table();
|
Table table = new Table();
|
||||||
table.setFillParent(true);
|
table.setFillParent(true);
|
||||||
|
table.touchable(Touchable.disabled);
|
||||||
table.update(() -> {
|
table.update(() -> {
|
||||||
if(state.is(State.menu)){
|
if(state.is(State.menu)) table.remove();
|
||||||
table.remove();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
table.actions(Actions.delay(duration * 0.9f), Actions.fadeOut(duration * 0.1f, Interpolation.fade), Actions.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);
|
table.top().table(Styles.black3, t -> t.margin(4).add(info).style(Styles.outlineLabel)).padTop(10);
|
||||||
Core.scene.add(table);
|
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();
|
||||||
@@ -439,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);
|
||||||
@@ -472,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 + "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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){
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import java.io.*;
|
|||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
|
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;
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ public class GroundUnit extends BaseUnit{
|
|||||||
moveToCore(PathTarget.enemyCores);
|
moveToCore(PathTarget.enemyCores);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
|
|
||||||
float dst = dst(core);
|
float dst = dst(core);
|
||||||
|
|
||||||
if(dst < getWeapon().bullet.range() / 1.1f){
|
if(dst < getWeapon().bullet.range() / 1.1f){
|
||||||
@@ -170,6 +169,7 @@ public class GroundUnit extends BaseUnit{
|
|||||||
|
|
||||||
if(!Units.invalidateTarget(target, this)){
|
if(!Units.invalidateTarget(target, this)){
|
||||||
if(dst(target) < getWeapon().bullet.range()){
|
if(dst(target) < getWeapon().bullet.range()){
|
||||||
|
|
||||||
rotate(angleTo(target));
|
rotate(angleTo(target));
|
||||||
|
|
||||||
if(Angles.near(angleTo(target), rotation, 13f)){
|
if(Angles.near(angleTo(target), rotation, 13f)){
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)),
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -2,19 +2,20 @@ package mindustry.world.blocks.distribution;
|
|||||||
|
|
||||||
import arc.*;
|
import arc.*;
|
||||||
import arc.func.*;
|
import arc.func.*;
|
||||||
import arc.math.*;
|
|
||||||
import arc.util.*;
|
|
||||||
import arc.struct.*;
|
|
||||||
import mindustry.ui.*;
|
|
||||||
import arc.math.geom.*;
|
|
||||||
import mindustry.type.*;
|
|
||||||
import mindustry.world.*;
|
|
||||||
import arc.graphics.g2d.*;
|
import arc.graphics.g2d.*;
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.math.geom.*;
|
||||||
|
import arc.struct.*;
|
||||||
|
import arc.util.ArcAnnotate.*;
|
||||||
|
import arc.util.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.world.meta.*;
|
|
||||||
import mindustry.world.blocks.*;
|
|
||||||
import mindustry.entities.type.*;
|
|
||||||
import mindustry.entities.traits.BuilderTrait.*;
|
import mindustry.entities.traits.BuilderTrait.*;
|
||||||
|
import mindustry.entities.type.*;
|
||||||
|
import mindustry.type.*;
|
||||||
|
import mindustry.ui.*;
|
||||||
|
import mindustry.world.*;
|
||||||
|
import mindustry.world.blocks.*;
|
||||||
|
import mindustry.world.meta.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
@@ -22,15 +23,11 @@ import static mindustry.Vars.*;
|
|||||||
|
|
||||||
public class ItemConveyor extends BaseConveyor implements Autotiler{
|
public class ItemConveyor extends BaseConveyor 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];
|
|
||||||
|
|
||||||
public float speed = 0f;
|
|
||||||
public float displayedSpeed = 0f;
|
public float displayedSpeed = 0f;
|
||||||
|
|
||||||
protected ItemConveyor(String name){
|
protected ItemConveyor(String name){
|
||||||
@@ -38,16 +35,9 @@ public class ItemConveyor extends BaseConveyor implements Autotiler{
|
|||||||
entityType = ItemConveyorEntity::new;
|
entityType = ItemConveyorEntity::new;
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
|
|
||||||
//have to add a custom calculated speed, since the actual movement speed is apparently not linear
|
//have to add a custom calculated speed, since the actual movement speed is apparently not linear
|
||||||
stats.add(BlockStat.itemsMoved, displayedSpeed, StatUnit.itemsSecond);
|
stats.add(BlockStat.itemsMoved, displayedSpeed, StatUnit.itemsSecond);
|
||||||
stats.add(BlockStat.boostEffect, "$blocks.itemsmoved");
|
stats.add(BlockStat.boostEffect, "$blocks.itemsmoved");
|
||||||
@@ -65,28 +55,31 @@ public class ItemConveyor extends BaseConveyor implements Autotiler{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawLayer(Tile tile){
|
public void onProximityUpdate(Tile tile){
|
||||||
|
super.onProximityUpdate(tile);
|
||||||
|
|
||||||
ItemConveyorEntity entity = tile.ent();
|
ItemConveyorEntity entity = tile.ent();
|
||||||
|
|
||||||
|
if(tile.front() != null && tile.front().entity != null){
|
||||||
|
entity.next = tile.front().entity;
|
||||||
|
entity.nextc = entity.next instanceof ItemConveyorEntity && entity.next.getTeam() == tile.getTeam() ? (ItemConveyorEntity)entity.next : null;
|
||||||
|
entity.aligned = entity.nextc != null && tile.rotation() == entity.next.tile.rotation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawLayer(Tile tile){
|
||||||
|
ItemConveyorEntity 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,109 +108,86 @@ public class ItemConveyor extends BaseConveyor 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){
|
||||||
ItemConveyorEntity entity = tile.ent();
|
ItemConveyorEntity 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 ItemConveyor && next.block().acceptItem(null, next, tile) ? 1f - Math.max(itemSpace - next.<ItemConveyorEntity>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 ItemConveyor){
|
|
||||||
ItemConveyorEntity 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
|
||||||
public Block getReplacement(BuildRequest req, Array<BuildRequest> requests){
|
public Block getReplacement(BuildRequest req, Array<BuildRequest> requests){
|
||||||
Boolf<Point2> cont = p -> requests.contains(o -> o.x == req.x + p.x && o.y == req.y + p.y && o.rotation == req.rotation && (req.block instanceof ItemConveyor || req.block instanceof Junction));
|
Boolf<Point2> cont = p -> requests.contains(o -> o.x == req.x + p.x && o.y == req.y + p.y && o.rotation == req.rotation && (req.block instanceof ItemConveyor || req.block instanceof Junction));
|
||||||
return cont.get(Geometry.d4(req.rotation)) &&
|
return cont.get(Geometry.d4(req.rotation)) &&
|
||||||
cont.get(Geometry.d4(req.rotation - 2)) &&
|
cont.get(Geometry.d4(req.rotation - 2)) &&
|
||||||
req.tile() != null &&
|
req.tile() != null &&
|
||||||
req.tile().block() instanceof ItemConveyor &&
|
req.tile().block() instanceof ItemConveyor &&
|
||||||
Mathf.mod(req.tile().rotation() - req.rotation, 2) == 1 ? Blocks.junction : this;
|
Mathf.mod(req.tile().rotation() - req.rotation, 2) == 1 ? Blocks.junction : this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int removeStack(Tile tile, Item item, int amount){
|
public int removeStack(Tile tile, Item item, int amount){
|
||||||
ItemConveyorEntity entity = tile.ent();
|
ItemConveyorEntity 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,150 +204,120 @@ public class ItemConveyor extends BaseConveyor 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){
|
||||||
ItemConveyorEntity entity = tile.ent();
|
ItemConveyorEntity 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){
|
||||||
|
ItemConveyorEntity 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.<ItemConveyorEntity>ent().minitem;
|
return (((direction == 0) && e.minitem >= itemSpace) || ((direction % 2 == 1) && e.minitem > 0.5f + itemSpace)) && (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();
|
ItemConveyorEntity 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);
|
||||||
|
|
||||||
ItemConveyorEntity 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 ItemConveyorEntity extends BaseConveyorEntity{
|
public static class ItemConveyorEntity extends BaseConveyorEntity{
|
||||||
|
//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 ItemConveyorEntity 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 blendsclx, blendscly;
|
||||||
|
|
||||||
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -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){
|
||||||
|
|||||||
9
fastlane/metadata/android/en-US/changelogs/103.1.txt
Normal file
9
fastlane/metadata/android/en-US/changelogs/103.1.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
- Added new icons w/ smooth scaling
|
||||||
|
- Added liquid void (Contributed by @GioIacca9)
|
||||||
|
- Added bridge opacity slider (Contributed by @Quezler)
|
||||||
|
- Added "underflow" gate (opposite of overflow gate)
|
||||||
|
- Added "emojis" for most blocks and items into the font
|
||||||
|
- Added new tech tree layout w/ better mod support
|
||||||
|
- Added game log file, stored in data folder
|
||||||
|
- Added new separator sprite/animation
|
||||||
|
- Added list of affinity tiles to stats of certain blocks
|
||||||
9
fastlane/metadata/android/en-US/changelogs/103.2.txt
Normal file
9
fastlane/metadata/android/en-US/changelogs/103.2.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
- Added new icons w/ smooth scaling
|
||||||
|
- Added liquid void (Contributed by @GioIacca9)
|
||||||
|
- Added bridge opacity slider (Contributed by @Quezler)
|
||||||
|
- Added "underflow" gate (opposite of overflow gate)
|
||||||
|
- Added "emojis" for most blocks and items into the font
|
||||||
|
- Added new tech tree layout w/ better mod support
|
||||||
|
- Added game log file, stored in data folder
|
||||||
|
- Added new separator sprite/animation
|
||||||
|
- Added list of affinity tiles to stats of certain blocks
|
||||||
9
fastlane/metadata/android/en-US/changelogs/103.3.txt
Normal file
9
fastlane/metadata/android/en-US/changelogs/103.3.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
- Added new icons w/ smooth scaling
|
||||||
|
- Added liquid void (Contributed by @GioIacca9)
|
||||||
|
- Added bridge opacity slider (Contributed by @Quezler)
|
||||||
|
- Added "underflow" gate (opposite of overflow gate)
|
||||||
|
- Added "emojis" for most blocks and items into the font
|
||||||
|
- Added new tech tree layout w/ better mod support
|
||||||
|
- Added game log file, stored in data folder
|
||||||
|
- Added new separator sprite/animation
|
||||||
|
- Added list of affinity tiles to stats of certain blocks
|
||||||
9
fastlane/metadata/android/en-US/changelogs/29591.txt
Normal file
9
fastlane/metadata/android/en-US/changelogs/29591.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
- Added new icons w/ smooth scaling
|
||||||
|
- Added liquid void (Contributed by @GioIacca9)
|
||||||
|
- Added bridge opacity slider (Contributed by @Quezler)
|
||||||
|
- Added "underflow" gate (opposite of overflow gate)
|
||||||
|
- Added "emojis" for most blocks and items into the font
|
||||||
|
- Added new tech tree layout w/ better mod support
|
||||||
|
- Added game log file, stored in data folder
|
||||||
|
- Added new separator sprite/animation
|
||||||
|
- Added list of affinity tiles to stats of certain blocks
|
||||||
9
fastlane/metadata/android/en-US/changelogs/29594.txt
Normal file
9
fastlane/metadata/android/en-US/changelogs/29594.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
- Added new icons w/ smooth scaling
|
||||||
|
- Added liquid void (Contributed by @GioIacca9)
|
||||||
|
- Added bridge opacity slider (Contributed by @Quezler)
|
||||||
|
- Added "underflow" gate (opposite of overflow gate)
|
||||||
|
- Added "emojis" for most blocks and items into the font
|
||||||
|
- Added new tech tree layout w/ better mod support
|
||||||
|
- Added game log file, stored in data folder
|
||||||
|
- Added new separator sprite/animation
|
||||||
|
- Added list of affinity tiles to stats of certain blocks
|
||||||
9
fastlane/metadata/android/en-US/changelogs/29597.txt
Normal file
9
fastlane/metadata/android/en-US/changelogs/29597.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
- Added new icons w/ smooth scaling
|
||||||
|
- Added liquid void (Contributed by @GioIacca9)
|
||||||
|
- Added bridge opacity slider (Contributed by @Quezler)
|
||||||
|
- Added "underflow" gate (opposite of overflow gate)
|
||||||
|
- Added "emojis" for most blocks and items into the font
|
||||||
|
- Added new tech tree layout w/ better mod support
|
||||||
|
- Added game log file, stored in data folder
|
||||||
|
- Added new separator sprite/animation
|
||||||
|
- Added list of affinity tiles to stats of certain blocks
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
org.gradle.daemon=true
|
org.gradle.daemon=true
|
||||||
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
||||||
archash=b54ec5513f66ad97f191b46da10f6c61046a301a
|
archash=649641d8936160221ce24c47f5b0ad10606de289
|
||||||
|
|||||||
@@ -829,7 +829,6 @@ public class ServerControl implements ApplicationListener{
|
|||||||
});
|
});
|
||||||
|
|
||||||
mods.eachClass(p -> p.registerServerCommands(handler));
|
mods.eachClass(p -> p.registerServerCommands(handler));
|
||||||
mods.eachClass(p -> p.registerClientCommands(netServer.clientCommands));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readCommands(){
|
private void readCommands(){
|
||||||
|
|||||||
@@ -1,25 +1,23 @@
|
|||||||
import arc.ApplicationCore;
|
import arc.*;
|
||||||
import arc.Core;
|
import arc.backend.headless.*;
|
||||||
import arc.backend.headless.HeadlessApplication;
|
import arc.math.geom.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.math.geom.Point2;
|
import arc.util.*;
|
||||||
import arc.util.Log;
|
import mindustry.*;
|
||||||
import arc.util.Time;
|
|
||||||
import mindustry.Vars;
|
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.core.GameState.State;
|
|
||||||
import mindustry.core.*;
|
import mindustry.core.*;
|
||||||
import mindustry.entities.traits.BuilderTrait.BuildRequest;
|
import mindustry.core.GameState.*;
|
||||||
import mindustry.entities.type.BaseUnit;
|
import mindustry.ctype.*;
|
||||||
|
import mindustry.entities.traits.BuilderTrait.*;
|
||||||
|
import mindustry.entities.type.*;
|
||||||
import mindustry.entities.type.base.*;
|
import mindustry.entities.type.base.*;
|
||||||
import mindustry.game.Team;
|
import mindustry.game.*;
|
||||||
import mindustry.io.SaveIO;
|
import mindustry.io.*;
|
||||||
import mindustry.maps.Map;
|
import mindustry.maps.*;
|
||||||
import mindustry.net.*;
|
import mindustry.net.Net;
|
||||||
import mindustry.ctype.ContentType;
|
import mindustry.type.*;
|
||||||
import mindustry.type.Item;
|
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
import mindustry.world.blocks.BlockPart;
|
import mindustry.world.blocks.*;
|
||||||
import org.junit.jupiter.api.*;
|
import org.junit.jupiter.api.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
@@ -216,6 +214,49 @@ public class ApplicationTests{
|
|||||||
assertTrue(state.teams.playerCores().size > 0);
|
assertTrue(state.teams.playerCores().size > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void conveyorBench(){
|
||||||
|
int[] items = {0};
|
||||||
|
|
||||||
|
world.loadMap(testMap);
|
||||||
|
state.set(State.playing);
|
||||||
|
int length = 128;
|
||||||
|
world.tile(0, 0).setBlock(Blocks.itemSource);
|
||||||
|
world.tile(0, 0).configureAny(Items.copper.id);
|
||||||
|
|
||||||
|
Array<TileEntity> entities = Array.with(world.tile(0, 0).entity);
|
||||||
|
|
||||||
|
for(int i = 0; i < length; i++){
|
||||||
|
world.tile(i + 1, 0).setBlock(Blocks.conveyor);
|
||||||
|
world.tile(i + 1, 0).rotation(0);
|
||||||
|
entities.add(world.tile(i + 1, 0).entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
world.tile(length + 1, 0).setBlock(new Block("___"){
|
||||||
|
@Override
|
||||||
|
public void handleItem(Item item, Tile tile, Tile source){
|
||||||
|
items[0] ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//warmup
|
||||||
|
for(int i = 0; i < 100000; i++){
|
||||||
|
entities.each(TileEntity::update);
|
||||||
|
}
|
||||||
|
|
||||||
|
Time.mark();
|
||||||
|
for(int i = 0; i < 200000; i++){
|
||||||
|
entities.each(TileEntity::update);
|
||||||
|
}
|
||||||
|
Log.info(Time.elapsed() + "ms to process " + items[0] + " items");
|
||||||
|
assertTrue(items[0] > 0);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void load77Save(){
|
void load77Save(){
|
||||||
resetWorld();
|
resetWorld();
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ public class FontGenerator{
|
|||||||
|
|
||||||
Log.info("Merge...");
|
Log.info("Merge...");
|
||||||
|
|
||||||
OS.exec("fontforge", "-script", "core/assets-raw/fontgen/merge.pe");
|
//don't merge since it breaks the font
|
||||||
|
//OS.exec("fontforge", "-script", "core/assets-raw/fontgen/merge.pe");
|
||||||
|
|
||||||
Log.info("Done.");
|
Log.info("Done.");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user