diff --git a/README.md b/README.md index 06026e0e02..aab377402d 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ See [CONTRIBUTING](CONTRIBUTING.md). Bleeding-edge live builds are generated automatically for every commit. You can see them [here](https://github.com/Anuken/MindustryBuilds/releases). Old builds might still be on [jenkins](https://jenkins.hellomouse.net/job/mindustry/). If you'd rather compile on your own, follow these instructions. -First, make sure you have [JDK 8](https://adoptopenjdk.net/) installed. Open a terminal in the root directory, `cd` to the Mindustry folder and run the following commands: +First, make sure you have [JDK 14](https://adoptopenjdk.net/) installed. Open a terminal in the root directory, `cd` to the Mindustry folder and run the following commands: #### Windows diff --git a/android/proguard-project.txt b/android/proguard-project.txt deleted file mode 100644 index 5576552446..0000000000 --- a/android/proguard-project.txt +++ /dev/null @@ -1,29 +0,0 @@ -# To enable ProGuard in your project, edit project.properties -# to define the proguard.config property as described in that file. -# -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in ${sdk.dir}/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the ProGuard -# include property in project.properties. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - --verbose --verbose --ignorewarnings --keep class mindustry.game.Rules --keep class mindustry.desktop.DesktopLauncher --keepclasseswithmembers public class * { - public static void main(java.lang.String[]); -} diff --git a/android/project.properties b/android/project.properties deleted file mode 100644 index f13bd4b19c..0000000000 --- a/android/project.properties +++ /dev/null @@ -1,13 +0,0 @@ -# This file is automatically generated by Android Tools. -# Do not modify this file -- YOUR CHANGES WILL BE ERASED! -# -# This file must be checked in Version Control Systems. -# -# To customize properties used by the Ant build system edit -# "ant.properties", and override values to adapt the script to your -# project structure. -# -# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): -#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt -# Project target. -target=android-19 diff --git a/annotations/src/main/java/mindustry/annotations/Annotations.java b/annotations/src/main/java/mindustry/annotations/Annotations.java index 99766716f1..4ccfbf74be 100644 --- a/annotations/src/main/java/mindustry/annotations/Annotations.java +++ b/annotations/src/main/java/mindustry/annotations/Annotations.java @@ -27,7 +27,7 @@ public class Annotations{ boolean clamped() default false; } - /** Indicates that a field will not be read from the server when syncing. */ + /** Indicates that a field will not be read from the server when syncing the local player state. */ @Target({ElementType.FIELD}) @Retention(RetentionPolicy.SOURCE) public @interface SyncLocal{ @@ -50,6 +50,9 @@ public class Annotations{ @Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) public @interface Component{ + /** Whether to generate a base class for this components. + * An entity cannot have two base classes, so only one component can have base be true. */ + boolean base() default false; } /** Indicates that a method is implemented by the annotation processor. */ diff --git a/annotations/src/main/java/mindustry/annotations/BaseProcessor.java b/annotations/src/main/java/mindustry/annotations/BaseProcessor.java index 46c4b92f73..710bef22ca 100644 --- a/annotations/src/main/java/mindustry/annotations/BaseProcessor.java +++ b/annotations/src/main/java/mindustry/annotations/BaseProcessor.java @@ -2,9 +2,9 @@ package mindustry.annotations; import arc.files.*; import arc.struct.*; -import arc.util.*; import arc.util.Log; import arc.util.Log.*; +import arc.util.*; import com.squareup.javapoet.*; import com.sun.source.util.*; import com.sun.tools.javac.model.*; @@ -22,9 +22,8 @@ import javax.tools.Diagnostic.*; import javax.tools.*; import java.io.*; import java.lang.annotation.*; -import java.lang.reflect.*; -import java.util.*; import java.util.List; +import java.util.*; @SupportedSourceVersion(SourceVersion.RELEASE_8) public abstract class BaseProcessor extends AbstractProcessor{ @@ -100,10 +99,16 @@ public abstract class BaseProcessor extends AbstractProcessor{ return str.contains(".") ? str.substring(str.lastIndexOf('.') + 1) : str; } - public static TypeName tname(String name) throws Exception{ - Constructor cons = TypeName.class.getDeclaredConstructor(String.class); - cons.setAccessible(true); - return cons.newInstance(name); + public static TypeName tname(String pack, String simple){ + return ClassName.get(pack, simple ); + } + + public static TypeName tname(String name){ + if(!name.contains(".")) return ClassName.get(packageName, name); + + String pack = name.substring(0, name.lastIndexOf(".")); + String simple = name.substring(name.lastIndexOf(".") + 1); + return ClassName.get(pack, simple); } public static TypeName tname(Class c){ diff --git a/annotations/src/main/java/mindustry/annotations/entity/EntityIO.java b/annotations/src/main/java/mindustry/annotations/entity/EntityIO.java index 2ec0185aef..341b26df3a 100644 --- a/annotations/src/main/java/mindustry/annotations/entity/EntityIO.java +++ b/annotations/src/main/java/mindustry/annotations/entity/EntityIO.java @@ -32,7 +32,7 @@ public class EntityIO{ MethodSpec.Builder method; ObjectSet presentFields = new ObjectSet<>(); - EntityIO(String name, TypeSpec.Builder type, ClassSerializer serializer, Fi directory){ + EntityIO(String name, TypeSpec.Builder type, Seq typeFields, ClassSerializer serializer, Fi directory){ this.directory = directory; this.type = type; this.serializer = serializer; @@ -49,7 +49,7 @@ public class EntityIO{ int nextRevision = revisions.isEmpty() ? 0 : revisions.max(r -> r.version).version + 1; //resolve preferred field order based on fields that fit - Seq fields = Seq.with(type.fieldSpecs).select(spec -> + Seq fields = typeFields.select(spec -> !spec.hasModifier(Modifier.TRANSIENT) && !spec.hasModifier(Modifier.STATIC) && !spec.hasModifier(Modifier.FINAL)/* && @@ -142,7 +142,13 @@ public class EntityIO{ io(field.type, "this." + (sf ? field.name + targetSuf : field.name) + " = "); - if(sl) econt(); + if(sl){ + ncont("else" ); + + io(field.type, ""); + + econt(); + } } st("afterSync()"); @@ -187,7 +193,7 @@ public class EntityIO{ st("$L = $L($T.$L($L, $L, alpha))", name, field.annotation(SyncField.class).clamped() ? "arc.math.Mathf.clamp" : "", Mathf.class, field.annotation(SyncField.class).value() ? "lerp" : "slerp", lastName, targetName); } - ncont("else"); //no meaningful data has arrived yet + ncont("else if(lastUpdated != 0)"); //check if no meaningful data has arrived yet //write values directly to targets for(Svar field : fields){ diff --git a/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java b/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java index a9ae65c448..3350d0e226 100644 --- a/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java +++ b/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java @@ -38,10 +38,12 @@ public class EntityProcess extends BaseProcessor{ ObjectMap> defComponents = new ObjectMap<>(); ObjectMap varInitializers = new ObjectMap<>(); ObjectMap methodBlocks = new ObjectMap<>(); + ObjectMap> baseClassDeps = new ObjectMap<>(); ObjectSet imports = new ObjectSet<>(); Seq allGroups = new Seq<>(); Seq allDefs = new Seq<>(); Seq allInterfaces = new Seq<>(); + Seq baseClasses = new Seq<>(); ClassSerializer serializer; { @@ -151,12 +153,53 @@ public class EntityProcess extends BaseProcessor{ write(inter); + //generate base class if necessary + //SPECIAL CASE: components with EntityDefs don't get a base class! the generated class becomes the base class itself + if(component.annotation(Component.class).base()){ + + Seq deps = depends.copy().and(component); + baseClassDeps.get(component, ObjectSet::new).addAll(deps); + + //do not generate base classes when the component will generate one itself + if(!component.has(EntityDef.class)){ + TypeSpec.Builder base = TypeSpec.classBuilder(baseName(component)).addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT); + + //go through all the fields. + for(Stype type : deps){ + //add public fields + for(Svar field : type.fields().select(e -> !e.is(Modifier.STATIC) && !e.is(Modifier.PRIVATE) && !e.has(Import.class) && !e.has(ReadOnly.class))){ + FieldSpec.Builder builder = FieldSpec.builder(field.tname(),field.name(), Modifier.PUBLIC); + + //keep transience + if(field.is(Modifier.TRANSIENT)) builder.addModifiers(Modifier.TRANSIENT); + //keep all annotations + builder.addAnnotations(field.annotations().map(AnnotationSpec::get)); + + //add initializer if it exists + if(varInitializers.containsKey(field.descString())){ + builder.initializer(varInitializers.get(field.descString())); + } + + base.addField(builder.build()); + } + } + + //add interfaces + for(Stype type : deps){ + base.addSuperinterface(tname(packageName, interfaceName(type))); + } + + //add to queue to be written later + baseClasses.add(base); + } + } + //LOGGING Log.debug("&gGenerating interface for " + component.name()); for(TypeName tn : inter.superinterfaces){ - Log.debug("&g> &lbextends @", simpleName(tn.toString())); + Log.debug("&g> &lbimplements @", simpleName(tn.toString())); } //log methods generated @@ -173,10 +216,19 @@ public class EntityProcess extends BaseProcessor{ //this needs to be done before the entity interfaces are generated, as the entity classes need to know which groups to add themselves to for(Selement group : allGroups){ GroupDef an = group.annotation(GroupDef.class); - Seq types = types(an, GroupDef::value).map(this::interfaceToComp); + Seq types = types(an, GroupDef::value).map(stype -> { + Stype result = interfaceToComp(stype); + if(result == null) throw new IllegalArgumentException("Interface " + stype + " does not have an associated component!"); + return result; + }); + + //representative component type + Stype repr = types.first(); + String groupType = repr.annotation(Component.class).base() ? baseName(repr) : interfaceName(repr); + boolean collides = an.collide(); groupDefs.add(new GroupDefinition(group.name().startsWith("g") ? group.name().substring(1) : group.name(), - ClassName.bestGuess(packageName + "." + interfaceName(types.first())), types, an.spatial(), an.mapping(), collides)); + ClassName.bestGuess(packageName + "." + groupType), types, an.spatial(), an.mapping(), collides)); } ObjectMap usedNames = new ObjectMap<>(); @@ -184,18 +236,41 @@ public class EntityProcess extends BaseProcessor{ //look at each definition for(Selement type : allDefs){ - EntityDef ann = type.annotation(EntityDef.class); boolean isFinal = ann.isFinal(); + //all component classes (not interfaces) + Seq components = allComponents(type); + Seq groups = groupDefs.select(g -> (!g.components.isEmpty() && !g.components.contains(s -> !components.contains(s))) || g.manualInclusions.contains(type)); + ObjectMap> methods = new ObjectMap<>(); + ObjectMap specVariables = new ObjectMap<>(); + ObjectSet usedFields = new ObjectSet<>(); + + //make sure there's less than 2 base classes + Seq baseClasses = components.select(s -> s.annotation(Component.class).base()); + if(baseClasses.size > 2){ + err("No entity may have more than 2 base classes. Base classes: " + baseClasses, type); + } + + //get base class type name for extension + Stype baseClassType = baseClasses.any() ? baseClasses.first() : null; + @Nullable TypeName baseClass = baseClasses.any() ? tname(packageName + "." + baseName(baseClassType)) : null; + //whether the main class is the base itself + boolean typeIsBase = baseClassType != null && type.has(Component.class) && type.annotation(Component.class).base(); + if(type.isType() && (!type.name().endsWith("Def") && !type.name().endsWith("Comp"))){ err("All entity def names must end with 'Def'/'Comp'", type.e); } String name = type.isType() ? - type.name().replace("Def", "Entity").replace("Comp", "Entity") : + type.name().replace("Def", "").replace("Comp", "") : createName(type); + //check for type name conflicts + if(!typeIsBase && baseClass != null && name.equals(baseName(baseClassType))){ + name += "Entity"; + } + //skip double classes if(usedNames.containsKey(name)){ extraNames.get(usedNames.get(name), ObjectSet::new).add(type.name()); @@ -209,31 +284,29 @@ public class EntityProcess extends BaseProcessor{ } TypeSpec.Builder builder = TypeSpec.classBuilder(name).addModifiers(Modifier.PUBLIC); - if(isFinal) builder.addModifiers(Modifier.FINAL); - Seq components = allComponents(type); - Seq groups = groupDefs.select(g -> (!g.components.isEmpty() && !g.components.contains(s -> !components.contains(s))) || g.manualInclusions.contains(type)); - ObjectMap> methods = new ObjectMap<>(); - ObjectMap specVariables = new ObjectMap<>(); - ObjectSet usedFields = new ObjectSet<>(); + if(isFinal && !typeIsBase) builder.addModifiers(Modifier.FINAL); //add serialize() boolean - builder.addMethod(MethodSpec.methodBuilder("serialize").addModifiers(Modifier.PUBLIC, Modifier.FINAL).returns(boolean.class).addStatement("return " + ann.serialize()).build()); + builder.addMethod(MethodSpec.methodBuilder("serialize").addModifiers(Modifier.PUBLIC).returns(boolean.class).addStatement("return " + ann.serialize()).build()); //all SyncField fields Seq syncedFields = new Seq<>(); Seq allFields = new Seq<>(); + Seq allFieldSpecs = new Seq<>(); boolean isSync = components.contains(s -> s.name().contains("Sync")); //add all components for(Stype comp : components){ + //whether this component's fields are defined in the base class + boolean isShadowed = baseClass != null && !typeIsBase && baseClassDeps.get(baseClassType).contains(comp); //write fields to the class; ignoring transient/imported ones Seq fields = comp.fields().select(f -> !f.has(Import.class)); for(Svar f : fields){ if(!usedFields.add(f.name())){ - err("Field '" + f.name() + "' of component '" + comp.name() + "' re-defines a field in entity '" + type.name() + "'"); + err("Field '" + f.name() + "' of component '" + comp.name() + "' redefines a field in entity '" + type.name() + "'"); continue; } @@ -255,9 +328,19 @@ public class EntityProcess extends BaseProcessor{ fbuilder.addModifiers(f.has(ReadOnly.class) ? Modifier.PROTECTED : Modifier.PUBLIC); fbuilder.addAnnotations(f.annotations().map(AnnotationSpec::get)); - builder.addField(fbuilder.build()); - specVariables.put(builder.fieldSpecs.get(builder.fieldSpecs.size() - 1), f); + FieldSpec spec = fbuilder.build(); + //whether this field would be added to the superclass + boolean isVisible = !f.is(Modifier.STATIC) && !f.is(Modifier.PRIVATE) && !f.has(ReadOnly.class); + + //add the field only if it isn't visible or it wasn't implemented by the base class + if(!isShadowed || !isVisible){ + builder.addField(spec); + } + + specVariables.put(spec, f); + + allFieldSpecs.add(spec); allFields.add(f); //add extra sync fields @@ -294,7 +377,7 @@ public class EntityProcess extends BaseProcessor{ .addModifiers(Modifier.PUBLIC) .addStatement("return $S + $L", name + "#", "id").build()); - EntityIO io = new EntityIO(type.name(), builder, serializer, rootDirectory.child("annotations/src/main/resources/revisions").child(name)); + EntityIO io = new EntityIO(type.name(), builder, allFieldSpecs, serializer, rootDirectory.child("annotations/src/main/resources/revisions").child(name)); //entities with no sync comp and no serialization gen no code boolean hasIO = ann.genio() && (components.contains(s -> s.name().contains("Sync")) || ann.serialize()); @@ -327,7 +410,7 @@ public class EntityProcess extends BaseProcessor{ //build method using same params/returns MethodSpec.Builder mbuilder = MethodSpec.methodBuilder(first.name()).addModifiers(first.is(Modifier.PRIVATE) ? Modifier.PRIVATE : Modifier.PUBLIC); - if(isFinal || entry.value.contains(s -> s.has(Final.class))) mbuilder.addModifiers(Modifier.FINAL); + //if(isFinal || entry.value.contains(s -> s.has(Final.class))) mbuilder.addModifiers(Modifier.FINAL); if(entry.value.contains(s -> s.has(CallSuper.class))) mbuilder.addAnnotation(CallSuper.class); //add callSuper here if necessary if(first.is(Modifier.STATIC)) mbuilder.addModifiers(Modifier.STATIC); mbuilder.addTypeVariables(first.typeVariables().map(TypeVariableName::get)); @@ -435,7 +518,7 @@ public class EntityProcess extends BaseProcessor{ builder.addSuperinterface(Poolable.class); //implement reset() MethodSpec.Builder resetBuilder = MethodSpec.methodBuilder("reset").addModifiers(Modifier.PUBLIC); - for(FieldSpec spec : builder.fieldSpecs){ + for(FieldSpec spec : allFieldSpecs){ @Nullable Svar variable = specVariables.get(spec); if(variable != null && variable.isAny(Modifier.STATIC, Modifier.FINAL)) continue; String desc = variable.descString(); @@ -462,7 +545,7 @@ public class EntityProcess extends BaseProcessor{ .returns(tname(packageName + "." + name)) .addStatement(ann.pooled() ? "return Pools.obtain($L.class, " +name +"::new)" : "return new $L()", name).build()); - definitions.add(new EntityDefinition(packageName + "." + name, builder, type, components, groups)); + definitions.add(new EntityDefinition(packageName + "." + name, builder, type, typeIsBase ? null : baseClass, components, groups, allFieldSpecs)); } //generate groups @@ -483,6 +566,14 @@ public class EntityProcess extends BaseProcessor{ //write the groups groupsBuilder.addMethod(groupInit.build()); + MethodSpec.Builder groupClear = MethodSpec.methodBuilder("clear").addModifiers(Modifier.PUBLIC, Modifier.STATIC); + for(GroupDefinition group : groupDefs){ + groupClear.addStatement("$L.clear()", group.name); + } + + //write clear + groupsBuilder.addMethod(groupClear.build()); + //add method for resizing all necessary groups MethodSpec.Builder groupResize = MethodSpec.methodBuilder("resize") .addParameter(TypeName.FLOAT, "x").addParameter(TypeName.FLOAT, "y").addParameter(TypeName.FLOAT, "w").addParameter(TypeName.FLOAT, "h") @@ -522,9 +613,9 @@ public class EntityProcess extends BaseProcessor{ int maxID = max == null ? 0 : max + 1; //assign IDs - definitions.sort(Structs.comparing(t -> t.base.toString())); + definitions.sort(Structs.comparing(t -> t.naming.toString())); for(EntityDefinition def : definitions){ - String name = def.base.fullName(); + String name = def.naming.fullName(); if(map.containsKey(name)){ def.classID = map.getInt(name); }else{ @@ -557,7 +648,7 @@ public class EntityProcess extends BaseProcessor{ for(EntityDefinition def : definitions){ //store mapping idStore.addStatement("idMap[$L] = $L::new", def.classID, def.name); - extraNames.get(def.base).each(extra -> { + extraNames.get(def.naming).each(extra -> { idStore.addStatement("nameMap.put($S, $L::new)", extra, def.name); if(!Strings.camelToKebab(extra).equals(extra)){ idStore.addStatement("nameMap.put($S, $L::new)", Strings.camelToKebab(extra), def.name); @@ -576,11 +667,21 @@ public class EntityProcess extends BaseProcessor{ }else{ //round 3: generate actual classes and implement interfaces + //write base classes + for(TypeSpec.Builder b : baseClasses){ + write(b, imports.asArray()); + } + //implement each definition for(EntityDefinition def : definitions){ ObjectSet methodNames = def.components.flatMap(type -> type.methods().map(Smethod::simpleString)).as().asSet(); + //add base class extension if it exists + if(def.extend != null){ + def.builder.superclass(def.extend); + } + //get interface for each component for(Stype comp : def.components){ @@ -596,18 +697,18 @@ public class EntityProcess extends BaseProcessor{ //generate getter/setter for each method for(Smethod method : inter.methods()){ String var = method.name(); - FieldSpec field = Seq.with(def.builder.fieldSpecs).find(f -> f.name.equals(var)); + FieldSpec field = Seq.with(def.fieldSpecs).find(f -> f.name.equals(var)); //make sure it's a real variable AND that the component doesn't already implement it somewhere with custom logic if(field == null || methodNames.contains(method.simpleString())) continue; //getter if(!method.isVoid()){ - def.builder.addMethod(MethodSpec.overriding(method.e).addStatement("return " + var).addModifiers(Modifier.FINAL).build()); + def.builder.addMethod(MethodSpec.overriding(method.e).addStatement("return " + var).build()); } //setter if(method.isVoid() && !Seq.with(field.annotations).contains(f -> f.type.toString().equals("@mindustry.annotations.Annotations.ReadOnly"))){ - def.builder.addMethod(MethodSpec.overriding(method.e).addModifiers(Modifier.FINAL).addStatement("this." + var + " = " + var).build()); + def.builder.addMethod(MethodSpec.overriding(method.e).addStatement("this." + var + " = " + var).build()); } } } @@ -625,6 +726,11 @@ public class EntityProcess extends BaseProcessor{ Seq methods = dependencies.flatMap(Stype::methods); methods.sortComparing(Object::toString); + //optionally add superclass + Stype superclass = dependencies.map(this::interfaceToComp).find(s -> s != null && s.annotation(Component.class).base()); + //use the base type when the interface being emulated has a base + TypeName type = superclass != null && interfaceToComp(interf).annotation(Component.class).base() ? tname(baseName(superclass)) : interf.tname(); + //used method signatures ObjectSet signatures = new ObjectSet<>(); @@ -635,6 +741,7 @@ public class EntityProcess extends BaseProcessor{ .addModifiers(Modifier.FINAL); nullBuilder.addSuperinterface(interf.tname()); + if(superclass != null) nullBuilder.superclass(tname(baseName(superclass))); for(Smethod method : methods){ String signature = method.toString(); @@ -642,6 +749,7 @@ public class EntityProcess extends BaseProcessor{ Stype compType = interfaceToComp(method.type()); MethodSpec.Builder builder = MethodSpec.overriding(method.e).addModifiers(Modifier.PUBLIC, Modifier.FINAL); + builder.addAnnotation(OverrideCallSuper.class); //just in case if(!method.isVoid()){ if(method.name().equals("isNull")){ @@ -665,7 +773,7 @@ public class EntityProcess extends BaseProcessor{ signatures.add(signature); } - nullsBuilder.addField(FieldSpec.builder(interf.cname(), Strings.camelize(baseName)).initializer("new " + className + "()").addModifiers(Modifier.FINAL, Modifier.STATIC, Modifier.PUBLIC).build()); + nullsBuilder.addField(FieldSpec.builder(type, Strings.camelize(baseName)).initializer("new " + className + "()").addModifiers(Modifier.FINAL, Modifier.STATIC, Modifier.PUBLIC).build()); write(nullBuilder); } @@ -681,12 +789,26 @@ public class EntityProcess extends BaseProcessor{ /** @return interface for a component type */ String interfaceName(Stype comp){ String suffix = "Comp"; - if(!comp.name().endsWith(suffix)){ - err("All components must have names that end with 'Comp'", comp.e); - } + if(!comp.name().endsWith(suffix)) err("All components must have names that end with 'Comp'", comp.e); + + //example: BlockComp -> IBlock return comp.name().substring(0, comp.name().length() - suffix.length()) + "c"; } + /** @return base class name for a component type */ + String baseName(Stype comp){ + String suffix = "Comp"; + if(!comp.name().endsWith(suffix)) err("All components must have names that end with 'Comp'", comp.e); + + return comp.name().substring(0, comp.name().length() - suffix.length()); + } + + @Nullable Stype interfaceToComp(Stype type){ + //example: IBlock -> BlockComp + String name = type.name().substring(0, type.name().length() - 1) + "Comp"; + return componentNames.get(name); + } + /** @return all components that a entity def has */ Seq allComponents(Selement type){ if(!defComponents.containsKey(type)){ @@ -746,19 +868,10 @@ public class EntityProcess extends BaseProcessor{ return interfaceToComp(type) != null; } - @Nullable Stype interfaceToComp(Stype type){ - String name = type.name().substring(0, type.name().length() - 1) + "Comp"; - return componentNames.get(name); - } - String createName(Selement elem){ Seq comps = types(elem.annotation(EntityDef.class), EntityDef::value).map(this::interfaceToComp);; comps.sortComparing(Selement::name); - return comps.toString("", s -> s.name().replace("Comp", "")) + "Entity"; - } - - boolean isComponent(Stype type){ - return type.annotation(Component.class) != null; + return comps.toString("", s -> s.name().replace("Comp", "")); } Seq types(T t, Cons consumer){ @@ -795,17 +908,21 @@ public class EntityProcess extends BaseProcessor{ class EntityDefinition{ final Seq groups; final Seq components; + final Seq fieldSpecs; final TypeSpec.Builder builder; - final Selement base; + final Selement naming; final String name; + final @Nullable TypeName extend; int classID; - public EntityDefinition(String name, Builder builder, Selement base, Seq components, Seq groups){ + public EntityDefinition(String name, Builder builder, Selement naming, TypeName extend, Seq components, Seq groups, Seq fieldSpec){ this.builder = builder; this.name = name; - this.base = base; + this.naming = naming; this.groups = groups; this.components = components; + this.extend = extend; + this.fieldSpecs = fieldSpec; } @Override @@ -813,7 +930,7 @@ public class EntityProcess extends BaseProcessor{ return "Definition{" + "groups=" + groups + "components=" + components + - ", base=" + base + + ", base=" + naming + '}'; } } diff --git a/annotations/src/main/java/mindustry/annotations/impl/StructProcess.java b/annotations/src/main/java/mindustry/annotations/impl/StructProcess.java index 7eadedb856..975e1dceee 100644 --- a/annotations/src/main/java/mindustry/annotations/impl/StructProcess.java +++ b/annotations/src/main/java/mindustry/annotations/impl/StructProcess.java @@ -1,17 +1,14 @@ package mindustry.annotations.impl; +import arc.struct.*; import com.squareup.javapoet.*; +import mindustry.annotations.Annotations.*; import mindustry.annotations.*; -import mindustry.annotations.Annotations.Struct; -import mindustry.annotations.Annotations.StructField; +import mindustry.annotations.util.*; import javax.annotation.processing.*; import javax.lang.model.element.*; -import javax.lang.model.type.TypeKind; -import javax.lang.model.util.ElementFilter; -import javax.tools.Diagnostic.Kind; -import java.util.List; -import java.util.Set; +import javax.lang.model.type.*; /** * Generates ""value types"" classes that are packed into integer primitives of the most aproppriate size. @@ -24,28 +21,28 @@ public class StructProcess extends BaseProcessor{ @Override public void process(RoundEnvironment env) throws Exception{ - Set elements = ElementFilter.typesIn(env.getElementsAnnotatedWith(Struct.class)); + Seq elements = types(Struct.class); - for(TypeElement elem : elements){ + for(Stype elem : elements){ - if(!elem.getSimpleName().toString().endsWith("Struct")){ - BaseProcessor.err("All classes annotated with @Struct must have their class names end in 'Struct'.", elem); + if(!elem.name().endsWith("Struct")){ + err("All classes annotated with @Struct must have their class names end in 'Struct'.", elem); continue; } - String structName = elem.getSimpleName().toString().substring(0, elem.getSimpleName().toString().length() - "Struct".length()); + String structName = elem.name().substring(0, elem.name().length() - "Struct".length()); String structParam = structName.toLowerCase(); TypeSpec.Builder classBuilder = TypeSpec.classBuilder(structName) .addModifiers(Modifier.FINAL, Modifier.PUBLIC); try{ - List variables = ElementFilter.fieldsIn(elem.getEnclosedElements()); - int structSize = variables.stream().mapToInt(StructProcess::varSize).sum(); + Seq variables = elem.fields(); + int structSize = variables.mapInt(StructProcess::varSize).sum(); int structTotalSize = (structSize <= 8 ? 8 : structSize <= 16 ? 16 : structSize <= 32 ? 32 : 64); - if(variables.size() == 0){ - BaseProcessor.err("making a struct with no fields is utterly pointles.", elem); + if(variables.size == 0){ + err("making a struct with no fields is utterly pointles.", elem); continue; } @@ -62,21 +59,21 @@ public class StructProcess extends BaseProcessor{ doc.append("Bits used: ").append(structSize).append(" / ").append(structTotalSize).append("\n"); int offset = 0; - for(VariableElement var : variables){ + for(Svar var : variables){ int size = varSize(var); - TypeName varType = TypeName.get(var.asType()); - String varName = var.getSimpleName().toString(); + TypeName varType = var.tname(); + String varName = var.name(); //add val param to constructor constructor.addParameter(varType, varName); //[get] field(structType) : fieldType - MethodSpec.Builder getter = MethodSpec.methodBuilder(var.getSimpleName().toString()) + MethodSpec.Builder getter = MethodSpec.methodBuilder(var.name().toString()) .addModifiers(Modifier.STATIC, Modifier.PUBLIC) .returns(varType) .addParameter(structType, structParam); //[set] field(structType, fieldType) : structType - MethodSpec.Builder setter = MethodSpec.methodBuilder(var.getSimpleName().toString()) + MethodSpec.Builder setter = MethodSpec.methodBuilder(var.name().toString()) .addModifiers(Modifier.STATIC, Modifier.PUBLIC) .returns(structType) .addParameter(structType, structParam).addParameter(varType, "value"); @@ -133,7 +130,7 @@ public class StructProcess extends BaseProcessor{ JavaFile.builder(packageName, classBuilder.build()).build().writeTo(BaseProcessor.filer); }catch(IllegalArgumentException e){ e.printStackTrace(); - BaseProcessor.err(e.getMessage(), elem); + err(e.getMessage(), elem); } } @@ -154,21 +151,21 @@ public class StructProcess extends BaseProcessor{ return "0b" + builder.reverse().toString() + "L"; } - static int varSize(VariableElement var) throws IllegalArgumentException{ - if(!var.asType().getKind().isPrimitive()){ + static int varSize(Svar var) throws IllegalArgumentException{ + if(!var.mirror().getKind().isPrimitive()){ throw new IllegalArgumentException("All struct fields must be primitives: " + var); } - StructField an = var.getAnnotation(StructField.class); - if(var.asType().getKind() == TypeKind.BOOLEAN && an != null && an.value() != 1){ + StructField an = var.annotation(StructField.class); + if(var.mirror().getKind() == TypeKind.BOOLEAN && an != null && an.value() != 1){ throw new IllegalArgumentException("Booleans can only be one bit long... why would you do this?"); } - if(var.asType().getKind() == TypeKind.FLOAT && an != null && an.value() != 32){ + if(var.mirror().getKind() == TypeKind.FLOAT && an != null && an.value() != 32){ throw new IllegalArgumentException("Float size can't be changed. Very sad."); } - return an == null ? typeSize(var.asType().getKind()) : an.value(); + return an == null ? typeSize(var.mirror().getKind()) : an.value(); } static Class typeForSize(int size) throws IllegalArgumentException{ diff --git a/annotations/src/main/java/mindustry/annotations/remote/RemoteProcess.java b/annotations/src/main/java/mindustry/annotations/remote/RemoteProcess.java index 9a00d12bfe..c785582157 100644 --- a/annotations/src/main/java/mindustry/annotations/remote/RemoteProcess.java +++ b/annotations/src/main/java/mindustry/annotations/remote/RemoteProcess.java @@ -1,15 +1,15 @@ package mindustry.annotations.remote; +import arc.struct.*; import com.squareup.javapoet.*; -import mindustry.annotations.*; import mindustry.annotations.Annotations.*; +import mindustry.annotations.*; import mindustry.annotations.util.*; import mindustry.annotations.util.TypeIOResolver.*; import javax.annotation.processing.*; import javax.lang.model.element.*; import java.util.*; -import java.util.stream.*; /** The annotation processor for generating remote method call code. */ @@ -33,13 +33,13 @@ public class RemoteProcess extends BaseProcessor{ //class serializers private ClassSerializer serializer; //all elements with the Remote annotation - private Set elements; + private Seq elements; //map of all classes to generate by name private HashMap classMap; //list of all method entries - private ArrayList methods; + private Seq methods; //list of all method entries - private ArrayList classes; + private Seq classes; { rounds = 2; @@ -54,23 +54,23 @@ public class RemoteProcess extends BaseProcessor{ //last method ID used int lastMethodID = 0; //find all elements with the Remote annotation - elements = roundEnv.getElementsAnnotatedWith(Remote.class); + elements = methods(Remote.class); //map of all classes to generate by name classMap = new HashMap<>(); //list of all method entries - methods = new ArrayList<>(); + methods = new Seq<>(); //list of all method entries - classes = new ArrayList<>(); + classes = new Seq<>(); - List orderedElements = new ArrayList<>(elements); - orderedElements.sort(Comparator.comparing(Object::toString)); + Seq orderedElements = elements.copy(); + orderedElements.sortComparing(Object::toString); //create methods - for(Element element : orderedElements){ - Remote annotation = element.getAnnotation(Remote.class); + for(Smethod element : orderedElements){ + Remote annotation = element.annotation(Remote.class); //check for static - if(!element.getModifiers().contains(Modifier.STATIC) || !element.getModifiers().contains(Modifier.PUBLIC)){ + if(!element.is(Modifier.STATIC) || !element.is(Modifier.PUBLIC)){ err("All @Remote methods must be public and static: ", element); } @@ -89,8 +89,8 @@ public class RemoteProcess extends BaseProcessor{ ClassEntry entry = classMap.get(callLocation); //create and add entry - MethodEntry method = new MethodEntry(entry.name, BaseProcessor.getMethodName(element), annotation.targets(), annotation.variants(), - annotation.called(), annotation.unreliable(), annotation.forward(), lastMethodID++, (ExecutableElement)element, annotation.priority()); + MethodEntry method = new MethodEntry(entry.name, BaseProcessor.getMethodName(element.e), annotation.targets(), annotation.variants(), + annotation.called(), annotation.unreliable(), annotation.forward(), lastMethodID++, element.e, annotation.priority()); entry.methods.add(method); methods.add(method); @@ -105,15 +105,15 @@ public class RemoteProcess extends BaseProcessor{ RemoteReadGenerator readgen = new RemoteReadGenerator(serializer); //generate server readers - readgen.generateFor(methods.stream().filter(method -> method.where.isClient).collect(Collectors.toList()), readServerName, packageName, true); + readgen.generateFor(methods.select(method -> method.where.isClient), readServerName, packageName, true); //generate client readers - readgen.generateFor(methods.stream().filter(method -> method.where.isServer).collect(Collectors.toList()), readClientName, packageName, false); + readgen.generateFor(methods.select(method -> method.where.isServer), readClientName, packageName, false); //create class for storing unique method hash TypeSpec.Builder hashBuilder = TypeSpec.classBuilder("MethodHash").addModifiers(Modifier.PUBLIC); hashBuilder.addJavadoc(autogenWarning); hashBuilder.addField(FieldSpec.builder(int.class, "HASH", Modifier.STATIC, Modifier.PUBLIC, Modifier.FINAL) - .initializer("$1L", Objects.hash(methods)).build()); + .initializer("$1L", Arrays.hashCode(methods.map(m -> m.element).toArray())).build()); //build and write resulting hash class TypeSpec spec = hashBuilder.build(); diff --git a/annotations/src/main/java/mindustry/annotations/remote/RemoteReadGenerator.java b/annotations/src/main/java/mindustry/annotations/remote/RemoteReadGenerator.java index 23fa4e5376..a8493d5643 100644 --- a/annotations/src/main/java/mindustry/annotations/remote/RemoteReadGenerator.java +++ b/annotations/src/main/java/mindustry/annotations/remote/RemoteReadGenerator.java @@ -1,14 +1,12 @@ package mindustry.annotations.remote; +import arc.struct.*; import arc.util.io.*; import com.squareup.javapoet.*; import mindustry.annotations.*; import mindustry.annotations.util.TypeIOResolver.*; -import javax.lang.model.element.Modifier; import javax.lang.model.element.*; -import java.lang.reflect.*; -import java.util.*; /** Generates code for reading remote invoke packets on the client and server. */ public class RemoteReadGenerator{ @@ -26,7 +24,7 @@ public class RemoteReadGenerator{ * @param packageName Full target package name. * @param needsPlayer Whether this read method requires a reference to the player sender. */ - public void generateFor(List entries, String className, String packageName, boolean needsPlayer) throws Exception{ + public void generateFor(Seq entries, String className, String packageName, boolean needsPlayer) throws Exception{ TypeSpec.Builder classBuilder = TypeSpec.classBuilder(className).addModifiers(Modifier.PUBLIC); classBuilder.addJavadoc(RemoteProcess.autogenWarning); @@ -39,14 +37,8 @@ public class RemoteReadGenerator{ .returns(void.class); if(needsPlayer){ - //since the player type isn't loaded yet, creating a type def is necessary - //this requires reflection since the TypeName constructor is private for some reason - Constructor cons = TypeName.class.getDeclaredConstructor(String.class); - cons.setAccessible(true); - - TypeName playerType = cons.newInstance("mindustry.gen.Playerc"); //add player parameter - readMethod.addParameter(playerType, "player"); + readMethod.addParameter(ClassName.get(packageName, "Player"), "player"); } CodeBlock.Builder readBlock = CodeBlock.builder(); //start building block of code inside read method @@ -111,7 +103,7 @@ public class RemoteReadGenerator{ if(entry.forward && entry.where.isServer && needsPlayer){ //call forwarded method readBlock.addStatement(packageName + "." + entry.className + "." + entry.element.getSimpleName() + - "__forward(player.con()" + (varResult.length() == 0 ? "" : ", ") + varResult.toString() + ")"); + "__forward(player.con" + (varResult.length() == 0 ? "" : ", ") + varResult.toString() + ")"); } readBlock.nextControlFlow("catch (java.lang.Exception e)"); diff --git a/annotations/src/main/java/mindustry/annotations/remote/RemoteWriteGenerator.java b/annotations/src/main/java/mindustry/annotations/remote/RemoteWriteGenerator.java index 066ee9b6d9..606fe513bd 100644 --- a/annotations/src/main/java/mindustry/annotations/remote/RemoteWriteGenerator.java +++ b/annotations/src/main/java/mindustry/annotations/remote/RemoteWriteGenerator.java @@ -9,7 +9,6 @@ import mindustry.annotations.util.TypeIOResolver.*; import javax.lang.model.element.*; import java.io.*; -import java.util.*; /** Generates code for writing remote invoke packets on the client and server. */ public class RemoteWriteGenerator{ @@ -21,7 +20,7 @@ public class RemoteWriteGenerator{ } /** Generates all classes in this list. */ - public void generateFor(List entries, String packageName) throws IOException{ + public void generateFor(Seq entries, String packageName) throws IOException{ for(ClassEntry entry : entries){ //create builder @@ -66,7 +65,7 @@ public class RemoteWriteGenerator{ //create builder MethodSpec.Builder method = MethodSpec.methodBuilder(elem.getSimpleName().toString() + (forwarded ? "__forward" : "")) //add except suffix when forwarding - .addModifiers(Modifier.STATIC, Modifier.SYNCHRONIZED) + .addModifiers(Modifier.STATIC) .returns(void.class); //forwarded methods aren't intended for use, and are not public @@ -81,8 +80,8 @@ public class RemoteWriteGenerator{ return; } - if(!elem.getParameters().get(0).asType().toString().contains("Playerc")){ - BaseProcessor.err("Client invoke methods should have a first parameter of type Playerc", elem); + if(!elem.getParameters().get(0).asType().toString().contains("Player")){ + BaseProcessor.err("Client invoke methods should have a first parameter of type Player", elem); return; } } diff --git a/annotations/src/main/java/mindustry/annotations/remote/SerializerResolver.java b/annotations/src/main/java/mindustry/annotations/remote/SerializerResolver.java index b41674ffab..7128d6572f 100644 --- a/annotations/src/main/java/mindustry/annotations/remote/SerializerResolver.java +++ b/annotations/src/main/java/mindustry/annotations/remote/SerializerResolver.java @@ -17,6 +17,6 @@ public class SerializerResolver{ } private static boolean isEntity(TypeMirror mirror){ - return !mirror.toString().contains(".") && mirror.toString().endsWith("c"); + return !mirror.toString().contains(".") || mirror.toString().startsWith("mindustry.gen.") && !mirror.toString().startsWith("byte"); } } diff --git a/annotations/src/main/java/mindustry/annotations/util/TypeIOResolver.java b/annotations/src/main/java/mindustry/annotations/util/TypeIOResolver.java index 88f8d79522..4f2b315bf7 100644 --- a/annotations/src/main/java/mindustry/annotations/util/TypeIOResolver.java +++ b/annotations/src/main/java/mindustry/annotations/util/TypeIOResolver.java @@ -29,7 +29,7 @@ public class TypeIOResolver{ }else if(params.size == 1 && params.first().tname().toString().equals("arc.util.io.Reads") && !meth.isVoid()){ //1 param, one is reader, returns type out.readers.put(fix(meth.retn().toString()), type.fullName() + "." + meth.name()); - }else if(params.size == 2 && params.first().tname().toString().equals("arc.util.io.Reads") && !meth.isVoid() && meth.ret() == meth.params().get(1).mirror()){ + }else if(params.size == 2 && params.first().tname().toString().equals("arc.util.io.Reads") && !meth.isVoid() && meth.ret().equals(meth.params().get(1).mirror())){ //2 params, one is reader, other is type, returns type - these are made to reduce garbage allocated out.mutatorReaders.put(fix(meth.retn().toString()), type.fullName() + "." + meth.name()); } diff --git a/annotations/src/main/resources/classids.properties b/annotations/src/main/resources/classids.properties index 85e912ce07..91aa31d081 100644 --- a/annotations/src/main/resources/classids.properties +++ b/annotations/src/main/resources/classids.properties @@ -1,23 +1,41 @@ #Maps entity names to IDs. Autogenerated. alpha=0 +arkyid=37 +atrax=38 block=1 cix=2 draug=3 +flare=36 +horizon=35 mace=4 -mindustry.entities.comp.BulletComp=5 +mega=28 +mindustry.entities.comp.BuildingComp=22 +mindustry.entities.comp.Buildingomp=11 +mindustry.entities.comp.BulletComp=24 +mindustry.entities.comp.Bulletomp=5 mindustry.entities.comp.DecalComp=6 mindustry.entities.comp.EffectComp=7 +mindustry.entities.comp.EffectInstanceComp=23 +mindustry.entities.comp.EffectStateComp=25 mindustry.entities.comp.FireComp=8 mindustry.entities.comp.LaunchCoreComp=21 mindustry.entities.comp.PlayerComp=9 mindustry.entities.comp.PuddleComp=10 -mindustry.entities.comp.TileComp=11 mindustry.type.Weather.WeatherComp=12 +mindustry.type.Weather.WeatherStateComp=26 mindustry.world.blocks.campaign.CoreLauncher.LaunchCoreComp=13 mindustry.world.blocks.campaign.LaunchPad.LaunchPayloadComp=14 +mono=29 +nova=30 oculon=15 phantom=16 +poly=31 +pulsar=34 +quasar=32 +risse=33 +spirit=27 +spiroct=39 tau=17 trident=18 vanguard=19 diff --git a/annotations/src/main/resources/revisions/BlockUnitUnit/0.json b/annotations/src/main/resources/revisions/BlockUnitUnit/0.json new file mode 100644 index 0000000000..2160b1858b --- /dev/null +++ b/annotations/src/main/resources/revisions/BlockUnitUnit/0.json @@ -0,0 +1 @@ +{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BlockUnitUnitEntity/0.json b/annotations/src/main/resources/revisions/BlockUnitUnitEntity/0.json deleted file mode 100644 index a558d32e9c..0000000000 --- a/annotations/src/main/resources/revisions/BlockUnitUnitEntity/0.json +++ /dev/null @@ -1 +0,0 @@ -{fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BlockUnitUnitEntity/1.json b/annotations/src/main/resources/revisions/BlockUnitUnitEntity/1.json deleted file mode 100644 index 054f8ae7c5..0000000000 --- a/annotations/src/main/resources/revisions/BlockUnitUnitEntity/1.json +++ /dev/null @@ -1 +0,0 @@ -{version:1,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderCommanderMechMinerUnit/0.json b/annotations/src/main/resources/revisions/BuilderCommanderMechMinerUnit/0.json new file mode 100644 index 0000000000..d5684055f5 --- /dev/null +++ b/annotations/src/main/resources/revisions/BuilderCommanderMechMinerUnit/0.json @@ -0,0 +1 @@ +{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderCommanderMechMinerUnitEntity/0.json b/annotations/src/main/resources/revisions/BuilderCommanderMechMinerUnitEntity/0.json deleted file mode 100644 index 5f0c82df0c..0000000000 --- a/annotations/src/main/resources/revisions/BuilderCommanderMechMinerUnitEntity/0.json +++ /dev/null @@ -1 +0,0 @@ -{fields:[{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:requests,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderCommanderMechMinerUnitEntity/1.json b/annotations/src/main/resources/revisions/BuilderCommanderMechMinerUnitEntity/1.json deleted file mode 100644 index 127433266b..0000000000 --- a/annotations/src/main/resources/revisions/BuilderCommanderMechMinerUnitEntity/1.json +++ /dev/null @@ -1 +0,0 @@ -{version:1,fields:[{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:plans,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderCommanderMechMinerUnitEntity/2.json b/annotations/src/main/resources/revisions/BuilderCommanderMechMinerUnitEntity/2.json deleted file mode 100644 index fa486b2486..0000000000 --- a/annotations/src/main/resources/revisions/BuilderCommanderMechMinerUnitEntity/2.json +++ /dev/null @@ -1 +0,0 @@ -{version:2,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:plans,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderLegsUnit/0.json b/annotations/src/main/resources/revisions/BuilderLegsUnit/0.json new file mode 100644 index 0000000000..719d06eac9 --- /dev/null +++ b/annotations/src/main/resources/revisions/BuilderLegsUnit/0.json @@ -0,0 +1 @@ +{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderMechUnit/0.json b/annotations/src/main/resources/revisions/BuilderMechUnit/0.json new file mode 100644 index 0000000000..b0bacdb1c1 --- /dev/null +++ b/annotations/src/main/resources/revisions/BuilderMechUnit/0.json @@ -0,0 +1 @@ +{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderMechUnitEntity/0.json b/annotations/src/main/resources/revisions/BuilderMechUnitEntity/0.json deleted file mode 100644 index 507ab66b2a..0000000000 --- a/annotations/src/main/resources/revisions/BuilderMechUnitEntity/0.json +++ /dev/null @@ -1 +0,0 @@ -{fields:[{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:requests,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderMechUnitEntity/1.json b/annotations/src/main/resources/revisions/BuilderMechUnitEntity/1.json deleted file mode 100644 index 61c5d89424..0000000000 --- a/annotations/src/main/resources/revisions/BuilderMechUnitEntity/1.json +++ /dev/null @@ -1 +0,0 @@ -{version:1,fields:[{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:plans,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderMechUnitEntity/2.json b/annotations/src/main/resources/revisions/BuilderMechUnitEntity/2.json deleted file mode 100644 index b0e880bc6c..0000000000 --- a/annotations/src/main/resources/revisions/BuilderMechUnitEntity/2.json +++ /dev/null @@ -1 +0,0 @@ -{version:2,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:plans,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderMinerPayloadUnit/0.json b/annotations/src/main/resources/revisions/BuilderMinerPayloadUnit/0.json new file mode 100644 index 0000000000..26faae9a77 --- /dev/null +++ b/annotations/src/main/resources/revisions/BuilderMinerPayloadUnit/0.json @@ -0,0 +1 @@ +{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:payloads,type:arc.struct.Seq,size:-1},{name:plans,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderMinerPayloadUnitEntity/0.json b/annotations/src/main/resources/revisions/BuilderMinerPayloadUnitEntity/0.json deleted file mode 100644 index e3ede883ad..0000000000 --- a/annotations/src/main/resources/revisions/BuilderMinerPayloadUnitEntity/0.json +++ /dev/null @@ -1 +0,0 @@ -{fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:payloads,type:arc.struct.Seq,size:-1},{name:requests,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderMinerPayloadUnitEntity/1.json b/annotations/src/main/resources/revisions/BuilderMinerPayloadUnitEntity/1.json deleted file mode 100644 index eb4c072449..0000000000 --- a/annotations/src/main/resources/revisions/BuilderMinerPayloadUnitEntity/1.json +++ /dev/null @@ -1 +0,0 @@ -{version:1,fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:payloads,type:arc.struct.Seq,size:-1},{name:plans,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderMinerPayloadUnitEntity/2.json b/annotations/src/main/resources/revisions/BuilderMinerPayloadUnitEntity/2.json deleted file mode 100644 index de78f53532..0000000000 --- a/annotations/src/main/resources/revisions/BuilderMinerPayloadUnitEntity/2.json +++ /dev/null @@ -1 +0,0 @@ -{version:2,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:payloads,type:arc.struct.Seq,size:-1},{name:plans,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderMinerTrailUnit/0.json b/annotations/src/main/resources/revisions/BuilderMinerTrailUnit/0.json new file mode 100644 index 0000000000..94f48a7b63 --- /dev/null +++ b/annotations/src/main/resources/revisions/BuilderMinerTrailUnit/0.json @@ -0,0 +1 @@ +{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderMinerUnit/0.json b/annotations/src/main/resources/revisions/BuilderMinerUnit/0.json new file mode 100644 index 0000000000..94f48a7b63 --- /dev/null +++ b/annotations/src/main/resources/revisions/BuilderMinerUnit/0.json @@ -0,0 +1 @@ +{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderMinerUnitEntity/0.json b/annotations/src/main/resources/revisions/BuilderMinerUnitEntity/0.json deleted file mode 100644 index 718245019c..0000000000 --- a/annotations/src/main/resources/revisions/BuilderMinerUnitEntity/0.json +++ /dev/null @@ -1 +0,0 @@ -{fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:requests,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderMinerUnitEntity/1.json b/annotations/src/main/resources/revisions/BuilderMinerUnitEntity/1.json deleted file mode 100644 index ebaf0c0c21..0000000000 --- a/annotations/src/main/resources/revisions/BuilderMinerUnitEntity/1.json +++ /dev/null @@ -1 +0,0 @@ -{version:1,fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:plans,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderMinerUnitEntity/2.json b/annotations/src/main/resources/revisions/BuilderMinerUnitEntity/2.json deleted file mode 100644 index d333a5f20f..0000000000 --- a/annotations/src/main/resources/revisions/BuilderMinerUnitEntity/2.json +++ /dev/null @@ -1 +0,0 @@ -{version:2,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:plans,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderUnit/0.json b/annotations/src/main/resources/revisions/BuilderUnit/0.json new file mode 100644 index 0000000000..719d06eac9 --- /dev/null +++ b/annotations/src/main/resources/revisions/BuilderUnit/0.json @@ -0,0 +1 @@ +{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:plans,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderUnitEntity/0.json b/annotations/src/main/resources/revisions/BuilderUnitEntity/0.json deleted file mode 100644 index 61b59221fa..0000000000 --- a/annotations/src/main/resources/revisions/BuilderUnitEntity/0.json +++ /dev/null @@ -1 +0,0 @@ -{fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:requests,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderUnitEntity/1.json b/annotations/src/main/resources/revisions/BuilderUnitEntity/1.json deleted file mode 100644 index 170f6b7766..0000000000 --- a/annotations/src/main/resources/revisions/BuilderUnitEntity/1.json +++ /dev/null @@ -1 +0,0 @@ -{version:1,fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:plans,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BuilderUnitEntity/2.json b/annotations/src/main/resources/revisions/BuilderUnitEntity/2.json deleted file mode 100644 index 7d1820ed91..0000000000 --- a/annotations/src/main/resources/revisions/BuilderUnitEntity/2.json +++ /dev/null @@ -1 +0,0 @@ -{version:2,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:plans,type:arc.struct.Queue,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/TileEntity/0.json b/annotations/src/main/resources/revisions/Building/0.json similarity index 100% rename from annotations/src/main/resources/revisions/TileEntity/0.json rename to annotations/src/main/resources/revisions/Building/0.json diff --git a/annotations/src/main/resources/revisions/Bullet/0.json b/annotations/src/main/resources/revisions/Bullet/0.json new file mode 100644 index 0000000000..f9e8a830d5 --- /dev/null +++ b/annotations/src/main/resources/revisions/Bullet/0.json @@ -0,0 +1 @@ +{fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:lifetime,type:float,size:4},{name:owner,type:mindustry.gen.Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/BulletEntity/0.json b/annotations/src/main/resources/revisions/BulletEntity/0.json deleted file mode 100644 index 4904375b03..0000000000 --- a/annotations/src/main/resources/revisions/BulletEntity/0.json +++ /dev/null @@ -1 +0,0 @@ -{fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:lifetime,type:float,size:4},{name:owner,type:Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/CommanderUnitWaterMove/0.json b/annotations/src/main/resources/revisions/CommanderUnitWaterMove/0.json new file mode 100644 index 0000000000..2160b1858b --- /dev/null +++ b/annotations/src/main/resources/revisions/CommanderUnitWaterMove/0.json @@ -0,0 +1 @@ +{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/0.json b/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/0.json deleted file mode 100644 index a558d32e9c..0000000000 --- a/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/0.json +++ /dev/null @@ -1 +0,0 @@ -{fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/1.json b/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/1.json deleted file mode 100644 index 054f8ae7c5..0000000000 --- a/annotations/src/main/resources/revisions/CommanderUnitWaterMoveEntity/1.json +++ /dev/null @@ -1 +0,0 @@ -{version:1,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/DecalEntity/0.json b/annotations/src/main/resources/revisions/Decal/0.json similarity index 100% rename from annotations/src/main/resources/revisions/DecalEntity/0.json rename to annotations/src/main/resources/revisions/Decal/0.json diff --git a/annotations/src/main/resources/revisions/EffectEntity/0.json b/annotations/src/main/resources/revisions/EffectState/0.json similarity index 61% rename from annotations/src/main/resources/revisions/EffectEntity/0.json rename to annotations/src/main/resources/revisions/EffectState/0.json index 5ce16bf09c..88eb281607 100644 --- a/annotations/src/main/resources/revisions/EffectEntity/0.json +++ b/annotations/src/main/resources/revisions/EffectState/0.json @@ -1 +1 @@ -{fields:[{name:color,type:arc.graphics.Color,size:-1},{name:data,type:java.lang.Object,size:-1},{name:effect,type:mindustry.entities.Effect,size:-1},{name:lifetime,type:float,size:4},{name:offsetX,type:float,size:4},{name:offsetY,type:float,size:4},{name:parent,type:Posc,size:-1},{name:rotation,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file +{fields:[{name:color,type:arc.graphics.Color,size:-1},{name:data,type:java.lang.Object,size:-1},{name:effect,type:mindustry.entities.Effect,size:-1},{name:lifetime,type:float,size:4},{name:offsetX,type:float,size:4},{name:offsetY,type:float,size:4},{name:parent,type:mindustry.gen.Posc,size:-1},{name:rotation,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/FireEntity/0.json b/annotations/src/main/resources/revisions/Fire/0.json similarity index 100% rename from annotations/src/main/resources/revisions/FireEntity/0.json rename to annotations/src/main/resources/revisions/Fire/0.json diff --git a/annotations/src/main/resources/revisions/LaunchCoreEntity/0.json b/annotations/src/main/resources/revisions/LaunchCore/0.json similarity index 100% rename from annotations/src/main/resources/revisions/LaunchCoreEntity/0.json rename to annotations/src/main/resources/revisions/LaunchCore/0.json diff --git a/annotations/src/main/resources/revisions/LaunchPayloadEntity/0.json b/annotations/src/main/resources/revisions/LaunchPayload/0.json similarity index 100% rename from annotations/src/main/resources/revisions/LaunchPayloadEntity/0.json rename to annotations/src/main/resources/revisions/LaunchPayload/0.json diff --git a/annotations/src/main/resources/revisions/LegsUnit/0.json b/annotations/src/main/resources/revisions/LegsUnit/0.json new file mode 100644 index 0000000000..2160b1858b --- /dev/null +++ b/annotations/src/main/resources/revisions/LegsUnit/0.json @@ -0,0 +1 @@ +{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/LegsUnitEntity/0.json b/annotations/src/main/resources/revisions/LegsUnitEntity/0.json deleted file mode 100644 index a558d32e9c..0000000000 --- a/annotations/src/main/resources/revisions/LegsUnitEntity/0.json +++ /dev/null @@ -1 +0,0 @@ -{fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/LegsUnitEntity/1.json b/annotations/src/main/resources/revisions/LegsUnitEntity/1.json deleted file mode 100644 index 054f8ae7c5..0000000000 --- a/annotations/src/main/resources/revisions/LegsUnitEntity/1.json +++ /dev/null @@ -1 +0,0 @@ -{version:1,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/MechUnit/0.json b/annotations/src/main/resources/revisions/MechUnit/0.json new file mode 100644 index 0000000000..32f895e075 --- /dev/null +++ b/annotations/src/main/resources/revisions/MechUnit/0.json @@ -0,0 +1 @@ +{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/MechUnitEntity/0.json b/annotations/src/main/resources/revisions/MechUnitEntity/0.json deleted file mode 100644 index 400bcb4975..0000000000 --- a/annotations/src/main/resources/revisions/MechUnitEntity/0.json +++ /dev/null @@ -1 +0,0 @@ -{fields:[{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/MechUnitEntity/1.json b/annotations/src/main/resources/revisions/MechUnitEntity/1.json deleted file mode 100644 index d622b81d98..0000000000 --- a/annotations/src/main/resources/revisions/MechUnitEntity/1.json +++ /dev/null @@ -1 +0,0 @@ -{version:1,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:baseRotation,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/MinerUnit/0.json b/annotations/src/main/resources/revisions/MinerUnit/0.json new file mode 100644 index 0000000000..5df97253d8 --- /dev/null +++ b/annotations/src/main/resources/revisions/MinerUnit/0.json @@ -0,0 +1 @@ +{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/MinerUnitEntity/0.json b/annotations/src/main/resources/revisions/MinerUnitEntity/0.json deleted file mode 100644 index 438047ff42..0000000000 --- a/annotations/src/main/resources/revisions/MinerUnitEntity/0.json +++ /dev/null @@ -1 +0,0 @@ -{fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/MinerUnitEntity/1.json b/annotations/src/main/resources/revisions/MinerUnitEntity/1.json deleted file mode 100644 index 1770a9c04a..0000000000 --- a/annotations/src/main/resources/revisions/MinerUnitEntity/1.json +++ /dev/null @@ -1 +0,0 @@ -{version:1,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/PlayerEntity/0.json b/annotations/src/main/resources/revisions/Player/0.json similarity index 74% rename from annotations/src/main/resources/revisions/PlayerEntity/0.json rename to annotations/src/main/resources/revisions/Player/0.json index de2ce4432f..f6443b400c 100644 --- a/annotations/src/main/resources/revisions/PlayerEntity/0.json +++ b/annotations/src/main/resources/revisions/Player/0.json @@ -1 +1 @@ -{fields:[{name:admin,type:boolean,size:1},{name:boosting,type:boolean,size:1},{name:color,type:arc.graphics.Color,size:-1},{name:mouseX,type:float,size:4},{name:mouseY,type:float,size:4},{name:name,type:java.lang.String,size:-1},{name:shooting,type:boolean,size:1},{name:team,type:mindustry.game.Team,size:-1},{name:typing,type:boolean,size:1},{name:unit,type:Unitc,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file +{fields:[{name:admin,type:boolean,size:1},{name:boosting,type:boolean,size:1},{name:color,type:arc.graphics.Color,size:-1},{name:mouseX,type:float,size:4},{name:mouseY,type:float,size:4},{name:name,type:java.lang.String,size:-1},{name:shooting,type:boolean,size:1},{name:team,type:mindustry.game.Team,size:-1},{name:typing,type:boolean,size:1},{name:unit,type:Unit,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/PuddleEntity/0.json b/annotations/src/main/resources/revisions/Puddle/0.json similarity index 100% rename from annotations/src/main/resources/revisions/PuddleEntity/0.json rename to annotations/src/main/resources/revisions/Puddle/0.json diff --git a/annotations/src/main/resources/revisions/UnitEntity/0.json b/annotations/src/main/resources/revisions/UnitEntity/0.json index a558d32e9c..2160b1858b 100644 --- a/annotations/src/main/resources/revisions/UnitEntity/0.json +++ b/annotations/src/main/resources/revisions/UnitEntity/0.json @@ -1 +1 @@ -{fields:[{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file +{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/UnitEntity/1.json b/annotations/src/main/resources/revisions/UnitEntity/1.json deleted file mode 100644 index 054f8ae7c5..0000000000 --- a/annotations/src/main/resources/revisions/UnitEntity/1.json +++ /dev/null @@ -1 +0,0 @@ -{version:1,fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/WeatherEntity/0.json b/annotations/src/main/resources/revisions/WeatherState/0.json similarity index 100% rename from annotations/src/main/resources/revisions/WeatherEntity/0.json rename to annotations/src/main/resources/revisions/WeatherState/0.json diff --git a/build.gradle b/build.gradle index ce1b985c77..a986b4e058 100644 --- a/build.gradle +++ b/build.gradle @@ -176,6 +176,7 @@ allprojects{ sourceCompatibility = 1.8 targetCompatibility = 1.8 options.encoding = "UTF-8" + options.compilerArgs += ["-Xlint:deprecation"] } } @@ -183,7 +184,6 @@ project(":desktop"){ apply plugin: "java" compileJava.options.fork = true - compileJava.options.compilerArgs += ["-XDignore.symbol.file"] dependencies{ implementation project(":core") @@ -325,7 +325,7 @@ project(":tools"){ implementation arcModule("natives:natives-box2d-desktop") implementation arcModule("backends:backend-headless") - implementation "org.reflections:reflections:0.9.12" + implementation "org.reflections:reflections:0.9.11" } } diff --git a/core/assets-raw/sprites/blocks/defense/parallax.png b/core/assets-raw/sprites/blocks/defense/parallax.png new file mode 100644 index 0000000000..d9224ab066 Binary files /dev/null and b/core/assets-raw/sprites/blocks/defense/parallax.png differ diff --git a/core/assets-raw/sprites/blocks/distribution/block-loader.png b/core/assets-raw/sprites/blocks/distribution/block-loader.png index bfd809c8b1..08c851a0cd 100644 Binary files a/core/assets-raw/sprites/blocks/distribution/block-loader.png and b/core/assets-raw/sprites/blocks/distribution/block-loader.png differ diff --git a/core/assets-raw/sprites/blocks/distribution/mass-driver-base.png b/core/assets-raw/sprites/blocks/distribution/mass-driver-base.png index da1f082874..4e52e7641d 100644 Binary files a/core/assets-raw/sprites/blocks/distribution/mass-driver-base.png and b/core/assets-raw/sprites/blocks/distribution/mass-driver-base.png differ diff --git a/core/assets-raw/sprites/blocks/distribution/mass-driver.png b/core/assets-raw/sprites/blocks/distribution/mass-driver.png index 8f835d1a40..c798c1370d 100644 Binary files a/core/assets-raw/sprites/blocks/distribution/mass-driver.png and b/core/assets-raw/sprites/blocks/distribution/mass-driver.png differ diff --git a/core/assets-raw/sprites/blocks/drills/laser-drill.png b/core/assets-raw/sprites/blocks/drills/laser-drill.png index b0069ad9e9..d85cd065f7 100644 Binary files a/core/assets-raw/sprites/blocks/drills/laser-drill.png and b/core/assets-raw/sprites/blocks/drills/laser-drill.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sand1.png b/core/assets-raw/sprites/blocks/environment/sand1.png index c7941f0059..9ca1dda7a0 100644 Binary files a/core/assets-raw/sprites/blocks/environment/sand1.png and b/core/assets-raw/sprites/blocks/environment/sand1.png differ diff --git a/core/assets-raw/sprites/blocks/power/rtg-generator.png b/core/assets-raw/sprites/blocks/power/rtg-generator.png index a38888ed7d..0a6766ab69 100644 Binary files a/core/assets-raw/sprites/blocks/power/rtg-generator.png and b/core/assets-raw/sprites/blocks/power/rtg-generator.png differ diff --git a/core/assets-raw/sprites/blocks/power/thorium-reactor.png b/core/assets-raw/sprites/blocks/power/thorium-reactor.png index 902d120898..e3a6656b3f 100644 Binary files a/core/assets-raw/sprites/blocks/power/thorium-reactor.png and b/core/assets-raw/sprites/blocks/power/thorium-reactor.png differ diff --git a/core/assets-raw/sprites/blocks/production/cultivator-top.png b/core/assets-raw/sprites/blocks/production/cultivator-top.png index 07a68428de..b87054124b 100644 Binary files a/core/assets-raw/sprites/blocks/production/cultivator-top.png and b/core/assets-raw/sprites/blocks/production/cultivator-top.png differ diff --git a/core/assets-raw/sprites/blocks/production/item-void.png b/core/assets-raw/sprites/blocks/production/item-void.png index a9f2dd45df..eb3e38a11c 100644 Binary files a/core/assets-raw/sprites/blocks/production/item-void.png and b/core/assets-raw/sprites/blocks/production/item-void.png differ diff --git a/core/assets-raw/sprites/blocks/production/liquid-void.png b/core/assets-raw/sprites/blocks/production/liquid-void.png index 67424c05ea..0aa9e75db1 100644 Binary files a/core/assets-raw/sprites/blocks/production/liquid-void.png and b/core/assets-raw/sprites/blocks/production/liquid-void.png differ diff --git a/core/assets-raw/sprites/blocks/production/spore-press-frame0.png b/core/assets-raw/sprites/blocks/production/spore-press-frame0.png index 84f6b39c9f..442adfd6f8 100644 Binary files a/core/assets-raw/sprites/blocks/production/spore-press-frame0.png and b/core/assets-raw/sprites/blocks/production/spore-press-frame0.png differ diff --git a/core/assets-raw/sprites/blocks/production/spore-press-frame1.png b/core/assets-raw/sprites/blocks/production/spore-press-frame1.png index d025f1c00a..14409d1122 100644 Binary files a/core/assets-raw/sprites/blocks/production/spore-press-frame1.png and b/core/assets-raw/sprites/blocks/production/spore-press-frame1.png differ diff --git a/core/assets-raw/sprites/blocks/production/spore-press-frame2.png b/core/assets-raw/sprites/blocks/production/spore-press-frame2.png index 3491c2887f..c392397bb4 100644 Binary files a/core/assets-raw/sprites/blocks/production/spore-press-frame2.png and b/core/assets-raw/sprites/blocks/production/spore-press-frame2.png differ diff --git a/core/assets-raw/sprites/blocks/production/spore-press.png b/core/assets-raw/sprites/blocks/production/spore-press.png index 3400f9d034..ae5aee87b3 100644 Binary files a/core/assets-raw/sprites/blocks/production/spore-press.png and b/core/assets-raw/sprites/blocks/production/spore-press.png differ diff --git a/core/assets-raw/sprites/effects/parallax-laser-end.png b/core/assets-raw/sprites/effects/parallax-laser-end.png new file mode 100644 index 0000000000..f81d8c09e9 Binary files /dev/null and b/core/assets-raw/sprites/effects/parallax-laser-end.png differ diff --git a/core/assets-raw/sprites/effects/parallax-laser.png b/core/assets-raw/sprites/effects/parallax-laser.png new file mode 100644 index 0000000000..8e05d41dcb Binary files /dev/null and b/core/assets-raw/sprites/effects/parallax-laser.png differ diff --git a/core/assets-raw/sprites/ui/button.9.png b/core/assets-raw/sprites/ui/button.9.png index c8fa691c60..8a01a045d1 100644 Binary files a/core/assets-raw/sprites/ui/button.9.png and b/core/assets-raw/sprites/ui/button.9.png differ diff --git a/core/assets-raw/sprites/units/lich-cell.png b/core/assets-raw/sprites/units/antumbra-cell.png similarity index 100% rename from core/assets-raw/sprites/units/lich-cell.png rename to core/assets-raw/sprites/units/antumbra-cell.png diff --git a/core/assets-raw/sprites/units/lich.png b/core/assets-raw/sprites/units/antumbra.png similarity index 100% rename from core/assets-raw/sprites/units/lich.png rename to core/assets-raw/sprites/units/antumbra.png diff --git a/core/assets-raw/sprites/units/cix-cell.png b/core/assets-raw/sprites/units/arkyid-cell.png similarity index 100% rename from core/assets-raw/sprites/units/cix-cell.png rename to core/assets-raw/sprites/units/arkyid-cell.png diff --git a/core/assets-raw/sprites/units/cix-foot.png b/core/assets-raw/sprites/units/arkyid-foot.png similarity index 100% rename from core/assets-raw/sprites/units/cix-foot.png rename to core/assets-raw/sprites/units/arkyid-foot.png diff --git a/core/assets-raw/sprites/units/cix-joint-base.png b/core/assets-raw/sprites/units/arkyid-joint-base.png similarity index 100% rename from core/assets-raw/sprites/units/cix-joint-base.png rename to core/assets-raw/sprites/units/arkyid-joint-base.png diff --git a/core/assets-raw/sprites/units/cix-leg-base.png b/core/assets-raw/sprites/units/arkyid-leg-base.png similarity index 100% rename from core/assets-raw/sprites/units/cix-leg-base.png rename to core/assets-raw/sprites/units/arkyid-leg-base.png diff --git a/core/assets-raw/sprites/units/cix-leg.png b/core/assets-raw/sprites/units/arkyid-leg.png similarity index 100% rename from core/assets-raw/sprites/units/cix-leg.png rename to core/assets-raw/sprites/units/arkyid-leg.png diff --git a/core/assets-raw/sprites/units/cix.png b/core/assets-raw/sprites/units/arkyid.png similarity index 100% rename from core/assets-raw/sprites/units/cix.png rename to core/assets-raw/sprites/units/arkyid.png diff --git a/core/assets-raw/sprites/units/eruptor-base.png b/core/assets-raw/sprites/units/atrax-base.png similarity index 100% rename from core/assets-raw/sprites/units/eruptor-base.png rename to core/assets-raw/sprites/units/atrax-base.png diff --git a/core/assets-raw/sprites/units/atrax-cell.png b/core/assets-raw/sprites/units/atrax-cell.png new file mode 100644 index 0000000000..9b8baf165d Binary files /dev/null and b/core/assets-raw/sprites/units/atrax-cell.png differ diff --git a/core/assets-raw/sprites/units/eruptor-foot.png b/core/assets-raw/sprites/units/atrax-foot.png similarity index 100% rename from core/assets-raw/sprites/units/eruptor-foot.png rename to core/assets-raw/sprites/units/atrax-foot.png diff --git a/core/assets-raw/sprites/units/eruptor-joint.png b/core/assets-raw/sprites/units/atrax-joint.png similarity index 100% rename from core/assets-raw/sprites/units/eruptor-joint.png rename to core/assets-raw/sprites/units/atrax-joint.png diff --git a/core/assets-raw/sprites/units/eruptor-leg-base.png b/core/assets-raw/sprites/units/atrax-leg-base.png similarity index 100% rename from core/assets-raw/sprites/units/eruptor-leg-base.png rename to core/assets-raw/sprites/units/atrax-leg-base.png diff --git a/core/assets-raw/sprites/units/eruptor-leg.png b/core/assets-raw/sprites/units/atrax-leg.png similarity index 100% rename from core/assets-raw/sprites/units/eruptor-leg.png rename to core/assets-raw/sprites/units/atrax-leg.png diff --git a/core/assets-raw/sprites/units/atrax.png b/core/assets-raw/sprites/units/atrax.png new file mode 100644 index 0000000000..b73d3046d0 Binary files /dev/null and b/core/assets-raw/sprites/units/atrax.png differ diff --git a/core/assets-raw/sprites/units/beta-cell.png b/core/assets-raw/sprites/units/beta-cell.png new file mode 100644 index 0000000000..7b53cad13e Binary files /dev/null and b/core/assets-raw/sprites/units/beta-cell.png differ diff --git a/core/assets-raw/sprites/units/beta.png b/core/assets-raw/sprites/units/beta.png new file mode 100644 index 0000000000..b1bca129e6 Binary files /dev/null and b/core/assets-raw/sprites/units/beta.png differ diff --git a/core/assets-raw/sprites/units/cix-old.png b/core/assets-raw/sprites/units/cix-old.png deleted file mode 100644 index 7996cd3aa4..0000000000 Binary files a/core/assets-raw/sprites/units/cix-old.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/crawler.png b/core/assets-raw/sprites/units/crawler.png index 5a60b1de27..0184ad19ba 100644 Binary files a/core/assets-raw/sprites/units/crawler.png and b/core/assets-raw/sprites/units/crawler.png differ diff --git a/core/assets-raw/sprites/units/delta-cell.png b/core/assets-raw/sprites/units/delta-cell.png deleted file mode 100644 index ee7c15a9dd..0000000000 Binary files a/core/assets-raw/sprites/units/delta-cell.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/delta.png b/core/assets-raw/sprites/units/delta.png deleted file mode 100644 index adf85f8795..0000000000 Binary files a/core/assets-raw/sprites/units/delta.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/draug-cell.png b/core/assets-raw/sprites/units/draug-cell.png deleted file mode 100644 index 439d7b8ea3..0000000000 Binary files a/core/assets-raw/sprites/units/draug-cell.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/draug.png b/core/assets-raw/sprites/units/draug.png deleted file mode 100644 index 004e23ea96..0000000000 Binary files a/core/assets-raw/sprites/units/draug.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/reaper-cell.png b/core/assets-raw/sprites/units/eclipse-cell.png similarity index 100% rename from core/assets-raw/sprites/units/reaper-cell.png rename to core/assets-raw/sprites/units/eclipse-cell.png diff --git a/core/assets-raw/sprites/units/reaper.aseprite b/core/assets-raw/sprites/units/eclipse.aseprite similarity index 100% rename from core/assets-raw/sprites/units/reaper.aseprite rename to core/assets-raw/sprites/units/eclipse.aseprite diff --git a/core/assets-raw/sprites/units/reaper.png b/core/assets-raw/sprites/units/eclipse.png similarity index 100% rename from core/assets-raw/sprites/units/reaper.png rename to core/assets-raw/sprites/units/eclipse.png diff --git a/core/assets-raw/sprites/units/eruptor-cell.png b/core/assets-raw/sprites/units/eruptor-cell.png deleted file mode 100644 index f98bfd223b..0000000000 Binary files a/core/assets-raw/sprites/units/eruptor-cell.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/eruptor.png b/core/assets-raw/sprites/units/eruptor.png deleted file mode 100644 index 96f255db16..0000000000 Binary files a/core/assets-raw/sprites/units/eruptor.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/wraith.png b/core/assets-raw/sprites/units/flare.png similarity index 100% rename from core/assets-raw/sprites/units/wraith.png rename to core/assets-raw/sprites/units/flare.png diff --git a/core/assets-raw/sprites/units/glaive-cell.png b/core/assets-raw/sprites/units/gamma-cell.png similarity index 100% rename from core/assets-raw/sprites/units/glaive-cell.png rename to core/assets-raw/sprites/units/gamma-cell.png diff --git a/core/assets-raw/sprites/units/gamma.png b/core/assets-raw/sprites/units/gamma.png new file mode 100644 index 0000000000..bbc3c7a57a Binary files /dev/null and b/core/assets-raw/sprites/units/gamma.png differ diff --git a/core/assets-raw/sprites/units/glaive.png b/core/assets-raw/sprites/units/glaive.png deleted file mode 100644 index 4553066c91..0000000000 Binary files a/core/assets-raw/sprites/units/glaive.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/ghoul-cell.png b/core/assets-raw/sprites/units/horizon-cell.png similarity index 100% rename from core/assets-raw/sprites/units/ghoul-cell.png rename to core/assets-raw/sprites/units/horizon-cell.png diff --git a/core/assets-raw/sprites/units/ghoul.png b/core/assets-raw/sprites/units/horizon.png similarity index 100% rename from core/assets-raw/sprites/units/ghoul.png rename to core/assets-raw/sprites/units/horizon.png diff --git a/core/assets-raw/sprites/units/mega-cell.png b/core/assets-raw/sprites/units/mega-cell.png new file mode 100644 index 0000000000..4ea5a1d2e7 Binary files /dev/null and b/core/assets-raw/sprites/units/mega-cell.png differ diff --git a/core/assets-raw/sprites/units/mega.png b/core/assets-raw/sprites/units/mega.png new file mode 100644 index 0000000000..9fdade2d20 Binary files /dev/null and b/core/assets-raw/sprites/units/mega.png differ diff --git a/core/assets-raw/sprites/units/spirit-cell.png b/core/assets-raw/sprites/units/mono-cell.png similarity index 100% rename from core/assets-raw/sprites/units/spirit-cell.png rename to core/assets-raw/sprites/units/mono-cell.png diff --git a/core/assets-raw/sprites/units/mono.png b/core/assets-raw/sprites/units/mono.png new file mode 100644 index 0000000000..573d2d0655 Binary files /dev/null and b/core/assets-raw/sprites/units/mono.png differ diff --git a/core/assets-raw/sprites/units/tau-base.png b/core/assets-raw/sprites/units/nova-base.png similarity index 100% rename from core/assets-raw/sprites/units/tau-base.png rename to core/assets-raw/sprites/units/nova-base.png diff --git a/core/assets-raw/sprites/units/tau-cell.png b/core/assets-raw/sprites/units/nova-cell.png similarity index 100% rename from core/assets-raw/sprites/units/tau-cell.png rename to core/assets-raw/sprites/units/nova-cell.png diff --git a/core/assets-raw/sprites/units/tau-leg.png b/core/assets-raw/sprites/units/nova-leg.png similarity index 100% rename from core/assets-raw/sprites/units/tau-leg.png rename to core/assets-raw/sprites/units/nova-leg.png diff --git a/core/assets-raw/sprites/units/tau.png b/core/assets-raw/sprites/units/nova.png similarity index 100% rename from core/assets-raw/sprites/units/tau.png rename to core/assets-raw/sprites/units/nova.png diff --git a/core/assets-raw/sprites/units/oculon-armor.png b/core/assets-raw/sprites/units/oculon-armor.png deleted file mode 100644 index 47d531379a..0000000000 Binary files a/core/assets-raw/sprites/units/oculon-armor.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/oculon-base-old.png b/core/assets-raw/sprites/units/oculon-base-old.png deleted file mode 100644 index 61fb31cf47..0000000000 Binary files a/core/assets-raw/sprites/units/oculon-base-old.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/oculon-cell-old.png b/core/assets-raw/sprites/units/oculon-cell-old.png deleted file mode 100644 index 8930e79cf5..0000000000 Binary files a/core/assets-raw/sprites/units/oculon-cell-old.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/oculon-cell.png b/core/assets-raw/sprites/units/oculon-cell.png deleted file mode 100644 index 1ee9c9c5fc..0000000000 Binary files a/core/assets-raw/sprites/units/oculon-cell.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/oculon-old.png b/core/assets-raw/sprites/units/oculon-old.png deleted file mode 100644 index 7e1d6cddd2..0000000000 Binary files a/core/assets-raw/sprites/units/oculon-old.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/phantom.png b/core/assets-raw/sprites/units/phantom.png deleted file mode 100644 index 33df9c8438..0000000000 Binary files a/core/assets-raw/sprites/units/phantom.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/phantom-cell.png b/core/assets-raw/sprites/units/poly-cell.png similarity index 100% rename from core/assets-raw/sprites/units/phantom-cell.png rename to core/assets-raw/sprites/units/poly-cell.png diff --git a/core/assets-raw/sprites/units/poly.png b/core/assets-raw/sprites/units/poly.png new file mode 100644 index 0000000000..b6c57ac149 Binary files /dev/null and b/core/assets-raw/sprites/units/poly.png differ diff --git a/core/assets-raw/sprites/units/oculon-leg-old.png b/core/assets-raw/sprites/units/pulsar-base.png similarity index 53% rename from core/assets-raw/sprites/units/oculon-leg-old.png rename to core/assets-raw/sprites/units/pulsar-base.png index d1f2fae6d6..f076436987 100644 Binary files a/core/assets-raw/sprites/units/oculon-leg-old.png and b/core/assets-raw/sprites/units/pulsar-base.png differ diff --git a/core/assets-raw/sprites/units/pulsar-cell.png b/core/assets-raw/sprites/units/pulsar-cell.png new file mode 100644 index 0000000000..9268d38651 Binary files /dev/null and b/core/assets-raw/sprites/units/pulsar-cell.png differ diff --git a/core/assets-raw/sprites/units/pulsar-leg.png b/core/assets-raw/sprites/units/pulsar-leg.png new file mode 100644 index 0000000000..9d3a4ec2af Binary files /dev/null and b/core/assets-raw/sprites/units/pulsar-leg.png differ diff --git a/core/assets-raw/sprites/units/pulsar.png b/core/assets-raw/sprites/units/pulsar.png new file mode 100644 index 0000000000..eb49cd3751 Binary files /dev/null and b/core/assets-raw/sprites/units/pulsar.png differ diff --git a/core/assets-raw/sprites/units/oculon-base.png b/core/assets-raw/sprites/units/quasar-base.png similarity index 100% rename from core/assets-raw/sprites/units/oculon-base.png rename to core/assets-raw/sprites/units/quasar-base.png diff --git a/core/assets-raw/sprites/units/quasar-cell.png b/core/assets-raw/sprites/units/quasar-cell.png new file mode 100644 index 0000000000..d15d720349 Binary files /dev/null and b/core/assets-raw/sprites/units/quasar-cell.png differ diff --git a/core/assets-raw/sprites/units/oculon-leg.png b/core/assets-raw/sprites/units/quasar-leg.png similarity index 100% rename from core/assets-raw/sprites/units/oculon-leg.png rename to core/assets-raw/sprites/units/quasar-leg.png diff --git a/core/assets-raw/sprites/units/oculon.png b/core/assets-raw/sprites/units/quasar.png similarity index 100% rename from core/assets-raw/sprites/units/oculon.png rename to core/assets-raw/sprites/units/quasar.png diff --git a/core/assets-raw/sprites/units/spirit.png b/core/assets-raw/sprites/units/spirit.png deleted file mode 100644 index 1f9a4e89ec..0000000000 Binary files a/core/assets-raw/sprites/units/spirit.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/spiroct-cell.png b/core/assets-raw/sprites/units/spiroct-cell.png new file mode 100644 index 0000000000..180d3e986b Binary files /dev/null and b/core/assets-raw/sprites/units/spiroct-cell.png differ diff --git a/core/assets-raw/sprites/units/spiroct-foot.png b/core/assets-raw/sprites/units/spiroct-foot.png new file mode 100644 index 0000000000..c501d7843d Binary files /dev/null and b/core/assets-raw/sprites/units/spiroct-foot.png differ diff --git a/core/assets-raw/sprites/units/spiroct-joint.png b/core/assets-raw/sprites/units/spiroct-joint.png new file mode 100644 index 0000000000..1fe4fdbd3e Binary files /dev/null and b/core/assets-raw/sprites/units/spiroct-joint.png differ diff --git a/core/assets-raw/sprites/units/spiroct-leg-base.png b/core/assets-raw/sprites/units/spiroct-leg-base.png new file mode 100644 index 0000000000..0c2a1783e1 Binary files /dev/null and b/core/assets-raw/sprites/units/spiroct-leg-base.png differ diff --git a/core/assets-raw/sprites/units/spiroct-leg.png b/core/assets-raw/sprites/units/spiroct-leg.png new file mode 100644 index 0000000000..cc9081fce9 Binary files /dev/null and b/core/assets-raw/sprites/units/spiroct-leg.png differ diff --git a/core/assets-raw/sprites/units/spiroct.png b/core/assets-raw/sprites/units/spiroct.png new file mode 100644 index 0000000000..a69a0b2657 Binary files /dev/null and b/core/assets-raw/sprites/units/spiroct.png differ diff --git a/core/assets-raw/sprites/units/trident-cell.png b/core/assets-raw/sprites/units/trident-cell.png deleted file mode 100644 index 4badf79a8d..0000000000 Binary files a/core/assets-raw/sprites/units/trident-cell.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/trident.png b/core/assets-raw/sprites/units/trident.png deleted file mode 100644 index 5e8f01284c..0000000000 Binary files a/core/assets-raw/sprites/units/trident.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/weapons/antumbra-missiles.png b/core/assets-raw/sprites/units/weapons/antumbra-missiles.png new file mode 100644 index 0000000000..a37cbfa449 Binary files /dev/null and b/core/assets-raw/sprites/units/weapons/antumbra-missiles.png differ diff --git a/core/assets-raw/sprites/units/weapons/artillery.png b/core/assets-raw/sprites/units/weapons/artillery.png index 27572467bf..fe8369d27a 100644 Binary files a/core/assets-raw/sprites/units/weapons/artillery.png and b/core/assets-raw/sprites/units/weapons/artillery.png differ diff --git a/core/assets-raw/sprites/units/weapons/beam-weapon.png b/core/assets-raw/sprites/units/weapons/beam-weapon.png index 0e802877f7..d4784aa69f 100644 Binary files a/core/assets-raw/sprites/units/weapons/beam-weapon.png and b/core/assets-raw/sprites/units/weapons/beam-weapon.png differ diff --git a/core/assets-raw/sprites/units/weapons/chaos.png b/core/assets-raw/sprites/units/weapons/chaos.png index 9c7f91085c..442d5b0417 100644 Binary files a/core/assets-raw/sprites/units/weapons/chaos.png and b/core/assets-raw/sprites/units/weapons/chaos.png differ diff --git a/core/assets-raw/sprites/units/weapons/reaper-weapon.png b/core/assets-raw/sprites/units/weapons/eclipse-weapon.png similarity index 100% rename from core/assets-raw/sprites/units/weapons/reaper-weapon.png rename to core/assets-raw/sprites/units/weapons/eclipse-weapon.png diff --git a/core/assets-raw/sprites/units/weapons/eradication.png b/core/assets-raw/sprites/units/weapons/eradication.png index 15a7748677..231158b058 100644 Binary files a/core/assets-raw/sprites/units/weapons/eradication.png and b/core/assets-raw/sprites/units/weapons/eradication.png differ diff --git a/core/assets-raw/sprites/units/weapons/eruption.png b/core/assets-raw/sprites/units/weapons/eruption.png index d17685fc57..172e9835e6 100644 Binary files a/core/assets-raw/sprites/units/weapons/eruption.png and b/core/assets-raw/sprites/units/weapons/eruption.png differ diff --git a/core/assets-raw/sprites/units/weapons/flakgun.png b/core/assets-raw/sprites/units/weapons/flakgun.png index e73c50aed2..12ee89862f 100644 Binary files a/core/assets-raw/sprites/units/weapons/flakgun.png and b/core/assets-raw/sprites/units/weapons/flakgun.png differ diff --git a/core/assets-raw/sprites/units/weapons/flamethrower.png b/core/assets-raw/sprites/units/weapons/flamethrower.png index 8887f4296d..6aac73acd3 100644 Binary files a/core/assets-raw/sprites/units/weapons/flamethrower.png and b/core/assets-raw/sprites/units/weapons/flamethrower.png differ diff --git a/core/assets-raw/sprites/units/weapons/heal-shotgun-weapon.png b/core/assets-raw/sprites/units/weapons/heal-shotgun-weapon.png new file mode 100644 index 0000000000..5b85b778a7 Binary files /dev/null and b/core/assets-raw/sprites/units/weapons/heal-shotgun-weapon.png differ diff --git a/core/assets-raw/sprites/units/weapons/heal-weapon-mount.png b/core/assets-raw/sprites/units/weapons/heal-weapon-mount.png index cebc522f86..2ff4d59c4a 100644 Binary files a/core/assets-raw/sprites/units/weapons/heal-weapon-mount.png and b/core/assets-raw/sprites/units/weapons/heal-weapon-mount.png differ diff --git a/core/assets-raw/sprites/units/weapons/heal-weapon.png b/core/assets-raw/sprites/units/weapons/heal-weapon.png index e7b61dd884..7ab9309d40 100644 Binary files a/core/assets-raw/sprites/units/weapons/heal-weapon.png and b/core/assets-raw/sprites/units/weapons/heal-weapon.png differ diff --git a/core/assets-raw/sprites/units/weapons/large-weapon.png b/core/assets-raw/sprites/units/weapons/large-weapon.png index b93338cfca..426fbfc470 100644 Binary files a/core/assets-raw/sprites/units/weapons/large-weapon.png and b/core/assets-raw/sprites/units/weapons/large-weapon.png differ diff --git a/core/assets-raw/sprites/units/weapons/lich-missiles.png b/core/assets-raw/sprites/units/weapons/lich-missiles.png deleted file mode 100644 index d8fbd8549b..0000000000 Binary files a/core/assets-raw/sprites/units/weapons/lich-missiles.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/weapons/missiles.png b/core/assets-raw/sprites/units/weapons/missiles.png index 89e8713f23..38c0548ca6 100644 Binary files a/core/assets-raw/sprites/units/weapons/missiles.png and b/core/assets-raw/sprites/units/weapons/missiles.png differ diff --git a/core/assets-raw/sprites/units/weapons/mount-purple-weapon.png b/core/assets-raw/sprites/units/weapons/mount-purple-weapon.png new file mode 100644 index 0000000000..d34950accd Binary files /dev/null and b/core/assets-raw/sprites/units/weapons/mount-purple-weapon.png differ diff --git a/core/assets-raw/sprites/units/weapons/mount-weapon.png b/core/assets-raw/sprites/units/weapons/mount-weapon.png index 2af685bf2b..3561c08013 100644 Binary files a/core/assets-raw/sprites/units/weapons/mount-weapon.png and b/core/assets-raw/sprites/units/weapons/mount-weapon.png differ diff --git a/core/assets-raw/sprites/units/weapons/revenant-missiles.png b/core/assets-raw/sprites/units/weapons/revenant-missiles.png deleted file mode 100644 index bc7dd1f0a5..0000000000 Binary files a/core/assets-raw/sprites/units/weapons/revenant-missiles.png and /dev/null differ diff --git a/core/assets-raw/sprites/units/weapons/small-basic-weapon.png b/core/assets-raw/sprites/units/weapons/small-basic-weapon.png index a5c7793ff2..e4833342a4 100644 Binary files a/core/assets-raw/sprites/units/weapons/small-basic-weapon.png and b/core/assets-raw/sprites/units/weapons/small-basic-weapon.png differ diff --git a/core/assets-raw/sprites/units/weapons/small-mount-weapon.png b/core/assets-raw/sprites/units/weapons/small-mount-weapon.png new file mode 100644 index 0000000000..f928b890d6 Binary files /dev/null and b/core/assets-raw/sprites/units/weapons/small-mount-weapon.png differ diff --git a/core/assets-raw/sprites/units/weapons/small-weapon.png b/core/assets-raw/sprites/units/weapons/small-weapon.png index 7d1e246dd4..ee4554082e 100644 Binary files a/core/assets-raw/sprites/units/weapons/small-weapon.png and b/core/assets-raw/sprites/units/weapons/small-weapon.png differ diff --git a/core/assets-raw/sprites/units/weapons/spiroct-weapon.png b/core/assets-raw/sprites/units/weapons/spiroct-weapon.png new file mode 100644 index 0000000000..91ff27033e Binary files /dev/null and b/core/assets-raw/sprites/units/weapons/spiroct-weapon.png differ diff --git a/core/assets-raw/sprites/units/weapons/weapon.png b/core/assets-raw/sprites/units/weapons/weapon.png index 277fe2463e..a0c24aa143 100644 Binary files a/core/assets-raw/sprites/units/weapons/weapon.png and b/core/assets-raw/sprites/units/weapons/weapon.png differ diff --git a/core/assets-raw/sprites/units/weapons/zenith-missiles.png b/core/assets-raw/sprites/units/weapons/zenith-missiles.png new file mode 100644 index 0000000000..e482202c65 Binary files /dev/null and b/core/assets-raw/sprites/units/weapons/zenith-missiles.png differ diff --git a/core/assets-raw/sprites/units/revenant-cell.png b/core/assets-raw/sprites/units/zenith-cell.png similarity index 100% rename from core/assets-raw/sprites/units/revenant-cell.png rename to core/assets-raw/sprites/units/zenith-cell.png diff --git a/core/assets-raw/sprites/units/revenant.png b/core/assets-raw/sprites/units/zenith.png similarity index 100% rename from core/assets-raw/sprites/units/revenant.png rename to core/assets-raw/sprites/units/zenith.png diff --git a/core/assets-raw/sprites/weapons/beam-weapon.png b/core/assets-raw/sprites/weapons/beam-weapon.png deleted file mode 100644 index 0e802877f7..0000000000 Binary files a/core/assets-raw/sprites/weapons/beam-weapon.png and /dev/null differ diff --git a/core/assets/baseparts/000.msch b/core/assets/baseparts/000.msch new file mode 100644 index 0000000000..35d2df8e14 Binary files /dev/null and b/core/assets/baseparts/000.msch differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 49db2f8b0a..1d5cf2f291 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -106,6 +106,7 @@ mods.guide = Modding Guide mods.report = Report Bug mods.openfolder = Open Folder mods.reload = Reload +mods.reloadexit = The game will now exit, to reload mods. mod.display = [gray]Mod:[orange] {0} mod.enabled = [lightgray]Enabled mod.disabled = [scarlet]Disabled @@ -120,10 +121,11 @@ mod.noerrorplay = [scarlet]You have mods with errors.[] Either disable the affec mod.nowdisabled = [scarlet]Mod '{0}' is missing dependencies:[accent] {1}\n[lightgray]These mods need to be downloaded first.\nThis mod will be automatically disabled. mod.enable = Enable mod.requiresrestart = The game will now close to apply the mod changes. -mod.reloadrequired = [scarlet]Reload Required +mod.reloadrequired = [scarlet]Restart Required mod.import = Import Mod mod.import.file = Import File mod.import.github = Import From GitHub +mod.jarwarn = [scarlet]JAR mods are inherently unsafe.[]\nMake sure you're importing this mod from a trustworthy source! mod.item.remove = This item is part of the[accent] '{0}'[] mod. To remove it, uninstall that mod. mod.remove.confirm = This mod will be deleted. mod.author = [lightgray]Author:[] {0} @@ -196,8 +198,8 @@ server.admins.none = No admins found! server.add = Add Server server.delete = Are you sure you want to delete this server? server.edit = Edit Server -server.outdated = [crimson]Outdated Server![] -server.outdated.client = [crimson]Outdated Client![] +server.outdated = [scarlet]Outdated Server![] +server.outdated.client = [scarlet]Outdated Client![] server.version = [gray]v{0} {1} server.custombuild = [accent]Custom Build confirmban = Are you sure you want to ban "{0}[white]"? @@ -219,7 +221,7 @@ connecting.data = [accent]Loading world data... server.port = Port: server.addressinuse = Address already in use! server.invalidport = Invalid port number! -server.error = [crimson]Error hosting server. +server.error = [scarlet]Error hosting server. save.new = New Save save.overwrite = Are you sure you want to overwrite\nthis save slot? overwrite = Overwrite @@ -229,8 +231,8 @@ save.delete.confirm = Are you sure you want to delete this save? save.delete = Delete save.export = Export Save save.import.invalid = [accent]This save is invalid! -save.import.fail = [crimson]Failed to import save: [accent]{0} -save.export.fail = [crimson]Failed to export save: [accent]{0} +save.import.fail = [scarlet]Failed to import save: [accent]{0} +save.export.fail = [scarlet]Failed to export save: [accent]{0} save.import = Import Save save.newslot = Save name: save.rename = Rename @@ -460,7 +462,9 @@ requirement.core = Destroy Enemy Core in {0} requirement.unlock = Unlock {0} resume = Resume Zone:\n[lightgray]{0} bestwave = [lightgray]Best Wave: {0} +#TODO fix/remove this launch = < LAUNCH > +launch.text = Launch launch.title = Launch Successful launch.next = [lightgray]next opportunity at wave {0} launch.unable2 = [scarlet]Unable to LAUNCH.[] @@ -468,13 +472,14 @@ launch.confirm = This will launch all resources in your core.\nYou will not be a launch.skip.confirm = If you skip now, you will not be able to launch until later waves. uncover = Uncover configure = Configure Loadout +#TODO +loadout = Loadout +resources = Resources bannedblocks = Banned Blocks addall = Add All -configure.locked = [lightgray]Unlock configuring loadout: {0}. configure.invalid = Amount must be a number between 0 and {0}. zone.unlocked = [lightgray]{0} unlocked. zone.requirement.complete = Requirement for {0} completed:[lightgray]\n{1} -zone.config.unlocked = Loadout unlocked:[lightgray]\n{0} zone.resources = [lightgray]Resources Detected: zone.objective = [lightgray]Objective: [accent]{0} zone.objective.survival = Survive @@ -482,7 +487,7 @@ zone.objective.attack = Destroy Enemy Core add = Add... boss.health = Boss Health -connectfail = [crimson]Connection error:\n\n[accent]{0} +connectfail = [scarlet]Connection error:\n\n[accent]{0} error.unreachable = Server unreachable.\nIs the address spelled correctly? error.invalidaddress = Invalid address. error.timedout = Timed out!\nMake sure the host has port forwarding set up, and that the address is correct! @@ -541,7 +546,7 @@ unplaceable.sectorcaptured = [scarlet]Requires captured sector yes = Yes no = No info.title = Info -error.title = [crimson]An error has occured +error.title = [scarlet]An error has occured error.crashtitle = An error has occured unit.nobuild = [scarlet]Unit can't build blocks.input = Input @@ -583,6 +588,8 @@ blocks.reload = Shots/Second blocks.ammo = Ammo bar.drilltierreq = Better Drill Required +bar.noresources = Missing Resources +bar.corereq = Core Base Required bar.drillspeed = Drill Speed: {0}/s bar.pumpspeed = Pump Speed: {0}/s bar.efficiency = Efficiency: {0}% @@ -664,7 +671,6 @@ setting.effects.name = Display Effects setting.destroyedblocks.name = Display Destroyed Blocks setting.blockstatus.name = Display Block Status setting.conveyorpathfinding.name = Conveyor Placement Pathfinding -setting.coreselect.name = Allow Schematic Cores setting.sensitivity.name = Controller Sensitivity setting.saveinterval.name = Save Interval setting.seconds = {0} seconds @@ -678,6 +684,7 @@ setting.blockselectkeys.name = Show Block Select Keys setting.vsync.name = VSync setting.pixelate.name = Pixelate setting.minimap.name = Show Minimap +setting.coreitems.name = Display Core Items (WIP) setting.position.name = Show Player Position setting.musicvol.name = Music Volume setting.atmosphere.name = Show Planet Atmosphere @@ -703,6 +710,7 @@ keybinds.mobile = [scarlet]Most keybinds here are not functional on mobile. Only category.general.name = General category.view.name = View category.multiplayer.name = Multiplayer +category.blocks.name = Block Select command.attack = Attack command.rally = Rally command.retreat = Retreat @@ -827,7 +835,6 @@ liquid.water.name = Water liquid.slag.name = Slag liquid.oil.name = Oil liquid.cryofluid.name = Cryofluid -item.corestorable = [lightgray]Storable in Core: {0} item.explosiveness = [lightgray]Explosiveness: {0}% item.flammability = [lightgray]Flammability: {0}% item.radioactivity = [lightgray]Radioactivity: {0}% @@ -1046,21 +1053,7 @@ team.orange.name = orange team.derelict.name = derelict team.green.name = green team.purple.name = purple -unit.spirit.name = Spirit Repair Drone -unit.draug.name = Draug Miner Drone -unit.phantom.name = Phantom Builder Drone -unit.dagger.name = Dagger -unit.crawler.name = Crawler -unit.titan.name = Titan -unit.ghoul.name = Ghoul Bomber -unit.wraith.name = Wraith Fighter -unit.fortress.name = Fortress -unit.revenant.name = Revenant -unit.eruptor.name = Eruptor -unit.chaos-array.name = Chaos Array -unit.eradicator.name = Eradicator -unit.lich.name = Lich -unit.reaper.name = Reaper + tutorial.next = [lightgray] tutorial.intro = You have entered the[scarlet] Mindustry Tutorial.[]\nUse[accent] [[WASD][] to move.\n[accent]Scroll[] to zoom in and out.\nBegin by[accent] mining copper[]. Move close to it, then tap a copper ore vein near your core to do this.\n\n[accent]{0}/{1} copper tutorial.intro.mobile = You have entered the[scarlet] Mindustry Tutorial.[]\nSwipe the screen to move.\n[accent]Pinch with 2 fingers[] to zoom in and out.\nBegin by[accent] mining copper[]. Move close to it, then tap a copper ore vein near your core to do this.\n\n[accent]{0}/{1} copper @@ -1103,17 +1096,7 @@ liquid.water.description = The most useful liquid. Commonly used for cooling mac liquid.slag.description = Various different types of molten metal mixed together. Can be separated into its constituent minerals, or sprayed at enemy units as a weapon. liquid.oil.description = A liquid used in advanced material production. Can be converted into coal as fuel, or sprayed and set on fire as a weapon. liquid.cryofluid.description = An inert, non-corrosive liquid created from water and titanium. Has extremely high heat capacity. Extensively used as coolant. -unit.draug.description = A primitive mining drone. Cheap to produce. Expendable. Automatically mines copper and lead in the vicinity. Delivers mined resources to the closest core. -unit.spirit.description = A modified draug drone, designed for repair instead of mining. Automatically fixes any damaged blocks in the area. -unit.phantom.description = An advanced drone unit. Follows users. Assists in block construction. Rebuilds destroyed blocks. -unit.dagger.description = The most basic ground mech. Cheap to produce. Overwhelming when used in swarms. -unit.crawler.description = A ground unit consisting of a stripped-down frame with high explosives strapped on top. Not particular durable. Explodes on contact with enemies. -unit.titan.description = An advanced, armored ground unit. Attacks both ground and air targets. Equipped with two miniature Scorch-class flamethrowers. -unit.fortress.description = A heavy artillery mech. Equipped with two modified Hail-type cannons for long-range assault on enemy structures and units. -unit.eruptor.description = A heavy mech designed to take down structures. Fires a stream of slag at enemy fortifications, melting them and setting volatiles on fire. -unit.wraith.description = A fast, hit-and-run interceptor unit. Targets power generators. -unit.ghoul.description = A heavy carpet bomber. Rips through enemy structures, targeting critical infrastructure. -unit.revenant.description = A heavy, hovering missile array. + block.message.description = Stores a message. Used for communication between allies. block.graphite-press.description = Compresses chunks of coal into pure sheets of graphite. block.multi-press.description = An upgraded version of the graphite press. Employs water and power to process coal quickly and efficiently. diff --git a/core/assets/icons/icons.properties b/core/assets/icons/icons.properties index 93b81a045e..ced18aafd9 100755 --- a/core/assets/icons/icons.properties +++ b/core/assets/icons/icons.properties @@ -252,3 +252,4 @@ 63492=exponential-reconstructor|block-exponential-reconstructor-medium 63491=tetrative-reconstructor|block-tetrative-reconstructor-medium 63490=resupply-point|block-resupply-point-medium +63489=parallax|block-parallax-medium diff --git a/core/assets/maps/groundZero.msav b/core/assets/maps/groundZero.msav index 628ab59ece..da07ea1925 100644 Binary files a/core/assets/maps/groundZero.msav and b/core/assets/maps/groundZero.msav differ diff --git a/core/assets/scripts/global.js b/core/assets/scripts/global.js index 11ced98b60..5d2f80aec7 100755 --- a/core/assets/scripts/global.js +++ b/core/assets/scripts/global.js @@ -24,72 +24,73 @@ const extend = function(classType, params){ const newEffect = (lifetime, renderer) => new Effects.Effect(lifetime, new Effects.EffectRenderer({render: renderer})) Call = Packages.mindustry.gen.Call -importPackage(Packages.arc.scene.ui) -importPackage(Packages.mindustry.editor) -importPackage(Packages.mindustry.entities.comp) -importPackage(Packages.mindustry.graphics.g3d) -importPackage(Packages.mindustry.world.blocks.sandbox) -importPackage(Packages.mindustry.game) -importPackage(Packages.mindustry.ui.dialogs) -importPackage(Packages.mindustry.ui.fragments) -importPackage(Packages.mindustry.world.blocks.environment) -importPackage(Packages.arc.math) importPackage(Packages.mindustry.world.blocks.power) -importPackage(Packages.mindustry.core) +importPackage(Packages.mindustry.game) +importPackage(Packages.arc.scene) +importPackage(Packages.mindustry.maps.filters) +importPackage(Packages.mindustry.gen) importPackage(Packages.arc.struct) -importPackage(Packages.mindustry.maps) +importPackage(Packages.mindustry.world.meta) +importPackage(Packages.arc.func) +importPackage(Packages.arc.math) +importPackage(Packages.mindustry.type) +importPackage(Packages.mindustry.world.blocks.environment) importPackage(Packages.arc.scene.actions) -importPackage(Packages.mindustry.ctype) +importPackage(Packages.arc.math.geom) +importPackage(Packages.mindustry.world.consumers) +importPackage(Packages.mindustry.graphics) +importPackage(Packages.arc.graphics) +importPackage(Packages.mindustry.world.blocks.units) +importPackage(Packages.mindustry.world.blocks.distribution) +importPackage(Packages.mindustry.world.blocks) +importPackage(Packages.mindustry.ui) +importPackage(Packages.mindustry.core) +importPackage(Packages.arc.scene.ui) +importPackage(Packages.arc.scene.ui.layout) +importPackage(Packages.mindustry.entities.comp) +importPackage(Packages.mindustry.ui.fragments) +importPackage(Packages.mindustry.entities) importPackage(Packages.mindustry.ai.formations) importPackage(Packages.arc.scene.utils) -importPackage(Packages.mindustry.world.blocks.defense) -importPackage(Packages.mindustry.ai.types) -importPackage(Packages.mindustry.gen) -importPackage(Packages.mindustry.world.blocks.distribution) -importPackage(Packages.mindustry.world.meta) -importPackage(Packages.mindustry.maps.filters) -importPackage(Packages.mindustry.logic) -importPackage(Packages.arc.math.geom) -importPackage(Packages.mindustry.graphics) -importPackage(Packages.mindustry.entities.bullet) -importPackage(Packages.mindustry.world.meta.values) -importPackage(Packages.mindustry.input) -importPackage(Packages.mindustry.entities) -importPackage(Packages.arc.func) -importPackage(Packages.mindustry.world.blocks.experimental) -importPackage(Packages.mindustry.world.consumers) -importPackage(Packages.mindustry.ai) -importPackage(Packages.mindustry.world.blocks.legacy) -importPackage(Packages.mindustry.world.modules) -importPackage(Packages.mindustry.async) -importPackage(Packages.mindustry.content) -importPackage(Packages.arc.graphics.g2d) -importPackage(Packages.mindustry.ui) -importPackage(Packages.mindustry.ui.layout) -importPackage(Packages.mindustry.entities.units) -importPackage(Packages.mindustry.type) -importPackage(Packages.arc.scene) -importPackage(Packages.mindustry.world.blocks.production) -importPackage(Packages.mindustry) -importPackage(Packages.mindustry.world.blocks.storage) -importPackage(Packages.mindustry.world) -importPackage(Packages.mindustry.world.blocks.units) -importPackage(Packages.arc.scene.event) -importPackage(Packages.arc.scene.ui.layout) -importPackage(Packages.mindustry.world.blocks.defense.turrets) -importPackage(Packages.arc.scene.style) -importPackage(Packages.arc.graphics) -importPackage(Packages.mindustry.world.blocks.liquid) -importPackage(Packages.mindustry.world.blocks) -importPackage(Packages.mindustry.audio) -importPackage(Packages.mindustry.ai.formations.patterns) -importPackage(Packages.mindustry.world.blocks.payloads) -importPackage(Packages.mindustry.maps.planet) -importPackage(Packages.arc.util) -importPackage(Packages.mindustry.world.producers) -importPackage(Packages.arc) -importPackage(Packages.mindustry.maps.generators) importPackage(Packages.mindustry.world.blocks.campaign) +importPackage(Packages.mindustry.content) +importPackage(Packages.mindustry.world.blocks.storage) +importPackage(Packages.mindustry.world.meta.values) +importPackage(Packages.mindustry.world) +importPackage(Packages.mindustry.world.blocks.experimental) +importPackage(Packages.arc.scene.event) +importPackage(Packages.mindustry.graphics.g3d) +importPackage(Packages.mindustry.ui.dialogs) +importPackage(Packages.mindustry.world.blocks.defense) +importPackage(Packages.mindustry.maps) +importPackage(Packages.mindustry.world.blocks.legacy) +importPackage(Packages.mindustry.ctype) +importPackage(Packages.mindustry.world.blocks.defense.turrets) +importPackage(Packages.mindustry.world.draw) +importPackage(Packages.mindustry.editor) +importPackage(Packages.mindustry.entities.bullet) +importPackage(Packages.mindustry.logic) +importPackage(Packages.arc.scene.style) +importPackage(Packages.mindustry.audio) +importPackage(Packages.mindustry.entities.units) +importPackage(Packages.mindustry.world.blocks.production) +importPackage(Packages.mindustry.ai.formations.patterns) +importPackage(Packages.mindustry.input) +importPackage(Packages.arc.util) +importPackage(Packages.mindustry.world.blocks.sandbox) +importPackage(Packages.mindustry.ai) +importPackage(Packages.mindustry.async) +importPackage(Packages.mindustry.world.blocks.liquid) +importPackage(Packages.arc) +importPackage(Packages.mindustry.ai.types) +importPackage(Packages.mindustry.world.modules) +importPackage(Packages.arc.graphics.g2d) +importPackage(Packages.mindustry.ui.layout) +importPackage(Packages.mindustry.maps.generators) +importPackage(Packages.mindustry.world.blocks.payloads) +importPackage(Packages.mindustry.world.producers) +importPackage(Packages.mindustry) +importPackage(Packages.mindustry.maps.planet) const PlayerIpUnbanEvent = Packages.mindustry.game.EventType.PlayerIpUnbanEvent const PlayerIpBanEvent = Packages.mindustry.game.EventType.PlayerIpBanEvent const PlayerUnbanEvent = Packages.mindustry.game.EventType.PlayerUnbanEvent @@ -107,7 +108,7 @@ const BlockBuildBeginEvent = Packages.mindustry.game.EventType.BlockBuildBeginEv const ResearchEvent = Packages.mindustry.game.EventType.ResearchEvent const UnlockEvent = Packages.mindustry.game.EventType.UnlockEvent const StateChangeEvent = Packages.mindustry.game.EventType.StateChangeEvent -const TileChangeEvent = Packages.mindustry.game.EventType.TileChangeEvent +const BuildinghangeEvent = Packages.mindustry.game.EventType.BuildinghangeEvent const GameOverEvent = Packages.mindustry.game.EventType.GameOverEvent const TapConfigEvent = Packages.mindustry.game.EventType.TapConfigEvent const TapEvent = Packages.mindustry.game.EventType.TapEvent @@ -129,7 +130,6 @@ const WaveEvent = Packages.mindustry.game.EventType.WaveEvent const ResetEvent = Packages.mindustry.game.EventType.ResetEvent const PlayEvent = Packages.mindustry.game.EventType.PlayEvent const DisposeEvent = Packages.mindustry.game.EventType.DisposeEvent -const ContentReloadEvent = Packages.mindustry.game.EventType.ContentReloadEvent const ServerLoadEvent = Packages.mindustry.game.EventType.ServerLoadEvent const ClientCreateEvent = Packages.mindustry.game.EventType.ClientCreateEvent const SaveLoadEvent = Packages.mindustry.game.EventType.SaveLoadEvent @@ -139,5 +139,4 @@ const ResizeEvent = Packages.mindustry.game.EventType.ResizeEvent const LaunchEvent = Packages.mindustry.game.EventType.LaunchEvent const LoseEvent = Packages.mindustry.game.EventType.LoseEvent const WinEvent = Packages.mindustry.game.EventType.WinEvent -const TurnEvent = Packages.mindustry.game.EventType.TurnEvent const Trigger = Packages.mindustry.game.EventType.Trigger diff --git a/core/assets/shaders/screenspace.frag b/core/assets/shaders/screenspace.frag index 493c608d6f..9cd773ad8c 100644 --- a/core/assets/shaders/screenspace.frag +++ b/core/assets/shaders/screenspace.frag @@ -1,4 +1,3 @@ - uniform sampler2D u_texture; varying vec2 v_texCoords; diff --git a/core/assets/shaders/shield.frag b/core/assets/shaders/shield.frag index bc953f1dcf..d4fdd10998 100644 --- a/core/assets/shaders/shield.frag +++ b/core/assets/shaders/shield.frag @@ -1,17 +1,14 @@ #define HIGHP -#define MAX_HITS 64 -#define HIT_RADIUS 12.0 #define ALPHA 0.18 -#define thickness 1.0 #define step 2.0 uniform sampler2D u_texture; uniform vec2 u_texsize; +uniform vec2 u_invsize; uniform float u_time; uniform float u_dp; uniform vec2 u_offset; -uniform vec4 u_shieldcolor; varying vec2 v_texCoords; @@ -20,20 +17,19 @@ void main(){ vec2 coords = (T * u_texsize) + u_offset; T += vec2(sin(coords.y / 3.0 + u_time / 20.0), sin(coords.x / 3.0 + u_time / 20.0)) / u_texsize; - - float si = sin(u_time / 20.0) / 8.0; + vec4 color = texture2D(u_texture, T); - vec2 v = vec2(1.0/u_texsize.x, 1.0/u_texsize.y); + vec2 v = u_invsize; - if(texture2D(u_texture, T).a < 0.9 && - (texture2D(u_texture, T + vec2(0, step) * v).a > 0.0 || texture2D(u_texture, T + vec2(0, -step) * v).a > 0.0 || - texture2D(u_texture, T + vec2(step, 0) * v).a > 0.0 || texture2D(u_texture, T + vec2(-step, 0) * v).a > 0.0)){ + vec4 maxed = max(max(max(texture2D(u_texture, T + vec2(0, step) * v), texture2D(u_texture, T + vec2(0, -step) * v)), texture2D(u_texture, T + vec2(step, 0) * v)), texture2D(u_texture, T + vec2(-step, 0) * v)); - gl_FragColor = mix(u_shieldcolor, vec4(1.0), si); + if(texture2D(u_texture, T).a < 0.9 && maxed.a > 0.9){ + + gl_FragColor = vec4(maxed.rgb, maxed.a * 100.0); }else{ if(color.a > 0.0){ - if(mod(coords.x / u_dp + coords.y / u_dp + sin(floor(coords.x / u_dp) / 5.0) * 3.0 + sin(floor(coords.y / u_dp) / 5.0) * 3.0 + u_time / 4.0, 10.0) < 2.0){ + if(mod(coords.x / u_dp + coords.y / u_dp + sin(coords.x / u_dp / 5.0) * 3.0 + sin(coords.y / u_dp / 5.0) * 3.0 + u_time / 4.0, 10.0) < 2.0){ color *= 1.65; } diff --git a/core/assets/shaders/water.frag b/core/assets/shaders/water.frag index 18a4258852..f0c41ccd24 100644 --- a/core/assets/shaders/water.frag +++ b/core/assets/shaders/water.frag @@ -13,7 +13,7 @@ const float mth = 7.0; void main(){ - vec2 c = v_texCoords.xy; + vec2 c = v_texCoords; vec2 v = vec2(1.0/u_resolution.x, 1.0/u_resolution.y); vec2 coords = vec2(c.x / v.x + u_campos.x, c.y / v.y + u_campos.y); diff --git a/core/assets/sprites/block_colors.png b/core/assets/sprites/block_colors.png index 4a55acf109..7c87b67e29 100644 Binary files a/core/assets/sprites/block_colors.png and b/core/assets/sprites/block_colors.png differ diff --git a/core/assets/sprites/fallback/sprites.atlas b/core/assets/sprites/fallback/sprites.atlas index 1eee5d2200..514a7620f1 100644 --- a/core/assets/sprites/fallback/sprites.atlas +++ b/core/assets/sprites/fallback/sprites.atlas @@ -4,534 +4,429 @@ size: 2048,2048 format: rgba8888 filter: nearest,nearest repeat: none -core-silo - rotate: false - xy: 1884, 613 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -blast-drill - rotate: false - xy: 1843, 159 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 white-tree rotate: false - xy: 1, 1083 + xy: 323, 1720 size: 320, 320 orig: 320, 320 offset: 0, 0 index: -1 white-tree-dead rotate: false - xy: 323, 1405 + xy: 645, 1720 size: 320, 320 orig: 320, 320 offset: 0, 0 index: -1 core-nucleus rotate: false - xy: 1722, 613 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -core-nucleus-team - rotate: false - xy: 1195, 419 + xy: 1873, 364 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 exponential-reconstructor rotate: false - xy: 775, 501 + xy: 323, 204 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 exponential-reconstructor-top rotate: false - xy: 775, 275 + xy: 549, 204 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 -factory-in-5 - rotate: false - xy: 1681, 289 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 factory-in-7 rotate: false - xy: 775, 49 + xy: 775, 10 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 factory-in-9 rotate: false - xy: 1225, 1469 + xy: 323, 1140 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 -factory-out-5 - rotate: false - xy: 1843, 451 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 factory-out-7 rotate: false - xy: 1065, 985 + xy: 1001, 462 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 factory-out-9 rotate: false - xy: 1515, 1759 + xy: 613, 1140 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 -multiplicative-reconstructor - rotate: false - xy: 1681, 127 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -multiplicative-reconstructor-top - rotate: false - xy: 1843, 289 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 tetrative-reconstructor rotate: false - xy: 1515, 1469 + xy: 1193, 1172 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 tetrative-reconstructor-top rotate: false - xy: 645, 1179 + xy: 1483, 1172 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 circle-shadow rotate: false - xy: 1001, 750 + xy: 323, 1 size: 201, 201 orig: 201, 201 offset: 0, 0 index: -1 +antumbra-wreck0 + rotate: false + xy: 1437, 446 + size: 216, 240 + orig: 216, 240 + offset: 0, 0 + index: -1 +antumbra-wreck1 + rotate: false + xy: 1655, 446 + size: 216, 240 + orig: 216, 240 + offset: 0, 0 + index: -1 +antumbra-wreck2 + rotate: false + xy: 1437, 204 + size: 216, 240 + orig: 216, 240 + offset: 0, 0 + index: -1 block-core-nucleus-full rotate: false - xy: 1398, 613 + xy: 1837, 1492 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 block-exponential-reconstructor-full rotate: false - xy: 1805, 1823 + xy: 839, 688 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 block-multiplicative-reconstructor-full rotate: false - xy: 1560, 613 + xy: 1873, 526 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 block-tetrative-reconstructor-full rotate: false - xy: 645, 1759 + xy: 967, 1752 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 -core-nucleus-team-crux - rotate: false - xy: 1195, 257 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -core-nucleus-team-sharded - rotate: false - xy: 1001, 6 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -cracks-5-0 - rotate: false - xy: 1195, 95 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -cracks-5-1 - rotate: false - xy: 1357, 419 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -cracks-5-2 - rotate: false - xy: 1357, 257 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -cracks-5-3 - rotate: false - xy: 1357, 95 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -cracks-5-4 - rotate: false - xy: 1519, 451 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -cracks-5-5 - rotate: false - xy: 1519, 289 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -cracks-5-6 - rotate: false - xy: 1681, 451 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -cracks-5-7 - rotate: false - xy: 1519, 127 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 cracks-6-0 rotate: false - xy: 1001, 556 + xy: 526, 10 size: 192, 192 orig: 192, 192 offset: 0, 0 index: -1 cracks-6-1 rotate: false - xy: 1001, 362 + xy: 1001, 26 size: 192, 192 orig: 192, 192 offset: 0, 0 index: -1 cracks-6-2 rotate: false - xy: 1001, 168 + xy: 1195, 26 size: 192, 192 orig: 192, 192 offset: 0, 0 index: -1 cracks-6-3 rotate: false - xy: 1204, 775 + xy: 1837, 1848 size: 192, 192 orig: 192, 192 offset: 0, 0 index: -1 cracks-6-4 rotate: false - xy: 1398, 775 + xy: 1837, 1654 size: 192, 192 orig: 192, 192 offset: 0, 0 index: -1 cracks-6-5 rotate: false - xy: 1592, 775 + xy: 1389, 10 size: 192, 192 orig: 192, 192 offset: 0, 0 index: -1 cracks-6-6 rotate: false - xy: 1786, 775 + xy: 1583, 10 size: 192, 192 orig: 192, 192 offset: 0, 0 index: -1 cracks-6-7 rotate: false - xy: 1204, 581 + xy: 1777, 10 size: 192, 192 orig: 192, 192 offset: 0, 0 index: -1 cracks-7-0 rotate: false - xy: 1805, 1597 + xy: 323, 656 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 cracks-7-1 rotate: false - xy: 613, 953 + xy: 549, 656 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 cracks-7-2 rotate: false - xy: 549, 727 + xy: 1065, 688 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 cracks-7-3 rotate: false - xy: 549, 501 + xy: 1291, 688 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 cracks-7-4 rotate: false - xy: 549, 275 + xy: 775, 462 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 cracks-7-5 rotate: false - xy: 549, 49 + xy: 323, 430 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 cracks-7-6 rotate: false - xy: 839, 953 + xy: 549, 430 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 cracks-7-7 rotate: false - xy: 775, 727 + xy: 775, 236 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 cracks-8-0 rotate: false - xy: 935, 1211 + xy: 1773, 1204 size: 256, 256 orig: 256, 256 offset: 0, 0 index: -1 cracks-8-1 rotate: false - xy: 1193, 1211 + xy: 1773, 946 size: 256, 256 orig: 256, 256 offset: 0, 0 index: -1 cracks-8-2 rotate: false - xy: 1451, 1211 + xy: 903, 914 size: 256, 256 orig: 256, 256 offset: 0, 0 index: -1 cracks-8-3 rotate: false - xy: 1709, 1211 + xy: 323, 882 size: 256, 256 orig: 256, 256 offset: 0, 0 index: -1 cracks-8-4 rotate: false - xy: 291, 825 + xy: 581, 882 size: 256, 256 orig: 256, 256 offset: 0, 0 index: -1 cracks-8-5 rotate: false - xy: 291, 567 + xy: 1161, 914 size: 256, 256 orig: 256, 256 offset: 0, 0 index: -1 cracks-8-6 rotate: false - xy: 291, 309 + xy: 1419, 914 size: 256, 256 orig: 256, 256 offset: 0, 0 index: -1 cracks-8-7 rotate: false - xy: 291, 51 + xy: 1677, 688 size: 256, 256 orig: 256, 256 offset: 0, 0 index: -1 cracks-9-0 rotate: false - xy: 1, 793 + xy: 1257, 1752 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 cracks-9-1 rotate: false - xy: 323, 1115 + xy: 1547, 1752 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 cracks-9-2 rotate: false - xy: 645, 1469 + xy: 967, 1462 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 cracks-9-3 rotate: false - xy: 935, 1759 + xy: 323, 1430 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 cracks-9-4 rotate: false - xy: 1, 503 + xy: 613, 1430 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 cracks-9-5 rotate: false - xy: 935, 1469 + xy: 1257, 1462 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 cracks-9-6 rotate: false - xy: 1225, 1759 + xy: 1547, 1462 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 cracks-9-7 rotate: false - xy: 1, 213 + xy: 903, 1172 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 -unit-lich-full +eclipse-wreck0 rotate: false - xy: 1727, 969 + xy: 1, 1076 + size: 320, 320 + orig: 320, 320 + offset: 0, 0 + index: -1 +eclipse-wreck1 + rotate: false + xy: 1, 754 + size: 320, 320 + orig: 320, 320 + offset: 0, 0 + index: -1 +eclipse-wreck2 + rotate: false + xy: 1, 432 + size: 320, 320 + orig: 320, 320 + offset: 0, 0 + index: -1 +unit-antumbra-full + rotate: false + xy: 1655, 204 size: 216, 240 orig: 216, 240 offset: 0, 0 index: -1 -unit-reaper-full +unit-eclipse-full rotate: false - xy: 323, 1727 + xy: 1, 110 size: 320, 320 orig: 320, 320 offset: 0, 0 index: -1 circle rotate: false - xy: 1, 10 + xy: 1227, 485 size: 201, 201 orig: 201, 201 offset: 0, 0 index: -1 -eradicator +antumbra rotate: false - xy: 1519, 1 - size: 152, 124 - orig: 152, 124 - offset: 0, 0 - index: -1 -eradicator-base - rotate: false - xy: 1673, 1 - size: 152, 124 - orig: 152, 124 - offset: 0, 0 - index: -1 -eradicator-cell - rotate: false - xy: 1827, 1 - size: 152, 124 - orig: 152, 124 - offset: 0, 0 - index: -1 -eradicator-leg - rotate: false - xy: 1805, 1471 - size: 152, 124 - orig: 152, 124 - offset: 0, 0 - index: -1 -lich - rotate: false - xy: 1291, 969 + xy: 1001, 220 size: 216, 240 orig: 216, 240 offset: 0, 0 index: -1 -lich-cell +antumbra-cell rotate: false - xy: 1509, 969 + xy: 1219, 220 size: 216, 240 orig: 216, 240 offset: 0, 0 index: -1 -reaper +eclipse rotate: false - xy: 1, 1727 + xy: 1, 1720 size: 320, 320 orig: 320, 320 offset: 0, 0 index: -1 -reaper-cell +eclipse-cell rotate: false - xy: 1, 1405 + xy: 1, 1398 size: 320, 320 orig: 320, 320 offset: 0, 0 @@ -542,5233 +437,5856 @@ size: 2048,2048 format: rgba8888 filter: nearest,nearest repeat: none +core-silo + rotate: false + xy: 1, 1563 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 data-processor rotate: false - xy: 397, 763 + xy: 1123, 1413 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 data-processor-2 rotate: false - xy: 1075, 1591 + xy: 831, 531 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 data-processor-top rotate: false - xy: 397, 665 + xy: 1221, 1413 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 launch-pad rotate: false - xy: 393, 371 + xy: 489, 735 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 launch-pad-large rotate: false - xy: 521, 1529 + xy: 1721, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 launch-pad-light rotate: false - xy: 491, 469 + xy: 489, 637 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 launchpod rotate: false - xy: 1527, 1689 + xy: 1981, 1983 size: 66, 64 orig: 66, 64 offset: 0, 0 index: -1 force-projector rotate: false - xy: 397, 567 + xy: 1319, 1393 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 force-projector-top rotate: false - xy: 495, 567 + xy: 1417, 1393 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 large-overdrive-projector rotate: false - xy: 295, 469 + xy: 1711, 1393 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 large-overdrive-projector-top rotate: false - xy: 197, 273 + xy: 1809, 1393 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mend-projector rotate: false - xy: 659, 739 + xy: 903, 603 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mend-projector-top rotate: false - xy: 659, 673 + xy: 897, 537 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mender rotate: false - xy: 953, 3 + xy: 1991, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mender-top rotate: false - xy: 1233, 1191 + xy: 1983, 691 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 overdrive-projector rotate: false - xy: 659, 541 + xy: 983, 751 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 overdrive-projector-top rotate: false - xy: 655, 475 + xy: 979, 685 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 shock-mine rotate: false - xy: 1321, 1127 + xy: 1939, 521 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-loader rotate: false - xy: 911, 1739 + xy: 391, 817 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-unloader rotate: false - xy: 1629, 1853 + xy: 375, 33 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 bridge-arrow rotate: false - xy: 879, 513 + xy: 1787, 733 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor rotate: false - xy: 845, 377 + xy: 1813, 665 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-bridge rotate: false - xy: 879, 411 + xy: 1805, 631 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-end rotate: false - xy: 845, 343 + xy: 1805, 597 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 center rotate: false - xy: 879, 377 + xy: 1839, 631 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-0-0 rotate: false - xy: 821, 79 + xy: 473, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-armored-conveyor-full rotate: false - xy: 821, 79 + xy: 473, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-0-1 rotate: false - xy: 817, 45 + xy: 507, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-0-2 rotate: false - xy: 817, 11 + xy: 1979, 1591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-0-3 rotate: false - xy: 1735, 1360 + xy: 1073, 345 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-1-0 rotate: false - xy: 1731, 1326 + xy: 1667, 913 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-1-1 rotate: false - xy: 1731, 1292 + xy: 1583, 787 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-1-2 rotate: false - xy: 1751, 1474 + xy: 1625, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-1-3 rotate: false - xy: 1785, 1481 + xy: 1499, 661 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-2-0 rotate: false - xy: 1819, 1481 + xy: 1541, 703 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-2-1 rotate: false - xy: 1525, 1275 + xy: 1667, 879 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-2-2 rotate: false - xy: 1559, 1275 + xy: 1583, 753 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-2-3 rotate: false - xy: 803, 1057 + xy: 2013, 1591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-3-0 rotate: false - xy: 837, 1057 + xy: 2005, 1557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-3-1 rotate: false - xy: 871, 1057 + xy: 2005, 1523 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-3-2 rotate: false - xy: 905, 1057 + xy: 2005, 1489 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-3-3 rotate: false - xy: 787, 1023 + xy: 2005, 1455 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-4-0 rotate: false - xy: 821, 1023 + xy: 2005, 1421 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-4-1 rotate: false - xy: 855, 1023 + xy: 207, 5 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-4-2 rotate: false - xy: 889, 1023 + xy: 1107, 6 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-4-3 rotate: false - xy: 791, 989 + xy: 1141, 6 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-1 rotate: false - xy: 879, 139 + xy: 1299, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-2 rotate: false - xy: 913, 513 + xy: 1297, 589 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-3 rotate: false - xy: 913, 479 + xy: 1293, 555 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-0 rotate: false - xy: 913, 445 + xy: 1293, 521 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-1 rotate: false - xy: 913, 411 + xy: 1327, 555 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-2 rotate: false - xy: 913, 377 + xy: 1327, 521 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-3 rotate: false - xy: 913, 343 + xy: 1331, 589 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-0 rotate: false - xy: 913, 309 + xy: 1365, 593 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-1 rotate: false - xy: 913, 275 + xy: 1399, 593 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-2 rotate: false - xy: 913, 241 + xy: 1311, 487 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-3 rotate: false - xy: 913, 207 + xy: 1311, 453 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-0 rotate: false - xy: 913, 173 + xy: 1345, 487 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-1 rotate: false - xy: 913, 139 + xy: 1345, 453 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-2 rotate: false - xy: 1153, 965 + xy: 1321, 419 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-3 rotate: false - xy: 1187, 965 + xy: 1321, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-0 rotate: false - xy: 1221, 965 + xy: 1355, 419 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-1 rotate: false - xy: 1693, 1271 + xy: 1355, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-2 rotate: false - xy: 1727, 1258 + xy: 1346, 351 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-3 rotate: false - xy: 855, 105 + xy: 1346, 317 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-conveyor rotate: false - xy: 927, 829 + xy: 2009, 589 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-conveyor-0 rotate: false - xy: 927, 795 + xy: 1973, 895 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-conveyor-1 rotate: false - xy: 927, 761 + xy: 1973, 861 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-conveyor-2 rotate: false - xy: 927, 727 + xy: 1999, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-conveyor-edge rotate: false - xy: 927, 693 + xy: 1463, 585 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-conveyor-stack rotate: false - xy: 927, 659 + xy: 1463, 551 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-1 rotate: false - xy: 1369, 1161 + xy: 2007, 487 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-2 rotate: false - xy: 1389, 1127 + xy: 1481, 491 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-3 rotate: false - xy: 1389, 1093 + xy: 1481, 457 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-0 rotate: false - xy: 1389, 1059 + xy: 1515, 491 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-1 rotate: false - xy: 1389, 1025 + xy: 1515, 457 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-2 rotate: false - xy: 1391, 991 + xy: 1491, 423 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-3 rotate: false - xy: 1391, 957 + xy: 1491, 389 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-0 rotate: false - xy: 1397, 1229 + xy: 1525, 423 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-1 rotate: false - xy: 1403, 1195 + xy: 1525, 389 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-2 rotate: false - xy: 1403, 1161 + xy: 1516, 355 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-3 rotate: false - xy: 1423, 1127 + xy: 1516, 321 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-0 rotate: false - xy: 1423, 1093 + xy: 1516, 287 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-1 rotate: false - xy: 1423, 1059 + xy: 1549, 481 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-2 rotate: false - xy: 1423, 1025 + xy: 1583, 481 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-3 rotate: false - xy: 1425, 991 + xy: 1559, 447 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-0 rotate: false - xy: 1425, 957 + xy: 1559, 413 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-1 rotate: false - xy: 1431, 1229 + xy: 1593, 447 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-2 rotate: false - xy: 1437, 1195 + xy: 1593, 413 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-3 rotate: false - xy: 1437, 1161 + xy: 1559, 379 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cross rotate: false - xy: 919, 37 + xy: 1389, 385 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 distributor rotate: false - xy: 1565, 1593 + xy: 851, 267 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 inverted-sorter rotate: false - xy: 1887, 1439 + xy: 1429, 525 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 junction rotate: false - xy: 1969, 1303 + xy: 1897, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mass-conveyor rotate: false - xy: 393, 175 + xy: 1107, 1311 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mass-conveyor-edge rotate: false - xy: 491, 273 + xy: 1205, 1315 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mass-conveyor-top rotate: false - xy: 491, 175 + xy: 1303, 1295 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 payload-router-top rotate: false - xy: 491, 175 + xy: 1303, 1295 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mass-driver-base rotate: false - xy: 295, 77 + xy: 1499, 1295 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 overflow-gate rotate: false - xy: 1253, 1123 + xy: 1907, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 payload-router rotate: false - xy: 879, 1625 + xy: 1401, 1197 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 payload-router-edge rotate: false - xy: 929, 1429 + xy: 1499, 1197 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 payload-router-over rotate: false - xy: 961, 1527 + xy: 1597, 1197 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 phase-conveyor rotate: false - xy: 1255, 953 + xy: 1907, 589 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-arrow rotate: false - xy: 927, 965 + xy: 1941, 589 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-bridge rotate: false - xy: 927, 931 + xy: 1975, 589 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-end rotate: false - xy: 927, 897 + xy: 2009, 657 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 router rotate: false - xy: 1267, 1195 + xy: 1701, 529 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sorter rotate: false - xy: 1321, 1059 + xy: 2007, 521 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 underflow-gate rotate: false - xy: 1457, 1059 + xy: 1550, 311 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 +blast-drill + rotate: false + xy: 1, 817 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 blast-drill-rim rotate: false - xy: 1, 1919 + xy: 1071, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 blast-drill-rotator rotate: false - xy: 1, 1789 + xy: 1, 687 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 blast-drill-top rotate: false - xy: 131, 1919 + xy: 1201, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 drill-top rotate: false - xy: 1763, 1573 + xy: 851, 69 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 turbine-generator-liquid rotate: false - xy: 1763, 1573 + xy: 851, 69 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 laser-drill rotate: false - xy: 295, 371 + xy: 1907, 1491 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-rim rotate: false - xy: 393, 469 + xy: 1907, 1393 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-rotator rotate: false - xy: 197, 175 + xy: 493, 931 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-top rotate: false - xy: 295, 273 + xy: 489, 833 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mechanical-drill rotate: false - xy: 659, 937 + xy: 917, 801 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-drill-rotator rotate: false - xy: 659, 871 + xy: 913, 735 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-drill-top rotate: false - xy: 659, 805 + xy: 913, 669 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 oil-extractor rotate: false - xy: 635, 1431 + xy: 1793, 1295 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-liquid rotate: false - xy: 733, 1429 + xy: 1891, 1295 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-rotator rotate: false - xy: 831, 1429 + xy: 1205, 1217 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-top rotate: false - xy: 863, 1527 + xy: 1303, 1197 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 pneumatic-drill rotate: false - xy: 721, 1003 + xy: 1051, 1031 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-rotator rotate: false - xy: 725, 937 + xy: 1051, 965 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-top rotate: false - xy: 725, 871 + xy: 1051, 899 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor rotate: false - xy: 1301, 1549 + xy: 1079, 445 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-liquid rotate: false - xy: 1367, 1549 + xy: 1073, 379 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-rotator rotate: false - xy: 1433, 1549 + xy: 1145, 425 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-top rotate: false - xy: 1499, 1549 + xy: 1139, 359 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-border rotate: false - xy: 825, 955 + xy: 1277, 461 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-middle rotate: false - xy: 825, 717 + xy: 1735, 903 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-select rotate: false - xy: 893, 853 + xy: 1669, 631 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-liquid rotate: false - xy: 845, 207 + xy: 1821, 733 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 message rotate: false - xy: 1233, 1157 + xy: 1907, 657 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 place-arrow rotate: false - xy: 1027, 1429 + xy: 1695, 1197 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 bridge-conduit rotate: false - xy: 845, 445 + xy: 1787, 699 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-arrow rotate: false - xy: 879, 479 + xy: 1779, 665 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-arrow rotate: false - xy: 879, 479 + xy: 1779, 665 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-bridge rotate: false - xy: 845, 411 + xy: 1771, 631 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-end rotate: false - xy: 879, 445 + xy: 1771, 597 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom rotate: false - xy: 845, 275 + xy: 1769, 869 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-0 rotate: false - xy: 879, 309 + xy: 1769, 835 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-1 rotate: false - xy: 845, 241 + xy: 1795, 801 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-2 rotate: false - xy: 879, 275 + xy: 1821, 767 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-3 rotate: false - xy: 879, 275 + xy: 1821, 767 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-4 rotate: false - xy: 879, 275 + xy: 1821, 767 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-0 rotate: false - xy: 879, 241 + xy: 1821, 699 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-1 rotate: false - xy: 845, 173 + xy: 1847, 665 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-2 rotate: false - xy: 879, 207 + xy: 1873, 631 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-3 rotate: false - xy: 845, 139 + xy: 1873, 597 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-3 rotate: false - xy: 845, 139 + xy: 1873, 597 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-4 rotate: false - xy: 879, 173 + xy: 1419, 1047 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-junction rotate: false - xy: 1901, 1269 + xy: 1855, 759 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-overflow-gate rotate: false - xy: 1829, 1235 + xy: 1923, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-overflow-gate-top rotate: false - xy: 1863, 1235 + xy: 1889, 759 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-bottom rotate: false - xy: 1897, 1235 + xy: 1923, 759 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-liquid rotate: false - xy: 1931, 1235 + xy: 1889, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-top rotate: false - xy: 1965, 1235 + xy: 1923, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-tank-bottom rotate: false - xy: 295, 175 + xy: 489, 539 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 liquid-tank-liquid rotate: false - xy: 393, 273 + xy: 489, 441 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 liquid-tank-top rotate: false - xy: 491, 371 + xy: 489, 343 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mechanical-pump rotate: false - xy: 1593, 1263 + xy: 1949, 691 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mechanical-pump-liquid rotate: false - xy: 1627, 1263 + xy: 1991, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rotary-pump-liquid rotate: false - xy: 1627, 1263 + xy: 1991, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thermal-pump-liquid rotate: false - xy: 1627, 1263 + xy: 1991, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit rotate: false - xy: 1253, 1089 + xy: 1941, 657 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-arrow rotate: false - xy: 1253, 1055 + xy: 1941, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-bridge rotate: false - xy: 1253, 1021 + xy: 1975, 657 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-end rotate: false - xy: 1255, 987 + xy: 1975, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plated-conduit-cap rotate: false - xy: 927, 591 + xy: 1531, 593 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plated-conduit-top-0 rotate: false - xy: 927, 557 + xy: 1497, 559 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plated-conduit-top-1 rotate: false - xy: 947, 523 + xy: 1531, 559 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plated-conduit-top-2 rotate: false - xy: 947, 489 + xy: 1565, 583 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plated-conduit-top-3 rotate: false - xy: 947, 455 + xy: 1599, 583 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plated-conduit-top-4 rotate: false - xy: 947, 421 + xy: 1565, 549 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-0 rotate: false - xy: 947, 285 + xy: 1667, 563 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-1 rotate: false - xy: 947, 251 + xy: 1701, 563 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-2 rotate: false - xy: 947, 217 + xy: 1735, 563 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-4 rotate: false - xy: 947, 183 + xy: 1769, 563 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rotary-pump rotate: false - xy: 725, 541 + xy: 1173, 1151 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thermal-pump rotate: false - xy: 1107, 1755 + xy: 689, 1141 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 battery rotate: false - xy: 791, 955 + xy: 1175, 10 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 battery-large rotate: false - xy: 1, 90 + xy: 1489, 1589 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 battery-large-top rotate: false - xy: 1143, 1951 + xy: 1587, 1589 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 battery-top rotate: false - xy: 825, 989 + xy: 1457, 619 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 combustion-generator rotate: false - xy: 845, 309 + xy: 1839, 597 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 combustion-generator-top rotate: false - xy: 879, 343 + xy: 1769, 903 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 differential-generator rotate: false - xy: 429, 861 + xy: 911, 1311 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 differential-generator-liquid rotate: false - xy: 495, 763 + xy: 1009, 1311 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 differential-generator-top rotate: false - xy: 495, 665 + xy: 1319, 1491 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 diode rotate: false - xy: 919, 3 + xy: 1413, 491 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 diode-arrow rotate: false - xy: 1785, 1447 + xy: 1413, 457 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 illuminator rotate: false - xy: 1955, 1473 + xy: 1448, 355 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 illuminator-top rotate: false - xy: 1989, 1473 + xy: 1448, 321 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 impact-reactor rotate: false - xy: 521, 1659 + xy: 811, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-bottom rotate: false - xy: 651, 1789 + xy: 941, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-light rotate: false - xy: 781, 1919 + xy: 1071, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-0 rotate: false - xy: 1, 1009 + xy: 1201, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-1 rotate: false - xy: 131, 1139 + xy: 1331, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-2 rotate: false - xy: 261, 1269 + xy: 1461, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-3 rotate: false - xy: 391, 1399 + xy: 1591, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 power-node rotate: false - xy: 947, 387 + xy: 1599, 549 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-node-large rotate: false - xy: 725, 805 + xy: 1051, 833 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 power-source rotate: false - xy: 947, 353 + xy: 1633, 573 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-void rotate: false - xy: 947, 319 + xy: 1633, 539 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rtg-generator rotate: false - xy: 721, 475 + xy: 1051, 767 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rtg-generator-top rotate: false - xy: 1267, 1161 + xy: 1735, 529 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel rotate: false - xy: 1321, 1093 + xy: 1973, 521 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel-large rotate: false - xy: 1009, 1739 + xy: 689, 1239 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 surge-tower rotate: false - xy: 1153, 1199 + xy: 983, 69 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thermal-generator rotate: false - xy: 223, 11 + xy: 1049, 141 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thorium-reactor rotate: false - xy: 1205, 1755 + xy: 689, 1043 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 thorium-reactor-lights rotate: false - xy: 1303, 1755 + xy: 787, 1233 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 thorium-reactor-top rotate: false - xy: 1401, 1755 + xy: 787, 1135 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 turbine-generator rotate: false - xy: 421, 11 + xy: 1115, 643 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 turbine-generator-cap rotate: false - xy: 487, 11 + xy: 1111, 577 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 turbine-generator-top rotate: false - xy: 553, 11 + xy: 1181, 623 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 turbine-generator-turbine0 rotate: false - xy: 619, 13 + xy: 1177, 557 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 turbine-generator-turbine1 rotate: false - xy: 685, 13 + xy: 1111, 511 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 alloy-smelter rotate: false - xy: 1, 286 + xy: 1913, 1691 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 alloy-smelter-top rotate: false - xy: 1, 188 + xy: 1391, 1589 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 blast-mixer rotate: false - xy: 1301, 1615 + xy: 1981, 1851 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-forge rotate: false - xy: 1731, 1951 + xy: 493, 1225 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 coal-centrifuge rotate: false - xy: 555, 1069 + xy: 677, 355 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-bottom rotate: false - xy: 589, 409 + xy: 785, 69 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-liquid rotate: false - xy: 589, 343 + xy: 777, 3 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-top rotate: false - xy: 589, 277 + xy: 985, 817 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator rotate: false - xy: 589, 211 + xy: 815, 465 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator-middle rotate: false - xy: 589, 145 + xy: 809, 399 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator-top rotate: false - xy: 589, 79 + xy: 809, 333 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 disassembler rotate: false - xy: 103, 585 + xy: 1417, 1491 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 disassembler-liquid rotate: false - xy: 99, 487 + xy: 1515, 1491 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 disassembler-spinner rotate: false - xy: 99, 389 + xy: 1613, 1491 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 graphite-press rotate: false - xy: 1961, 1557 + xy: 881, 465 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 incinerator rotate: false - xy: 1853, 1439 + xy: 1429, 559 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-source rotate: false - xy: 1973, 1371 + xy: 1871, 895 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-void rotate: false - xy: 1935, 1303 + xy: 1863, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 kiln rotate: false - xy: 559, 1201 + xy: 875, 399 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 kiln-top rotate: false - xy: 559, 1135 + xy: 875, 333 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 silicon-smelter-top rotate: false - xy: 559, 1135 + xy: 875, 333 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 liquid-source rotate: false - xy: 2007, 1337 + xy: 1957, 759 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-void rotate: false - xy: 2003, 1303 + xy: 1957, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 melter rotate: false - xy: 953, 37 + xy: 1991, 759 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 multi-press rotate: false - xy: 393, 77 + xy: 1597, 1295 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 phase-weaver rotate: false - xy: 655, 343 + xy: 963, 537 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-bottom rotate: false - xy: 655, 277 + xy: 1013, 471 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-weave rotate: false - xy: 655, 211 + xy: 1041, 1163 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 plastanium-compressor rotate: false - xy: 655, 145 + xy: 1041, 1097 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 plastanium-compressor-top rotate: false - xy: 655, 79 + xy: 1107, 1171 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pulverizer rotate: false - xy: 947, 149 + xy: 1803, 563 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulverizer-rotator rotate: false - xy: 957, 115 + xy: 1837, 563 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pyratite-mixer rotate: false - xy: 725, 739 + xy: 1117, 973 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 separator rotate: false - xy: 967, 1265 + xy: 1117, 709 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 separator-liquid rotate: false - xy: 1033, 1265 + xy: 1183, 689 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 separator-spinner rotate: false - xy: 691, 1199 + xy: 975, 3 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 silicon-crucible rotate: false - xy: 1027, 1331 + xy: 591, 1093 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 silicon-crucible-top rotate: false - xy: 977, 1641 + xy: 591, 995 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 silicon-smelter rotate: false - xy: 757, 1199 + xy: 941, 399 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press rotate: false - xy: 823, 1199 + xy: 941, 333 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-frame0 rotate: false - xy: 889, 1199 + xy: 1007, 405 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-frame1 rotate: false - xy: 955, 1199 + xy: 1007, 339 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-frame2 rotate: false - xy: 1021, 1199 + xy: 983, 267 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-liquid rotate: false - xy: 1099, 1265 + xy: 983, 201 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-top rotate: false - xy: 1087, 1199 + xy: 983, 135 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rock1 rotate: false - xy: 1425, 1349 + xy: 1273, 51 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 rock2 rotate: false - xy: 1475, 1349 + xy: 1273, 1 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 sand-boulder1 rotate: false - xy: 1287, 1127 + xy: 1769, 529 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sand-boulder2 rotate: false - xy: 1287, 1093 + xy: 1803, 529 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shale-boulder1 rotate: false - xy: 1301, 1195 + xy: 2007, 555 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shale-boulder2 rotate: false - xy: 1301, 1161 + xy: 1905, 521 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 snowrock1 rotate: false - xy: 1153, 1049 + xy: 1247, 595 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 snowrock2 rotate: false - xy: 1203, 1049 + xy: 1243, 545 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spore-cluster1 rotate: false - xy: 1651, 1297 + xy: 1457, 653 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 spore-cluster2 rotate: false - xy: 1693, 1423 + xy: 1499, 695 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 spore-cluster3 rotate: false - xy: 1693, 1381 + xy: 1541, 737 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 container rotate: false - xy: 527, 937 + xy: 743, 399 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 core-foundation rotate: false - xy: 391, 1789 + xy: 1851, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 core-foundation-team rotate: false - xy: 521, 1919 + xy: 163, 1015 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 +core-nucleus-team + rotate: false + xy: 1, 1887 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 core-shard rotate: false - xy: 1727, 1853 + xy: 617, 1387 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 core-shard-team rotate: false - xy: 1825, 1853 + xy: 731, 1533 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 unloader rotate: false - xy: 1457, 1025 + xy: 1584, 345 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 unloader-center rotate: false - xy: 1459, 991 + xy: 1584, 311 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 vault rotate: false - xy: 1499, 1755 + xy: 787, 1037 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 arc-heat rotate: false - xy: 1735, 1394 + xy: 569, 1387 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-1 rotate: false - xy: 791, 921 + xy: 1667, 845 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-2 rotate: false - xy: 1367, 1615 + xy: 765, 531 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-3 rotate: false - xy: 1241, 1951 + xy: 1685, 1589 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-4 rotate: false - xy: 1, 1659 + xy: 1, 557 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 hail-heat rotate: false - xy: 457, 961 + xy: 837, 599 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 lancer-heat rotate: false - xy: 637, 1267 + xy: 917, 201 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 meltdown-heat rotate: false - xy: 781, 1789 + xy: 261, 885 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 ripple-heat rotate: false - xy: 733, 1331 + xy: 1891, 1197 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 salvo-heat rotate: false - xy: 721, 343 + xy: 1049, 701 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 salvo-panel-left rotate: false - xy: 721, 277 + xy: 1045, 635 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 salvo-panel-right rotate: false - xy: 721, 211 + xy: 1045, 569 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scorch-heat rotate: false - xy: 1287, 1025 + xy: 1871, 529 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 wave-liquid rotate: false - xy: 1631, 1507 + xy: 1205, 359 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 additive-reconstructor rotate: false - xy: 1, 580 + xy: 1097, 1609 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 additive-reconstructor-top rotate: false - xy: 1, 482 + xy: 1195, 1609 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 air-factory rotate: false - xy: 1, 384 + xy: 1293, 1609 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 command-center rotate: false - xy: 589, 1003 + xy: 749, 465 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 factory-in-3 rotate: false - xy: 99, 97 + xy: 1711, 1491 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 +factory-in-5 + rotate: false + xy: 325, 1563 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 factory-out-3 rotate: false - xy: 201, 567 + xy: 473, 35 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 +factory-out-5 + rotate: false + xy: 487, 1725 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 factory-top-3 rotate: false - xy: 299, 567 + xy: 1809, 1491 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ground-factory rotate: false - xy: 197, 371 + xy: 1613, 1393 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 +multiplicative-reconstructor + rotate: false + xy: 649, 1887 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 +multiplicative-reconstructor-top + rotate: false + xy: 1, 1077 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 naval-factory rotate: false - xy: 491, 77 + xy: 1695, 1295 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 rally-point rotate: false - xy: 725, 673 + xy: 1117, 907 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 repair-point-base rotate: false - xy: 1261, 1229 + xy: 1667, 529 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 resupply-point rotate: false - xy: 725, 607 + xy: 1117, 841 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 copper-wall rotate: false - xy: 889, 105 + xy: 1380, 351 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper-wall-large rotate: false - xy: 527, 871 + xy: 743, 333 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door rotate: false - xy: 1819, 1447 + xy: 1423, 423 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 door-large rotate: false - xy: 1631, 1573 + xy: 851, 201 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door-large-open rotate: false - xy: 1697, 1573 + xy: 851, 135 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door-open rotate: false - xy: 1853, 1473 + xy: 1423, 389 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall rotate: false - xy: 927, 863 + xy: 2009, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall-large rotate: false - xy: 655, 409 + xy: 947, 471 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 plastanium-wall rotate: false - xy: 927, 625 + xy: 1497, 593 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-wall-large rotate: false - xy: 687, 1069 + xy: 1107, 1105 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-gigantic rotate: false - xy: 911, 1919 + xy: 261, 755 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 scrap-wall-huge2 rotate: false - xy: 831, 1331 + xy: 591, 1289 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 scrap-wall-huge3 rotate: false - xy: 929, 1331 + xy: 591, 1191 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 scrap-wall-large1 rotate: false - xy: 721, 79 + xy: 1183, 1019 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-large2 rotate: false - xy: 703, 1265 + xy: 1183, 953 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-large3 rotate: false - xy: 769, 1265 + xy: 1183, 887 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-large4 rotate: false - xy: 835, 1265 + xy: 1183, 821 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall2 rotate: false - xy: 1289, 991 + xy: 1905, 555 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall3 rotate: false - xy: 1289, 957 + xy: 1939, 555 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall4 rotate: false - xy: 1295, 1229 + xy: 1973, 555 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall5 rotate: false - xy: 1295, 1229 + xy: 1973, 555 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-wall rotate: false - xy: 1363, 1229 + xy: 1939, 487 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-wall-large rotate: false - xy: 91, 24 + xy: 1049, 273 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thorium-wall rotate: false - xy: 1369, 1195 + xy: 1973, 487 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium-wall-large rotate: false - xy: 289, 11 + xy: 1049, 75 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thruster rotate: false - xy: 131, 1009 + xy: 261, 495 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 titanium-wall rotate: false - xy: 1457, 1127 + xy: 1593, 379 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-wall-large rotate: false - xy: 355, 11 + xy: 1041, 3 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 bullet rotate: false - xy: 925, 1145 + xy: 1365, 1027 size: 52, 52 orig: 52, 52 offset: 0, 0 index: -1 bullet-back rotate: false - xy: 979, 1145 + xy: 1423, 1085 size: 52, 52 orig: 52, 52 offset: 0, 0 index: -1 casing rotate: false - xy: 517, 959 + xy: 837, 723 size: 8, 16 orig: 8, 16 offset: 0, 0 index: -1 circle-end rotate: false - xy: 1, 678 + xy: 293, 1074 size: 100, 199 orig: 100, 199 offset: 0, 0 index: -1 circle-mid rotate: false - xy: 961, 798 + xy: 1323, 84 size: 1, 199 orig: 1, 199 offset: 0, 0 index: -1 error rotate: false - xy: 953, 1095 + xy: 1631, 1097 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 laser rotate: false - xy: 905, 1739 + xy: 157, 1027 size: 4, 48 orig: 4, 48 offset: 0, 0 index: -1 laser-end rotate: false - xy: 1305, 1681 + xy: 779, 963 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 minelaser rotate: false - xy: 2043, 1999 + xy: 1297, 1167 size: 4, 48 orig: 4, 48 offset: 0, 0 index: -1 minelaser-end rotate: false - xy: 1379, 1681 + xy: 777, 889 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 missile rotate: false - xy: 2007, 1691 + xy: 2011, 1763 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 missile-back rotate: false - xy: 1693, 1343 + xy: 2011, 1725 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 +parallax-laser + rotate: false + xy: 715, 1435 + size: 4, 48 + orig: 4, 48 + offset: 0, 0 + index: -1 +parallax-laser-end + rotate: false + xy: 773, 815 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 particle rotate: false - xy: 1609, 1297 + xy: 1625, 863 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 scale_marker rotate: false - xy: 1625, 1521 + xy: 813, 1429 size: 4, 4 orig: 4, 4 offset: 0, 0 index: -1 shell rotate: false - xy: 1693, 1305 + xy: 131, 1 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 shell-back rotate: false - xy: 1735, 1428 + xy: 169, 1 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 transfer rotate: false - xy: 2043, 1949 + xy: 2041, 1801 size: 4, 48 orig: 4, 48 offset: 0, 0 index: -1 transfer-arrow rotate: false - xy: 1457, 1093 + xy: 1550, 345 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 white rotate: false - xy: 1, 1 + xy: 1107, 1 size: 3, 3 orig: 3, 3 offset: 0, 0 index: -1 +alpha-wreck0 + rotate: false + xy: 1365, 977 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +alpha-wreck1 + rotate: false + xy: 1531, 1147 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +alpha-wreck2 + rotate: false + xy: 1307, 865 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 arc rotate: false - xy: 787, 79 + xy: 2011, 1691 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 +arkyid-wreck0 + rotate: false + xy: 1, 947 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +arkyid-wreck1 + rotate: false + xy: 163, 1145 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +arkyid-wreck2 + rotate: false + xy: 941, 1919 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +atrax-wreck0 + rotate: false + xy: 689, 977 + size: 88, 64 + orig: 88, 64 + offset: 0, 0 + index: -1 +atrax-wreck1 + rotate: false + xy: 687, 911 + size: 88, 64 + orig: 88, 64 + offset: 0, 0 + index: -1 +atrax-wreck2 + rotate: false + xy: 683, 845 + size: 88, 64 + orig: 88, 64 + offset: 0, 0 + index: -1 +beta-wreck0 + rotate: false + xy: 1681, 1147 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +beta-wreck1 + rotate: false + xy: 1307, 707 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +beta-wreck2 + rotate: false + xy: 1731, 1147 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 block-additive-reconstructor-full rotate: false - xy: 1339, 1951 + xy: 1783, 1589 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-air-factory-full rotate: false - xy: 1437, 1951 + xy: 1881, 1589 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-arc-full rotate: false - xy: 859, 989 + xy: 1583, 719 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-blast-drill-full rotate: false - xy: 131, 1789 + xy: 1331, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 block-char-full rotate: false - xy: 791, 887 + xy: 1277, 427 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-cliffs-full rotate: false - xy: 859, 955 + xy: 1715, 1005 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-conduit-full rotate: false - xy: 825, 921 + xy: 1715, 971 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-conveyor-full rotate: false - xy: 791, 853 + xy: 1707, 937 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-0 rotate: false - xy: 791, 853 + xy: 1707, 937 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-core-foundation-full rotate: false - xy: 261, 1919 + xy: 1, 427 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 block-core-shard-full rotate: false - xy: 1535, 1951 + xy: 395, 1209 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-craters-full rotate: false - xy: 859, 921 + xy: 1701, 903 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-cryofluidmixer-full rotate: false - xy: 1433, 1615 + xy: 853, 971 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-cultivator-full rotate: false - xy: 1595, 1659 + xy: 1979, 1625 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-cyclone-full rotate: false - xy: 1633, 1951 + xy: 395, 1111 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-dark-metal-full rotate: false - xy: 825, 887 + xy: 1701, 869 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-darksand-full rotate: false - xy: 791, 819 + xy: 1701, 835 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-dunerocks-full rotate: false - xy: 859, 887 + xy: 1617, 787 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-duo-full rotate: false - xy: 825, 853 + xy: 1617, 753 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-fuse-full rotate: false - xy: 1829, 1951 + xy: 493, 1127 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-grass-full rotate: false - xy: 791, 785 + xy: 1617, 719 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ground-factory-full rotate: false - xy: 1927, 1951 + xy: 395, 1013 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-hail-full rotate: false - xy: 859, 853 + xy: 1499, 627 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-holostone-full rotate: false - xy: 825, 819 + xy: 1533, 661 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-hotrock-full rotate: false - xy: 791, 751 + xy: 1533, 627 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ice-full rotate: false - xy: 859, 819 + xy: 1575, 685 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ice-snow-full rotate: false - xy: 825, 785 + xy: 1609, 685 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-icerocks-full rotate: false - xy: 791, 717 + xy: 1567, 651 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ignarock-full rotate: false - xy: 859, 785 + xy: 1601, 651 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-impact-reactor-full rotate: false - xy: 1, 1529 + xy: 1461, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 block-lancer-full rotate: false - xy: 1661, 1639 + xy: 653, 269 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-laser-drill-full rotate: false - xy: 781, 1625 + xy: 493, 1029 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-liquid-router-full rotate: false - xy: 825, 751 + xy: 1567, 617 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-liquid-tank-full rotate: false - xy: 765, 1527 + xy: 391, 915 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-magmarock-full rotate: false - xy: 791, 683 + xy: 1601, 617 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-mass-conveyor-full rotate: false - xy: 261, 959 + xy: 391, 719 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mass-conveyor-icon rotate: false - xy: 261, 959 + xy: 391, 719 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-mass-driver-full rotate: false - xy: 1041, 1869 + xy: 391, 621 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-mechanical-drill-full rotate: false - xy: 1727, 1639 + xy: 653, 203 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-meltdown-full rotate: false - xy: 131, 1659 + xy: 1, 297 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 block-metal-floor-damaged-full rotate: false - xy: 859, 751 + xy: 1741, 937 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-moss-full rotate: false - xy: 791, 649 + xy: 1735, 869 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-naval-factory-full rotate: false - xy: 1139, 1853 + xy: 391, 523 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-oil-extractor-full rotate: false - xy: 1237, 1853 + xy: 391, 425 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-ore-coal-full rotate: false - xy: 859, 717 + xy: 1735, 835 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-copper-full rotate: false - xy: 825, 683 + xy: 1659, 811 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-lead-full rotate: false - xy: 791, 615 + xy: 1651, 777 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-scrap-full rotate: false - xy: 859, 683 + xy: 1651, 743 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-thorium-full rotate: false - xy: 825, 649 + xy: 1651, 709 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-titanium-full rotate: false - xy: 791, 581 + xy: 1693, 801 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 +block-parallax-full + rotate: false + xy: 653, 137 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 block-payload-router-full rotate: false - xy: 1335, 1853 + xy: 391, 327 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 payload-router-icon rotate: false - xy: 1335, 1853 + xy: 391, 327 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-pebbles-full rotate: false - xy: 859, 649 + xy: 1727, 801 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-phase-weaver-full rotate: false - xy: 1793, 1639 + xy: 653, 71 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-plated-conduit-full rotate: false - xy: 825, 615 + xy: 1685, 767 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-pneumatic-drill-full rotate: false - xy: 1859, 1639 + xy: 645, 5 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-pulse-conduit-full rotate: false - xy: 791, 547 + xy: 1685, 733 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-pulverizer-full rotate: false - xy: 859, 615 + xy: 1719, 767 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-repair-point-full rotate: false - xy: 825, 581 + xy: 1719, 733 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ripple-full rotate: false - xy: 1433, 1853 + xy: 375, 229 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-rock-full rotate: false - xy: 1133, 1149 + xy: 1781, 1147 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-rocks-full rotate: false - xy: 859, 581 + xy: 1685, 699 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-saltrocks-full rotate: false - xy: 825, 547 + xy: 1719, 699 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-salvo-full rotate: false - xy: 1925, 1623 + xy: 919, 999 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-sand-boulder-full rotate: false - xy: 859, 547 + xy: 1643, 675 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-sand-full rotate: false - xy: 893, 989 + xy: 1635, 641 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-sandrocks-full rotate: false - xy: 893, 955 + xy: 1635, 607 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-scatter-full rotate: false - xy: 1499, 1615 + xy: 985, 1015 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-scorch-full rotate: false - xy: 893, 921 + xy: 1677, 665 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-scrap-wall-full rotate: false - xy: 893, 887 + xy: 1711, 665 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall1 rotate: false - xy: 893, 887 + xy: 1711, 665 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-scrap-wall-huge-full rotate: false - xy: 1531, 1853 + xy: 375, 131 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 scrap-wall-huge1 rotate: false - xy: 1531, 1853 + xy: 375, 131 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-scrap-wall-large-full rotate: false - xy: 505, 1333 + xy: 919, 933 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-segment-full rotate: false - xy: 505, 1267 + xy: 985, 949 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-shale-boulder-full rotate: false - xy: 893, 819 + xy: 1703, 631 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-shale-full rotate: false - xy: 893, 785 + xy: 1669, 597 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-shalerocks-full rotate: false - xy: 893, 751 + xy: 1703, 597 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-shrubs-full rotate: false - xy: 893, 717 + xy: 1761, 801 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-snow-full rotate: false - xy: 893, 683 + xy: 1753, 767 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-snowrock-full rotate: false - xy: 803, 1091 + xy: 1831, 1147 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-snowrocks-full rotate: false - xy: 893, 649 + xy: 1753, 733 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-spectre-full rotate: false - xy: 261, 1789 + xy: 1591, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 block-spore-cluster-full rotate: false - xy: 1259, 1567 + xy: 1415, 927 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-spore-moss-full rotate: false - xy: 893, 615 + xy: 1753, 699 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-spore-press-full rotate: false - xy: 493, 1201 + xy: 853, 905 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-sporerocks-full rotate: false - xy: 893, 581 + xy: 1745, 665 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-stone-full rotate: false - xy: 893, 547 + xy: 1737, 631 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-swarmer-full rotate: false - xy: 493, 1135 + xy: 919, 867 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-tendrils-full rotate: false - xy: 845, 513 + xy: 1737, 597 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-titanium-conveyor-full rotate: false - xy: 845, 479 + xy: 1787, 767 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-0 rotate: false - xy: 845, 479 + xy: 1787, 767 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-turbine-generator-full rotate: false - xy: 489, 1069 + xy: 985, 883 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-water-extractor-full rotate: false - xy: 457, 1003 + xy: 683, 487 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-wave-full rotate: false - xy: 523, 1003 + xy: 677, 421 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 core-foundation-team-crux rotate: false - xy: 1, 1269 + xy: 131, 885 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 core-foundation-team-sharded rotate: false - xy: 131, 1399 + xy: 131, 755 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 +core-nucleus-team-crux + rotate: false + xy: 1, 1725 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 +core-nucleus-team-sharded + rotate: false + xy: 163, 1887 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 core-shard-team-crux rotate: false - xy: 1923, 1853 + xy: 731, 1435 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 core-shard-team-sharded rotate: false - xy: 391, 1085 + xy: 829, 1527 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-1-0 rotate: false - xy: 855, 71 + xy: 1380, 317 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-1 rotate: false - xy: 889, 71 + xy: 1361, 555 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-2 rotate: false - xy: 851, 37 + xy: 1361, 521 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-3 rotate: false - xy: 885, 37 + xy: 1395, 559 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-4 rotate: false - xy: 851, 3 + xy: 1395, 525 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-5 rotate: false - xy: 885, 3 + xy: 1379, 487 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-6 rotate: false - xy: 923, 105 + xy: 1379, 453 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-7 rotate: false - xy: 923, 71 + xy: 1389, 419 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-2-0 rotate: false - xy: 593, 937 + xy: 719, 267 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-1 rotate: false - xy: 593, 871 + xy: 719, 201 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-2 rotate: false - xy: 593, 805 + xy: 719, 135 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-3 rotate: false - xy: 593, 739 + xy: 719, 69 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-4 rotate: false - xy: 593, 673 + xy: 711, 3 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-5 rotate: false - xy: 593, 607 + xy: 785, 267 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-6 rotate: false - xy: 593, 541 + xy: 785, 201 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-7 rotate: false - xy: 589, 475 + xy: 785, 135 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-3-0 rotate: false - xy: 103, 781 + xy: 829, 1429 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-1 rotate: false - xy: 103, 683 + xy: 715, 1337 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-2 rotate: false - xy: 233, 861 + xy: 813, 1331 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-3 rotate: false - xy: 201, 763 + xy: 927, 1507 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-4 rotate: false - xy: 201, 665 + xy: 927, 1409 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-5 rotate: false - xy: 299, 763 + xy: 1025, 1507 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-6 rotate: false - xy: 299, 665 + xy: 1025, 1409 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-7 rotate: false - xy: 331, 861 + xy: 1123, 1511 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-4-0 rotate: false - xy: 261, 1529 + xy: 131, 625 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-1 rotate: false - xy: 391, 1659 + xy: 131, 495 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-2 rotate: false - xy: 521, 1789 + xy: 131, 365 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-3 rotate: false - xy: 651, 1919 + xy: 131, 235 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-4 rotate: false - xy: 1, 1139 + xy: 131, 105 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-5 rotate: false - xy: 131, 1269 + xy: 325, 1307 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-6 rotate: false - xy: 261, 1399 + xy: 487, 1469 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-7 rotate: false - xy: 391, 1529 + xy: 649, 1631 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 +cracks-5-0 + rotate: false + xy: 163, 1725 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 +cracks-5-1 + rotate: false + xy: 325, 1887 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 +cracks-5-2 + rotate: false + xy: 1, 1401 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 +cracks-5-3 + rotate: false + xy: 163, 1563 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 +cracks-5-4 + rotate: false + xy: 325, 1725 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 +cracks-5-5 + rotate: false + xy: 487, 1887 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 +cracks-5-6 + rotate: false + xy: 1, 1239 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 +cracks-5-7 + rotate: false + xy: 163, 1401 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 +crawler-wreck0 + rotate: false + xy: 1357, 877 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +crawler-wreck1 + rotate: false + xy: 1357, 827 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +crawler-wreck2 + rotate: false + xy: 1357, 777 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 cyclone rotate: false - xy: 359, 959 + xy: 1221, 1511 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 +dagger-wreck0 + rotate: false + xy: 1357, 627 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dagger-wreck1 + rotate: false + xy: 1481, 1097 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dagger-wreck2 + rotate: false + xy: 1531, 1097 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 duo rotate: false - xy: 1887, 1473 + xy: 1414, 351 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 +flare-wreck0 + rotate: false + xy: 1881, 1097 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +flare-wreck1 + rotate: false + xy: 1931, 1097 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +flare-wreck2 + rotate: false + xy: 1981, 1093 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +fortress-wreck0 + rotate: false + xy: 1097, 1707 + size: 100, 80 + orig: 100, 80 + offset: 0, 0 + index: -1 +fortress-wreck1 + rotate: false + xy: 1199, 1707 + size: 100, 80 + orig: 100, 80 + offset: 0, 0 + index: -1 +fortress-wreck2 + rotate: false + xy: 1301, 1707 + size: 100, 80 + orig: 100, 80 + offset: 0, 0 + index: -1 fuse rotate: false - xy: 197, 469 + xy: 1515, 1393 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 +gamma-wreck0 + rotate: false + xy: 1249, 1101 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +gamma-wreck1 + rotate: false + xy: 1249, 1043 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +gamma-wreck2 + rotate: false + xy: 1249, 985 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 hail rotate: false - xy: 1921, 1473 + xy: 1414, 317 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 +horizon-wreck0 + rotate: false + xy: 967, 1081 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 +horizon-wreck1 + rotate: false + xy: 1123, 1237 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 +horizon-wreck2 + rotate: false + xy: 571, 15 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 item-blast-compound-large rotate: false - xy: 1525, 1435 + xy: 1665, 947 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-blast-compound-medium rotate: false - xy: 1955, 1439 + xy: 1447, 457 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-blast-compound-small rotate: false - xy: 207, 881 + xy: 1803, 835 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-blast-compound-tiny rotate: false - xy: 1141, 1591 + xy: 1293, 503 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-blast-compound-xlarge rotate: false - xy: 1125, 1491 + xy: 1881, 1047 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-coal-large rotate: false - xy: 1525, 1393 + xy: 1457, 905 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-coal-medium rotate: false - xy: 1773, 1413 + xy: 1457, 389 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-coal-small rotate: false - xy: 1249, 1283 + xy: 1829, 801 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-coal-tiny rotate: false - xy: 1661, 1707 + xy: 2031, 1175 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-coal-xlarge rotate: false - xy: 1125, 1441 + xy: 1931, 1047 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-copper-large rotate: false - xy: 1567, 1435 + xy: 1457, 863 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-copper-medium rotate: false - xy: 1769, 1379 + xy: 1482, 321 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-copper-small rotate: false - xy: 2023, 1481 + xy: 1855, 699 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-copper-tiny rotate: false - xy: 499, 959 + xy: 2031, 1157 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-copper-xlarge rotate: false - xy: 1125, 1391 + xy: 1981, 1043 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-graphite-large rotate: false - xy: 1525, 1351 + xy: 1499, 905 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-graphite-medium rotate: false - xy: 1769, 1345 + xy: 1482, 287 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-graphite-small rotate: false - xy: 2023, 1455 + xy: 1881, 665 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-graphite-tiny rotate: false - xy: 1275, 1549 + xy: 2031, 1139 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-graphite-xlarge rotate: false - xy: 1125, 1341 + xy: 1407, 877 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-lead-large rotate: false - xy: 1567, 1393 + xy: 1457, 821 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-lead-medium rotate: false - xy: 1765, 1311 + xy: 1749, 971 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-lead-small rotate: false - xy: 363, 1113 + xy: 689, 1361 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-lead-tiny rotate: false - xy: 201, 861 + xy: 2031, 1121 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-lead-xlarge rotate: false - xy: 1175, 1509 + xy: 1407, 827 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-metaglass-large rotate: false - xy: 1525, 1309 + xy: 1499, 863 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-metaglass-medium rotate: false - xy: 1765, 1277 + xy: 1783, 1005 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-metaglass-small rotate: false - xy: 1013, 1893 + xy: 1463, 525 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-metaglass-tiny rotate: false - xy: 733, 1527 + xy: 2031, 1103 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-metaglass-xlarge rotate: false - xy: 1175, 1459 + xy: 1407, 777 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-phase-fabric-large rotate: false - xy: 1567, 1351 + xy: 1541, 905 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-phase-fabric-medium rotate: false - xy: 1761, 1243 + xy: 1817, 963 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-phase-fabric-small rotate: false - xy: 571, 1339 + xy: 1433, 593 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-phase-fabric-tiny rotate: false - xy: 887, 1771 + xy: 2031, 1085 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-phase-fabric-xlarge rotate: false - xy: 1175, 1409 + xy: 1407, 727 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-plastanium-large rotate: false - xy: 1567, 1309 + xy: 1457, 779 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-plastanium-medium rotate: false - xy: 1841, 1405 + xy: 1885, 963 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-plastanium-small rotate: false - xy: 499, 977 + xy: 131, 1051 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-plastanium-tiny rotate: false - xy: 2025, 2031 + xy: 2031, 1067 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-plastanium-xlarge rotate: false - xy: 1175, 1359 + xy: 1407, 677 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-pyratite-large rotate: false - xy: 1165, 1267 + xy: 1499, 821 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-pyratite-medium rotate: false - xy: 1909, 1405 + xy: 1809, 929 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-pyratite-small rotate: false - xy: 1661, 1271 + xy: 101, 11 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-pyratite-tiny rotate: false - xy: 1631, 1641 + xy: 2031, 1049 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-pyratite-xlarge rotate: false - xy: 1225, 1509 + xy: 1407, 627 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-sand-large rotate: false - xy: 1207, 1267 + xy: 1541, 863 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-sand-medium rotate: false - xy: 1977, 1405 + xy: 1877, 929 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-sand-small rotate: false - xy: 1459, 965 + xy: 541, 9 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-sand-tiny rotate: false - xy: 1, 6 + xy: 2031, 1031 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-sand-xlarge rotate: false - xy: 1225, 1459 + xy: 1477, 1047 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-scrap-large rotate: false - xy: 1219, 1225 + xy: 1583, 905 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-scrap-medium rotate: false - xy: 1871, 1371 + xy: 1803, 895 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-scrap-small rotate: false - xy: 363, 1087 + xy: 2005, 1395 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-scrap-tiny rotate: false - xy: 1525, 1531 + xy: 2031, 1013 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-scrap-xlarge rotate: false - xy: 1225, 1409 + xy: 1527, 1047 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-silicon-large rotate: false - xy: 1625, 1465 + xy: 1457, 737 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-silicon-medium rotate: false - xy: 1939, 1371 + xy: 1837, 895 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-silicon-small rotate: false - xy: 1013, 1867 + xy: 1953, 971 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-silicon-tiny rotate: false - xy: 233, 963 + xy: 2031, 995 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-silicon-xlarge rotate: false - xy: 1225, 1359 + xy: 1577, 1047 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-spore-pod-large rotate: false - xy: 1667, 1465 + xy: 1499, 779 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-spore-pod-medium rotate: false - xy: 1871, 1337 + xy: 1905, 895 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-spore-pod-small rotate: false - xy: 363, 1061 + xy: 131, 1025 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-spore-pod-tiny rotate: false - xy: 887, 1753 + xy: 2031, 977 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-spore-pod-xlarge rotate: false - xy: 1275, 1499 + xy: 1627, 1047 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-surge-alloy-large rotate: false - xy: 1709, 1466 + xy: 1541, 821 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-surge-alloy-medium rotate: false - xy: 1939, 1337 + xy: 1905, 861 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-surge-alloy-small rotate: false - xy: 1013, 1841 + xy: 1550, 285 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-surge-alloy-tiny rotate: false - xy: 2025, 2013 + xy: 2031, 959 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-surge-alloy-xlarge rotate: false - xy: 1325, 1499 + xy: 1677, 1039 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-thorium-large rotate: false - xy: 1609, 1423 + xy: 1583, 863 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-thorium-medium rotate: false - xy: 1833, 1303 + xy: 1939, 895 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-thorium-small rotate: false - xy: 597, 1339 + xy: 1576, 285 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-thorium-tiny rotate: false - xy: 19, 6 + xy: 2031, 941 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-thorium-xlarge rotate: false - xy: 1275, 1449 + xy: 1831, 997 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-titanium-large rotate: false - xy: 1609, 1381 + xy: 1625, 905 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-titanium-medium rotate: false - xy: 1901, 1303 + xy: 1829, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-titanium-small rotate: false - xy: 1039, 1843 + xy: 1979, 967 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-titanium-tiny rotate: false - xy: 1543, 1531 + xy: 2031, 1403 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-titanium-xlarge rotate: false - xy: 1375, 1499 + xy: 1881, 997 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 lancer rotate: false - xy: 571, 1267 + xy: 917, 267 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 liquid-cryofluid-large rotate: false - xy: 1651, 1423 + xy: 1457, 695 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 liquid-cryofluid-medium rotate: false - xy: 1867, 1269 + xy: 1855, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-cryofluid-small rotate: false - xy: 1065, 1843 + xy: 2005, 967 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 liquid-cryofluid-tiny rotate: false - xy: 887, 1735 + xy: 927, 1607 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 liquid-cryofluid-xlarge rotate: false - xy: 1425, 1499 + xy: 1981, 993 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 liquid-oil-large rotate: false - xy: 1609, 1339 + xy: 1499, 737 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 liquid-oil-medium rotate: false - xy: 1969, 1269 + xy: 1855, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-oil-small rotate: false - xy: 389, 1059 + xy: 1979, 941 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 liquid-oil-tiny rotate: false - xy: 2025, 1995 + xy: 1319, 1591 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 liquid-oil-xlarge rotate: false - xy: 1325, 1399 + xy: 1173, 244 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 liquid-slag-large rotate: false - xy: 1651, 1381 + xy: 1541, 779 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 liquid-slag-medium rotate: false - xy: 2007, 1371 + xy: 1957, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-slag-small rotate: false - xy: 415, 1059 + xy: 2005, 941 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 liquid-slag-tiny rotate: false - xy: 37, 6 + xy: 885, 1313 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 liquid-slag-xlarge rotate: false - xy: 1375, 1449 + xy: 1173, 194 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 liquid-water-large rotate: false - xy: 1651, 1339 + xy: 1583, 821 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 liquid-water-medium rotate: false - xy: 1999, 1235 + xy: 1915, 691 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-water-small rotate: false - xy: 1565, 1663 + xy: 317, 1281 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 liquid-water-tiny rotate: false - xy: 2025, 1977 + xy: 677, 337 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 liquid-water-xlarge rotate: false - xy: 1475, 1499 + xy: 1173, 144 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 +mace-wreck0 + rotate: false + xy: 847, 773 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mace-wreck1 + rotate: false + xy: 847, 707 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mace-wreck2 + rotate: false + xy: 837, 641 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 mass-driver rotate: false - xy: 197, 77 + xy: 1401, 1295 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 +mega-wreck0 + rotate: false + xy: 1607, 1687 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +mega-wreck1 + rotate: false + xy: 1709, 1687 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +mega-wreck2 + rotate: false + xy: 1811, 1687 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 meltdown rotate: false - xy: 651, 1659 + xy: 1851, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 +mono-wreck0 + rotate: false + xy: 1223, 151 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mono-wreck1 + rotate: false + xy: 1223, 101 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mono-wreck2 + rotate: false + xy: 1223, 51 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +nova-wreck0 + rotate: false + xy: 1249, 811 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +nova-wreck1 + rotate: false + xy: 1249, 753 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +nova-wreck2 + rotate: false + xy: 1249, 695 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +parallax + rotate: false + xy: 979, 619 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +poly-wreck0 + rotate: false + xy: 1307, 1139 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +poly-wreck1 + rotate: false + xy: 1307, 1081 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +poly-wreck2 + rotate: false + xy: 1365, 1139 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +pulsar-wreck0 + rotate: false + xy: 1989, 1243 + size: 58, 48 + orig: 58, 48 + offset: 0, 0 + index: -1 +pulsar-wreck1 + rotate: false + xy: 1989, 1193 + size: 58, 48 + orig: 58, 48 + offset: 0, 0 + index: -1 +pulsar-wreck2 + rotate: false + xy: 293, 1024 + size: 58, 48 + orig: 58, 48 + offset: 0, 0 + index: -1 +quasar-wreck0 + rotate: false + xy: 885, 1229 + size: 80, 80 + orig: 80, 80 + offset: 0, 0 + index: -1 +quasar-wreck1 + rotate: false + xy: 885, 1147 + size: 80, 80 + orig: 80, 80 + offset: 0, 0 + index: -1 +quasar-wreck2 + rotate: false + xy: 967, 1229 + size: 80, 80 + orig: 80, 80 + offset: 0, 0 + index: -1 repair-point rotate: false - xy: 957, 81 + xy: 1871, 563 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ripple rotate: false - xy: 635, 1333 + xy: 1793, 1197 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 salvo rotate: false - xy: 721, 409 + xy: 1117, 775 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scatter rotate: false - xy: 721, 145 + xy: 1183, 1085 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scorch rotate: false - xy: 1287, 1059 + xy: 1837, 529 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 segment rotate: false - xy: 901, 1265 + xy: 1183, 755 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spectre rotate: false - xy: 1, 879 + xy: 261, 625 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 +spiroct-wreck0 + rotate: false + xy: 587, 764 + size: 94, 75 + orig: 94, 75 + offset: 0, 0 + index: -1 +spiroct-wreck1 + rotate: false + xy: 587, 687 + size: 94, 75 + orig: 94, 75 + offset: 0, 0 + index: -1 +spiroct-wreck2 + rotate: false + xy: 587, 610 + size: 94, 75 + orig: 94, 75 + offset: 0, 0 + index: -1 splash-0 rotate: false - xy: 1321, 1025 + xy: 1531, 525 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 splash-1 rotate: false - xy: 1323, 991 + xy: 1565, 515 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 splash-10 rotate: false - xy: 1357, 991 + xy: 1871, 495 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 splash-11 rotate: false - xy: 1357, 957 + xy: 1905, 487 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 splash-2 rotate: false - xy: 1323, 957 + xy: 1599, 515 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 splash-3 rotate: false - xy: 1329, 1229 + xy: 1633, 505 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 splash-4 rotate: false - xy: 1335, 1195 + xy: 1667, 495 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 splash-5 rotate: false - xy: 1335, 1161 + xy: 1701, 495 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 splash-6 rotate: false - xy: 1355, 1127 + xy: 1735, 495 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 splash-7 rotate: false - xy: 1355, 1093 + xy: 1769, 495 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 splash-8 rotate: false - xy: 1355, 1059 + xy: 1803, 495 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 splash-9 rotate: false - xy: 1355, 1025 + xy: 1837, 495 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 swarmer rotate: false - xy: 157, 11 + xy: 1049, 207 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 unit-alpha-full rotate: false - xy: 1375, 1299 + xy: 1243, 495 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -unit-cix-full +unit-arkyid-full rotate: false - xy: 261, 1139 + xy: 261, 365 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 +unit-atrax-full + rotate: false + xy: 683, 779 + size: 88, 64 + orig: 88, 64 + offset: 0, 0 + index: -1 +unit-beta-full + rotate: false + xy: 1465, 997 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 unit-crawler-full rotate: false - xy: 1425, 1299 + xy: 1515, 997 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 unit-dagger-full rotate: false - xy: 1475, 1299 + xy: 1565, 997 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -unit-draug-full +unit-flare-full rotate: false - xy: 953, 1045 + xy: 1615, 997 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -unit-eruptor-full - rotate: false - xy: 1867, 1787 - size: 88, 64 - orig: 88, 64 - offset: 0, 0 - index: -1 unit-fortress-full rotate: false - xy: 261, 1057 + xy: 893, 1625 size: 100, 80 orig: 100, 80 offset: 0, 0 index: -1 -unit-ghoul-full +unit-gamma-full rotate: false - xy: 1453, 1681 + xy: 1365, 1081 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +unit-horizon-full + rotate: false + xy: 773, 741 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 unit-mace-full rotate: false - xy: 751, 13 + xy: 1177, 491 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -unit-oculon-full +unit-mega-full rotate: false - xy: 1075, 1657 - size: 80, 80 - orig: 80, 80 - offset: 0, 0 - index: -1 -unit-phantom-full - rotate: false - xy: 809, 1141 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -unit-revenant-full - rotate: false - xy: 651, 1545 - size: 112, 112 - orig: 112, 112 - offset: 0, 0 - index: -1 -unit-spirit-full - rotate: false - xy: 1003, 1037 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -unit-tau-full - rotate: false - xy: 867, 1141 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -unit-trident-full - rotate: false - xy: 391, 1183 + xy: 995, 1605 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -unit-vanguard-full +unit-mono-full rotate: false - xy: 1053, 999 + xy: 1665, 989 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -unit-wraith-full +unit-nova-full rotate: false - xy: 1103, 991 - size: 48, 48 - orig: 48, 48 + xy: 1423, 1139 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +unit-poly-full + rotate: false + xy: 1307, 965 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +unit-pulsar-full + rotate: false + xy: 1981, 1801 + size: 58, 48 + orig: 58, 48 + offset: 0, 0 + index: -1 +unit-quasar-full + rotate: false + xy: 885, 1065 + size: 80, 80 + orig: 80, 80 + offset: 0, 0 + index: -1 +unit-spiroct-full + rotate: false + xy: 587, 533 + size: 94, 75 + orig: 94, 75 + offset: 0, 0 + index: -1 +unit-zenith-full + rotate: false + xy: 261, 251 + size: 112, 112 + orig: 112, 112 offset: 0, 0 index: -1 wave rotate: false - xy: 1565, 1527 + xy: 1211, 425 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 +zenith-wreck0 + rotate: false + xy: 455, 1323 + size: 112, 112 + orig: 112, 112 + offset: 0, 0 + index: -1 +zenith-wreck1 + rotate: false + xy: 617, 1485 + size: 112, 112 + orig: 112, 112 + offset: 0, 0 + index: -1 +zenith-wreck2 + rotate: false + xy: 779, 1647 + size: 112, 112 + orig: 112, 112 + offset: 0, 0 + index: -1 item-blast-compound rotate: false - xy: 1921, 1439 + xy: 1447, 491 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-coal rotate: false - xy: 1989, 1439 + xy: 1457, 423 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-copper rotate: false - xy: 1807, 1413 + xy: 1482, 355 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-graphite rotate: false - xy: 1803, 1379 + xy: 1448, 287 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-lead rotate: false - xy: 1803, 1345 + xy: 1749, 1005 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-metaglass rotate: false - xy: 1799, 1311 + xy: 1775, 937 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-phase-fabric rotate: false - xy: 1799, 1277 + xy: 1783, 971 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-plastanium rotate: false - xy: 1795, 1243 + xy: 1851, 963 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-pyratite rotate: false - xy: 1875, 1405 + xy: 1919, 963 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-sand rotate: false - xy: 1943, 1405 + xy: 1843, 929 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-scrap rotate: false - xy: 1837, 1371 + xy: 1911, 929 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-silicon rotate: false - xy: 1905, 1371 + xy: 1803, 861 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-spore-pod rotate: false - xy: 1837, 1337 + xy: 1837, 861 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-surge-alloy rotate: false - xy: 1905, 1337 + xy: 1871, 861 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-thorium rotate: false - xy: 1973, 1337 + xy: 1945, 929 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-titanium rotate: false - xy: 1867, 1303 + xy: 1939, 861 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-cryofluid rotate: false - xy: 1833, 1269 + xy: 1931, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-oil rotate: false - xy: 1935, 1269 + xy: 1889, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-slag rotate: false - xy: 2011, 1405 + xy: 1965, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-water rotate: false - xy: 2003, 1269 + xy: 1881, 691 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 blank rotate: false - xy: 765, 1656 + xy: 479, 1560 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 shape-3 rotate: false - xy: 1697, 1508 + xy: 1115, 294 size: 63, 63 orig: 63, 63 offset: 0, 0 index: -1 alpha rotate: false - xy: 1033, 1149 + xy: 1481, 1147 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 alpha-cell rotate: false - xy: 1083, 1149 + xy: 1307, 915 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -chaos-array +arkyid rotate: false - xy: 391, 1919 + xy: 811, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 -cix +chaos-array rotate: false - xy: 391, 1919 + xy: 811, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 +arkyid-cell + rotate: false + xy: 587, 467 + size: 88, 64 + orig: 88, 64 + offset: 0, 0 + index: -1 +arkyid-foot + rotate: false + xy: 765, 669 + size: 70, 70 + orig: 70, 70 + offset: 0, 0 + index: -1 +arkyid-joint-base + rotate: false + xy: 765, 597 + size: 70, 70 + orig: 70, 70 + offset: 0, 0 + index: -1 +arkyid-leg + rotate: false + xy: 1239, 1159 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +arkyid-leg-base + rotate: false + xy: 131, 39 + size: 104, 64 + orig: 104, 64 + offset: 0, 0 + index: -1 +atrax + rotate: false + xy: 587, 401 + size: 88, 64 + orig: 88, 64 + offset: 0, 0 + index: -1 +atrax-base + rotate: false + xy: 1981, 1917 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +atrax-cell + rotate: false + xy: 587, 335 + size: 88, 64 + orig: 88, 64 + offset: 0, 0 + index: -1 +atrax-foot + rotate: false + xy: 353, 1032 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +atrax-joint + rotate: false + xy: 885, 1037 + size: 26, 26 + orig: 26, 26 + offset: 0, 0 + index: -1 +atrax-leg + rotate: false + xy: 803, 1761 + size: 36, 26 + orig: 36, 26 + offset: 0, 0 + index: -1 +atrax-leg-base + rotate: false + xy: 841, 1761 + size: 36, 26 + orig: 36, 26 + offset: 0, 0 + index: -1 +beta + rotate: false + xy: 1631, 1147 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +beta-cell + rotate: false + xy: 1307, 757 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 chaos-array-base rotate: false - xy: 1, 1399 + xy: 1, 167 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 chaos-array-cell rotate: false - xy: 131, 1529 + xy: 1721, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 chaos-array-leg rotate: false - xy: 261, 1659 + xy: 1, 37 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 -cix-cell - rotate: false - xy: 1, 24 - size: 88, 64 - orig: 88, 64 - offset: 0, 0 - index: -1 -cix-foot - rotate: false - xy: 1157, 1609 - size: 70, 70 - orig: 70, 70 - offset: 0, 0 - index: -1 -cix-joint-base - rotate: false - xy: 1229, 1609 - size: 70, 70 - orig: 70, 70 - offset: 0, 0 - index: -1 -cix-leg - rotate: false - xy: 1991, 1631 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -cix-leg-base - rotate: false - xy: 781, 1723 - size: 104, 64 - orig: 104, 64 - offset: 0, 0 - index: -1 -cix-old - rotate: false - xy: 1597, 1787 - size: 88, 64 - orig: 88, 64 - offset: 0, 0 - index: -1 crawler rotate: false - xy: 853, 1091 + xy: 1881, 1147 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 crawler-base rotate: false - xy: 1183, 1149 + xy: 1931, 1147 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 crawler-cell rotate: false - xy: 571, 1365 + xy: 1981, 1143 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 crawler-leg rotate: false - xy: 1059, 1541 + xy: 1365, 927 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger rotate: false - xy: 1109, 1541 + xy: 1357, 727 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger-base rotate: false - xy: 1159, 1559 + xy: 1357, 677 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger-leg rotate: false - xy: 1209, 1559 + xy: 1307, 657 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -delta +eradicator rotate: false - xy: 1878, 1507 + xy: 163, 1275 + size: 152, 124 + orig: 152, 124 + offset: 0, 0 + index: -1 +eradicator-base + rotate: false + xy: 325, 1437 + size: 152, 124 + orig: 152, 124 + offset: 0, 0 + index: -1 +eradicator-cell + rotate: false + xy: 487, 1599 + size: 152, 124 + orig: 152, 124 + offset: 0, 0 + index: -1 +eradicator-leg + rotate: false + xy: 649, 1761 + size: 152, 124 + orig: 152, 124 + offset: 0, 0 + index: -1 +flare + rotate: false + xy: 1831, 1097 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -delta-cell - rotate: false - xy: 1928, 1507 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -draug - rotate: false - xy: 1978, 1507 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -draug-cell - rotate: false - xy: 903, 1091 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -eruptor - rotate: false - xy: 1687, 1787 - size: 88, 64 - orig: 88, 64 - offset: 0, 0 - index: -1 -eruptor-base - rotate: false - xy: 1829, 1573 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -eruptor-cell - rotate: false - xy: 1777, 1787 - size: 88, 64 - orig: 88, 64 - offset: 0, 0 - index: -1 -eruptor-foot - rotate: false - xy: 2007, 1729 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -eruptor-joint - rotate: false - xy: 233, 981 - size: 26, 26 - orig: 26, 26 - offset: 0, 0 - index: -1 -eruptor-leg - rotate: false - xy: 131, 879 - size: 36, 26 - orig: 36, 26 - offset: 0, 0 - index: -1 -eruptor-leg-base - rotate: false - xy: 169, 879 - size: 36, 26 - orig: 36, 26 - offset: 0, 0 - index: -1 fortress rotate: false - xy: 911, 1837 + xy: 893, 1707 size: 100, 80 orig: 100, 80 offset: 0, 0 index: -1 fortress-base rotate: false - xy: 1895, 1557 + xy: 843, 3 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 fortress-cell rotate: false - xy: 1041, 1967 + xy: 995, 1707 size: 100, 80 orig: 100, 80 offset: 0, 0 index: -1 fortress-leg rotate: false - xy: 1597, 1725 + xy: 683, 635 size: 80, 60 orig: 80, 60 offset: 0, 0 index: -1 -ghoul +gamma rotate: false - xy: 1157, 1681 - size: 72, 72 - orig: 72, 72 - offset: 0, 0 - index: -1 -ghoul-cell - rotate: false - xy: 1231, 1681 - size: 72, 72 - orig: 72, 72 - offset: 0, 0 - index: -1 -glaive - rotate: false - xy: 1762, 1515 + xy: 1180, 301 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 -glaive-cell +gamma-cell rotate: false - xy: 787, 345 + xy: 1115, 98 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 +horizon + rotate: false + xy: 967, 1155 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 +horizon-cell + rotate: false + xy: 1049, 1237 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 mace rotate: false - xy: 625, 1201 + xy: 917, 135 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mace-base rotate: false - xy: 625, 1135 + xy: 917, 69 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mace-cell rotate: false - xy: 621, 1069 + xy: 909, 3 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mace-leg rotate: false - xy: 655, 1003 + xy: 851, 839 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -oculon +mega rotate: false - xy: 1679, 1705 - size: 80, 80 - orig: 80, 80 + xy: 1403, 1687 + size: 100, 100 + orig: 100, 100 offset: 0, 0 index: -1 -oculon-armor +mega-cell rotate: false - xy: 659, 607 - size: 64, 64 - orig: 64, 64 + xy: 1505, 1687 + size: 100, 100 + orig: 100, 100 offset: 0, 0 index: -1 -oculon-base +mono rotate: false - xy: 1761, 1705 - size: 80, 80 - orig: 80, 80 - offset: 0, 0 - index: -1 -oculon-base-old - rotate: false - xy: 1475, 1449 + xy: 1223, 251 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -oculon-cell +mono-cell rotate: false - xy: 1843, 1705 - size: 80, 80 - orig: 80, 80 - offset: 0, 0 - index: -1 -oculon-cell-old - rotate: false - xy: 1475, 1399 + xy: 1223, 201 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -oculon-leg +nova rotate: false - xy: 1925, 1689 - size: 80, 80 - orig: 80, 80 - offset: 0, 0 - index: -1 -oculon-leg-old - rotate: false - xy: 1275, 1349 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -oculon-old - rotate: false - xy: 691, 1149 - size: 58, 48 - orig: 58, 48 - offset: 0, 0 - index: -1 -phantom - rotate: false - xy: 1820, 1515 + xy: 1249, 927 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 -phantom-cell +nova-base rotate: false - xy: 787, 287 + xy: 1273, 201 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +nova-cell + rotate: false + xy: 1249, 869 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +nova-leg + rotate: false + xy: 1273, 151 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +poly + rotate: false + xy: 1238, 301 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +poly-cell + rotate: false + xy: 1115, 40 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 power-cell rotate: false - xy: 787, 229 + xy: 1307, 1023 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 -revenant +pulsar rotate: false - xy: 391, 1285 - size: 112, 112 - orig: 112, 112 + xy: 1989, 1343 + size: 58, 48 + orig: 58, 48 offset: 0, 0 index: -1 -revenant-cell +pulsar-base rotate: false - xy: 521, 1415 - size: 112, 112 - orig: 112, 112 - offset: 0, 0 - index: -1 -spirit - rotate: false - xy: 1175, 1309 + xy: 1273, 101 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -spirit-cell +pulsar-cell rotate: false - xy: 1225, 1309 - size: 48, 48 - orig: 48, 48 + xy: 1989, 1293 + size: 58, 48 + orig: 58, 48 offset: 0, 0 index: -1 -tau +pulsar-leg rotate: false - xy: 787, 171 - size: 56, 56 - orig: 56, 56 + xy: 1117, 1039 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 -tau-base +quasar rotate: false - xy: 1275, 1299 - size: 48, 48 - orig: 48, 48 + xy: 683, 553 + size: 80, 80 + orig: 80, 80 offset: 0, 0 index: -1 -tau-cell +quasar-base rotate: false - xy: 787, 113 - size: 56, 56 - orig: 56, 56 + xy: 571, 253 + size: 80, 80 + orig: 80, 80 offset: 0, 0 index: -1 -tau-leg +quasar-cell rotate: false - xy: 1325, 1299 - size: 48, 48 - orig: 48, 48 + xy: 571, 171 + size: 80, 80 + orig: 80, 80 offset: 0, 0 index: -1 -trident +quasar-leg rotate: false - xy: 131, 907 - size: 100, 100 - orig: 100, 100 + xy: 571, 89 + size: 80, 80 + orig: 80, 80 offset: 0, 0 index: -1 -trident-cell +spiroct rotate: false - xy: 751, 1141 - size: 56, 56 - orig: 56, 56 + xy: 591, 918 + size: 94, 75 + orig: 94, 75 + offset: 0, 0 + index: -1 +spiroct-cell + rotate: false + xy: 587, 841 + size: 94, 75 + orig: 94, 75 + offset: 0, 0 + index: -1 +spiroct-foot + rotate: false + xy: 569, 1421 + size: 46, 46 + orig: 46, 46 + offset: 0, 0 + index: -1 +spiroct-joint + rotate: false + xy: 1497, 525 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spiroct-leg + rotate: false + xy: 1, 1 + size: 48, 34 + orig: 48, 34 + offset: 0, 0 + index: -1 +spiroct-leg-base + rotate: false + xy: 51, 1 + size: 48, 34 + orig: 48, 34 offset: 0, 0 index: -1 vanguard rotate: false - xy: 1153, 999 + xy: 1465, 947 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 vanguard-cell rotate: false - xy: 1203, 999 + xy: 1515, 947 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +antumbra-missiles + rotate: false + xy: 1581, 1147 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 artillery rotate: false - xy: 753, 1083 + xy: 1307, 807 size: 48, 56 orig: 48, 56 offset: 0, 0 index: -1 +beam-weapon + rotate: false + xy: 683, 697 + size: 80, 80 + orig: 80, 80 + offset: 0, 0 + index: -1 chaos rotate: false - xy: 787, 403 + xy: 1115, 156 size: 56, 136 orig: 56, 136 offset: 0, 0 index: -1 +eclipse-weapon + rotate: false + xy: 1581, 1097 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 eradication rotate: false - xy: 99, 195 + xy: 473, 133 size: 96, 192 orig: 96, 192 offset: 0, 0 index: -1 eruption rotate: false - xy: 1003, 1087 + xy: 1681, 1089 size: 48, 56 orig: 48, 56 offset: 0, 0 index: -1 flakgun rotate: false - xy: 1053, 1099 + xy: 1731, 1097 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 flamethrower rotate: false - xy: 1103, 1091 + xy: 1781, 1089 size: 48, 56 orig: 48, 56 offset: 0, 0 index: -1 +heal-shotgun-weapon + rotate: false + xy: 1731, 1047 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 heal-weapon rotate: false - xy: 1153, 1099 + xy: 1781, 1039 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 heal-weapon-mount rotate: false - xy: 1203, 1099 + xy: 1831, 1047 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 large-weapon rotate: false - xy: 1275, 1399 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -lich-missiles - rotate: false - xy: 1325, 1449 + xy: 1931, 997 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 missiles rotate: false - xy: 1375, 1399 + xy: 1173, 94 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 missiles-mount rotate: false - xy: 1425, 1449 + xy: 1173, 44 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mount-purple-weapon + rotate: false + xy: 1223, 1 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mount-weapon rotate: false - xy: 1425, 1399 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -reaper-weapon - rotate: false - xy: 1325, 1349 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -revenant-missiles - rotate: false - xy: 1375, 1349 + xy: 1273, 251 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 small-basic-weapon rotate: false - xy: 1053, 1049 + xy: 1271, 375 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +small-mount-weapon + rotate: false + xy: 1296, 325 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 small-weapon rotate: false - xy: 1103, 1041 + xy: 1249, 645 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 +spiroct-weapon + rotate: false + xy: 1415, 969 + size: 48, 56 + orig: 48, 56 + offset: 0, 0 + index: -1 weapon rotate: false - xy: 1525, 1477 + xy: 1565, 947 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -wraith +zenith-missiles rotate: false - xy: 1575, 1477 + xy: 1615, 947 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -beam-weapon +zenith rotate: false - xy: 1957, 1771 - size: 80, 80 - orig: 80, 80 + xy: 261, 137 + size: 112, 112 + orig: 112, 112 offset: 0, 0 index: -1 -beam-weapon +zenith-cell rotate: false - xy: 1957, 1771 - size: 80, 80 - orig: 80, 80 + xy: 261, 23 + size: 112, 112 + orig: 112, 112 offset: 0, 0 index: -1 @@ -7450,35 +7968,35 @@ air-factory-icon-editor index: -1 alloy-smelter-icon-editor rotate: false - xy: 1685, 921 + xy: 1555, 921 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 arc-icon-editor rotate: false - xy: 763, 725 + xy: 375, 207 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-icon-editor rotate: false - xy: 1929, 723 + xy: 181, 17 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 battery-icon-editor rotate: false - xy: 1929, 689 + xy: 295, 47 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 battery-large-icon-editor rotate: false - xy: 485, 533 + xy: 1653, 921 size: 96, 96 orig: 96, 96 offset: 0, 0 @@ -7492,140 +8010,140 @@ blast-drill-icon-editor index: -1 blast-mixer-icon-editor rotate: false - xy: 1979, 953 + xy: 1005, 725 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-border-editor rotate: false - xy: 1929, 655 + xy: 295, 13 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-forge-icon-editor rotate: false - xy: 1783, 921 + xy: 1751, 921 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-loader-icon-editor rotate: false - xy: 485, 435 + xy: 1849, 921 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-unloader-icon-editor rotate: false - xy: 1881, 921 + xy: 1947, 921 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 bridge-conduit-icon-editor rotate: false - xy: 1929, 621 + xy: 583, 695 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-icon-editor rotate: false - xy: 1963, 739 + xy: 583, 661 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 char-icon-editor rotate: false - xy: 1963, 705 + xy: 583, 627 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-char1 rotate: false - xy: 1963, 705 + xy: 583, 627 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 clear-editor rotate: false - xy: 775, 886 + xy: 2045, 1016 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 cliff-icon-editor rotate: false - xy: 1963, 671 + xy: 583, 593 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cliffs-icon-editor rotate: false - xy: 1963, 637 + xy: 583, 559 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 coal-centrifuge-icon-editor rotate: false - xy: 1005, 725 + xy: 1071, 725 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 combustion-generator-icon-editor rotate: false - xy: 763, 691 + xy: 587, 367 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-icon-editor rotate: false - xy: 1963, 603 + xy: 587, 333 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 container-icon-editor rotate: false - xy: 1071, 725 + xy: 1137, 725 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 conveyor-icon-editor rotate: false - xy: 1997, 739 + xy: 587, 299 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper-wall-icon-editor rotate: false - xy: 1997, 705 + xy: 521, 235 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper-wall-large-icon-editor rotate: false - xy: 1137, 725 + xy: 1203, 725 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 core-foundation-icon-editor rotate: false - xy: 775, 889 + xy: 323, 437 size: 128, 128 orig: 128, 128 offset: 0, 0 @@ -7644,37 +8162,30 @@ core-shard-icon-editor orig: 96, 96 offset: 0, 0 index: -1 -core-silo-icon-editor - rotate: false - xy: 613, 857 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 craters-icon-editor rotate: false - xy: 1997, 671 + xy: 555, 235 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-craters1 rotate: false - xy: 1997, 671 + xy: 555, 235 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cryofluidmixer-icon-editor rotate: false - xy: 1203, 725 + xy: 1269, 725 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator-icon-editor rotate: false - xy: 1269, 725 + xy: 1335, 725 size: 64, 64 orig: 64, 64 offset: 0, 0 @@ -7688,119 +8199,119 @@ cyclone-icon-editor index: -1 dark-metal-icon-editor rotate: false - xy: 1997, 637 + xy: 1995, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dark-panel-1-icon-editor rotate: false - xy: 1997, 603 + xy: 1995, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-dark-panel-1 rotate: false - xy: 1997, 603 + xy: 1995, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dark-panel-2-icon-editor rotate: false - xy: 361, 77 + xy: 1995, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-dark-panel-2 rotate: false - xy: 361, 77 + xy: 1995, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dark-panel-3-icon-editor rotate: false - xy: 361, 43 + xy: 1995, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-dark-panel-3 rotate: false - xy: 361, 43 + xy: 1995, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dark-panel-4-icon-editor rotate: false - xy: 395, 77 + xy: 1995, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-dark-panel-4 rotate: false - xy: 395, 77 + xy: 1995, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dark-panel-5-icon-editor rotate: false - xy: 395, 43 + xy: 1995, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-dark-panel-5 rotate: false - xy: 395, 43 + xy: 1995, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dark-panel-6-icon-editor rotate: false - xy: 429, 77 + xy: 329, 57 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-dark-panel-6 rotate: false - xy: 429, 77 + xy: 329, 57 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 darksand-icon-editor rotate: false - xy: 429, 43 + xy: 329, 23 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-darksand1 rotate: false - xy: 429, 43 + xy: 329, 23 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 darksand-tainted-water-icon-editor rotate: false - xy: 463, 77 + xy: 409, 205 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 darksand-water-icon-editor rotate: false - xy: 463, 43 + xy: 443, 205 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -7814,861 +8325,861 @@ data-processor-icon-editor index: -1 deepwater-icon-editor rotate: false - xy: 361, 9 + xy: 477, 205 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-deepwater rotate: false - xy: 361, 9 + xy: 477, 205 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 differential-generator-icon-editor rotate: false - xy: 325, 307 + xy: 229, 81 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 diode-icon-editor rotate: false - xy: 395, 9 + xy: 511, 201 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 disassembler-icon-editor rotate: false - xy: 325, 209 + xy: 485, 533 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 distributor-icon-editor rotate: false - xy: 1335, 725 + xy: 1401, 725 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door-icon-editor rotate: false - xy: 429, 9 + xy: 545, 201 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 door-large-icon-editor rotate: false - xy: 1401, 725 + xy: 1467, 725 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 dunerocks-icon-editor rotate: false - xy: 463, 9 + xy: 363, 57 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 duo-icon-editor rotate: false - xy: 497, 71 + xy: 363, 23 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-char2 rotate: false - xy: 497, 37 + xy: 579, 201 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-char3 rotate: false - xy: 531, 71 + xy: 617, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-craters2 rotate: false - xy: 531, 37 + xy: 617, 691 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-craters3 rotate: false - xy: 497, 3 + xy: 651, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-darksand-tainted-water1 rotate: false - xy: 565, 37 + xy: 685, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-darksand-tainted-water2 rotate: false - xy: 565, 3 + xy: 617, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-darksand-tainted-water3 rotate: false - xy: 583, 675 + xy: 651, 657 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-darksand-water1 rotate: false - xy: 583, 641 + xy: 685, 691 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-darksand-water2 rotate: false - xy: 617, 675 + xy: 719, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-darksand-water3 rotate: false - xy: 583, 607 + xy: 617, 589 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-darksand2 rotate: false - xy: 531, 3 + xy: 617, 657 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-darksand3 rotate: false - xy: 565, 71 + xy: 651, 691 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-grass1 rotate: false - xy: 617, 641 + xy: 651, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 grass-icon-editor rotate: false - xy: 617, 641 + xy: 651, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-grass2 rotate: false - xy: 651, 675 + xy: 685, 657 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-grass3 rotate: false - xy: 583, 573 + xy: 719, 691 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-holostone1 rotate: false - xy: 617, 607 + xy: 753, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 holostone-icon-editor rotate: false - xy: 617, 607 + xy: 753, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-holostone2 rotate: false - xy: 651, 641 + xy: 651, 589 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-holostone3 rotate: false - xy: 685, 675 + xy: 685, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-hotrock1 rotate: false - xy: 583, 539 + xy: 719, 657 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 hotrock-icon-editor rotate: false - xy: 583, 539 + xy: 719, 657 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-hotrock2 rotate: false - xy: 617, 573 + xy: 753, 691 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-hotrock3 rotate: false - xy: 651, 607 + xy: 685, 589 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice-snow1 rotate: false - xy: 617, 539 + xy: 753, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice-snow-icon-editor rotate: false - xy: 617, 539 + xy: 753, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice-snow2 rotate: false - xy: 651, 573 + xy: 753, 589 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice-snow3 rotate: false - xy: 685, 607 + xy: 617, 555 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice1 rotate: false - xy: 685, 641 + xy: 719, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice-icon-editor rotate: false - xy: 685, 641 + xy: 719, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice2 rotate: false - xy: 719, 675 + xy: 753, 657 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice3 rotate: false - xy: 583, 505 + xy: 719, 589 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ignarock1 rotate: false - xy: 719, 641 + xy: 651, 555 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ignarock-icon-editor rotate: false - xy: 719, 641 + xy: 651, 555 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ignarock2 rotate: false - xy: 583, 471 + xy: 685, 555 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ignarock3 rotate: false - xy: 617, 505 + xy: 719, 555 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-magmarock1 rotate: false - xy: 651, 539 + xy: 753, 555 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 magmarock-icon-editor rotate: false - xy: 651, 539 + xy: 753, 555 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-magmarock2 rotate: false - xy: 685, 573 + xy: 787, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-magmarock3 rotate: false - xy: 719, 607 + xy: 787, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor rotate: false - xy: 583, 437 + xy: 787, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-icon-editor rotate: false - xy: 583, 437 + xy: 787, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-2 rotate: false - xy: 617, 471 + xy: 821, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-2-icon-editor rotate: false - xy: 617, 471 + xy: 821, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-3 rotate: false - xy: 651, 505 + xy: 821, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-3-icon-editor rotate: false - xy: 651, 505 + xy: 821, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-5 rotate: false - xy: 685, 539 + xy: 787, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-5-icon-editor rotate: false - xy: 685, 539 + xy: 787, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-damaged1 rotate: false - xy: 719, 573 + xy: 821, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-damaged-icon-editor rotate: false - xy: 719, 573 + xy: 821, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-damaged2 rotate: false - xy: 617, 437 + xy: 855, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-damaged3 rotate: false - xy: 651, 471 + xy: 855, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-moss1 rotate: false - xy: 685, 505 + xy: 821, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 moss-icon-editor rotate: false - xy: 685, 505 + xy: 821, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-moss2 rotate: false - xy: 719, 539 + xy: 855, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-moss3 rotate: false - xy: 651, 437 + xy: 889, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-coal1 rotate: false - xy: 685, 471 + xy: 889, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-coal2 rotate: false - xy: 719, 505 + xy: 855, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-coal3 rotate: false - xy: 685, 437 + xy: 889, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-copper1 rotate: false - xy: 719, 471 + xy: 923, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-copper2 rotate: false - xy: 719, 437 + xy: 923, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-copper3 rotate: false - xy: 587, 403 + xy: 889, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-lead1 rotate: false - xy: 587, 369 + xy: 923, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-lead2 rotate: false - xy: 621, 403 + xy: 957, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-lead3 rotate: false - xy: 587, 335 + xy: 957, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-scrap1 rotate: false - xy: 621, 369 + xy: 923, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-scrap2 rotate: false - xy: 655, 403 + xy: 957, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-scrap3 rotate: false - xy: 587, 301 + xy: 957, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-thorium1 rotate: false - xy: 621, 335 + xy: 991, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-thorium2 rotate: false - xy: 655, 369 + xy: 991, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-thorium3 rotate: false - xy: 689, 403 + xy: 1025, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-titanium1 rotate: false - xy: 587, 267 + xy: 991, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-titanium2 rotate: false - xy: 621, 301 + xy: 1025, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-titanium3 rotate: false - xy: 655, 335 + xy: 1059, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-pebbles1 rotate: false - xy: 689, 369 + xy: 1025, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-pebbles2 rotate: false - xy: 621, 267 + xy: 1059, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-pebbles3 rotate: false - xy: 655, 301 + xy: 1093, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-salt rotate: false - xy: 689, 335 + xy: 1059, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 salt-icon-editor rotate: false - xy: 689, 335 + xy: 1059, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand-water1 rotate: false - xy: 723, 403 + xy: 1127, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand-water2 rotate: false - xy: 723, 369 + xy: 1161, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand-water3 rotate: false - xy: 723, 335 + xy: 1127, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand1 rotate: false - xy: 655, 267 + xy: 1093, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sand-icon-editor rotate: false - xy: 655, 267 + xy: 1093, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand2 rotate: false - xy: 689, 301 + xy: 1127, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand3 rotate: false - xy: 689, 267 + xy: 1093, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-shale1 rotate: false - xy: 723, 301 + xy: 1161, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shale-icon-editor rotate: false - xy: 723, 301 + xy: 1161, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-shale2 rotate: false - xy: 723, 267 + xy: 1195, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-shale3 rotate: false - xy: 753, 657 + xy: 1161, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-slag rotate: false - xy: 753, 623 + xy: 1195, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 slag-icon-editor rotate: false - xy: 753, 623 + xy: 1195, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-snow1 rotate: false - xy: 753, 589 + xy: 1229, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-snow2 rotate: false - xy: 753, 555 + xy: 1195, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-snow3 rotate: false - xy: 753, 521 + xy: 1229, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-spawn rotate: false - xy: 753, 487 + xy: 1263, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-spore-moss1 rotate: false - xy: 753, 453 + xy: 1229, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spore-moss-icon-editor rotate: false - xy: 753, 453 + xy: 1229, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-spore-moss2 rotate: false - xy: 757, 419 + xy: 1263, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-spore-moss3 rotate: false - xy: 757, 385 + xy: 1297, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-stone1 rotate: false - xy: 757, 351 + xy: 1263, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 stone-icon-editor rotate: false - xy: 757, 351 + xy: 1263, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-stone2 rotate: false - xy: 757, 317 + xy: 1297, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-stone3 rotate: false - xy: 757, 283 + xy: 1331, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-tainted-water rotate: false - xy: 757, 249 + xy: 1297, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 tainted-water-icon-editor rotate: false - xy: 757, 249 + xy: 1297, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-tar rotate: false - xy: 787, 657 + xy: 1331, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 tar-icon-editor rotate: false - xy: 787, 657 + xy: 1331, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-tendrils1 rotate: false - xy: 787, 623 + xy: 1365, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-tendrils2 rotate: false - xy: 787, 589 + xy: 1331, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-tendrils3 rotate: false - xy: 787, 555 + xy: 1365, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-water rotate: false - xy: 787, 521 + xy: 1399, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 water-icon-editor rotate: false - xy: 787, 521 + xy: 1399, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -8682,735 +9193,742 @@ exponential-reconstructor-icon-editor index: -1 force-projector-icon-editor rotate: false - xy: 229, 81 + xy: 711, 759 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fuse-icon-editor rotate: false - xy: 327, 111 + xy: 809, 791 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 graphite-press-icon-editor rotate: false - xy: 1467, 725 + xy: 1533, 725 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 ground-factory-icon-editor rotate: false - xy: 711, 759 + xy: 907, 791 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 hail-icon-editor rotate: false - xy: 787, 487 + xy: 1365, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 icerocks-icon-editor rotate: false - xy: 787, 453 + xy: 1399, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 illuminator-icon-editor rotate: false - xy: 821, 659 + xy: 1433, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 impact-reactor-icon-editor rotate: false - xy: 905, 889 + xy: 775, 889 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 incinerator-icon-editor rotate: false - xy: 821, 625 + xy: 1399, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 inverted-sorter-icon-editor rotate: false - xy: 821, 591 + xy: 1433, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-source-icon-editor rotate: false - xy: 855, 659 + xy: 1467, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-void-icon-editor rotate: false - xy: 855, 625 + xy: 1433, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 junction-icon-editor rotate: false - xy: 855, 591 + xy: 1467, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 kiln-icon-editor rotate: false - xy: 1533, 725 + xy: 1599, 757 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 lancer-icon-editor rotate: false - xy: 1599, 725 + xy: 1665, 757 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 large-overdrive-projector-icon-editor rotate: false - xy: 809, 791 + xy: 1005, 791 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-icon-editor rotate: false - xy: 907, 791 + xy: 1103, 791 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 launch-pad-icon-editor rotate: false - xy: 1005, 791 + xy: 1201, 791 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 launch-pad-large-icon-editor rotate: false - xy: 1035, 889 + xy: 905, 889 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 liquid-junction-icon-editor rotate: false - xy: 821, 557 + xy: 1501, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-icon-editor rotate: false - xy: 889, 659 + xy: 1467, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-source-icon-editor rotate: false - xy: 889, 625 + xy: 1501, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-tank-icon-editor rotate: false - xy: 1103, 791 + xy: 1299, 791 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 liquid-void-icon-editor rotate: false - xy: 889, 591 + xy: 1535, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mass-conveyor-icon-editor rotate: false - xy: 1201, 791 + xy: 1397, 791 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mass-driver-icon-editor rotate: false - xy: 1299, 791 + xy: 453, 435 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mechanical-drill-icon-editor rotate: false - xy: 1691, 757 + xy: 1731, 757 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-pump-icon-editor rotate: false - xy: 821, 523 + xy: 1501, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 meltdown-icon-editor rotate: false - xy: 1165, 889 + xy: 1035, 889 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 melter-icon-editor rotate: false - xy: 855, 557 + xy: 1535, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mend-projector-icon-editor rotate: false - xy: 1757, 757 + xy: 1797, 757 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mender-icon-editor rotate: false - xy: 923, 659 + xy: 1535, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 message-icon-editor rotate: false - xy: 923, 625 + xy: 617, 521 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 multi-press-icon-editor rotate: false - xy: 1397, 791 + xy: 1495, 791 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 multiplicative-reconstructor-icon-editor rotate: false - xy: 323, 405 + xy: 613, 857 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 naval-factory-icon-editor rotate: false - xy: 1495, 791 + xy: 1593, 823 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-icon-editor rotate: false - xy: 1593, 791 + xy: 1691, 823 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 overdrive-projector-icon-editor rotate: false - xy: 1823, 757 + xy: 1863, 757 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 overflow-gate-icon-editor rotate: false - xy: 923, 591 + xy: 617, 487 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 +parallax-icon-editor + rotate: false + xy: 1929, 757 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 payload-router-icon-editor - rotate: false - xy: 1691, 823 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -pebbles-icon-editor - rotate: false - xy: 821, 489 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-conduit-icon-editor - rotate: false - xy: 855, 523 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-conveyor-icon-editor - rotate: false - xy: 889, 557 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-wall-icon-editor - rotate: false - xy: 957, 659 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-wall-large-icon-editor - rotate: false - xy: 1889, 757 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -phase-weaver-icon-editor - rotate: false - xy: 521, 369 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -pine-icon-editor - rotate: false - xy: 131, 1 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -plastanium-compressor-icon-editor - rotate: false - xy: 521, 303 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -plastanium-conveyor-icon-editor - rotate: false - xy: 957, 625 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -plastanium-wall-icon-editor - rotate: false - xy: 957, 591 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -plastanium-wall-large-icon-editor - rotate: false - xy: 521, 237 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -plated-conduit-icon-editor - rotate: false - xy: 821, 455 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pneumatic-drill-icon-editor - rotate: false - xy: 523, 171 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -power-node-icon-editor - rotate: false - xy: 855, 489 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -power-node-large-icon-editor - rotate: false - xy: 523, 105 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -power-source-icon-editor - rotate: false - xy: 889, 523 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -power-void-icon-editor - rotate: false - xy: 923, 557 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulse-conduit-icon-editor - rotate: false - xy: 855, 455 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulverizer-icon-editor - rotate: false - xy: 889, 489 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pyratite-mixer-icon-editor - rotate: false - xy: 1005, 659 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -repair-point-icon-editor - rotate: false - xy: 923, 523 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -resupply-point-icon-editor - rotate: false - xy: 1071, 659 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -ripple-icon-editor rotate: false xy: 1789, 823 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 -rock-icon-editor +pebbles-icon-editor rotate: false - xy: 613, 709 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -rocks-icon-editor - rotate: false - xy: 957, 557 + xy: 651, 521 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -rotary-pump-icon-editor +phase-conduit-icon-editor + rotate: false + xy: 617, 453 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conveyor-icon-editor + rotate: false + xy: 651, 487 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-wall-icon-editor + rotate: false + xy: 685, 521 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-wall-large-icon-editor + rotate: false + xy: 551, 467 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phase-weaver-icon-editor + rotate: false + xy: 1005, 659 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +pine-icon-editor + rotate: false + xy: 325, 191 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +plastanium-compressor-icon-editor + rotate: false + xy: 1071, 659 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +plastanium-conveyor-icon-editor + rotate: false + xy: 617, 419 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +plastanium-wall-icon-editor + rotate: false + xy: 651, 453 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +plastanium-wall-large-icon-editor rotate: false xy: 1137, 659 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -router-icon-editor +plated-conduit-icon-editor rotate: false - xy: 889, 455 + xy: 685, 487 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -rtg-generator-icon-editor +pneumatic-drill-icon-editor rotate: false xy: 1203, 659 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -saltrocks-icon-editor +power-node-icon-editor rotate: false - xy: 923, 489 + xy: 719, 521 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -salvo-icon-editor +power-node-large-icon-editor rotate: false xy: 1269, 659 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -sand-boulder-icon-editor +power-source-icon-editor rotate: false - xy: 957, 523 + xy: 651, 419 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -sand-water-icon-editor +power-void-icon-editor rotate: false - xy: 923, 455 + xy: 685, 453 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -sandrocks-icon-editor +pulse-conduit-icon-editor rotate: false - xy: 957, 489 + xy: 719, 487 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -scatter-icon-editor +pulverizer-icon-editor + rotate: false + xy: 753, 521 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pyratite-mixer-icon-editor rotate: false xy: 1335, 659 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -scorch-icon-editor +repair-point-icon-editor rotate: false - xy: 957, 455 + xy: 787, 523 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -scrap-wall-gigantic-icon-editor - rotate: false - xy: 1295, 889 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -scrap-wall-huge-icon-editor - rotate: false - xy: 1887, 823 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -scrap-wall-icon-editor - rotate: false - xy: 791, 419 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scrap-wall-large-icon-editor +resupply-point-icon-editor rotate: false xy: 1401, 659 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -segment-icon-editor +ripple-icon-editor + rotate: false + xy: 1887, 823 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +rock-icon-editor + rotate: false + xy: 1985, 871 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rocks-icon-editor + rotate: false + xy: 685, 419 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rotary-pump-icon-editor rotate: false xy: 1467, 659 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -separator-icon-editor +router-icon-editor + rotate: false + xy: 719, 453 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rtg-generator-icon-editor rotate: false xy: 1533, 659 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -shale-boulder-icon-editor +saltrocks-icon-editor rotate: false - xy: 791, 385 + xy: 753, 487 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -shalerocks-icon-editor +salvo-icon-editor rotate: false - xy: 791, 351 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -shock-mine-icon-editor - rotate: false - xy: 791, 317 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -shrubs-icon-editor - rotate: false - xy: 791, 283 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -silicon-crucible-icon-editor - rotate: false - xy: 423, 307 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -silicon-smelter-icon-editor - rotate: false - xy: 1599, 659 + xy: 1599, 691 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -snow-icon-editor +sand-boulder-icon-editor rotate: false - xy: 791, 249 + xy: 787, 489 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -snow-pine-icon-editor +sand-water-icon-editor rotate: false - xy: 663, 709 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -snowrock-icon-editor - rotate: false - xy: 713, 709 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -snowrocks-icon-editor - rotate: false - xy: 825, 421 + xy: 821, 523 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -solar-panel-icon-editor +sandrocks-icon-editor rotate: false - xy: 825, 387 + xy: 719, 419 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -solar-panel-large-icon-editor - rotate: false - xy: 423, 209 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -sorter-icon-editor - rotate: false - xy: 859, 421 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spawn-icon-editor - rotate: false - xy: 825, 353 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spectre-icon-editor - rotate: false - xy: 1425, 889 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -spore-cluster-icon-editor - rotate: false - xy: 181, 9 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -spore-pine-icon-editor - rotate: false - xy: 1955, 773 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -spore-press-icon-editor +scatter-icon-editor rotate: false xy: 1665, 691 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -sporerocks-icon-editor +scorch-icon-editor rotate: false - xy: 859, 387 + xy: 753, 453 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -surge-tower-icon-editor +scrap-wall-gigantic-icon-editor + rotate: false + xy: 1165, 889 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +scrap-wall-huge-icon-editor + rotate: false + xy: 325, 339 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +scrap-wall-icon-editor + rotate: false + xy: 787, 455 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall-large-icon-editor rotate: false xy: 1731, 691 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -surge-wall-icon-editor - rotate: false - xy: 893, 421 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -surge-wall-large-icon-editor +segment-icon-editor rotate: false xy: 1797, 691 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -swarmer-icon-editor +separator-icon-editor rotate: false xy: 1863, 691 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 +shale-boulder-icon-editor + rotate: false + xy: 821, 489 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shalerocks-icon-editor + rotate: false + xy: 855, 523 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shock-mine-icon-editor + rotate: false + xy: 753, 419 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shrubs-icon-editor + rotate: false + xy: 787, 421 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +silicon-crucible-icon-editor + rotate: false + xy: 325, 241 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +silicon-smelter-icon-editor + rotate: false + xy: 1929, 691 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +snow-icon-editor + rotate: false + xy: 821, 455 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow-pine-icon-editor + rotate: false + xy: 327, 141 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +snowrock-icon-editor + rotate: false + xy: 327, 91 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +snowrocks-icon-editor + rotate: false + xy: 855, 489 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +solar-panel-icon-editor + rotate: false + xy: 889, 523 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +solar-panel-large-icon-editor + rotate: false + xy: 423, 337 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +sorter-icon-editor + rotate: false + xy: 821, 421 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spawn-icon-editor + rotate: false + xy: 855, 455 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spectre-icon-editor + rotate: false + xy: 1295, 889 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +spore-cluster-icon-editor + rotate: false + xy: 1985, 829 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +spore-pine-icon-editor + rotate: false + xy: 131, 1 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spore-press-icon-editor + rotate: false + xy: 551, 401 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +sporerocks-icon-editor + rotate: false + xy: 889, 489 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +surge-tower-icon-editor + rotate: false + xy: 521, 335 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +surge-wall-icon-editor + rotate: false + xy: 923, 523 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +surge-wall-large-icon-editor + rotate: false + xy: 521, 269 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +swarmer-icon-editor + rotate: false + xy: 1599, 625 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 tendrils-icon-editor rotate: false - xy: 825, 319 + xy: 855, 421 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -9431,7 +9949,7 @@ thermal-generator-icon-editor index: -1 thermal-pump-icon-editor rotate: false - xy: 425, 111 + xy: 423, 239 size: 96, 96 orig: 96, 96 offset: 0, 0 @@ -9445,7 +9963,7 @@ thorium-reactor-icon-editor index: -1 thorium-wall-icon-editor rotate: false - xy: 859, 353 + xy: 889, 455 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -9459,21 +9977,21 @@ thorium-wall-large-icon-editor index: -1 thruster-icon-editor rotate: false - xy: 1555, 889 + xy: 1425, 889 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 titanium-conveyor-icon-editor rotate: false - xy: 893, 387 + xy: 923, 489 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-wall-icon-editor rotate: false - xy: 927, 421 + xy: 957, 523 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -9494,14 +10012,14 @@ turbine-generator-icon-editor index: -1 underflow-gate-icon-editor rotate: false - xy: 825, 285 + xy: 889, 421 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 unloader-icon-editor rotate: false - xy: 859, 319 + xy: 923, 455 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -9515,14 +10033,14 @@ vault-icon-editor index: -1 water-extractor-icon-editor rotate: false - xy: 229, 15 + xy: 1929, 625 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wave-icon-editor rotate: false - xy: 295, 15 + xy: 229, 15 size: 64, 64 orig: 64, 64 offset: 0, 0 @@ -10515,2940 +11033,2940 @@ block-core-shard-xlarge orig: 48, 48 offset: 0, 0 index: -1 -block-core-silo-large +block-craters-large rotate: false xy: 435, 22 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-core-silo-medium +block-craters-medium rotate: false xy: 983, 605 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-core-silo-small +block-craters-small rotate: false xy: 1147, 4 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-core-silo-tiny +block-craters-tiny rotate: false xy: 1293, 542 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-core-silo-xlarge +block-craters-xlarge rotate: false xy: 51, 78 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-craters-large +block-cryofluidmixer-large rotate: false xy: 493, 324 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-craters-medium +block-cryofluidmixer-medium rotate: false xy: 983, 571 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-craters-small +block-cryofluidmixer-small rotate: false xy: 1967, 797 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-craters-tiny +block-cryofluidmixer-tiny rotate: false xy: 1177, 397 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-craters-xlarge +block-cryofluidmixer-xlarge rotate: false xy: 51, 28 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-cryofluidmixer-large +block-cultivator-large rotate: false xy: 485, 282 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-cryofluidmixer-medium +block-cultivator-medium rotate: false xy: 743, 553 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-cryofluidmixer-small +block-cultivator-small rotate: false xy: 1967, 771 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-cryofluidmixer-tiny +block-cultivator-tiny rotate: false xy: 1293, 524 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-cryofluidmixer-xlarge +block-cultivator-xlarge rotate: false xy: 857, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-cultivator-large +block-cyclone-large rotate: false xy: 543, 374 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-cultivator-medium +block-cyclone-medium rotate: false xy: 777, 544 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-cultivator-small +block-cyclone-small rotate: false xy: 735, 527 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-cultivator-tiny +block-cyclone-tiny rotate: false xy: 1311, 542 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-cultivator-xlarge +block-cyclone-xlarge rotate: false xy: 907, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-cyclone-large +block-dark-metal-large rotate: false xy: 535, 332 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-cyclone-medium +block-dark-metal-medium rotate: false xy: 811, 544 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-cyclone-small +block-dark-metal-small rotate: false xy: 1785, 745 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-cyclone-tiny +block-dark-metal-tiny rotate: false xy: 1177, 379 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-cyclone-xlarge +block-dark-metal-xlarge rotate: false xy: 957, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-dark-metal-large +block-dark-panel-1-large rotate: false xy: 593, 424 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-dark-metal-medium +block-dark-panel-1-medium rotate: false xy: 845, 544 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-dark-metal-small +block-dark-panel-1-small rotate: false xy: 1811, 745 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-dark-metal-tiny +block-dark-panel-1-tiny rotate: false xy: 1311, 524 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-dark-metal-xlarge +block-dark-panel-1-xlarge rotate: false xy: 1007, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-dark-panel-1-large +block-dark-panel-2-large rotate: false xy: 585, 382 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-dark-panel-1-medium +block-dark-panel-2-medium rotate: false xy: 879, 537 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-dark-panel-1-small +block-dark-panel-2-small rotate: false xy: 1837, 745 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-dark-panel-1-tiny +block-dark-panel-2-tiny rotate: false xy: 1329, 542 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-dark-panel-1-xlarge +block-dark-panel-2-xlarge rotate: false xy: 1057, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-dark-panel-2-large +block-dark-panel-3-large rotate: false xy: 643, 474 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-dark-panel-2-medium +block-dark-panel-3-medium rotate: false xy: 913, 537 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-dark-panel-2-small +block-dark-panel-3-small rotate: false xy: 1863, 745 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-dark-panel-2-tiny +block-dark-panel-3-tiny rotate: false xy: 1177, 361 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-dark-panel-2-xlarge +block-dark-panel-3-xlarge rotate: false xy: 1107, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-dark-panel-3-large +block-dark-panel-4-large rotate: false xy: 635, 432 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-dark-panel-3-medium +block-dark-panel-4-medium rotate: false xy: 947, 537 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-dark-panel-3-small +block-dark-panel-4-small rotate: false xy: 1889, 745 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-dark-panel-3-tiny +block-dark-panel-4-tiny rotate: false xy: 1329, 524 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-dark-panel-3-xlarge +block-dark-panel-4-xlarge rotate: false xy: 1157, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-dark-panel-4-large +block-dark-panel-5-large rotate: false xy: 693, 524 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-dark-panel-4-medium +block-dark-panel-5-medium rotate: false xy: 981, 537 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-dark-panel-4-small +block-dark-panel-5-small rotate: false xy: 1915, 745 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-dark-panel-4-tiny +block-dark-panel-5-tiny rotate: false xy: 1347, 542 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-dark-panel-4-xlarge +block-dark-panel-5-xlarge rotate: false xy: 1207, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-dark-panel-5-large +block-dark-panel-6-large rotate: false xy: 685, 482 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-dark-panel-5-medium +block-dark-panel-6-medium rotate: false xy: 1027, 786 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-dark-panel-5-small +block-dark-panel-6-small rotate: false xy: 1941, 745 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-dark-panel-5-tiny +block-dark-panel-6-tiny rotate: false xy: 1177, 343 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-dark-panel-5-xlarge +block-dark-panel-6-xlarge rotate: false xy: 1257, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-dark-panel-6-large +block-darksand-large rotate: false xy: 477, 232 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-dark-panel-6-medium +block-darksand-medium rotate: false xy: 1069, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-dark-panel-6-small +block-darksand-small rotate: false xy: 1967, 745 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-dark-panel-6-tiny - rotate: false - xy: 1347, 524 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-dark-panel-6-xlarge - rotate: false - xy: 1307, 975 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -block-darksand-large +block-darksand-tainted-water-large rotate: false xy: 477, 190 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-darksand-medium +block-darksand-tainted-water-medium rotate: false xy: 1103, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-darksand-small +block-darksand-tainted-water-small rotate: false xy: 1993, 813 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-darksand-tainted-water-large - rotate: false - xy: 477, 148 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -block-darksand-tainted-water-medium - rotate: false - xy: 1137, 828 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -block-darksand-tainted-water-small - rotate: false - xy: 1993, 787 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 block-darksand-tainted-water-tiny rotate: false - xy: 1365, 542 + xy: 1347, 524 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-darksand-tainted-water-xlarge rotate: false - xy: 1357, 975 + xy: 1307, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-darksand-tiny rotate: false - xy: 1177, 325 + xy: 1365, 542 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-darksand-water-large rotate: false - xy: 477, 106 + xy: 477, 148 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-darksand-water-medium rotate: false - xy: 1171, 828 + xy: 1137, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-darksand-water-small rotate: false - xy: 2019, 813 + xy: 1993, 787 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-darksand-water-tiny rotate: false - xy: 1365, 524 + xy: 1177, 325 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-darksand-water-xlarge rotate: false - xy: 1407, 975 + xy: 1357, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-darksand-xlarge rotate: false - xy: 1457, 975 + xy: 1407, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-data-processor-large rotate: false - xy: 477, 64 + xy: 477, 106 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-data-processor-medium rotate: false - xy: 1205, 828 + xy: 1171, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-data-processor-small rotate: false - xy: 1993, 761 + xy: 2019, 813 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-data-processor-tiny rotate: false - xy: 1383, 542 + xy: 1365, 524 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-data-processor-xlarge rotate: false - xy: 1507, 975 + xy: 1457, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-deepwater-large rotate: false - xy: 477, 22 + xy: 477, 64 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-deepwater-medium rotate: false - xy: 1239, 828 + xy: 1205, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-deepwater-small rotate: false - xy: 2019, 787 + xy: 1993, 761 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-deepwater-tiny rotate: false - xy: 1177, 307 + xy: 1383, 542 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-deepwater-xlarge rotate: false - xy: 1557, 975 + xy: 1507, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-differential-generator-large rotate: false - xy: 527, 282 + xy: 477, 22 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-differential-generator-medium rotate: false - xy: 1273, 828 + xy: 1239, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-differential-generator-small rotate: false - xy: 2019, 761 + xy: 2019, 787 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-differential-generator-tiny rotate: false - xy: 1383, 524 + xy: 1177, 307 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-differential-generator-xlarge rotate: false - xy: 1607, 975 + xy: 1557, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-diode-large rotate: false - xy: 519, 240 + xy: 527, 282 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-diode-medium rotate: false - xy: 1307, 828 + xy: 1273, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-diode-small rotate: false - xy: 1993, 735 + xy: 2019, 761 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-diode-tiny rotate: false - xy: 1401, 542 + xy: 1383, 524 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-diode-xlarge rotate: false - xy: 1657, 975 + xy: 1607, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-disassembler-large rotate: false - xy: 519, 198 + xy: 519, 240 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-disassembler-medium rotate: false - xy: 1341, 828 + xy: 1307, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-disassembler-small rotate: false - xy: 2019, 735 + xy: 1993, 735 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-disassembler-tiny rotate: false - xy: 1177, 289 + xy: 1401, 542 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-disassembler-xlarge rotate: false - xy: 1707, 975 + xy: 1657, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-distributor-large rotate: false - xy: 519, 156 + xy: 519, 198 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-distributor-medium rotate: false - xy: 1375, 828 + xy: 1341, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-distributor-small rotate: false - xy: 1095, 768 + xy: 2019, 735 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-distributor-tiny rotate: false - xy: 1401, 524 + xy: 1177, 289 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-distributor-xlarge rotate: false - xy: 1757, 975 + xy: 1707, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-door-large rotate: false - xy: 519, 114 + xy: 519, 156 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-door-large-large rotate: false - xy: 519, 72 + xy: 519, 114 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-door-large-medium rotate: false - xy: 1409, 828 + xy: 1375, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-door-large-small rotate: false - xy: 1121, 768 + xy: 1095, 768 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-door-large-tiny rotate: false - xy: 1419, 542 + xy: 1401, 524 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-door-large-xlarge rotate: false - xy: 1807, 975 + xy: 1757, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-door-medium rotate: false - xy: 1443, 828 + xy: 1409, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-door-small rotate: false - xy: 1147, 768 + xy: 1121, 768 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-door-tiny rotate: false - xy: 1177, 271 + xy: 1419, 542 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-door-xlarge rotate: false - xy: 1857, 975 + xy: 1807, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-dunerocks-large rotate: false - xy: 519, 30 + xy: 519, 72 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-dunerocks-medium rotate: false - xy: 1477, 828 + xy: 1443, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-dunerocks-small rotate: false - xy: 1173, 768 + xy: 1147, 768 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-dunerocks-tiny rotate: false - xy: 1419, 524 + xy: 1177, 271 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-dunerocks-xlarge rotate: false - xy: 1907, 975 + xy: 1857, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-duo-large rotate: false - xy: 577, 332 + xy: 519, 30 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-duo-medium rotate: false - xy: 1511, 828 + xy: 1477, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-duo-small rotate: false - xy: 1199, 768 + xy: 1173, 768 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-duo-tiny rotate: false - xy: 1437, 542 + xy: 1419, 524 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-duo-xlarge rotate: false - xy: 1957, 975 + xy: 1907, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-exponential-reconstructor-large rotate: false - xy: 569, 290 + xy: 577, 332 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-exponential-reconstructor-medium rotate: false - xy: 1545, 828 + xy: 1511, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-exponential-reconstructor-small rotate: false - xy: 1225, 768 + xy: 1199, 768 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-exponential-reconstructor-tiny rotate: false - xy: 1177, 253 + xy: 1437, 542 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-exponential-reconstructor-xlarge rotate: false - xy: 345, 866 + xy: 1957, 975 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-force-projector-large rotate: false - xy: 627, 382 + xy: 569, 290 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-force-projector-medium rotate: false - xy: 985, 744 + xy: 1545, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-force-projector-small rotate: false - xy: 1251, 768 + xy: 1225, 768 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-force-projector-tiny rotate: false - xy: 1437, 524 + xy: 1177, 253 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-force-projector-xlarge rotate: false - xy: 395, 866 + xy: 345, 866 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-fuse-large rotate: false - xy: 619, 340 + xy: 627, 382 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-fuse-medium rotate: false - xy: 977, 710 + xy: 985, 744 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-fuse-small rotate: false - xy: 1277, 768 + xy: 1251, 768 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-fuse-tiny rotate: false - xy: 1455, 542 + xy: 1437, 524 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-fuse-xlarge rotate: false - xy: 445, 866 + xy: 395, 866 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-graphite-press-large rotate: false - xy: 677, 432 + xy: 619, 340 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-graphite-press-medium rotate: false - xy: 1979, 865 + xy: 977, 710 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-graphite-press-small rotate: false - xy: 1303, 768 + xy: 1277, 768 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-graphite-press-tiny rotate: false - xy: 1177, 235 + xy: 1455, 542 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-graphite-press-xlarge rotate: false - xy: 495, 866 + xy: 445, 866 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-grass-large rotate: false - xy: 669, 390 + xy: 677, 432 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-grass-medium rotate: false - xy: 2013, 873 + xy: 1979, 865 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-grass-small rotate: false - xy: 1329, 768 + xy: 1303, 768 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-grass-tiny rotate: false - xy: 1455, 524 + xy: 1177, 235 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-grass-xlarge rotate: false - xy: 545, 866 + xy: 495, 866 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ground-factory-large rotate: false - xy: 727, 482 + xy: 669, 390 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ground-factory-medium rotate: false - xy: 1011, 710 + xy: 2013, 873 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ground-factory-small rotate: false - xy: 1355, 768 + xy: 1329, 768 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ground-factory-tiny rotate: false - xy: 1473, 542 + xy: 1455, 524 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ground-factory-xlarge rotate: false - xy: 595, 866 + xy: 545, 866 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-hail-large rotate: false - xy: 719, 440 + xy: 727, 482 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-hail-medium rotate: false - xy: 1003, 676 + xy: 1011, 710 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-hail-small rotate: false - xy: 1381, 768 + xy: 1355, 768 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-hail-tiny rotate: false - xy: 1177, 217 + xy: 1473, 542 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-hail-xlarge rotate: false - xy: 645, 866 + xy: 595, 866 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-holostone-large rotate: false - xy: 561, 240 + xy: 719, 440 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-holostone-medium rotate: false - xy: 1019, 744 + xy: 1003, 676 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-holostone-small rotate: false - xy: 1407, 768 + xy: 1381, 768 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-holostone-tiny rotate: false - xy: 1473, 524 + xy: 1177, 217 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-holostone-xlarge rotate: false - xy: 695, 866 + xy: 645, 866 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-hotrock-large rotate: false - xy: 561, 198 + xy: 561, 240 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-hotrock-medium rotate: false - xy: 1017, 642 + xy: 1019, 744 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-hotrock-small rotate: false - xy: 1433, 768 + xy: 1407, 768 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-hotrock-tiny rotate: false - xy: 1491, 542 + xy: 1473, 524 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-hotrock-xlarge rotate: false - xy: 101, 478 + xy: 695, 866 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ice-large rotate: false - xy: 561, 156 + xy: 561, 198 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ice-medium rotate: false - xy: 1017, 608 + xy: 1017, 642 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ice-small rotate: false - xy: 1459, 768 + xy: 1433, 768 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ice-snow-large rotate: false - xy: 561, 114 + xy: 561, 156 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ice-snow-medium rotate: false - xy: 1017, 574 + xy: 1017, 608 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ice-snow-small rotate: false - xy: 1485, 768 + xy: 1459, 768 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ice-snow-tiny rotate: false - xy: 1177, 199 + xy: 1491, 542 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ice-snow-xlarge rotate: false - xy: 101, 428 + xy: 101, 478 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ice-tiny rotate: false - xy: 1491, 524 + xy: 1177, 199 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ice-xlarge rotate: false - xy: 101, 378 + xy: 101, 428 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-icerocks-large rotate: false - xy: 561, 72 + xy: 561, 114 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-icerocks-medium rotate: false - xy: 1037, 676 + xy: 1017, 574 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-icerocks-small rotate: false - xy: 1511, 768 + xy: 1485, 768 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-icerocks-tiny rotate: false - xy: 1509, 542 + xy: 1491, 524 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icerocks-xlarge rotate: false - xy: 101, 328 + xy: 101, 378 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ignarock-large rotate: false - xy: 561, 30 + xy: 561, 72 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ignarock-medium rotate: false - xy: 1045, 710 + xy: 1037, 676 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ignarock-small rotate: false - xy: 1537, 768 + xy: 1511, 768 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ignarock-tiny rotate: false - xy: 1177, 181 + xy: 1509, 542 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ignarock-xlarge rotate: false - xy: 101, 278 + xy: 101, 328 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-illuminator-large rotate: false - xy: 611, 290 + xy: 561, 30 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-illuminator-medium rotate: false - xy: 1051, 642 + xy: 1045, 710 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-illuminator-small rotate: false - xy: 1563, 763 + xy: 1537, 768 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-illuminator-tiny rotate: false - xy: 1509, 524 + xy: 1177, 181 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-illuminator-xlarge rotate: false - xy: 101, 228 + xy: 101, 278 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-impact-reactor-large rotate: false - xy: 603, 248 + xy: 611, 290 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-impact-reactor-medium rotate: false - xy: 1051, 608 + xy: 1051, 642 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-impact-reactor-small rotate: false - xy: 1087, 742 + xy: 1563, 763 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-impact-reactor-tiny rotate: false - xy: 1177, 163 + xy: 1509, 524 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-impact-reactor-xlarge rotate: false - xy: 101, 178 + xy: 101, 228 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-incinerator-large rotate: false - xy: 603, 206 + xy: 603, 248 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-incinerator-medium rotate: false - xy: 1051, 574 + xy: 1051, 608 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-incinerator-small rotate: false - xy: 1113, 742 + xy: 1087, 742 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-incinerator-tiny rotate: false - xy: 1177, 145 + xy: 1177, 163 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-incinerator-xlarge rotate: false - xy: 101, 128 + xy: 101, 178 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-inverted-sorter-large rotate: false - xy: 603, 164 + xy: 603, 206 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-inverted-sorter-medium rotate: false - xy: 1071, 676 + xy: 1051, 574 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-inverted-sorter-small rotate: false - xy: 1139, 742 + xy: 1113, 742 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-inverted-sorter-tiny rotate: false - xy: 1177, 127 + xy: 1177, 145 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-inverted-sorter-xlarge rotate: false - xy: 101, 78 + xy: 101, 128 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-item-source-large rotate: false - xy: 603, 122 + xy: 603, 164 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-item-source-medium rotate: false - xy: 1085, 642 + xy: 1071, 676 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-item-source-small rotate: false - xy: 1165, 742 + xy: 1139, 742 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-item-source-tiny rotate: false - xy: 1177, 109 + xy: 1177, 127 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-item-source-xlarge rotate: false - xy: 101, 28 + xy: 101, 78 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-item-void-large rotate: false - xy: 603, 80 + xy: 603, 122 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-item-void-medium rotate: false - xy: 1085, 608 + xy: 1085, 642 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-item-void-small rotate: false - xy: 1191, 742 + xy: 1165, 742 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-item-void-tiny rotate: false - xy: 1177, 91 + xy: 1177, 109 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-item-void-xlarge rotate: false - xy: 231, 608 + xy: 101, 28 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-junction-large rotate: false - xy: 603, 38 + xy: 603, 80 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-junction-medium rotate: false - xy: 1085, 574 + xy: 1085, 608 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-junction-small rotate: false - xy: 1217, 742 + xy: 1191, 742 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-junction-tiny rotate: false - xy: 1177, 73 + xy: 1177, 91 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-junction-xlarge rotate: false - xy: 231, 558 + xy: 231, 608 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-kiln-large rotate: false - xy: 661, 340 + xy: 603, 38 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-kiln-medium rotate: false - xy: 2013, 839 + xy: 1085, 574 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-kiln-small rotate: false - xy: 1243, 742 + xy: 1217, 742 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-kiln-tiny rotate: false - xy: 1177, 55 + xy: 1177, 73 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-kiln-xlarge rotate: false - xy: 745, 866 + xy: 231, 558 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-lancer-large rotate: false - xy: 653, 298 + xy: 661, 340 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-lancer-medium rotate: false - xy: 1579, 823 + xy: 2013, 839 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-lancer-small rotate: false - xy: 1269, 742 + xy: 1243, 742 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-lancer-tiny rotate: false - xy: 1177, 37 + xy: 1177, 55 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-lancer-xlarge rotate: false - xy: 151, 508 + xy: 745, 866 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-large-overdrive-projector-large rotate: false - xy: 711, 390 + xy: 653, 298 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-large-overdrive-projector-medium rotate: false - xy: 1613, 823 + xy: 1579, 823 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-large-overdrive-projector-small rotate: false - xy: 1295, 742 + xy: 1269, 742 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-large-overdrive-projector-tiny rotate: false - xy: 667, 2 + xy: 1177, 37 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-large-overdrive-projector-xlarge rotate: false - xy: 151, 458 + xy: 151, 508 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-laser-drill-large rotate: false - xy: 703, 348 + xy: 711, 390 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-laser-drill-medium rotate: false - xy: 1647, 823 + xy: 1613, 823 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-laser-drill-small rotate: false - xy: 1321, 742 + xy: 1295, 742 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-laser-drill-tiny rotate: false - xy: 1527, 542 + xy: 667, 2 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-laser-drill-xlarge rotate: false - xy: 201, 508 + xy: 151, 458 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-launch-pad-large rotate: false - xy: 761, 440 + xy: 703, 348 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-launch-pad-large-large rotate: false - xy: 753, 398 + xy: 761, 440 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-launch-pad-large-medium rotate: false - xy: 1681, 823 + xy: 1647, 823 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-launch-pad-large-small rotate: false - xy: 1347, 742 + xy: 1321, 742 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-launch-pad-large-tiny rotate: false - xy: 1527, 524 + xy: 1527, 542 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-launch-pad-large-xlarge rotate: false - xy: 151, 408 + xy: 201, 508 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-launch-pad-medium rotate: false - xy: 1715, 823 + xy: 1681, 823 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-launch-pad-small rotate: false - xy: 1373, 742 + xy: 1347, 742 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-launch-pad-tiny rotate: false - xy: 1561, 599 + xy: 1527, 524 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-launch-pad-xlarge rotate: false - xy: 201, 458 + xy: 151, 408 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-liquid-junction-large rotate: false - xy: 645, 248 + xy: 753, 398 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-liquid-junction-medium rotate: false - xy: 1749, 823 + xy: 1715, 823 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-liquid-junction-small rotate: false - xy: 1399, 742 + xy: 1373, 742 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-liquid-junction-tiny rotate: false - xy: 1541, 571 + xy: 1561, 599 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-liquid-junction-xlarge rotate: false - xy: 151, 358 + xy: 201, 458 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-liquid-router-large rotate: false - xy: 645, 206 + xy: 645, 248 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-liquid-router-medium rotate: false - xy: 1783, 823 + xy: 1749, 823 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-liquid-router-small rotate: false - xy: 1425, 742 + xy: 1399, 742 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-liquid-router-tiny rotate: false - xy: 435, 4 + xy: 1541, 571 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-liquid-router-xlarge rotate: false - xy: 201, 408 + xy: 151, 358 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-liquid-source-large rotate: false - xy: 645, 164 + xy: 645, 206 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-liquid-source-medium rotate: false - xy: 1817, 823 + xy: 1783, 823 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-liquid-source-small rotate: false - xy: 1451, 742 + xy: 1425, 742 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-liquid-source-tiny rotate: false - xy: 453, 4 + xy: 435, 4 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-liquid-source-xlarge rotate: false - xy: 151, 308 + xy: 201, 408 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-liquid-tank-large rotate: false - xy: 645, 122 + xy: 645, 164 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-liquid-tank-medium rotate: false - xy: 1851, 823 + xy: 1817, 823 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-liquid-tank-small rotate: false - xy: 1477, 742 + xy: 1451, 742 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-liquid-tank-tiny rotate: false - xy: 471, 4 + xy: 453, 4 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-liquid-tank-xlarge rotate: false - xy: 201, 358 + xy: 151, 308 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-liquid-void-large rotate: false - xy: 645, 80 + xy: 645, 122 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-liquid-void-medium rotate: false - xy: 1885, 823 + xy: 1851, 823 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-liquid-void-small rotate: false - xy: 1503, 742 + xy: 1477, 742 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-liquid-void-tiny rotate: false - xy: 489, 4 + xy: 471, 4 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-liquid-void-xlarge rotate: false - xy: 151, 258 + xy: 201, 358 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-magmarock-large rotate: false - xy: 645, 38 + xy: 645, 80 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-magmarock-medium rotate: false - xy: 1919, 823 + xy: 1885, 823 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-magmarock-small rotate: false - xy: 1529, 742 + xy: 1503, 742 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-magmarock-tiny rotate: false - xy: 855, 2 + xy: 489, 4 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-magmarock-xlarge rotate: false - xy: 201, 308 + xy: 151, 258 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-mass-conveyor-large rotate: false - xy: 695, 298 + xy: 645, 38 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-mass-conveyor-medium rotate: false - xy: 1953, 823 + xy: 1919, 823 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-mass-conveyor-small rotate: false - xy: 1079, 716 + xy: 1529, 742 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-mass-conveyor-tiny rotate: false - xy: 873, 2 + xy: 855, 2 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-mass-conveyor-xlarge rotate: false - xy: 151, 208 + xy: 201, 308 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-mass-driver-large rotate: false - xy: 687, 256 + xy: 695, 298 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-mass-driver-medium rotate: false - xy: 769, 510 + xy: 1953, 823 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-mass-driver-small rotate: false - xy: 1105, 716 + xy: 1079, 716 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-mass-driver-tiny rotate: false - xy: 891, 2 + xy: 873, 2 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-mass-driver-xlarge rotate: false - xy: 201, 258 + xy: 151, 208 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-mechanical-drill-large rotate: false - xy: 687, 214 + xy: 687, 256 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-mechanical-drill-medium rotate: false - xy: 803, 510 + xy: 769, 510 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-mechanical-drill-small rotate: false - xy: 1131, 716 + xy: 1105, 716 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-mechanical-drill-tiny rotate: false - xy: 909, 2 + xy: 891, 2 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-mechanical-drill-xlarge rotate: false - xy: 151, 158 + xy: 201, 258 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-mechanical-pump-large rotate: false - xy: 687, 172 + xy: 687, 214 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-mechanical-pump-medium rotate: false - xy: 837, 510 + xy: 803, 510 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-mechanical-pump-small rotate: false - xy: 1157, 716 + xy: 1131, 716 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-mechanical-pump-tiny rotate: false - xy: 1581, 745 + xy: 909, 2 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-mechanical-pump-xlarge rotate: false - xy: 201, 208 + xy: 151, 158 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-meltdown-large rotate: false - xy: 687, 130 + xy: 687, 172 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-meltdown-medium rotate: false - xy: 871, 503 + xy: 837, 510 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-meltdown-small rotate: false - xy: 1183, 716 + xy: 1157, 716 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-meltdown-tiny rotate: false - xy: 1195, 505 + xy: 1581, 745 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-meltdown-xlarge rotate: false - xy: 151, 108 + xy: 201, 208 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-melter-large rotate: false - xy: 687, 88 + xy: 687, 130 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-melter-medium rotate: false - xy: 905, 503 + xy: 871, 503 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-melter-small rotate: false - xy: 1209, 716 + xy: 1183, 716 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-melter-tiny rotate: false - xy: 1195, 487 + xy: 1195, 505 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-melter-xlarge rotate: false - xy: 201, 158 + xy: 151, 108 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-mend-projector-large rotate: false - xy: 687, 46 + xy: 687, 88 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-mend-projector-medium rotate: false - xy: 939, 503 + xy: 905, 503 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-mend-projector-small rotate: false - xy: 1235, 716 + xy: 1209, 716 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-mend-projector-tiny rotate: false - xy: 1195, 469 + xy: 1195, 487 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-mend-projector-xlarge rotate: false - xy: 151, 58 + xy: 201, 158 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-mender-large rotate: false - xy: 745, 348 + xy: 687, 46 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-mender-medium rotate: false - xy: 973, 503 + xy: 939, 503 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-mender-small rotate: false - xy: 1261, 716 + xy: 1235, 716 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-mender-tiny rotate: false - xy: 1195, 451 + xy: 1195, 469 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-mender-xlarge rotate: false - xy: 201, 108 + xy: 151, 58 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-message-large rotate: false - xy: 737, 306 + xy: 745, 348 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-message-medium rotate: false - xy: 1007, 503 + xy: 973, 503 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-message-small rotate: false - xy: 1287, 716 + xy: 1261, 716 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-message-tiny rotate: false - xy: 1195, 433 + xy: 1195, 451 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-message-xlarge rotate: false - xy: 201, 58 + xy: 201, 108 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-metal-floor-2-large rotate: false - xy: 795, 398 + xy: 737, 306 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-metal-floor-2-medium rotate: false - xy: 1015, 537 + xy: 1007, 503 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-metal-floor-2-small rotate: false - xy: 1313, 716 + xy: 1287, 716 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-metal-floor-2-tiny rotate: false - xy: 1195, 415 + xy: 1195, 433 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-metal-floor-2-xlarge rotate: false - xy: 251, 508 + xy: 201, 58 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-metal-floor-3-large rotate: false - xy: 787, 356 + xy: 795, 398 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-metal-floor-3-medium rotate: false - xy: 1049, 540 + xy: 1015, 537 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-metal-floor-3-small rotate: false - xy: 1339, 716 + xy: 1313, 716 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-metal-floor-3-tiny rotate: false - xy: 1195, 397 + xy: 1195, 415 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-metal-floor-3-xlarge rotate: false - xy: 251, 458 + xy: 251, 508 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-metal-floor-5-large rotate: false - xy: 729, 256 + xy: 787, 356 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-metal-floor-5-medium rotate: false - xy: 1083, 540 + xy: 1049, 540 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-metal-floor-5-small rotate: false - xy: 1365, 716 + xy: 1339, 716 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-metal-floor-5-tiny rotate: false - xy: 1195, 379 + xy: 1195, 397 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-metal-floor-5-xlarge rotate: false - xy: 251, 408 + xy: 251, 458 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-metal-floor-damaged-large rotate: false - xy: 729, 214 + xy: 729, 256 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-metal-floor-damaged-medium rotate: false - xy: 1041, 503 + xy: 1083, 540 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-metal-floor-damaged-small rotate: false - xy: 1391, 716 + xy: 1365, 716 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-metal-floor-damaged-tiny rotate: false - xy: 1195, 361 + xy: 1195, 379 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-metal-floor-damaged-xlarge rotate: false - xy: 251, 358 + xy: 251, 408 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-metal-floor-large rotate: false - xy: 729, 172 + xy: 729, 214 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-metal-floor-medium rotate: false - xy: 1075, 506 + xy: 1041, 503 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-metal-floor-small rotate: false - xy: 1417, 716 + xy: 1391, 716 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-metal-floor-tiny rotate: false - xy: 1195, 343 + xy: 1195, 361 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-metal-floor-xlarge rotate: false - xy: 251, 308 + xy: 251, 358 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-moss-large rotate: false - xy: 729, 130 + xy: 729, 172 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-moss-medium rotate: false - xy: 1109, 506 + xy: 1075, 506 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-moss-small rotate: false - xy: 1443, 716 + xy: 1417, 716 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-moss-tiny rotate: false - xy: 1195, 325 + xy: 1195, 343 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-moss-xlarge rotate: false - xy: 251, 258 + xy: 251, 308 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-multi-press-large rotate: false - xy: 729, 88 + xy: 729, 130 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-multi-press-medium rotate: false - xy: 1117, 540 + xy: 1109, 506 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-multi-press-small rotate: false - xy: 1469, 716 + xy: 1443, 716 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-multi-press-tiny rotate: false - xy: 1195, 307 + xy: 1195, 325 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-multi-press-xlarge rotate: false - xy: 251, 208 + xy: 251, 258 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-multiplicative-reconstructor-large rotate: false - xy: 729, 46 + xy: 729, 88 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-multiplicative-reconstructor-medium rotate: false - xy: 1143, 506 + xy: 1117, 540 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-multiplicative-reconstructor-small rotate: false - xy: 1495, 716 + xy: 1469, 716 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-multiplicative-reconstructor-tiny rotate: false - xy: 1195, 289 + xy: 1195, 307 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-multiplicative-reconstructor-xlarge rotate: false - xy: 251, 158 + xy: 251, 208 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-naval-factory-large rotate: false - xy: 687, 4 + xy: 729, 46 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-naval-factory-medium rotate: false - xy: 837, 476 + xy: 1143, 506 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-naval-factory-small rotate: false - xy: 1521, 716 + xy: 1495, 716 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-naval-factory-tiny rotate: false - xy: 1195, 271 + xy: 1195, 289 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-naval-factory-xlarge rotate: false - xy: 251, 108 + xy: 251, 158 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-oil-extractor-large rotate: false - xy: 729, 4 + xy: 687, 4 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-oil-extractor-medium rotate: false - xy: 803, 476 + xy: 837, 476 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-oil-extractor-small rotate: false - xy: 1105, 690 + xy: 1521, 716 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-oil-extractor-tiny rotate: false - xy: 1195, 253 + xy: 1195, 271 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-oil-extractor-xlarge rotate: false - xy: 251, 58 + xy: 251, 108 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ore-coal-large rotate: false - xy: 779, 306 + xy: 729, 4 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ore-coal-medium rotate: false - xy: 803, 442 + xy: 803, 476 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-coal-small rotate: false - xy: 1131, 690 + xy: 1105, 690 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ore-coal-tiny rotate: false - xy: 1195, 235 + xy: 1195, 253 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ore-coal-xlarge rotate: false - xy: 151, 8 + xy: 251, 58 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ore-copper-large rotate: false - xy: 771, 264 + xy: 779, 306 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ore-copper-medium rotate: false - xy: 837, 442 + xy: 803, 442 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-copper-small rotate: false - xy: 1157, 690 + xy: 1131, 690 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ore-copper-tiny rotate: false - xy: 1195, 217 + xy: 1195, 235 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ore-copper-xlarge rotate: false - xy: 201, 8 + xy: 151, 8 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ore-lead-large rotate: false - xy: 771, 222 + xy: 771, 264 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ore-lead-medium rotate: false - xy: 871, 469 + xy: 837, 442 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-lead-small rotate: false - xy: 1183, 690 + xy: 1157, 690 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ore-lead-tiny rotate: false - xy: 1195, 199 + xy: 1195, 217 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ore-lead-xlarge rotate: false - xy: 251, 8 + xy: 201, 8 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ore-scrap-large rotate: false - xy: 771, 180 + xy: 771, 222 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ore-scrap-medium rotate: false - xy: 905, 469 + xy: 871, 469 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-scrap-small rotate: false - xy: 1209, 690 + xy: 1183, 690 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ore-scrap-tiny rotate: false - xy: 1195, 181 + xy: 1195, 199 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ore-scrap-xlarge rotate: false - xy: 281, 619 + xy: 251, 8 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ore-thorium-large rotate: false - xy: 771, 138 + xy: 771, 180 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ore-thorium-medium rotate: false - xy: 939, 469 + xy: 905, 469 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-thorium-small rotate: false - xy: 1235, 690 + xy: 1209, 690 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ore-thorium-tiny rotate: false - xy: 1195, 163 + xy: 1195, 181 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ore-thorium-xlarge rotate: false - xy: 281, 569 + xy: 281, 619 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ore-titanium-large rotate: false - xy: 771, 96 + xy: 771, 138 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ore-titanium-medium rotate: false - xy: 973, 469 + xy: 939, 469 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-titanium-small rotate: false - xy: 1261, 690 + xy: 1235, 690 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ore-titanium-tiny rotate: false - xy: 1195, 145 + xy: 1195, 163 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ore-titanium-xlarge rotate: false - xy: 301, 519 + xy: 281, 569 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-overdrive-projector-large rotate: false - xy: 771, 54 + xy: 771, 96 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-overdrive-projector-medium rotate: false - xy: 1007, 469 + xy: 973, 469 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-overdrive-projector-small rotate: false - xy: 1287, 690 + xy: 1261, 690 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-overdrive-projector-tiny rotate: false - xy: 1195, 127 + xy: 1195, 145 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-overdrive-projector-xlarge rotate: false - xy: 301, 469 + xy: 301, 519 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-overflow-gate-large rotate: false - xy: 771, 12 + xy: 771, 54 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-overflow-gate-medium rotate: false - xy: 1041, 469 + xy: 1007, 469 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-overflow-gate-small rotate: false - xy: 1313, 690 + xy: 1287, 690 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-overflow-gate-tiny rotate: false - xy: 1195, 109 + xy: 1195, 127 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-overflow-gate-xlarge + rotate: false + xy: 301, 469 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +block-parallax-large + rotate: false + xy: 771, 12 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +block-parallax-medium + rotate: false + xy: 1041, 469 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +block-parallax-small + rotate: false + xy: 1313, 690 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +block-parallax-tiny + rotate: false + xy: 1195, 109 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +block-parallax-xlarge rotate: false xy: 301, 419 size: 48, 48 diff --git a/core/assets/sprites/fallback/sprites.png b/core/assets/sprites/fallback/sprites.png index 5b30418964..9b0e0dced6 100644 Binary files a/core/assets/sprites/fallback/sprites.png and b/core/assets/sprites/fallback/sprites.png differ diff --git a/core/assets/sprites/fallback/sprites2.png b/core/assets/sprites/fallback/sprites2.png index c1776da98d..68e5843bdb 100644 Binary files a/core/assets/sprites/fallback/sprites2.png and b/core/assets/sprites/fallback/sprites2.png differ diff --git a/core/assets/sprites/fallback/sprites3.png b/core/assets/sprites/fallback/sprites3.png index 1b766809aa..dfa1d65281 100644 Binary files a/core/assets/sprites/fallback/sprites3.png and b/core/assets/sprites/fallback/sprites3.png differ diff --git a/core/assets/sprites/fallback/sprites4.png b/core/assets/sprites/fallback/sprites4.png index 97e679515f..04a20e93af 100644 Binary files a/core/assets/sprites/fallback/sprites4.png and b/core/assets/sprites/fallback/sprites4.png differ diff --git a/core/assets/sprites/fallback/sprites5.png b/core/assets/sprites/fallback/sprites5.png index ea35158ac6..8b649a827e 100644 Binary files a/core/assets/sprites/fallback/sprites5.png and b/core/assets/sprites/fallback/sprites5.png differ diff --git a/core/assets/sprites/fallback/sprites6.png b/core/assets/sprites/fallback/sprites6.png index c1d4185275..b1d8f1a6fa 100644 Binary files a/core/assets/sprites/fallback/sprites6.png and b/core/assets/sprites/fallback/sprites6.png differ diff --git a/core/assets/sprites/noiseAlpha.png b/core/assets/sprites/noiseAlpha.png new file mode 100644 index 0000000000..3553bc5891 Binary files /dev/null and b/core/assets/sprites/noiseAlpha.png differ diff --git a/core/assets/sprites/sprites.atlas b/core/assets/sprites/sprites.atlas index 95468e534f..2066ad7f01 100644 --- a/core/assets/sprites/sprites.atlas +++ b/core/assets/sprites/sprites.atlas @@ -6,5763 +6,6281 @@ filter: nearest,nearest repeat: none core-silo rotate: false - xy: 291, 759 + xy: 1097, 563 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 data-processor rotate: false - xy: 3013, 1081 + xy: 2203, 849 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 data-processor-2 rotate: false - xy: 2121, 525 + xy: 3415, 1051 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 data-processor-top rotate: false - xy: 3045, 983 + xy: 2203, 751 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 launch-pad rotate: false - xy: 3699, 1081 + xy: 2987, 849 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 launch-pad-large rotate: false - xy: 1233, 887 + xy: 2849, 1403 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 launch-pad-light rotate: false - xy: 3535, 885 + xy: 2987, 751 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 launchpod rotate: false - xy: 3099, 1483 + xy: 1796, 242 size: 66, 64 orig: 66, 64 offset: 0, 0 index: -1 force-projector rotate: false - xy: 1657, 719 + xy: 2791, 751 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 force-projector-top rotate: false - xy: 3307, 1081 + xy: 2137, 649 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 large-overdrive-projector rotate: false - xy: 3405, 1081 + xy: 2431, 653 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 large-overdrive-projector-top rotate: false - xy: 3503, 1081 + xy: 2889, 849 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mend-projector rotate: false - xy: 2479, 621 + xy: 3413, 721 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mend-projector-top rotate: false - xy: 2545, 621 + xy: 3479, 721 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mender rotate: false - xy: 2915, 1303 + xy: 3420, 163 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mender-top rotate: false - xy: 2949, 1303 + xy: 3454, 163 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 overdrive-projector rotate: false - xy: 2677, 621 + xy: 3481, 1051 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 overdrive-projector-top rotate: false - xy: 2319, 555 + xy: 3481, 985 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 shock-mine rotate: false - xy: 1397, 203 + xy: 3817, 905 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-loader rotate: false - xy: 854, 57 + xy: 1713, 747 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-unloader rotate: false - xy: 2555, 983 + xy: 2073, 943 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 bridge-arrow rotate: false - xy: 3745, 751 + xy: 3819, 1007 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor rotate: false - xy: 3847, 785 + xy: 3989, 1005 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-bridge rotate: false - xy: 3745, 683 + xy: 4023, 1005 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-end rotate: false - xy: 3779, 717 + xy: 4057, 997 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 center rotate: false - xy: 3813, 751 + xy: 2464, 279 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-0-0 rotate: false - xy: 1371, 237 + xy: 303, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-armored-conveyor-full rotate: false - xy: 1371, 237 + xy: 303, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-0-1 rotate: false - xy: 1405, 237 + xy: 337, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-0-2 rotate: false - xy: 1439, 237 + xy: 371, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-0-3 rotate: false - xy: 1473, 237 + xy: 405, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-1-0 rotate: false - xy: 1507, 237 + xy: 439, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-1-1 rotate: false - xy: 756, 7 + xy: 473, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-1-2 rotate: false - xy: 790, 7 + xy: 4063, 1201 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-1-3 rotate: false - xy: 824, 7 + xy: 4063, 1167 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-2-0 rotate: false - xy: 4062, 1445 + xy: 4063, 1133 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-2-1 rotate: false - xy: 1673, 271 + xy: 4063, 1099 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-2-2 rotate: false - xy: 1707, 271 + xy: 4063, 1065 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-2-3 rotate: false - xy: 2785, 619 + xy: 4063, 1031 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-3-0 rotate: false - xy: 2819, 619 + xy: 4061, 2015 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-3-1 rotate: false - xy: 2853, 619 + xy: 1861, 110 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-3-2 rotate: false - xy: 2887, 619 + xy: 3154, 563 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-3-3 rotate: false - xy: 2781, 585 + xy: 895, 54 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-4-0 rotate: false - xy: 2781, 551 + xy: 3511, 1119 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-4-1 rotate: false - xy: 2815, 585 + xy: 3266, 265 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-4-2 rotate: false - xy: 2781, 517 + xy: 4061, 1981 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-4-3 rotate: false - xy: 2815, 551 + xy: 3300, 265 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-1 rotate: false - xy: 3881, 683 + xy: 2634, 287 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-2 rotate: false - xy: 3915, 717 + xy: 2668, 287 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-3 rotate: false - xy: 3949, 751 + xy: 2601, 253 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-0 rotate: false - xy: 3915, 683 + xy: 2601, 219 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-1 rotate: false - xy: 3949, 717 + xy: 2635, 253 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-2 rotate: false - xy: 3949, 683 + xy: 2635, 219 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-3 rotate: false - xy: 3983, 771 + xy: 2669, 253 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-0 rotate: false - xy: 4017, 771 + xy: 2669, 219 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-1 rotate: false - xy: 3983, 737 + xy: 3672, 223 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-2 rotate: false - xy: 3983, 703 + xy: 3182, 223 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-3 rotate: false - xy: 4017, 737 + xy: 3216, 227 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-0 rotate: false - xy: 4051, 753 + xy: 3250, 227 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-1 rotate: false - xy: 4017, 703 + xy: 3284, 231 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-2 rotate: false - xy: 4051, 719 + xy: 3318, 231 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-3 rotate: false - xy: 3983, 669 + xy: 3352, 231 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-0 rotate: false - xy: 4017, 669 + xy: 3386, 231 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-1 rotate: false - xy: 4051, 685 + xy: 3420, 231 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-2 rotate: false - xy: 4051, 651 + xy: 3454, 231 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-3 rotate: false - xy: 3643, 641 + xy: 3488, 231 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-conveyor rotate: false - xy: 3265, 619 + xy: 3579, 948 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-conveyor-0 rotate: false - xy: 3299, 627 + xy: 3647, 982 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-conveyor-1 rotate: false - xy: 3333, 627 + xy: 3579, 914 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-conveyor-2 rotate: false - xy: 3367, 627 + xy: 3613, 948 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-conveyor-edge rotate: false - xy: 3401, 627 + xy: 3579, 880 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-conveyor-stack rotate: false - xy: 3435, 627 + xy: 3613, 914 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-1 rotate: false - xy: 3503, 593 + xy: 3953, 869 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-2 rotate: false - xy: 3537, 593 + xy: 3987, 903 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-3 rotate: false - xy: 3571, 593 + xy: 4021, 937 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-0 rotate: false - xy: 3605, 593 + xy: 3987, 869 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-1 rotate: false - xy: 3639, 573 + xy: 4021, 903 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-2 rotate: false - xy: 3673, 581 + xy: 4021, 869 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-3 rotate: false - xy: 3707, 581 + xy: 3953, 835 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-0 rotate: false - xy: 3741, 581 + xy: 3987, 835 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-1 rotate: false - xy: 3775, 581 + xy: 4021, 835 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-2 rotate: false - xy: 3809, 581 + xy: 4055, 929 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-3 rotate: false - xy: 3843, 581 + xy: 4055, 895 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-0 rotate: false - xy: 3877, 581 + xy: 4055, 861 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-1 rotate: false - xy: 3911, 581 + xy: 4055, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-2 rotate: false - xy: 3945, 581 + xy: 3749, 803 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-3 rotate: false - xy: 3979, 567 + xy: 3783, 803 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-0 rotate: false - xy: 4013, 567 + xy: 3817, 803 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-1 rotate: false - xy: 4047, 549 + xy: 3851, 803 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-2 rotate: false - xy: 1737, 329 + xy: 3885, 803 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-3 rotate: false - xy: 1771, 330 + xy: 3919, 803 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cross rotate: false - xy: 3983, 635 + xy: 3921, 973 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 distributor rotate: false - xy: 2215, 655 + xy: 3349, 985 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 inverted-sorter rotate: false - xy: 1052, 143 + xy: 3284, 197 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 junction rotate: false - xy: 1222, 166 + xy: 2574, 11 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mass-conveyor rotate: false - xy: 3731, 983 + xy: 3085, 767 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mass-conveyor-edge rotate: false - xy: 3895, 1081 + xy: 2627, 653 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mass-conveyor-top rotate: false - xy: 3731, 885 + xy: 2725, 653 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 payload-router-top rotate: false - xy: 3731, 885 + xy: 2725, 653 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mass-driver-base rotate: false - xy: 3829, 885 + xy: 2921, 653 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 overflow-gate rotate: false - xy: 3017, 1303 + xy: 3522, 163 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 payload-router rotate: false - xy: 1629, 523 + xy: 3867, 1109 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 payload-router-edge rotate: false - xy: 1755, 789 + xy: 3965, 1137 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 payload-router-over rotate: false - xy: 1755, 691 + xy: 3965, 1039 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 phase-conveyor rotate: false - xy: 3095, 619 + xy: 3692, 155 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-arrow rotate: false - xy: 3129, 619 + xy: 3658, 121 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-bridge rotate: false - xy: 3163, 619 + xy: 3692, 121 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-end rotate: false - xy: 3197, 619 + xy: 3579, 982 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 router rotate: false - xy: 4017, 601 + xy: 3681, 817 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sorter rotate: false - xy: 1465, 203 + xy: 3783, 837 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 underflow-gate rotate: false - xy: 3299, 559 + xy: 4021, 801 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 blast-drill rotate: false - xy: 453, 859 + xy: 1419, 1371 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 blast-drill-rim rotate: false - xy: 453, 729 + xy: 1419, 1241 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 blast-drill-rotator rotate: false - xy: 453, 599 + xy: 1419, 1111 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 blast-drill-top rotate: false - xy: 453, 469 + xy: 1549, 1403 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 drill-top rotate: false - xy: 3099, 1351 + xy: 3183, 853 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 turbine-generator-liquid rotate: false - xy: 3099, 1351 + xy: 3183, 853 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 laser-drill rotate: false - xy: 3437, 983 + xy: 2889, 751 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-rim rotate: false - xy: 3601, 1081 + xy: 2529, 653 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-rotator rotate: false - xy: 3437, 885 + xy: 2945, 1045 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-top rotate: false - xy: 3535, 983 + xy: 2955, 947 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mechanical-drill rotate: false - xy: 2677, 687 + xy: 3447, 919 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-drill-rotator rotate: false - xy: 2347, 621 + xy: 3447, 853 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-drill-top rotate: false - xy: 2413, 621 + xy: 3447, 787 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 oil-extractor rotate: false - xy: 3993, 1081 + xy: 3971, 1235 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-liquid rotate: false - xy: 1531, 609 + xy: 3769, 1207 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-rotator rotate: false - xy: 1531, 511 + xy: 3867, 1207 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-top rotate: false - xy: 1629, 621 + xy: 3769, 1109 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 pneumatic-drill rotate: false - xy: 2451, 489 + xy: 3519, 655 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-rotator rotate: false - xy: 2517, 489 + xy: 3255, 589 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-top rotate: false - xy: 2583, 489 + xy: 3321, 589 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor rotate: false - xy: 952, 37 + xy: 3088, 465 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-liquid rotate: false - xy: 3985, 805 + xy: 3154, 471 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-rotator rotate: false - xy: 1699, 429 + xy: 3220, 457 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-top rotate: false - xy: 1765, 429 + xy: 3286, 457 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-border rotate: false - xy: 2883, 585 + xy: 4061, 1879 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-middle rotate: false - xy: 2405, 1319 + xy: 3547, 1016 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-select rotate: false - xy: 3643, 743 + xy: 3785, 1075 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-liquid rotate: false - xy: 3847, 717 + xy: 2533, 249 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 message rotate: false - xy: 2983, 1303 + xy: 3488, 163 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 place-arrow rotate: false - xy: 1727, 593 + xy: 1060, 15 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 bridge-conduit rotate: false - xy: 3813, 785 + xy: 3853, 1007 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-arrow rotate: false - xy: 3711, 683 + xy: 3887, 1007 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-arrow rotate: false - xy: 3711, 683 + xy: 3887, 1007 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-bridge rotate: false - xy: 3745, 717 + xy: 3921, 1007 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-end rotate: false - xy: 3779, 751 + xy: 3955, 1005 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom rotate: false - xy: 3813, 717 + xy: 2465, 245 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-0 rotate: false - xy: 3847, 751 + xy: 2465, 211 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-1 rotate: false - xy: 3915, 785 + xy: 2499, 249 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-2 rotate: false - xy: 3813, 683 + xy: 2499, 215 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-3 rotate: false - xy: 3813, 683 + xy: 2499, 215 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-4 rotate: false - xy: 3813, 683 + xy: 2499, 215 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-0 rotate: false - xy: 3881, 751 + xy: 2533, 215 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-1 rotate: false - xy: 3949, 785 + xy: 2566, 283 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-2 rotate: false - xy: 3847, 683 + xy: 2567, 249 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-3 rotate: false - xy: 3881, 717 + xy: 2567, 215 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-3 rotate: false - xy: 3881, 717 + xy: 2567, 215 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-4 rotate: false - xy: 3915, 751 + xy: 2600, 287 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-junction rotate: false - xy: 1222, 132 + xy: 2608, 117 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-overflow-gate rotate: false - xy: 1222, 64 + xy: 2608, 49 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-overflow-gate-top rotate: false - xy: 1154, 30 + xy: 2642, 83 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-bottom rotate: false - xy: 1188, 30 + xy: 2608, 15 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-liquid rotate: false - xy: 1222, 30 + xy: 2642, 49 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-top rotate: false - xy: 1261, 199 + xy: 2642, 15 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-tank-bottom rotate: false - xy: 3633, 983 + xy: 3043, 1061 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 liquid-tank-liquid rotate: false - xy: 3797, 1081 + xy: 3053, 963 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 liquid-tank-top rotate: false - xy: 3633, 885 + xy: 3085, 865 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mechanical-pump rotate: false - xy: 2813, 1303 + xy: 3318, 163 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mechanical-pump-liquid rotate: false - xy: 2847, 1303 + xy: 3352, 163 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rotary-pump-liquid rotate: false - xy: 2847, 1303 + xy: 3352, 163 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thermal-pump-liquid rotate: false - xy: 2847, 1303 + xy: 3352, 163 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit rotate: false - xy: 3051, 1303 + xy: 3556, 147 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-arrow rotate: false - xy: 2993, 619 + xy: 3590, 147 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-bridge rotate: false - xy: 3027, 611 + xy: 3624, 147 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-end rotate: false - xy: 3061, 611 + xy: 3658, 155 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plated-conduit-cap rotate: false - xy: 3503, 627 + xy: 3579, 846 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plated-conduit-top-0 rotate: false - xy: 3537, 627 + xy: 3613, 880 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plated-conduit-top-1 rotate: false - xy: 3571, 627 + xy: 3647, 914 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plated-conduit-top-2 rotate: false - xy: 3605, 627 + xy: 3579, 812 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plated-conduit-top-3 rotate: false - xy: 3639, 607 + xy: 3613, 846 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plated-conduit-top-4 rotate: false - xy: 1868, 345 + xy: 3647, 880 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-0 rotate: false - xy: 3745, 615 + xy: 3681, 953 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-1 rotate: false - xy: 3779, 615 + xy: 3715, 953 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-2 rotate: false - xy: 3813, 615 + xy: 3681, 919 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-4 rotate: false - xy: 3847, 615 + xy: 3715, 919 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rotary-pump rotate: false - xy: 2121, 459 + xy: 3189, 537 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thermal-pump rotate: false - xy: 1951, 723 + xy: 1844, 11 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 battery rotate: false - xy: 2849, 585 + xy: 4061, 1947 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 battery-large rotate: false - xy: 658, 111 + xy: 2651, 1045 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 battery-large-top rotate: false - xy: 756, 139 + xy: 2749, 1045 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 battery-top rotate: false - xy: 2781, 483 + xy: 3334, 265 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 combustion-generator rotate: false - xy: 3881, 785 + xy: 2498, 283 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 combustion-generator-top rotate: false - xy: 3779, 683 + xy: 2532, 283 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 differential-generator rotate: false - xy: 3045, 885 + xy: 2301, 849 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 differential-generator-liquid rotate: false - xy: 3111, 1081 + xy: 2301, 751 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 differential-generator-top rotate: false - xy: 3143, 983 + xy: 2399, 849 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 diode rotate: false - xy: 4017, 635 + xy: 3955, 971 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 diode-arrow rotate: false - xy: 4051, 617 + xy: 3989, 971 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 illuminator rotate: false - xy: 1018, 143 + xy: 2669, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 illuminator-top rotate: false - xy: 1052, 177 + xy: 3216, 193 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 impact-reactor rotate: false - xy: 843, 627 + xy: 2329, 1143 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-bottom rotate: false - xy: 973, 757 + xy: 2589, 1403 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-light rotate: false - xy: 1103, 887 + xy: 2589, 1273 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-0 rotate: false - xy: 713, 367 + xy: 2459, 1143 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-1 rotate: false - xy: 843, 497 + xy: 2719, 1403 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-2 rotate: false - xy: 973, 627 + xy: 2719, 1273 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-3 rotate: false - xy: 1103, 757 + xy: 2589, 1143 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 power-node rotate: false - xy: 1902, 345 + xy: 3613, 812 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-node-large rotate: false - xy: 2649, 489 + xy: 3387, 589 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 power-source rotate: false - xy: 3677, 615 + xy: 3647, 846 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-void rotate: false - xy: 3711, 615 + xy: 3647, 812 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rtg-generator rotate: false - xy: 2187, 457 + xy: 3255, 523 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rtg-generator-top rotate: false - xy: 4051, 583 + xy: 3715, 817 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel rotate: false - xy: 1431, 203 + xy: 3885, 939 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel-large rotate: false - xy: 2049, 821 + xy: 1746, 11 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 surge-tower rotate: false - xy: 1547, 379 + xy: 2362, 521 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thermal-generator rotate: false - xy: 1349, 313 + xy: 2560, 521 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thorium-reactor rotate: false - xy: 2147, 821 + xy: 3109, 1191 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 thorium-reactor-lights rotate: false - xy: 2049, 723 + xy: 3207, 1191 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 thorium-reactor-top rotate: false - xy: 2147, 723 + xy: 3305, 1191 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 turbine-generator rotate: false - xy: 1547, 313 + xy: 2758, 521 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 turbine-generator-cap rotate: false - xy: 1613, 313 + xy: 2824, 521 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 turbine-generator-top rotate: false - xy: 957, 301 + xy: 2890, 521 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 turbine-generator-turbine0 rotate: false - xy: 957, 235 + xy: 2956, 521 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 turbine-generator-turbine1 rotate: false - xy: 952, 169 + xy: 3022, 521 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 alloy-smelter rotate: false - xy: 1087, 361 + xy: 2455, 1045 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 alloy-smelter-top rotate: false - xy: 1185, 360 + xy: 2553, 1045 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 blast-mixer rotate: false - xy: 3655, 819 + xy: 2214, 424 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-forge rotate: false - xy: 2229, 1081 + xy: 1877, 943 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 coal-centrifuge rotate: false - xy: 4020, 1479 + xy: 2059, 128 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-bottom rotate: false - xy: 1923, 525 + xy: 3151, 985 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-liquid rotate: false - xy: 1989, 591 + xy: 3217, 1051 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-top rotate: false - xy: 1989, 525 + xy: 3283, 1051 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator rotate: false - xy: 2055, 591 + xy: 3217, 985 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator-middle rotate: false - xy: 2055, 525 + xy: 3349, 1051 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator-top rotate: false - xy: 2121, 591 + xy: 3283, 985 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 disassembler rotate: false - xy: 3143, 885 + xy: 2399, 751 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 disassembler-liquid rotate: false - xy: 3209, 1081 + xy: 2497, 849 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 disassembler-spinner rotate: false - xy: 3241, 983 + xy: 2497, 751 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 graphite-press rotate: false - xy: 3297, 1328 + xy: 3183, 787 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 incinerator rotate: false - xy: 1018, 109 + xy: 3250, 193 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-source rotate: false - xy: 1120, 65 + xy: 2472, 11 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-void rotate: false - xy: 1188, 132 + xy: 2574, 45 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 kiln rotate: false - xy: 2281, 655 + xy: 3315, 919 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 kiln-top rotate: false - xy: 2253, 589 + xy: 3249, 853 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 silicon-smelter-top rotate: false - xy: 2253, 589 + xy: 3249, 853 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 liquid-source rotate: false - xy: 1256, 97 + xy: 2676, 83 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-void rotate: false - xy: 1256, 63 + xy: 2676, 49 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 melter rotate: false - xy: 2881, 1303 + xy: 3386, 163 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 multi-press rotate: false - xy: 3927, 983 + xy: 3019, 653 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 phase-weaver rotate: false - xy: 2451, 555 + xy: 3513, 787 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-bottom rotate: false - xy: 2517, 555 + xy: 3545, 721 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-weave rotate: false - xy: 2583, 555 + xy: 3255, 655 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 plastanium-compressor rotate: false - xy: 2649, 555 + xy: 3321, 655 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 plastanium-compressor-top rotate: false - xy: 2319, 489 + xy: 3387, 655 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pulverizer rotate: false - xy: 3881, 615 + xy: 3681, 885 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulverizer-rotator rotate: false - xy: 3915, 615 + xy: 3715, 885 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pyratite-mixer rotate: false - xy: 1923, 459 + xy: 3519, 589 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 separator rotate: false - xy: 1303, 445 + xy: 2555, 587 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 separator-liquid rotate: false - xy: 1369, 445 + xy: 2621, 587 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 separator-spinner rotate: false - xy: 1435, 447 + xy: 2687, 587 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 silicon-crucible rotate: false - xy: 1825, 495 + xy: 1550, 11 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 silicon-crucible-top rotate: false - xy: 1951, 821 + xy: 1648, 11 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 silicon-smelter rotate: false - xy: 1283, 379 + xy: 2753, 587 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press rotate: false - xy: 1349, 379 + xy: 2819, 587 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-frame0 rotate: false - xy: 1501, 445 + xy: 2885, 587 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-frame1 rotate: false - xy: 1567, 445 + xy: 2951, 587 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-frame2 rotate: false - xy: 1633, 457 + xy: 3017, 587 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-liquid rotate: false - xy: 1415, 379 + xy: 2230, 517 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-top rotate: false - xy: 1481, 379 + xy: 2296, 521 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rock1 rotate: false - xy: 3143, 653 + xy: 3530, 365 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 rock2 rotate: false - xy: 3193, 653 + xy: 3530, 315 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 sand-boulder1 rotate: false - xy: 2349, 1201 + xy: 3749, 939 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sand-boulder2 rotate: false - xy: 1295, 199 + xy: 3783, 939 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shale-boulder1 rotate: false - xy: 1329, 203 + xy: 3749, 837 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shale-boulder2 rotate: false - xy: 1363, 203 + xy: 3783, 871 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 snowrock1 rotate: false - xy: 3343, 661 + xy: 3630, 307 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 snowrock2 rotate: false - xy: 3393, 661 + xy: 3530, 265 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spore-cluster1 rotate: false - xy: 1433, 271 + xy: 3064, 231 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 spore-cluster2 rotate: false - xy: 1475, 271 + xy: 3106, 229 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 spore-cluster3 rotate: false - xy: 1517, 271 + xy: 3148, 257 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 white-tree rotate: false - xy: 1, 1083 + xy: 1, 761 size: 320, 320 orig: 320, 320 offset: 0, 0 index: -1 white-tree-dead rotate: false - xy: 323, 1405 + xy: 323, 1083 size: 320, 320 orig: 320, 320 offset: 0, 0 index: -1 container rotate: false - xy: 2409, 753 + xy: 2125, 144 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 core-foundation rotate: false - xy: 583, 729 + xy: 1809, 1143 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 core-foundation-team rotate: false - xy: 583, 599 + xy: 2069, 1403 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 core-nucleus rotate: false - xy: 2613, 1387 + xy: 1161, 887 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 core-nucleus-team rotate: false - xy: 2775, 1387 + xy: 1323, 887 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 core-shard rotate: false - xy: 2555, 885 + xy: 2007, 845 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 core-shard-team rotate: false - xy: 2621, 1081 + xy: 2007, 747 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 unloader rotate: false - xy: 3333, 559 + xy: 4055, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 unloader-center rotate: false - xy: 3367, 559 + xy: 3611, 778 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 vault rotate: false - xy: 2245, 787 + xy: 3403, 1191 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 arc-heat rotate: false - xy: 1337, 237 + xy: 269, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-1 rotate: false - xy: 2815, 517 + xy: 4061, 1913 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-2 rotate: false - xy: 3099, 1417 + xy: 2124, 342 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-3 rotate: false - xy: 854, 155 + xy: 2847, 1045 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-4 rotate: false - xy: 453, 339 + xy: 1549, 1273 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 hail-heat rotate: false - xy: 1139, 319 + xy: 2380, 263 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 lancer-heat rotate: false - xy: 2347, 687 + xy: 3315, 853 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 meltdown-heat rotate: false - xy: 843, 367 + xy: 2719, 1143 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 ripple-heat rotate: false - xy: 1853, 789 + xy: 1256, 15 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 salvo-heat rotate: false - xy: 2319, 423 + xy: 3387, 523 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 salvo-panel-left rotate: false - xy: 2385, 423 + xy: 3453, 523 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 salvo-panel-right rotate: false - xy: 2451, 423 + xy: 3519, 523 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scorch-heat rotate: false - xy: 1290, 131 + xy: 3817, 939 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 wave-liquid rotate: false - xy: 1679, 363 + xy: 3418, 457 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 additive-reconstructor rotate: false - xy: 2131, 1081 + xy: 2161, 1045 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 additive-reconstructor-top rotate: false - xy: 1205, 458 + xy: 2259, 1045 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 air-factory rotate: false - xy: 1595, 817 + xy: 2357, 1045 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 command-center rotate: false - xy: 2343, 753 + xy: 2074, 62 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 exponential-reconstructor rotate: false - xy: 1517, 1017 + xy: 935, 985 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 exponential-reconstructor-top rotate: false - xy: 1805, 1275 + xy: 1193, 1049 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 factory-in-3 rotate: false - xy: 3241, 885 + xy: 2693, 849 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 factory-in-5 rotate: false - xy: 3534, 1435 + xy: 1148, 239 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 factory-in-7 rotate: false - xy: 2063, 1533 + xy: 903, 759 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 factory-in-9 rotate: false - xy: 1225, 1469 + xy: 2127, 1759 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 factory-out-3 rotate: false - xy: 1461, 707 + xy: 2791, 849 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 factory-out-5 rotate: false - xy: 3696, 1435 + xy: 1310, 239 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 factory-out-7 rotate: false - xy: 2289, 1565 + xy: 871, 533 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 factory-out-9 rotate: false - xy: 1515, 1759 + xy: 2417, 1759 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 factory-top-3 rotate: false - xy: 1559, 719 + xy: 2693, 751 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ground-factory rotate: false - xy: 3339, 885 + xy: 2333, 653 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 multiplicative-reconstructor rotate: false - xy: 3858, 1435 + xy: 1472, 239 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 multiplicative-reconstructor-top rotate: false - xy: 3363, 1273 + xy: 1634, 239 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 naval-factory rotate: false - xy: 3927, 885 + xy: 3117, 669 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 rally-point rotate: false - xy: 1989, 459 + xy: 3585, 655 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 repair-point-base rotate: false - xy: 3983, 601 + xy: 3715, 851 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 resupply-point rotate: false - xy: 2055, 459 + xy: 3585, 589 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 tetrative-reconstructor rotate: false - xy: 1515, 1469 + xy: 2707, 1759 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 tetrative-reconstructor-top rotate: false - xy: 1805, 1759 + xy: 2997, 1759 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 copper-wall rotate: false - xy: 3677, 649 + xy: 3522, 231 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper-wall-large rotate: false - xy: 2475, 753 + xy: 2191, 152 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door rotate: false - xy: 1023, 211 + xy: 4023, 971 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 door-large rotate: false - xy: 2187, 589 + xy: 3415, 985 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door-large-open rotate: false - xy: 2187, 523 + xy: 3183, 919 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door-open rotate: false - xy: 1057, 211 + xy: 4057, 963 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall rotate: false - xy: 3231, 619 + xy: 3613, 982 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall-large rotate: false - xy: 2385, 555 + xy: 3513, 853 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 plastanium-wall rotate: false - xy: 3469, 627 + xy: 3647, 948 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-wall-large rotate: false - xy: 2385, 489 + xy: 3453, 655 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-gigantic rotate: false - xy: 973, 497 + xy: 2979, 1403 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 scrap-wall-huge2 rotate: false - xy: 1853, 691 + xy: 1354, 15 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 scrap-wall-huge3 rotate: false - xy: 1825, 593 + xy: 1452, 15 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 scrap-wall-large1 rotate: false - xy: 2583, 423 + xy: 2225, 583 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-large2 rotate: false - xy: 2649, 423 + xy: 2291, 587 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-large3 rotate: false - xy: 2715, 555 + xy: 2357, 587 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-large4 rotate: false - xy: 2715, 489 + xy: 2423, 587 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall2 rotate: false - xy: 1290, 97 + xy: 3749, 871 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall3 rotate: false - xy: 1290, 63 + xy: 3783, 905 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall4 rotate: false - xy: 1290, 29 + xy: 3851, 939 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall5 rotate: false - xy: 1290, 29 + xy: 3851, 939 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-wall rotate: false - xy: 3435, 593 + xy: 3953, 903 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-wall-large rotate: false - xy: 1613, 379 + xy: 2428, 521 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thorium-wall rotate: false - xy: 3469, 593 + xy: 3987, 937 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium-wall-large rotate: false - xy: 1415, 313 + xy: 2626, 521 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thruster rotate: false - xy: 1233, 757 + xy: 2849, 1143 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 titanium-wall rotate: false - xy: 1567, 203 + xy: 3953, 801 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-wall-large rotate: false - xy: 1481, 313 + xy: 2692, 521 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 bullet rotate: false - xy: 2739, 765 + xy: 2470, 467 size: 52, 52 orig: 52, 52 offset: 0, 0 index: -1 bullet-back rotate: false - xy: 2625, 1333 + xy: 2524, 467 size: 52, 52 orig: 52, 52 offset: 0, 0 index: -1 casing rotate: false - xy: 1733, 915 + xy: 3141, 1099 size: 8, 16 orig: 8, 16 offset: 0, 0 index: -1 circle-end rotate: false - xy: 1233, 556 + xy: 3565, 1202 size: 100, 199 orig: 100, 199 offset: 0, 0 index: -1 circle-mid rotate: false - xy: 4085, 586 + xy: 4089, 762 size: 1, 199 orig: 1, 199 offset: 0, 0 index: -1 circle-shadow rotate: false - xy: 3169, 1588 + xy: 727, 88 size: 201, 201 orig: 201, 201 offset: 0, 0 index: -1 error rotate: false - xy: 2893, 703 + xy: 2630, 371 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 laser rotate: false - xy: 607, 1065 + xy: 3661, 1152 size: 4, 48 orig: 4, 48 offset: 0, 0 index: -1 laser-end rotate: false - xy: 3433, 811 + xy: 3215, 1117 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 minelaser rotate: false - xy: 4091, 887 + xy: 3965, 1255 size: 4, 48 orig: 4, 48 offset: 0, 0 index: -1 minelaser-end rotate: false - xy: 3507, 811 + xy: 3289, 1117 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 missile rotate: false - xy: 1559, 275 + xy: 663, 1 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 missile-back rotate: false - xy: 1597, 275 + xy: 3215, 683 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 +parallax-laser + rotate: false + xy: 4091, 981 + size: 4, 48 + orig: 4, 48 + offset: 0, 0 + index: -1 +parallax-laser-end + rotate: false + xy: 3363, 1117 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 particle rotate: false - xy: 1391, 271 + xy: 3022, 237 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 scale_marker rotate: false - xy: 1081, 377 + xy: 4003, 1435 size: 4, 4 orig: 4, 4 offset: 0, 0 index: -1 shell rotate: false - xy: 1635, 275 + xy: 3190, 261 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 shell-back rotate: false - xy: 1265, 233 + xy: 3228, 261 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 transfer rotate: false - xy: 607, 1015 + xy: 639, 1033 size: 4, 48 orig: 4, 48 offset: 0, 0 index: -1 transfer-arrow rotate: false - xy: 1601, 207 + xy: 3987, 801 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 white rotate: false - xy: 952, 248 + xy: 2225, 578 size: 3, 3 orig: 3, 3 offset: 0, 0 index: -1 +alpha-wreck0 + rotate: false + xy: 2628, 471 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +alpha-wreck1 + rotate: false + xy: 2678, 471 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +alpha-wreck2 + rotate: false + xy: 2728, 471 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +antumbra-wreck0 + rotate: false + xy: 509, 389 + size: 216, 240 + orig: 216, 240 + offset: 0, 0 + index: -1 +antumbra-wreck1 + rotate: false + xy: 509, 147 + size: 216, 240 + orig: 216, 240 + offset: 0, 0 + index: -1 +antumbra-wreck2 + rotate: false + xy: 291, 35 + size: 216, 240 + orig: 216, 240 + offset: 0, 0 + index: -1 arc rotate: false - xy: 1303, 237 + xy: 3083, 619 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 +arkyid-wreck0 + rotate: false + xy: 1731, 109 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +arkyid-wreck1 + rotate: false + xy: 930, 6 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +arkyid-wreck2 + rotate: false + xy: 3841, 1305 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +atrax-wreck0 + rotate: false + xy: 1796, 374 + size: 88, 64 + orig: 88, 64 + offset: 0, 0 + index: -1 +atrax-wreck1 + rotate: false + xy: 1976, 506 + size: 88, 64 + orig: 88, 64 + offset: 0, 0 + index: -1 +atrax-wreck2 + rotate: false + xy: 1886, 440 + size: 88, 64 + orig: 88, 64 + offset: 0, 0 + index: -1 +beta-wreck0 + rotate: false + xy: 2878, 471 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +beta-wreck1 + rotate: false + xy: 2380, 305 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +beta-wreck2 + rotate: false + xy: 2928, 471 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 block-additive-reconstructor-full rotate: false - xy: 1363, 707 + xy: 1485, 943 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-air-factory-full rotate: false - xy: 1335, 609 + xy: 1583, 943 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-arc-full rotate: false - xy: 2849, 551 + xy: 3368, 265 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-blast-drill-full rotate: false - xy: 3954, 1725 + xy: 1679, 1403 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 block-char-full rotate: false - xy: 2781, 449 + xy: 3402, 265 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-cliffs-full rotate: false - xy: 2815, 483 + xy: 4061, 1845 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-conduit-full rotate: false - xy: 2849, 517 + xy: 3436, 265 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-conveyor-full rotate: false - xy: 2883, 551 + xy: 4061, 1811 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-0 rotate: false - xy: 2883, 551 + xy: 4061, 1811 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-core-foundation-full rotate: false - xy: 453, 209 + xy: 1679, 1273 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 block-core-nucleus-full rotate: false - xy: 2289, 1403 + xy: 1, 19 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 block-core-shard-full rotate: false - xy: 1335, 511 + xy: 1681, 943 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-craters-full rotate: false - xy: 2815, 449 + xy: 4063, 1777 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-cryofluidmixer-full rotate: false - xy: 3721, 819 + xy: 2124, 276 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-cultivator-full rotate: false - xy: 3787, 819 + xy: 2190, 350 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-cyclone-full rotate: false - xy: 3987, 1337 + xy: 1779, 943 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-dark-metal-full rotate: false - xy: 2849, 483 + xy: 4063, 1743 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-darksand-full rotate: false - xy: 2883, 517 + xy: 4063, 1709 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-dunerocks-full rotate: false - xy: 2849, 449 + xy: 4063, 1675 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-duo-full rotate: false - xy: 2883, 483 + xy: 4063, 1641 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-exponential-reconstructor-full rotate: false - xy: 645, 1243 + xy: 1193, 1275 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 block-fuse-full rotate: false - xy: 2261, 983 + xy: 1615, 845 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-grass-full rotate: false - xy: 2883, 449 + xy: 4063, 1607 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ground-factory-full rotate: false - xy: 2261, 885 + xy: 1615, 747 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-hail-full rotate: false - xy: 2781, 415 + xy: 3470, 265 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-holostone-full rotate: false - xy: 2815, 415 + xy: 3148, 223 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-hotrock-full rotate: false - xy: 2849, 415 + xy: 895, 20 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ice-full rotate: false - xy: 2883, 415 + xy: 2280, 429 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ice-snow-full rotate: false - xy: 2371, 1303 + xy: 3545, 1118 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-icerocks-full rotate: false - xy: 1541, 237 + xy: 3579, 1118 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ignarock-full rotate: false - xy: 1575, 241 + xy: 3613, 1118 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-impact-reactor-full rotate: false - xy: 398, 79 + xy: 1549, 1143 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 block-lancer-full rotate: false - xy: 3853, 819 + xy: 2190, 284 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-laser-drill-full rotate: false - xy: 658, 13 + xy: 1713, 845 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-liquid-router-full rotate: false - xy: 1609, 241 + xy: 3547, 1084 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-liquid-tank-full rotate: false - xy: 756, 41 + xy: 1811, 845 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-magmarock-full rotate: false - xy: 858, 23 + xy: 3547, 1050 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-mass-conveyor-full rotate: false - xy: 2327, 1081 + xy: 1811, 747 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mass-conveyor-icon rotate: false - xy: 2327, 1081 + xy: 1811, 747 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-mass-driver-full rotate: false - xy: 2359, 983 + xy: 1745, 649 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-mechanical-drill-full rotate: false - xy: 3919, 819 + xy: 2124, 210 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-meltdown-full rotate: false - xy: 528, 79 + xy: 1809, 1403 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 block-metal-floor-damaged-full rotate: false - xy: 892, 23 + xy: 3581, 1084 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-moss-full rotate: false - xy: 2371, 1269 + xy: 3581, 1050 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-multiplicative-reconstructor-full rotate: false - xy: 2451, 1387 + xy: 3841, 1435 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 block-naval-factory-full rotate: false - xy: 2359, 885 + xy: 1909, 845 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-oil-extractor-full rotate: false - xy: 2425, 1081 + xy: 1909, 747 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-ore-coal-full rotate: false - xy: 2405, 1285 + xy: 3581, 1016 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-copper-full rotate: false - xy: 2439, 1295 + xy: 3615, 1084 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-lead-full rotate: false - xy: 2473, 1295 + xy: 3615, 1050 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-scrap-full rotate: false - xy: 2507, 1295 + xy: 3615, 1016 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-thorium-full rotate: false - xy: 2541, 1295 + xy: 3647, 1118 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-titanium-full rotate: false - xy: 2575, 1295 + xy: 3649, 1084 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 +block-parallax-full + rotate: false + xy: 2190, 218 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 block-payload-router-full rotate: false - xy: 2457, 983 + xy: 1843, 649 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 payload-router-icon rotate: false - xy: 2457, 983 + xy: 1843, 649 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-pebbles-full rotate: false - xy: 2365, 1235 + xy: 3649, 1050 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-phase-weaver-full rotate: false - xy: 2245, 721 + xy: 2256, 358 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-plated-conduit-full rotate: false - xy: 2405, 1251 + xy: 3649, 1016 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-pneumatic-drill-full rotate: false - xy: 398, 13 + xy: 2256, 292 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-pulse-conduit-full rotate: false - xy: 2439, 1261 + xy: 3681, 1123 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-pulverizer-full rotate: false - xy: 2473, 1261 + xy: 3715, 1123 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-repair-point-full rotate: false - xy: 2507, 1261 + xy: 3683, 1089 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ripple-full rotate: false - xy: 2457, 885 + xy: 1941, 649 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-rock-full rotate: false - xy: 2779, 1337 + xy: 2978, 471 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-rocks-full rotate: false - xy: 2541, 1261 + xy: 3683, 1055 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-saltrocks-full rotate: false - xy: 2575, 1261 + xy: 3683, 1021 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-salvo-full rotate: false - xy: 464, 13 + xy: 2256, 226 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-sand-boulder-full rotate: false - xy: 2609, 1295 + xy: 3717, 1089 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-sand-full rotate: false - xy: 2609, 1261 + xy: 3717, 1055 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-sandrocks-full rotate: false - xy: 2643, 1299 + xy: 3717, 1021 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-scatter-full rotate: false - xy: 530, 13 + xy: 1864, 210 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-scorch-full rotate: false - xy: 2643, 1265 + xy: 3751, 1075 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-scrap-wall-full rotate: false - xy: 3643, 777 + xy: 3751, 1041 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall1 rotate: false - xy: 3643, 777 + xy: 3751, 1041 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-scrap-wall-huge-full rotate: false - xy: 2523, 1081 + xy: 1975, 943 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 scrap-wall-huge1 rotate: false - xy: 2523, 1081 + xy: 1975, 943 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-scrap-wall-large-full rotate: false - xy: 4025, 871 + xy: 1861, 144 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-segment-full rotate: false - xy: 2193, 1467 + xy: 1930, 194 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-shale-boulder-full rotate: false - xy: 3643, 709 + xy: 3785, 1041 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-shale-full rotate: false - xy: 3643, 675 + xy: 3819, 1075 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-shalerocks-full rotate: false - xy: 3677, 785 + xy: 3819, 1041 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-shrubs-full rotate: false - xy: 3711, 785 + xy: 3853, 1075 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-snow-full rotate: false - xy: 3677, 751 + xy: 3853, 1041 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-snowrock-full rotate: false - xy: 2829, 1337 + xy: 3028, 471 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-snowrocks-full rotate: false - xy: 3745, 785 + xy: 3887, 1075 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-spectre-full rotate: false - xy: 3525, 1179 + xy: 1809, 1273 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 block-spore-cluster-full rotate: false - xy: 4020, 1437 + xy: 829, 547 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-spore-moss-full rotate: false - xy: 3677, 717 + xy: 3887, 1041 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-spore-press-full rotate: false - xy: 2193, 1401 + xy: 1996, 194 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-sporerocks-full rotate: false - xy: 3711, 751 + xy: 3921, 1075 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-stone-full rotate: false - xy: 3779, 785 + xy: 3921, 1041 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-swarmer-full rotate: false - xy: 2193, 1335 + xy: 1927, 128 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-tendrils-full rotate: false - xy: 3677, 683 + xy: 3751, 1007 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-tetrative-reconstructor-full rotate: false - xy: 645, 1759 + xy: 645, 1437 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 block-titanium-conveyor-full rotate: false - xy: 3711, 717 + xy: 3785, 1007 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-0 rotate: false - xy: 3711, 717 + xy: 3785, 1007 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-turbine-generator-full rotate: false - xy: 2259, 1337 + xy: 1993, 128 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-water-extractor-full rotate: false - xy: 2325, 1337 + xy: 1942, 62 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-wave-full rotate: false - xy: 4020, 1545 + xy: 2008, 62 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 core-foundation-team-crux rotate: false - xy: 583, 469 + xy: 2069, 1273 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 core-foundation-team-sharded rotate: false - xy: 583, 339 + xy: 1939, 1143 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 core-nucleus-team-crux rotate: false - xy: 2937, 1387 + xy: 1129, 725 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 core-nucleus-team-sharded rotate: false - xy: 291, 921 + xy: 1291, 725 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 core-shard-team-crux rotate: false - xy: 2653, 983 + xy: 2171, 947 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 core-shard-team-sharded rotate: false - xy: 2653, 885 + xy: 2269, 947 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-1-0 rotate: false - xy: 3711, 649 + xy: 3672, 189 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-1 rotate: false - xy: 3745, 649 + xy: 3683, 987 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-2 rotate: false - xy: 3779, 649 + xy: 3717, 987 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-3 rotate: false - xy: 3813, 649 + xy: 3751, 973 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-4 rotate: false - xy: 3847, 649 + xy: 3785, 973 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-5 rotate: false - xy: 3881, 649 + xy: 3819, 973 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-6 rotate: false - xy: 3915, 649 + xy: 3853, 973 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-7 rotate: false - xy: 3949, 649 + xy: 3887, 973 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-2-0 rotate: false - xy: 2541, 753 + xy: 2257, 160 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-1 rotate: false - xy: 2607, 753 + xy: 2140, 78 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-2 rotate: false - xy: 2673, 753 + xy: 2206, 86 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-3 rotate: false - xy: 1951, 657 + xy: 2272, 94 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-4 rotate: false - xy: 2017, 657 + xy: 2140, 12 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-5 rotate: false - xy: 2083, 657 + xy: 2206, 20 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-6 rotate: false - xy: 2149, 657 + xy: 2272, 28 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-7 rotate: false - xy: 1923, 591 + xy: 3151, 1051 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-3-0 rotate: false - xy: 2719, 1081 + xy: 2367, 947 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-1 rotate: false - xy: 2751, 983 + xy: 2465, 947 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-2 rotate: false - xy: 2751, 885 + xy: 2563, 947 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-3 rotate: false - xy: 2817, 1081 + xy: 2661, 947 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-4 rotate: false - xy: 2849, 983 + xy: 2759, 947 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-5 rotate: false - xy: 2849, 885 + xy: 2857, 947 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-6 rotate: false - xy: 2915, 1081 + xy: 2105, 845 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-7 rotate: false - xy: 2947, 983 + xy: 2105, 747 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-4-0 rotate: false - xy: 583, 209 + xy: 2199, 1403 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-1 rotate: false - xy: 713, 887 + xy: 2199, 1273 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-2 rotate: false - xy: 713, 757 + xy: 2069, 1143 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-3 rotate: false - xy: 843, 887 + xy: 2329, 1403 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-4 rotate: false - xy: 713, 627 + xy: 2329, 1273 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-5 rotate: false - xy: 843, 757 + xy: 2199, 1143 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-6 rotate: false - xy: 973, 887 + xy: 2459, 1403 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-7 rotate: false - xy: 713, 497 + xy: 2459, 1273 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-5-0 rotate: false - xy: 291, 597 + xy: 1259, 563 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 cracks-5-1 rotate: false - xy: 291, 435 + xy: 1148, 401 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 cracks-5-2 rotate: false - xy: 291, 273 + xy: 1310, 401 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 cracks-5-3 rotate: false - xy: 1743, 887 + xy: 1421, 563 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 cracks-5-4 rotate: false - xy: 1937, 919 + xy: 1453, 725 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 cracks-5-5 rotate: false - xy: 2031, 1339 + xy: 1472, 401 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 cracks-5-6 rotate: false - xy: 2099, 919 + xy: 1583, 563 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 cracks-5-7 rotate: false - xy: 3372, 1435 + xy: 1634, 401 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 cracks-6-0 rotate: false - xy: 3901, 1855 + xy: 945, 136 size: 192, 192 orig: 192, 192 offset: 0, 0 index: -1 cracks-6-1 rotate: false - xy: 3372, 1597 + xy: 3287, 1597 size: 192, 192 orig: 192, 192 offset: 0, 0 index: -1 cracks-6-2 rotate: false - xy: 3566, 1597 + xy: 3481, 1597 size: 192, 192 orig: 192, 192 offset: 0, 0 index: -1 cracks-6-3 rotate: false - xy: 3760, 1597 + xy: 3675, 1597 size: 192, 192 orig: 192, 192 offset: 0, 0 index: -1 cracks-6-4 rotate: false - xy: 204, 19 + xy: 3869, 1597 size: 192, 192 orig: 192, 192 offset: 0, 0 index: -1 cracks-6-5 rotate: false - xy: 3169, 1394 + xy: 3259, 1403 size: 192, 192 orig: 192, 192 offset: 0, 0 index: -1 cracks-6-6 rotate: false - xy: 1743, 1049 + xy: 3453, 1403 size: 192, 192 orig: 192, 192 offset: 0, 0 index: -1 cracks-6-7 rotate: false - xy: 1937, 1081 + xy: 3647, 1403 size: 192, 192 orig: 192, 192 offset: 0, 0 index: -1 cracks-7-0 rotate: false - xy: 871, 1243 + xy: 1451, 1533 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 cracks-7-1 rotate: false - xy: 1097, 1243 + xy: 1677, 1533 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 cracks-7-2 rotate: false - xy: 1323, 1243 + xy: 1903, 1533 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 cracks-7-3 rotate: false - xy: 1549, 1243 + xy: 2129, 1533 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 cracks-7-4 rotate: false - xy: 613, 1017 + xy: 2355, 1533 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 cracks-7-5 rotate: false - xy: 839, 1017 + xy: 2581, 1533 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 cracks-7-6 rotate: false - xy: 1065, 1017 + xy: 2807, 1533 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 cracks-7-7 rotate: false - xy: 1291, 1017 + xy: 3033, 1533 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 cracks-8-0 rotate: false - xy: 1805, 1501 + xy: 3287, 1791 size: 256, 256 orig: 256, 256 offset: 0, 0 index: -1 cracks-8-1 rotate: false - xy: 2095, 1791 + xy: 3545, 1791 size: 256, 256 orig: 256, 256 offset: 0, 0 index: -1 cracks-8-2 rotate: false - xy: 2353, 1791 + xy: 3803, 1791 size: 256, 256 orig: 256, 256 offset: 0, 0 index: -1 cracks-8-3 rotate: false - xy: 2611, 1791 + xy: 645, 889 size: 256, 256 orig: 256, 256 offset: 0, 0 index: -1 cracks-8-4 rotate: false - xy: 2869, 1791 + xy: 613, 631 size: 256, 256 orig: 256, 256 offset: 0, 0 index: -1 cracks-8-5 rotate: false - xy: 3127, 1791 + xy: 935, 1469 size: 256, 256 orig: 256, 256 offset: 0, 0 index: -1 cracks-8-6 rotate: false - xy: 3385, 1791 + xy: 935, 1211 size: 256, 256 orig: 256, 256 offset: 0, 0 index: -1 cracks-8-7 rotate: false - xy: 3643, 1791 + xy: 1193, 1501 size: 256, 256 orig: 256, 256 offset: 0, 0 index: -1 cracks-9-0 rotate: false - xy: 1, 793 + xy: 967, 1759 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 cracks-9-1 rotate: false - xy: 323, 1115 + xy: 1, 471 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 cracks-9-2 rotate: false - xy: 645, 1469 + xy: 323, 793 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 cracks-9-3 rotate: false - xy: 935, 1759 + xy: 645, 1147 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 cracks-9-4 rotate: false - xy: 1, 503 + xy: 1257, 1759 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 cracks-9-5 rotate: false - xy: 935, 1469 + xy: 1, 181 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 cracks-9-6 rotate: false - xy: 1225, 1759 + xy: 1547, 1759 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 cracks-9-7 rotate: false - xy: 1, 213 + xy: 1837, 1759 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 +crawler-wreck0 + rotate: false + xy: 2480, 367 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +crawler-wreck1 + rotate: false + xy: 2480, 317 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +crawler-wreck2 + rotate: false + xy: 2530, 417 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 cyclone rotate: false - xy: 2947, 885 + xy: 2039, 649 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 +dagger-wreck0 + rotate: false + xy: 2630, 421 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dagger-wreck1 + rotate: false + xy: 2580, 371 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dagger-wreck2 + rotate: false + xy: 2680, 421 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 duo rotate: false - xy: 1091, 211 + xy: 2601, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -fuse - rotate: false - xy: 3339, 983 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -hail - rotate: false - xy: 1018, 177 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-blast-compound-large - rotate: false - xy: 2743, 623 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-blast-compound-medium - rotate: false - xy: 1018, 75 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-blast-compound-small - rotate: false - xy: 1897, 469 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-blast-compound-tiny - rotate: false - xy: 1697, 915 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-blast-compound-xlarge - rotate: false - xy: 3193, 753 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -item-coal-large - rotate: false - xy: 1697, 975 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-coal-medium - rotate: false - xy: 1086, 143 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-coal-small - rotate: false - xy: 926, 31 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-coal-tiny - rotate: false - xy: 1265, 342 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-coal-xlarge - rotate: false - xy: 2943, 695 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -item-copper-large - rotate: false - xy: 1693, 823 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-copper-medium - rotate: false - xy: 1052, 75 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-copper-small - rotate: false - xy: 1897, 443 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-copper-tiny - rotate: false - xy: 1715, 915 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-copper-xlarge - rotate: false - xy: 2993, 703 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -item-graphite-large - rotate: false - xy: 2231, 1193 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-graphite-medium - rotate: false - xy: 1052, 41 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-graphite-small - rotate: false - xy: 613, 1379 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-graphite-tiny - rotate: false - xy: 1265, 324 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-graphite-xlarge - rotate: false - xy: 3243, 753 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -item-lead-large - rotate: false - xy: 1139, 277 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-lead-medium - rotate: false - xy: 1086, 41 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-lead-small - rotate: false - xy: 2095, 1765 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-lead-tiny - rotate: false - xy: 204, 1 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-lead-xlarge - rotate: false - xy: 3043, 695 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -item-metaglass-large - rotate: false - xy: 1697, 933 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-metaglass-medium - rotate: false - xy: 2315, 1211 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-metaglass-small - rotate: false - xy: 1775, 1443 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-metaglass-tiny - rotate: false - xy: 222, 1 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-metaglass-xlarge - rotate: false - xy: 3093, 703 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -item-phase-fabric-large - rotate: false - xy: 4051, 829 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-phase-fabric-medium - rotate: false - xy: 2439, 1227 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-phase-fabric-small - rotate: false - xy: 323, 1089 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-phase-fabric-tiny - rotate: false - xy: 240, 1 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-phase-fabric-xlarge - rotate: false - xy: 3143, 703 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -item-plastanium-large - rotate: false - xy: 2281, 1245 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-plastanium-medium - rotate: false - xy: 2507, 1227 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-plastanium-small - rotate: false - xy: 1335, 731 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-plastanium-tiny - rotate: false - xy: 258, 1 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-plastanium-xlarge - rotate: false - xy: 3193, 703 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -item-pyratite-large - rotate: false - xy: 2323, 1245 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-pyratite-medium - rotate: false - xy: 2575, 1227 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-pyratite-small - rotate: false - xy: 1465, 861 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-pyratite-tiny - rotate: false - xy: 276, 1 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-pyratite-xlarge - rotate: false - xy: 3243, 703 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -item-sand-large - rotate: false - xy: 1181, 318 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-sand-medium - rotate: false - xy: 2643, 1231 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-sand-small - rotate: false - xy: 1905, 1023 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-sand-tiny - rotate: false - xy: 294, 1 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-sand-xlarge - rotate: false - xy: 3293, 761 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -item-scrap-large - rotate: false - xy: 1223, 318 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-scrap-medium - rotate: false - xy: 1120, 167 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-scrap-small - rotate: false - xy: 2063, 1507 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-scrap-tiny - rotate: false - xy: 312, 1 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-scrap-xlarge - rotate: false - xy: 3293, 711 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -item-silicon-large - rotate: false - xy: 1181, 276 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-silicon-medium - rotate: false - xy: 1120, 99 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-silicon-small - rotate: false - xy: 2259, 1507 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-silicon-tiny - rotate: false - xy: 330, 1 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-silicon-xlarge - rotate: false - xy: 3343, 761 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -item-spore-pod-large - rotate: false - xy: 1223, 276 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-spore-pod-medium - rotate: false - xy: 1159, 200 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-spore-pod-small - rotate: false - xy: 1923, 665 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-spore-pod-tiny - rotate: false - xy: 348, 1 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-spore-pod-xlarge - rotate: false - xy: 3343, 711 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -item-surge-alloy-large - rotate: false - xy: 1139, 235 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-surge-alloy-medium - rotate: false - xy: 1227, 200 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-surge-alloy-small - rotate: false - xy: 2311, 761 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-surge-alloy-tiny - rotate: false - xy: 366, 1 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-surge-alloy-xlarge - rotate: false - xy: 3393, 761 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -item-thorium-large - rotate: false - xy: 1181, 234 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-thorium-medium - rotate: false - xy: 1154, 132 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-thorium-small - rotate: false - xy: 2319, 629 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-thorium-tiny - rotate: false - xy: 1209, 609 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-thorium-xlarge - rotate: false - xy: 3393, 711 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -item-titanium-large - rotate: false - xy: 1223, 234 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-titanium-medium - rotate: false - xy: 1154, 98 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-titanium-small - rotate: false - xy: 1303, 530 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-titanium-tiny - rotate: false - xy: 2921, 635 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-titanium-xlarge - rotate: false - xy: 3443, 761 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -lancer - rotate: false - xy: 2253, 523 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -liquid-cryofluid-large - rotate: false - xy: 4051, 787 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -liquid-cryofluid-medium - rotate: false - xy: 1188, 98 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-cryofluid-small - rotate: false - xy: 1699, 497 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -liquid-cryofluid-tiny - rotate: false - xy: 3079, 1369 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -liquid-cryofluid-xlarge - rotate: false - xy: 3493, 711 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -liquid-oil-large - rotate: false - xy: 1265, 271 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -liquid-oil-medium - rotate: false - xy: 1222, 98 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-oil-small - rotate: false - xy: 4025, 1311 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -liquid-oil-tiny - rotate: false - xy: 1737, 311 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -liquid-oil-xlarge - rotate: false - xy: 3543, 761 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -liquid-slag-large - rotate: false - xy: 1307, 271 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -liquid-slag-medium - rotate: false - xy: 1256, 131 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-slag-small - rotate: false - xy: 1643, 249 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -liquid-slag-tiny - rotate: false - xy: 613, 1361 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -liquid-slag-xlarge - rotate: false - xy: 3543, 711 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -liquid-water-large - rotate: false - xy: 1349, 271 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -liquid-water-medium - rotate: false - xy: 2779, 1303 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-water-small - rotate: false - xy: 3401, 567 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -liquid-water-tiny - rotate: false - xy: 2121, 1773 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -liquid-water-xlarge - rotate: false - xy: 3593, 761 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -mass-driver - rotate: false - xy: 3829, 983 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -meltdown - rotate: false - xy: 713, 237 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -repair-point - rotate: false - xy: 3949, 615 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ripple - rotate: false - xy: 1727, 495 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -salvo - rotate: false - xy: 2253, 457 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -scatter - rotate: false - xy: 2517, 423 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -scorch - rotate: false - xy: 1290, 165 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -segment - rotate: false - xy: 2715, 423 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -spectre - rotate: false - xy: 1103, 627 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -splash-0 - rotate: false - xy: 1499, 203 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -splash-1 - rotate: false - xy: 1533, 203 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -splash-10 - rotate: false - xy: 3367, 593 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -splash-11 - rotate: false - xy: 3401, 593 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -splash-2 - rotate: false - xy: 3095, 585 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -splash-3 - rotate: false - xy: 3129, 585 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -splash-4 - rotate: false - xy: 3163, 585 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -splash-5 - rotate: false - xy: 3197, 585 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -splash-6 - rotate: false - xy: 3231, 585 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -splash-7 - rotate: false - xy: 3265, 585 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -splash-8 - rotate: false - xy: 3299, 593 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -splash-9 - rotate: false - xy: 3333, 593 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -swarmer - rotate: false - xy: 1283, 313 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -unit-alpha-full - rotate: false - xy: 2131, 1231 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -unit-cix-full - rotate: false - xy: 1363, 887 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -unit-crawler-full - rotate: false - xy: 2131, 1181 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -unit-dagger-full - rotate: false - xy: 1693, 865 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -unit-draug-full - rotate: false - xy: 1868, 379 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -unit-eruptor-full - rotate: false - xy: 2703, 819 - size: 88, 64 - orig: 88, 64 - offset: 0, 0 - index: -1 -unit-fortress-full - rotate: false - xy: 1493, 853 - size: 100, 80 - orig: 100, 80 - offset: 0, 0 - index: -1 -unit-ghoul-full - rotate: false - xy: 3581, 811 - size: 72, 72 - orig: 72, 72 - offset: 0, 0 - index: -1 -unit-lich-full - rotate: false - xy: 2951, 1549 - size: 216, 240 - orig: 216, 240 - offset: 0, 0 - index: -1 -unit-mace-full - rotate: false - xy: 952, 103 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -unit-oculon-full - rotate: false - xy: 3203, 803 - size: 80, 80 - orig: 80, 80 - offset: 0, 0 - index: -1 -unit-phantom-full - rotate: false - xy: 2509, 1329 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -unit-reaper-full +eclipse-wreck0 rotate: false xy: 323, 1727 size: 320, 320 orig: 320, 320 offset: 0, 0 index: -1 -unit-revenant-full +eclipse-wreck1 rotate: false - xy: 973, 383 - size: 112, 112 - orig: 112, 112 + xy: 1, 1083 + size: 320, 320 + orig: 320, 320 offset: 0, 0 index: -1 -unit-spirit-full +eclipse-wreck2 rotate: false - xy: 2171, 1285 + xy: 323, 1405 + size: 320, 320 + orig: 320, 320 + offset: 0, 0 + index: -1 +flare-wreck0 + rotate: false + xy: 2830, 421 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -unit-tau-full +flare-wreck1 rotate: false - xy: 2567, 1329 + xy: 2680, 321 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +flare-wreck2 + rotate: false + xy: 2730, 363 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +fortress-wreck0 + rotate: false + xy: 3667, 1239 + size: 100, 80 + orig: 100, 80 + offset: 0, 0 + index: -1 +fortress-wreck1 + rotate: false + xy: 509, 711 + size: 100, 80 + orig: 100, 80 + offset: 0, 0 + index: -1 +fortress-wreck2 + rotate: false + xy: 3667, 1157 + size: 100, 80 + orig: 100, 80 + offset: 0, 0 + index: -1 +fuse + rotate: false + xy: 2235, 653 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +gamma-wreck0 + rotate: false + xy: 2060, 4 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 -unit-trident-full +gamma-wreck1 rotate: false - xy: 1103, 459 - size: 100, 100 - orig: 100, 100 + xy: 721, 30 + size: 56, 56 + orig: 56, 56 offset: 0, 0 index: -1 -unit-vanguard-full +gamma-wreck2 rotate: false - xy: 2221, 1285 + xy: 779, 30 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +hail + rotate: false + xy: 2635, 185 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +horizon-wreck0 + rotate: false + xy: 2050, 334 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 +horizon-wreck1 + rotate: false + xy: 2050, 260 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 +horizon-wreck2 + rotate: false + xy: 3141, 1117 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 +item-blast-compound-large + rotate: false + xy: 2980, 279 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-blast-compound-medium + rotate: false + xy: 3352, 197 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-blast-compound-small + rotate: false + xy: 3769, 1305 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-blast-compound-tiny + rotate: false + xy: 1, 1 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-blast-compound-xlarge + rotate: false + xy: 2930, 421 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -unit-wraith-full +item-coal-large rotate: false - xy: 2271, 1287 + xy: 3022, 279 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-coal-medium + rotate: false + xy: 3420, 197 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-coal-small + rotate: false + xy: 3154, 537 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-coal-tiny + rotate: false + xy: 19, 1 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-coal-xlarge + rotate: false + xy: 2880, 371 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -wave +item-copper-large rotate: false - xy: 1831, 429 + xy: 3502, 416 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-copper-medium + rotate: false + xy: 3488, 197 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-copper-small + rotate: false + xy: 3504, 273 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-copper-tiny + rotate: false + xy: 37, 1 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-copper-xlarge + rotate: false + xy: 2980, 421 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-graphite-large + rotate: false + xy: 2381, 221 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-graphite-medium + rotate: false + xy: 3556, 215 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-graphite-small + rotate: false + xy: 3795, 1305 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-graphite-tiny + rotate: false + xy: 55, 1 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-graphite-xlarge + rotate: false + xy: 2930, 371 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-lead-large + rotate: false + xy: 3064, 273 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-lead-medium + rotate: false + xy: 3556, 181 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-lead-small + rotate: false + xy: 613, 1057 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-lead-tiny + rotate: false + xy: 73, 1 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-lead-xlarge + rotate: false + xy: 2980, 371 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-metaglass-large + rotate: false + xy: 2381, 179 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-metaglass-medium + rotate: false + xy: 3624, 181 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-metaglass-small + rotate: false + xy: 903, 1121 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-metaglass-tiny + rotate: false + xy: 91, 1 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-metaglass-xlarge + rotate: false + xy: 3030, 421 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-phase-fabric-large + rotate: false + xy: 2388, 137 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-phase-fabric-medium + rotate: false + xy: 2533, 181 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-phase-fabric-small + rotate: false + xy: 871, 863 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-phase-fabric-tiny + rotate: false + xy: 109, 1 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-phase-fabric-xlarge + rotate: false + xy: 3030, 371 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-plastanium-large + rotate: false + xy: 2388, 95 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-plastanium-medium + rotate: false + xy: 2472, 147 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-plastanium-small + rotate: false + xy: 1161, 1185 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-plastanium-tiny + rotate: false + xy: 127, 1 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-plastanium-xlarge + rotate: false + xy: 2730, 313 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-pyratite-large + rotate: false + xy: 2388, 53 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-pyratite-medium + rotate: false + xy: 2506, 147 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-pyratite-small + rotate: false + xy: 1129, 959 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-pyratite-tiny + rotate: false + xy: 145, 1 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-pyratite-xlarge + rotate: false + xy: 2780, 313 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-sand-large + rotate: false + xy: 2388, 11 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-sand-medium + rotate: false + xy: 2506, 113 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-sand-small + rotate: false + xy: 1097, 733 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-sand-tiny + rotate: false + xy: 3239, 1515 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-sand-xlarge + rotate: false + xy: 2830, 321 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-scrap-large + rotate: false + xy: 3106, 271 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-scrap-medium + rotate: false + xy: 2472, 45 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-scrap-small + rotate: false + xy: 1451, 1507 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-scrap-tiny + rotate: false + xy: 1957, 1043 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-scrap-xlarge + rotate: false + xy: 2880, 321 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-silicon-large + rotate: false + xy: 2422, 263 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-silicon-medium + rotate: false + xy: 2540, 113 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-silicon-small + rotate: false + xy: 323, 767 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-silicon-tiny + rotate: false + xy: 1615, 729 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-silicon-xlarge + rotate: false + xy: 2930, 321 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-spore-pod-large + rotate: false + xy: 2423, 221 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-spore-pod-medium + rotate: false + xy: 2540, 79 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-spore-pod-small + rotate: false + xy: 2230, 491 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-spore-pod-tiny + rotate: false + xy: 1060, 118 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-spore-pod-xlarge + rotate: false + xy: 2980, 321 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-surge-alloy-large + rotate: false + xy: 2423, 179 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-surge-alloy-medium + rotate: false + xy: 2540, 45 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-surge-alloy-small + rotate: false + xy: 1005, 1733 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-surge-alloy-tiny + rotate: false + xy: 1864, 290 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-surge-alloy-xlarge + rotate: false + xy: 3030, 321 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-thorium-large + rotate: false + xy: 2430, 137 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-thorium-medium + rotate: false + xy: 2574, 147 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-thorium-small + rotate: false + xy: 1895, 118 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-thorium-tiny + rotate: false + xy: 3151, 967 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-thorium-xlarge + rotate: false + xy: 3080, 415 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-titanium-large + rotate: false + xy: 2430, 95 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +item-titanium-medium + rotate: false + xy: 2574, 79 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-titanium-small + rotate: false + xy: 2702, 295 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-titanium-tiny + rotate: false + xy: 3183, 769 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +item-titanium-xlarge + rotate: false + xy: 3080, 365 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +lancer + rotate: false + xy: 3381, 919 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 +liquid-cryofluid-large + rotate: false + xy: 2430, 53 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +liquid-cryofluid-medium + rotate: false + xy: 2642, 151 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-cryofluid-small + rotate: false + xy: 2465, 185 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +liquid-cryofluid-tiny + rotate: false + xy: 2118, 44 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +liquid-cryofluid-xlarge + rotate: false + xy: 3130, 363 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +liquid-oil-large + rotate: false + xy: 2430, 11 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +liquid-oil-medium + rotate: false + xy: 2642, 117 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-oil-small + rotate: false + xy: 3547, 990 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +liquid-oil-tiny + rotate: false + xy: 1595, 925 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +liquid-oil-xlarge + rotate: false + xy: 3130, 313 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +liquid-slag-large + rotate: false + xy: 3630, 215 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +liquid-slag-medium + rotate: false + xy: 2676, 117 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-slag-small + rotate: false + xy: 3645, 786 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +liquid-slag-tiny + rotate: false + xy: 3130, 447 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +liquid-slag-xlarge + rotate: false + xy: 3180, 349 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +liquid-water-large + rotate: false + xy: 2980, 237 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +liquid-water-medium + rotate: false + xy: 3284, 163 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-water-small + rotate: false + xy: 3611, 752 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +liquid-water-tiny + rotate: false + xy: 701, 21 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +liquid-water-xlarge + rotate: false + xy: 3230, 349 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mace-wreck0 + rotate: false + xy: 3215, 721 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mace-wreck1 + rotate: false + xy: 3281, 721 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mace-wreck2 + rotate: false + xy: 3347, 721 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mass-driver + rotate: false + xy: 2823, 653 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +mega-wreck0 + rotate: false + xy: 1651, 1041 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +mega-wreck1 + rotate: false + xy: 1753, 1041 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +mega-wreck2 + rotate: false + xy: 1855, 1041 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +meltdown + rotate: false + xy: 2849, 1273 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +mono-wreck0 + rotate: false + xy: 3180, 299 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mono-wreck1 + rotate: false + xy: 3230, 299 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mono-wreck2 + rotate: false + xy: 3280, 299 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +nova-wreck0 + rotate: false + xy: 2323, 203 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +nova-wreck1 + rotate: false + xy: 3549, 415 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +nova-wreck2 + rotate: false + xy: 3607, 407 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +parallax + rotate: false + xy: 3513, 919 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +poly-wreck0 + rotate: false + xy: 3270, 399 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +poly-wreck1 + rotate: false + xy: 3328, 399 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +poly-wreck2 + rotate: false + xy: 3386, 399 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +pulsar-wreck0 + rotate: false + xy: 3501, 1239 + size: 58, 48 + orig: 58, 48 + offset: 0, 0 + index: -1 +pulsar-wreck1 + rotate: false + xy: 2062, 210 + size: 58, 48 + orig: 58, 48 + offset: 0, 0 + index: -1 +pulsar-wreck2 + rotate: false + xy: 1942, 12 + size: 58, 48 + orig: 58, 48 + offset: 0, 0 + index: -1 +quasar-wreck0 + rotate: false + xy: 1968, 342 + size: 80, 80 + orig: 80, 80 + offset: 0, 0 + index: -1 +quasar-wreck1 + rotate: false + xy: 1886, 276 + size: 80, 80 + orig: 80, 80 + offset: 0, 0 + index: -1 +quasar-wreck2 + rotate: false + xy: 1968, 260 + size: 80, 80 + orig: 80, 80 + offset: 0, 0 + index: -1 +repair-point + rotate: false + xy: 3681, 851 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ripple + rotate: false + xy: 1158, 15 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +salvo + rotate: false + xy: 3321, 523 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scatter + rotate: false + xy: 3585, 523 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scorch + rotate: false + xy: 3749, 905 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +segment + rotate: false + xy: 2489, 587 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spectre + rotate: false + xy: 2979, 1273 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +spiroct-wreck0 + rotate: false + xy: 1841, 572 + size: 94, 75 + orig: 94, 75 + offset: 0, 0 + index: -1 +spiroct-wreck1 + rotate: false + xy: 1937, 572 + size: 94, 75 + orig: 94, 75 + offset: 0, 0 + index: -1 +spiroct-wreck2 + rotate: false + xy: 2033, 572 + size: 94, 75 + orig: 94, 75 + offset: 0, 0 + index: -1 +splash-0 + rotate: false + xy: 3851, 905 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +splash-1 + rotate: false + xy: 3919, 939 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +splash-10 + rotate: false + xy: 3919, 837 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +splash-11 + rotate: false + xy: 3953, 937 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +splash-2 + rotate: false + xy: 3817, 837 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +splash-3 + rotate: false + xy: 3851, 871 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +splash-4 + rotate: false + xy: 3885, 905 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +splash-5 + rotate: false + xy: 3851, 837 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +splash-6 + rotate: false + xy: 3885, 871 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +splash-7 + rotate: false + xy: 3919, 905 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +splash-8 + rotate: false + xy: 3885, 837 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +splash-9 + rotate: false + xy: 3919, 871 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +swarmer + rotate: false + xy: 2494, 521 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +unit-alpha-full + rotate: false + xy: 3630, 257 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +unit-antumbra-full + rotate: false + xy: 727, 291 + size: 216, 240 + orig: 216, 240 + offset: 0, 0 + index: -1 +unit-arkyid-full + rotate: false + xy: 3109, 1403 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +unit-atrax-full + rotate: false + xy: 1796, 308 + size: 88, 64 + orig: 88, 64 + offset: 0, 0 + index: -1 +unit-beta-full + rotate: false + xy: 3511, 1153 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +unit-crawler-full + rotate: false + xy: 3561, 1152 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +unit-dagger-full + rotate: false + xy: 3611, 1152 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +unit-eclipse-full + rotate: false + xy: 645, 1727 + size: 320, 320 + orig: 320, 320 + offset: 0, 0 + index: -1 +unit-flare-full + rotate: false + xy: 2338, 117 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +unit-fortress-full + rotate: false + xy: 1957, 1061 + size: 100, 80 + orig: 100, 80 + offset: 0, 0 + index: -1 +unit-gamma-full + rotate: false + xy: 2296, 463 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +unit-horizon-full + rotate: false + xy: 3437, 1117 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 +unit-mace-full + rotate: false + xy: 3088, 531 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +unit-mega-full + rotate: false + xy: 2059, 1041 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +unit-mono-full + rotate: false + xy: 2338, 67 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +unit-nova-full + rotate: false + xy: 2354, 463 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +unit-poly-full + rotate: false + xy: 2412, 463 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +unit-pulsar-full + rotate: false + xy: 3549, 473 + size: 58, 48 + orig: 58, 48 + offset: 0, 0 + index: -1 +unit-quasar-full + rotate: false + xy: 2058, 408 + size: 80, 80 + orig: 80, 80 + offset: 0, 0 + index: -1 +unit-spiroct-full + rotate: false + xy: 2129, 572 + size: 94, 75 + orig: 94, 75 + offset: 0, 0 + index: -1 +unit-zenith-full + rotate: false + xy: 163, 67 + size: 112, 112 + orig: 112, 112 + offset: 0, 0 + index: -1 +wave + rotate: false + xy: 3352, 457 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +zenith-wreck0 + rotate: false + xy: 3223, 1289 + size: 112, 112 + orig: 112, 112 + offset: 0, 0 + index: -1 +zenith-wreck1 + rotate: false + xy: 3337, 1289 + size: 112, 112 + orig: 112, 112 + offset: 0, 0 + index: -1 +zenith-wreck2 + rotate: false + xy: 3451, 1289 + size: 112, 112 + orig: 112, 112 + offset: 0, 0 + index: -1 item-blast-compound rotate: false - xy: 1086, 177 + xy: 3318, 197 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-coal rotate: false - xy: 1052, 109 + xy: 3386, 197 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-copper rotate: false - xy: 1018, 41 + xy: 3454, 197 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-graphite rotate: false - xy: 1086, 109 + xy: 3522, 197 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-lead rotate: false - xy: 1086, 75 + xy: 3590, 215 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-metaglass rotate: false - xy: 2281, 1211 + xy: 3590, 181 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-phase-fabric rotate: false - xy: 2399, 1217 + xy: 2499, 181 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-plastanium rotate: false - xy: 2473, 1227 + xy: 2567, 181 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-pyratite rotate: false - xy: 2541, 1227 + xy: 2472, 113 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-sand rotate: false - xy: 2609, 1227 + xy: 2472, 79 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-scrap rotate: false - xy: 1125, 201 + xy: 2540, 147 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-silicon rotate: false - xy: 1120, 133 + xy: 2506, 79 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-spore-pod rotate: false - xy: 1120, 31 + xy: 2506, 45 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-surge-alloy rotate: false - xy: 1193, 200 + xy: 2506, 11 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-thorium rotate: false - xy: 1154, 166 + xy: 2540, 11 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-titanium rotate: false - xy: 1188, 166 + xy: 2574, 113 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-cryofluid rotate: false - xy: 1154, 64 + xy: 2608, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-oil rotate: false - xy: 1188, 64 + xy: 2608, 83 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-slag rotate: false - xy: 1256, 165 + xy: 2676, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-water rotate: false - xy: 1256, 29 + xy: 2676, 15 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 blank rotate: false - xy: 3951, 1852 + xy: 509, 631 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 circle rotate: false - xy: 1, 10 + xy: 945, 330 size: 201, 201 orig: 201, 201 offset: 0, 0 index: -1 shape-3 rotate: false - xy: 1745, 364 + xy: 3484, 458 size: 63, 63 orig: 63, 63 offset: 0, 0 index: -1 alpha rotate: false - xy: 3901, 1805 + xy: 1545, 893 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 alpha-cell rotate: false - xy: 2679, 1337 + xy: 2578, 471 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -chaos-array +antumbra rotate: false - xy: 3655, 1179 + xy: 291, 519 + size: 216, 240 + orig: 216, 240 + offset: 0, 0 + index: -1 +antumbra-cell + rotate: false + xy: 291, 277 + size: 216, 240 + orig: 216, 240 + offset: 0, 0 + index: -1 +arkyid + rotate: false + xy: 1601, 109 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 -cix +chaos-array rotate: false - xy: 3655, 1179 + xy: 1601, 109 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 +arkyid-cell + rotate: false + xy: 1796, 506 + size: 88, 64 + orig: 88, 64 + offset: 0, 0 + index: -1 +arkyid-foot + rotate: false + xy: 3769, 1331 + size: 70, 70 + orig: 70, 70 + offset: 0, 0 + index: -1 +arkyid-joint-base + rotate: false + xy: 3117, 597 + size: 70, 70 + orig: 70, 70 + offset: 0, 0 + index: -1 +arkyid-leg + rotate: false + xy: 663, 39 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +arkyid-leg-base + rotate: false + xy: 163, 1 + size: 104, 64 + orig: 104, 64 + offset: 0, 0 + index: -1 +atrax + rotate: false + xy: 1796, 440 + size: 88, 64 + orig: 88, 64 + offset: 0, 0 + index: -1 +atrax-base + rotate: false + xy: 3189, 603 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +atrax-cell + rotate: false + xy: 1886, 506 + size: 88, 64 + orig: 88, 64 + offset: 0, 0 + index: -1 +atrax-foot + rotate: false + xy: 829, 589 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +atrax-joint + rotate: false + xy: 3259, 1731 + size: 26, 26 + orig: 26, 26 + offset: 0, 0 + index: -1 +atrax-leg + rotate: false + xy: 967, 1731 + size: 36, 26 + orig: 36, 26 + offset: 0, 0 + index: -1 +atrax-leg-base + rotate: false + xy: 1097, 535 + size: 36, 26 + orig: 36, 26 + offset: 0, 0 + index: -1 +beta + rotate: false + xy: 2828, 471 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +beta-cell + rotate: false + xy: 2380, 355 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 chaos-array-base rotate: false - xy: 3785, 1179 + xy: 1679, 1143 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 chaos-array-cell rotate: false - xy: 3915, 1179 + xy: 1939, 1403 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 chaos-array-leg rotate: false - xy: 583, 859 + xy: 1939, 1273 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 -cix-cell - rotate: false - xy: 2343, 819 - size: 88, 64 - orig: 88, 64 - offset: 0, 0 - index: -1 -cix-foot - rotate: false - xy: 4025, 1009 - size: 70, 70 - orig: 70, 70 - offset: 0, 0 - index: -1 -cix-joint-base - rotate: false - xy: 4025, 937 - size: 70, 70 - orig: 70, 70 - offset: 0, 0 - index: -1 -cix-leg - rotate: false - xy: 291, 215 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -cix-leg-base - rotate: false - xy: 1103, 561 - size: 104, 64 - orig: 104, 64 - offset: 0, 0 - index: -1 -cix-old - rotate: false - xy: 2433, 819 - size: 88, 64 - orig: 88, 64 - offset: 0, 0 - index: -1 crawler rotate: false - xy: 2879, 1337 + xy: 2430, 413 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 crawler-base rotate: false - xy: 2929, 1337 + xy: 2430, 363 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 crawler-cell rotate: false - xy: 2979, 1337 + xy: 2430, 313 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 crawler-leg rotate: false - xy: 3029, 1337 + xy: 2480, 417 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger rotate: false - xy: 2743, 715 + xy: 2530, 367 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger-base rotate: false - xy: 2793, 753 + xy: 2530, 317 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger-leg rotate: false - xy: 2743, 665 + xy: 2580, 421 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -delta - rotate: false - xy: 2793, 703 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -delta-cell - rotate: false - xy: 2843, 753 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -draug - rotate: false - xy: 2843, 703 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -draug-cell - rotate: false - xy: 2893, 753 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -eradicator - rotate: false - xy: 3525, 1309 - size: 152, 124 - orig: 152, 124 - offset: 0, 0 - index: -1 -eradicator-base - rotate: false - xy: 3679, 1309 - size: 152, 124 - orig: 152, 124 - offset: 0, 0 - index: -1 -eradicator-cell - rotate: false - xy: 3833, 1309 - size: 152, 124 - orig: 152, 124 - offset: 0, 0 - index: -1 -eradicator-leg - rotate: false - xy: 453, 989 - size: 152, 124 - orig: 152, 124 - offset: 0, 0 - index: -1 -eruptor - rotate: false - xy: 2523, 819 - size: 88, 64 - orig: 88, 64 - offset: 0, 0 - index: -1 -eruptor-base - rotate: false - xy: 3165, 1328 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -eruptor-cell - rotate: false - xy: 2613, 819 - size: 88, 64 - orig: 88, 64 - offset: 0, 0 - index: -1 -eruptor-foot - rotate: false - xy: 407, 231 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -eruptor-joint - rotate: false - xy: 1727, 691 - size: 26, 26 - orig: 26, 26 - offset: 0, 0 - index: -1 -eruptor-leg - rotate: false - xy: 713, 209 - size: 36, 26 - orig: 36, 26 - offset: 0, 0 - index: -1 -eruptor-leg-base - rotate: false - xy: 3987, 1309 - size: 36, 26 - orig: 36, 26 - offset: 0, 0 - index: -1 -fortress - rotate: false - xy: 1363, 805 - size: 100, 80 - orig: 100, 80 - offset: 0, 0 - index: -1 -fortress-base - rotate: false - xy: 3231, 1328 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -fortress-cell - rotate: false - xy: 1493, 935 - size: 100, 80 - orig: 100, 80 - offset: 0, 0 - index: -1 -fortress-leg - rotate: false - xy: 2031, 1277 - size: 80, 60 - orig: 80, 60 - offset: 0, 0 - index: -1 -ghoul - rotate: false - xy: 3285, 811 - size: 72, 72 - orig: 72, 72 - offset: 0, 0 - index: -1 -ghoul-cell - rotate: false - xy: 3359, 811 - size: 72, 72 - orig: 72, 72 - offset: 0, 0 - index: -1 -glaive - rotate: false - xy: 596, 21 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -glaive-cell - rotate: false - xy: 2113, 1281 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -lich - rotate: false - xy: 2515, 1549 - size: 216, 240 - orig: 216, 240 - offset: 0, 0 - index: -1 -lich-cell - rotate: false - xy: 2733, 1549 - size: 216, 240 - orig: 216, 240 - offset: 0, 0 - index: -1 -mace - rotate: false - xy: 2413, 687 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -mace-base - rotate: false - xy: 2479, 687 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -mace-cell - rotate: false - xy: 2545, 687 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -mace-leg - rotate: false - xy: 2611, 687 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -oculon - rotate: false - xy: 2875, 803 - size: 80, 80 - orig: 80, 80 - offset: 0, 0 - index: -1 -oculon-armor - rotate: false - xy: 2611, 621 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -oculon-base - rotate: false - xy: 2957, 803 - size: 80, 80 - orig: 80, 80 - offset: 0, 0 - index: -1 -oculon-base-old - rotate: false - xy: 2893, 653 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -oculon-cell - rotate: false - xy: 3039, 803 - size: 80, 80 - orig: 80, 80 - offset: 0, 0 - index: -1 -oculon-cell-old - rotate: false - xy: 2943, 645 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -oculon-leg - rotate: false - xy: 3121, 803 - size: 80, 80 - orig: 80, 80 - offset: 0, 0 - index: -1 -oculon-leg-old - rotate: false - xy: 2993, 653 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -oculon-old - rotate: false - xy: 2391, 1353 - size: 58, 48 - orig: 58, 48 - offset: 0, 0 - index: -1 -phantom - rotate: false - xy: 1810, 371 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -phantom-cell - rotate: false - xy: 349, 215 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -power-cell - rotate: false - xy: 1081, 303 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -reaper +eclipse rotate: false xy: 1, 1727 size: 320, 320 orig: 320, 320 offset: 0, 0 index: -1 -reaper-cell +eclipse-cell rotate: false xy: 1, 1405 size: 320, 320 orig: 320, 320 offset: 0, 0 index: -1 -revenant +eradicator rotate: false - xy: 3954, 1611 - size: 112, 112 - orig: 112, 112 + xy: 509, 21 + size: 152, 124 + orig: 152, 124 offset: 0, 0 index: -1 -revenant-cell +eradicator-base rotate: false - xy: 843, 253 - size: 112, 112 - orig: 112, 112 + xy: 1139, 113 + size: 152, 124 + orig: 152, 124 offset: 0, 0 index: -1 -spirit +eradicator-cell rotate: false - xy: 3443, 661 + xy: 1293, 113 + size: 152, 124 + orig: 152, 124 + offset: 0, 0 + index: -1 +eradicator-leg + rotate: false + xy: 1447, 113 + size: 152, 124 + orig: 152, 124 + offset: 0, 0 + index: -1 +flare + rotate: false + xy: 2630, 321 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -spirit-cell +fortress rotate: false - xy: 3493, 661 - size: 48, 48 - orig: 48, 48 + xy: 727, 549 + size: 100, 80 + orig: 100, 80 offset: 0, 0 index: -1 -tau +fortress-base rotate: false - xy: 1081, 245 + xy: 3249, 919 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +fortress-cell + rotate: false + xy: 3667, 1321 + size: 100, 80 + orig: 100, 80 + offset: 0, 0 + index: -1 +fortress-leg + rotate: false + xy: 1419, 1049 + size: 80, 60 + orig: 80, 60 + offset: 0, 0 + index: -1 +gamma + rotate: false + xy: 2322, 261 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 -tau-base +gamma-cell rotate: false - xy: 3543, 661 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -tau-cell - rotate: false - xy: 1679, 305 + xy: 2002, 4 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 -tau-leg +horizon rotate: false - xy: 3593, 661 - size: 48, 48 - orig: 48, 48 + xy: 4003, 1441 + size: 72, 72 + orig: 72, 72 offset: 0, 0 index: -1 -trident +horizon-cell rotate: false - xy: 1595, 915 + xy: 2140, 416 + size: 72, 72 + orig: 72, 72 + offset: 0, 0 + index: -1 +mace + rotate: false + xy: 3249, 787 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mace-base + rotate: false + xy: 3381, 853 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mace-cell + rotate: false + xy: 3315, 787 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mace-leg + rotate: false + xy: 3381, 787 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mega + rotate: false + xy: 3971, 1333 size: 100, 100 orig: 100, 100 offset: 0, 0 index: -1 -trident-cell +mega-cell rotate: false - xy: 2451, 1329 + xy: 1549, 1041 + size: 100, 100 + orig: 100, 100 + offset: 0, 0 + index: -1 +mono + rotate: false + xy: 3380, 349 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mono-cell + rotate: false + xy: 3430, 349 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +nova + rotate: false + xy: 837, 30 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 +nova-base + rotate: false + xy: 3430, 299 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +nova-cell + rotate: false + xy: 3609, 465 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +nova-leg + rotate: false + xy: 3480, 349 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +poly + rotate: false + xy: 3154, 413 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +poly-cell + rotate: false + xy: 3212, 399 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +power-cell + rotate: false + xy: 3444, 399 + size: 56, 56 + orig: 56, 56 + offset: 0, 0 + index: -1 +pulsar + rotate: false + xy: 663, 97 + size: 58, 48 + orig: 58, 48 + offset: 0, 0 + index: -1 +pulsar-base + rotate: false + xy: 3480, 299 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +pulsar-cell + rotate: false + xy: 1485, 893 + size: 58, 48 + orig: 58, 48 + offset: 0, 0 + index: -1 +pulsar-leg + rotate: false + xy: 3453, 589 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +quasar + rotate: false + xy: 2066, 490 + size: 80, 80 + orig: 80, 80 + offset: 0, 0 + index: -1 +quasar-base + rotate: false + xy: 2148, 490 + size: 80, 80 + orig: 80, 80 + offset: 0, 0 + index: -1 +quasar-cell + rotate: false + xy: 1976, 424 + size: 80, 80 + orig: 80, 80 + offset: 0, 0 + index: -1 +quasar-leg + rotate: false + xy: 4003, 1515 + size: 80, 80 + orig: 80, 80 + offset: 0, 0 + index: -1 +spiroct + rotate: false + xy: 509, 634 + size: 94, 75 + orig: 94, 75 + offset: 0, 0 + index: -1 +spiroct-cell + rotate: false + xy: 1745, 572 + size: 94, 75 + orig: 94, 75 + offset: 0, 0 + index: -1 +spiroct-foot + rotate: false + xy: 1501, 1063 + size: 46, 46 + orig: 46, 46 + offset: 0, 0 + index: -1 +spiroct-joint + rotate: false + xy: 3817, 871 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spiroct-leg + rotate: false + xy: 3501, 1203 + size: 48, 34 + orig: 48, 34 + offset: 0, 0 + index: -1 +spiroct-leg-base + rotate: false + xy: 2323, 167 + size: 48, 34 + orig: 48, 34 + offset: 0, 0 + index: -1 vanguard rotate: false - xy: 2321, 1287 + xy: 2338, 17 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 vanguard-cell rotate: false - xy: 2181, 1235 + xy: 2830, 271 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +antumbra-missiles + rotate: false + xy: 2778, 471 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 artillery rotate: false - xy: 2729, 1329 + xy: 2380, 405 size: 48, 56 orig: 48, 56 offset: 0, 0 index: -1 +beam-weapon + rotate: false + xy: 1886, 358 + size: 80, 80 + orig: 80, 80 + offset: 0, 0 + index: -1 chaos rotate: false - xy: 1023, 245 + xy: 2322, 319 size: 56, 136 orig: 56, 136 offset: 0, 0 index: -1 +eclipse-weapon + rotate: false + xy: 2580, 321 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 eradication rotate: false - xy: 1433, 513 + xy: 2595, 753 size: 96, 192 orig: 96, 192 offset: 0, 0 index: -1 eruption rotate: false - xy: 2943, 745 + xy: 2730, 413 size: 48, 56 orig: 48, 56 offset: 0, 0 index: -1 flakgun rotate: false - xy: 2993, 753 + xy: 2680, 371 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 flamethrower rotate: false - xy: 3043, 745 + xy: 2780, 413 size: 48, 56 orig: 48, 56 offset: 0, 0 index: -1 +heal-shotgun-weapon + rotate: false + xy: 2880, 421 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 heal-weapon rotate: false - xy: 3093, 753 + xy: 2780, 363 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 heal-weapon-mount rotate: false - xy: 3143, 753 + xy: 2830, 371 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 large-weapon rotate: false - xy: 3443, 711 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -lich-missiles - rotate: false - xy: 3493, 761 + xy: 3080, 315 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 missiles rotate: false - xy: 3593, 711 + xy: 3280, 349 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 missiles-mount rotate: false - xy: 2793, 653 + xy: 3330, 349 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mount-purple-weapon + rotate: false + xy: 3330, 299 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mount-weapon rotate: false - xy: 2843, 653 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -reaper-weapon - rotate: false - xy: 3043, 645 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -revenant-missiles - rotate: false - xy: 3093, 653 + xy: 3380, 299 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 small-basic-weapon rotate: false - xy: 3243, 653 + xy: 3580, 357 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +small-mount-weapon + rotate: false + xy: 3580, 307 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 small-weapon rotate: false - xy: 3293, 661 + xy: 3630, 357 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 +spiroct-weapon + rotate: false + xy: 3580, 249 + size: 48, 56 + orig: 48, 56 + offset: 0, 0 + index: -1 weapon rotate: false - xy: 2181, 1185 + xy: 2880, 271 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -wraith +zenith-missiles rotate: false - xy: 2231, 1235 + xy: 2930, 271 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -beam-weapon +zenith rotate: false - xy: 2793, 803 - size: 80, 80 - orig: 80, 80 + xy: 3109, 1289 + size: 112, 112 + orig: 112, 112 offset: 0, 0 index: -1 -beam-weapon +zenith-cell rotate: false - xy: 2793, 803 - size: 80, 80 - orig: 80, 80 + xy: 2979, 1159 + size: 112, 112 + orig: 112, 112 offset: 0, 0 index: -1 @@ -7430,2107 +7948,2107 @@ filter: nearest,nearest repeat: none additive-reconstructor-icon-editor rotate: false - xy: 2103, 391 + xy: 1973, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 air-factory-icon-editor rotate: false - xy: 2201, 391 + xy: 2071, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 alloy-smelter-icon-editor rotate: false - xy: 2299, 391 + xy: 2169, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 arc-icon-editor rotate: false - xy: 4063, 455 + xy: 1085, 227 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 armored-conveyor-icon-editor rotate: false - xy: 4063, 421 + xy: 1565, 225 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 battery-icon-editor rotate: false - xy: 325, 3 + xy: 1119, 227 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 battery-large-icon-editor rotate: false - xy: 2397, 391 + xy: 2267, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 blast-drill-icon-editor rotate: false - xy: 1323, 359 + xy: 163, 35 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 blast-mixer-icon-editor rotate: false - xy: 2043, 293 + xy: 4031, 421 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-border-editor rotate: false - xy: 359, 3 + xy: 1599, 225 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-forge-icon-editor rotate: false - xy: 2495, 391 + xy: 2365, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-loader-icon-editor rotate: false - xy: 2593, 391 + xy: 2463, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-unloader-icon-editor rotate: false - xy: 2691, 391 + xy: 2561, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 bridge-conduit-icon-editor rotate: false - xy: 393, 3 + xy: 1633, 225 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-icon-editor rotate: false - xy: 427, 3 + xy: 1667, 225 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 char-icon-editor rotate: false - xy: 461, 3 + xy: 1701, 225 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-char1 rotate: false - xy: 461, 3 + xy: 1701, 225 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 clear-editor rotate: false - xy: 1323, 356 + xy: 645, 194 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 cliff-icon-editor rotate: false - xy: 495, 3 + xy: 1735, 225 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cliffs-icon-editor rotate: false - xy: 529, 3 + xy: 1769, 225 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 coal-centrifuge-icon-editor rotate: false - xy: 1131, 163 + xy: 4031, 355 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 combustion-generator-icon-editor rotate: false - xy: 1357, 227 + xy: 1803, 225 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-icon-editor rotate: false - xy: 1391, 227 + xy: 1847, 257 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 container-icon-editor rotate: false - xy: 1197, 163 + xy: 1847, 291 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 conveyor-icon-editor rotate: false - xy: 1425, 227 + xy: 1881, 257 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper-wall-icon-editor rotate: false - xy: 1459, 227 + xy: 1915, 257 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper-wall-large-icon-editor rotate: false - xy: 1263, 163 + xy: 1913, 291 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 core-foundation-icon-editor rotate: false - xy: 325, 37 + xy: 1323, 357 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 core-nucleus-icon-editor rotate: false - xy: 1, 5 + xy: 1, 3 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 core-shard-icon-editor rotate: false - xy: 2789, 391 + xy: 2659, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 -core-silo-icon-editor - rotate: false - xy: 1161, 327 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 craters-icon-editor rotate: false - xy: 1493, 227 + xy: 1979, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-craters1 rotate: false - xy: 1493, 227 + xy: 1979, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cryofluidmixer-icon-editor rotate: false - xy: 683, 133 + xy: 1979, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator-icon-editor rotate: false - xy: 749, 133 + xy: 2045, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cyclone-icon-editor rotate: false - xy: 2887, 391 + xy: 2757, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 dark-metal-icon-editor rotate: false - xy: 1527, 227 + xy: 2013, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dark-panel-1-icon-editor rotate: false - xy: 1561, 227 + xy: 2047, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-dark-panel-1 rotate: false - xy: 1561, 227 + xy: 2047, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dark-panel-2-icon-editor rotate: false - xy: 1595, 227 + xy: 2081, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-dark-panel-2 rotate: false - xy: 1595, 227 + xy: 2081, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dark-panel-3-icon-editor rotate: false - xy: 1629, 227 + xy: 2115, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-dark-panel-3 rotate: false - xy: 1629, 227 + xy: 2115, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dark-panel-4-icon-editor rotate: false - xy: 1663, 227 + xy: 2149, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-dark-panel-4 rotate: false - xy: 1663, 227 + xy: 2149, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dark-panel-5-icon-editor rotate: false - xy: 1697, 227 + xy: 2183, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-dark-panel-5 rotate: false - xy: 1697, 227 + xy: 2183, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dark-panel-6-icon-editor rotate: false - xy: 1731, 227 + xy: 2217, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-dark-panel-6 rotate: false - xy: 1731, 227 + xy: 2217, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 darksand-icon-editor rotate: false - xy: 1765, 227 + xy: 2251, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-darksand1 rotate: false - xy: 1765, 227 + xy: 2251, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 darksand-tainted-water-icon-editor rotate: false - xy: 1799, 227 + xy: 2285, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 darksand-water-icon-editor rotate: false - xy: 1833, 227 + xy: 2319, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 data-processor-icon-editor rotate: false - xy: 2985, 391 + xy: 2855, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 deepwater-icon-editor rotate: false - xy: 1867, 227 + xy: 2353, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-deepwater rotate: false - xy: 1867, 227 + xy: 2353, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 differential-generator-icon-editor rotate: false - xy: 3083, 391 + xy: 2953, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 diode-icon-editor rotate: false - xy: 1901, 227 + xy: 2387, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 disassembler-icon-editor rotate: false - xy: 3181, 391 + xy: 3051, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 distributor-icon-editor rotate: false - xy: 815, 133 + xy: 2111, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door-icon-editor rotate: false - xy: 1935, 227 + xy: 2421, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 door-large-icon-editor rotate: false - xy: 683, 67 + xy: 2177, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 dunerocks-icon-editor rotate: false - xy: 1969, 227 + xy: 2455, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 duo-icon-editor rotate: false - xy: 2003, 227 + xy: 2489, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-char2 rotate: false - xy: 2043, 259 + xy: 2523, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-char3 rotate: false - xy: 585, 35 + xy: 2557, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-craters2 rotate: false - xy: 619, 35 + xy: 2591, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-craters3 rotate: false - xy: 2109, 291 + xy: 2625, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-darksand-tainted-water1 rotate: false - xy: 2211, 291 + xy: 2727, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-darksand-tainted-water2 rotate: false - xy: 2245, 291 + xy: 2761, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-darksand-tainted-water3 rotate: false - xy: 2279, 291 + xy: 2795, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-darksand-water1 rotate: false - xy: 2313, 291 + xy: 2829, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-darksand-water2 rotate: false - xy: 2347, 291 + xy: 2863, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-darksand-water3 rotate: false - xy: 2381, 291 + xy: 2897, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-darksand2 rotate: false - xy: 2143, 291 + xy: 2659, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-darksand3 rotate: false - xy: 2177, 291 + xy: 2693, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-grass1 rotate: false - xy: 2415, 291 + xy: 2931, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 grass-icon-editor rotate: false - xy: 2415, 291 + xy: 2931, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-grass2 rotate: false - xy: 2449, 291 + xy: 2965, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-grass3 rotate: false - xy: 2483, 291 + xy: 2999, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-holostone1 rotate: false - xy: 2517, 291 + xy: 3033, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 holostone-icon-editor rotate: false - xy: 2517, 291 + xy: 3033, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-holostone2 rotate: false - xy: 2551, 291 + xy: 3067, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-holostone3 rotate: false - xy: 2585, 291 + xy: 3101, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-hotrock1 rotate: false - xy: 2619, 291 + xy: 3135, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 hotrock-icon-editor rotate: false - xy: 2619, 291 + xy: 3135, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-hotrock2 rotate: false - xy: 2653, 291 + xy: 3169, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-hotrock3 rotate: false - xy: 2687, 291 + xy: 3203, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice-snow1 rotate: false - xy: 2823, 291 + xy: 3339, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice-snow-icon-editor rotate: false - xy: 2823, 291 + xy: 3339, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice-snow2 rotate: false - xy: 2857, 291 + xy: 3373, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice-snow3 rotate: false - xy: 2891, 291 + xy: 3407, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice1 rotate: false - xy: 2721, 291 + xy: 3237, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice-icon-editor rotate: false - xy: 2721, 291 + xy: 3237, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice2 rotate: false - xy: 2755, 291 + xy: 3271, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice3 rotate: false - xy: 2789, 291 + xy: 3305, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ignarock1 rotate: false - xy: 2925, 291 + xy: 3441, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ignarock-icon-editor rotate: false - xy: 2925, 291 + xy: 3441, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ignarock2 rotate: false - xy: 2959, 291 + xy: 3475, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ignarock3 rotate: false - xy: 2993, 291 + xy: 3509, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-magmarock1 rotate: false - xy: 3027, 291 + xy: 3543, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 magmarock-icon-editor rotate: false - xy: 3027, 291 + xy: 3543, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-magmarock2 rotate: false - xy: 3061, 291 + xy: 3577, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-magmarock3 rotate: false - xy: 3095, 291 + xy: 3611, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor rotate: false - xy: 3129, 291 + xy: 3645, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-icon-editor rotate: false - xy: 3129, 291 + xy: 3645, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-2 rotate: false - xy: 3163, 291 + xy: 3679, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-2-icon-editor rotate: false - xy: 3163, 291 + xy: 3679, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-3 rotate: false - xy: 3197, 291 + xy: 3713, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-3-icon-editor rotate: false - xy: 3197, 291 + xy: 3713, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-5 rotate: false - xy: 3231, 291 + xy: 3747, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-5-icon-editor rotate: false - xy: 3231, 291 + xy: 3747, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-damaged1 rotate: false - xy: 3265, 291 + xy: 3781, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-damaged-icon-editor rotate: false - xy: 3265, 291 + xy: 3781, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-damaged2 rotate: false - xy: 3299, 291 + xy: 3815, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-damaged3 rotate: false - xy: 3333, 291 + xy: 3849, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-moss1 rotate: false - xy: 3367, 291 + xy: 3883, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 moss-icon-editor rotate: false - xy: 3367, 291 + xy: 3883, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-moss2 rotate: false - xy: 3401, 291 + xy: 3917, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-moss3 rotate: false - xy: 3435, 291 + xy: 3951, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-coal1 rotate: false - xy: 3469, 291 + xy: 3985, 289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-coal2 rotate: false - xy: 3503, 291 + xy: 163, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-coal3 rotate: false - xy: 3537, 291 + xy: 197, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-copper1 rotate: false - xy: 3571, 291 + xy: 231, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-copper2 rotate: false - xy: 3605, 291 + xy: 265, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-copper3 rotate: false - xy: 3639, 291 + xy: 299, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-lead1 rotate: false - xy: 3673, 291 + xy: 333, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-lead2 rotate: false - xy: 3707, 291 + xy: 367, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-lead3 rotate: false - xy: 3741, 291 + xy: 401, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-scrap1 rotate: false - xy: 3775, 291 + xy: 435, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-scrap2 rotate: false - xy: 3809, 291 + xy: 469, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-scrap3 rotate: false - xy: 3843, 291 + xy: 503, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-thorium1 rotate: false - xy: 3877, 291 + xy: 915, 65 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-thorium2 rotate: false - xy: 3911, 291 + xy: 915, 31 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-thorium3 rotate: false - xy: 3945, 291 + xy: 4025, 321 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-titanium1 rotate: false - xy: 3979, 291 + xy: 4059, 321 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-titanium2 rotate: false - xy: 4013, 291 + xy: 4019, 287 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-titanium3 rotate: false - xy: 4047, 291 + xy: 4053, 287 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-pebbles1 rotate: false - xy: 881, 65 + xy: 1837, 223 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-pebbles2 rotate: false - xy: 1123, 129 + xy: 1871, 223 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-pebbles3 rotate: false - xy: 1157, 129 + xy: 1905, 223 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-salt rotate: false - xy: 1191, 129 + xy: 945, 177 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 salt-icon-editor rotate: false - xy: 1191, 129 + xy: 945, 177 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand-water1 rotate: false - xy: 2037, 225 + xy: 979, 143 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand-water2 rotate: false - xy: 931, 81 + xy: 1013, 177 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand-water3 rotate: false - xy: 965, 81 + xy: 979, 109 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand1 rotate: false - xy: 1225, 129 + xy: 945, 143 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sand-icon-editor rotate: false - xy: 1225, 129 + xy: 945, 143 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand2 rotate: false - xy: 1259, 129 + xy: 979, 177 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand3 rotate: false - xy: 1293, 129 + xy: 945, 109 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-shale1 rotate: false - xy: 999, 81 + xy: 1013, 143 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shale-icon-editor rotate: false - xy: 999, 81 + xy: 1013, 143 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-shale2 rotate: false - xy: 1033, 81 + xy: 1047, 177 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-shale3 rotate: false - xy: 1067, 81 + xy: 1013, 109 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-slag rotate: false - xy: 1101, 89 + xy: 1047, 143 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 slag-icon-editor rotate: false - xy: 1101, 89 + xy: 1047, 143 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-snow1 rotate: false - xy: 1135, 95 + xy: 1047, 109 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-snow2 rotate: false - xy: 1169, 95 + xy: 949, 75 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-snow3 rotate: false - xy: 1203, 95 + xy: 949, 41 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-spawn rotate: false - xy: 1237, 95 + xy: 983, 75 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-spore-moss1 rotate: false - xy: 1271, 95 + xy: 983, 41 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spore-moss-icon-editor rotate: false - xy: 1271, 95 + xy: 983, 41 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-spore-moss2 rotate: false - xy: 1305, 95 + xy: 1017, 75 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-spore-moss3 rotate: false - xy: 1327, 129 + xy: 1017, 41 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-stone1 rotate: false - xy: 1339, 95 + xy: 1051, 75 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 stone-icon-editor rotate: false - xy: 1339, 95 + xy: 1051, 75 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-stone2 rotate: false - xy: 563, 1 + xy: 1051, 41 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-stone3 rotate: false - xy: 597, 1 + xy: 1423, 175 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-tainted-water rotate: false - xy: 631, 1 + xy: 1457, 175 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 tainted-water-icon-editor rotate: false - xy: 631, 1 + xy: 1457, 175 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-tar rotate: false - xy: 1101, 55 + xy: 1491, 175 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 tar-icon-editor rotate: false - xy: 1101, 55 + xy: 1491, 175 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-tendrils1 rotate: false - xy: 1135, 61 + xy: 1525, 183 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-tendrils2 rotate: false - xy: 1169, 61 + xy: 1085, 193 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-tendrils3 rotate: false - xy: 1203, 61 + xy: 1119, 193 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-water rotate: false - xy: 1237, 61 + xy: 1081, 159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 water-icon-editor rotate: false - xy: 1237, 61 + xy: 1081, 159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 exponential-reconstructor-icon-editor rotate: false - xy: 935, 263 + xy: 935, 261 size: 224, 224 orig: 224, 224 offset: 0, 0 index: -1 force-projector-icon-editor rotate: false - xy: 3279, 391 + xy: 3149, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fuse-icon-editor rotate: false - xy: 3377, 391 + xy: 3247, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 graphite-press-icon-editor rotate: false - xy: 749, 67 + xy: 2243, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 ground-factory-icon-editor rotate: false - xy: 3475, 391 + xy: 3345, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 hail-icon-editor rotate: false - xy: 1271, 61 + xy: 1081, 125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 icerocks-icon-editor rotate: false - xy: 1305, 61 + xy: 1115, 159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 illuminator-icon-editor rotate: false - xy: 1339, 61 + xy: 1115, 125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 impact-reactor-icon-editor rotate: false - xy: 1453, 359 + xy: 293, 35 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 incinerator-icon-editor rotate: false - xy: 2071, 225 + xy: 1153, 193 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 inverted-sorter-icon-editor rotate: false - xy: 1329, 193 + xy: 1149, 159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-source-icon-editor rotate: false - xy: 1363, 193 + xy: 1187, 193 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-void-icon-editor rotate: false - xy: 1397, 193 + xy: 1149, 125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 junction-icon-editor rotate: false - xy: 1431, 193 + xy: 1183, 159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 kiln-icon-editor rotate: false - xy: 815, 67 + xy: 2309, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 lancer-icon-editor rotate: false - xy: 2109, 325 + xy: 2375, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 large-overdrive-projector-icon-editor rotate: false - xy: 3573, 391 + xy: 3443, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-icon-editor rotate: false - xy: 3671, 391 + xy: 3541, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 launch-pad-icon-editor rotate: false - xy: 3769, 391 + xy: 3639, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 launch-pad-large-icon-editor rotate: false - xy: 455, 37 + xy: 1453, 357 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 liquid-junction-icon-editor rotate: false - xy: 1465, 193 + xy: 1221, 193 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-icon-editor rotate: false - xy: 1499, 193 + xy: 1183, 125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-source-icon-editor rotate: false - xy: 1533, 193 + xy: 1217, 159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-tank-icon-editor rotate: false - xy: 3867, 391 + xy: 3737, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 liquid-void-icon-editor rotate: false - xy: 1567, 193 + xy: 1255, 193 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mass-conveyor-icon-editor rotate: false - xy: 3965, 391 + xy: 3835, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mass-driver-icon-editor rotate: false - xy: 935, 165 + xy: 3933, 389 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mechanical-drill-icon-editor rotate: false - xy: 2175, 325 + xy: 2441, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-pump-icon-editor rotate: false - xy: 1601, 193 + xy: 1217, 125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 meltdown-icon-editor rotate: false - xy: 1583, 359 + xy: 423, 35 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 melter-icon-editor rotate: false - xy: 1635, 193 + xy: 1251, 159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mend-projector-icon-editor rotate: false - xy: 2241, 325 + xy: 2507, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mender-icon-editor rotate: false - xy: 1669, 193 + xy: 1289, 193 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 message-icon-editor rotate: false - xy: 1703, 193 + xy: 1323, 193 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 multi-press-icon-editor rotate: false - xy: 1033, 165 + xy: 553, 67 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 multiplicative-reconstructor-icon-editor rotate: false - xy: 163, 5 + xy: 1161, 325 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 naval-factory-icon-editor rotate: false - xy: 1161, 229 + xy: 651, 99 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-icon-editor rotate: false - xy: 1259, 229 + xy: 749, 99 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 overdrive-projector-icon-editor rotate: false - xy: 2307, 325 + xy: 2573, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 overflow-gate-icon-editor rotate: false - xy: 1737, 193 + xy: 1251, 125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 +parallax-icon-editor + rotate: false + xy: 2639, 323 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 payload-router-icon-editor rotate: false - xy: 1357, 261 + xy: 847, 99 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 pebbles-icon-editor rotate: false - xy: 1771, 193 + xy: 1285, 159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-icon-editor rotate: false - xy: 1805, 193 + xy: 1285, 125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-icon-editor rotate: false - xy: 1839, 193 + xy: 1319, 159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall-icon-editor rotate: false - xy: 1873, 193 + xy: 1319, 125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall-large-icon-editor rotate: false - xy: 2373, 325 + xy: 2705, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-icon-editor rotate: false - xy: 2439, 325 + xy: 2771, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pine-icon-editor rotate: false - xy: 881, 149 + xy: 935, 211 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 plastanium-compressor-icon-editor rotate: false - xy: 2505, 325 + xy: 2837, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 plastanium-conveyor-icon-editor rotate: false - xy: 1907, 193 + xy: 1353, 159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-wall-icon-editor rotate: false - xy: 1941, 193 + xy: 1353, 125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-wall-large-icon-editor rotate: false - xy: 2571, 325 + xy: 2903, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 plated-conduit-icon-editor rotate: false - xy: 1975, 193 + xy: 1387, 159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pneumatic-drill-icon-editor rotate: false - xy: 2637, 325 + xy: 2969, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 power-node-icon-editor rotate: false - xy: 1135, 27 + xy: 1387, 125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-node-large-icon-editor rotate: false - xy: 2703, 325 + xy: 3035, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 power-source-icon-editor rotate: false - xy: 1169, 27 + xy: 1421, 141 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-void-icon-editor rotate: false - xy: 1203, 27 + xy: 1455, 141 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-icon-editor rotate: false - xy: 1237, 27 + xy: 1489, 141 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulverizer-icon-editor rotate: false - xy: 1271, 27 + xy: 1085, 91 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pyratite-mixer-icon-editor rotate: false - xy: 2769, 325 + xy: 3101, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 repair-point-icon-editor rotate: false - xy: 1305, 27 + xy: 1085, 57 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 resupply-point-icon-editor rotate: false - xy: 2835, 325 + xy: 3167, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 ripple-icon-editor rotate: false - xy: 1455, 261 + xy: 1161, 227 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 rock-icon-editor rotate: false - xy: 881, 99 + xy: 1423, 209 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 rocks-icon-editor rotate: false - xy: 1339, 27 + xy: 1119, 91 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rotary-pump-icon-editor rotate: false - xy: 2901, 325 + xy: 3233, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 router-icon-editor rotate: false - xy: 1361, 159 + xy: 1119, 57 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rtg-generator-icon-editor rotate: false - xy: 2967, 325 + xy: 3299, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 saltrocks-icon-editor rotate: false - xy: 1395, 159 + xy: 1153, 91 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 salvo-icon-editor rotate: false - xy: 3033, 325 + xy: 3365, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 sand-boulder-icon-editor rotate: false - xy: 1429, 159 + xy: 1153, 57 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sand-water-icon-editor rotate: false - xy: 1463, 159 + xy: 1187, 91 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sandrocks-icon-editor rotate: false - xy: 1497, 159 + xy: 1187, 57 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scatter-icon-editor rotate: false - xy: 3099, 325 + xy: 3431, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scorch-icon-editor rotate: false - xy: 1531, 159 + xy: 1221, 91 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall-gigantic-icon-editor rotate: false - xy: 1713, 359 + xy: 1583, 357 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 scrap-wall-huge-icon-editor rotate: false - xy: 1553, 261 + xy: 1259, 227 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 scrap-wall-icon-editor rotate: false - xy: 1565, 159 + xy: 1221, 57 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall-large-icon-editor rotate: false - xy: 3165, 325 + xy: 3497, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 segment-icon-editor rotate: false - xy: 3231, 325 + xy: 3563, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 separator-icon-editor rotate: false - xy: 3297, 325 + xy: 3629, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 shale-boulder-icon-editor rotate: false - xy: 1599, 159 + xy: 1255, 91 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shalerocks-icon-editor rotate: false - xy: 1633, 159 + xy: 1255, 57 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shock-mine-icon-editor rotate: false - xy: 1667, 159 + xy: 1289, 91 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shrubs-icon-editor rotate: false - xy: 1701, 159 + xy: 1289, 57 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 silicon-crucible-icon-editor rotate: false - xy: 1651, 261 + xy: 1357, 259 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 silicon-smelter-icon-editor rotate: false - xy: 3363, 325 + xy: 3695, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 snow-icon-editor rotate: false - xy: 1735, 159 + xy: 1323, 91 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 snow-pine-icon-editor rotate: false - xy: 931, 115 + xy: 985, 211 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 snowrock-icon-editor rotate: false - xy: 981, 115 + xy: 1473, 209 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 snowrocks-icon-editor rotate: false - xy: 1769, 159 + xy: 1323, 57 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel-icon-editor rotate: false - xy: 1803, 159 + xy: 1357, 91 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel-large-icon-editor rotate: false - xy: 1749, 261 + xy: 1455, 259 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 sorter-icon-editor rotate: false - xy: 1837, 159 + xy: 1357, 57 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spawn-icon-editor rotate: false - xy: 1871, 159 + xy: 1391, 91 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spectre-icon-editor rotate: false - xy: 1843, 359 + xy: 1713, 357 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 spore-cluster-icon-editor rotate: false - xy: 1081, 123 + xy: 1523, 217 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 spore-pine-icon-editor rotate: false - xy: 1031, 115 + xy: 1035, 211 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spore-press-icon-editor rotate: false - xy: 3429, 325 + xy: 3761, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 sporerocks-icon-editor rotate: false - xy: 1905, 159 + xy: 1391, 57 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-tower-icon-editor rotate: false - xy: 3495, 325 + xy: 3827, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 surge-wall-icon-editor rotate: false - xy: 1939, 159 + xy: 1425, 107 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-wall-large-icon-editor rotate: false - xy: 3561, 325 + xy: 3893, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 swarmer-icon-editor rotate: false - xy: 3627, 325 + xy: 3959, 323 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 tendrils-icon-editor rotate: false - xy: 1973, 159 + xy: 1425, 73 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 tetrative-reconstructor-icon-editor rotate: false - xy: 645, 199 + xy: 645, 197 size: 288, 288 orig: 288, 288 offset: 0, 0 index: -1 thermal-generator-icon-editor rotate: false - xy: 3693, 325 + xy: 553, 1 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thermal-pump-icon-editor rotate: false - xy: 1847, 261 + xy: 1553, 259 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 thorium-reactor-icon-editor rotate: false - xy: 1945, 261 + xy: 1651, 259 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 thorium-wall-icon-editor rotate: false - xy: 2009, 191 + xy: 1459, 107 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium-wall-large-icon-editor rotate: false - xy: 3759, 325 + xy: 651, 33 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thruster-icon-editor rotate: false - xy: 1973, 359 + xy: 1843, 357 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 titanium-conveyor-icon-editor rotate: false - xy: 2043, 191 + xy: 1459, 73 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-wall-icon-editor rotate: false - xy: 2007, 157 + xy: 1493, 107 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-wall-large-icon-editor rotate: false - xy: 3825, 325 + xy: 717, 33 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 turbine-generator-icon-editor rotate: false - xy: 3891, 325 + xy: 783, 33 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 underflow-gate-icon-editor rotate: false - xy: 2041, 157 + xy: 1493, 73 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 unloader-icon-editor rotate: false - xy: 2077, 191 + xy: 1085, 23 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 vault-icon-editor rotate: false - xy: 585, 69 + xy: 1749, 259 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 water-extractor-icon-editor rotate: false - xy: 3957, 325 + xy: 849, 33 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wave-icon-editor rotate: false - xy: 4023, 325 + xy: 1357, 193 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 white-tree-dead-icon-editor rotate: false - xy: 1, 167 + xy: 1, 165 size: 320, 320 orig: 320, 320 offset: 0, 0 index: -1 white-tree-icon-editor rotate: false - xy: 323, 167 + xy: 323, 165 size: 320, 320 orig: 320, 320 offset: 0, 0 @@ -10509,2940 +11027,2940 @@ block-core-shard-xlarge orig: 48, 48 offset: 0, 0 index: -1 -block-core-silo-large +block-craters-large rotate: false xy: 3993, 418 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-core-silo-medium +block-craters-medium rotate: false xy: 3473, 384 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-core-silo-small +block-craters-small rotate: false xy: 3005, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-core-silo-tiny +block-craters-tiny rotate: false xy: 1613, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-core-silo-xlarge +block-craters-xlarge rotate: false xy: 1757, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-craters-large +block-cryofluidmixer-large rotate: false xy: 131, 1 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-craters-medium +block-cryofluidmixer-medium rotate: false xy: 3507, 384 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-craters-small +block-cryofluidmixer-small rotate: false xy: 3031, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-craters-tiny +block-cryofluidmixer-tiny rotate: false xy: 1613, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-craters-xlarge +block-cryofluidmixer-xlarge rotate: false xy: 1807, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-cryofluidmixer-large +block-cultivator-large rotate: false xy: 173, 1 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-cryofluidmixer-medium +block-cultivator-medium rotate: false xy: 3541, 384 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-cryofluidmixer-small +block-cultivator-small rotate: false xy: 3057, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-cryofluidmixer-tiny +block-cultivator-tiny rotate: false xy: 1631, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-cryofluidmixer-xlarge +block-cultivator-xlarge rotate: false xy: 1857, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-cultivator-large +block-cyclone-large rotate: false xy: 215, 1 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-cultivator-medium +block-cyclone-medium rotate: false xy: 3575, 384 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-cultivator-small +block-cyclone-small rotate: false xy: 3083, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-cultivator-tiny +block-cyclone-tiny rotate: false xy: 1631, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-cultivator-xlarge +block-cyclone-xlarge rotate: false xy: 1907, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-cyclone-large +block-dark-metal-large rotate: false xy: 845, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-cyclone-medium +block-dark-metal-medium rotate: false xy: 3609, 384 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-cyclone-small +block-dark-metal-small rotate: false xy: 3109, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-cyclone-tiny +block-dark-metal-tiny rotate: false xy: 1649, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-cyclone-xlarge +block-dark-metal-xlarge rotate: false xy: 1957, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-dark-metal-large +block-dark-panel-1-large rotate: false xy: 887, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-dark-metal-medium +block-dark-panel-1-medium rotate: false xy: 3643, 384 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-dark-metal-small +block-dark-panel-1-small rotate: false xy: 3135, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-dark-metal-tiny +block-dark-panel-1-tiny rotate: false xy: 1649, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-dark-metal-xlarge +block-dark-panel-1-xlarge rotate: false xy: 2007, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-dark-panel-1-large +block-dark-panel-2-large rotate: false xy: 929, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-dark-panel-1-medium +block-dark-panel-2-medium rotate: false xy: 3677, 384 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-dark-panel-1-small +block-dark-panel-2-small rotate: false xy: 3161, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-dark-panel-1-tiny +block-dark-panel-2-tiny rotate: false xy: 1667, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-dark-panel-1-xlarge +block-dark-panel-2-xlarge rotate: false xy: 2057, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-dark-panel-2-large +block-dark-panel-3-large rotate: false xy: 971, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-dark-panel-2-medium +block-dark-panel-3-medium rotate: false xy: 3711, 384 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-dark-panel-2-small +block-dark-panel-3-small rotate: false xy: 3187, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-dark-panel-2-tiny +block-dark-panel-3-tiny rotate: false xy: 1667, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-dark-panel-2-xlarge +block-dark-panel-3-xlarge rotate: false xy: 2107, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-dark-panel-3-large +block-dark-panel-4-large rotate: false xy: 1013, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-dark-panel-3-medium +block-dark-panel-4-medium rotate: false xy: 3745, 384 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-dark-panel-3-small +block-dark-panel-4-small rotate: false xy: 3213, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-dark-panel-3-tiny +block-dark-panel-4-tiny rotate: false xy: 1685, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-dark-panel-3-xlarge +block-dark-panel-4-xlarge rotate: false xy: 2157, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-dark-panel-4-large +block-dark-panel-5-large rotate: false xy: 1055, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-dark-panel-4-medium +block-dark-panel-5-medium rotate: false xy: 3779, 384 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-dark-panel-4-small +block-dark-panel-5-small rotate: false xy: 3239, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-dark-panel-4-tiny +block-dark-panel-5-tiny rotate: false xy: 1685, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-dark-panel-4-xlarge +block-dark-panel-5-xlarge rotate: false xy: 2207, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-dark-panel-5-large +block-dark-panel-6-large rotate: false xy: 1097, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-dark-panel-5-medium +block-dark-panel-6-medium rotate: false xy: 3813, 384 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-dark-panel-5-small +block-dark-panel-6-small rotate: false xy: 3265, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-dark-panel-5-tiny +block-dark-panel-6-tiny rotate: false xy: 1703, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 -block-dark-panel-5-xlarge +block-dark-panel-6-xlarge rotate: false xy: 2257, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -block-dark-panel-6-large +block-darksand-large rotate: false xy: 1139, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-dark-panel-6-medium +block-darksand-medium rotate: false xy: 3847, 384 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-dark-panel-6-small +block-darksand-small rotate: false xy: 3291, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-dark-panel-6-tiny - rotate: false - xy: 1703, 130 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -block-dark-panel-6-xlarge - rotate: false - xy: 2307, 460 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -block-darksand-large +block-darksand-tainted-water-large rotate: false xy: 1181, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -block-darksand-medium +block-darksand-tainted-water-medium rotate: false xy: 3881, 384 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -block-darksand-small +block-darksand-tainted-water-small rotate: false xy: 3317, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -block-darksand-tainted-water-large - rotate: false - xy: 1223, 368 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -block-darksand-tainted-water-medium - rotate: false - xy: 3915, 384 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -block-darksand-tainted-water-small - rotate: false - xy: 3343, 256 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 block-darksand-tainted-water-tiny rotate: false - xy: 1721, 148 + xy: 1703, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-darksand-tainted-water-xlarge rotate: false - xy: 2357, 460 + xy: 2307, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-darksand-tiny rotate: false - xy: 1721, 130 + xy: 1721, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-darksand-water-large rotate: false - xy: 1265, 368 + xy: 1223, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-darksand-water-medium rotate: false - xy: 3949, 384 + xy: 3915, 384 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-darksand-water-small rotate: false - xy: 3369, 256 + xy: 3343, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-darksand-water-tiny rotate: false - xy: 1739, 148 + xy: 1721, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-darksand-water-xlarge rotate: false - xy: 2407, 460 + xy: 2357, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-darksand-xlarge rotate: false - xy: 2457, 460 + xy: 2407, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-data-processor-large rotate: false - xy: 1307, 368 + xy: 1265, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-data-processor-medium rotate: false - xy: 3983, 384 + xy: 3949, 384 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-data-processor-small rotate: false - xy: 3395, 256 + xy: 3369, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-data-processor-tiny rotate: false - xy: 1739, 130 + xy: 1739, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-data-processor-xlarge rotate: false - xy: 2507, 460 + xy: 2457, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-deepwater-large rotate: false - xy: 1349, 368 + xy: 1307, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-deepwater-medium rotate: false - xy: 938, 166 + xy: 3983, 384 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-deepwater-small rotate: false - xy: 3421, 256 + xy: 3395, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-deepwater-tiny rotate: false - xy: 1757, 148 + xy: 1739, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-deepwater-xlarge rotate: false - xy: 2557, 460 + xy: 2507, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-differential-generator-large rotate: false - xy: 1391, 368 + xy: 1349, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-differential-generator-medium rotate: false - xy: 972, 166 + xy: 938, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-differential-generator-small rotate: false - xy: 3447, 256 + xy: 3421, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-differential-generator-tiny rotate: false - xy: 1757, 130 + xy: 1757, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-differential-generator-xlarge rotate: false - xy: 2607, 460 + xy: 2557, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-diode-large rotate: false - xy: 1433, 368 + xy: 1391, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-diode-medium rotate: false - xy: 1006, 166 + xy: 972, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-diode-small rotate: false - xy: 3473, 256 + xy: 3447, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-diode-tiny rotate: false - xy: 1775, 148 + xy: 1757, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-diode-xlarge rotate: false - xy: 2657, 460 + xy: 2607, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-disassembler-large rotate: false - xy: 1475, 368 + xy: 1433, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-disassembler-medium rotate: false - xy: 1040, 166 + xy: 1006, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-disassembler-small rotate: false - xy: 3499, 256 + xy: 3473, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-disassembler-tiny rotate: false - xy: 1775, 130 + xy: 1775, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-disassembler-xlarge rotate: false - xy: 2707, 460 + xy: 2657, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-distributor-large rotate: false - xy: 1517, 368 + xy: 1475, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-distributor-medium rotate: false - xy: 1074, 166 + xy: 1040, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-distributor-small rotate: false - xy: 3525, 256 + xy: 3499, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-distributor-tiny rotate: false - xy: 1793, 148 + xy: 1775, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-distributor-xlarge rotate: false - xy: 2757, 460 + xy: 2707, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-door-large rotate: false - xy: 1559, 368 + xy: 1517, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-door-large-large rotate: false - xy: 1601, 368 + xy: 1559, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-door-large-medium rotate: false - xy: 1108, 166 + xy: 1074, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-door-large-small rotate: false - xy: 3551, 256 + xy: 3525, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-door-large-tiny rotate: false - xy: 1793, 130 + xy: 1793, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-door-large-xlarge rotate: false - xy: 2807, 460 + xy: 2757, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-door-medium rotate: false - xy: 1142, 166 + xy: 1108, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-door-small rotate: false - xy: 3577, 256 + xy: 3551, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-door-tiny rotate: false - xy: 1811, 148 + xy: 1793, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-door-xlarge rotate: false - xy: 2857, 460 + xy: 2807, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-dunerocks-large rotate: false - xy: 1643, 368 + xy: 1601, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-dunerocks-medium rotate: false - xy: 1176, 166 + xy: 1142, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-dunerocks-small rotate: false - xy: 3603, 256 + xy: 3577, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-dunerocks-tiny rotate: false - xy: 1811, 130 + xy: 1811, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-dunerocks-xlarge rotate: false - xy: 2907, 460 + xy: 2857, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-duo-large rotate: false - xy: 1685, 368 + xy: 1643, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-duo-medium rotate: false - xy: 1210, 166 + xy: 1176, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-duo-small rotate: false - xy: 3629, 256 + xy: 3603, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-duo-tiny rotate: false - xy: 1829, 148 + xy: 1811, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-duo-xlarge rotate: false - xy: 2957, 460 + xy: 2907, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-exponential-reconstructor-large rotate: false - xy: 1727, 368 + xy: 1685, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-exponential-reconstructor-medium rotate: false - xy: 1244, 166 + xy: 1210, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-exponential-reconstructor-small rotate: false - xy: 3655, 256 + xy: 3629, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-exponential-reconstructor-tiny rotate: false - xy: 1829, 130 + xy: 1829, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-exponential-reconstructor-xlarge rotate: false - xy: 3007, 460 + xy: 2957, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-force-projector-large rotate: false - xy: 1769, 368 + xy: 1727, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-force-projector-medium rotate: false - xy: 1278, 166 + xy: 1244, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-force-projector-small rotate: false - xy: 2845, 230 + xy: 3655, 256 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-force-projector-tiny rotate: false - xy: 1847, 148 + xy: 1829, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-force-projector-xlarge rotate: false - xy: 3057, 460 + xy: 3007, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-fuse-large rotate: false - xy: 1811, 368 + xy: 1769, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-fuse-medium rotate: false - xy: 1312, 166 + xy: 1278, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-fuse-small rotate: false - xy: 2871, 230 + xy: 2845, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-fuse-tiny rotate: false - xy: 1847, 130 + xy: 1847, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-fuse-xlarge rotate: false - xy: 3107, 460 + xy: 3057, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-graphite-press-large rotate: false - xy: 1853, 368 + xy: 1811, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-graphite-press-medium rotate: false - xy: 1346, 166 + xy: 1312, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-graphite-press-small rotate: false - xy: 2897, 230 + xy: 2871, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-graphite-press-tiny rotate: false - xy: 1865, 148 + xy: 1847, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-graphite-press-xlarge rotate: false - xy: 3157, 460 + xy: 3107, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-grass-large rotate: false - xy: 1895, 368 + xy: 1853, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-grass-medium rotate: false - xy: 1380, 166 + xy: 1346, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-grass-small rotate: false - xy: 2923, 230 + xy: 2897, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-grass-tiny rotate: false - xy: 1865, 130 + xy: 1865, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-grass-xlarge rotate: false - xy: 3207, 460 + xy: 3157, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ground-factory-large rotate: false - xy: 1937, 368 + xy: 1895, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ground-factory-medium rotate: false - xy: 1414, 166 + xy: 1380, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ground-factory-small rotate: false - xy: 2949, 230 + xy: 2923, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ground-factory-tiny rotate: false - xy: 1883, 148 + xy: 1865, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ground-factory-xlarge rotate: false - xy: 3257, 460 + xy: 3207, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-hail-large rotate: false - xy: 1979, 368 + xy: 1937, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-hail-medium rotate: false - xy: 1448, 166 + xy: 1414, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-hail-small rotate: false - xy: 2975, 230 + xy: 2949, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-hail-tiny rotate: false - xy: 1883, 130 + xy: 1883, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-hail-xlarge rotate: false - xy: 3307, 460 + xy: 3257, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-holostone-large rotate: false - xy: 2021, 368 + xy: 1979, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-holostone-medium rotate: false - xy: 1482, 166 + xy: 1448, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-holostone-small rotate: false - xy: 3001, 230 + xy: 2975, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-holostone-tiny rotate: false - xy: 1901, 148 + xy: 1883, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-holostone-xlarge rotate: false - xy: 3357, 460 + xy: 3307, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-hotrock-large rotate: false - xy: 2063, 368 + xy: 2021, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-hotrock-medium rotate: false - xy: 1516, 166 + xy: 1482, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-hotrock-small rotate: false - xy: 3027, 230 + xy: 3001, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-hotrock-tiny rotate: false - xy: 1901, 130 + xy: 1901, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-hotrock-xlarge rotate: false - xy: 3407, 460 + xy: 3357, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ice-large rotate: false - xy: 2105, 368 + xy: 2063, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ice-medium rotate: false - xy: 1550, 166 + xy: 1516, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ice-small rotate: false - xy: 3053, 230 + xy: 3027, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ice-snow-large rotate: false - xy: 2147, 368 + xy: 2105, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ice-snow-medium rotate: false - xy: 1584, 166 + xy: 1550, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ice-snow-small rotate: false - xy: 3079, 230 + xy: 3053, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ice-snow-tiny rotate: false - xy: 1919, 148 + xy: 1901, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ice-snow-xlarge rotate: false - xy: 3457, 460 + xy: 3407, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ice-tiny rotate: false - xy: 1919, 130 + xy: 1919, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ice-xlarge rotate: false - xy: 3507, 460 + xy: 3457, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-icerocks-large rotate: false - xy: 2189, 368 + xy: 2147, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-icerocks-medium rotate: false - xy: 1618, 166 + xy: 1584, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-icerocks-small rotate: false - xy: 3105, 230 + xy: 3079, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-icerocks-tiny rotate: false - xy: 1937, 148 + xy: 1919, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-icerocks-xlarge rotate: false - xy: 3557, 460 + xy: 3507, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ignarock-large rotate: false - xy: 2231, 368 + xy: 2189, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ignarock-medium rotate: false - xy: 1652, 166 + xy: 1618, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ignarock-small rotate: false - xy: 3131, 230 + xy: 3105, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ignarock-tiny rotate: false - xy: 1937, 130 + xy: 1937, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ignarock-xlarge rotate: false - xy: 3607, 460 + xy: 3557, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-illuminator-large rotate: false - xy: 2273, 368 + xy: 2231, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-illuminator-medium rotate: false - xy: 1686, 166 + xy: 1652, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-illuminator-small rotate: false - xy: 3157, 230 + xy: 3131, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-illuminator-tiny rotate: false - xy: 1955, 148 + xy: 1937, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-illuminator-xlarge rotate: false - xy: 3657, 460 + xy: 3607, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-impact-reactor-large rotate: false - xy: 2315, 368 + xy: 2273, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-impact-reactor-medium rotate: false - xy: 1720, 166 + xy: 1686, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-impact-reactor-small rotate: false - xy: 3183, 230 + xy: 3157, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-impact-reactor-tiny rotate: false - xy: 1955, 130 + xy: 1955, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-impact-reactor-xlarge rotate: false - xy: 3707, 460 + xy: 3657, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-incinerator-large rotate: false - xy: 2357, 368 + xy: 2315, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-incinerator-medium rotate: false - xy: 1754, 166 + xy: 1720, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-incinerator-small rotate: false - xy: 3209, 230 + xy: 3183, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-incinerator-tiny rotate: false - xy: 1973, 148 + xy: 1955, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-incinerator-xlarge rotate: false - xy: 3757, 460 + xy: 3707, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-inverted-sorter-large rotate: false - xy: 2399, 368 + xy: 2357, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-inverted-sorter-medium rotate: false - xy: 1788, 166 + xy: 1754, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-inverted-sorter-small rotate: false - xy: 3235, 230 + xy: 3209, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-inverted-sorter-tiny rotate: false - xy: 1973, 130 + xy: 1973, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-inverted-sorter-xlarge rotate: false - xy: 3807, 460 + xy: 3757, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-item-source-large rotate: false - xy: 2441, 368 + xy: 2399, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-item-source-medium rotate: false - xy: 1822, 166 + xy: 1788, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-item-source-small rotate: false - xy: 3261, 230 + xy: 3235, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-item-source-tiny rotate: false - xy: 1991, 148 + xy: 1973, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-item-source-xlarge rotate: false - xy: 3857, 460 + xy: 3807, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-item-void-large rotate: false - xy: 2483, 368 + xy: 2441, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-item-void-medium rotate: false - xy: 1856, 166 + xy: 1822, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-item-void-small rotate: false - xy: 3287, 230 + xy: 3261, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-item-void-tiny rotate: false - xy: 1991, 130 + xy: 1991, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-item-void-xlarge rotate: false - xy: 3907, 460 + xy: 3857, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-junction-large rotate: false - xy: 2525, 368 + xy: 2483, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-junction-medium rotate: false - xy: 1890, 166 + xy: 1856, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-junction-small rotate: false - xy: 3313, 230 + xy: 3287, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-junction-tiny rotate: false - xy: 2009, 148 + xy: 1991, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-junction-xlarge rotate: false - xy: 3957, 460 + xy: 3907, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-kiln-large rotate: false - xy: 2567, 368 + xy: 2525, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-kiln-medium rotate: false - xy: 1924, 166 + xy: 1890, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-kiln-small rotate: false - xy: 3339, 230 + xy: 3313, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-kiln-tiny rotate: false - xy: 2009, 130 + xy: 2009, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-kiln-xlarge rotate: false - xy: 4007, 460 + xy: 3957, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-lancer-large rotate: false - xy: 2609, 368 + xy: 2567, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-lancer-medium rotate: false - xy: 1958, 166 + xy: 1924, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-lancer-small rotate: false - xy: 3365, 230 + xy: 3339, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-lancer-tiny rotate: false - xy: 2027, 148 + xy: 2009, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-lancer-xlarge rotate: false - xy: 345, 351 + xy: 4007, 460 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-large-overdrive-projector-large rotate: false - xy: 2651, 368 + xy: 2609, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-large-overdrive-projector-medium rotate: false - xy: 1992, 166 + xy: 1958, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-large-overdrive-projector-small rotate: false - xy: 3391, 230 + xy: 3365, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-large-overdrive-projector-tiny rotate: false - xy: 2027, 130 + xy: 2027, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-large-overdrive-projector-xlarge rotate: false - xy: 395, 351 + xy: 345, 351 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-laser-drill-large rotate: false - xy: 2693, 368 + xy: 2651, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-laser-drill-medium rotate: false - xy: 2026, 166 + xy: 1992, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-laser-drill-small rotate: false - xy: 3417, 230 + xy: 3391, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-laser-drill-tiny rotate: false - xy: 2045, 148 + xy: 2027, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-laser-drill-xlarge rotate: false - xy: 445, 351 + xy: 395, 351 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-launch-pad-large rotate: false - xy: 2735, 368 + xy: 2693, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-launch-pad-large-large rotate: false - xy: 2777, 368 + xy: 2735, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-launch-pad-large-medium rotate: false - xy: 2060, 166 + xy: 2026, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-launch-pad-large-small rotate: false - xy: 3443, 230 + xy: 3417, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-launch-pad-large-tiny rotate: false - xy: 2045, 130 + xy: 2045, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-launch-pad-large-xlarge rotate: false - xy: 495, 351 + xy: 445, 351 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-launch-pad-medium rotate: false - xy: 2203, 276 + xy: 2060, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-launch-pad-small rotate: false - xy: 3469, 230 + xy: 3443, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-launch-pad-tiny rotate: false - xy: 2063, 148 + xy: 2045, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-launch-pad-xlarge rotate: false - xy: 545, 351 + xy: 495, 351 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-liquid-junction-large rotate: false - xy: 2819, 368 + xy: 2777, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-liquid-junction-medium rotate: false - xy: 2237, 276 + xy: 2203, 276 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-liquid-junction-small rotate: false - xy: 3495, 230 + xy: 3469, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-liquid-junction-tiny rotate: false - xy: 2063, 130 + xy: 2063, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-liquid-junction-xlarge rotate: false - xy: 595, 351 + xy: 545, 351 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-liquid-router-large rotate: false - xy: 859, 326 + xy: 2819, 368 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-liquid-router-medium rotate: false - xy: 2271, 276 + xy: 2237, 276 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-liquid-router-small rotate: false - xy: 3521, 230 + xy: 3495, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-liquid-router-tiny rotate: false - xy: 2081, 148 + xy: 2063, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-liquid-router-xlarge rotate: false - xy: 645, 351 + xy: 595, 351 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-liquid-source-large rotate: false - xy: 859, 284 + xy: 859, 326 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-liquid-source-medium rotate: false - xy: 2305, 276 + xy: 2271, 276 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-liquid-source-small rotate: false - xy: 3547, 230 + xy: 3521, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-liquid-source-tiny rotate: false - xy: 2081, 130 + xy: 2081, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-liquid-source-xlarge rotate: false - xy: 695, 351 + xy: 645, 351 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-liquid-tank-large rotate: false - xy: 901, 326 + xy: 859, 284 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-liquid-tank-medium rotate: false - xy: 2339, 276 + xy: 2305, 276 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-liquid-tank-small rotate: false - xy: 3573, 230 + xy: 3547, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-liquid-tank-tiny rotate: false - xy: 2099, 148 + xy: 2081, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-liquid-tank-xlarge rotate: false - xy: 231, 93 + xy: 695, 351 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-liquid-void-large rotate: false - xy: 859, 242 + xy: 901, 326 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-liquid-void-medium rotate: false - xy: 2373, 276 + xy: 2339, 276 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-liquid-void-small rotate: false - xy: 3599, 230 + xy: 3573, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-liquid-void-tiny rotate: false - xy: 2099, 130 + xy: 2099, 148 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-liquid-void-xlarge rotate: false - xy: 231, 43 + xy: 231, 93 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-magmarock-large rotate: false - xy: 901, 284 + xy: 859, 242 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-magmarock-medium rotate: false - xy: 2407, 276 + xy: 2373, 276 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-magmarock-small rotate: false - xy: 3625, 230 + xy: 3599, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-magmarock-tiny rotate: false - xy: 3833, 224 + xy: 2099, 130 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-magmarock-xlarge rotate: false - xy: 745, 351 + xy: 231, 43 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-mass-conveyor-large rotate: false - xy: 943, 326 + xy: 901, 284 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-mass-conveyor-medium rotate: false - xy: 2441, 276 + xy: 2407, 276 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-mass-conveyor-small rotate: false - xy: 3651, 230 + xy: 3625, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-mass-conveyor-tiny rotate: false - xy: 1471, 106 + xy: 3833, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-mass-conveyor-xlarge rotate: false - xy: 281, 104 + xy: 745, 351 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-mass-driver-large rotate: false - xy: 859, 200 + xy: 943, 326 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-mass-driver-medium rotate: false - xy: 2475, 276 + xy: 2441, 276 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-mass-driver-small rotate: false - xy: 2162, 127 + xy: 3651, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-mass-driver-tiny rotate: false - xy: 2195, 224 + xy: 1471, 106 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-mass-driver-xlarge rotate: false - xy: 281, 54 + xy: 281, 104 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-mechanical-drill-large rotate: false - xy: 901, 242 + xy: 859, 200 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-mechanical-drill-medium rotate: false - xy: 2509, 276 + xy: 2475, 276 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-mechanical-drill-small rotate: false - xy: 2188, 127 + xy: 2162, 127 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-mechanical-drill-tiny rotate: false - xy: 2213, 224 + xy: 2195, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-mechanical-drill-xlarge rotate: false - xy: 795, 363 + xy: 281, 54 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-mechanical-pump-large rotate: false - xy: 943, 284 + xy: 901, 242 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-mechanical-pump-medium rotate: false - xy: 2543, 276 + xy: 2509, 276 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-mechanical-pump-small rotate: false - xy: 4069, 455 + xy: 2188, 127 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-mechanical-pump-tiny rotate: false - xy: 2231, 224 + xy: 2213, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-mechanical-pump-xlarge rotate: false - xy: 309, 301 + xy: 795, 363 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-meltdown-large rotate: false - xy: 985, 326 + xy: 943, 284 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-meltdown-medium rotate: false - xy: 2617, 300 + xy: 2543, 276 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-meltdown-small rotate: false - xy: 4069, 429 + xy: 4069, 455 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-meltdown-tiny rotate: false - xy: 2249, 224 + xy: 2231, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-meltdown-xlarge rotate: false - xy: 309, 251 + xy: 309, 301 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-melter-large rotate: false - xy: 901, 200 + xy: 985, 326 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-melter-medium rotate: false - xy: 2651, 300 + xy: 2617, 300 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-melter-small rotate: false - xy: 3677, 230 + xy: 4069, 429 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-melter-tiny rotate: false - xy: 2267, 224 + xy: 2249, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-melter-xlarge rotate: false - xy: 359, 301 + xy: 309, 251 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-mend-projector-large rotate: false - xy: 943, 242 + xy: 901, 200 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-mend-projector-medium rotate: false - xy: 2685, 300 + xy: 2651, 300 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-mend-projector-small rotate: false - xy: 3703, 250 + xy: 3677, 230 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-mend-projector-tiny rotate: false - xy: 2285, 224 + xy: 2267, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-mend-projector-xlarge rotate: false - xy: 309, 201 + xy: 359, 301 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-mender-large rotate: false - xy: 985, 284 + xy: 943, 242 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-mender-medium rotate: false - xy: 2719, 300 + xy: 2685, 300 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-mender-small rotate: false - xy: 3729, 250 + xy: 3703, 250 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-mender-tiny rotate: false - xy: 2303, 224 + xy: 2285, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-mender-xlarge rotate: false - xy: 359, 251 + xy: 309, 201 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-message-large rotate: false - xy: 1027, 326 + xy: 985, 284 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-message-medium rotate: false - xy: 2753, 300 + xy: 2719, 300 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-message-small rotate: false - xy: 3755, 250 + xy: 3729, 250 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-message-tiny rotate: false - xy: 2321, 224 + xy: 2303, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-message-xlarge rotate: false - xy: 409, 301 + xy: 359, 251 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-metal-floor-2-large rotate: false - xy: 943, 200 + xy: 1027, 326 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-metal-floor-2-medium rotate: false - xy: 2787, 300 + xy: 2753, 300 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-metal-floor-2-small rotate: false - xy: 3703, 224 + xy: 3755, 250 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-metal-floor-2-tiny rotate: false - xy: 2339, 224 + xy: 2321, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-metal-floor-2-xlarge rotate: false - xy: 359, 201 + xy: 409, 301 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-metal-floor-3-large rotate: false - xy: 985, 242 + xy: 943, 200 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-metal-floor-3-medium rotate: false - xy: 2821, 300 + xy: 2787, 300 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-metal-floor-3-small rotate: false - xy: 3729, 224 + xy: 3703, 224 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-metal-floor-3-tiny rotate: false - xy: 2357, 224 + xy: 2339, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-metal-floor-3-xlarge rotate: false - xy: 409, 251 + xy: 359, 201 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-metal-floor-5-large rotate: false - xy: 1027, 284 + xy: 985, 242 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-metal-floor-5-medium rotate: false - xy: 2094, 166 + xy: 2821, 300 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-metal-floor-5-small rotate: false - xy: 3755, 224 + xy: 3729, 224 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-metal-floor-5-tiny rotate: false - xy: 2375, 224 + xy: 2357, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-metal-floor-5-xlarge rotate: false - xy: 459, 301 + xy: 409, 251 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-metal-floor-damaged-large rotate: false - xy: 1069, 326 + xy: 1027, 284 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-metal-floor-damaged-medium rotate: false - xy: 881, 140 + xy: 2094, 166 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-metal-floor-damaged-small rotate: false - xy: 3781, 250 + xy: 3755, 224 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-metal-floor-damaged-tiny rotate: false - xy: 2393, 224 + xy: 2375, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-metal-floor-damaged-xlarge rotate: false - xy: 409, 201 + xy: 459, 301 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-metal-floor-large rotate: false - xy: 985, 200 + xy: 1069, 326 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-metal-floor-medium rotate: false - xy: 881, 106 + xy: 881, 140 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-metal-floor-small rotate: false - xy: 3781, 224 + xy: 3781, 250 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-metal-floor-tiny rotate: false - xy: 2411, 224 + xy: 2393, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-metal-floor-xlarge rotate: false - xy: 459, 251 + xy: 409, 201 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-moss-large rotate: false - xy: 1027, 242 + xy: 985, 200 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-moss-medium rotate: false - xy: 881, 72 + xy: 881, 106 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-moss-small rotate: false - xy: 3807, 252 + xy: 3781, 224 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-moss-tiny rotate: false - xy: 2429, 224 + xy: 2411, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-moss-xlarge rotate: false - xy: 509, 301 + xy: 459, 251 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-multi-press-large rotate: false - xy: 1069, 284 + xy: 1027, 242 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-multi-press-medium rotate: false - xy: 881, 38 + xy: 881, 72 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-multi-press-small rotate: false - xy: 3807, 226 + xy: 3807, 252 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-multi-press-tiny rotate: false - xy: 2447, 224 + xy: 2429, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-multi-press-xlarge rotate: false - xy: 459, 201 + xy: 509, 301 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-multiplicative-reconstructor-large rotate: false - xy: 1111, 326 + xy: 1069, 284 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-multiplicative-reconstructor-medium rotate: false - xy: 881, 4 + xy: 881, 38 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-multiplicative-reconstructor-small rotate: false - xy: 915, 140 + xy: 3807, 226 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-multiplicative-reconstructor-tiny rotate: false - xy: 2465, 224 + xy: 2447, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-multiplicative-reconstructor-xlarge rotate: false - xy: 509, 251 + xy: 459, 201 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-naval-factory-large rotate: false - xy: 1027, 200 + xy: 1111, 326 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-naval-factory-medium rotate: false - xy: 2577, 271 + xy: 881, 4 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-naval-factory-small rotate: false - xy: 941, 140 + xy: 915, 140 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-naval-factory-tiny rotate: false - xy: 2483, 224 + xy: 2465, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-naval-factory-xlarge rotate: false - xy: 559, 301 + xy: 509, 251 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-oil-extractor-large rotate: false - xy: 1069, 242 + xy: 1027, 200 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-oil-extractor-medium rotate: false - xy: 2611, 266 + xy: 2577, 271 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-oil-extractor-small rotate: false - xy: 915, 114 + xy: 941, 140 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-oil-extractor-tiny rotate: false - xy: 2501, 224 + xy: 2483, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-oil-extractor-xlarge rotate: false - xy: 509, 201 + xy: 559, 301 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ore-coal-large rotate: false - xy: 1111, 284 + xy: 1069, 242 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ore-coal-medium rotate: false - xy: 2645, 266 + xy: 2611, 266 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-coal-small rotate: false - xy: 967, 140 + xy: 915, 114 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ore-coal-tiny rotate: false - xy: 2519, 224 + xy: 2501, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ore-coal-xlarge rotate: false - xy: 559, 251 + xy: 509, 201 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ore-copper-large rotate: false - xy: 1153, 326 + xy: 1111, 284 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ore-copper-medium rotate: false - xy: 2679, 266 + xy: 2645, 266 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-copper-small rotate: false - xy: 915, 88 + xy: 967, 140 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ore-copper-tiny rotate: false - xy: 2537, 224 + xy: 2519, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ore-copper-xlarge rotate: false - xy: 609, 301 + xy: 559, 251 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ore-lead-large rotate: false - xy: 1069, 200 + xy: 1153, 326 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ore-lead-medium rotate: false - xy: 2713, 266 + xy: 2679, 266 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-lead-small rotate: false - xy: 941, 114 + xy: 915, 88 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ore-lead-tiny rotate: false - xy: 2555, 224 + xy: 2537, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ore-lead-xlarge rotate: false - xy: 559, 201 + xy: 609, 301 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ore-scrap-large rotate: false - xy: 1111, 242 + xy: 1069, 200 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ore-scrap-medium rotate: false - xy: 2747, 266 + xy: 2713, 266 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-scrap-small rotate: false - xy: 993, 140 + xy: 941, 114 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ore-scrap-tiny rotate: false - xy: 2196, 206 + xy: 2555, 224 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ore-scrap-xlarge rotate: false - xy: 609, 251 + xy: 559, 201 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ore-thorium-large rotate: false - xy: 1153, 284 + xy: 1111, 242 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ore-thorium-medium rotate: false - xy: 2781, 266 + xy: 2747, 266 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-thorium-small rotate: false - xy: 915, 62 + xy: 993, 140 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ore-thorium-tiny rotate: false - xy: 2214, 206 + xy: 2196, 206 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ore-thorium-xlarge rotate: false - xy: 659, 301 + xy: 609, 251 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-ore-titanium-large rotate: false - xy: 1195, 326 + xy: 1153, 284 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-ore-titanium-medium rotate: false - xy: 2815, 266 + xy: 2781, 266 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-ore-titanium-small rotate: false - xy: 941, 88 + xy: 915, 62 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-ore-titanium-tiny rotate: false - xy: 2196, 188 + xy: 2214, 206 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-ore-titanium-xlarge rotate: false - xy: 609, 201 + xy: 659, 301 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-overdrive-projector-large rotate: false - xy: 1111, 200 + xy: 1195, 326 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-overdrive-projector-medium rotate: false - xy: 4035, 426 + xy: 2815, 266 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-overdrive-projector-small rotate: false - xy: 967, 114 + xy: 941, 88 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-overdrive-projector-tiny rotate: false - xy: 2214, 188 + xy: 2196, 188 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-overdrive-projector-xlarge rotate: false - xy: 659, 251 + xy: 609, 201 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 block-overflow-gate-large rotate: false - xy: 1153, 242 + xy: 1111, 200 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 block-overflow-gate-medium rotate: false - xy: 4017, 384 + xy: 4035, 426 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-overflow-gate-small rotate: false - xy: 1019, 140 + xy: 967, 114 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 block-overflow-gate-tiny rotate: false - xy: 2232, 206 + xy: 2214, 188 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 block-overflow-gate-xlarge + rotate: false + xy: 659, 251 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +block-parallax-large + rotate: false + xy: 1153, 242 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +block-parallax-medium + rotate: false + xy: 4017, 384 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +block-parallax-small + rotate: false + xy: 1019, 140 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +block-parallax-tiny + rotate: false + xy: 2232, 206 + size: 16, 16 + orig: 16, 16 + offset: 0, 0 + index: -1 +block-parallax-xlarge rotate: false xy: 709, 301 size: 48, 48 diff --git a/core/assets/sprites/sprites.png b/core/assets/sprites/sprites.png index 027ec6b153..5850b6cf32 100644 Binary files a/core/assets/sprites/sprites.png and b/core/assets/sprites/sprites.png differ diff --git a/core/assets/sprites/sprites2.png b/core/assets/sprites/sprites2.png index 1a34438d80..33652412a6 100644 Binary files a/core/assets/sprites/sprites2.png and b/core/assets/sprites/sprites2.png differ diff --git a/core/assets/sprites/sprites3.png b/core/assets/sprites/sprites3.png index ca73704f2c..64ad51443a 100644 Binary files a/core/assets/sprites/sprites3.png and b/core/assets/sprites/sprites3.png differ diff --git a/core/assets/sprites/sprites4.png b/core/assets/sprites/sprites4.png index c827aad9a0..572a1ee374 100644 Binary files a/core/assets/sprites/sprites4.png and b/core/assets/sprites/sprites4.png differ diff --git a/core/assets/sprites/sprites5.png b/core/assets/sprites/sprites5.png index aaebb47d17..1f70cc9521 100644 Binary files a/core/assets/sprites/sprites5.png and b/core/assets/sprites/sprites5.png differ diff --git a/core/src/mindustry/ClientLauncher.java b/core/src/mindustry/ClientLauncher.java index 461b5014c4..9c42f6d9ea 100644 --- a/core/src/mindustry/ClientLauncher.java +++ b/core/src/mindustry/ClientLauncher.java @@ -36,14 +36,14 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform loader = new LoadRenderer(); Events.fire(new ClientCreateEvent()); - Vars.loadFileLogger(); - Vars.platform = this; + loadFileLogger(); + platform = this; beginTime = Time.millis(); //debug GL information Log.info("[GL] Version: @", graphics.getGLVersion()); Log.info("[GL] Max texture size: @", Gl.getInt(Gl.maxTextureSize)); - Log.info("[GL] OpenGL 3.0 context: @", gl30 != null); + Log.info("[GL] Using @ context.", gl30 != null ? "OpenGL 3" : "OpenGL 2"); Log.info("[JAVA] Version: @", System.getProperty("java.version")); Time.setDeltaProvider(() -> { diff --git a/core/src/mindustry/Vars.java b/core/src/mindustry/Vars.java index 1587c69460..34b4e99e8a 100644 --- a/core/src/mindustry/Vars.java +++ b/core/src/mindustry/Vars.java @@ -36,6 +36,8 @@ public class Vars implements Loadable{ public static boolean loadLocales = true; /** Whether the logger is loaded. */ public static boolean loadedLogger = false, loadedFileLogger = false; + /** Maximum extra padding around deployment schematics. */ + public static final int maxLoadoutSchematicPad = 4; /** Maximum schematic size.*/ public static final int maxSchematicSize = 32; /** All schematic base64 starts with this string.*/ @@ -76,8 +78,10 @@ public class Vars implements Loadable{ public static final float miningRange = 70f; /** range for building */ public static final float buildingRange = 220f; - /** duration of one turn in ticks */ - public static final float turnDuration = 5 * Time.toMinutes; + /** duration of time between turns in ticks */ + public static final float turnDuration = 20 * Time.toMinutes; + /** turns needed to destroy a sector completely */ + public static final float sectorDestructionTurns = 3f; /** min armor fraction damage; e.g. 0.05 = at least 5% damage */ public static final float minArmorDamage = 0.05f; /** launch animation duration */ @@ -195,7 +199,8 @@ public class Vars implements Loadable{ public static NetServer netServer; public static NetClient netClient; - public static Playerc player; + public static + Player player; @Override public void loadAsync(){ @@ -283,7 +288,13 @@ public class Vars implements Loadable{ if(!headless && (ui == null || ui.scriptfrag == null)){ logBuffer.add(result); }else if(!headless){ - ui.scriptfrag.addMessage(result); + if(!OS.isWindows){ + for(String code : ColorCodes.values){ + result = result.replace(code, ""); + } + } + + ui.scriptfrag.addMessage(Log.removeCodes(result)); } }); @@ -324,6 +335,7 @@ public class Vars implements Loadable{ settings.defaults("locale", "default", "blocksync", true); keybinds.setDefaults(Binding.values()); + settings.setAutosave(false); settings.load(); Scl.setProduct(settings.getInt("uiscale", 100) / 100f); diff --git a/core/src/mindustry/ai/BaseAI.java b/core/src/mindustry/ai/BaseAI.java index 06e7720651..88e224db76 100644 --- a/core/src/mindustry/ai/BaseAI.java +++ b/core/src/mindustry/ai/BaseAI.java @@ -45,7 +45,7 @@ public class BaseAI{ //create AI core unit if(!Groups.unit.contains(u -> u.team() == data.team && u.type() == block.unitType)){ - Unitc unit = block.unitType.create(data.team); + Unit unit = block.unitType.create(data.team); unit.set(data.core()); unit.add(); Fx.spawn.at(unit); diff --git a/core/src/mindustry/ai/BlockIndexer.java b/core/src/mindustry/ai/BlockIndexer.java index 637bed1bbb..46261c1c5f 100644 --- a/core/src/mindustry/ai/BlockIndexer.java +++ b/core/src/mindustry/ai/BlockIndexer.java @@ -6,7 +6,6 @@ import arc.math.*; import arc.math.geom.*; import arc.struct.EnumSet; import arc.struct.*; -import arc.util.*; import mindustry.content.*; import mindustry.game.EventType.*; import mindustry.game.*; @@ -34,7 +33,7 @@ public class BlockIndexer{ /** Maps each team ID to a quarant. A quadrant is a grid of bits, where each bit is set if and only if there is a block of that team in that quadrant. */ private GridBits[] structQuadrants; /** Stores all damaged tile entities by team. */ - private TileArray[] damagedTiles = new TileArray[Team.all.length]; + private BuildingArray[] damagedTiles = new BuildingArray[Team.all.length]; /** All ores available on this map. */ private ObjectSet allOres = new ObjectSet<>(); /** Stores teams that are present here as tiles. */ @@ -49,9 +48,11 @@ public class BlockIndexer{ private TileArray emptySet = new TileArray(); /** Array used for returning and reusing. */ private Seq returnArray = new Seq<>(); + /** Array used for returning and reusing. */ + private Seq breturnArray = new Seq<>(); public BlockIndexer(){ - Events.on(TileChangeEvent.class, event -> { + Events.on(BuildinghangeEvent.class, event -> { if(typeMap.get(event.tile.pos()) != null){ TileIndex index = typeMap.get(event.tile.pos()); for(BlockFlag flag : index.flags){ @@ -69,7 +70,7 @@ public class BlockIndexer{ Events.on(WorldLoadEvent.class, event -> { scanOres.clear(); scanOres.addAll(Item.getAllOres()); - damagedTiles = new TileArray[Team.all.length]; + damagedTiles = new BuildingArray[Team.all.length]; flagMap = new TileArray[Team.all.length][BlockFlag.all.length]; unitCaps = new int[Team.all.length]; @@ -89,8 +90,8 @@ public class BlockIndexer{ for(Tile tile : world.tiles){ process(tile); - if(tile.entity != null && tile.entity.damaged()){ - notifyTileDamaged(tile.entity); + if(tile.build != null && tile.build.damaged()){ + notifyTileDamaged(tile.build); } if(tile.drop() != null) allOres.add(tile.drop()); @@ -111,11 +112,10 @@ public class BlockIndexer{ } private GridBits structQuadrant(Team t){ - int id = Pack.u(t.id); - if(structQuadrants[id] == null){ - structQuadrants[id] = new GridBits(Mathf.ceil(world.width() / (float)quadrantSize), Mathf.ceil(world.height() / (float)quadrantSize)); + if(structQuadrants[t.id] == null){ + structQuadrants[t.id] = new GridBits(Mathf.ceil(world.width() / (float)quadrantSize), Mathf.ceil(world.height() / (float)quadrantSize)); } - return structQuadrants[id]; + return structQuadrants[t.id]; } /** Updates all the structure quadrants for a newly activated team. */ @@ -138,21 +138,21 @@ public class BlockIndexer{ } /** Returns all damaged tiles by team. */ - public TileArray getDamaged(Team team){ + public BuildingArray getDamaged(Team team){ returnArray.clear(); if(damagedTiles[team.id] == null){ - damagedTiles[team.id] = new TileArray(); + damagedTiles[team.id] = new BuildingArray(); } - TileArray set = damagedTiles[team.id]; - for(Tile tile : set){ - if((tile.entity == null || tile.entity.team() != team || !tile.entity.damaged()) || tile.block() instanceof BuildBlock){ - returnArray.add(tile); + BuildingArray set = damagedTiles[team.id]; + for(Building build : set){ + if((!build.isValid() || build.team != team || !build.damaged()) || build.block instanceof BuildBlock){ + breturnArray.add(build); } } - for(Tile tile : returnArray){ + for(Building tile : breturnArray){ set.remove(tile); } @@ -164,11 +164,11 @@ public class BlockIndexer{ return flagMap[team.id][type.ordinal()]; } - public boolean eachBlock(Teamc team, float range, Boolf pred, Cons cons){ + public boolean eachBlock(Teamc team, float range, Boolf pred, Cons cons){ return eachBlock(team.team(), team.getX(), team.getY(), range, pred, cons); } - public boolean eachBlock(Team team, float wx, float wy, float range, Boolf pred, Cons cons){ + public boolean eachBlock(Team team, float wx, float wy, float range, Boolf pred, Cons cons){ intSet.clear(); int tx = world.toTile(wx); @@ -181,7 +181,7 @@ public class BlockIndexer{ for(int y = -tileRange + ty; y <= tileRange + ty; y++){ if(!Mathf.within(x * tilesize, y * tilesize, wx, wy, range)) continue; - Tilec other = world.ent(x, y); + Building other = world.ent(x, y); if(other == null) continue; @@ -211,20 +211,18 @@ public class BlockIndexer{ return returnArray; } - public void notifyTileDamaged(Tilec entity){ - if(damagedTiles[(int)entity.team().id] == null){ - damagedTiles[(int)entity.team().id] = new TileArray(); + public void notifyTileDamaged(Building entity){ + if(damagedTiles[entity.team().id] == null){ + damagedTiles[entity.team().id] = new BuildingArray(); } - TileArray set = damagedTiles[(int)entity.team().id]; - set.add(entity.tile()); + damagedTiles[entity.team().id].add(entity); } - public Tilec findEnemyTile(Team team, float x, float y, float range, Boolf pred){ - for(Team enemy : activeTeams){ - if(!team.isEnemy(enemy)) continue; + public Building findEnemyTile(Team team, float x, float y, float range, Boolf pred){ + for(Team enemy : team.enemies()){ - Tilec entity = indexer.findTile(enemy, x, y, range, pred, true); + Building entity = indexer.findTile(enemy, x, y, range, pred, true); if(entity != null){ return entity; } @@ -233,12 +231,12 @@ public class BlockIndexer{ return null; } - public Tilec findTile(Team team, float x, float y, float range, Boolf pred){ + public Building findTile(Team team, float x, float y, float range, Boolf pred){ return findTile(team, x, y, range, pred, false); } - public Tilec findTile(Team team, float x, float y, float range, Boolf pred, boolean usePriority){ - Tilec closest = null; + public Building findTile(Team team, float x, float y, float range, Boolf pred, boolean usePriority){ + Building closest = null; float dst = 0; float range2 = range * range; @@ -249,7 +247,7 @@ public class BlockIndexer{ for(int tx = rx * quadrantSize; tx < (rx + 1) * quadrantSize && tx < world.width(); tx++){ for(int ty = ry * quadrantSize; ty < (ry + 1) * quadrantSize && ty < world.height(); ty++){ - Tilec e = world.ent(tx, ty); + Building e = world.ent(tx, ty); if(e == null) continue; @@ -380,7 +378,7 @@ public class BlockIndexer{ GridBits bits = structQuadrant(team); //fast-set this quadrant to 'occupied' if the tile just placed is already of this team - if(tile.team() == team && tile.entity != null && tile.block().targetable){ + if(tile.team() == team && tile.build != null && tile.block().targetable){ bits.set(quadrantX, quadrantY); continue; //no need to process futher } @@ -390,7 +388,7 @@ public class BlockIndexer{ outer: for(int x = quadrantX * quadrantSize; x < world.width() && x < (quadrantX + 1) * quadrantSize; x++){ for(int y = quadrantY * quadrantSize; y < world.height() && y < (quadrantY + 1) * quadrantSize; y++){ - Tilec result = world.ent(x, y); + Building result = world.ent(x, y); //when a targetable block is found, mark this quadrant as occupied and stop searching if(result != null && result.team() == team){ bits.set(quadrantX, quadrantY); @@ -474,4 +472,35 @@ public class BlockIndexer{ return tiles.iterator(); } } + + //TODO copy-pasted code, generics would be nice here + public static class BuildingArray implements Iterable{ + private Seq tiles = new Seq<>(false, 16); + private IntSet contained = new IntSet(); + + public void add(Building tile){ + if(contained.add(tile.pos())){ + tiles.add(tile); + } + } + + public void remove(Building tile){ + if(contained.remove(tile.pos())){ + tiles.remove(tile); + } + } + + public int size(){ + return tiles.size; + } + + public Building first(){ + return tiles.first(); + } + + @Override + public Iterator iterator(){ + return tiles.iterator(); + } + } } diff --git a/core/src/mindustry/ai/Pathfinder.java b/core/src/mindustry/ai/Pathfinder.java index 5b8f58b93e..fed6acd16f 100644 --- a/core/src/mindustry/ai/Pathfinder.java +++ b/core/src/mindustry/ai/Pathfinder.java @@ -63,12 +63,12 @@ public class Pathfinder implements Runnable{ Events.on(ResetEvent.class, event -> stop()); - Events.on(TileChangeEvent.class, event -> updateTile(event.tile)); + Events.on(BuildinghangeEvent.class, event -> updateTile(event.tile)); } /** Packs a tile into its internal representation. */ private int packTile(Tile tile){ - return PathTile.get(tile.cost, tile.getTeamID(), !tile.solid() && tile.floor().drownTime <= 0f, !tile.solid() && tile.floor().isLiquid); + return PathTile.get(tile.cost, (byte)tile.getTeamID(), !tile.solid() && tile.floor().drownTime <= 0f, !tile.solid() && tile.floor().isLiquid); } /** Starts or restarts the pathfinding thread. */ @@ -86,11 +86,6 @@ public class Pathfinder implements Runnable{ queue.clear(); } - //public int debugValue(Team team, int x, int y){ - // if(pathMap[team.id][FlagTarget.enemyCores.ordinal()] == null) return 0; - // return pathMap[team.id][FlagTarget.enemyCores.ordinal()].weights[x][y]; - //} - /** Update a tile in the internal pathfinding grid. * Causes a complete pathfinding reclaculation. Main thread only. */ public void updateTile(Tile tile){ @@ -144,9 +139,9 @@ public class Pathfinder implements Runnable{ Core.app.post(() -> { //remove its used state - if(fieldMap[team.uid] != null){ - fieldMap[team.uid].remove(data.target); - fieldMapUsed[team.uid].remove(data.target); + if(fieldMap[team.id] != null){ + fieldMap[team.id].remove(data.target); + fieldMapUsed[team.id].remove(data.target); } //remove from main thread list mainList.remove(data); @@ -180,16 +175,16 @@ public class Pathfinder implements Runnable{ public Tile getTargetTile(Tile tile, Team team, PathTarget target){ if(tile == null) return null; - if(fieldMap[team.uid] == null){ - fieldMap[team.uid] = new ObjectMap<>(); - fieldMapUsed[team.uid] = new ObjectSet<>(); + if(fieldMap[team.id] == null){ + fieldMap[team.id] = new ObjectMap<>(); + fieldMapUsed[team.id] = new ObjectSet<>(); } - Flowfield data = fieldMap[team.uid].get(target); + Flowfield data = fieldMap[team.id].get(target); if(data == null){ //if this combination is not found, create it on request - if(fieldMapUsed[team.uid].add(target)){ + if(fieldMapUsed[team.id].add(target)){ //grab targets since this is run on main thread IntSeq targets = target.getPositions(team, new IntSeq()); queue.post(() -> createPath(team, target, targets)); @@ -311,8 +306,8 @@ public class Pathfinder implements Runnable{ //add to main thread's list of paths Core.app.post(() -> { mainList.add(path); - if(fieldMap[team.uid] != null){ - fieldMap[team.uid].put(target, path); + if(fieldMap[team.id] != null){ + fieldMap[team.id].put(target, path); } }); diff --git a/core/src/mindustry/ai/WaveSpawner.java b/core/src/mindustry/ai/WaveSpawner.java index 61b02e6113..7f75b594af 100644 --- a/core/src/mindustry/ai/WaveSpawner.java +++ b/core/src/mindustry/ai/WaveSpawner.java @@ -34,7 +34,7 @@ public class WaveSpawner{ /** @return true if the player is near a ground spawn point. */ public boolean playerNear(){ - return !player.dead() && spawns.contains(g -> Mathf.dst(g.x * tilesize, g.y * tilesize, player.x(), player.y()) < state.rules.dropZoneRadius && player.team() != state.rules.waveTeam); + return !player.dead() && spawns.contains(g -> Mathf.dst(g.x * tilesize, g.y * tilesize, player.x, player.y) < state.rules.dropZoneRadius && player.team() != state.rules.waveTeam); } public void spawnEnemies(){ @@ -48,7 +48,7 @@ public class WaveSpawner{ eachFlyerSpawn((spawnX, spawnY) -> { for(int i = 0; i < spawned; i++){ - Unitc unit = group.createUnit(state.rules.waveTeam, state.wave - 1); + Unit unit = group.createUnit(state.rules.waveTeam, state.wave - 1); unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread)); unit.add(); } @@ -61,7 +61,7 @@ public class WaveSpawner{ for(int i = 0; i < spawned; i++){ Tmp.v1.rnd(spread); - Unitc unit = group.createUnit(state.rules.waveTeam, state.wave - 1); + Unit unit = group.createUnit(state.rules.waveTeam, state.wave - 1); unit.set(spawnX + Tmp.v1.x, spawnY + Tmp.v1.y); Time.run(Math.min(i * 5, 60 * 2), () -> spawnEffect(unit)); } @@ -85,10 +85,10 @@ public class WaveSpawner{ } if(state.rules.attackMode && state.teams.isActive(state.rules.waveTeam) && !state.teams.playerCores().isEmpty()){ - Tilec firstCore = state.teams.playerCores().first(); - for(Tilec core : state.rules.waveTeam.cores()){ + Building firstCore = state.teams.playerCores().first(); + for(Building core : state.rules.waveTeam.cores()){ Tmp.v1.set(firstCore).sub(core).limit(coreMargin + core.block().size * tilesize); - cons.accept(core.x() + Tmp.v1.x, core.y() + Tmp.v1.y, false); + cons.accept(core.x + Tmp.v1.x, core.y + Tmp.v1.y, false); } } } @@ -104,8 +104,8 @@ public class WaveSpawner{ } if(state.rules.attackMode && state.teams.isActive(state.rules.waveTeam)){ - for(Tilec core : state.teams.get(state.rules.waveTeam).cores){ - cons.get(core.x(), core.y()); + for(Building core : state.teams.get(state.rules.waveTeam).cores){ + cons.get(core.x, core.y); } } } @@ -124,7 +124,7 @@ public class WaveSpawner{ } } - private void spawnEffect(Unitc unit){ + private void spawnEffect(Unit unit){ Fx.unitSpawn.at(unit.x(), unit.y(), 0f, unit); Time.run(30f, () -> { unit.add(); diff --git a/core/src/mindustry/ai/types/BuilderAI.java b/core/src/mindustry/ai/types/BuilderAI.java index 31486988f9..68953a8d7b 100644 --- a/core/src/mindustry/ai/types/BuilderAI.java +++ b/core/src/mindustry/ai/types/BuilderAI.java @@ -15,7 +15,7 @@ import static mindustry.Vars.*; public class BuilderAI extends AIController{ @Override - public void update(){ + public void updateUnit(){ Builderc builder = (Builderc)unit; if(builder.moving()){ @@ -27,7 +27,7 @@ public class BuilderAI extends AIController{ BuildPlan req = builder.buildPlan(); boolean valid = - (req.tile().entity instanceof BuildEntity && req.tile().ent().cblock == req.block) || + (req.tile().build instanceof BuildEntity && req.tile().bc().cblock == req.block) || (req.breaking ? Build.validBreak(unit.team(), req.x, req.y) : Build.validPlace(req.block, unit.team(), req.x, req.y, req.rotation)); @@ -60,8 +60,6 @@ public class BuilderAI extends AIController{ blocks.removeFirst(); blocks.addLast(block); } - }else{ - //TODO implement AI base building } } } diff --git a/core/src/mindustry/ai/types/FlyingAI.java b/core/src/mindustry/ai/types/FlyingAI.java index faf2a543bd..a85a657fa3 100644 --- a/core/src/mindustry/ai/types/FlyingAI.java +++ b/core/src/mindustry/ai/types/FlyingAI.java @@ -10,7 +10,7 @@ import mindustry.world.meta.*; public class FlyingAI extends AIController{ @Override - public void update(){ + public void updateUnit(){ if(unit.moving()){ unit.rotation(unit.vel().angle()); } diff --git a/core/src/mindustry/ai/types/FormationAI.java b/core/src/mindustry/ai/types/FormationAI.java index 49367ae12f..66ca6a9d21 100644 --- a/core/src/mindustry/ai/types/FormationAI.java +++ b/core/src/mindustry/ai/types/FormationAI.java @@ -8,58 +8,58 @@ import mindustry.entities.units.*; import mindustry.gen.*; public class FormationAI extends AIController implements FormationMember{ - public Unitc leader; + public Unit leader; private Vec3 target = new Vec3(); private @Nullable Formation formation; - public FormationAI(Unitc leader, Formation formation){ + public FormationAI(Unit leader, Formation formation){ this.leader = leader; this.formation = formation; } @Override public void init(){ - target.set(unit.x(), unit.y(), 0); + target.set(unit.x, unit.y, 0); } @Override - public void update(){ - if(leader.dead()){ + public void updateUnit(){ + if(leader.dead){ unit.resetController(); return; } - unit.controlWeapons(leader.isRotate(), leader.isShooting()); + unit.controlWeapons(leader.isRotate(), leader.isShooting); // unit.moveAt(Tmp.v1.set(deltaX, deltaY).limit(unit.type().speed)); - if(leader.isShooting()){ + if(leader.isShooting){ unit.aimLook(leader.aimX(), leader.aimY()); }else{ if(!unit.moving()){ - unit.lookAt(unit.vel().angle()); + unit.lookAt(unit.vel.angle()); }else{ - unit.lookAt(leader.rotation()); + unit.lookAt(leader.rotation); } } Vec2 realtarget = vec.set(target); if(unit.isGrounded() && Vars.world.raycast(unit.tileX(), unit.tileY(), leader.tileX(), leader.tileY(), Vars.world::solid)){ - realtarget.set(Vars.pathfinder.getTargetTile(unit.tileOn(), unit.team(), leader)); + realtarget.set(Vars.pathfinder.getTargetTile(unit.tileOn(), unit.team, leader)); } unit.moveAt(realtarget.sub(unit).limit(unit.type().speed)); } @Override - public void removed(Unitc unit){ + public void removed(Unit unit){ if(formation != null){ formation.removeMember(this); } } @Override - public boolean isBeingControlled(Unitc player){ + public boolean isBeingControlled(Unit player){ return leader == player; } diff --git a/core/src/mindustry/ai/types/GroundAI.java b/core/src/mindustry/ai/types/GroundAI.java index b32f431682..0a7384ff45 100644 --- a/core/src/mindustry/ai/types/GroundAI.java +++ b/core/src/mindustry/ai/types/GroundAI.java @@ -12,7 +12,7 @@ import static mindustry.Vars.pathfinder; public class GroundAI extends AIController{ @Override - public void update(){ + public void updateUnit(){ if(Units.invalidateTarget(target, unit.team(), unit.x(), unit.y(), Float.MAX_VALUE)){ target = null; @@ -22,7 +22,7 @@ public class GroundAI extends AIController{ targetClosest(); } - Tilec core = unit.closestEnemyCore(); + Building core = unit.closestEnemyCore(); if(core != null){ if(unit.within(core,unit.range() / 1.1f)){ @@ -81,7 +81,7 @@ public class GroundAI extends AIController{ Tile tile = unit.tileOn(); if(tile == null) return; Tile targetTile = pathfinder.getTargetTile(tile, enemy, FlagTarget.enemyCores); - Tilec core = unit.closestCore(); + Building core = unit.closestCore(); if(tile == targetTile || core == null || unit.within(core, 120f)) return; diff --git a/core/src/mindustry/ai/types/SuicideAI.java b/core/src/mindustry/ai/types/SuicideAI.java index d56baec2e5..57638d7597 100644 --- a/core/src/mindustry/ai/types/SuicideAI.java +++ b/core/src/mindustry/ai/types/SuicideAI.java @@ -10,7 +10,7 @@ public class SuicideAI extends GroundAI{ static boolean blockedByBlock; @Override - public void update(){ + public void updateUnit(){ if(Units.invalidateTarget(target, unit.team(), unit.x(), unit.y(), Float.MAX_VALUE)){ target = null; @@ -20,14 +20,14 @@ public class SuicideAI extends GroundAI{ targetClosest(); } - Tilec core = unit.closestEnemyCore(); + Building core = unit.closestEnemyCore(); boolean rotate = false, shoot = false; if(!Units.invalidateTarget(target, unit, unit.range())){ rotate = true; shoot = unit.within(target, unit.type().weapons.first().bullet.range() + - (target instanceof Tilec ? ((Tilec)target).block().size * Vars.tilesize / 2f : ((Hitboxc)target).hitSize() / 2f)); + (target instanceof Building ? ((Building)target).block().size * Vars.tilesize / 2f : ((Hitboxc)target).hitSize() / 2f)); if(unit.type().hasWeapons()){ unit.aimLook(Predict.intercept(unit, target, unit.type().weapons.first().bullet.speed)); @@ -38,8 +38,8 @@ public class SuicideAI extends GroundAI{ //raycast for target boolean blocked = Vars.world.raycast(unit.tileX(), unit.tileY(), target.tileX(), target.tileY(), (x, y) -> { Tile tile = Vars.world.tile(x, y); - if(tile != null && tile.entity == target) return false; - if(tile != null && tile.entity != null && tile.entity.team() != unit.team()){ + if(tile != null && tile.build == target) return false; + if(tile != null && tile.build != null && tile.build.team() != unit.team()){ blockedByBlock = true; return true; }else{ diff --git a/core/src/mindustry/async/TeamIndexProcess.java b/core/src/mindustry/async/TeamIndexProcess.java index 2b5c0043a6..f1d9a6324b 100644 --- a/core/src/mindustry/async/TeamIndexProcess.java +++ b/core/src/mindustry/async/TeamIndexProcess.java @@ -9,13 +9,13 @@ import java.util.*; /** Creates quadtrees per unit team. */ public class TeamIndexProcess implements AsyncProcess{ - private QuadTree[] trees = new QuadTree[Team.all.length]; + private QuadTree[] trees = new QuadTree[Team.all.length]; private int[] counts = new int[Team.all.length]; - public QuadTree tree(Team team){ - if(trees[team.uid] == null) trees[team.uid] = new QuadTree<>(Vars.world.getQuadBounds(new Rect())); + public QuadTree tree(Team team){ + if(trees[team.id] == null) trees[team.id] = new QuadTree<>(Vars.world.getQuadBounds(new Rect())); - return trees[team.uid]; + return trees[team.id]; } public int count(Team team){ @@ -36,16 +36,16 @@ public class TeamIndexProcess implements AsyncProcess{ public void begin(){ for(Team team : Team.all){ - if(trees[team.uid] != null){ - trees[team.uid].clear(); + if(trees[team.id] != null){ + trees[team.id].clear(); } } Arrays.fill(counts, 0); - for(Unitc unit : Groups.unit){ - tree(unit.team()).insert(unit); - counts[unit.team().id] ++; + for(Unit unit : Groups.unit){ + tree(unit.team).insert(unit); + counts[unit.team.id] ++; } } diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 32b8e448c1..2b6d2be05e 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -3,10 +3,7 @@ package mindustry.content; import arc.*; import arc.graphics.*; import arc.graphics.g2d.*; -import arc.math.*; -import arc.util.*; import mindustry.ctype.*; -import mindustry.entities.*; import mindustry.entities.bullet.*; import mindustry.gen.*; import mindustry.graphics.*; @@ -30,6 +27,8 @@ import mindustry.world.consumers.*; import mindustry.world.draw.*; import mindustry.world.meta.*; +import static mindustry.type.ItemStack.*; + public class Blocks implements ContentList{ public static Block @@ -74,7 +73,7 @@ public class Blocks implements ContentList{ coreShard, coreFoundation, coreNucleus, vault, container, unloader, //turrets - duo, scatter, scorch, hail, arc, wave, lancer, swarmer, salvo, fuse, ripple, cyclone, spectre, meltdown, segment, + duo, scatter, scorch, hail, arc, wave, lancer, swarmer, salvo, fuse, ripple, cyclone, spectre, meltdown, segment, parallax, //units groundFactory, airFactory, navalFactory, @@ -226,6 +225,10 @@ public class Blocks implements ContentList{ attributes.set(Attribute.heat, 0.5f); attributes.set(Attribute.water, -0.2f); blendGroup = ignarock; + + emitLight = true; + lightRadius = 30f; + lightColor = Color.orange.cpy().a(0.15f); }}; magmarock = new Floor("magmarock"){{ @@ -233,6 +236,10 @@ public class Blocks implements ContentList{ attributes.set(Attribute.water, -0.5f); updateEffect = Fx.magmasmoke; blendGroup = ignarock; + + emitLight = true; + lightRadius = 60f; + lightColor = Color.orange.cpy().a(0.3f); }}; sand = new Floor("sand"){{ @@ -446,7 +453,7 @@ public class Blocks implements ContentList{ //region crafting graphitePress = new GenericCrafter("graphite-press"){{ - requirements(Category.crafting, ItemStack.with(Items.copper, 75, Items.lead, 30)); + requirements(Category.crafting, with(Items.copper, 75, Items.lead, 30)); craftEffect = Fx.pulverizeMedium; outputItem = new ItemStack(Items.graphite, 1); @@ -458,7 +465,7 @@ public class Blocks implements ContentList{ }}; multiPress = new GenericCrafter("multi-press"){{ - requirements(Category.crafting, ItemStack.with(Items.titanium, 100, Items.silicon, 25, Items.lead, 100, Items.graphite, 50)); + requirements(Category.crafting, with(Items.titanium, 100, Items.silicon, 25, Items.lead, 100, Items.graphite, 50)); craftEffect = Fx.pulverizeMedium; outputItem = new ItemStack(Items.graphite, 2); @@ -474,7 +481,7 @@ public class Blocks implements ContentList{ }}; siliconSmelter = new GenericSmelter("silicon-smelter"){{ - requirements(Category.crafting, ItemStack.with(Items.copper, 30, Items.lead, 25)); + requirements(Category.crafting, with(Items.copper, 30, Items.lead, 25)); craftEffect = Fx.smeltsmoke; outputItem = new ItemStack(Items.silicon, 1); craftTime = 40f; @@ -488,7 +495,7 @@ public class Blocks implements ContentList{ }}; siliconCrucible = new AttributeSmelter("silicon-crucible"){{ - requirements(Category.crafting, ItemStack.with(Items.titanium, 120, Items.metaglass, 80, Items.plastanium, 35, Items.silicon, 60)); + requirements(Category.crafting, with(Items.titanium, 120, Items.metaglass, 80, Items.plastanium, 35, Items.silicon, 60)); craftEffect = Fx.smeltsmoke; outputItem = new ItemStack(Items.silicon, 5); craftTime = 140f; @@ -504,7 +511,7 @@ public class Blocks implements ContentList{ }}; kiln = new GenericSmelter("kiln"){{ - requirements(Category.crafting, ItemStack.with(Items.copper, 60, Items.graphite, 30, Items.lead, 30)); + requirements(Category.crafting, with(Items.copper, 60, Items.graphite, 30, Items.lead, 30)); craftEffect = Fx.smeltsmoke; outputItem = new ItemStack(Items.metaglass, 1); craftTime = 30f; @@ -517,7 +524,7 @@ public class Blocks implements ContentList{ }}; plastaniumCompressor = new GenericCrafter("plastanium-compressor"){{ - requirements(Category.crafting, ItemStack.with(Items.silicon, 80, Items.lead, 115, Items.graphite, 60, Items.titanium, 80)); + requirements(Category.crafting, with(Items.silicon, 80, Items.lead, 115, Items.graphite, 60, Items.titanium, 80)); hasItems = true; liquidCapacity = 60f; craftTime = 60f; @@ -535,7 +542,7 @@ public class Blocks implements ContentList{ }}; phaseWeaver = new GenericCrafter("phase-weaver"){{ - requirements(Category.crafting, ItemStack.with(Items.silicon, 130, Items.lead, 120, Items.thorium, 75)); + requirements(Category.crafting, with(Items.silicon, 130, Items.lead, 120, Items.thorium, 75)); craftEffect = Fx.smeltsmoke; outputItem = new ItemStack(Items.phasefabric, 1); craftTime = 120f; @@ -549,7 +556,7 @@ public class Blocks implements ContentList{ }}; surgeSmelter = new GenericSmelter("alloy-smelter"){{ - requirements(Category.crafting, ItemStack.with(Items.silicon, 80, Items.lead, 80, Items.thorium, 70)); + requirements(Category.crafting, with(Items.silicon, 80, Items.lead, 80, Items.thorium, 70)); craftEffect = Fx.smeltsmoke; outputItem = new ItemStack(Items.surgealloy, 1); craftTime = 75f; @@ -561,7 +568,7 @@ public class Blocks implements ContentList{ }}; cryofluidMixer = new LiquidConverter("cryofluidmixer"){{ - requirements(Category.crafting, ItemStack.with(Items.lead, 65, Items.silicon, 40, Items.titanium, 60)); + requirements(Category.crafting, with(Items.lead, 65, Items.silicon, 40, Items.titanium, 60)); outputLiquid = new LiquidStack(Liquids.cryofluid, 0.2f); craftTime = 120f; size = 2; @@ -579,7 +586,7 @@ public class Blocks implements ContentList{ }}; blastMixer = new GenericCrafter("blast-mixer"){{ - requirements(Category.crafting, ItemStack.with(Items.lead, 30, Items.titanium, 20)); + requirements(Category.crafting, with(Items.lead, 30, Items.titanium, 20)); hasItems = true; hasPower = true; outputItem = new ItemStack(Items.blastCompound, 1); @@ -590,7 +597,7 @@ public class Blocks implements ContentList{ }}; pyratiteMixer = new GenericSmelter("pyratite-mixer"){{ - requirements(Category.crafting, ItemStack.with(Items.copper, 50, Items.lead, 25)); + requirements(Category.crafting, with(Items.copper, 50, Items.lead, 25)); flameColor = Color.clear; hasItems = true; hasPower = true; @@ -603,7 +610,7 @@ public class Blocks implements ContentList{ }}; melter = new GenericCrafter("melter"){{ - requirements(Category.crafting, ItemStack.with(Items.copper, 30, Items.lead, 35, Items.graphite, 45)); + requirements(Category.crafting, with(Items.copper, 30, Items.lead, 35, Items.graphite, 45)); health = 200; outputLiquid = new LiquidStack(Liquids.slag, 2f); craftTime = 10f; @@ -614,8 +621,8 @@ public class Blocks implements ContentList{ }}; separator = new Separator("separator"){{ - requirements(Category.crafting, ItemStack.with(Items.copper, 30, Items.titanium, 25)); - results = ItemStack.with( + requirements(Category.crafting, with(Items.copper, 30, Items.titanium, 25)); + results = with( Items.copper, 5, Items.lead, 3, Items.graphite, 2, @@ -630,8 +637,8 @@ public class Blocks implements ContentList{ }}; disassembler = new Separator("disassembler"){{ - requirements(Category.crafting, ItemStack.with(Items.graphite, 140, Items.titanium, 100, Items.silicon, 150, Items.surgealloy, 70)); - results = ItemStack.with( + requirements(Category.crafting, with(Items.graphite, 140, Items.titanium, 100, Items.silicon, 150, Items.surgealloy, 70)); + results = with( Items.sand, 4, Items.graphite, 2, Items.titanium, 2, @@ -648,7 +655,7 @@ public class Blocks implements ContentList{ }}; sporePress = new GenericCrafter("spore-press"){{ - requirements(Category.crafting, ItemStack.with(Items.lead, 35, Items.silicon, 30)); + requirements(Category.crafting, with(Items.lead, 35, Items.silicon, 30)); liquidCapacity = 60f; craftTime = 20f; outputLiquid = new LiquidStack(Liquids.oil, 6f); @@ -664,7 +671,7 @@ public class Blocks implements ContentList{ }}; pulverizer = new GenericCrafter("pulverizer"){{ - requirements(Category.crafting, ItemStack.with(Items.copper, 30, Items.lead, 25)); + requirements(Category.crafting, with(Items.copper, 30, Items.lead, 25)); outputItem = new ItemStack(Items.sand, 1); craftEffect = Fx.pulverize; craftTime = 40f; @@ -677,7 +684,7 @@ public class Blocks implements ContentList{ }}; coalCentrifuge = new GenericCrafter("coal-centrifuge"){{ - requirements(Category.crafting, ItemStack.with(Items.titanium, 20, Items.graphite, 40, Items.lead, 30)); + requirements(Category.crafting, with(Items.titanium, 20, Items.graphite, 40, Items.lead, 30)); craftEffect = Fx.smeltsmoke; outputItem = new ItemStack(Items.coal, 1); craftTime = 30f; @@ -689,7 +696,7 @@ public class Blocks implements ContentList{ }}; incinerator = new Incinerator("incinerator"){{ - requirements(Category.crafting, ItemStack.with(Items.graphite, 5, Items.lead, 15)); + requirements(Category.crafting, with(Items.graphite, 5, Items.lead, 15)); health = 90; consumes.power(0.50f); }}; @@ -700,7 +707,7 @@ public class Blocks implements ContentList{ int wallHealthMultiplier = 4; copperWall = new Wall("copper-wall"){{ - requirements(Category.defense, ItemStack.with(Items.copper, 6)); + requirements(Category.defense, with(Items.copper, 6)); health = 80 * wallHealthMultiplier; }}; @@ -711,7 +718,7 @@ public class Blocks implements ContentList{ }}; titaniumWall = new Wall("titanium-wall"){{ - requirements(Category.defense, ItemStack.with(Items.titanium, 6)); + requirements(Category.defense, with(Items.titanium, 6)); health = 110 * wallHealthMultiplier; }}; @@ -722,7 +729,7 @@ public class Blocks implements ContentList{ }}; plastaniumWall = new Wall("plastanium-wall"){{ - requirements(Category.defense, ItemStack.with(Items.plastanium, 5, Items.metaglass, 2)); + requirements(Category.defense, with(Items.plastanium, 5, Items.metaglass, 2)); health = 190 * wallHealthMultiplier; insulated = true; absorbLasers = true; @@ -737,7 +744,7 @@ public class Blocks implements ContentList{ }}; thoriumWall = new Wall("thorium-wall"){{ - requirements(Category.defense, ItemStack.with(Items.thorium, 6)); + requirements(Category.defense, with(Items.thorium, 6)); health = 200 * wallHealthMultiplier; }}; @@ -747,30 +754,34 @@ public class Blocks implements ContentList{ size = 2; }}; - phaseWall = new DeflectorWall("phase-wall"){{ - requirements(Category.defense, ItemStack.with(Items.phasefabric, 6)); + phaseWall = new Wall("phase-wall"){{ + requirements(Category.defense, with(Items.phasefabric, 6)); health = 150 * wallHealthMultiplier; + flashWhite = deflect = true; }}; - phaseWallLarge = new DeflectorWall("phase-wall-large"){{ + phaseWallLarge = new Wall("phase-wall-large"){{ requirements(Category.defense, ItemStack.mult(phaseWall.requirements, 4)); health = 150 * 4 * wallHealthMultiplier; size = 2; + flashWhite = deflect = true; }}; - surgeWall = new SurgeWall("surge-wall"){{ - requirements(Category.defense, ItemStack.with(Items.surgealloy, 6)); + surgeWall = new Wall("surge-wall"){{ + requirements(Category.defense, with(Items.surgealloy, 6)); health = 230 * wallHealthMultiplier; + lightningChance = 0.05f; }}; - surgeWallLarge = new SurgeWall("surge-wall-large"){{ + surgeWallLarge = new Wall("surge-wall-large"){{ requirements(Category.defense, ItemStack.mult(surgeWall.requirements, 4)); health = 230 * 4 * wallHealthMultiplier; size = 2; + lightningChance = 0.05f; }}; door = new Door("door"){{ - requirements(Category.defense, ItemStack.with(Items.graphite, 6, Items.silicon, 4)); + requirements(Category.defense, with(Items.graphite, 6, Items.silicon, 4)); health = 100 * wallHealthMultiplier; }}; @@ -783,27 +794,27 @@ public class Blocks implements ContentList{ }}; scrapWall = new Wall("scrap-wall"){{ - requirements(Category.defense, BuildVisibility.sandboxOnly, ItemStack.with()); + requirements(Category.defense, BuildVisibility.sandboxOnly, with()); health = 60 * wallHealthMultiplier; variants = 5; }}; scrapWallLarge = new Wall("scrap-wall-large"){{ - requirements(Category.defense, BuildVisibility.sandboxOnly, ItemStack.with()); + requirements(Category.defense, BuildVisibility.sandboxOnly, with()); health = 60 * 4 * wallHealthMultiplier; size = 2; variants = 4; }}; scrapWallHuge = new Wall("scrap-wall-huge"){{ - requirements(Category.defense, BuildVisibility.sandboxOnly, ItemStack.with()); + requirements(Category.defense, BuildVisibility.sandboxOnly, with()); health = 60 * 9 * wallHealthMultiplier; size = 3; variants = 3; }}; scrapWallGigantic = new Wall("scrap-wall-gigantic"){{ - requirements(Category.defense, BuildVisibility.sandboxOnly, ItemStack.with()); + requirements(Category.defense, BuildVisibility.sandboxOnly, with()); health = 60 * 16 * wallHealthMultiplier; size = 4; }}; @@ -814,7 +825,7 @@ public class Blocks implements ContentList{ }}; mender = new MendProjector("mender"){{ - requirements(Category.effect, ItemStack.with(Items.lead, 30, Items.copper, 25)); + requirements(Category.effect, with(Items.lead, 30, Items.copper, 25)); consumes.power(0.3f); size = 1; reload = 200f; @@ -827,7 +838,7 @@ public class Blocks implements ContentList{ }}; mendProjector = new MendProjector("mend-projector"){{ - requirements(Category.effect, ItemStack.with(Items.lead, 100, Items.titanium, 25, Items.silicon, 40)); + requirements(Category.effect, with(Items.lead, 100, Items.titanium, 25, Items.silicon, 40)); consumes.power(1.5f); size = 2; reload = 250f; @@ -838,7 +849,7 @@ public class Blocks implements ContentList{ }}; overdriveProjector = new OverdriveProjector("overdrive-projector"){{ - requirements(Category.effect, ItemStack.with(Items.lead, 100, Items.titanium, 75, Items.silicon, 75, Items.plastanium, 30)); + requirements(Category.effect, with(Items.lead, 100, Items.titanium, 75, Items.silicon, 75, Items.plastanium, 30)); consumes.power(3.50f); size = 2; consumes.item(Items.phasefabric).boost(); @@ -846,25 +857,25 @@ public class Blocks implements ContentList{ //TODO better name largeOverdriveProjector = new OverdriveProjector("large-overdrive-projector"){{ - requirements(Category.effect, ItemStack.with(Items.lead, 200, Items.titanium, 130, Items.silicon, 130, Items.plastanium, 80, Items.surgealloy, 120)); + requirements(Category.effect, with(Items.lead, 200, Items.titanium, 130, Items.silicon, 130, Items.plastanium, 80, Items.surgealloy, 120)); consumes.power(10f); size = 3; range = 200f; speedBoost = 2.5f; useTime = 300f; hasBoost = false; - consumes.items(ItemStack.with(Items.phasefabric, 1, Items.silicon, 1)); + consumes.items(with(Items.phasefabric, 1, Items.silicon, 1)); }}; forceProjector = new ForceProjector("force-projector"){{ - requirements(Category.effect, ItemStack.with(Items.lead, 100, Items.titanium, 75, Items.silicon, 125)); + requirements(Category.effect, with(Items.lead, 100, Items.titanium, 75, Items.silicon, 125)); size = 3; consumes.item(Items.phasefabric).boost(); consumes.power(3f); }}; shockMine = new ShockMine("shock-mine"){{ - requirements(Category.effect, ItemStack.with(Items.lead, 25, Items.silicon, 12)); + requirements(Category.effect, with(Items.lead, 25, Items.silicon, 12)); hasShadow = false; health = 40; damage = 11; @@ -877,35 +888,35 @@ public class Blocks implements ContentList{ //region distribution conveyor = new Conveyor("conveyor"){{ - requirements(Category.distribution, ItemStack.with(Items.copper, 1), true); + requirements(Category.distribution, with(Items.copper, 1), true); health = 45; speed = 0.03f; displayedSpeed = 4.2f; }}; titaniumConveyor = new Conveyor("titanium-conveyor"){{ - requirements(Category.distribution, ItemStack.with(Items.copper, 1, Items.lead, 1, Items.titanium, 1)); + requirements(Category.distribution, with(Items.copper, 1, Items.lead, 1, Items.titanium, 1)); health = 65; speed = 0.08f; displayedSpeed = 11f; }}; plastaniumConveyor = new StackConveyor("plastanium-conveyor"){{ - requirements(Category.distribution, ItemStack.with(Items.plastanium, 1, Items.silicon, 1, Items.graphite, 1)); + requirements(Category.distribution, with(Items.plastanium, 1, Items.silicon, 1, Items.graphite, 1)); health = 75; speed = 2.5f / 60f; recharge = 2f; }}; armoredConveyor = new ArmoredConveyor("armored-conveyor"){{ - requirements(Category.distribution, ItemStack.with(Items.plastanium, 1, Items.thorium, 1, Items.metaglass, 1)); + requirements(Category.distribution, with(Items.plastanium, 1, Items.thorium, 1, Items.metaglass, 1)); health = 180; speed = 0.08f; displayedSpeed = 10f; }}; junction = new Junction("junction"){{ - requirements(Category.distribution, ItemStack.with(Items.copper, 2), true); + requirements(Category.distribution, with(Items.copper, 2), true); speed = 26; capacity = 12; health = 30; @@ -913,14 +924,14 @@ public class Blocks implements ContentList{ }}; itemBridge = new BufferedItemBridge("bridge-conveyor"){{ - requirements(Category.distribution, ItemStack.with(Items.lead, 4, Items.copper, 4)); + requirements(Category.distribution, with(Items.lead, 4, Items.copper, 4)); range = 4; speed = 70f; bufferCapacity = 14; }}; phaseConveyor = new ItemBridge("phase-conveyor"){{ - requirements(Category.distribution, ItemStack.with(Items.phasefabric, 5, Items.silicon, 7, Items.lead, 10, Items.graphite, 10)); + requirements(Category.distribution, with(Items.phasefabric, 5, Items.silicon, 7, Items.lead, 10, Items.graphite, 10)); range = 12; canOverdrive = false; hasPower = true; @@ -928,39 +939,39 @@ public class Blocks implements ContentList{ }}; sorter = new Sorter("sorter"){{ - requirements(Category.distribution, ItemStack.with(Items.lead, 2, Items.copper, 2)); + requirements(Category.distribution, with(Items.lead, 2, Items.copper, 2)); buildCostMultiplier = 3f; }}; invertedSorter = new Sorter("inverted-sorter"){{ - requirements(Category.distribution, ItemStack.with(Items.lead, 2, Items.copper, 2)); + requirements(Category.distribution, with(Items.lead, 2, Items.copper, 2)); buildCostMultiplier = 3f; invert = true; }}; router = new Router("router"){{ - requirements(Category.distribution, ItemStack.with(Items.copper, 3)); + requirements(Category.distribution, with(Items.copper, 3)); buildCostMultiplier = 2f; }}; distributor = new Router("distributor"){{ - requirements(Category.distribution, ItemStack.with(Items.lead, 4, Items.copper, 4)); + requirements(Category.distribution, with(Items.lead, 4, Items.copper, 4)); size = 2; }}; overflowGate = new OverflowGate("overflow-gate"){{ - requirements(Category.distribution, ItemStack.with(Items.lead, 2, Items.copper, 4)); + requirements(Category.distribution, with(Items.lead, 2, Items.copper, 4)); buildCostMultiplier = 3f; }}; underflowGate = new OverflowGate("underflow-gate"){{ - requirements(Category.distribution, ItemStack.with(Items.lead, 2, Items.copper, 4)); + requirements(Category.distribution, with(Items.lead, 2, Items.copper, 4)); buildCostMultiplier = 3f; invert = true; }}; massDriver = new MassDriver("mass-driver"){{ - requirements(Category.distribution, ItemStack.with(Items.titanium, 125, Items.silicon, 75, Items.lead, 125, Items.thorium, 50)); + requirements(Category.distribution, with(Items.titanium, 125, Items.silicon, 75, Items.lead, 125, Items.thorium, 50)); size = 3; itemCapacity = 120; reloadTime = 200f; @@ -969,23 +980,23 @@ public class Blocks implements ContentList{ }}; payloadConveyor = new PayloadConveyor("mass-conveyor"){{ - requirements(Category.distribution, ItemStack.with(Items.copper, 1)); + requirements(Category.distribution, with(Items.copper, 1)); }}; payloadRouter = new PayloadRouter("payload-router"){{ - requirements(Category.distribution, ItemStack.with(Items.copper, 1)); + requirements(Category.distribution, with(Items.copper, 1)); }}; //endregion //region liquid mechanicalPump = new Pump("mechanical-pump"){{ - requirements(Category.liquid, ItemStack.with(Items.copper, 15, Items.metaglass, 10)); + requirements(Category.liquid, with(Items.copper, 15, Items.metaglass, 10)); pumpAmount = 0.1f; }}; rotaryPump = new Pump("rotary-pump"){{ - requirements(Category.liquid, ItemStack.with(Items.copper, 70, Items.metaglass, 50, Items.silicon, 20, Items.titanium, 35)); + requirements(Category.liquid, with(Items.copper, 70, Items.metaglass, 50, Items.silicon, 20, Items.titanium, 35)); pumpAmount = 0.8f; consumes.power(0.15f); liquidCapacity = 30f; @@ -994,7 +1005,7 @@ public class Blocks implements ContentList{ }}; thermalPump = new Pump("thermal-pump"){{ - requirements(Category.liquid, ItemStack.with(Items.copper, 80, Items.metaglass, 70, Items.silicon, 30, Items.titanium, 40, Items.thorium, 35)); + requirements(Category.liquid, with(Items.copper, 80, Items.metaglass, 70, Items.silicon, 30, Items.titanium, 40, Items.thorium, 35)); pumpAmount = 1.5f; consumes.power(0.30f); liquidCapacity = 40f; @@ -1003,48 +1014,48 @@ public class Blocks implements ContentList{ }}; conduit = new Conduit("conduit"){{ - requirements(Category.liquid, ItemStack.with(Items.metaglass, 1)); + requirements(Category.liquid, with(Items.metaglass, 1)); health = 45; }}; pulseConduit = new Conduit("pulse-conduit"){{ - requirements(Category.liquid, ItemStack.with(Items.titanium, 2, Items.metaglass, 1)); + requirements(Category.liquid, with(Items.titanium, 2, Items.metaglass, 1)); liquidCapacity = 16f; liquidPressure = 1.025f; health = 90; }}; platedConduit = new ArmoredConduit("plated-conduit"){{ - requirements(Category.liquid, ItemStack.with(Items.thorium, 2, Items.metaglass, 1, Items.plastanium, 1)); + requirements(Category.liquid, with(Items.thorium, 2, Items.metaglass, 1, Items.plastanium, 1)); liquidCapacity = 16f; liquidPressure = 1.025f; health = 220; }}; liquidRouter = new LiquidRouter("liquid-router"){{ - requirements(Category.liquid, ItemStack.with(Items.graphite, 4, Items.metaglass, 2)); + requirements(Category.liquid, with(Items.graphite, 4, Items.metaglass, 2)); liquidCapacity = 20f; }}; liquidTank = new LiquidRouter("liquid-tank"){{ - requirements(Category.liquid, ItemStack.with(Items.titanium, 25, Items.metaglass, 25)); + requirements(Category.liquid, with(Items.titanium, 25, Items.metaglass, 25)); size = 3; liquidCapacity = 1500f; health = 500; }}; liquidJunction = new LiquidJunction("liquid-junction"){{ - requirements(Category.liquid, ItemStack.with(Items.graphite, 2, Items.metaglass, 2)); + requirements(Category.liquid, with(Items.graphite, 2, Items.metaglass, 2)); }}; bridgeConduit = new LiquidExtendingBridge("bridge-conduit"){{ - requirements(Category.liquid, ItemStack.with(Items.graphite, 4, Items.metaglass, 8)); + requirements(Category.liquid, with(Items.graphite, 4, Items.metaglass, 8)); range = 4; hasPower = false; }}; phaseConduit = new LiquidBridge("phase-conduit"){{ - requirements(Category.liquid, ItemStack.with(Items.phasefabric, 5, Items.silicon, 7, Items.metaglass, 20, Items.titanium, 10)); + requirements(Category.liquid, with(Items.phasefabric, 5, Items.silicon, 7, Items.metaglass, 20, Items.titanium, 10)); range = 12; hasPower = true; canOverdrive = false; @@ -1055,55 +1066,55 @@ public class Blocks implements ContentList{ //region power powerNode = new PowerNode("power-node"){{ - requirements(Category.power, ItemStack.with(Items.copper, 1, Items.lead, 3)); + requirements(Category.power, with(Items.copper, 1, Items.lead, 3)); maxNodes = 20; laserRange = 6; }}; powerNodeLarge = new PowerNode("power-node-large"){{ - requirements(Category.power, ItemStack.with(Items.titanium, 5, Items.lead, 10, Items.silicon, 3)); + requirements(Category.power, with(Items.titanium, 5, Items.lead, 10, Items.silicon, 3)); size = 2; maxNodes = 30; laserRange = 9.5f; }}; surgeTower = new PowerNode("surge-tower"){{ - requirements(Category.power, ItemStack.with(Items.titanium, 7, Items.lead, 10, Items.silicon, 15, Items.surgealloy, 15)); + requirements(Category.power, with(Items.titanium, 7, Items.lead, 10, Items.silicon, 15, Items.surgealloy, 15)); size = 2; maxNodes = 2; laserRange = 30f; }}; diode = new PowerDiode("diode"){{ - requirements(Category.power, ItemStack.with(Items.silicon, 10, Items.plastanium, 5, Items.metaglass, 10)); + requirements(Category.power, with(Items.silicon, 10, Items.plastanium, 5, Items.metaglass, 10)); }}; battery = new Battery("battery"){{ - requirements(Category.power, ItemStack.with(Items.copper, 4, Items.lead, 20)); + requirements(Category.power, with(Items.copper, 4, Items.lead, 20)); consumes.powerBuffered(4000f); }}; batteryLarge = new Battery("battery-large"){{ - requirements(Category.power, ItemStack.with(Items.titanium, 20, Items.lead, 40, Items.silicon, 20)); + requirements(Category.power, with(Items.titanium, 20, Items.lead, 40, Items.silicon, 20)); size = 3; consumes.powerBuffered(50000f); }}; combustionGenerator = new BurnerGenerator("combustion-generator"){{ - requirements(Category.power, ItemStack.with(Items.copper, 25, Items.lead, 15)); + requirements(Category.power, with(Items.copper, 25, Items.lead, 15)); powerProduction = 1f; itemDuration = 120f; }}; thermalGenerator = new ThermalGenerator("thermal-generator"){{ - requirements(Category.power, ItemStack.with(Items.copper, 40, Items.graphite, 35, Items.lead, 50, Items.silicon, 35, Items.metaglass, 40)); + requirements(Category.power, with(Items.copper, 40, Items.graphite, 35, Items.lead, 50, Items.silicon, 35, Items.metaglass, 40)); powerProduction = 1.8f; generateEffect = Fx.redgeneratespark; size = 2; }}; turbineGenerator = new BurnerGenerator("turbine-generator"){{ - requirements(Category.power, ItemStack.with(Items.copper, 35, Items.graphite, 25, Items.lead, 40, Items.silicon, 30)); + requirements(Category.power, with(Items.copper, 35, Items.graphite, 25, Items.lead, 40, Items.silicon, 30)); powerProduction = 6f; itemDuration = 90f; consumes.liquid(Liquids.water, 0.05f); @@ -1112,7 +1123,7 @@ public class Blocks implements ContentList{ }}; differentialGenerator = new SingleTypeGenerator("differential-generator"){{ - requirements(Category.power, ItemStack.with(Items.copper, 70, Items.titanium, 50, Items.lead, 100, Items.silicon, 65, Items.metaglass, 50)); + requirements(Category.power, with(Items.copper, 70, Items.titanium, 50, Items.lead, 100, Items.silicon, 65, Items.metaglass, 50)); powerProduction = 16f; itemDuration = 140f; hasLiquids = true; @@ -1124,25 +1135,25 @@ public class Blocks implements ContentList{ }}; rtgGenerator = new DecayGenerator("rtg-generator"){{ - requirements(Category.power, ItemStack.with(Items.lead, 100, Items.silicon, 75, Items.phasefabric, 25, Items.plastanium, 75, Items.thorium, 50)); + requirements(Category.power, with(Items.lead, 100, Items.silicon, 75, Items.phasefabric, 25, Items.plastanium, 75, Items.thorium, 50)); size = 2; powerProduction = 4f; itemDuration = 500f; }}; solarPanel = new SolarGenerator("solar-panel"){{ - requirements(Category.power, ItemStack.with(Items.lead, 10, Items.silicon, 15)); + requirements(Category.power, with(Items.lead, 10, Items.silicon, 15)); powerProduction = 0.06f; }}; largeSolarPanel = new SolarGenerator("solar-panel-large"){{ - requirements(Category.power, ItemStack.with(Items.lead, 100, Items.silicon, 145, Items.phasefabric, 15)); + requirements(Category.power, with(Items.lead, 100, Items.silicon, 145, Items.phasefabric, 15)); size = 3; powerProduction = 0.9f; }}; thoriumReactor = new NuclearReactor("thorium-reactor"){{ - requirements(Category.power, ItemStack.with(Items.lead, 300, Items.silicon, 200, Items.graphite, 150, Items.thorium, 150, Items.metaglass, 50)); + requirements(Category.power, with(Items.lead, 300, Items.silicon, 200, Items.graphite, 150, Items.thorium, 150, Items.metaglass, 50)); size = 3; health = 700; itemDuration = 360f; @@ -1153,7 +1164,7 @@ public class Blocks implements ContentList{ }}; impactReactor = new ImpactReactor("impact-reactor"){{ - requirements(Category.power, ItemStack.with(Items.lead, 500, Items.silicon, 300, Items.graphite, 400, Items.thorium, 100, Items.surgealloy, 250, Items.metaglass, 250)); + requirements(Category.power, with(Items.lead, 500, Items.silicon, 300, Items.graphite, 400, Items.thorium, 100, Items.surgealloy, 250, Items.metaglass, 250)); size = 4; health = 900; powerProduction = 130f; @@ -1167,7 +1178,7 @@ public class Blocks implements ContentList{ //region production mechanicalDrill = new Drill("mechanical-drill"){{ - requirements(Category.production, ItemStack.with(Items.copper, 12), true); + requirements(Category.production, with(Items.copper, 12), true); tier = 2; drillTime = 600; size = 2; @@ -1176,7 +1187,7 @@ public class Blocks implements ContentList{ }}; pneumaticDrill = new Drill("pneumatic-drill"){{ - requirements(Category.production, ItemStack.with(Items.copper, 18, Items.graphite, 10)); + requirements(Category.production, with(Items.copper, 18, Items.graphite, 10)); tier = 3; drillTime = 400; size = 2; @@ -1185,7 +1196,7 @@ public class Blocks implements ContentList{ }}; laserDrill = new Drill("laser-drill"){{ - requirements(Category.production, ItemStack.with(Items.copper, 35, Items.graphite, 30, Items.silicon, 30, Items.titanium, 20)); + requirements(Category.production, with(Items.copper, 35, Items.graphite, 30, Items.silicon, 30, Items.titanium, 20)); drillTime = 280; size = 3; hasPower = true; @@ -1198,7 +1209,7 @@ public class Blocks implements ContentList{ }}; blastDrill = new Drill("blast-drill"){{ - requirements(Category.production, ItemStack.with(Items.copper, 65, Items.silicon, 60, Items.titanium, 50, Items.thorium, 75)); + requirements(Category.production, with(Items.copper, 65, Items.silicon, 60, Items.titanium, 50, Items.thorium, 75)); drillTime = 280; size = 4; drawRim = true; @@ -1215,7 +1226,7 @@ public class Blocks implements ContentList{ }}; waterExtractor = new SolidPump("water-extractor"){{ - requirements(Category.production, ItemStack.with(Items.copper, 25, Items.graphite, 25, Items.lead, 20)); + requirements(Category.production, with(Items.copper, 25, Items.graphite, 25, Items.lead, 20)); result = Liquids.water; pumpAmount = 0.11f; size = 2; @@ -1227,7 +1238,7 @@ public class Blocks implements ContentList{ }}; cultivator = new Cultivator("cultivator"){{ - requirements(Category.production, ItemStack.with(Items.copper, 10, Items.lead, 25, Items.silicon, 10)); + requirements(Category.production, with(Items.copper, 10, Items.lead, 25, Items.silicon, 10)); outputItem = new ItemStack(Items.sporePod, 1); craftTime = 140; size = 2; @@ -1240,7 +1251,7 @@ public class Blocks implements ContentList{ }}; oilExtractor = new Fracker("oil-extractor"){{ - requirements(Category.production, ItemStack.with(Items.copper, 150, Items.graphite, 175, Items.lead, 115, Items.thorium, 115, Items.silicon, 75)); + requirements(Category.production, with(Items.copper, 150, Items.graphite, 175, Items.lead, 115, Items.thorium, 115, Items.silicon, 75)); result = Liquids.oil; updateEffect = Fx.pulverize; liquidCapacity = 50f; @@ -1259,44 +1270,47 @@ public class Blocks implements ContentList{ //region storage coreShard = new CoreBlock("core-shard"){{ - requirements(Category.effect, BuildVisibility.hidden, ItemStack.with()); + requirements(Category.effect, BuildVisibility.hidden, with(Items.copper, 1000, Items.lead, 1000)); alwaysUnlocked = true; + unitType = UnitTypes.alpha; health = 1100; itemCapacity = 4000; size = 3; }}; coreFoundation = new CoreBlock("core-foundation"){{ - requirements(Category.effect, BuildVisibility.hidden, ItemStack.with()); + requirements(Category.effect, with(Items.copper, 3000, Items.lead, 3000, Items.silicon, 2000)); + unitType = UnitTypes.beta; health = 2000; itemCapacity = 9000; size = 4; }}; coreNucleus = new CoreBlock("core-nucleus"){{ - requirements(Category.effect, BuildVisibility.hidden, ItemStack.with()); + requirements(Category.effect, with(Items.copper, 1000, Items.lead, 1000)); + unitType = UnitTypes.gamma; health = 4000; itemCapacity = 13000; size = 5; }}; vault = new StorageBlock("vault"){{ - requirements(Category.effect, ItemStack.with(Items.titanium, 250, Items.thorium, 125)); + requirements(Category.effect, with(Items.titanium, 250, Items.thorium, 125)); size = 3; itemCapacity = 1000; }}; container = new StorageBlock("container"){{ - requirements(Category.effect, ItemStack.with(Items.titanium, 100)); + requirements(Category.effect, with(Items.titanium, 100)); size = 2; itemCapacity = 300; }}; unloader = new Unloader("unloader"){{ - requirements(Category.effect, ItemStack.with(Items.titanium, 25, Items.silicon, 30)); + requirements(Category.effect, with(Items.titanium, 25, Items.silicon, 30)); speed = 7f; }}; @@ -1304,7 +1318,7 @@ public class Blocks implements ContentList{ //region turrets duo = new ItemTurret("duo"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 35), true); + requirements(Category.turret, with(Items.copper, 35), true); ammo( Items.copper, Bullets.standardCopper, Items.graphite, Bullets.standardDense, @@ -1326,14 +1340,14 @@ public class Blocks implements ContentList{ }}; scatter = new ItemTurret("scatter"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 85, Items.lead, 45)); + requirements(Category.turret, with(Items.copper, 85, Items.lead, 45)); ammo( Items.scrap, Bullets.flakScrap, Items.lead, Bullets.flakLead, Items.metaglass, Bullets.flakGlass ); reloadTime = 18f; - range = 170f; + range = 160f; size = 2; burstSpacing = 5f; shots = 2; @@ -1349,7 +1363,7 @@ public class Blocks implements ContentList{ }}; scorch = new ItemTurret("scorch"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 25, Items.graphite, 22)); + requirements(Category.turret, with(Items.copper, 25, Items.graphite, 22)); ammo( Items.coal, Bullets.basicFlame, Items.pyratite, Bullets.pyraFlame @@ -1366,7 +1380,7 @@ public class Blocks implements ContentList{ }}; hail = new ItemTurret("hail"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 40, Items.graphite, 17)); + requirements(Category.turret, with(Items.copper, 40, Items.graphite, 17)); ammo( Items.graphite, Bullets.artilleryDense, Items.silicon, Bullets.artilleryHoming, @@ -1383,7 +1397,7 @@ public class Blocks implements ContentList{ }}; wave = new LiquidTurret("wave"){{ - requirements(Category.turret, ItemStack.with(Items.metaglass, 45, Items.lead, 75)); + requirements(Category.turret, with(Items.metaglass, 45, Items.lead, 75)); ammo( Liquids.water, Bullets.waterShot, Liquids.slag, Bullets.slagShot, @@ -1404,12 +1418,11 @@ public class Blocks implements ContentList{ }}; lancer = new ChargeTurret("lancer"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 25, Items.lead, 50, Items.silicon, 45)); + requirements(Category.turret, with(Items.copper, 25, Items.lead, 50, Items.silicon, 45)); range = 155f; chargeTime = 50f; chargeMaxDelay = 30f; chargeEffects = 7; - shootType = Bullets.lancerLaser; recoilAmount = 2f; reloadTime = 90f; cooldown = 0.03f; @@ -1424,11 +1437,24 @@ public class Blocks implements ContentList{ health = 280 * size * size; targetAir = false; shootSound = Sounds.laser; + + shootType = new LaserBulletType(140){{ + colors = new Color[]{Pal.lancerLaser.cpy().mul(1f, 1f, 1f, 0.4f), Pal.lancerLaser, Color.white}; + hitEffect = Fx.hitLancer; + despawnEffect = Fx.none; + hitSize = 4; + lifetime = 16f; + drawSize = 400f; + }}; }}; arc = new PowerTurret("arc"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 35, Items.lead, 50)); - shootType = Bullets.arc; + requirements(Category.turret, with(Items.copper, 35, Items.lead, 50)); + shootType = new LightningBulletType(){{ + damage = 21; + lightningLength = 25; + collidesAir = false; + }}; reloadTime = 35f; shootCone = 40f; rotatespeed = 8f; @@ -1444,7 +1470,7 @@ public class Blocks implements ContentList{ }}; swarmer = new ItemTurret("swarmer"){{ - requirements(Category.turret, ItemStack.with(Items.graphite, 35, Items.titanium, 35, Items.plastanium, 45, Items.silicon, 30)); + requirements(Category.turret, with(Items.graphite, 35, Items.titanium, 35, Items.plastanium, 45, Items.silicon, 30)); ammo( Items.blastCompound, Bullets.missileExplosive, Items.pyratite, Bullets.missileIncendiary, @@ -1462,7 +1488,7 @@ public class Blocks implements ContentList{ }}; salvo = new ItemTurret("salvo"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 105, Items.graphite, 95, Items.titanium, 60)); + requirements(Category.turret, with(Items.copper, 105, Items.graphite, 95, Items.titanium, 60)); ammo( Items.copper, Bullets.standardCopper, Items.graphite, Bullets.standardDense, @@ -1487,7 +1513,7 @@ public class Blocks implements ContentList{ }}; fuse = new ItemTurret("fuse"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 225, Items.graphite, 225, Items.thorium, 100)); + requirements(Category.turret, with(Items.copper, 225, Items.graphite, 225, Items.thorium, 100)); reloadTime = 35f; shootShake = 4f; @@ -1502,46 +1528,15 @@ public class Blocks implements ContentList{ health = 220 * size * size; shootSound = Sounds.shotgun; - ammo(Items.thorium, new BulletType(0.01f, 105){ - int rays = 1; - float rayLength = range + 10f; - - { - hitEffect = Fx.hitLancer; - shootEffect = smokeEffect = Fx.lightningShoot; - lifetime = 10f; - despawnEffect = Fx.none; - ammoMultiplier = 6f; - pierce = true; - } - - @Override - public void init(Bulletc b){ - for(int i = 0; i < rays; i++){ - Damage.collideLine(b, b.team(), hitEffect, b.x(), b.y(), b.rotation(), rayLength - Math.abs(i - (rays / 2)) * 20f); - } - } - - @Override - public void draw(Bulletc b){ - super.draw(b); - Draw.color(Color.white, Pal.lancerLaser, b.fin()); - //Draw.alpha(b.fout()); - for(int i = 0; i < 7; i++){ - Tmp.v1.trns(b.rotation(), i * 8f); - float sl = Mathf.clamp(b.fout() - 0.5f) * (80f - i * 10); - Drawf.tri(b.x() + Tmp.v1.x, b.y() + Tmp.v1.y, 4f, sl, b.rotation() + 90); - Drawf.tri(b.x() + Tmp.v1.x, b.y() + Tmp.v1.y, 4f, sl, b.rotation() - 90); - } - Drawf.tri(b.x(), b.y(), 20f * b.fout(), (rayLength + 50), b.rotation()); - Drawf.tri(b.x(), b.y(), 20f * b.fout(), 10f, b.rotation() + 180f); - Draw.reset(); - } - }); + ammo(Items.thorium, new ShrapnelBulletType(){{ + length = range + 10f; + damage = 105f; + ammoMultiplier = 6f; + }}); }}; ripple = new ItemTurret("ripple"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 150, Items.graphite, 135, Items.titanium, 60)); + requirements(Category.turret, with(Items.copper, 150, Items.graphite, 135, Items.titanium, 60)); ammo( Items.graphite, Bullets.artilleryDense, Items.silicon, Bullets.artilleryHoming, @@ -1570,12 +1565,12 @@ public class Blocks implements ContentList{ }}; cyclone = new ItemTurret("cyclone"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 200, Items.titanium, 125, Items.plastanium, 80)); + requirements(Category.turret, with(Items.copper, 200, Items.titanium, 125, Items.plastanium, 80)); ammo( - Items.metaglass, Bullets.flakGlass, - Items.blastCompound, Bullets.flakExplosive, - Items.plastanium, Bullets.flakPlastic, - Items.surgealloy, Bullets.flakSurge + Items.metaglass, Bullets.fragGlass, + Items.blastCompound, Bullets.fragExplosive, + Items.plastanium, Bullets.fragPlastic, + Items.surgealloy, Bullets.fragSurge ); xRand = 4f; reloadTime = 6f; @@ -1591,7 +1586,7 @@ public class Blocks implements ContentList{ }}; spectre = new ItemTurret("spectre"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 350, Items.graphite, 300, Items.surgealloy, 250, Items.plastanium, 175, Items.thorium, 250)); + requirements(Category.turret, with(Items.copper, 350, Items.graphite, 300, Items.surgealloy, 250, Items.plastanium, 175, Items.thorium, 250)); ammo( Items.graphite, Bullets.standardDenseBig, Items.pyratite, Bullets.standardIncendiaryBig, @@ -1617,8 +1612,7 @@ public class Blocks implements ContentList{ }}; meltdown = new LaserTurret("meltdown"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 250, Items.lead, 350, Items.graphite, 300, Items.surgealloy, 325, Items.silicon, 325)); - shootType = Bullets.meltdownLaser; + requirements(Category.turret, with(Items.copper, 250, Items.lead, 350, Items.graphite, 300, Items.surgealloy, 325, Items.silicon, 325)); shootEffect = Fx.shootBigSmoke2; shootCone = 40f; recoilAmount = 4f; @@ -1633,12 +1627,22 @@ public class Blocks implements ContentList{ activeSound = Sounds.beam; activeSoundVolume = 2f; + shootType = new ContinuousLaserBulletType(70){{ + length = 220f; + hitEffect = Fx.hitMeltdown; + drawSize = 420f; + + incendChance = 0.4f; + incendSpread = 5f; + incendAmount = 1; + }}; + health = 200 * size * size; consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.5f)).update(false); }}; segment = new PointDefenseTurret("segment"){{ - requirements(Category.turret, ItemStack.with(Items.silicon, 80, Items.thorium, 80, Items.surgealloy, 50)); + requirements(Category.turret, with(Items.silicon, 80, Items.thorium, 80, Items.surgealloy, 50)); hasPower = true; consumes.power(3f); @@ -1649,36 +1653,49 @@ public class Blocks implements ContentList{ health = 190 * size * size; }}; + parallax = new TractorBeamTurret("parallax"){{ + requirements(Category.turret, with(Items.silicon, 120, Items.titanium, 90)); + + hasPower = true; + size = 2; + force = 2.5f; + scaledForce = 5f; + range = 170f; + damage = 0.08f; + health = 160 * size * size; + rotateSpeed = 10; + + consumes.power(3f); + }}; + //endregion //region units groundFactory = new UnitFactory("ground-factory"){{ - requirements(Category.units, ItemStack.with(Items.copper, 30, Items.lead, 70)); + requirements(Category.units, with(Items.copper, 30, Items.lead, 70)); plans = new UnitPlan[]{ - new UnitPlan(UnitTypes.dagger, 200f, ItemStack.with(Items.silicon, 10, Items.lead, 10)), - new UnitPlan(UnitTypes.crawler, 200f, ItemStack.with(Items.silicon, 10, Items.blastCompound, 5)), - new UnitPlan(UnitTypes.tau, 200f, ItemStack.with(Items.silicon, 20, Items.lead, 10)), + new UnitPlan(UnitTypes.dagger, 200f, with(Items.silicon, 10, Items.lead, 10)), + new UnitPlan(UnitTypes.crawler, 200f, with(Items.silicon, 10, Items.blastCompound, 10)), + new UnitPlan(UnitTypes.nova, 200f, with(Items.silicon, 20, Items.lead, 20, Items.titanium, 20)), }; size = 3; consumes.power(1.2f); }}; airFactory = new UnitFactory("air-factory"){{ - requirements(Category.units, ItemStack.with(Items.copper, 30, Items.lead, 70)); + requirements(Category.units, with(Items.copper, 30, Items.lead, 70)); plans = new UnitPlan[]{ - new UnitPlan(UnitTypes.wraith, 200f, ItemStack.with(Items.silicon, 10)), - new UnitPlan(UnitTypes.spirit, 200f, ItemStack.with(Items.silicon, 10)), - new UnitPlan(UnitTypes.draug, 200f, ItemStack.with(Items.silicon, 10)), - new UnitPlan(UnitTypes.phantom, 200f, ItemStack.with(Items.silicon, 10)), + new UnitPlan(UnitTypes.flare, 200f, with(Items.silicon, 10)), + new UnitPlan(UnitTypes.mono, 200f, with(Items.silicon, 15, Items.lead, 15)), }; size = 3; consumes.power(1.2f); }}; navalFactory = new UnitFactory("naval-factory"){{ - requirements(Category.units, ItemStack.with(Items.copper, 30, Items.lead, 70)); + requirements(Category.units, with(Items.copper, 30, Items.lead, 70)); plans = new UnitPlan[]{ - new UnitPlan(UnitTypes.vanguard, 200f, ItemStack.with(Items.silicon, 10)), + new UnitPlan(UnitTypes.risse, 200f, with(Items.silicon, 10)), }; size = 3; requiresWater = true; @@ -1686,76 +1703,82 @@ public class Blocks implements ContentList{ }}; additiveReconstructor = new Reconstructor("additive-reconstructor"){{ - requirements(Category.units, ItemStack.with(Items.copper, 50, Items.lead, 120, Items.silicon, 230)); + requirements(Category.units, with(Items.copper, 50, Items.lead, 120, Items.silicon, 230)); size = 3; consumes.power(3f); - consumes.items(ItemStack.with(Items.silicon, 40, Items.graphite, 30)); + consumes.items(with(Items.silicon, 40, Items.graphite, 40)); constructTime = 60f * 5f; upgrades = new UnitType[][]{ - {UnitTypes.tau, UnitTypes.oculon}, + {UnitTypes.nova, UnitTypes.quasar}, {UnitTypes.dagger, UnitTypes.mace}, - {UnitTypes.crawler, UnitTypes.eruptor}, - {UnitTypes.wraith, UnitTypes.ghoul}, + {UnitTypes.crawler, UnitTypes.atrax}, + {UnitTypes.flare, UnitTypes.horizon}, + {UnitTypes.mono, UnitTypes.poly}, + {UnitTypes.risse, UnitTypes.minke}, }; }}; multiplicativeReconstructor = new Reconstructor("multiplicative-reconstructor"){{ - requirements(Category.units, ItemStack.with(Items.copper, 50, Items.lead, 120, Items.silicon, 230)); + requirements(Category.units, with(Items.copper, 50, Items.lead, 120, Items.silicon, 230)); size = 5; consumes.power(6f); - consumes.items(ItemStack.with(Items.silicon, 120, Items.titanium, 80)); + consumes.items(with(Items.silicon, 130, Items.titanium, 80, Items.metaglass, 30)); constructTime = 60f * 15f; upgrades = new UnitType[][]{ - {UnitTypes.ghoul, UnitTypes.revenant}, + {UnitTypes.horizon, UnitTypes.zenith}, {UnitTypes.mace, UnitTypes.fortress}, + {UnitTypes.poly, UnitTypes.mega}, + {UnitTypes.minke, UnitTypes.bryde}, + {UnitTypes.quasar, UnitTypes.pulsar}, + {UnitTypes.atrax, UnitTypes.spiroct}, }; }}; exponentialReconstructor = new Reconstructor("exponential-reconstructor"){{ - requirements(Category.units, ItemStack.with(Items.copper, 50, Items.lead, 120, Items.silicon, 230)); + requirements(Category.units, with(Items.copper, 50, Items.lead, 120, Items.silicon, 230)); size = 7; consumes.power(12f); - consumes.items(ItemStack.with(Items.silicon, 200, Items.titanium, 200, Items.surgealloy, 200)); + consumes.items(with(Items.silicon, 200, Items.titanium, 200, Items.surgealloy, 240)); consumes.liquid(Liquids.cryofluid, 1f); constructTime = 60f * 60f; upgrades = new UnitType[][]{ - {UnitTypes.revenant, UnitTypes.lich}, + {UnitTypes.zenith, UnitTypes.antumbra}, }; }}; tetrativeReconstructor = new Reconstructor("tetrative-reconstructor"){{ - requirements(Category.units, ItemStack.with(Items.copper, 50, Items.lead, 120, Items.silicon, 230)); + requirements(Category.units, with(Items.copper, 50, Items.lead, 120, Items.silicon, 230)); size = 9; consumes.power(25f); - consumes.items(ItemStack.with(Items.silicon, 300, Items.plastanium, 300, Items.surgealloy, 300, Items.phasefabric, 250)); + consumes.items(with(Items.silicon, 300, Items.plastanium, 300, Items.surgealloy, 300, Items.phasefabric, 250)); consumes.liquid(Liquids.cryofluid, 3f); constructTime = 60f * 60f * 3; upgrades = new UnitType[][]{ - {UnitTypes.lich, UnitTypes.reaper}, + {UnitTypes.antumbra, UnitTypes.eclipse}, }; }}; repairPoint = new RepairPoint("repair-point"){{ - requirements(Category.units, ItemStack.with(Items.lead, 15, Items.copper, 15, Items.silicon, 15)); + requirements(Category.units, with(Items.lead, 15, Items.copper, 15, Items.silicon, 15)); repairSpeed = 0.5f; repairRadius = 65f; powerUse = 1f; }}; resupplyPoint = new ResupplyPoint("resupply-point"){{ - requirements(Category.units, BuildVisibility.ammoOnly, ItemStack.with(Items.lead, 20, Items.copper, 15, Items.silicon, 15)); + requirements(Category.units, BuildVisibility.ammoOnly, with(Items.lead, 20, Items.copper, 15, Items.silicon, 15)); size = 2; range = 80f; @@ -1767,41 +1790,41 @@ public class Blocks implements ContentList{ //region sandbox powerSource = new PowerSource("power-source"){{ - requirements(Category.power, BuildVisibility.sandboxOnly, ItemStack.with()); + requirements(Category.power, BuildVisibility.sandboxOnly, with()); alwaysUnlocked = true; }}; powerVoid = new PowerVoid("power-void"){{ - requirements(Category.power, BuildVisibility.sandboxOnly, ItemStack.with()); + requirements(Category.power, BuildVisibility.sandboxOnly, with()); alwaysUnlocked = true; }}; itemSource = new ItemSource("item-source"){{ - requirements(Category.distribution, BuildVisibility.sandboxOnly, ItemStack.with()); + requirements(Category.distribution, BuildVisibility.sandboxOnly, with()); alwaysUnlocked = true; }}; itemVoid = new ItemVoid("item-void"){{ - requirements(Category.distribution, BuildVisibility.sandboxOnly, ItemStack.with()); + requirements(Category.distribution, BuildVisibility.sandboxOnly, with()); alwaysUnlocked = true; }}; liquidSource = new LiquidSource("liquid-source"){{ - requirements(Category.liquid, BuildVisibility.sandboxOnly, ItemStack.with()); + requirements(Category.liquid, BuildVisibility.sandboxOnly, with()); alwaysUnlocked = true; }}; liquidVoid = new LiquidVoid("liquid-void"){{ - requirements(Category.liquid, BuildVisibility.sandboxOnly, ItemStack.with()); + requirements(Category.liquid, BuildVisibility.sandboxOnly, with()); alwaysUnlocked = true; }}; message = new MessageBlock("message"){{ - requirements(Category.effect, ItemStack.with(Items.graphite, 5)); + requirements(Category.effect, with(Items.graphite, 5)); }}; illuminator = new LightBlock("illuminator"){{ - requirements(Category.effect, BuildVisibility.lightingOnly, ItemStack.with(Items.graphite, 4, Items.silicon, 2)); + requirements(Category.effect, BuildVisibility.lightingOnly, with(Items.graphite, 4, Items.silicon, 2)); brightness = 0.67f; radius = 120f; consumes.power(0.05f); @@ -1819,7 +1842,7 @@ public class Blocks implements ContentList{ //region campaign launchPad = new LaunchPad("launch-pad"){{ - requirements(Category.effect, BuildVisibility.campaignOnly, ItemStack.with(Items.copper, 350, Items.silicon, 140, Items.lead, 200, Items.titanium, 150)); + requirements(Category.effect, BuildVisibility.campaignOnly, with(Items.copper, 350, Items.silicon, 140, Items.lead, 200, Items.titanium, 150)); size = 3; itemCapacity = 100; launchTime = 60f * 20; @@ -1827,8 +1850,9 @@ public class Blocks implements ContentList{ consumes.power(4f); }}; + //TODO remove launchPadLarge = new LaunchPad("launch-pad-large"){{ - requirements(Category.effect, BuildVisibility.campaignOnly, ItemStack.with(Items.titanium, 200, Items.silicon, 150, Items.lead, 250, Items.plastanium, 75)); + //requirements(Category.effect, BuildVisibility.campaignOnly, with(Items.titanium, 200, Items.silicon, 150, Items.lead, 250, Items.plastanium, 75)); size = 4; itemCapacity = 300; launchTime = 60f * 35; @@ -1837,7 +1861,7 @@ public class Blocks implements ContentList{ }}; dataProcessor = new ResearchBlock("data-processor"){{ - requirements(Category.effect, BuildVisibility.campaignOnly, ItemStack.with(Items.copper, 200, Items.lead, 100)); + //requirements(Category.effect, BuildVisibility.campaignOnly, with(Items.copper, 200, Items.lead, 100)); size = 3; alwaysUnlocked = true; @@ -1847,21 +1871,21 @@ public class Blocks implements ContentList{ //region experimental blockForge = new BlockForge("block-forge"){{ - requirements(Category.production, BuildVisibility.debugOnly, ItemStack.with(Items.thorium, 100)); + requirements(Category.production, BuildVisibility.debugOnly, with(Items.thorium, 100)); hasPower = true; consumes.power(2f); size = 3; }}; blockLoader = new BlockLoader("block-loader"){{ - requirements(Category.production, BuildVisibility.debugOnly, ItemStack.with(Items.thorium, 100)); + requirements(Category.production, BuildVisibility.debugOnly, with(Items.thorium, 100)); hasPower = true; consumes.power(2f); size = 3; }}; blockUnloader = new BlockUnloader("block-unloader"){{ - requirements(Category.production, BuildVisibility.debugOnly, ItemStack.with(Items.thorium, 100)); + requirements(Category.production, BuildVisibility.debugOnly, with(Items.thorium, 100)); hasPower = true; consumes.power(2f); size = 3; diff --git a/core/src/mindustry/content/Bullets.java b/core/src/mindustry/content/Bullets.java index 9d764a538a..a1bea100c8 100644 --- a/core/src/mindustry/content/Bullets.java +++ b/core/src/mindustry/content/Bullets.java @@ -9,6 +9,7 @@ import mindustry.entities.*; import mindustry.entities.bullet.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.io.*; import mindustry.world.*; import static mindustry.Vars.*; @@ -20,23 +21,23 @@ public class Bullets implements ContentList{ artilleryDense, artilleryPlastic, artilleryPlasticFrag, artilleryHoming, artilleryIncendiary, artilleryExplosive, //flak - flakScrap, flakLead, flakPlastic, flakExplosive, flakSurge, flakGlass, glassFrag, + flakScrap, flakLead, flakGlass, flakGlassFrag, + + //frag (flak-like but hits ground) + fragGlass, fragExplosive, fragPlastic, fragSurge, fragGlassFrag, fragPlasticFrag, //missiles - missileExplosive, missileIncendiary, missileSurge, missileJavelin, missileSwarm, + missileExplosive, missileIncendiary, missileSurge, missileSwarm, //standard standardCopper, standardDense, standardThorium, standardHoming, standardIncendiary, standardMechSmall, standardGlaive, standardDenseBig, standardThoriumBig, standardIncendiaryBig, - //electric - lancerLaser, meltdownLaser, arc, damageLightning, - //liquid waterShot, cryoShot, slagShot, oilShot, //environment, misc. - fireball, basicFlame, pyraFlame, driverBolt, healBullet, healBulletBig, frag, + damageLightning, damageLightningGround, fireball, basicFlame, pyraFlame, driverBolt, healBullet, healBulletBig, frag, //bombs bombExplosive, bombIncendiary, bombOil; @@ -62,6 +63,7 @@ public class Bullets implements ContentList{ backColor = Pal.plastaniumBack; frontColor = Pal.plastaniumFront; despawnEffect = Fx.none; + collidesAir = false; }}; artilleryPlastic = new ArtilleryBulletType(3.4f, 12, "shell"){{ @@ -122,7 +124,7 @@ public class Bullets implements ContentList{ statusDuration = 60f; }}; - glassFrag = new BasicBulletType(3f, 5, "bullet"){{ + flakGlassFrag = new BasicBulletType(3f, 5, "bullet"){{ width = 5f; height = 12f; shrinkY = 1f; @@ -130,6 +132,7 @@ public class Bullets implements ContentList{ backColor = Pal.gray; frontColor = Color.white; despawnEffect = Fx.none; + collidesGround = false; }}; flakLead = new FlakBulletType(4.2f, 3){{ @@ -165,37 +168,78 @@ public class Bullets implements ContentList{ hitEffect = Fx.flakExplosion; splashDamage = 20f; splashDamageRadius = 20f; - fragBullet = glassFrag; + fragBullet = flakGlassFrag; fragBullets = 5; }}; - flakPlastic = new FlakBulletType(4f, 6){{ - splashDamageRadius = 50f; + fragGlassFrag = new BasicBulletType(3f, 5, "bullet"){{ + width = 5f; + height = 12f; + shrinkY = 1f; + lifetime = 20f; + backColor = Pal.gray; + frontColor = Color.white; + despawnEffect = Fx.none; + }}; + + fragPlasticFrag = new BasicBulletType(2.5f, 10, "bullet"){{ + width = 10f; + height = 12f; + shrinkY = 1f; + lifetime = 15f; + backColor = Pal.plastaniumBack; + frontColor = Pal.plastaniumFront; + despawnEffect = Fx.none; + }}; + + fragGlass = new FlakBulletType(4f, 3){{ + lifetime = 70f; + ammoMultiplier = 5f; + shootEffect = Fx.shootSmall; + reloadMultiplier = 0.8f; + width = 6f; + height = 8f; + hitEffect = Fx.flakExplosion; + splashDamage = 18f; + splashDamageRadius = 16f; + fragBullet = flakGlassFrag; + fragBullets = 3; + explodeRange = 20f; + collidesGround = true; + }}; + + fragPlastic = new FlakBulletType(4f, 6){{ + splashDamageRadius = 40f; splashDamage = 25f; - fragBullet = artilleryPlasticFrag; - fragBullets = 6; + fragBullet = fragPlasticFrag; + fragBullets = 5; hitEffect = Fx.plasticExplosion; frontColor = Pal.plastaniumFront; backColor = Pal.plastaniumBack; shootEffect = Fx.shootBig; + collidesGround = true; + explodeRange = 20f; }}; - flakExplosive = new FlakBulletType(4f, 5){{ + fragExplosive = new FlakBulletType(4f, 5){{ shootEffect = Fx.shootBig; ammoMultiplier = 4f; splashDamage = 15f; splashDamageRadius = 34f; + collidesGround = true; status = StatusEffects.blasted; statusDuration = 60f; }}; - flakSurge = new FlakBulletType(4.5f, 13){{ + fragSurge = new FlakBulletType(4.5f, 13){{ splashDamage = 45f; splashDamageRadius = 40f; lightning = 2; lightningLength = 7; shootEffect = Fx.shootBig; + collidesGround = true; + explodeRange = 20f; }}; missileExplosive = new MissileBulletType(2.7f, 10, "missile"){{ @@ -243,24 +287,6 @@ public class Bullets implements ContentList{ lightningLength = 14; }}; - missileJavelin = new MissileBulletType(5f, 10.5f, "missile"){{ - width = 8f; - height = 8f; - shrinkY = 0f; - drag = -0.003f; - keepVelocity = false; - splashDamageRadius = 20f; - splashDamage = 1f; - lifetime = 90f; - trailColor = Color.valueOf("b6c6fd"); - hitEffect = Fx.blastExplosion; - despawnEffect = Fx.blastExplosion; - backColor = Pal.bulletYellowBack; - frontColor = Pal.bulletYellow; - weaveScale = 8f; - weaveMag = 2f; - }}; - missileSwarm = new MissileBulletType(2.7f, 12, "missile"){{ width = 8f; height = 8f; @@ -372,6 +398,12 @@ public class Bullets implements ContentList{ hittable = false; }}; + //this is just a copy of the damage lightning bullet that doesn't damage air units + damageLightningGround = new BulletType(0.0001f, 0f){{ + collidesAir = false; + }}; + JsonIO.copy(damageLightning, damageLightningGround); + healBullet = new HealBulletType(5.2f, 13){{ healPercent = 3f; }}; @@ -390,32 +422,32 @@ public class Bullets implements ContentList{ } @Override - public void init(Bulletc b){ - b.vel().setLength(0.6f + Mathf.random(2f)); + public void init(Bullet b){ + b.vel.setLength(0.6f + Mathf.random(2f)); } @Override - public void draw(Bulletc b){ + public void draw(Bullet b){ Draw.color(Pal.lightFlame, Pal.darkFlame, Color.gray, b.fin()); - Fill.circle(b.x(), b.y(), 3f * b.fout()); + Fill.circle(b.x, b.y, 3f * b.fout()); Draw.reset(); } @Override - public void update(Bulletc b){ + public void update(Bullet b){ if(Mathf.chance(0.04 * Time.delta())){ - Tile tile = world.tileWorld(b.x(), b.y()); + Tile tile = world.tileWorld(b.x, b.y); if(tile != null){ Fires.create(tile); } } if(Mathf.chance(0.1 * Time.delta())){ - Fx.fireballsmoke.at(b.x(), b.y()); + Fx.fireballsmoke.at(b.x, b.y); } if(Mathf.chance(0.1 * Time.delta())){ - Fx.ballfire.at(b.x(), b.y()); + Fx.ballfire.at(b.x, b.y); } } }; @@ -442,7 +474,7 @@ public class Bullets implements ContentList{ } @Override - public void draw(Bulletc b){ + public void draw(Bullet b){ } }; @@ -462,29 +494,10 @@ public class Bullets implements ContentList{ } @Override - public void draw(Bulletc b){ + public void draw(Bullet b){ } }; - lancerLaser = new LaserBulletType(140){{ - colors = new Color[]{Pal.lancerLaser.cpy().mul(1f, 1f, 1f, 0.4f), Pal.lancerLaser, Color.white}; - hitEffect = Fx.hitLancer; - despawnEffect = Fx.none; - hitSize = 4; - lifetime = 16f; - drawSize = 400f; - }}; - - meltdownLaser = new ContinuousLaserBulletType(70){{ - length = 220f; - hitEffect = Fx.hitMeltdown; - drawSize = 420f; - - incendChance = 0.4f; - incendSpread = 5f; - incendAmount = 1; - }}; - waterShot = new LiquidBulletType(Liquids.water){{ knockback = 0.7f; }}; @@ -502,11 +515,6 @@ public class Bullets implements ContentList{ drag = 0.03f; }}; - arc = new LightningBulletType(){{ - damage = 21; - lightningLength = 25; - }}; - driverBolt = new MassDriverBolt(); frag = new BasicBulletType(5f, 8, "bullet"){{ @@ -549,7 +557,7 @@ public class Bullets implements ContentList{ } @Override - public void hit(Bulletc b, float x, float y){ + public void hit(Bullet b, float x, float y){ super.hit(b, x, y); for(int i = 0; i < 3; i++){ diff --git a/core/src/mindustry/content/Fx.java b/core/src/mindustry/content/Fx.java index 16d6fd9fac..b7dde19ab8 100644 --- a/core/src/mindustry/content/Fx.java +++ b/core/src/mindustry/content/Fx.java @@ -26,31 +26,31 @@ public class Fx{ none = new Effect(0, 0f, e -> {}), unitSpawn = new Effect(30f, e -> { - if(!(e.data instanceof Unitc)) return; + if(!(e.data instanceof Unit)) return; alpha(e.fin()); float scl = 1f + e.fout() * 2f; - Unitc unit = (Unitc)e.data; + Unit unit = e.data(); rect(unit.type().region, e.x, e.y, unit.type().region.getWidth() * Draw.scl * scl, unit.type().region.getHeight() * Draw.scl * scl, 180f); }), unitControl = new Effect(30f, e -> { - if(!(e.data instanceof Unitc)) return; + if(!(e.data instanceof Unit)) return; - Unitc select = (Unitc)e.data; + Unit select = e.data(); mixcol(Pal.accent, 1f); alpha(e.fout()); - rect(select.type().icon(Cicon.full), select.x(), select.y(), select.rotation() - 90f); + rect(select.type().icon(Cicon.full), select.x, select.y, select.rotation - 90f); alpha(1f); Lines.stroke(e.fslope() * 1f); - Lines.square(select.x(), select.y(), e.fout() * select.hitSize() * 2f, 45); + Lines.square(select.x, select.y, e.fout() * select.hitSize * 2f, 45); Lines.stroke(e.fslope() * 2f); - Lines.square(select.x(), select.y(), e.fout() * select.hitSize() * 3f, 45f); + Lines.square(select.x, select.y, e.fout() * select.hitSize * 3f, 45f); reset(); }), @@ -144,6 +144,12 @@ public class Fx{ Lines.circle(e.x, e.y, 4f + e.finpow() * 120f); }), + upgradeCore = new Effect(120f, e -> { + color(Color.white, Pal.accent, e.fin()); + alpha(e.fout()); + Fill.square(e.x, e.y, tilesize / 2f * e.rotation); + }), + placeBlock = new Effect(16, e -> { color(Pal.accent); stroke(3f - e.fin() * 2f); @@ -177,6 +183,27 @@ public class Fx{ Fill.circle(e.x, e.y, (7f - e.fin() * 7f)/2f); }), + fallSmoke = new Effect(110, e -> { + color(Color.gray, Color.darkGray, e.rotation); + Fill.circle(e.x, e.y, e.fout() * 3.5f); + }), + + unitWreck = new Effect(200f, e -> { + if(!(e.data instanceof TextureRegion)) return; + + Draw.mixcol(Pal.rubble, 1f); + + TextureRegion reg = e.data(); + float vel = e.fin(Interp.pow5Out) * 2f * Mathf.randomSeed(e.id, 1f); + float totalRot = Mathf.randomSeed(e.id + 1, 10f); + Tmp.v1.trns(Mathf.randomSeed(e.id + 2, 360f), vel); + + Draw.z(Mathf.lerp(Layer.flyingUnitLow, Layer.debris, e.fin())); + Draw.alpha(e.fout(Interp.pow5Out)); + + Draw.rect(reg, e.x + Tmp.v1.x, e.y + Tmp.v1.y, e.rotation - 90 + totalRot * e.fin(Interp.pow5Out)); + }), + rocketSmoke = new Effect(120, e -> { color(Color.gray); alpha(Mathf.clamp(e.fout()*1.6f - Interp.pow3In.apply(e.rotation)*1.2f)); @@ -264,6 +291,18 @@ public class Fx{ Lines.circle(e.x, e.y, 2f + e.finpow() * 7f); }), + shieldWave = new Effect(22, e -> { + color(Pal.shield); + stroke(e.fout() * 2f); + Lines.circle(e.x, e.y, 4f + e.finpow() * 60f); + }), + + shieldApply = new Effect(11, e -> { + color(Pal.shield); + stroke(e.fout() * 2f); + Lines.circle(e.x, e.y, 2f + e.finpow() * 7f); + }), + hitBulletSmall = new Effect(14, e -> { color(Color.white, Pal.lightOrange, e.fin()); @@ -593,6 +632,15 @@ public class Fx{ }), + sapped = new Effect(40f, e -> { + color(Pal.sap); + + randLenVectors(e.id, 2, 1f + e.fin() * 2f, (x, y) -> { + Fill.square(e.x + x, e.y + y, e.fslope() * 1.1f, 45f); + }); + + }), + oily = new Effect(42f, e -> { color(Liquids.oil.color); @@ -1248,15 +1296,15 @@ public class Fx{ }), shieldBreak = new Effect(40, e -> { - color(Pal.accent); + color(e.color); stroke(3f * e.fout()); - Lines.poly(e.x, e.y, 6, e.rotation + e.fin(), 90); + Lines.poly(e.x, e.y, 6, e.rotation + e.fin()); }), unitShieldBreak = new Effect(35, e -> { if(!(e.data instanceof Unitc)) return; - Unitc unit = e.data(); + Unit unit = e.data(); float radius = unit.hitSize() * 1.3f; diff --git a/core/src/mindustry/content/Items.java b/core/src/mindustry/content/Items.java index 1aea6e89c1..08f5868b76 100644 --- a/core/src/mindustry/content/Items.java +++ b/core/src/mindustry/content/Items.java @@ -1,9 +1,8 @@ package mindustry.content; -import arc.graphics.Color; -import mindustry.ctype.ContentList; -import mindustry.type.Item; -import mindustry.type.ItemType; +import arc.graphics.*; +import mindustry.ctype.*; +import mindustry.type.*; public class Items implements ContentList{ public static Item scrap, copper, lead, graphite, coal, titanium, thorium, silicon, plastanium, phasefabric, surgealloy, @@ -12,26 +11,22 @@ public class Items implements ContentList{ @Override public void load(){ copper = new Item("copper", Color.valueOf("d99d73")){{ - type = ItemType.material; hardness = 1; cost = 0.5f; alwaysUnlocked = true; }}; lead = new Item("lead", Color.valueOf("8c7fa9")){{ - type = ItemType.material; hardness = 1; cost = 0.7f; alwaysUnlocked = true; }}; metaglass = new Item("metaglass", Color.valueOf("ebeef5")){{ - type = ItemType.material; cost = 1.5f; }}; graphite = new Item("graphite", Color.valueOf("b2c6d2")){{ - type = ItemType.material; cost = 1f; }}; @@ -46,13 +41,11 @@ public class Items implements ContentList{ }}; titanium = new Item("titanium", Color.valueOf("8da1e3")){{ - type = ItemType.material; hardness = 3; cost = 1f; }}; thorium = new Item("thorium", Color.valueOf("f9a3c7")){{ - type = ItemType.material; explosiveness = 0.2f; hardness = 4; radioactivity = 1f; @@ -64,25 +57,21 @@ public class Items implements ContentList{ }}; silicon = new Item("silicon", Color.valueOf("53565c")){{ - type = ItemType.material; cost = 0.8f; }}; plastanium = new Item("plastanium", Color.valueOf("cbd97f")){{ - type = ItemType.material; flammability = 0.1f; explosiveness = 0.2f; cost = 1.3f; }}; phasefabric = new Item("phase-fabric", Color.valueOf("f4ba6e")){{ - type = ItemType.material; cost = 1.3f; radioactivity = 0.6f; }}; surgealloy = new Item("surge-alloy", Color.valueOf("f3e979")){{ - type = ItemType.material; }}; sporePod = new Item("spore-pod", Color.valueOf("7457ce")){{ diff --git a/core/src/mindustry/content/Loadouts.java b/core/src/mindustry/content/Loadouts.java index 145da6120e..2a7c4435db 100644 --- a/core/src/mindustry/content/Loadouts.java +++ b/core/src/mindustry/content/Loadouts.java @@ -6,14 +6,12 @@ import mindustry.game.*; public class Loadouts implements ContentList{ public static Schematic basicShard, - advancedShard, basicFoundation, basicNucleus; @Override public void load(){ basicShard = Schematics.readBase64("bXNjaAB4nD2K2wqAIBiD5ymibnoRn6YnEP1BwUMoBL19FuJ2sbFvUFgYZDaJsLeQrkinN9UJHImsNzlYE7WrIUastuSbnlKx2VJJt+8IQGGKdfO/8J5yrGJSMegLg+YUIA=="); - advancedShard = Schematics.readBase64("bXNjaAB4nD2LjQqAIAyET7OMIOhFfJqeYMxBgSkYCL199gu33fFtB4tOwUTaBCP5QpHFzwtl32DahBeKK1NwPq8hoOcUixwpY+CUxe3XIwBbB/pa6tadVCUP02hgHvp5vZq/0b7pBHPYFOQ="); basicFoundation = Schematics.readBase64("bXNjaAB4nD1OSQ6DMBBzFhVu8BG+0X8MQyoiJTNSukj8nlCi2Adbtg/GA4OBF8oB00rvyE/9ykafqOIw58A7SWRKy1ZiShhZ5RcOLZhYS1hefQ1gRIeptH9jq/qW2lvc1d2tgWsOfVX/tOwE86AYBA=="); basicNucleus = Schematics.readBase64("bXNjaAB4nD2MUQqAIBBEJy0s6qOLdJXuYNtCgikYBd2+LNmdj308hkGHtkId7M4YFns4mk/yfB4a48602eDI+mlNznu0FMPFd0wYKCaewl8F0EOueqM+yKSLVfJrNKWnSw/FZGzEGXFG9sy/px4gEBW1"); } diff --git a/core/src/mindustry/content/StatusEffects.java b/core/src/mindustry/content/StatusEffects.java index 173a8bd6fc..55672f886c 100644 --- a/core/src/mindustry/content/StatusEffects.java +++ b/core/src/mindustry/content/StatusEffects.java @@ -9,7 +9,7 @@ import mindustry.type.StatusEffect; import static mindustry.Vars.*; public class StatusEffects implements ContentList{ - public static StatusEffect none, burning, freezing, wet, melting, tarred, overdrive, shielded, shocked, blasted, corroded, boss; + public static StatusEffect none, burning, freezing, wet, melting, sapped, tarred, overdrive, shielded, shocked, blasted, corroded, boss; @Override public void load(){ @@ -74,6 +74,13 @@ public class StatusEffects implements ContentList{ }); }}; + sapped = new StatusEffect("sapped"){{ + speedMultiplier = 0.7f; + armorMultiplier = 0.8f; + effect = Fx.sapped; + effectChance = 0.1f; + }}; + tarred = new StatusEffect("tarred"){{ speedMultiplier = 0.6f; effect = Fx.oily; diff --git a/core/src/mindustry/content/UnitTypes.java b/core/src/mindustry/content/UnitTypes.java index b0cdd121f4..e8f685b224 100644 --- a/core/src/mindustry/content/UnitTypes.java +++ b/core/src/mindustry/content/UnitTypes.java @@ -1,76 +1,69 @@ package mindustry.content; import arc.graphics.*; -import arc.math.*; import arc.struct.*; import mindustry.ai.types.*; import mindustry.annotations.Annotations.*; import mindustry.ctype.*; +import mindustry.entities.abilities.*; import mindustry.entities.bullet.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.type.*; public class UnitTypes implements ContentList{ + //region definitions //ground - public static @EntityDef({Unitc.class, Mechc.class}) UnitType mace, dagger, crawler, fortress, chaosArray, eradicator; + public static @EntityDef({Unitc.class, Mechc.class}) UnitType mace, dagger, crawler, fortress, siegeArray, eradicator; //ground + builder - public static @EntityDef({Unitc.class, Mechc.class, Builderc.class}) UnitType tau; + public static @EntityDef({Unitc.class, Mechc.class, Builderc.class}) UnitType nova; //ground + builder + miner + commander - public static @EntityDef({Unitc.class, Mechc.class, Builderc.class, Minerc.class, Commanderc.class}) UnitType oculon; + public static @EntityDef({Unitc.class, Mechc.class, Builderc.class, Minerc.class, Commanderc.class}) UnitType pulsar, quasar; //legs - public static @EntityDef({Unitc.class, Legsc.class}) UnitType cix, eruptor; + public static @EntityDef({Unitc.class, Legsc.class}) UnitType atrax; - //air - public static @EntityDef({Unitc.class}) UnitType wraith, reaper, ghoul, revenant, lich; + //legs + building + public static @EntityDef({Unitc.class, Legsc.class, Builderc.class}) UnitType spiroct, arkyid; + + //air (no special traits) + public static @EntityDef({Unitc.class}) UnitType flare, eclipse, horizon, zenith, antumbra; //air + mining - public static @EntityDef({Unitc.class, Minerc.class}) UnitType draug; - - //air + building - public static @EntityDef({Unitc.class, Builderc.class}) UnitType phantom, spirit; + public static @EntityDef({Unitc.class, Minerc.class}) UnitType mono; //air + building + mining - //TODO implement other starter drones - public static @EntityDef({Unitc.class, Builderc.class, Minerc.class}) UnitType alpha, beta, gamma; + public static @EntityDef({Unitc.class, Builderc.class, Minerc.class}) UnitType poly; //air + building + mining + payload - public static @EntityDef({Unitc.class, Builderc.class, Minerc.class, Payloadc.class}) UnitType trident; + public static @EntityDef({Unitc.class, Builderc.class, Minerc.class, Payloadc.class}) UnitType mega; + + //air + building + mining + public static @EntityDef({Unitc.class, Builderc.class, Minerc.class, Trailc.class}) UnitType alpha, beta, gamma; //water - public static @EntityDef({Unitc.class, WaterMovec.class, Commanderc.class}) UnitType vanguard; + public static @EntityDef({Unitc.class, WaterMovec.class, Commanderc.class}) UnitType risse, minke, bryde; //special block unit type public static @EntityDef({Unitc.class, BlockUnitc.class}) UnitType block; + //endregion + @Override public void load(){ - block = new UnitType("block"){ - { - speed = 0f; - hitsize = 0f; - health = 1; - rotateSpeed = 360f; - } - - @Override - public boolean isHidden(){ - return true; - } - }; + //region ground attack dagger = new UnitType("dagger"){{ speed = 0.5f; hitsize = 8f; - health = 130; + health = 140; weapons.add(new Weapon("large-weapon"){{ reload = 14f; x = 4f; - alternate = true; + y = 2f; ejectEffect = Fx.shellEjectSmall; bullet = Bullets.standardCopper; }}); @@ -80,7 +73,8 @@ public class UnitTypes implements ContentList{ speed = 0.4f; hitsize = 9f; range = 10f; - health = 460; + health = 500; + armor = 2f; immunities.add(StatusEffects.burning); @@ -88,107 +82,24 @@ public class UnitTypes implements ContentList{ shootSound = Sounds.flame; shootY = 2f; reload = 14f; - alternate = true; recoil = 1f; ejectEffect = Fx.none; bullet = Bullets.basicFlame; }}); }}; - tau = new UnitType("tau"){{ - itemCapacity = 60; - canBoost = true; - boostMultiplier = 1.5f; - speed = 0.5f; - hitsize = 8f; - health = 100f; - buildSpeed = 0.8f; - - weapons.add(new Weapon("heal-weapon"){{ - shootY = 1.5f; - reload = 24f; - x = 1f; - shootX = 3.5f; - alternate = false; - ejectEffect = Fx.none; - recoil = 2f; - bullet = Bullets.healBullet; - shootSound = Sounds.pew; - }}); - } - - /* - - float healRange = 60f; - float healAmount = 10f; - float healReload = 160f; - boolean wasHealed; - - @Override - public void update(Unitc player){ - - if(player.timer().get(Playerc.timerAbility, healReload)){ - wasHealed = false; - - Units.nearby(player.team(), player.x, player.y, healRange, unit -> { - if(unit.health < unit.maxHealth()){ - Fx.heal.at(unit); - wasHealed = true; - } - unit.heal(healAmount); - }); - - if(wasHealed){ - Fx.healWave.at(player); - } - } - }*/ - }; - - oculon = new UnitType("oculon"){{ - drillTier = 1; - hitsize = 9f; - boostMultiplier = 2f; - itemCapacity = 20; - health = 230f; - buildSpeed = 1.5f; - canBoost = true; - - speed = 0.4f; - hitsize = 10f; - - weapons.add(new Weapon("beam-weapon"){{ - shake = 2f; - shootY = 4f; - shootX = 6f; - x = 0.25f; - reload = 50f; - alternate = true; - recoil = 4f; - shootSound = Sounds.laser; - - bullet = new LaserBulletType(){{ - damage = 20f; - recoil = 1f; - sideAngle = 45f; - sideWidth = 1f; - sideLength = 70f; - colors = new Color[]{Pal.heal.cpy().a(0.4f), Pal.heal, Color.white}; - }}; - }}); - }}; - fortress = new UnitType("fortress"){{ speed = 0.38f; hitsize = 13f; rotateSpeed = 3f; targetAir = false; - health = 750; + health = 790; + armor = 5f; + weapons.add(new Weapon("artillery"){{ y = 1f; x = 9f; reload = 60f; - alternate = true; recoil = 4f; shake = 2f; ejectEffect = Fx.shellEjectMedium; @@ -200,7 +111,7 @@ public class UnitTypes implements ContentList{ width = height = 14f; collides = true; collidesTiles = true; - splashDamageRadius = 20f; + splashDamageRadius = 24f; splashDamage = 38f; backColor = Pal.bulletYellowBack; frontColor = Pal.bulletYellow; @@ -208,12 +119,123 @@ public class UnitTypes implements ContentList{ }}); }}; + //endregion + //region ground support + + nova = new UnitType("nova"){{ + itemCapacity = 60; + canBoost = true; + boostMultiplier = 1.5f; + speed = 0.52f; + hitsize = 8f; + health = 110f; + buildSpeed = 0.8f; + armor = 1f; + + abilities.add(new HealFieldAbility(10f, 60f * 4, 60f)); + + weapons.add(new Weapon("heal-weapon"){{ + shootY = 2f; + reload = 24f; + x = 4.5f; + alternate = false; + ejectEffect = Fx.none; + recoil = 2f; + bullet = Bullets.healBullet; + shootSound = Sounds.pew; + }}); + }}; + + pulsar = new UnitType("pulsar"){{ + itemCapacity = 60; + canBoost = true; + boostMultiplier = 1.5f; + speed = 0.48f; + hitsize = 10f; + health = 300f; + buildSpeed = 0.9f; + armor = 3f; + + mineTier = 2; + mineSpeed = 5f; + commandLimit = 8; + + abilities.add(new ShieldFieldAbility(15f, 30f, 60f * 5, 60f)); + + weapons.add(new Weapon("heal-shotgun-weapon"){{ + x = 5f; + shake = 2.2f; + y = 0.5f; + shootY = 5f; + + shootY = 2.5f; + reload = 38f; + shots = 3; + inaccuracy = 35; + shotDelay = 0.5f; + spacing = 0f; + ejectEffect = Fx.none; + recoil = 2.5f; + shootSound = Sounds.pew; + + bullet = new LightningBulletType(){{ + lightningColor = hitColor = Pal.heal; + damage = 11f; + lightningLength = 7; + lightningLengthRand = 7; + shootEffect = Fx.shootHeal; + }}; + }}); + }}; + + quasar = new UnitType("quasar"){{ + mineTier = 1; + hitsize = 12f; + boostMultiplier = 2f; + itemCapacity = 80; + health = 640f; + buildSpeed = 1.7f; + canBoost = true; + armor = 6f; + landShake = 2f; + + speed = 0.4f; + hitsize = 10f; + + mineTier = 2; + mineSpeed = 7f; + drawShields = false; + + abilities.add(new ForceFieldAbility(60f, 0.12f, 200f, 60f * 8)); + + weapons.add(new Weapon("beam-weapon"){{ + shake = 2f; + shootY = 4f; + x = 6.5f; + reload = 50f; + recoil = 4f; + shootSound = Sounds.laser; + + bullet = new LaserBulletType(){{ + damage = 27f; + recoil = 1f; + sideAngle = 45f; + sideWidth = 1f; + sideLength = 70f; + colors = new Color[]{Pal.heal.cpy().a(0.4f), Pal.heal, Color.white}; + }}; + }}); + }}; + + //endregion + //region ground legs + crawler = new UnitType("crawler"){{ defaultController = SuicideAI::new; - speed = 0.8f; + speed = 0.85f; hitsize = 8f; - health = 140; + health = 170; sway = 0.25f; range = 40f; @@ -228,15 +250,15 @@ public class UnitTypes implements ContentList{ speed = 1f; splashDamageRadius = 55f; instantDisappear = true; - splashDamage = 30f; + splashDamage = 40f; killShooter = true; hittable = false; }}; }}); }}; - eruptor = new UnitType("eruptor"){{ - speed = 0.4f; + atrax = new UnitType("atrax"){{ + speed = 0.5f; drag = 0.4f; hitsize = 10f; rotateSpeed = 3f; @@ -247,11 +269,16 @@ public class UnitTypes implements ContentList{ legLength = 9f; legTrns = 0.6f; legMoveSpace = 1.4f; + hovering = true; + armor = 3f; + + allowLegStep = true; + visualElevation = 0.2f; + groundLayer = Layer.legUnit - 1f; weapons.add(new Weapon("eruption"){{ shootY = 3f; reload = 10f; - alternate = true; ejectEffect = Fx.none; recoil = 1f; x = 7f; @@ -260,18 +287,84 @@ public class UnitTypes implements ContentList{ bullet = new LiquidBulletType(Liquids.slag){{ damage = 11; speed = 2.3f; - drag = 0.02f; + drag = 0.01f; shootEffect = Fx.shootSmall; + lifetime = 56f; + collidesAir = false; }}; }}); }}; - cix = new UnitType("cix"){{ + spiroct = new UnitType("spiroct"){{ + speed = 0.4f; + drag = 0.4f; + hitsize = 12f; + rotateSpeed = 3f; + health = 600; + immunities = ObjectSet.with(StatusEffects.burning, StatusEffects.melting); + legCount = 6; + legLength = 13f; + legTrns = 0.7f; + legMoveSpace = 1.4f; + legBaseOffset = 2f; + hovering = true; + armor = 3f; + + buildSpeed = 0.75f; + + allowLegStep = true; + visualElevation = 0.3f; + groundLayer = Layer.legUnit; + + weapons.add(new Weapon("spiroct-weapon"){{ + shootY = 4f; + reload = 15f; + ejectEffect = Fx.none; + recoil = 2f; + rotate = true; + shootSound = Sounds.flame; + + x = 8.5f; + y = -1.5f; + + bullet = new SapBulletType(){{ + sapStrength = 0.3f; + length = 75f; + damage = 15; + shootEffect = Fx.shootSmall; + hitColor = color = Color.valueOf("bf92f9"); + despawnEffect = Fx.none; + width = 0.54f; + lifetime = 35f; + knockback = -1f; + }}; + }}); + + weapons.add(new Weapon("mount-purple-weapon"){{ + reload = 20f; + rotate = true; + x = 4f; + y = 3f; + + bullet = new SapBulletType(){{ + sapStrength = 0.65f; + length = 40f; + damage = 12; + shootEffect = Fx.shootSmall; + hitColor = color = Color.valueOf("bf92f9"); + despawnEffect = Fx.none; + width = 0.4f; + lifetime = 25f; + knockback = -0.5f; + }}; + }}); + }}; + + arkyid = new UnitType("arkyid"){{ drag = 0.1f; speed = 0.5f; hitsize = 9f; health = 140; - baseElevation = 0.51f; legCount = 6; legMoveSpace = 1f; @@ -288,21 +381,20 @@ public class UnitTypes implements ContentList{ legSplashDamage = 32; legSplashRange = 30; - for(boolean b : Mathf.booleans){ - weapons.add( - new Weapon("missiles-mount"){{ - reload = 20f; - x = 4f * Mathf.sign(b); - rotate = true; - mirror = false; - flipSprite = !b; - shake = 1f; - bullet = Bullets.missileSwarm; - }}); - } + weapons.add( + new Weapon("missiles-mount"){{ + reload = 20f; + x = 4f; + rotate = true; + shake = 1f; + bullet = Bullets.missileSwarm; + }}); }}; - wraith = new UnitType("wraith"){{ + //endregion + //region air attack + + flare = new UnitType("flare"){{ speed = 3f; accel = 0.08f; drag = 0.01f; @@ -315,14 +407,13 @@ public class UnitTypes implements ContentList{ y = 0f; x = 2f; reload = 15f; - alternate = true; ejectEffect = Fx.shellEjectSmall; bullet = Bullets.standardCopper; shootSound = Sounds.shoot; }}); }}; - ghoul = new UnitType("ghoul"){{ + horizon = new UnitType("horizon"){{ health = 220; speed = 2f; accel = 0.08f; @@ -338,7 +429,6 @@ public class UnitTypes implements ContentList{ shootY = 0f; reload = 12f; shootCone = 180f; - alternate = true; ejectEffect = Fx.none; inaccuracy = 15f; ignoreRotation = true; @@ -347,8 +437,8 @@ public class UnitTypes implements ContentList{ }}); }}; - revenant = new UnitType("revenant"){{ - health = 220; + zenith = new UnitType("zenith"){{ + health = 450; speed = 1.9f; accel = 0.04f; drag = 0.016f; @@ -360,39 +450,37 @@ public class UnitTypes implements ContentList{ engineOffset = 12f; engineSize = 3f; - for(boolean b : Mathf.booleans){ - weapons.add( - new Weapon("revenant-missiles"){{ - reload = 70f; - x = 7f * Mathf.sign(b); - rotate = true; - mirror = false; - flipSprite = !b; - shake = 1f; + weapons.add(new Weapon("zenith-missiles"){{ + reload = 32f; + x = 7f; + rotate = true; + shake = 1f; + shots = 2; + inaccuracy = 5f; + velocityRnd = 0.2f; - bullet = new MissileBulletType(2.7f, 12, "missile"){{ - width = 8f; - height = 8f; - shrinkY = 0f; - drag = -0.003f; - homingRange = 60f; - keepVelocity = false; - splashDamageRadius = 25f; - splashDamage = 10f; - lifetime = 60f; - trailColor = Pal.unitBack; - backColor = Pal.unitBack; - frontColor = Pal.unitFront; - hitEffect = Fx.blastExplosion; - despawnEffect = Fx.blastExplosion; - weaveScale = 6f; - weaveMag = 1f; - }}; - }}); - } + bullet = new MissileBulletType(3f, 12){{ + width = 8f; + height = 8f; + shrinkY = 0f; + drag = -0.003f; + homingRange = 60f; + keepVelocity = false; + splashDamageRadius = 25f; + splashDamage = 10f; + lifetime = 60f; + trailColor = Pal.unitBack; + backColor = Pal.unitBack; + frontColor = Pal.unitFront; + hitEffect = Fx.blastExplosion; + despawnEffect = Fx.blastExplosion; + weaveScale = 6f; + weaveMag = 1f; + }}; + }}); }}; - reaper = new UnitType("reaper"){{ + antumbra = new UnitType("antumbra"){{ speed = 1.1f; accel = 0.02f; drag = 0.05f; @@ -407,14 +495,13 @@ public class UnitTypes implements ContentList{ weapons.add(new Weapon(){{ y = 1.5f; reload = 28f; - alternate = true; ejectEffect = Fx.shellEjectSmall; bullet = Bullets.standardCopper; shootSound = Sounds.shoot; }}); }}; - lich = new UnitType("lich"){{ + eclipse = new UnitType("eclipse"){{ speed = 1.1f; accel = 0.02f; drag = 0.05f; @@ -425,18 +512,132 @@ public class UnitTypes implements ContentList{ engineOffset = 38; engineSize = 7.3f; hitsize = 58f; + destructibleWreck = false; weapons.add(new Weapon(){{ y = 1.5f; reload = 28f; - alternate = true; ejectEffect = Fx.shellEjectSmall; bullet = Bullets.standardCopper; shootSound = Sounds.shoot; }}); }}; - vanguard = new UnitType("vanguard"){{ + //endregion + //region air support + + mono = new UnitType("mono"){{ + flying = true; + drag = 0.05f; + accel = 0.15f; + speed = 2f; + health = 100; + engineSize = 1.8f; + engineOffset = 5.7f; + + mineTier = 1; + mineSpeed = 2.5f; + + weapons.add(new Weapon(){{ + y = 1.5f; + x = 0f; + + reload = 40f; + ejectEffect = Fx.none; + recoil = 2f; + shootSound = Sounds.pew; + mirror = false; + + bullet = new HealBulletType(5.2f, 10){{ + healPercent = 4f; + }}; + }}); + }}; + + poly = new UnitType("poly"){{ + defaultController = BuilderAI::new; + + flying = true; + drag = 0.05f; + speed = 2f; + rotateSpeed = 15f; + accel = 0.1f; + range = 70f; + itemCapacity = 70; + health = 400; + buildSpeed = 0.5f; + engineOffset = 6.5f; + hitsize = 8f; + lowAltitude = true; + + mineTier = 2; + mineSpeed = 3.5f; + + abilities.add(new HealFieldAbility(5f, 60f * 5, 50f)); + + weapons.add(new Weapon("heal-weapon-mount"){{ + y = -2.5f; + x = 3.5f; + reload = 34f; + ejectEffect = Fx.none; + recoil = 2f; + shootSound = Sounds.pew; + shots = 1; + velocityRnd = 0.5f; + inaccuracy = 15f; + alternate = true; + + bullet = new MissileBulletType(4f, 10){{ + homingPower = 0.08f; + weaveMag = 4; + weaveScale = 4; + lifetime = 50f; + keepVelocity = false; + shootEffect = Fx.shootHeal; + smokeEffect = Fx.hitLaser; + frontColor = Color.white; + + backColor = Pal.heal; + trailColor = Pal.heal; + }}; + }}); + }}; + + mega = new UnitType("mega"){{ + + health = 500; + speed = 1.8f; + accel = 0.06f; + drag = 0.017f; + lowAltitude = true; + flying = true; + engineOffset = 10.5f; + rotateShooting = false; + hitsize = 15f; + engineSize = 3f; + payloadCapacity = 3; + + weapons.add( + new Weapon("heal-weapon-mount"){{ + reload = 25f; + x = 8f; + y = -6f; + rotate = true; + bullet = Bullets.healBulletBig; + }}, + new Weapon("heal-weapon-mount"){{ + reload = 15f; + x = 4f; + y = 5f; + rotate = true; + bullet = Bullets.healBullet; + }}); + }}; + + //endregion + //region naval attack + + risse = new UnitType("risse"){{ speed = 1.3f; drag = 0.1f; hitsize = 8f; @@ -445,71 +646,67 @@ public class UnitTypes implements ContentList{ weapons.add(new Weapon("mount-weapon"){{ reload = 10f; x = 1.25f; - alternate = true; rotate = true; ejectEffect = Fx.shellEjectSmall; bullet = Bullets.standardCopper; }}); }}; - draug = new UnitType("draug"){{ - flying = true; - drag = 0.05f; - speed = 2f; - range = 50f; - accel = 0.2f; - health = 80; - mineSpeed = 0.9f; - engineSize = 1.8f; - engineOffset = 5.7f; - drillTier = 1; - }}; - - spirit = new UnitType("spirit"){{ - flying = true; - drag = 0.05f; - accel = 0.2f; - speed = 2f; - range = 50f; - health = 100; - engineSize = 1.8f; - engineOffset = 5.7f; - weapons.add(new Weapon(){{ - y = 1.5f; - reload = 40f; - x = 0.5f; - alternate = true; - ejectEffect = Fx.none; - recoil = 2f; - bullet = Bullets.healBulletBig; - shootSound = Sounds.pew; + minke = new UnitType("minke"){{ + speed = 1.3f; + drag = 0.1f; + hitsize = 8f; + health = 130; + immunities = ObjectSet.with(StatusEffects.wet); + weapons.add(new Weapon("mount-weapon"){{ + reload = 10f; + x = 1.25f; + rotate = true; + ejectEffect = Fx.shellEjectSmall; + bullet = Bullets.standardCopper; }}); }}; + bryde = new UnitType("bryde"){{ + speed = 1.3f; + drag = 0.1f; + hitsize = 8f; + health = 130; + immunities = ObjectSet.with(StatusEffects.wet); + weapons.add(new Weapon("mount-weapon"){{ + reload = 10f; + x = 1.25f; + rotate = true; + ejectEffect = Fx.shellEjectSmall; + bullet = Bullets.standardCopper; + }}); + }}; + + //endregion + //region core + alpha = new UnitType("alpha"){{ //TODO maybe these should be changed defaultController = BuilderAI::new; isCounted = false; flying = true; - mineSpeed = 2f; + mineSpeed = 6f; + mineTier = 1; buildSpeed = 0.5f; drag = 0.05f; - speed = 2.4f; + speed = 2.6f; rotateSpeed = 15f; accel = 0.1f; - range = 70f; itemCapacity = 30; health = 80f; engineOffset = 6f; hitsize = 8f; weapons.add(new Weapon("small-basic-weapon"){{ - reload = 15f; - x = -1f; - y = -1f; - shootX = 3.5f; - alternate = true; + reload = 20f; + x = 2.75f; + y = 1f; bullet = new BasicBulletType(2.5f, 9){{ width = 7f; @@ -522,492 +719,102 @@ public class UnitTypes implements ContentList{ }}); }}; - phantom = new UnitType("phantom"){{ + beta = new UnitType("beta"){{ + //TODO maybe these should be changed defaultController = BuilderAI::new; + isCounted = false; flying = true; + mineSpeed = 7f; + mineTier = 1; + buildSpeed = 0.75f; drag = 0.05f; - speed = 3f; - rotateSpeed = 15f; - accel = 0.3f; - range = 70f; - itemCapacity = 70; - health = 400; - buildSpeed = 0.5f; - engineOffset = 6.5f; - hitsize = 8f; - }}; - - trident = new UnitType("trident"){{ - - health = 500; - speed = 2f; - accel = 0.05f; - drag = 0.016f; - lowAltitude = true; - flying = true; - engineOffset = 10.5f; + speed = 2.9f; + rotateSpeed = 17f; + accel = 0.1f; + itemCapacity = 50; + health = 120f; + engineOffset = 6f; + hitsize = 9f; rotateShooting = false; - hitsize = 14f; - engineSize = 3f; + lowAltitude = true; - for(boolean b : Mathf.booleans){ - weapons.add( - new Weapon("heal-weapon-mount"){{ - reload = 25f; - x = 8f * Mathf.sign(b); - y = -6f; - rotate = true; - mirror = false; - flipSprite = !b; - bullet = Bullets.healBulletBig; - }}, - new Weapon("heal-weapon-mount"){{ - reload = 15f; - x = 4f * Mathf.sign(b); - y = 5f; - rotate = true; - mirror = false; - flipSprite = !b; - bullet = Bullets.healBullet; - }} - ); - } - }}; - - /* - chaosArray = new UnitType("chaos-array", GroundUnit::new){{ - maxVelocity = 0.68f; - speed = 0.12f; - drag = 0.4f; - mass = 5f; - hitsize = 20f; - rotatespeed = 0.06f; - health = 3000; - weapons.add(new Weapon("chaos"){{ - length = 8f; - reload = 50f; - width = 17f; - alternate = true; - recoil = 3f; - shake = 2f; - shots = 4; - spacing = 4f; - shotDelay = 5; - ejectEffect = Fx.shellEjectMedium; - bullet = Bullets.flakSurge; - shootSound = Sounds.shootBig; - }}); - }}; - - eradicator = new UnitType("eradicator", GroundUnit::new){{ - maxVelocity = 0.68f; - speed = 0.12f; - drag = 0.4f; - mass = 5f; - hitsize = 20f; - rotatespeed = 0.06f; - health = 9000; - weapons.add(new Weapon("eradication"){{ - length = 13f; - reload = 30f; - width = 22f; - alternate = true; - recoil = 3f; - shake = 2f; - inaccuracy = 3f; - shots = 4; + weapons.add(new Weapon("small-mount-weapon"){{ + reload = 20f; + x = 3f; + y = 0.5f; + rotate = true; + shots = 2; + shotDelay = 4f; spacing = 0f; - shotDelay = 3; - ejectEffect = Fx.shellEjectMedium; - bullet = Bullets.standardThoriumBig; - shootSound = Sounds.shootBig; + + bullet = new BasicBulletType(3f, 9){{ + width = 7f; + height = 9f; + lifetime = 60f; + shootEffect = Fx.shootSmall; + smokeEffect = Fx.shootSmallSmoke; + tileDamageMultiplier = 0.14f; + }}; }}); }}; - lich = new UnitType("lich", HoverUnit::new){{ - health = 6000; - mass = 20f; - hitsize = 40f; - speed = 0.01f; - maxVelocity = 0.6f; - drag = 0.02f; - range = 80f; - shootCone = 20f; - flying = true; - //rotateWeapons = true; - engineOffset = 21; - engineSize = 5.3f; - rotatespeed = 0.01f; - attackLength = 90f; - baseRotateSpeed = 0.04f; - weapons.add(new Weapon("lich-missiles"){{ - length = 4f; - reload = 160f; - width = 22f; - shots = 16; - shootCone = 100f; - shotDelay = 2; - inaccuracy = 10f; - alternate = true; - ejectEffect = Fx.none; - velocityRnd = 0.2f; - spacing = 1f; - bullet = Bullets.missileRevenant; - shootSound = Sounds.artillery; - }}); - }}; + gamma = new UnitType("gamma"){{ + //TODO maybe these should be changed + defaultController = BuilderAI::new; + isCounted = false; - reaper = new UnitType("reaper", HoverUnit::new){{ - health = 11000; - mass = 30f; - hitsize = 56f; - speed = 0.01f; - maxVelocity = 0.6f; - drag = 0.02f; - range = 80f; - shootCone = 30f; flying = true; - //rotateWeapons = true; - engineOffset = 40; - engineSize = 7.3f; - rotatespeed = 0.01f; - baseRotateSpeed = 0.04f; - weapons.add(new Weapon("reaper-gun"){{ - length = 3f; - reload = 10f; - width = 32f; - shots = 1; - shootCone = 100f; + mineSpeed = 8f; + mineTier = 2; + buildSpeed = 1f; + drag = 0.05f; + speed = 3.4f; + rotateSpeed = 19f; + accel = 0.11f; + itemCapacity = 70; + health = 160f; + engineOffset = 6f; + hitsize = 10f; - shake = 1f; + weapons.add(new Weapon("small-mount-weapon"){{ + reload = 15f; + x = 1f; + y = 2f; + shots = 2; + spacing = 2f; inaccuracy = 3f; - alternate = true; - ejectEffect = Fx.none; - bullet = new BasicBulletType(7f, 42, "bullet"){ - { - bulletWidth = 15f; - bulletHeight = 21f; - shootEffect = Fx.shootBig; - } + shotDelay = 3f; - @Override - public float range(){ - return 165f; - } - }; - shootSound = Sounds.shootBig; + bullet = new BasicBulletType(3.5f, 9){{ + width = 6.5f; + height = 11f; + lifetime = 70f; + shootEffect = Fx.shootSmall; + smokeEffect = Fx.shootSmallSmoke; + tileDamageMultiplier = 0.15f; + homingPower = 0.04f; + }}; }}); }}; + + //endregion + //region internal + + block = new UnitType("block"){ + { + speed = 0f; + hitsize = 0f; + health = 1; + rotateSpeed = 360f; } @Override - public boolean alwaysUnlocked(){ + public boolean isHidden(){ return true; } - - @Override - public void update(Playerc player){ - if(player.timer.get(Playerc.timerAbility, healReload)){ - if(indexer.eachBlock(player, healRange, other -> other.entity.damaged(), other -> { - other.entity.heal(other.entity.maxHealth() * healPercent / 100f); - Fx.healBlockFull.at(other.drawx(), other.drawy(), other.block().size, Pal.heal); - })){ - Fx.healWave.at(player); - } - } - } }; - delta = new UnitType("delta-mech", false){ - { - drillPower = 1; - mineSpeed = 1.5f; - mass = 1.2f; - speed = 0.5f; - itemCapacity = 40; - boostSpeed = 0.95f; - buildSpeed = 1.2f; - engineColor = Color.valueOf("ffd37f"); - health = 250f; - weaponOffsetX = 4f; - - weapons.add(new Weapon("flamethrower"){{ - length = 1.5f; - reload = 30f; - width = 4f; - alternate = true; - shots = 3; - inaccuracy = 40f; - shootSound = Sounds.spark; - bullet = new LightningBulletType(){{ - damage = 5; - lightningLength = 10; - lightningColor = Pal.lightFlame; - }}); - }}; - } - }; - - tau = new UnitType("tau-mech", false){ - float healRange = 60f; - float healAmount = 10f; - float healReload = 160f; - boolean wasHealed; - - { - drillPower = 4; - mineSpeed = 3f; - itemCapacity = 70; - weaponOffsetY = -1; - weaponOffsetX = 1; - mass = 1.75f; - speed = 0.44f; - drag = 0.35f; - boostSpeed = 0.8f; - canHeal = true; - health = 200f; - buildSpeed = 1.6f; - engineColor = Pal.heal; - - weapons.add(new Weapon("heal-gun"){{ - length = 1.5f; - reload = 24f; - alternate = false; - ejectEffect = Fx.none; - recoil = 2f; - bullet = Bullets.healBullet; - shootSound = Sounds.pew; - }}; - } - - @Override - public void update(Playerc player){ - - if(player.timer.get(Playerc.timerAbility, healReload)){ - wasHealed = false; - - Units.nearby(player.team(), player.x, player.y, healRange, unit -> { - if(unit.health < unit.maxHealth()){ - Fx.heal.at(unit); - wasHealed = true; - } - unit.heal(healAmount); - }); - - if(wasHealed){ - Fx.healWave.at(player); - } - } - } - }; - - omega = new UnitType("omega-mech", false){ - protected TextureRegion armorRegion; - - { - drillPower = 2; - mineSpeed = 1.5f; - itemCapacity = 80; - speed = 0.36f; - boostSpeed = 0.6f; - mass = 4f; - shake = 4f; - weaponOffsetX = 1; - weaponOffsetY = 0; - engineColor = Color.valueOf("feb380"); - health = 350f; - buildSpeed = 1.5f; - weapons.add(new Weapon("missiles"){{ - length = 1.5f; - recoil = 4f; - reload = 38f; - shots = 4; - spacing = 8f; - inaccuracy = 8f; - alternate = true; - ejectEffect = Fx.none; - shake = 3f; - bullet = Bullets.missileSwarm; - shootSound = Sounds.shootBig; - }}; - } - - @Override - public float getRotationAlpha(Playerc player){ - return 0.6f - player.shootHeat * 0.3f; - } - - @Override - public float spreadX(Playerc player){ - return player.shootHeat * 2f; - } - - @Override - public void load(){ - super.load(); - armorRegion = Core.atlas.find(name + "-armor"); - } - - @Override - public void update(Playerc player){ - float scl = 1f - player.shootHeat / 2f*Time.delta(); - player.vel().scl(scl); - } - - @Override - public float getExtraArmor(Playerc player){ - return player.shootHeat * 30f; - } - - @Override - public void draw(Playerc player){ - if(player.shootHeat <= 0.01f) return; - - Shaders.build.progress = player.shootHeat; - Shaders.build.region = armorRegion; - Shaders.build.time = Time.time() / 10f; - Shaders.build.color.set(Pal.accent).a = player.shootHeat; - Draw.shader(Shaders.build); - Draw.rect(armorRegion, player.x, player.y, player.rotation); - Draw.shader(); - } - }; - - dart = new UnitType("dart-ship"){ - float effectRange = 60f; - float effectReload = 60f * 5; - float effectDuration = 60f * 10f; - - { - flying = true; - drillPower = 1; - mineSpeed = 2f; - speed = 0.5f; - drag = 0.09f; - health = 200f; - weaponOffsetX = -1; - weaponOffsetY = -1; - engineColor = Pal.lightTrail; - cellTrnsY = 1f; - buildSpeed = 1.1f; - weapons.add(new Weapon("gun"){{ - length = 1.5f; - reload = 15f; - alternate = true; - ejectEffect = Fx.shellEjectSmall; - bullet = Bullets.standardCopper; - }}; - } - - @Override - public void update(Playerc player){ - super.update(player); - - if(player.timer.get(Playerc.timerAbility, effectReload)){ - - Units.nearby(player.team(), player.x, player.y, effectRange, unit -> { - //unit.applyEffect(StatusEffects.overdrive, effectDuration); - }); - - indexer.eachBlock(player, effectRange, other -> other.entity.damaged(), other -> { - other.entity.applyBoost(1.5f, effectDuration); - Fx.healBlockFull.at(other.drawx(), other.drawy(), other.block().size, Pal.heal); - }); - - Fx.overdriveWave.at(player); - } - } - }; - - javelin = new UnitType("javelin-ship"){ - float minV = 3.6f; - float maxV = 6f; - TextureRegion shield; - - { - flying = true; - drillPower = -1; - speed = 0.11f; - drag = 0.01f; - mass = 2f; - health = 170f; - engineColor = Color.valueOf("d3ddff"); - cellTrnsY = 1f; - weapons.add(new Weapon("missiles"){{ - length = 1.5f; - reload = 70f; - shots = 4; - inaccuracy = 2f; - alternate = true; - ejectEffect = Fx.none; - velocityRnd = 0.2f; - spacing = 1f; - bullet = Bullets.missileJavelin; - shootSound = Sounds.missile; - }}; - } - - @Override - public void load(){ - super.load(); - shield = Core.atlas.find(name + "-shield"); - } - - @Override - public float getRotationAlpha(Playerc player){ - return 0.5f; - } - - @Override - public void update(Playerc player){ - float scl = scld(player); - if(Mathf.chanceDelta((0.15 * scl))){ - Fx.hitLancer.at(Pal.lancerLaser, player.x, player.y); - Lightning.create(player.team(), Pal.lancerLaser, 10f * Vars.state.rules.playerDamageMultiplier, - player.x + player.vel().x, player.y + player.vel().y, player.rotation, 14); - } - } - - @Override - public void draw(Playerc player){ - float scl = scld(player); - if(scl < 0.01f) return; - Draw.color(Pal.lancerLaser); - Draw.alpha(scl / 2f); - Draw.blend(Blending.additive); - Draw.rect(shield, player.x + Mathf.range(scl / 2f), player.y + Mathf.range(scl / 2f), player.rotation - 90); - Draw.blend(); - } - - float scld(Playerc player){ - return Mathf.clamp((player.vel().len() - minV) / (maxV - minV)); - } - }; - - glaive = new UnitType("glaive-ship"){ - { - flying = true; - drillPower = 4; - mineSpeed = 1.3f; - speed = 0.32f; - drag = 0.06f; - mass = 3f; - health = 240f; - itemCapacity = 60; - engineColor = Color.valueOf("feb380"); - cellTrnsY = 1f; - buildSpeed = 1.2f; - - weapons.add(new Weapon("bomber"){{ - length = 1.5f; - reload = 13f; - alternate = true; - ejectEffect = Fx.shellEjectSmall; - bullet = Bullets.standardGlaive; - shootSound = Sounds.shootSnap; - }}; - } - };*/ + //endregion } } diff --git a/core/src/mindustry/content/Weathers.java b/core/src/mindustry/content/Weathers.java index d14c3a63e8..9c3a16ea44 100644 --- a/core/src/mindustry/content/Weathers.java +++ b/core/src/mindustry/content/Weathers.java @@ -2,6 +2,7 @@ package mindustry.content; import arc.*; import arc.graphics.*; +import arc.graphics.Texture.*; import arc.graphics.g2d.*; import arc.math.*; import arc.math.geom.*; @@ -33,7 +34,7 @@ public class Weathers implements ContentList{ } @Override - public void drawOver(Weatherc state){ + public void drawOver(WeatherState state){ rand.setSeed(0); Tmp.r1.setCentered(Core.camera.position.x, Core.camera.position.y, Core.graphics.getWidth() / renderer.minScale(), Core.graphics.getHeight() / renderer.minScale()); Tmp.r1.grow(padding); @@ -78,7 +79,7 @@ public class Weathers implements ContentList{ } @Override - public void drawOver(Weatherc state){ + public void drawOver(WeatherState state){ Tmp.r1.setCentered(Core.camera.position.x, Core.camera.position.y, Core.graphics.getWidth() / renderer.minScale(), Core.graphics.getHeight() / renderer.minScale()); Tmp.r1.grow(padding); Core.camera.bounds(Tmp.r2); @@ -110,7 +111,7 @@ public class Weathers implements ContentList{ } @Override - public void drawUnder(Weatherc state){ + public void drawUnder(WeatherState state){ Tmp.r1.setCentered(Core.camera.position.x, Core.camera.position.y, Core.graphics.getWidth() / renderer.minScale(), Core.graphics.getHeight() / renderer.minScale()); Tmp.r1.grow(padding); Core.camera.bounds(Tmp.r2); @@ -158,19 +159,44 @@ public class Weathers implements ContentList{ sandstorm = new Weather("sandstorm"){ TextureRegion region; - float yspeed = 0.3f, xspeed = 6f, padding = 110f, size = 110f, invDensity = 800f; - Vec2 force = new Vec2(0.4f, 0.01f); + float yspeed = 0.3f, xspeed = 6f, size = 140f, padding = size, invDensity = 1500f; + Vec2 force = new Vec2(0.45f, 0.01f); Color color = Color.valueOf("f7cba4"); + Texture noise; @Override public void load(){ - super.load(); - region = Core.atlas.find("circle-shadow"); + noise = new Texture("sprites/noiseAlpha.png"); + noise.setWrap(TextureWrap.repeat); + noise.setFilter(TextureFilter.linear); } @Override - public void drawOver(Weatherc state){ + public void dispose(){ + noise.dispose(); + } + + @Override + public void update(WeatherState state){ + + for(Unit unit : Groups.unit){ + unit.impulse(force.x * state.intensity(), force.y * state.intensity()); + } + } + + @Override + public void drawOver(WeatherState state){ + Draw.tint(color); + + float scale = 1f / 2000f; + float scroll = Time.time() * scale; + Tmp.tr1.setTexture(noise); + Core.camera.bounds(Tmp.r1); + Tmp.tr1.set(Tmp.r1.x*scale, Tmp.r1.y*scale, (Tmp.r1.x + Tmp.r1.width)*scale, (Tmp.r1.y + Tmp.r1.height)*scale); + Tmp.tr1.scroll(-xspeed * scroll, -yspeed * scroll); + Draw.rect(Tmp.tr1, Core.camera.position.x, Core.camera.position.y, Core.camera.width, -Core.camera.height); + rand.setSeed(0); Tmp.r1.setCentered(Core.camera.position.x, Core.camera.position.y, Core.graphics.getWidth() / renderer.minScale(), Core.graphics.getHeight() / renderer.minScale()); Tmp.r1.grow(padding); @@ -179,10 +205,6 @@ public class Weathers implements ContentList{ Draw.tint(color); float baseAlpha = Draw.getColor().a; - for(Unitc unit : Groups.unit){ - unit.impulse(force.x * state.intensity(), force.y * state.intensity()); - } - for(int i = 0; i < total; i++){ float scl = rand.random(0.5f, 1f); float scl2 = rand.random(0.5f, 1f); @@ -202,7 +224,6 @@ public class Weathers implements ContentList{ if(Tmp.r3.setCentered(x, y, size * sscl).overlaps(Tmp.r2)){ Draw.alpha(alpha * baseAlpha); - //Fill.circle(x, y, size * sscl / 2f); Draw.rect(region, x, y, size * sscl, size * sscl); } } diff --git a/core/src/mindustry/core/ContentLoader.java b/core/src/mindustry/core/ContentLoader.java index 16897778c1..604d04059c 100644 --- a/core/src/mindustry/core/ContentLoader.java +++ b/core/src/mindustry/core/ContentLoader.java @@ -22,8 +22,8 @@ import static mindustry.Vars.mods; */ @SuppressWarnings("unchecked") public class ContentLoader{ - private ObjectMap[] contentNameMap = new ObjectMap[ContentType.values().length]; - private Seq[] contentMap = new Seq[ContentType.values().length]; + private ObjectMap[] contentNameMap = new ObjectMap[ContentType.all.length]; + private Seq[] contentMap = new Seq[ContentType.all.length]; private MappableContent[][] temporaryMapper; private @Nullable LoadedMod currentMod; private @Nullable Content lastAdded; @@ -48,11 +48,11 @@ public class ContentLoader{ /** Clears all initialized content.*/ public void clear(){ - contentNameMap = new ObjectMap[ContentType.values().length]; - contentMap = new Seq[ContentType.values().length]; + contentNameMap = new ObjectMap[ContentType.all.length]; + contentMap = new Seq[ContentType.all.length]; initialization = new ObjectSet<>(); - for(ContentType type : ContentType.values()){ + for(ContentType type : ContentType.all){ contentMap[type.ordinal()] = new Seq<>(); contentNameMap[type.ordinal()] = new ObjectMap<>(); } @@ -87,9 +87,9 @@ public class ContentLoader{ Log.debug("--- CONTENT INFO ---"); for(int k = 0; k < contentMap.length; k++){ - Log.debug("[@]: loaded @", ContentType.values()[k].name(), contentMap[k].size); + Log.debug("[@]: loaded @", ContentType.all[k].name(), contentMap[k].size); } - Log.debug("Total content loaded: @", Seq.with(ContentType.values()).mapInt(c -> contentMap[c.ordinal()].size).sum()); + Log.debug("Total content loaded: @", Seq.with(ContentType.all).mapInt(c -> contentMap[c.ordinal()].size).sum()); Log.debug("-------------------"); } @@ -107,7 +107,7 @@ public class ContentLoader{ private void initialize(Cons callable){ if(initialization.contains(callable)) return; - for(ContentType type : ContentType.values()){ + for(ContentType type : ContentType.all){ for(Content content : contentMap[type.ordinal()]){ try{ callable.get(content); diff --git a/core/src/mindustry/core/Control.java b/core/src/mindustry/core/Control.java index e704148ae5..3a2ddf5eb5 100644 --- a/core/src/mindustry/core/Control.java +++ b/core/src/mindustry/core/Control.java @@ -9,6 +9,7 @@ import arc.math.*; import arc.scene.ui.*; import arc.struct.*; import arc.util.*; +import arc.util.ArcAnnotate.*; import mindustry.*; import mindustry.audio.*; import mindustry.content.*; @@ -25,6 +26,7 @@ import mindustry.maps.Map; import mindustry.type.*; import mindustry.ui.dialogs.*; import mindustry.world.*; +import mindustry.world.blocks.storage.CoreBlock.*; import java.io.*; import java.text.*; @@ -42,7 +44,7 @@ import static mindustry.Vars.*; */ public class Control implements ApplicationListener, Loadable{ public Saves saves; - public mindustry.audio.MusicControl music; + public MusicControl music; public Tutorial tutorial; public InputHandler input; @@ -72,8 +74,8 @@ public class Control implements ApplicationListener, Loadable{ }); Events.on(WorldLoadEvent.class, event -> { - if(Mathf.zero(player.x()) && Mathf.zero(player.y())){ - Tilec core = state.teams.closestCore(0, 0, player.team()); + if(Mathf.zero(player.x) && Mathf.zero(player.y)){ + Building core = state.teams.closestCore(0, 0, player.team()); if(core != null){ player.set(core); camera.position.set(core); @@ -109,7 +111,7 @@ public class Control implements ApplicationListener, Loadable{ state.stats.wavesLasted = state.wave; Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y); //the restart dialog can show info for any number of scenarios - Call.onGameOver(event.winner); + Call.gameOver(event.winner); }); //autohost for pvp maps @@ -157,7 +159,7 @@ public class Control implements ApplicationListener, Loadable{ }); Events.on(Trigger.newGame, () -> { - Tilec core = player.closestCore(); + Building core = player.closestCore(); if(core == null) return; @@ -176,6 +178,7 @@ public class Control implements ApplicationListener, Loadable{ Effects.shake(5f, 5f, core); }); }); + } @Override @@ -197,9 +200,9 @@ public class Control implements ApplicationListener, Loadable{ } void createPlayer(){ - player = PlayerEntity.create(); - player.name(Core.settings.getString("name")); - player.color().set(Core.settings.getInt("color-0")); + player = Player.create(); + player.name = Core.settings.getString("name"); + player.color.set(Core.settings.getInt("color-0")); if(mobile){ input = new MobileInput(); @@ -241,15 +244,23 @@ public class Control implements ApplicationListener, Loadable{ } //TODO move - public void handleLaunch(Tilec tile){ - LaunchCorec ent = LaunchCoreEntity.create(); + public void handleLaunch(CoreEntity tile){ + LaunchCorec ent = LaunchCore.create(); ent.set(tile); ent.block(Blocks.coreShard); ent.lifetime(Vars.launchDuration); ent.add(); + + //remove schematic requirements from core + tile.items.remove(universe.getLastLoadout().requirements()); + tile.items.remove(universe.getLaunchResources()); } public void playSector(Sector sector){ + playSector(sector, sector); + } + + public void playSector(@Nullable Sector origin, Sector sector){ ui.loadAnd(() -> { ui.planet.hide(); SaveSlot slot = sector.save; @@ -261,10 +272,11 @@ public class Control implements ApplicationListener, Loadable{ state.rules.sector = sector; //if there is no base, simulate a new game and place the right loadout at the spawn position + //TODO this is broken? if(state.rules.defaultTeam.cores().isEmpty()){ //kill all friendly units, since they should be dead anwyay - for(Unitc unit : Groups.unit){ + for(Unit unit : Groups.unit){ if(unit.team() == state.rules.defaultTeam){ unit.remove(); } @@ -272,7 +284,7 @@ public class Control implements ApplicationListener, Loadable{ Tile spawn = world.tile(sector.getSpawnPosition()); //TODO PLACE CORRECT LOADOUT - Schematics.placeLoadout(Loadouts.advancedShard, spawn.x, spawn.y); + Schematics.placeLoadout(universe.getLastLoadout(), spawn.x, spawn.y); //set up camera/player locations player.set(spawn.x * tilesize, spawn.y * tilesize); @@ -288,7 +300,7 @@ public class Control implements ApplicationListener, Loadable{ sector.save = null; Time.runTask(10f, () -> ui.showErrorMessage("$save.corrupted")); slot.delete(); - playSector(sector); + playSector(origin, sector); } ui.planet.hide(); }else{ @@ -296,6 +308,8 @@ public class Control implements ApplicationListener, Loadable{ logic.reset(); world.loadSector(sector); state.rules.sector = sector; + //assign origin when launching + state.secinfo.origin = origin; logic.play(); control.saves.saveSector(sector); Events.fire(Trigger.newGame); @@ -343,13 +357,13 @@ public class Control implements ApplicationListener, Loadable{ zone.rules.get(state.rules); //TODO assign zone!! //state.rules.zone = zone; - for(Tilec core : state.teams.playerCores()){ + for(Building core : state.teams.playerCores()){ for(ItemStack stack : zone.getStartingItems()){ - core.items().add(stack.item, stack.amount); + core.items.add(stack.item, stack.amount); } } - Tilec core = state.teams.playerCores().first(); - core.items().clear(); + Building core = state.teams.playerCores().first(); + core.items.clear(); logic.play(); state.rules.waveTimer = false; @@ -493,7 +507,7 @@ public class Control implements ApplicationListener, Loadable{ platform.updateRPC(); } - if(Core.input.keyTap(Binding.pause) && !scene.hasDialog() && !scene.hasKeyboard() && !ui.restart.isShown() && (state.is(State.paused) || state.is(State.playing))){ + if(Core.input.keyTap(Binding.pause) && !state.isOutOfTime() && !scene.hasDialog() && !scene.hasKeyboard() && !ui.restart.isShown() && (state.is(State.paused) || state.is(State.playing))){ state.set(state.is(State.playing) ? State.paused : State.playing); } diff --git a/core/src/mindustry/core/GameState.java b/core/src/mindustry/core/GameState.java index 51ab59a460..b006aae76f 100644 --- a/core/src/mindustry/core/GameState.java +++ b/core/src/mindustry/core/GameState.java @@ -33,8 +33,8 @@ public class GameState{ private State state = State.menu; //TODO optimize - public Unitc boss(){ - return Groups.unit.find(u -> u.isBoss() && u.team() == rules.waveTeam); + public Unit boss(){ + return Groups.unit.find(u -> u.isBoss() && u.team == rules.waveTeam); } public void set(State astate){ @@ -47,6 +47,11 @@ public class GameState{ return rules.sector != null; } + /** @return whether the player is in a campaign and they are out of sector time */ + public boolean isOutOfTime(){ + return isCampaign() && isGame() && getSector().getTimeSpent() >= turnDuration; + } + public boolean hasSector(){ return rules.sector != null; } diff --git a/core/src/mindustry/core/Logic.java b/core/src/mindustry/core/Logic.java index fc10df0b9b..ef09b2046d 100644 --- a/core/src/mindustry/core/Logic.java +++ b/core/src/mindustry/core/Logic.java @@ -2,6 +2,7 @@ package mindustry.core; import arc.*; import arc.math.*; +import arc.struct.*; import arc.util.*; import mindustry.annotations.Annotations.*; import mindustry.content.*; @@ -16,6 +17,7 @@ import mindustry.type.Weather.*; import mindustry.world.*; import mindustry.world.blocks.*; import mindustry.world.blocks.BuildBlock.*; +import mindustry.world.blocks.storage.CoreBlock.*; import java.util.*; @@ -33,23 +35,16 @@ public class Logic implements ApplicationListener{ public Logic(){ - Events.on(WaveEvent.class, event -> { - if(state.isCampaign()){ - //TODO implement - //state.getSector().updateWave(state.wave); - } - }); - Events.on(BlockDestroyEvent.class, event -> { //blocks that get broken are appended to the team's broken block queue Tile tile = event.tile; Block block = tile.block(); //skip null entities or un-rebuildables, for obvious reasons; also skip client since they can't modify these requests - if(tile.entity == null || !tile.block().rebuildable || net.client()) return; + if(tile.build == null || !tile.block().rebuildable || net.client()) return; if(block instanceof BuildBlock){ - BuildEntity entity = tile.ent(); + BuildEntity entity = tile.bc(); //update block to reflect the fact that something was being constructed if(entity.cblock != null && entity.cblock.synthetic()){ @@ -72,7 +67,7 @@ public class Logic implements ApplicationListener{ } } - data.blocks.addFirst(new BlockPlan(tile.x, tile.y, tile.rotation(), block.id, tile.entity.config())); + data.blocks.addFirst(new BlockPlan(tile.x, tile.y, tile.rotation(), block.id, tile.build.config())); }); Events.on(BlockBuildEndEvent.class, event -> { @@ -93,23 +88,50 @@ public class Logic implements ApplicationListener{ //when loading a 'damaged' sector, propagate the damage Events.on(WorldLoadEvent.class, e -> { - if(state.isCampaign() && state.rules.sector.hasWaves() && state.rules.sector.getTurnsPassed() > 0){ - SectorDamage.apply(state.rules.sector.getTurnsPassed()); - state.rules.sector.setTurnsPassed(0); + if(state.isCampaign() && state.rules.sector.getSecondsPassed() > 0 && state.rules.sector.hasBase()){ + long seconds = state.rules.sector.getSecondsPassed(); + CoreEntity core = state.rules.defaultTeam.core(); + + //apply fractional damage based on how many turns have passed for this sector + float turnsPassed = seconds / (turnDuration / 60f); + + if(state.rules.sector.hasWaves()){ + SectorDamage.apply(turnsPassed / sectorDestructionTurns); + } + + //add resources based on turns passed + if(state.rules.sector.save != null && core != null){ + + //add produced items + //TODO move to recieved items + state.rules.sector.save.meta.secinfo.production.each((item, stat) -> { + core.items.add(item, (int)(stat.mean * seconds)); + }); + + //add recieved items + state.rules.sector.getRecievedItems().each(stack -> core.items.add(stack.item, stack.amount)); + + //clear recieved items + state.rules.sector.setRecievedItems(new Seq<>()); + + //validation + for(Item item : content.items()){ + //ensure positive items + if(core.items.get(item) < 0) core.items.set(item, 0); + //cap the items + if(core.items.get(item) > core.storageCapacity) core.items.set(item, core.storageCapacity); + } + } + + state.rules.sector.setSecondsPassed(0); } //enable infinite ammo for wave team by default state.rules.waveTeam.rules().infiniteAmmo = true; - }); - //TODO dying takes up a turn (?) - /* - Events.on(GameOverEvent.class, e -> { - //simulate a turn on a normal non-launch gameover - if(state.isCampaign() && !state.launched){ - universe.runTurn(); - } - });*/ + //save settings + Core.settings.manualSave(); + }); } @@ -124,7 +146,7 @@ public class Logic implements ApplicationListener{ if(!state.isCampaign()){ for(TeamData team : state.teams.getActive()){ if(team.hasCore()){ - TileEntity entity = team.core(); + Building entity = team.core(); entity.items.clear(); for(ItemStack stack : state.rules.loadout){ entity.items.add(stack.item, stack.amount); @@ -141,9 +163,21 @@ public class Logic implements ApplicationListener{ //fire change event, since it was technically changed Events.fire(new StateChangeEvent(prev, State.menu)); - Groups.all.clear(); + Groups.clear(); Time.clear(); Events.fire(new ResetEvent()); + + //save settings on reset + Core.settings.manualSave(); + } + + public void skipWave(){ + if(state.isCampaign()){ + //warp time spent forward because the wave was just skipped. + state.secinfo.internalTimeSpent += state.wavetime; + } + + state.wavetime = 0; } public void runWave(){ @@ -223,32 +257,37 @@ public class Logic implements ApplicationListener{ @Remote(called = Loc.both) public static void launchZone(){ + if(!state.isCampaign()) return; + if(!headless){ ui.hudfrag.showLaunch(); } - //TODO core launch effect - for(Tilec tile : state.teams.playerCores()){ + //TODO better core launch effect + for(Building tile : state.teams.playerCores()){ Fx.launch.at(tile); } - if(state.isCampaign()){ - //TODO implement? - //state.getSector().setLaunched(); - } - Sector sector = state.rules.sector; //TODO containers must be launched too Time.runTask(30f, () -> { - for(Tilec entity : state.teams.playerCores()){ - for(Item item : content.items()){ - //TODO where do the items go? - //data.addItem(item, entity.items().get(item)); - //Events.fire(new LaunchItemEvent(new ItemStack(item, entity.items().get(item)))); + Sector origin = sector.save.meta.secinfo.origin; + if(origin != null){ + Seq stacks = origin.getRecievedItems(); + + //add up all items into list + for(Building entity : state.teams.playerCores()){ + entity.items.each((item, amount) -> ItemStack.insert(stacks, item, amount)); } - entity.tile().remove(); + + //save recieved items + origin.setRecievedItems(stacks); } + + //remove all the cores + state.teams.playerCores().each(b -> b.tile.remove()); + state.launched = true; state.gameOver = true; @@ -257,8 +296,11 @@ public class Logic implements ApplicationListener{ //run a turn, since launching takes up a turn universe.runTurn(); - sector.setTurnsPassed(sector.getTurnsPassed() + 3); + //TODO apply extra damage to sector + //sector.setTurnsPassed(sector.getTurnsPassed() + 3); + + //TODO load the sector that was launched from Events.fire(new LaunchEvent()); //manually fire game over event now Events.fire(new GameOverEvent(state.rules.defaultTeam)); @@ -266,12 +308,18 @@ public class Logic implements ApplicationListener{ } @Remote(called = Loc.both) - public static void onGameOver(Team winner){ + public static void gameOver(Team winner){ state.stats.wavesLasted = state.wave; ui.restart.show(winner); netClient.setQuiet(); } + @Override + public void dispose(){ + //save the settings before quitting + Core.settings.manualSave(); + } + @Override public void update(){ Events.fire(Trigger.update); @@ -282,6 +330,11 @@ public class Logic implements ApplicationListener{ state.enemies = Groups.unit.count(u -> u.team() == state.rules.waveTeam && u.type().isCounted); } + //force pausing when the player is out of sector time + if(state.isOutOfTime()){ + state.set(State.paused); + } + if(!state.isPaused()){ state.secinfo.update(); diff --git a/core/src/mindustry/core/NetClient.java b/core/src/mindustry/core/NetClient.java index 2cb3719ecf..25d80e6194 100644 --- a/core/src/mindustry/core/NetClient.java +++ b/core/src/mindustry/core/NetClient.java @@ -73,7 +73,7 @@ public class NetClient implements ApplicationListener{ }); ConnectPacket c = new ConnectPacket(); - c.name = player.name(); + c.name = player.name; c.mods = mods.getModStrings(); c.mobile = mobile; c.versionType = Version.type; @@ -153,7 +153,7 @@ public class NetClient implements ApplicationListener{ //called on all clients @Remote(targets = Loc.server, variants = Variant.both) - public static void sendMessage(String message, String sender, Playerc playersender){ + public static void sendMessage(String message, String sender, Player playersender){ if(Vars.ui != null){ Vars.ui.chatfrag.addMessage(message, sender); } @@ -174,7 +174,7 @@ public class NetClient implements ApplicationListener{ //called when a server recieves a chat message from a player @Remote(called = Loc.server, targets = Loc.client) - public static void sendChatMessage(Playerc player, String message){ + public static void sendChatMessage(Player player, String message){ if(message.length() > maxTextLength){ throw new ValidateException(player, "Player has sent a message above the text limit."); } @@ -192,18 +192,18 @@ public class NetClient implements ApplicationListener{ //special case; graphical server needs to see its message if(!headless){ - sendMessage(message, colorizeName(player.id(), player.name()), player); + sendMessage(message, colorizeName(player.id(), player.name), player); } //server console logging - Log.info("&y@: &lb@", player.name(), message); + Log.info("&y@: &lb@", player.name, message); //invoke event for all clients but also locally //this is required so other clients get the correct name even if they don't know who's sending it yet - Call.sendMessage(message, colorizeName(player.id(), player.name()), player); + Call.sendMessage(message, colorizeName(player.id(), player.name), player); }else{ //log command to console but with brackets - Log.info("<&y@: &lm@&lg>", player.name(), message); + Log.info("<&y@: &lm@&lg>", player.name, message); //a command was sent, now get the output if(response.type != ResponseType.valid){ @@ -224,13 +224,13 @@ public class NetClient implements ApplicationListener{ } public static String colorizeName(int id, String name){ - Playerc player = Groups.player.getByID(id); + Player player = Groups.player.getByID(id); if(name == null || player == null) return null; return "[#" + player.color().toString().toUpperCase() + "]" + name; } @Remote(called = Loc.client, variants = Variant.one) - public static void onConnect(String ip, int port){ + public static void connect(String ip, int port){ netClient.disconnectQuietly(); logic.reset(); @@ -238,24 +238,24 @@ public class NetClient implements ApplicationListener{ } @Remote(targets = Loc.client) - public static void onPing(Playerc player, long time){ - Call.onPingResponse(player.con(), time); + public static void ping(Player player, long time){ + Call.pingResponse(player.con, time); } @Remote(variants = Variant.one) - public static void onPingResponse(long time){ + public static void pingResponse(long time){ netClient.ping = Time.timeSinceMillis(time); } @Remote(variants = Variant.one) - public static void onTraceInfo(Playerc player, TraceInfo info){ + public static void traceInfo(Player player, TraceInfo info){ if(player != null){ ui.traces.show(player, info); } } @Remote(variants = Variant.one, priority = PacketPriority.high) - public static void onKick(KickReason reason){ + public static void kick(KickReason reason){ netClient.disconnectQuietly(); logic.reset(); @@ -270,7 +270,7 @@ public class NetClient implements ApplicationListener{ } @Remote(variants = Variant.one, priority = PacketPriority.high) - public static void onKick(String reason){ + public static void kick(String reason){ netClient.disconnectQuietly(); logic.reset(); ui.showText("$disconnect", reason, Align.left); @@ -296,21 +296,21 @@ public class NetClient implements ApplicationListener{ } @Remote(variants = Variant.both) - public static void onInfoMessage(String message){ + public static void infoMessage(String message){ if(message == null) return; ui.showText("", message); } @Remote(variants = Variant.both) - public static void onInfoPopup(String message, float duration, int align, int top, int left, int bottom, int right){ + public static void infoPopup(String message, float duration, int align, int top, int left, int bottom, int right){ if(message == null) return; ui.showInfoPopup(message, duration, align, top, left, bottom, right); } @Remote(variants = Variant.both) - public static void onLabel(String message, float duration, float worldx, float worldy){ + public static void label(String message, float duration, float worldx, float worldy){ if(message == null) return; ui.showLabel(message, duration, worldx, worldy); @@ -330,20 +330,20 @@ public class NetClient implements ApplicationListener{ }*/ @Remote(variants = Variant.both) - public static void onInfoToast(String message, float duration){ + public static void infoToast(String message, float duration){ if(message == null) return; ui.showInfoToast(message, duration); } @Remote(variants = Variant.both) - public static void onSetRules(Rules rules){ + public static void setRules(Rules rules){ state.rules = rules; } @Remote(variants = Variant.both) - public static void onWorldDataBegin(){ - Groups.all.clear(); + public static void worldDataBegin(){ + Groups.clear(); netClient.removed.clear(); logic.reset(); @@ -360,17 +360,18 @@ public class NetClient implements ApplicationListener{ } @Remote(variants = Variant.one) - public static void onPositionSet(float x, float y){ + public static void setPosition(float x, float y){ + player.unit().set(x, y); player.set(x, y); } @Remote - public static void onPlayerDisconnect(int playerid){ + public static void playerDisconnect(int playerid){ Groups.player.removeByID(playerid); } @Remote(variants = Variant.one, priority = PacketPriority.low, unreliable = true) - public static void onEntitySnapshot(short amount, short dataLen, byte[] data){ + public static void entitySnapshot(short amount, short dataLen, byte[] data){ try{ netClient.byteStream.setBytes(net.decompressSnapshot(data, dataLen)); DataInputStream input = netClient.dataStream; @@ -417,7 +418,7 @@ public class NetClient implements ApplicationListener{ } @Remote(variants = Variant.both, priority = PacketPriority.low, unreliable = true) - public static void onBlockSnapshot(short amount, short dataLen, byte[] data){ + public static void blockSnapshot(short amount, short dataLen, byte[] data){ try{ netClient.byteStream.setBytes(net.decompressSnapshot(data, dataLen)); DataInputStream input = netClient.dataStream; @@ -425,11 +426,11 @@ public class NetClient implements ApplicationListener{ for(int i = 0; i < amount; i++){ int pos = input.readInt(); Tile tile = world.tile(pos); - if(tile == null || tile.entity == null){ + if(tile == null || tile.build == null){ Log.warn("Missing entity at @. Skipping block snapshot.", tile); break; } - tile.entity.readAll(Reads.get(input), tile.entity.version()); + tile.build.readAll(Reads.get(input), tile.build.version()); } }catch(Exception e){ e.printStackTrace(); @@ -437,7 +438,7 @@ public class NetClient implements ApplicationListener{ } @Remote(variants = Variant.one, priority = PacketPriority.low, unreliable = true) - public static void onStateSnapshot(float waveTime, int wave, int enemies, boolean paused, short coreDataLen, byte[] coreData){ + public static void stateSnapshot(float waveTime, int wave, int enemies, boolean paused, short coreDataLen, byte[] coreData){ try{ if(wave > state.wave){ state.wave = wave; @@ -457,8 +458,8 @@ public class NetClient implements ApplicationListener{ int pos = input.readInt(); Tile tile = world.tile(pos); - if(tile != null && tile.entity != null){ - tile.entity.items().read(Reads.get(input)); + if(tile != null && tile.build != null){ + tile.build.items.read(Reads.get(input)); }else{ new ItemModule().read(Reads.get(input)); } @@ -517,7 +518,7 @@ public class NetClient implements ApplicationListener{ quiet = false; lastSent = 0; - Groups.all.clear(); + Groups.clear(); ui.chatfrag.clearMessages(); } @@ -563,23 +564,24 @@ public class NetClient implements ApplicationListener{ } } - Unitc unit = player.dead() ? Nulls.unit : player.unit(); + Unit unit = player.dead() ? Nulls.unit : player.unit(); - Call.onClientShapshot(lastSent++, - unit.x(), unit.y(), + Call.clientShapshot(lastSent++, + player.dead(), + unit.x, unit.y, player.unit().aimX(), player.unit().aimY(), - unit.rotation(), + unit.rotation, unit instanceof Mechc ? ((Mechc)unit).baseRotation() : 0, - unit.vel().x, unit.vel().y, + unit.vel.x, unit.vel.y, player.miner().mineTile(), - control.input.isBoosting, control.input.isShooting, ui.chatfrag.shown(), + player.boosting, player.shooting, ui.chatfrag.shown(), requests, Core.camera.position.x, Core.camera.position.y, Core.camera.width * viewScale, Core.camera.height * viewScale); } if(timer.get(1, 60)){ - Call.onPing(Time.millis()); + Call.ping(Time.millis()); } } diff --git a/core/src/mindustry/core/NetServer.java b/core/src/mindustry/core/NetServer.java index 5eb1d6f9c0..d3c3f38cff 100644 --- a/core/src/mindustry/core/NetServer.java +++ b/core/src/mindustry/core/NetServer.java @@ -51,7 +51,7 @@ public class NetServer implements ApplicationListener{ if((state.rules.waveTeam == data.team && state.rules.waves) || !data.team.active()) return Integer.MAX_VALUE; int count = 0; - for(Playerc other : players){ + for(Player other : players){ if(other.team() == data.team && other != player){ count++; } @@ -75,7 +75,7 @@ public class NetServer implements ApplicationListener{ /** Data stream for writing player sync data to. */ private DataOutputStream dataStream = new DataOutputStream(syncStream); /** Packet handlers for custom types of messages. */ - private ObjectMap>> customPacketHandlers = new ObjectMap<>(); + private ObjectMap>> customPacketHandlers = new ObjectMap<>(); public NetServer(){ @@ -162,7 +162,7 @@ public class NetServer implements ApplicationListener{ info.lastName = packet.name; info.id = packet.uuid; admins.save(); - Call.onInfoMessage(con, "You are not whitelisted here."); + Call.infoMessage(con, "You are not whitelisted here."); Log.info("&lcDo &lywhitelist-add @&lc to whitelist the player &lb'@'", packet.uuid, packet.name); con.kick(KickReason.whitelist); return; @@ -176,7 +176,7 @@ public class NetServer implements ApplicationListener{ boolean preventDuplicates = headless && netServer.admins.getStrict(); if(preventDuplicates){ - if(Groups.player.contains(p -> p.name().trim().equalsIgnoreCase(packet.name.trim()))){ + if(Groups.player.contains(p -> p.name.trim().equalsIgnoreCase(packet.name.trim()))){ con.kick(KickReason.nameInUse); return; } @@ -207,17 +207,17 @@ public class NetServer implements ApplicationListener{ con.modclient = true; } - Playerc player = PlayerEntity.create(); - player.admin(admins.isAdmin(uuid, packet.usid)); - player.con(con); - player.con().usid = packet.usid; - player.con().uuid = uuid; - player.con().mobile = packet.mobile; - player.name(packet.name); - player.color().set(packet.color).a(1f); + Player player = Player.create(); + player.admin = admins.isAdmin(uuid, packet.usid); + player.con = con; + player.con.usid = packet.usid; + player.con.uuid = uuid; + player.con.mobile = packet.mobile; + player.name = packet.name; + player.color.set(packet.color).a(1f); //save admin ID but don't overwrite it - if(!player.admin() && !info.admin){ + if(!player.admin && !info.admin){ info.adminUsid = packet.usid; } @@ -267,7 +267,7 @@ public class NetServer implements ApplicationListener{ } private void registerCommands(){ - clientCommands.register("help", "[page]", "Lists all commands.", (args, player) -> { + clientCommands.register("help", "[page]", "Lists all commands.", (args, player) -> { if(args.length > 0 && !Strings.canParseInt(args[0])){ player.sendMessage("[scarlet]'page' must be a number."); return; @@ -293,10 +293,10 @@ public class NetServer implements ApplicationListener{ player.sendMessage(result.toString()); }); - clientCommands.register("t", "", "Send a message only to your teammates.", (args, player) -> { + clientCommands.register("t", "", "Send a message only to your teammates.", (args, player) -> { String message = admins.filterMessage(player, args[0]); if(message != null){ - Groups.player.each(p -> p.team() == player.team(), o -> o.sendMessage(message, player, "[#" + player.team().color.toString() + "]" + NetClient.colorizeName(player.id(), player.name()))); + Groups.player.each(p -> p.team() == player.team(), o -> o.sendMessage(message, player, "[#" + player.team().color.toString() + "]" + NetClient.colorizeName(player.id(), player.name))); } }); @@ -308,35 +308,35 @@ public class NetServer implements ApplicationListener{ int voteCooldown = 60 * 5; class VoteSession{ - Playerc target; + Player target; ObjectSet voted = new ObjectSet<>(); VoteSession[] map; Timer.Task task; int votes; - public VoteSession(VoteSession[] map, Playerc target){ + public VoteSession(VoteSession[] map, Player target){ this.target = target; this.map = map; this.task = Timer.schedule(() -> { if(!checkPass()){ - Call.sendMessage(Strings.format("[lightgray]Vote failed. Not enough votes to kick[orange] @[lightgray].", target.name())); + Call.sendMessage(Strings.format("[lightgray]Vote failed. Not enough votes to kick[orange] @[lightgray].", target.name)); map[0] = null; task.cancel(); } }, voteDuration); } - void vote(Playerc player, int d){ + void vote(Player player, int d){ votes += d; voted.addAll(player.uuid(), admins.getInfo(player.uuid()).lastIP); - - Call.sendMessage(Strings.format("[orange]@[lightgray] has voted on kicking[orange] @[].[accent] (@/@)\n[lightgray]Type[orange] /vote [] to agree.", - player.name(), target.name(), votes, votesRequired())); + + Call.sendMessage(Strings.format("[lightgray]A player has voted on kicking[orange] @[].[accent] (@/@)\n[lightgray]Type[orange] /vote [] to agree.", + target.name, votes, votesRequired())); } boolean checkPass(){ if(votes >= votesRequired()){ - Call.sendMessage(Strings.format("[orange]Vote passed.[scarlet] @[orange] will be banned from the server for @ minutes.", target.name(), (kickDuration/60))); + Call.sendMessage(Strings.format("[orange]Vote passed.[scarlet] @[orange] will be banned from the server for @ minutes.", target.name, (kickDuration/60))); target.getInfo().lastKicked = Time.millis() + kickDuration*1000; Groups.player.each(p -> p.uuid().equals(target.uuid()), p -> p.kick(KickReason.vote)); map[0] = null; @@ -352,7 +352,7 @@ public class NetServer implements ApplicationListener{ //current kick sessions VoteSession[] currentlyKicking = {null}; - clientCommands.register("votekick", "[player...]", "Vote to kick a player.", (args, player) -> { + clientCommands.register("votekick", "[player...]", "Vote to kick a player.", (args, player) -> { if(!Config.enableVotekick.bool()){ player.sendMessage("[scarlet]Vote-kick is disabled on this server."); return; @@ -372,21 +372,23 @@ public class NetServer implements ApplicationListener{ StringBuilder builder = new StringBuilder(); builder.append("[orange]Players to kick: \n"); - Groups.player.each(p -> !p.admin() && p.con() != null && p != player, p -> { - builder.append("[lightgray] ").append(p.name()).append("[accent] (#").append(p.id()).append(")\n"); + Groups.player.each(p -> !p.admin && p.con != null && p != player, p -> { + builder.append("[lightgray] ").append(p.name).append("[accent] (#").append(p.id()).append(")\n"); }); player.sendMessage(builder.toString()); }else{ - Playerc found; + Player found; if(args[0].length() > 1 && args[0].startsWith("#") && Strings.canParseInt(args[0].substring(1))){ int id = Strings.parseInt(args[0].substring(1)); found = Groups.player.find(p -> p.id() == id); }else{ - found = Groups.player.find(p -> p.name().equalsIgnoreCase(args[0])); + found = Groups.player.find(p -> { + return p.name.equalsIgnoreCase(args[0]); + }); } if(found != null){ - if(found.admin()){ + if(found.admin){ player.sendMessage("[scarlet]Did you really expect to be able to kick an admin?"); }else if(found.isLocal()){ player.sendMessage("[scarlet]Local players cannot be kicked."); @@ -411,7 +413,7 @@ public class NetServer implements ApplicationListener{ } }); - clientCommands.register("vote", "", "Vote to kick the current player.", (arg, player) -> { + clientCommands.register("vote", "", "Vote to kick the current player.", (arg, player) -> { if(currentlyKicking[0] == null){ player.sendMessage("[scarlet]Nobody is being voted on."); }else{ @@ -441,7 +443,7 @@ public class NetServer implements ApplicationListener{ } }); - clientCommands.register("sync", "Re-synchronize world state.", (args, player) -> { + clientCommands.register("sync", "Re-synchronize world state.", (args, player) -> { if(player.isLocal()){ player.sendMessage("[scarlet]Re-synchronizing as the host is pointless."); }else{ @@ -451,7 +453,7 @@ public class NetServer implements ApplicationListener{ } player.getInfo().lastSyncTime = Time.millis(); - Call.onWorldDataBegin(player.con()); + Call.worldDataBegin(player.con); netServer.sendWorldData(player); } }); @@ -461,72 +463,73 @@ public class NetServer implements ApplicationListener{ return 2 + (Groups.player.size() > 4 ? 1 : 0); } - public Team assignTeam(Playerc current){ + public Team assignTeam(Player current){ return assigner.assign(current, Groups.player); } - public Team assignTeam(Playerc current, Iterable players){ + public Team assignTeam(Player current, Iterable players){ return assigner.assign(current, players); } - public void sendWorldData(Playerc player){ + public void sendWorldData(Player player){ ByteArrayOutputStream stream = new ByteArrayOutputStream(); DeflaterOutputStream def = new FastDeflaterOutputStream(stream); NetworkIO.writeWorld(player, def); WorldStream data = new WorldStream(); data.stream = new ByteArrayInputStream(stream.toByteArray()); - player.con().sendStream(data); + player.con.sendStream(data); Log.debug("Packed @ compressed bytes of world data.", stream.size()); } - public void addPacketHandler(String type, Cons2 handler){ + public void addPacketHandler(String type, Cons2 handler){ customPacketHandlers.get(type, Seq::new).add(handler); } - public Seq> getPacketHandlers(String type){ + public Seq> getPacketHandlers(String type){ return customPacketHandlers.get(type, Seq::new); } - public static void onDisconnect(Playerc player, String reason){ + public static void onDisconnect(Player player, String reason){ //singleplayer multiplayer wierdness - if(player.con() == null){ + if(player.con == null){ player.remove(); return; } - if(!player.con().hasDisconnected){ - if(player.con().hasConnected){ + if(!player.con.hasDisconnected){ + if(player.con.hasConnected){ Events.fire(new PlayerLeave(player)); - if(Config.showConnectMessages.bool()) Call.sendMessage("[accent]" + player.name() + "[accent] has disconnected."); - Call.onPlayerDisconnect(player.id()); + if(Config.showConnectMessages.bool()) Call.sendMessage("[accent]" + player.name + "[accent] has disconnected."); + Call.playerDisconnect(player.id()); } - if(Config.showConnectMessages.bool()) Log.info("&lm[@] &lc@ has disconnected. &lg&fi(@)", player.uuid(), player.name(), reason); + if(Config.showConnectMessages.bool()) Log.info("&lm[@] &lc@ has disconnected. &lg&fi(@)", player.uuid(), player.name, reason); } player.remove(); - player.con().hasDisconnected = true; + player.con.hasDisconnected = true; } @Remote(targets = Loc.client) - public static void serverPacketReliable(Playerc player, String type, String contents){ + public static void serverPacketReliable(Player player, String type, String contents){ if(netServer.customPacketHandlers.containsKey(type)){ - for(Cons2 c : netServer.customPacketHandlers.get(type)){ + for(Cons2 c : netServer.customPacketHandlers.get(type)){ c.get(player, contents); } } } @Remote(targets = Loc.client, unreliable = true) - public static void serverPacketUnreliable(Playerc player, String type, String contents){ + public static void serverPacketUnreliable(Player player, String type, String contents){ serverPacketReliable(player, type, contents); } @Remote(targets = Loc.client, unreliable = true) - public static void onClientShapshot( - Playerc player, + public static void clientShapshot( + Player player, int snapshotID, + boolean dead, float x, float y, float pointerX, float pointerY, float rotation, float baseRotation, @@ -536,28 +539,29 @@ public class NetServer implements ApplicationListener{ @Nullable BuildPlan[] requests, float viewX, float viewY, float viewWidth, float viewHeight ){ - NetConnection connection = player.con(); - if(connection == null || snapshotID < connection.lastRecievedClientSnapshot) return; + NetConnection con = player.con; + if(con == null || snapshotID < con.lastRecievedClientSnapshot) return; boolean verifyPosition = !player.dead() && netServer.admins.getStrict() && headless; - if(connection.lastRecievedClientTime == 0) connection.lastRecievedClientTime = Time.millis() - 16; + if(con.lastRecievedClientTime == 0) con.lastRecievedClientTime = Time.millis() - 16; - connection.viewX = viewX; - connection.viewY = viewY; - connection.viewWidth = viewWidth; - connection.viewHeight = viewHeight; + con.viewX = viewX; + con.viewY = viewY; + con.viewWidth = viewWidth; + con.viewHeight = viewHeight; //disable shooting when a mech flies if(!player.dead() && player.unit().isFlying() && player.unit() instanceof Mechc){ shooting = false; } - player.mouseX(pointerX); - player.mouseY(pointerY); - player.typing(chatting); - player.shooting(shooting); - player.boosting(boosting); + //TODO these need to be assigned elsewhere + player.mouseX = pointerX; + player.mouseY = pointerY; + player.typing = chatting; + player.shooting = shooting; + player.boosting = boosting; player.unit().controlWeapons(shooting, shooting); player.unit().aim(pointerX, pointerY); @@ -580,7 +584,7 @@ public class NetServer implements ApplicationListener{ continue; }else if(!req.breaking && tile.block() == req.block && (!req.block.rotate || tile.rotation() == req.rotation)){ continue; - }else if(connection.rejectedRequests.contains(r -> r.breaking == req.breaking && r.x == req.x && r.y == req.y)){ //check if request was recently rejected, and skip it if so + }else if(con.rejectedRequests.contains(r -> r.breaking == req.breaking && r.x == req.x && r.y == req.y)){ //check if request was recently rejected, and skip it if so continue; }else if(!netServer.admins.allowAction(player, req.breaking ? ActionType.breakBlock : ActionType.placeBlock, tile, action -> { //make sure request is allowed by the server action.block = req.block; @@ -588,32 +592,40 @@ public class NetServer implements ApplicationListener{ action.config = req.config; })){ //force the player to remove this request if that's not the case - Call.removeQueueBlock(player.con(), req.x, req.y, req.breaking); - connection.rejectedRequests.add(req); + Call.removeQueueBlock(player.con, req.x, req.y, req.breaking); + con.rejectedRequests.add(req); continue; } player.builder().plans().addLast(req); } } - connection.rejectedRequests.clear(); + con.rejectedRequests.clear(); if(!player.dead()){ - Unitc unit = player.unit(); - long elapsed = Time.timeSinceMillis(connection.lastRecievedClientTime); - float maxSpeed = player.dead() ? Float.MAX_VALUE : player.unit().type().speed; + Unit unit = player.unit(); + + unit.vel.set(xVelocity, yVelocity).limit(unit.type().speed); + long elapsed = Time.timeSinceMillis(con.lastRecievedClientTime); + float maxSpeed = player.unit().type().speed; float maxMove = elapsed / 1000f * 60f * maxSpeed * 1.1f; - if(connection.lastUnit != unit && !player.dead()){ - connection.lastUnit = unit; - connection.lastPosition.set(unit); + if(con.lastUnit != unit){ + con.lastUnit = unit; + con.lastPosition.set(unit); } - vector.set(x, y).sub(connection.lastPosition); + //if the player think they're dead their position should be ignored + if(dead){ + x = unit.x; + y = unit.y; + } + + vector.set(x, y).sub(con.lastPosition); vector.limit(maxMove); - float prevx = unit.x(), prevy = unit.y(); - unit.set(connection.lastPosition); + float prevx = unit.x, prevy = unit.y; + unit.set(con.lastPosition); if(!unit.isFlying()){ unit.move(vector.x, vector.y); }else{ @@ -621,27 +633,24 @@ public class NetServer implements ApplicationListener{ } //set last position after movement - connection.lastPosition.set(unit); - float newx = unit.x(), newy = unit.y(); + con.lastPosition.set(unit); + float newx = unit.x, newy = unit.y; if(!verifyPosition){ unit.set(prevx, prevy); newx = x; newy = y; - }else if(!Mathf.within(x, y, newx, newy, correctDist)){ - Call.onPositionSet(player.con(), newx, newy); //teleport and correct position when necessary + }else if(!Mathf.within(x, y, newx, newy, correctDist) && !dead){ + Call.setPosition(player.con, newx, newy); //teleport and correct position when necessary } - //reset player to previous synced position so it gets interpolated - unit.set(prevx, prevy); - //write sync data to the buffer fbuffer.limit(20); fbuffer.position(0); //now, put the new position, rotation and baserotation into the buffer so it can be read + //TODO this is terrible if(unit instanceof Mechc) fbuffer.put(baseRotation); //base rotation is optional - fbuffer.put(unit.elevation()); fbuffer.put(rotation); //rotation is always there fbuffer.put(newx); fbuffer.put(newy); @@ -649,64 +658,60 @@ public class NetServer implements ApplicationListener{ //read sync data so it can be used for interpolation for the server unit.readSyncManual(fbuffer); - - //TODO clients shouldn't care about velocities, so should it always just get set to 0? why even save it? - //[[ignore sent velocity values, set it to the delta movement vector instead]] - //unit.vel().set(vector); }else{ - player.x(x); - player.y(y); + player.x = x; + player.y = y; } - connection.lastRecievedClientSnapshot = snapshotID; - connection.lastRecievedClientTime = Time.millis(); + con.lastRecievedClientSnapshot = snapshotID; + con.lastRecievedClientTime = Time.millis(); } @Remote(targets = Loc.client, called = Loc.server) - public static void onAdminRequest(Playerc player, Playerc other, AdminAction action){ + public static void adminRequest(Player player, Player other, AdminAction action){ - if(!player.admin()){ + if(!player.admin){ Log.warn("ACCESS DENIED: Player @ / @ attempted to perform admin action without proper security access.", - player.name(), player.con().address); + player.name, player.con.address); return; } - if(other == null || ((other.admin() && !player.isLocal()) && other != player)){ - Log.warn("@ attempted to perform admin action on nonexistant or admin player.", player.name()); + if(other == null || ((other.admin && !player.isLocal()) && other != player)){ + Log.warn("@ attempted to perform admin action on nonexistant or admin player.", player.name); return; } if(action == AdminAction.wave){ //no verification is done, so admins can hypothetically spam waves //not a real issue, because server owners may want to do just that - state.wavetime = 0f; + logic.skipWave(); }else if(action == AdminAction.ban){ - netServer.admins.banPlayerIP(other.con().address); + netServer.admins.banPlayerIP(other.con.address); other.kick(KickReason.banned); - Log.info("&lc@ has banned @.", player.name(), other.name()); + Log.info("&lc@ has banned @.", player.name, other.name); }else if(action == AdminAction.kick){ other.kick(KickReason.kick); - Log.info("&lc@ has kicked @.", player.name(), other.name()); + Log.info("&lc@ has kicked @.", player.name, other.name); }else if(action == AdminAction.trace){ - TraceInfo info = new TraceInfo(other.con().address, other.uuid(), other.con().modclient, other.con().mobile); - if(player.con() != null){ - Call.onTraceInfo(player.con(), other, info); + TraceInfo info = new TraceInfo(other.con.address, other.uuid(), other.con.modclient, other.con.mobile); + if(player.con != null){ + Call.traceInfo(player.con, other, info); }else{ - NetClient.onTraceInfo(other, info); + NetClient.traceInfo(other, info); } - Log.info("&lc@ has requested trace info of @.", player.name(), other.name()); + Log.info("&lc@ has requested trace info of @.", player.name, other.name); } } @Remote(targets = Loc.client) - public static void connectConfirm(Playerc player){ - if(player.con() == null || player.con().hasConnected) return; + public static void connectConfirm(Player player){ + if(player.con == null || player.con.hasConnected) return; player.add(); - player.con().hasConnected = true; + player.con.hasConnected = true; if(Config.showConnectMessages.bool()){ - Call.sendMessage("[accent]" + player.name() + "[accent] has connected."); - Log.info("&lm[@] &y@ has connected. ", player.uuid(), player.name()); + Call.sendMessage("[accent]" + player.name + "[accent] has connected."); + Log.info("&lm[@] &y@ has connected. ", player.uuid(), player.name); } if(!Config.motd.string().equalsIgnoreCase("off")){ @@ -772,7 +777,7 @@ public class NetServer implements ApplicationListener{ syncStream.reset(); short sent = 0; - for(Tilec entity : Groups.tile){ + for(Building entity : Groups.tile){ if(!entity.block().sync) continue; sent ++; @@ -782,7 +787,7 @@ public class NetServer implements ApplicationListener{ if(syncStream.size() > maxSnapshotSize){ dataStream.close(); byte[] stateBytes = syncStream.toByteArray(); - Call.onBlockSnapshot(sent, (short)stateBytes.length, net.compressSnapshot(stateBytes)); + Call.blockSnapshot(sent, (short)stateBytes.length, net.compressSnapshot(stateBytes)); sent = 0; syncStream.reset(); } @@ -791,11 +796,11 @@ public class NetServer implements ApplicationListener{ if(sent > 0){ dataStream.close(); byte[] stateBytes = syncStream.toByteArray(); - Call.onBlockSnapshot(sent, (short)stateBytes.length, net.compressSnapshot(stateBytes)); + Call.blockSnapshot(sent, (short)stateBytes.length, net.compressSnapshot(stateBytes)); } } - public void writeEntitySnapshot(Playerc player) throws IOException{ + public void writeEntitySnapshot(Player player) throws IOException{ syncStream.reset(); Seq cores = state.teams.cores(player.team()); @@ -803,16 +808,16 @@ public class NetServer implements ApplicationListener{ for(CoreEntity entity : cores){ dataStream.writeInt(entity.tile().pos()); - entity.items().write(Writes.get(dataStream)); + entity.items.write(Writes.get(dataStream)); } dataStream.close(); byte[] stateBytes = syncStream.toByteArray(); //write basic state data. - Call.onStateSnapshot(player.con(), state.wavetime, state.wave, state.enemies, state.serverPaused, (short)stateBytes.length, net.compressSnapshot(stateBytes)); + Call.stateSnapshot(player.con, state.wavetime, state.wave, state.enemies, state.serverPaused, (short)stateBytes.length, net.compressSnapshot(stateBytes)); - viewport.setSize(player.con().viewWidth, player.con().viewHeight).setCenter(player.con().viewX, player.con().viewY); + viewport.setSize(player.con.viewWidth, player.con.viewHeight).setCenter(player.con.viewX, player.con.viewY); syncStream.reset(); @@ -829,7 +834,7 @@ public class NetServer implements ApplicationListener{ if(syncStream.size() > maxSnapshotSize){ dataStream.close(); byte[] syncBytes = syncStream.toByteArray(); - Call.onEntitySnapshot(player.con(), (short)sent, (short)syncBytes.length, net.compressSnapshot(syncBytes)); + Call.entitySnapshot(player.con, (short)sent, (short)syncBytes.length, net.compressSnapshot(syncBytes)); sent = 0; syncStream.reset(); } @@ -839,7 +844,7 @@ public class NetServer implements ApplicationListener{ dataStream.close(); byte[] syncBytes = syncStream.toByteArray(); - Call.onEntitySnapshot(player.con(), (short)sent, (short)syncBytes.length, net.compressSnapshot(syncBytes)); + Call.entitySnapshot(player.con, (short)sent, (short)syncBytes.length, net.compressSnapshot(syncBytes)); } } @@ -898,12 +903,12 @@ public class NetServer implements ApplicationListener{ try{ Groups.player.each(p -> !p.isLocal(), player -> { - if(player.con() == null || !player.con().isConnected()){ + if(player.con == null || !player.con.isConnected()){ onDisconnect(player, "disappeared"); return; } - NetConnection connection = player.con(); + NetConnection connection = player.con; if(!player.timer(0, serverSyncTime) || !connection.hasConnected) return; @@ -924,6 +929,6 @@ public class NetServer implements ApplicationListener{ } public interface TeamAssigner{ - Team assign(Playerc player, Iterable players); + Team assign(Player player, Iterable players); } } diff --git a/core/src/mindustry/core/Platform.java b/core/src/mindustry/core/Platform.java index 767bfa993d..83390c82a8 100644 --- a/core/src/mindustry/core/Platform.java +++ b/core/src/mindustry/core/Platform.java @@ -136,7 +136,7 @@ public interface Platform{ * @param extension File extension to filter */ default void showFileChooser(boolean open, String extension, Cons cons){ - new FileChooser(open ? "$open" : "$save", file -> file.extension().toLowerCase().equals(extension), open, file -> { + new FileChooser(open ? "$open" : "$save", file -> file.extEquals(extension), open, file -> { if(!open){ cons.get(file.parent().child(file.nameWithoutExtension() + "." + extension)); }else{ @@ -145,6 +145,19 @@ public interface Platform{ }).show(); } + /** + * Show a file chooser for multiple file types. Only supported on desktop. + * @param cons Selection listener + * @param extensions File extensions to filter + */ + default void showMultiFileChooser(Cons cons, String... extensions){ + if(mobile){ + showFileChooser(true, extensions[0], cons); + }else{ + new FileChooser("$open", file -> Structs.contains(extensions, file.extension().toLowerCase()), true, cons).show(); + } + } + /** Hide the app. Android only. */ default void hide(){ } diff --git a/core/src/mindustry/core/Renderer.java b/core/src/mindustry/core/Renderer.java index cf0c911d52..a60dbbefc6 100644 --- a/core/src/mindustry/core/Renderer.java +++ b/core/src/mindustry/core/Renderer.java @@ -233,7 +233,7 @@ public class Renderer implements ApplicationListener{ Draw.draw(Layer.plans, overlays::drawBottom); - if(settings.getBool("animatedshields")){ + if(settings.getBool("animatedshields") && Shaders.shield != null){ Draw.drawRange(Layer.shields, 1f, () -> effectBuffer.begin(Color.clear), () -> { effectBuffer.end(); effectBuffer.blit(Shaders.shield); @@ -259,7 +259,7 @@ public class Renderer implements ApplicationListener{ private void drawLanding(){ if(landTime > 0 && player.closestCore() != null){ float fract = landTime / Fx.coreLand.lifetime; - Tilec entity = player.closestCore(); + Building entity = player.closestCore(); TextureRegion reg = entity.block().icon(Cicon.full); float scl = Scl.scl(4f) / camerascale; diff --git a/core/src/mindustry/core/UI.java b/core/src/mindustry/core/UI.java index f26c2cd498..8dfcefdad9 100644 --- a/core/src/mindustry/core/UI.java +++ b/core/src/mindustry/core/UI.java @@ -63,8 +63,7 @@ public class UI implements ApplicationListener, Loadable{ public DatabaseDialog database; public ContentInfoDialog content; public PlanetDialog planet; - public TechTreeDialog tech; - //public MinimapDialog minimap; + public ResearchDialog research; public SchematicsDialog schematics; public ModsDialog mods; public ColorPicker picker; @@ -176,7 +175,7 @@ public class UI implements ApplicationListener, Loadable{ maps = new MapsDialog(); content = new ContentInfoDialog(); planet = new PlanetDialog(); - tech = new TechTreeDialog(); + research = new ResearchDialog(); mods = new ModsDialog(); schematics = new SchematicsDialog(); @@ -334,10 +333,17 @@ public class UI implements ApplicationListener, Loadable{ } public void showInfo(String info){ + showInfo(info, () -> {}); + } + + public void showInfo(String info, Runnable listener){ new Dialog(""){{ getCell(cont).growX(); cont.margin(15).add(info).width(400f).wrap().get().setAlignment(Align.center, Align.center); - buttons.button("$ok", this::hide).size(110, 50).pad(4); + buttons.button("$ok", () -> { + hide(); + listener.run(); + }).size(110, 50).pad(4); }}.show(); } @@ -461,6 +467,15 @@ public class UI implements ApplicationListener, Loadable{ dialog.show(); } + public void announce(String text){ + Table t = new Table(); + t.background(Styles.black3).margin(8f) + .add(text).style(Styles.outlineLabel); + t.update(() -> t.setPosition(Core.graphics.getWidth()/2f, Core.graphics.getHeight()/2f, Align.center)); + t.actions(Actions.fadeOut(3, Interp.pow4In)); + Core.scene.add(t); + } + public void showOkText(String title, String text, Runnable confirmed){ BaseDialog dialog = new BaseDialog(title); dialog.cont.add(text).width(500f).wrap().pad(4f).get().setAlignment(Align.center, Align.center); diff --git a/core/src/mindustry/core/World.java b/core/src/mindustry/core/World.java index 415619bf94..fb9d5585eb 100644 --- a/core/src/mindustry/core/World.java +++ b/core/src/mindustry/core/World.java @@ -102,25 +102,25 @@ public class World{ } @Nullable - public Tile tilec(int x, int y){ + public Tile Building(int x, int y){ Tile tile = tiles.get(x, y); if(tile == null) return null; - if(tile.entity != null) return tile.entity.tile(); + if(tile.build != null) return tile.build.tile(); return tile; } @Nullable - public Tilec ent(int x, int y){ + public Building ent(int x, int y){ Tile tile = tile(x, y); if(tile == null) return null; - return tile.entity; + return tile.build; } @Nullable - public Tilec ent(int pos){ + public Building ent(int pos){ Tile tile = tile(pos); if(tile == null) return null; - return tile.entity; + return tile.build; } @NonNull @@ -134,7 +134,7 @@ public class World{ } @Nullable - public Tilec entWorld(float x, float y){ + public Building entWorld(float x, float y){ return ent(Math.round(x / tilesize), Math.round(y / tilesize)); } @@ -144,8 +144,8 @@ public class World{ private void clearTileEntities(){ for(Tile tile : tiles){ - if(tile != null && tile.entity != null){ - tile.entity.remove(); + if(tile != null && tile.build != null){ + tile.build.remove(); } } } @@ -166,7 +166,7 @@ public class World{ /** * Call to signify the beginning of map loading. - * TileChangeEvents will not be fired until endMapLoad(). + * BuildinghangeEvents will not be fired until endMapLoad(). */ public void beginMapLoad(){ generating = true; @@ -187,8 +187,8 @@ public class World{ tile.updateOcclusion(); - if(tile.entity != null){ - tile.entity.updateProximity(); + if(tile.build != null){ + tile.build.updateProximity(); } } @@ -317,7 +317,7 @@ public class World{ public void notifyChanged(Tile tile){ if(!generating){ - Core.app.post(() -> Events.fire(new TileChangeEvent(tile))); + Core.app.post(() -> Events.fire(new BuildinghangeEvent(tile))); } } diff --git a/core/src/mindustry/editor/DrawOperation.java b/core/src/mindustry/editor/DrawOperation.java index 0d6607e8ff..c28219f629 100755 --- a/core/src/mindustry/editor/DrawOperation.java +++ b/core/src/mindustry/editor/DrawOperation.java @@ -52,7 +52,7 @@ public class DrawOperation{ }else if(type == OpType.rotation.ordinal()){ return tile.rotation(); }else if(type == OpType.team.ordinal()){ - return tile.getTeamID(); + return (byte)tile.getTeamID(); }else if(type == OpType.overlay.ordinal()){ return tile.overlayID(); } diff --git a/core/src/mindustry/editor/EditorTile.java b/core/src/mindustry/editor/EditorTile.java index 8af3a40818..45965b4dab 100644 --- a/core/src/mindustry/editor/EditorTile.java +++ b/core/src/mindustry/editor/EditorTile.java @@ -55,7 +55,7 @@ public class EditorTile extends Tile{ op(OpType.block, block.id); if(rotation != 0) op(OpType.rotation, (byte)rotation); - if(team() != Team.derelict) op(OpType.team, team().id); + if(team() != Team.derelict) op(OpType.team, (byte)team().id); super.setBlock(type, team, rotation); } @@ -67,7 +67,7 @@ public class EditorTile extends Tile{ } if(getTeamID() == team.id) return; - op(OpType.team, getTeamID()); + op(OpType.team, (byte)getTeamID()); super.setTeam(team); } @@ -109,13 +109,13 @@ public class EditorTile extends Tile{ } @Override - protected void changeEntity(Team team, Prov entityprov){ + protected void changeEntity(Team team, Prov entityprov){ if(state.isGame()){ super.changeEntity(team, entityprov); return; } - entity = null; + build = null; if(block == null) block = Blocks.air; if(floor == null) floor = (Floor)Blocks.air; @@ -123,11 +123,11 @@ public class EditorTile extends Tile{ Block block = block(); if(block.hasEntity()){ - entity = entityprov.get().init(this, team, false); - entity.cons(new ConsumeModule(entity)); - if(block.hasItems) entity.items(new ItemModule()); - if(block.hasLiquids) entity.liquids(new LiquidModule()); - if(block.hasPower) entity.power(new PowerModule()); + build = entityprov.get().init(this, team, false); + build.cons(new ConsumeModule(build)); + if(block.hasItems) build.items = new ItemModule(); + if(block.hasLiquids) build.liquids(new LiquidModule()); + if(block.hasPower) build.power(new PowerModule()); } } diff --git a/core/src/mindustry/editor/EditorTool.java b/core/src/mindustry/editor/EditorTool.java index a6493d4401..47053049e2 100644 --- a/core/src/mindustry/editor/EditorTool.java +++ b/core/src/mindustry/editor/EditorTool.java @@ -139,7 +139,7 @@ public enum EditorTool{ if(tile.synthetic()){ Team dest = tile.team(); if(dest == editor.drawTeam) return; - fill(editor, x, y, false, t -> t.getTeamID() == (int)dest.id && t.synthetic(), t -> t.setTeam(editor.drawTeam)); + fill(editor, x, y, false, t -> t.getTeamID() == dest.id && t.synthetic(), t -> t.setTeam(editor.drawTeam)); } } } diff --git a/core/src/mindustry/editor/MapEditorDialog.java b/core/src/mindustry/editor/MapEditorDialog.java index 7c5dd8d321..a8caf77d8c 100644 --- a/core/src/mindustry/editor/MapEditorDialog.java +++ b/core/src/mindustry/editor/MapEditorDialog.java @@ -156,7 +156,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ } platform.publish(map); - }).padTop(-3).size(swidth * 2f + 10, 60f).update(b -> b.setText(editor.getTags().containsKey("steamid") ? editor.getTags().get("author").equals(player.name()) ? "$workshop.listing" : "$view.workshop" : "$editor.publish.workshop")); + }).padTop(-3).size(swidth * 2f + 10, 60f).update(b -> b.setText(editor.getTags().containsKey("steamid") ? editor.getTags().get("author").equals(player.name) ? "$workshop.listing" : "$view.workshop" : "$editor.publish.workshop")); menu.cont.row(); } @@ -234,6 +234,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ show(); state.rules = (lastSavedRules == null ? new Rules() : lastSavedRules); lastSavedRules = null; + saved = false; editor.renderer().updateAll(); } @@ -248,15 +249,15 @@ public class MapEditorDialog extends Dialog implements Disposable{ state.rules = Gamemode.editor.apply(lastSavedRules.copy()); state.rules.sector = null; state.map = new Map(StringMap.of( - "name", "Editor Playtesting", - "width", editor.width(), - "height", editor.height() - )); + "name", "Editor Playtesting", + "width", editor.width(), + "height", editor.height() + )); world.endMapLoad(); //add entities so they update. is this really needed? for(Tile tile : world.tiles){ - if(tile.entity != null){ - tile.entity.add(); + if(tile.build != null){ + tile.build.add(); } } player.set(world.width() * tilesize/2f, world.height() * tilesize/2f); diff --git a/core/src/mindustry/editor/MapGenerateDialog.java b/core/src/mindustry/editor/MapGenerateDialog.java index 1517a63db8..c7d7d86ae4 100644 --- a/core/src/mindustry/editor/MapGenerateDialog.java +++ b/core/src/mindustry/editor/MapGenerateDialog.java @@ -51,7 +51,7 @@ public class MapGenerateDialog extends BaseDialog{ private CachedTile ctile = new CachedTile(){ //nothing. @Override - protected void changeEntity(Team team, Prov entityprov){ + protected void changeEntity(Team team, Prov entityprov){ } }; @@ -409,7 +409,7 @@ public class MapGenerateDialog extends BaseDialog{ this.floor = floor.id; this.block = wall.id; this.ore = ore.id; - this.team = team.id; + this.team = (byte)team.id; this.rotation = (byte)rotation; } diff --git a/core/src/mindustry/editor/MapRenderer.java b/core/src/mindustry/editor/MapRenderer.java index 4cf969a5dd..91345b37ea 100644 --- a/core/src/mindustry/editor/MapRenderer.java +++ b/core/src/mindustry/editor/MapRenderer.java @@ -7,7 +7,6 @@ import arc.math.*; import arc.struct.*; import arc.util.*; import mindustry.content.*; -import mindustry.game.EventType.*; import mindustry.game.*; import mindustry.graphics.*; import mindustry.world.*; @@ -26,10 +25,6 @@ public class MapRenderer implements Disposable{ public MapRenderer(MapEditor editor){ this.editor = editor; this.texture = Core.atlas.find("clear-editor").getTexture(); - - Events.on(ContentReloadEvent.class, e -> { - texture = Core.atlas.find("clear-editor").getTexture(); - }); } public void resize(int width, int height){ diff --git a/core/src/mindustry/entities/Damage.java b/core/src/mindustry/entities/Damage.java index 26516d8ecb..7e2f977871 100644 --- a/core/src/mindustry/entities/Damage.java +++ b/core/src/mindustry/entities/Damage.java @@ -26,6 +26,8 @@ public class Damage{ private static GridBits bits = new GridBits(30, 30); private static IntQueue propagation = new IntQueue(); private static IntSet collidedBlocks = new IntSet(); + private static Building tmpBuilding; + private static Unit tmpUnit; /** Creates a dynamic explosion based on specified parameters. */ public static void dynamicExplosion(float x, float y, float flammability, float explosiveness, float power, float radius, Color color){ @@ -72,7 +74,7 @@ public class Damage{ } } - public static void collideLine(Bulletc hitter, Team team, Effect effect, float x, float y, float angle, float length){ + public static void collideLine(Bullet hitter, Team team, Effect effect, float x, float y, float angle, float length){ collideLine(hitter, team, effect, x, y, angle, length, false); } @@ -80,27 +82,29 @@ public class Damage{ * Damages entities in a line. * Only enemies of the specified team are damaged. */ - public static void collideLine(Bulletc hitter, Team team, Effect effect, float x, float y, float angle, float length, boolean large){ + public static void collideLine(Bullet hitter, Team team, Effect effect, float x, float y, float angle, float length, boolean large){ collidedBlocks.clear(); tr.trns(angle, length); Intc2 collider = (cx, cy) -> { - Tilec tile = world.ent(cx, cy); + Building tile = world.ent(cx, cy); if(tile != null && !collidedBlocks.contains(tile.pos()) && tile.team() != team && tile.collide(hitter)){ tile.collision(hitter); collidedBlocks.add(tile.pos()); - hitter.type().hit(hitter, tile.x(), tile.y()); + hitter.type.hit(hitter, tile.x, tile.y); } }; - world.raycastEachWorld(x, y, x + tr.x, y + tr.y, (cx, cy) -> { - collider.get(cx, cy); - if(large){ - for(Point2 p : Geometry.d4){ - collider.get(cx + p.x, cy + p.y); + if(hitter.type.collidesGround){ + world.raycastEachWorld(x, y, x + tr.x, y + tr.y, (cx, cy) -> { + collider.get(cx, cy); + if(large){ + for(Point2 p : Geometry.d4){ + collider.get(cx + p.x, cy + p.y); + } } - } - return false; - }); + return false; + }); + } rect.setPosition(x, y).setSize(tr.x, tr.y); float x2 = tr.x + x, y2 = tr.y + y; @@ -122,7 +126,9 @@ public class Damage{ rect.width += expand * 2; rect.height += expand * 2; - Cons cons = e -> { + Cons cons = e -> { + if(!e.checkTarget(hitter.type.collidesAir, hitter.type.collidesGround)) return; + e.hitbox(hitrect); Rect other = hitrect; other.y -= expand; @@ -142,9 +148,76 @@ public class Damage{ Units.nearbyEnemies(team, rect, cons); } + /** + * Casts forward in a line. + * @return the first encountered object. + */ + public static Healthc linecast(Bullet hitter, float x, float y, float angle, float length){ + tr.trns(angle, length); + + if(hitter.type.collidesGround){ + tmpBuilding = null; + + world.raycastEachWorld(x, y, x + tr.x, y + tr.y, (cx, cy) -> { + Building tile = world.ent(cx, cy); + if(tile != null && tile.team != hitter.team){ + tmpBuilding = tile; + //TODO return tile + return true; + } + return false; + }); + + if(tmpBuilding != null) return tmpBuilding; + } + + rect.setPosition(x, y).setSize(tr.x, tr.y); + float x2 = tr.x + x, y2 = tr.y + y; + + if(rect.width < 0){ + rect.x += rect.width; + rect.width *= -1; + } + + if(rect.height < 0){ + rect.y += rect.height; + rect.height *= -1; + } + + float expand = 3f; + + rect.y -= expand; + rect.x -= expand; + rect.width += expand * 2; + rect.height += expand * 2; + + tmpUnit = null; + + Cons cons = e -> { + if((tmpUnit != null && e.dst2(x, y) > tmpUnit.dst2(x, y)) || !e.checkTarget(hitter.type.collidesAir, hitter.type.collidesGround)) return; + + e.hitbox(hitrect); + Rect other = hitrect; + other.y -= expand; + other.x -= expand; + other.width += expand * 2; + other.height += expand * 2; + + Vec2 vec = Geometry.raycastRect(x, y, x2, y2, other); + + if(vec != null){ + tmpUnit = e; + } + }; + + Units.nearbyEnemies(hitter.team, rect, cons); + + return tmpUnit; + } + /** Damages all entities and blocks in a radius that are enemies of the team. */ - public static void damageUnits(Team team, float x, float y, float size, float damage, Boolf predicate, Cons acceptor){ - Cons cons = entity -> { + public static void damageUnits(Team team, float x, float y, float size, float damage, Boolf predicate, Cons acceptor){ + Cons cons = entity -> { if(!predicate.get(entity)) return; entity.hitbox(hitrect); @@ -180,8 +253,8 @@ public class Damage{ /** Applies a status effect to all enemy units in a range. */ public static void status(Team team, float x, float y, float radius, StatusEffect effect, float duration, boolean air, boolean ground){ - Cons cons = entity -> { - if(entity.team() == team || !entity.within(x, y, radius) || (entity.isFlying() && !air) || (entity.isGrounded() && !ground)){ + Cons cons = entity -> { + if(entity.team == team || !entity.within(x, y, radius) || (entity.isFlying() && !air) || (entity.isGrounded() && !ground)){ return; } @@ -203,15 +276,15 @@ public class Damage{ /** Damages all entities and blocks in a radius that are enemies of the team. */ public static void damage(Team team, float x, float y, float radius, float damage, boolean complete, boolean air, boolean ground){ - Cons cons = entity -> { - if(entity.team() == team || !entity.within(x, y, radius) || (entity.isFlying() && !air) || (entity.isGrounded() && !ground)){ + Cons cons = entity -> { + if(entity.team == team || !entity.within(x, y, radius) || (entity.isFlying() && !air) || (entity.isGrounded() && !ground)){ return; } float amount = calculateDamage(x, y, entity.getX(), entity.getY(), radius, damage); entity.damage(amount); //TODO better velocity displacement float dst = tr.set(entity.getX() - x, entity.getY() - y).len(); - entity.vel().add(tr.setLength((1f - dst / radius) * 2f / entity.mass())); + entity.vel.add(tr.setLength((1f - dst / radius) * 2f / entity.mass())); if(complete && damage >= 9999999f && entity.isPlayer()){ Events.fire(Trigger.exclusionDeath); @@ -225,14 +298,16 @@ public class Damage{ Units.nearby(rect, cons); } - if(!complete){ - int trad = (int)(radius / tilesize); - Tile tile = world.tileWorld(x, y); - if(tile != null){ - tileDamage(team, tile.x, tile.y, trad, damage); + if(ground){ + if(!complete){ + int trad = (int)(radius / tilesize); + Tile tile = world.tileWorld(x, y); + if(tile != null){ + tileDamage(team, tile.x, tile.y, trad, damage); + } + }else{ + completeDamage(team, x, y, radius, damage); } - }else{ - completeDamage(team, x, y, radius, damage); } } @@ -265,10 +340,10 @@ public class Damage{ if(scaledDamage <= 0 || tile == null) continue; //apply damage to entity if needed - if(tile.entity != null && tile.team() != team){ - int health = (int)tile.entity.health(); - if(tile.entity.health() > 0){ - tile.entity.damage(scaledDamage); + if(tile.build != null && tile.team() != team){ + int health = (int)tile.build.health(); + if(tile.build.health() > 0){ + tile.build.damage(scaledDamage); scaledDamage -= health; if(scaledDamage <= 0) continue; @@ -290,8 +365,8 @@ public class Damage{ for(int dx = -trad; dx <= trad; dx++){ for(int dy = -trad; dy <= trad; dy++){ Tile tile = world.tile(Math.round(x / tilesize) + dx, Math.round(y / tilesize) + dy); - if(tile != null && tile.entity != null && (team == null ||team.isEnemy(tile.team())) && Mathf.dst(dx, dy) <= trad){ - tile.entity.damage(damage); + if(tile != null && tile.build != null && (team == null ||team.isEnemy(tile.team())) && Mathf.dst(dx, dy) <= trad){ + tile.build.damage(damage); } } } diff --git a/core/src/mindustry/entities/Effects.java b/core/src/mindustry/entities/Effects.java index 86f3defddd..c66aaabcf0 100644 --- a/core/src/mindustry/entities/Effects.java +++ b/core/src/mindustry/entities/Effects.java @@ -42,7 +42,7 @@ public class Effects{ Rect pos = Tmp.r2.setSize(effect.size).setCenter(x, y); if(view.overlaps(pos)){ - Effectc entity = EffectEntity.create(); + EffectState entity = EffectState.create(); entity.effect(effect); entity.rotation(rotation); entity.data(data); @@ -55,10 +55,14 @@ public class Effects{ } } + public static void decal(TextureRegion region, float x, float y, float rotation){ + decal(region, x, y, rotation, 3600f, Pal.rubble); + } + public static void decal(TextureRegion region, float x, float y, float rotation, float lifetime, Color color){ if(headless || region == null || !Core.atlas.isFound(region)) return; - Decalc decal = DecalEntity.create(); + Decal decal = Decal.create(); decal.set(x, y); decal.rotation(rotation); decal.lifetime(lifetime); diff --git a/core/src/mindustry/entities/EntityCollisions.java b/core/src/mindustry/entities/EntityCollisions.java index 41a9f21276..2d8402e92c 100644 --- a/core/src/mindustry/entities/EntityCollisions.java +++ b/core/src/mindustry/entities/EntityCollisions.java @@ -24,6 +24,12 @@ public class EntityCollisions{ //entity collisions private Seq arrOut = new Seq<>(); + public void moveCheck(Hitboxc entity, float deltax, float deltay, SolidPred solidCheck){ + if(!solidCheck.solid(entity.tileX(), entity.tileY())){ + move(entity, deltax, deltay, solidCheck); + } + } + public void move(Hitboxc entity, float deltax, float deltay){ move(entity, deltax, deltay, EntityCollisions::solid); } @@ -119,14 +125,19 @@ public class EntityCollisions{ }); } + public static boolean legsSolid(int x, int y){ + Tile tile = world.tile(x, y); + return tile == null || tile.staticDarkness() >= 2; + } + public static boolean waterSolid(int x, int y){ Tile tile = world.tile(x, y); - return tile != null && (tile.solid() || !tile.floor().isLiquid); + return tile == null || (tile.solid() || !tile.floor().isLiquid); } public static boolean solid(int x, int y){ Tile tile = world.tile(x, y); - return tile != null && tile.solid(); + return tile == null || tile.solid(); } private void checkCollide(Hitboxc a, Hitboxc b){ diff --git a/core/src/mindustry/entities/EntityGroup.java b/core/src/mindustry/entities/EntityGroup.java index 80d01ea9cd..f9c6d55316 100644 --- a/core/src/mindustry/entities/EntityGroup.java +++ b/core/src/mindustry/entities/EntityGroup.java @@ -166,6 +166,9 @@ public class EntityGroup implements Iterable{ int idx = array.indexOf(type, true); if(idx != -1){ array.remove(idx); + if(map != null){ + map.remove(type.id()); + } //fix iteration index when removing if(index >= idx){ diff --git a/core/src/mindustry/entities/Fires.java b/core/src/mindustry/entities/Fires.java index a5577c2027..6d329e8f50 100644 --- a/core/src/mindustry/entities/Fires.java +++ b/core/src/mindustry/entities/Fires.java @@ -13,16 +13,16 @@ import static mindustry.Vars.*; public class Fires{ private static final float baseLifetime = 1000f; - private static final IntMap map = new IntMap<>(); + private static final IntMap map = new IntMap<>(); /** Start a fire on the tile. If there already is a file there, refreshes its lifetime. */ public static void create(Tile tile){ if(net.client() || tile == null) return; //not clientside. - Firec fire = map.get(tile.pos()); + Fire fire = map.get(tile.pos()); if(fire == null){ - fire = FireEntity.create(); + fire = Fire.create(); fire.tile(tile); fire.lifetime(baseLifetime); fire.set(tile.worldx(), tile.worldy()); @@ -34,7 +34,7 @@ public class Fires{ } } - public static Firec get(int x, int y){ + public static Fire get(int x, int y){ return map.get(Point2.pack(x, y)); } @@ -42,7 +42,7 @@ public class Fires{ if(!Structs.inBounds(x, y, world.width(), world.height()) || !map.containsKey(Point2.pack(x, y))){ return false; } - Firec fire = map.get(Point2.pack(x, y)); + Fire fire = map.get(Point2.pack(x, y)); return fire.isAdded() && fire.fin() < 1f && fire.tile() != null && fire.tile().x == x && fire.tile().y == y; } @@ -51,7 +51,7 @@ public class Fires{ */ public static void extinguish(Tile tile, float intensity){ if(tile != null && map.containsKey(tile.pos())){ - Firec fire = map.get(tile.pos()); + Fire fire = map.get(tile.pos()); fire.time(fire.time() + intensity * Time.delta()); Fx.steam.at(fire); if(fire.time() >= fire.lifetime()){ @@ -64,7 +64,7 @@ public class Fires{ map.remove(tile.pos()); } - public static void register(Firec fire){ - map.put(fire.tile().pos(), fire); + public static void register(Fire fire){ + map.put(fire.tile.pos(), fire); } } diff --git a/core/src/mindustry/entities/GroupDefs.java b/core/src/mindustry/entities/GroupDefs.java index f91be60928..3d2dcc1580 100644 --- a/core/src/mindustry/entities/GroupDefs.java +++ b/core/src/mindustry/entities/GroupDefs.java @@ -4,12 +4,12 @@ import mindustry.annotations.Annotations.*; import mindustry.gen.*; class GroupDefs{ - @GroupDef(value = Entityc.class, mapping = true) G all; + @GroupDef(value = Entityc.class) G all; @GroupDef(value = Playerc.class, mapping = true) G player; @GroupDef(value = Bulletc.class, spatial = true, collide = true) G bullet; @GroupDef(value = Unitc.class, spatial = true, mapping = true) G unit; - @GroupDef(value = Tilec.class) G tile; + @GroupDef(value = Buildingc.class) G tile; @GroupDef(value = Syncc.class, mapping = true) G sync; @GroupDef(value = Drawc.class) G draw; - @GroupDef(value = Weatherc.class) G weather; + @GroupDef(value = WeatherStatec.class) G weather; } diff --git a/core/src/mindustry/entities/Lightning.java b/core/src/mindustry/entities/Lightning.java index db37d6c39b..dbc7f616c9 100644 --- a/core/src/mindustry/entities/Lightning.java +++ b/core/src/mindustry/entities/Lightning.java @@ -5,6 +5,7 @@ import arc.math.*; import arc.math.geom.*; import arc.struct.*; import mindustry.content.*; +import mindustry.entities.bullet.*; import mindustry.game.*; import mindustry.gen.*; import mindustry.world.*; @@ -21,22 +22,28 @@ public class Lightning{ private static boolean bhit = false; private static int lastSeed = 0; - /** Create a lighting branch at a location. Use Team.none to damage everyone. */ + /** Create a lighting branch at a location. Use Team.derelict to damage everyone. */ public static void create(Team team, Color color, float damage, float x, float y, float targetAngle, int length){ - createLightingInternal(lastSeed++, team, color, damage, x, y, targetAngle, length); + createLightingInternal(null, lastSeed++, team, color, damage, x, y, targetAngle, length); + } + + /** Create a lighting branch at a location. Uses bullet parameters. */ + public static void create(Bullet bullet, Color color, float damage, float x, float y, float targetAngle, int length){ + createLightingInternal(bullet, lastSeed++, bullet.team, color, damage, x, y, targetAngle, length); } //TODO remote method //@Remote(called = Loc.server, unreliable = true) - private static void createLightingInternal(int seed, Team team, Color color, float damage, float x, float y, float rotation, int length){ + private static void createLightingInternal(Bullet hitter, int seed, Team team, Color color, float damage, float x, float y, float rotation, int length){ random.setSeed(seed); hit.clear(); + BulletType bulletType = hitter != null && !hitter.type.collidesAir ? Bullets.damageLightningGround : Bullets.damageLightning; Seq lines = new Seq<>(); bhit = false; for(int i = 0; i < length / 2; i++){ - Bullets.damageLightning.create(null, team, x, y, 0f, damage, 1f, 1f, null); + bulletType.create(null, team, x, y, 0f, damage, 1f, 1f, hitter); lines.add(new Vec2(x + Mathf.range(3f), y + Mathf.range(3f))); if(lines.size > 1){ @@ -61,7 +68,7 @@ public class Lightning{ entities.clear(); if(hit.size < maxChain){ Units.nearbyEnemies(team, rect, u -> { - if(!hit.contains(u.id())){ + if(!hit.contains(u.id()) && (hitter == null || u.checkTarget(hitter.type.collidesAir, hitter.type.collidesGround))){ entities.add(u); } }); diff --git a/core/src/mindustry/entities/Puddles.java b/core/src/mindustry/entities/Puddles.java index 9d10b84213..3b9f02c75c 100644 --- a/core/src/mindustry/entities/Puddles.java +++ b/core/src/mindustry/entities/Puddles.java @@ -10,22 +10,22 @@ import mindustry.type.*; import mindustry.world.*; public class Puddles{ - private static final IntMap map = new IntMap<>(); + private static final IntMap map = new IntMap<>(); public static final float maxLiquid = 70f; - /** Deposists a Puddlec between tile and source. */ + /** Deposists a Puddle between tile and source. */ public static void deposit(Tile tile, Tile source, Liquid liquid, float amount){ deposit(tile, source, liquid, amount, 0); } - /** Deposists a Puddlec at a tile. */ + /** Deposists a Puddle at a tile. */ public static void deposit(Tile tile, Liquid liquid, float amount){ deposit(tile, tile, liquid, amount, 0); } - /** Returns the Puddlec on the specified tile. May return null. */ - public static Puddlec get(Tile tile){ + /** Returns the Puddle on the specified tile. May return null. */ + public static Puddle get(Tile tile){ return map.get(tile.pos()); } @@ -36,7 +36,7 @@ public class Puddles{ reactPuddle(tile.floor().liquidDrop, liquid, amount, tile, (tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f); - Puddlec p = map.get(tile.pos()); + Puddle p = map.get(tile.pos()); if(generation == 0 && p != null && p.lastRipple() <= Time.time() - 40f){ Fx.ripple.at((tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f, 1f, tile.floor().liquidDrop.color); @@ -45,9 +45,9 @@ public class Puddles{ return; } - Puddlec p = map.get(tile.pos()); + Puddle p = map.get(tile.pos()); if(p == null){ - Puddlec puddle = PuddleEntity.create(); + Puddle puddle = Puddle.create(); puddle.tile(tile); puddle.liquid(liquid); puddle.amount(amount); @@ -73,7 +73,7 @@ public class Puddles{ map.remove(tile.pos()); } - public static void register(Puddlec puddle){ + public static void register(Puddle puddle){ map.put(puddle.tile().pos(), puddle); } @@ -85,12 +85,12 @@ public class Puddles{ if(Mathf.chance(0.006 * amount)){ Call.createBullet(Bullets.fireball, Team.derelict, x, y, Mathf.random(360f), -1f, 1f, 1f); } - }else if(dest.temperature > 0.7f && liquid.temperature < 0.55f){ //cold liquid poured onto hot Puddlec + }else if(dest.temperature > 0.7f && liquid.temperature < 0.55f){ //cold liquid poured onto hot Puddle if(Mathf.chance(0.5f * amount)){ Fx.steam.at(x, y); } return -0.1f * amount; - }else if(liquid.temperature > 0.7f && dest.temperature < 0.55f){ //hot liquid poured onto cold Puddlec + }else if(liquid.temperature > 0.7f && dest.temperature < 0.55f){ //hot liquid poured onto cold Puddle if(Mathf.chance(0.8f * amount)){ Fx.steam.at(x, y); } diff --git a/core/src/mindustry/entities/Units.java b/core/src/mindustry/entities/Units.java index 07a31a4368..3948c608c5 100644 --- a/core/src/mindustry/entities/Units.java +++ b/core/src/mindustry/entities/Units.java @@ -2,6 +2,8 @@ package mindustry.entities; import arc.func.*; import arc.math.geom.*; +import mindustry.annotations.Annotations.*; +import mindustry.content.*; import mindustry.game.*; import mindustry.gen.*; import mindustry.world.*; @@ -10,11 +12,22 @@ import static mindustry.Vars.*; /** Utility class for unit and team interactions.*/ public class Units{ - private static Rect hitrect = new Rect(); - private static Unitc result; + private static final Rect hitrect = new Rect(); + private static Unit result; private static float cdist; private static boolean boolResult; + @Remote(called = Loc.server) + public static void unitDeath(Unit unit){ + unit.killed(); + } + + @Remote(called = Loc.server) + public static void unitDespawn(Unit unit){ + Fx.unitDespawn.at(unit.x, unit.y, 0, unit); + unit.remove(); + } + /** @return whether a new instance of a unit of this team can be created. */ public static boolean canCreate(Team team){ return teamIndex.count(team) < getCap(team); @@ -25,7 +38,7 @@ public class Units{ } /** @return whether this player can interact with a specific tile. if either of these are null, returns true.*/ - public static boolean canInteract(Playerc player, Tilec tile){ + public static boolean canInteract(Player player, Building tile){ return player == null || tile == null || tile.interactable(player.team()); } @@ -48,7 +61,7 @@ public class Units{ } /** See {@link #invalidateTarget(Posc, Team, float, float, float)} */ - public static boolean invalidateTarget(Teamc target, Unitc targeter, float range){ + public static boolean invalidateTarget(Teamc target, Unit targeter, float range){ return invalidateTarget(target, targeter.team(), targeter.x(), targeter.y(), range); } @@ -85,18 +98,17 @@ public class Units{ } /** Returns the neareset damaged tile. */ - public static Tilec findDamagedTile(Team team, float x, float y){ - Tile tile = Geometry.findClosest(x, y, indexer.getDamaged(team)); - return tile == null ? null : tile.entity; + public static Building findDamagedTile(Team team, float x, float y){ + return Geometry.findClosest(x, y, indexer.getDamaged(team)); } /** Returns the neareset ally tile in a range. */ - public static Tilec findAllyTile(Team team, float x, float y, float range, Boolf pred){ + public static Building findAllyTile(Team team, float x, float y, float range, Boolf pred){ return indexer.findTile(team, x, y, range, pred); } /** Returns the neareset enemy tile in a range. */ - public static Tilec findEnemyTile(Team team, float x, float y, float range, Boolf pred){ + public static Building findEnemyTile(Team team, float x, float y, float range, Boolf pred){ if(team == Team.derelict) return null; return indexer.findEnemyTile(team, x, y, range, pred); @@ -104,19 +116,19 @@ public class Units{ /** Returns the closest target enemy. First, units are checked, then tile entities. */ public static Teamc closestTarget(Team team, float x, float y, float range){ - return closestTarget(team, x, y, range, Unitc::isValid); + return closestTarget(team, x, y, range, Unit::isValid); } /** Returns the closest target enemy. First, units are checked, then tile entities. */ - public static Teamc closestTarget(Team team, float x, float y, float range, Boolf unitPred){ + public static Teamc closestTarget(Team team, float x, float y, float range, Boolf unitPred){ return closestTarget(team, x, y, range, unitPred, t -> true); } /** Returns the closest target enemy. First, units are checked, then tile entities. */ - public static Teamc closestTarget(Team team, float x, float y, float range, Boolf unitPred, Boolf tilePred){ + public static Teamc closestTarget(Team team, float x, float y, float range, Boolf unitPred, Boolf tilePred){ if(team == Team.derelict) return null; - Unitc unit = closestEnemy(team, x, y, range, unitPred); + Unit unit = closestEnemy(team, x, y, range, unitPred); if(unit != null){ return unit; }else{ @@ -125,7 +137,7 @@ public class Units{ } /** Returns the closest enemy of this team. Filter by predicate. */ - public static Unitc closestEnemy(Team team, float x, float y, float range, Boolf predicate){ + public static Unit closestEnemy(Team team, float x, float y, float range, Boolf predicate){ if(team == Team.derelict) return null; result = null; @@ -145,11 +157,11 @@ public class Units{ } /** Returns the closest ally of this team. Filter by predicate. No range. */ - public static Unitc closest(Team team, float x, float y, Boolf predicate){ + public static Unit closest(Team team, float x, float y, Boolf predicate){ result = null; cdist = 0f; - for(Unitc e : Groups.unit){ + for(Unit e : Groups.unit){ if(!predicate.get(e) || e.team() != team) continue; float dist = e.dst2(x, y); @@ -163,7 +175,7 @@ public class Units{ } /** Returns the closest ally of this team. Filter by predicate. */ - public static Unitc closest(Team team, float x, float y, float range, Boolf predicate){ + public static Unit closest(Team team, float x, float y, float range, Boolf predicate){ result = null; cdist = 0f; @@ -182,7 +194,7 @@ public class Units{ /** Returns the closest ally of this team. Filter by predicate. * Unlike the closest() function, this only guarantees that unit hitboxes overlap the range. */ - public static Unitc closestOverlap(Team team, float x, float y, float range, Boolf predicate){ + public static Unit closestOverlap(Team team, float x, float y, float range, Boolf predicate){ result = null; cdist = 0f; @@ -200,12 +212,12 @@ public class Units{ } /** Iterates over all units in a rectangle. */ - public static void nearby(Team team, float x, float y, float width, float height, Cons cons){ + public static void nearby(Team team, float x, float y, float width, float height, Cons cons){ teamIndex.tree(team).intersect(x, y, width, height, cons); } /** Iterates over all units in a circle around this position. */ - public static void nearby(Team team, float x, float y, float radius, Cons cons){ + public static void nearby(Team team, float x, float y, float radius, Cons cons){ nearby(team, x - radius, y - radius, radius*2f, radius*2f, unit -> { if(unit.within(x, y, radius)){ cons.get(unit); @@ -214,24 +226,24 @@ public class Units{ } /** Iterates over all units in a rectangle. */ - public static void nearby(float x, float y, float width, float height, Cons cons){ + public static void nearby(float x, float y, float width, float height, Cons cons){ Groups.unit.intersect(x, y, width, height, cons); } /** Iterates over all units in a rectangle. */ - public static void nearby(Rect rect, Cons cons){ + public static void nearby(Rect rect, Cons cons){ nearby(rect.x, rect.y, rect.width, rect.height, cons); } /** Iterates over all units that are enemies of this team. */ - public static void nearbyEnemies(Team team, float x, float y, float width, float height, Cons cons){ + public static void nearbyEnemies(Team team, float x, float y, float width, float height, Cons cons){ for(Team enemy : state.teams.enemiesOf(team)){ nearby(enemy, x, y, width, height, cons); } } /** Iterates over all units that are enemies of this team. */ - public static void nearbyEnemies(Team team, Rect rect, Cons cons){ + public static void nearbyEnemies(Team team, Rect rect, Cons cons){ nearbyEnemies(team, rect.x, rect.y, rect.width, rect.height, cons); } diff --git a/core/src/mindustry/entities/abilities/Ability.java b/core/src/mindustry/entities/abilities/Ability.java new file mode 100644 index 0000000000..d8aed57239 --- /dev/null +++ b/core/src/mindustry/entities/abilities/Ability.java @@ -0,0 +1,8 @@ +package mindustry.entities.abilities; + +import mindustry.gen.*; + +public interface Ability{ + default void update(Unit unit){} + default void draw(Unit unit){} +} diff --git a/core/src/mindustry/entities/abilities/ForceFieldAbility.java b/core/src/mindustry/entities/abilities/ForceFieldAbility.java new file mode 100644 index 0000000000..57841d6886 --- /dev/null +++ b/core/src/mindustry/entities/abilities/ForceFieldAbility.java @@ -0,0 +1,82 @@ +package mindustry.entities.abilities; + +import arc.func.*; +import arc.graphics.*; +import arc.graphics.g2d.*; +import arc.math.*; +import arc.math.geom.*; +import arc.util.*; +import mindustry.content.*; +import mindustry.gen.*; +import mindustry.graphics.*; + +public class ForceFieldAbility implements Ability{ + /** Shield radius. */ + public float radius = 60f; + /** Shield regen speed in damage/tick. */ + public float regen = 0.1f; + /** Maximum shield. */ + public float max = 200f; + /** Cooldown after the shield is broken, in ticks. */ + public float cooldown = 60f * 5; + + private float realRad; + private Unit paramUnit; + private final Cons shieldConsumer = trait -> { + if(trait.team() != paramUnit.team && Intersector.isInsideHexagon(paramUnit.x, paramUnit.y, realRad * 2f, trait.x(), trait.y()) && paramUnit.shield > 0){ + trait.absorb(); + Fx.absorb.at(trait); + + //break shield + if(paramUnit.shield <= trait.damage()){ + paramUnit.shield -= cooldown * regen; + Fx.shieldBreak.at(paramUnit.x, paramUnit.y, radius, paramUnit.team.color); + } + + paramUnit.shield -= trait.damage(); + paramUnit.shieldAlpha = 1f; + } + }; + + public ForceFieldAbility(float radius, float regen, float max, float cooldown){ + this.radius = radius; + this.regen = regen; + this.max = max; + this.cooldown = cooldown; + } + + ForceFieldAbility(){} + + @Override + public void update(Unit unit){ + if(unit.shield < max){ + unit.shield += Time.delta() * regen; + } + + if(unit.shield > 0){ + unit.timer2 = Mathf.lerpDelta(unit.timer2, 1f, 0.06f); + paramUnit = unit; + checkRadius(unit); + + Groups.bullet.intersect(unit.x - realRad, unit.y - realRad, realRad * 2f, realRad * 2f, shieldConsumer); + }else{ + unit.timer2 = 0f; + } + } + + @Override + public void draw(Unit unit){ + checkRadius(unit); + + if(unit.shield > 0){ + Draw.z(Layer.shields); + Draw.color(unit.team.color, Color.white, Mathf.clamp(unit.shieldAlpha)); + Fill.poly(unit.x, unit.y, 6, realRad); + } + } + + private void checkRadius(Unit unit){ + //timer2 is used to store radius scale as an effect + realRad = unit.timer2 * radius; + } +} diff --git a/core/src/mindustry/entities/abilities/HealFieldAbility.java b/core/src/mindustry/entities/abilities/HealFieldAbility.java new file mode 100644 index 0000000000..df3903ffa5 --- /dev/null +++ b/core/src/mindustry/entities/abilities/HealFieldAbility.java @@ -0,0 +1,45 @@ +package mindustry.entities.abilities; + +import arc.util.*; +import mindustry.content.*; +import mindustry.entities.*; +import mindustry.gen.*; + +public class HealFieldAbility implements Ability{ + public float amount = 1, reload = 100, range = 60; + public Effect healEffect = Fx.heal; + public Effect activeEffect = Fx.healWave; + + private boolean wasHealed = false; + + HealFieldAbility(){} + + public HealFieldAbility(float amount, float reload, float range){ + this.amount = amount; + this.reload = reload; + this.range = range; + } + + @Override + public void update(Unit unit){ + unit.timer1 += Time.delta(); + + if(unit.timer1 >= reload){ + wasHealed = false; + + Units.nearby(unit.team, unit.x, unit.y, range, other -> { + if(other.damaged()){ + healEffect.at(unit); + wasHealed = true; + } + other.heal(amount); + }); + + if(wasHealed){ + activeEffect.at(unit); + } + + unit.timer1 = 0f; + } + } +} diff --git a/core/src/mindustry/entities/abilities/ShieldFieldAbility.java b/core/src/mindustry/entities/abilities/ShieldFieldAbility.java new file mode 100644 index 0000000000..15f9fc9147 --- /dev/null +++ b/core/src/mindustry/entities/abilities/ShieldFieldAbility.java @@ -0,0 +1,47 @@ +package mindustry.entities.abilities; + +import arc.util.*; +import mindustry.content.*; +import mindustry.entities.*; +import mindustry.gen.*; + +public class ShieldFieldAbility implements Ability{ + public float amount = 1, max = 100f, reload = 100, range = 60; + public Effect applyEffect = Fx.shieldApply; + public Effect activeEffect = Fx.shieldWave; + + private boolean applied = false; + + ShieldFieldAbility(){} + + public ShieldFieldAbility(float amount, float max, float reload, float range){ + this.amount = amount; + this.max = max; + this.reload = reload; + this.range = range; + } + + @Override + public void update(Unit unit){ + unit.timer1 += Time.delta(); + + if(unit.timer1 >= reload){ + applied = false; + + Units.nearby(unit.team, unit.x, unit.y, range, other -> { + if(other.shield < max){ + other.shield = Math.max(other.shield + amount, max); + other.shieldAlpha = 1f; //TODO may not be necessary + applyEffect.at(unit); + applied = true; + } + }); + + if(applied){ + activeEffect.at(unit); + } + + unit.timer1 = 0f; + } + } +} diff --git a/core/src/mindustry/entities/abilities/StatusFieldAbility.java b/core/src/mindustry/entities/abilities/StatusFieldAbility.java new file mode 100644 index 0000000000..1993e29120 --- /dev/null +++ b/core/src/mindustry/entities/abilities/StatusFieldAbility.java @@ -0,0 +1,40 @@ +package mindustry.entities.abilities; + +import arc.util.ArcAnnotate.*; +import arc.util.*; +import mindustry.content.*; +import mindustry.entities.*; +import mindustry.gen.*; +import mindustry.type.*; + +public class StatusFieldAbility implements Ability{ + public @NonNull StatusEffect effect; + public float duration = 60, reload = 100, range = 20; + public Effect applyEffect = Fx.heal; + public Effect activeEffect = Fx.healWave; + + StatusFieldAbility(){} + + public StatusFieldAbility(@NonNull StatusEffect effect, float duration, float reload, float range){ + this.duration = duration; + this.reload = reload; + this.range = range; + this.effect = effect; + } + + @Override + public void update(Unit unit){ + unit.timer2 += Time.delta(); + + if(unit.timer2 >= reload){ + + Units.nearby(unit.team, unit.x, unit.y, range, other -> { + other.apply(effect, duration); + }); + + activeEffect.at(unit); + + unit.timer2 = 0f; + } + } +} diff --git a/core/src/mindustry/entities/bullet/ArtilleryBulletType.java b/core/src/mindustry/entities/bullet/ArtilleryBulletType.java index c000ed470a..dfcab76e8a 100644 --- a/core/src/mindustry/entities/bullet/ArtilleryBulletType.java +++ b/core/src/mindustry/entities/bullet/ArtilleryBulletType.java @@ -2,12 +2,10 @@ package mindustry.entities.bullet; import arc.graphics.g2d.*; import mindustry.content.*; -import mindustry.entities.*; import mindustry.gen.*; //TODO scale velocity depending on fslope() public class ArtilleryBulletType extends BasicBulletType{ - protected Effect trailEffect = Fx.artilleryTrail; public ArtilleryBulletType(float speed, float damage, String bulletSprite){ super(speed, damage, bulletSprite); @@ -17,6 +15,7 @@ public class ArtilleryBulletType extends BasicBulletType{ scaleVelocity = true; hitShake = 1f; hitSound = Sounds.explosion; + trailEffect = Fx.artilleryTrail; } public ArtilleryBulletType(){ @@ -24,25 +23,25 @@ public class ArtilleryBulletType extends BasicBulletType{ } @Override - public void update(Bulletc b){ + public void update(Bullet b){ super.update(b); if(b.timer(0, 3 + b.fslope() * 2f)){ - trailEffect.at(b.x(), b.y(), b.fslope() * 4f, backColor); + trailEffect.at(b.x, b.y, b.fslope() * 4f, backColor); } } @Override - public void draw(Bulletc b){ + public void draw(Bullet b){ float baseScale = 0.7f; float scale = (baseScale + b.fslope() * (1f - baseScale)); float height = this.height * ((1f - shrinkY) + shrinkY * b.fout()); Draw.color(backColor); - Draw.rect(backRegion, b.x(), b.y(), width * scale, height * scale, b.rotation() - 90); + Draw.rect(backRegion, b.x, b.y, width * scale, height * scale, b.rotation() - 90); Draw.color(frontColor); - Draw.rect(frontRegion, b.x(), b.y(), width * scale, height * scale, b.rotation() - 90); + Draw.rect(frontRegion, b.x, b.y, width * scale, height * scale, b.rotation() - 90); Draw.color(); } } diff --git a/core/src/mindustry/entities/bullet/BasicBulletType.java b/core/src/mindustry/entities/bullet/BasicBulletType.java index becfc69ec8..96b3bfc3bc 100644 --- a/core/src/mindustry/entities/bullet/BasicBulletType.java +++ b/core/src/mindustry/entities/bullet/BasicBulletType.java @@ -39,14 +39,14 @@ public class BasicBulletType extends BulletType{ } @Override - public void draw(Bulletc b){ + public void draw(Bullet b){ float height = this.height * ((1f - shrinkY) + shrinkY * b.fout()); float width = this.width * ((1f - shrinkX) + shrinkX * b.fout()); Draw.color(backColor); - Draw.rect(backRegion, b.x(), b.y(), width, height, b.rotation() - 90); + Draw.rect(backRegion, b.x, b.y, width, height, b.rotation() - 90); Draw.color(frontColor); - Draw.rect(frontRegion, b.x(), b.y(), width, height, b.rotation() - 90); + Draw.rect(frontRegion, b.x, b.y, width, height, b.rotation() - 90); Draw.color(); } } diff --git a/core/src/mindustry/entities/bullet/BulletType.java b/core/src/mindustry/entities/bullet/BulletType.java index ea9babae9c..460aa9608c 100644 --- a/core/src/mindustry/entities/bullet/BulletType.java +++ b/core/src/mindustry/entities/bullet/BulletType.java @@ -15,7 +15,7 @@ import mindustry.graphics.*; import mindustry.type.*; public abstract class BulletType extends Content{ - public float lifetime; + public float lifetime = 40f; public float speed; public float damage; public float hitSize = 4; @@ -75,6 +75,11 @@ public abstract class BulletType extends Content{ public BulletType fragBullet = null; public Color hitColor = Color.white; + public Color trailColor = Pal.missileYellowBack; + public float trailChance = -0.0001f; + public Effect trailEffect = Fx.missileTrail; + public float trailParam = 2f; + /** Use a negative value to disable splash damage. */ public float splashDamageRadius = -1f; @@ -100,29 +105,32 @@ public abstract class BulletType extends Content{ public BulletType(float speed, float damage){ this.speed = speed; this.damage = damage; - lifetime = 40f; hitEffect = Fx.hitBulletSmall; despawnEffect = Fx.hitBulletSmall; } + public BulletType(){ + this(1f, 1f); + } + /** Returns maximum distance the bullet this bullet type has can travel. */ public float range(){ return speed * lifetime * (1f - drag); } - public boolean collides(Bulletc bullet, Tilec tile){ + public boolean collides(Bullet bullet, Building tile){ return true; } - public void hitTile(Bulletc b, Tilec tile){ + public void hitTile(Bullet b, Building tile){ hit(b); } - public void hit(Bulletc b){ - hit(b, b.getX(), b.getY()); + public void hit(Bullet b){ + hit(b, b.x, b.y); } - public void hit(Bulletc b, float x, float y){ + public void hit(Bullet b, float x, float y){ hitEffect.at(x, y, b.rotation(), hitColor); hitSound.at(b); @@ -141,20 +149,20 @@ public abstract class BulletType extends Content{ } if(splashDamageRadius > 0){ - Damage.damage(b.team(), x, y, splashDamageRadius, splashDamage * b.damageMultiplier(), collidesAir, collidesGround); + Damage.damage(b.team, x, y, splashDamageRadius, splashDamage * b.damageMultiplier(), collidesAir, collidesGround); if(status != StatusEffects.none){ - Damage.status(b.team(), x, y, splashDamageRadius, status, statusDuration, collidesAir, collidesGround); + Damage.status(b.team, x, y, splashDamageRadius, status, statusDuration, collidesAir, collidesGround); } } for(int i = 0; i < lightning; i++){ - Lightning.create(b.team(), Pal.surge, lightningDamage < 0 ? damage : lightningDamage, b.getX(), b.getY(), Mathf.random(360f), lightningLength); + Lightning.create(b, Pal.surge, lightningDamage < 0 ? damage : lightningDamage, b.x, b.y, Mathf.random(360f), lightningLength); } } - public void despawned(Bulletc b){ - despawnEffect.at(b.getX(), b.getY(), b.rotation()); + public void despawned(Bullet b){ + despawnEffect.at(b.x, b.y, b.rotation(), hitColor); hitSound.at(b); if(fragBullet != null || splashDamageRadius > 0 || lightning > 0){ @@ -162,14 +170,14 @@ public abstract class BulletType extends Content{ } } - public void draw(Bulletc b){ + public void draw(Bullet b){ } - public void drawLight(Bulletc b){ - Drawf.light(b.team(), b, lightRadius, lightColor, lightOpacity); + public void drawLight(Bullet b){ + Drawf.light(b.team, b, lightRadius, lightColor, lightOpacity); } - public void init(Bulletc b){ + public void init(Bullet b){ if(killShooter && b.owner() instanceof Healthc){ ((Healthc)b.owner()).kill(); } @@ -179,16 +187,22 @@ public abstract class BulletType extends Content{ } } - public void update(Bulletc b){ + public void update(Bullet b){ if(homingPower > 0.0001f){ - Teamc target = Units.closestTarget(b.team(), b.getX(), b.getY(), homingRange, e -> (e.isGrounded() && collidesGround) || (e.isFlying() && collidesAir), t -> collidesGround); + Teamc target = Units.closestTarget(b.team, b.x, b.y, homingRange, e -> (e.isGrounded() && collidesGround) || (e.isFlying() && collidesAir), t -> collidesGround); if(target != null){ - b.vel().setAngle(Mathf.slerpDelta(b.rotation(), b.angleTo(target), homingPower)); + b.vel.setAngle(Mathf.slerpDelta(b.rotation(), b.angleTo(target), homingPower)); } } if(weaveMag > 0){ - b.vel().rotate(Mathf.sin(Time.time() + b.id() * 3, weaveScale, weaveMag) * Time.delta()); + b.vel.rotate(Mathf.sin(Mathf.randomSeed(b.id, 10f) + b.time, weaveScale, weaveMag) * Time.delta()); + } + + if(trailChance > 0){ + if(Mathf.chanceDelta(trailChance)){ + trailEffect.at(b.x, b.y, trailParam, trailColor); + } } } @@ -197,45 +211,45 @@ public abstract class BulletType extends Content{ return ContentType.bullet; } - public Bulletc create(Teamc owner, float x, float y, float angle){ + public Bullet create(Teamc owner, float x, float y, float angle){ return create(owner, owner.team(), x, y, angle); } - public Bulletc create(Entityc owner, Team team, float x, float y, float angle){ + public Bullet create(Entityc owner, Team team, float x, float y, float angle){ return create(owner, team, x, y, angle, 1f); } - public Bulletc create(Entityc owner, Team team, float x, float y, float angle, float velocityScl){ + public Bullet create(Entityc owner, Team team, float x, float y, float angle, float velocityScl){ return create(owner, team, x, y, angle, -1, velocityScl, 1f, null); } - public Bulletc create(Entityc owner, Team team, float x, float y, float angle, float velocityScl, float lifetimeScl){ + public Bullet create(Entityc owner, Team team, float x, float y, float angle, float velocityScl, float lifetimeScl){ return create(owner, team, x, y, angle, -1, velocityScl, lifetimeScl, null); } - public Bulletc create(Bulletc parent, float x, float y, float angle){ - return create(parent.owner(), parent.team(), x, y, angle); + public Bullet create(Bullet parent, float x, float y, float angle){ + return create(parent.owner(), parent.team, x, y, angle); } - public Bulletc create(Bulletc parent, float x, float y, float angle, float velocityScl){ - return create(parent.owner(), parent.team(), x, y, angle, velocityScl); + public Bullet create(Bullet parent, float x, float y, float angle, float velocityScl){ + return create(parent.owner(), parent.team, x, y, angle, velocityScl); } - public Bulletc create(@Nullable Entityc owner, Team team, float x, float y, float angle, float damage, float velocityScl, float lifetimeScl, Object data){ - Bulletc bullet = BulletEntity.create(); - bullet.type(this); - bullet.owner(owner); - bullet.team(team); - bullet.vel().trns(angle, speed * velocityScl); - bullet.set(x - bullet.vel().x * Time.delta(), y - bullet.vel().y * Time.delta()); - bullet.lifetime(lifetime * lifetimeScl); - bullet.data(data); - bullet.drag(drag); - bullet.hitSize(hitSize); - bullet.damage(damage < 0 ? this.damage : damage); + public Bullet create(@Nullable Entityc owner, Team team, float x, float y, float angle, float damage, float velocityScl, float lifetimeScl, Object data){ + Bullet bullet = Bullet.create(); + bullet.type = this; + bullet.owner = owner; + bullet.team = team; + bullet.vel.trns(angle, speed * velocityScl); + bullet.set(x - bullet.vel.x * Time.delta(), y - bullet.vel.y * Time.delta()); + bullet.lifetime = lifetime * lifetimeScl; + bullet.data = data; + bullet.drag = drag; + bullet.hitSize = hitSize; + bullet.damage = damage < 0 ? this.damage : damage; bullet.add(); - if(keepVelocity && owner instanceof Hitboxc) bullet.vel().add(((Hitboxc)owner).deltaX(), ((Hitboxc)owner).deltaY()); + if(keepVelocity && owner instanceof Hitboxc) bullet.vel.add(((Hitboxc)owner).deltaX(), ((Hitboxc)owner).deltaY()); return bullet; } diff --git a/core/src/mindustry/entities/bullet/ContinuousLaserBulletType.java b/core/src/mindustry/entities/bullet/ContinuousLaserBulletType.java index ea77877b76..ef40d9b95b 100644 --- a/core/src/mindustry/entities/bullet/ContinuousLaserBulletType.java +++ b/core/src/mindustry/entities/bullet/ContinuousLaserBulletType.java @@ -43,12 +43,12 @@ public class ContinuousLaserBulletType extends BulletType{ } @Override - public void update(Bulletc b){ + public void update(Bullet b){ //TODO possible laser absorption from blocks //damage every 5 ticks if(b.timer(1, 5f)){ - Damage.collideLine(b, b.team(), hitEffect, b.x(), b.y(), b.rotation(), length, true); + Damage.collideLine(b, b.team, hitEffect, b.x, b.y, b.rotation(), length, true); } if(shake > 0){ @@ -57,27 +57,27 @@ public class ContinuousLaserBulletType extends BulletType{ } @Override - public void draw(Bulletc b){ + public void draw(Bullet b){ float baseLen = length * b.fout(); - Lines.lineAngle(b.x(), b.y(), b.rotation(), baseLen); + Lines.lineAngle(b.x, b.y, b.rotation(), baseLen); for(int s = 0; s < colors.length; s++){ Draw.color(Tmp.c1.set(colors[s]).mul(1f + Mathf.absin(Time.time(), 1f, 0.1f))); for(int i = 0; i < tscales.length; i++){ Tmp.v1.trns(b.rotation() + 180f, (lenscales[i] - 1f) * 35f); Lines.stroke((9f + Mathf.absin(Time.time(), 0.8f, 1.5f)) * b.fout() * strokes[s] * tscales[i]); - Lines.lineAngle(b.x() + Tmp.v1.x, b.y() + Tmp.v1.y, b.rotation(), baseLen * lenscales[i], CapStyle.none); + Lines.lineAngle(b.x + Tmp.v1.x, b.y + Tmp.v1.y, b.rotation(), baseLen * lenscales[i], CapStyle.none); } } Tmp.v1.trns(b.rotation(), baseLen * 1.1f); - Drawf.light(b.team(), b.x(), b.y(), b.x() + Tmp.v1.x, b.y() + Tmp.v1.y, 40, Color.orange, 0.7f); + Drawf.light(b.team, b.x, b.y, b.x + Tmp.v1.x, b.y + Tmp.v1.y, 40, Color.orange, 0.7f); Draw.reset(); } @Override - public void drawLight(Bulletc b){ + public void drawLight(Bullet b){ //no light drawn here } diff --git a/core/src/mindustry/entities/bullet/FlakBulletType.java b/core/src/mindustry/entities/bullet/FlakBulletType.java index 689e185d7b..ad5f8be7fa 100644 --- a/core/src/mindustry/entities/bullet/FlakBulletType.java +++ b/core/src/mindustry/entities/bullet/FlakBulletType.java @@ -23,13 +23,13 @@ public class FlakBulletType extends BasicBulletType{ } @Override - public void update(Bulletc b){ + public void update(Bullet b){ super.update(b); if(b.data() instanceof Integer) return; if(b.timer(2, 6)){ - Units.nearbyEnemies(b.team(), Tmp.r1.setSize(explodeRange * 2f).setCenter(b.x(), b.y()), unit -> { - if(b.data() instanceof Float || (unit.isFlying() && !collidesAir) || (unit.isGrounded() && !collidesGround)) return; + Units.nearbyEnemies(b.team, Tmp.r1.setSize(explodeRange * 2f).setCenter(b.x, b.y), unit -> { + if(b.data() instanceof Float || !unit.checkTarget(collidesAir, collidesGround)) return; if(unit.dst(b) < explodeRange){ b.data(0); diff --git a/core/src/mindustry/entities/bullet/HealBulletType.java b/core/src/mindustry/entities/bullet/HealBulletType.java index a9c683299d..af66a4c931 100644 --- a/core/src/mindustry/entities/bullet/HealBulletType.java +++ b/core/src/mindustry/entities/bullet/HealBulletType.java @@ -9,7 +9,7 @@ import mindustry.world.blocks.*; public class HealBulletType extends BulletType{ protected float healPercent = 3f; - protected float bulletHeight = 7f, bulletWidth = 2f; + protected float height = 7f, width = 2f; protected Color backColor = Pal.heal, frontColor = Color.white; public HealBulletType(float speed, float damage){ @@ -28,26 +28,26 @@ public class HealBulletType extends BulletType{ } @Override - public boolean collides(Bulletc b, Tilec tile){ - return tile.team() != b.team() || tile.healthf() < 1f; + public boolean collides(Bullet b, Building tile){ + return tile.team() != b.team || tile.healthf() < 1f; } @Override - public void draw(Bulletc b){ + public void draw(Bullet b){ Draw.color(backColor); - Lines.stroke(bulletWidth); - Lines.lineAngleCenter(b.x(), b.y(), b.rotation(), bulletHeight); + Lines.stroke(width); + Lines.lineAngleCenter(b.x, b.y, b.rotation(), height); Draw.color(frontColor); - Lines.lineAngleCenter(b.x(), b.y(), b.rotation(), bulletHeight / 2f); + Lines.lineAngleCenter(b.x, b.y, b.rotation(), height / 2f); Draw.reset(); } @Override - public void hitTile(Bulletc b, Tilec tile){ + public void hitTile(Bullet b, Building tile){ super.hit(b); - if(tile.team() == b.team() && !(tile.block() instanceof BuildBlock)){ - Fx.healBlockFull.at(tile.x(), tile.y(), tile.block().size, Pal.heal); + if(tile.team() == b.team && !(tile.block() instanceof BuildBlock)){ + Fx.healBlockFull.at(tile.x, tile.y, tile.block().size, Pal.heal); tile.heal(healPercent / 100f * tile.maxHealth()); } } diff --git a/core/src/mindustry/entities/bullet/LaserBulletType.java b/core/src/mindustry/entities/bullet/LaserBulletType.java index c9a3977f77..571a78826d 100644 --- a/core/src/mindustry/entities/bullet/LaserBulletType.java +++ b/core/src/mindustry/entities/bullet/LaserBulletType.java @@ -48,24 +48,24 @@ public class LaserBulletType extends BulletType{ } @Override - public void init(Bulletc b){ + public void init(Bullet b){ Tmp.v1.trns(b.rotation(), length); furthest = null; - world.raycast(b.tileX(), b.tileY(), world.toTile(b.x() + Tmp.v1.x), world.toTile(b.y() + Tmp.v1.y), - (x, y) -> (furthest = world.tile(x, y)) != null && furthest.team() != b.team() && furthest.block().absorbLasers); + world.raycast(b.tileX(), b.tileY(), world.toTile(b.x + Tmp.v1.x), world.toTile(b.y + Tmp.v1.y), + (x, y) -> (furthest = world.tile(x, y)) != null && furthest.team() != b.team && furthest.block().absorbLasers); float resultLength = furthest != null ? Math.max(6f, b.dst(furthest.worldx(), furthest.worldy())) : length; - Damage.collideLine(b, b.team(), hitEffect, b.x(), b.y(), b.rotation(), resultLength); + Damage.collideLine(b, b.team, hitEffect, b.x, b.y, b.rotation(), resultLength); if(furthest != null) b.data(resultLength); - laserEffect.at(b.x(), b.y(), b.rotation(), resultLength * 0.75f); + laserEffect.at(b.x, b.y, b.rotation(), resultLength * 0.75f); } @Override - public void draw(Bulletc b){ + public void draw(Bullet b){ float realLength = b.data() == null ? length : (Float)b.data(); float f = Mathf.curve(b.fin(), 0f, 0.2f); @@ -73,18 +73,18 @@ public class LaserBulletType extends BulletType{ float cwidth = width; float compound = 1f; - Lines.lineAngle(b.x(), b.y(), b.rotation(), baseLen); + Lines.lineAngle(b.x, b.y, b.rotation(), baseLen); Lines.precise(true); for(Color color : colors){ Draw.color(color); Lines.stroke((cwidth *= lengthFalloff) * b.fout()); - Lines.lineAngle(b.x(), b.y(), b.rotation(), baseLen, CapStyle.none); + Lines.lineAngle(b.x, b.y, b.rotation(), baseLen, CapStyle.none); Tmp.v1.trns(b.rotation(), baseLen); - Drawf.tri(b.x() + Tmp.v1.x, b.y() + Tmp.v1.y, Lines.getStroke() * 1.22f, cwidth * 2f + width / 2f, b.rotation()); + Drawf.tri(b.x + Tmp.v1.x, b.y + Tmp.v1.y, Lines.getStroke() * 1.22f, cwidth * 2f + width / 2f, b.rotation()); - Fill.circle(b.x(), b.y(), 1f * cwidth * b.fout()); + Fill.circle(b.x, b.y, 1f * cwidth * b.fout()); for(int i : Mathf.signs){ - Drawf.tri(b.x(), b.y(), sideWidth * b.fout() * cwidth, sideLength * compound, b.rotation() + sideAngle * i); + Drawf.tri(b.x, b.y, sideWidth * b.fout() * cwidth, sideLength * compound, b.rotation() + sideAngle * i); } compound *= lengthFalloff; @@ -93,11 +93,11 @@ public class LaserBulletType extends BulletType{ Draw.reset(); Tmp.v1.trns(b.rotation(), baseLen * 1.1f); - Drawf.light(b.team(), b.x(), b.y(), b.x() + Tmp.v1.x, b.y() + Tmp.v1.y, width * 1.4f * b.fout(), colors[0], 0.6f); + Drawf.light(b.team, b.x, b.y, b.x + Tmp.v1.x, b.y + Tmp.v1.y, width * 1.4f * b.fout(), colors[0], 0.6f); } @Override - public void drawLight(Bulletc b){ + public void drawLight(Bullet b){ //no light drawn here } } diff --git a/core/src/mindustry/entities/bullet/LightningBulletType.java b/core/src/mindustry/entities/bullet/LightningBulletType.java index 4ca0f1d2c2..dbfbcc0301 100644 --- a/core/src/mindustry/entities/bullet/LightningBulletType.java +++ b/core/src/mindustry/entities/bullet/LightningBulletType.java @@ -1,6 +1,7 @@ package mindustry.entities.bullet; import arc.graphics.*; +import arc.math.*; import mindustry.content.*; import mindustry.entities.*; import mindustry.gen.*; @@ -8,7 +9,7 @@ import mindustry.graphics.*; public class LightningBulletType extends BulletType{ protected Color lightningColor = Pal.lancerLaser; - protected int lightningLength = 25; + protected int lightningLength = 25, lightningLengthRand = 0; public LightningBulletType(){ super(0.0001f, 1f); @@ -22,15 +23,15 @@ public class LightningBulletType extends BulletType{ @Override public float range(){ - return lightningLength * 2.33f; + return (lightningLength + lightningLengthRand/2f) * 6f; } @Override - public void draw(Bulletc b){ + public void draw(Bullet b){ } @Override - public void init(Bulletc b){ - Lightning.create(b.team(), lightningColor, damage, b.x(), b.y(), b.rotation(), lightningLength); + public void init(Bullet b){ + Lightning.create(b, lightningColor, damage, b.x, b.y, b.rotation(), lightningLength + Mathf.random(lightningLengthRand)); } } diff --git a/core/src/mindustry/entities/bullet/LiquidBulletType.java b/core/src/mindustry/entities/bullet/LiquidBulletType.java index 835c8a4d32..155ed32973 100644 --- a/core/src/mindustry/entities/bullet/LiquidBulletType.java +++ b/core/src/mindustry/entities/bullet/LiquidBulletType.java @@ -14,7 +14,7 @@ import static mindustry.Vars.*; public class LiquidBulletType extends BulletType{ public @NonNull Liquid liquid; - public float puddleSize = 5f; + public float puddleSize = 6f; public LiquidBulletType(@Nullable Liquid liquid){ super(3.5f, 0); @@ -44,11 +44,11 @@ public class LiquidBulletType extends BulletType{ } @Override - public void update(Bulletc b){ + public void update(Bullet b){ super.update(b); if(liquid.canExtinguish()){ - Tile tile = world.tileWorld(b.x(), b.y()); + Tile tile = world.tileWorld(b.x, b.y); if(tile != null && Fires.has(tile.x, tile.y)){ Fires.extinguish(tile, 100f); b.remove(); @@ -58,21 +58,22 @@ public class LiquidBulletType extends BulletType{ } @Override - public void draw(Bulletc b){ + public void draw(Bullet b){ Draw.color(liquid.color, Color.white, b.fout() / 100f); - Fill.circle(b.x(), b.y(), 3f); + Fill.circle(b.x, b.y, 3f); } @Override - public void despawned(Bulletc b){ + public void despawned(Bullet b){ super.despawned(b); - hit(b, b.x(), b.y()); + //don't create liquids when the projectile despawns + hitEffect.at(b.x, b.y, liquid.color); } @Override - public void hit(Bulletc b, float hitx, float hity){ + public void hit(Bullet b, float hitx, float hity){ hitEffect.at(hitx, hity, liquid.color); Puddles.deposit(world.tileWorld(hitx, hity), liquid, puddleSize); diff --git a/core/src/mindustry/entities/bullet/MassDriverBolt.java b/core/src/mindustry/entities/bullet/MassDriverBolt.java index 390eff95d3..61c6d4c2bc 100644 --- a/core/src/mindustry/entities/bullet/MassDriverBolt.java +++ b/core/src/mindustry/entities/bullet/MassDriverBolt.java @@ -22,20 +22,20 @@ public class MassDriverBolt extends BulletType{ } @Override - public void draw(Bulletc b){ + public void draw(Bullet b){ float w = 11f, h = 13f; Draw.color(Pal.bulletYellowBack); - Draw.rect("shell-back", b.x(), b.y(), w, h, b.rotation() + 90); + Draw.rect("shell-back", b.x, b.y, w, h, b.rotation() + 90); Draw.color(Pal.bulletYellow); - Draw.rect("shell", b.x(), b.y(), w, h, b.rotation() + 90); + Draw.rect("shell", b.x, b.y, w, h, b.rotation() + 90); Draw.reset(); } @Override - public void update(Bulletc b){ + public void update(Bullet b){ //data MUST be an instance of DriverBulletData if(!(b.data() instanceof DriverBulletData)){ hit(b); @@ -66,7 +66,7 @@ public class MassDriverBolt extends BulletType{ if(Angles.near(angleTo, baseAngle, 2f)){ intersect = true; //snap bullet position back; this is used for low-FPS situations - b.set(data.to.x() + Angles.trnsx(baseAngle, hitDst), data.to.y() + Angles.trnsy(baseAngle, hitDst)); + b.set(data.to.x + Angles.trnsx(baseAngle, hitDst), data.to.y + Angles.trnsy(baseAngle, hitDst)); } } @@ -81,7 +81,7 @@ public class MassDriverBolt extends BulletType{ } @Override - public void despawned(Bulletc b){ + public void despawned(Bullet b){ super.despawned(b); if(!(b.data() instanceof DriverBulletData)) return; @@ -92,13 +92,13 @@ public class MassDriverBolt extends BulletType{ int amountDropped = Mathf.random(0, data.items[i]); if(amountDropped > 0){ float angle = b.rotation() + Mathf.range(100f); - Fx.dropItem.at(b.x(), b.y(), angle, Color.white, content.item(i)); + Fx.dropItem.at(b.x, b.y, angle, Color.white, content.item(i)); } } } @Override - public void hit(Bulletc b, float hitx, float hity){ + public void hit(Bullet b, float hitx, float hity){ super.hit(b, hitx, hity); despawned(b); } diff --git a/core/src/mindustry/entities/bullet/MissileBulletType.java b/core/src/mindustry/entities/bullet/MissileBulletType.java index 1241ad6894..a3670ac3c0 100644 --- a/core/src/mindustry/entities/bullet/MissileBulletType.java +++ b/core/src/mindustry/entities/bullet/MissileBulletType.java @@ -1,32 +1,27 @@ package mindustry.entities.bullet; -import arc.graphics.*; -import arc.math.*; -import mindustry.content.*; import mindustry.gen.*; import mindustry.graphics.*; public class MissileBulletType extends BasicBulletType{ - protected Color trailColor = Pal.missileYellowBack; public MissileBulletType(float speed, float damage, String bulletSprite){ super(speed, damage, bulletSprite); backColor = Pal.missileYellowBack; frontColor = Pal.missileYellow; homingPower = 0.08f; + shrinkY = 0f; + width = 8f; + height = 8f; hitSound = Sounds.explosion; + trailChance = 0.2f; + } + + public MissileBulletType(float speed, float damage){ + this(speed, damage, "missile"); } public MissileBulletType(){ this(1f, 1f, "missile"); } - - @Override - public void update(Bulletc b){ - super.update(b); - - if(Mathf.chanceDelta(0.2)){ - Fx.missileTrail.at(b.x(), b.y(), 2f, trailColor); - } - } } diff --git a/core/src/mindustry/entities/bullet/SapBulletType.java b/core/src/mindustry/entities/bullet/SapBulletType.java new file mode 100644 index 0000000000..6dab6ce13c --- /dev/null +++ b/core/src/mindustry/entities/bullet/SapBulletType.java @@ -0,0 +1,82 @@ +package mindustry.entities.bullet; + +import arc.*; +import arc.graphics.*; +import arc.graphics.g2d.*; +import arc.math.geom.*; +import arc.util.*; +import mindustry.content.*; +import mindustry.entities.*; +import mindustry.gen.*; +import mindustry.graphics.*; + +public class SapBulletType extends BulletType{ + public float length = 100f; + public float sapStrength = 0.5f; + public Color color = Color.white.cpy(); + public float width = 0.4f; + + public SapBulletType(){ + speed = 0.0001f; + despawnEffect = Fx.none; + pierce = true; + hitSize = 0f; + hittable = false; + hitEffect = Fx.hitLiquid; + status = StatusEffects.sapped; + statusDuration = 60f * 3f; + } + + @Override + public void draw(Bullet b){ + if(b.data instanceof Position){ + Position data = (Position)b.data; + Tmp.v1.set(data).lerp(b, b.fin()); + + Draw.color(color); + Drawf.laser(b.team, Core.atlas.find("laser"), Core.atlas.find("laser-end"), + b.x, b.y, Tmp.v1.x, Tmp.v1.y, width * b.fout()); + + Draw.reset(); + + Drawf.light(b.team, b.x, b.y, b.x + Tmp.v1.x, b.y + Tmp.v1.y, 15f * b.fout(), lightColor, 0.6f); + } + } + + @Override + public float range(){ + return length; + } + + @Override + public void init(Bullet b){ + super.init(b); + + Healthc target = Damage.linecast(b, b.x, b.y, b.rotation(), length); + b.data = target; + + if(target != null){ + float result = Math.min(target.health(), damage); + + if(b.owner instanceof Healthc){ + ((Healthc)b.owner).heal(result * sapStrength); + } + } + + if(target instanceof Hitboxc){ + Hitboxc hit = (Hitboxc)target; + + hit.collision(b, hit.x(), hit.y()); + b.collision(hit, hit.x(), hit.y()); + }else if(target instanceof Building){ + Building tile = (Building)target; + + if(tile.collide(b)){ + tile.collision(b); + hit(b, tile.x, tile.y); + } + }else{ + b.data = new Vec2().trns(b.rotation(), length).add(b.x, b.y); + } + } +} diff --git a/core/src/mindustry/entities/bullet/ShrapnelBulletType.java b/core/src/mindustry/entities/bullet/ShrapnelBulletType.java new file mode 100644 index 0000000000..8f26efeaae --- /dev/null +++ b/core/src/mindustry/entities/bullet/ShrapnelBulletType.java @@ -0,0 +1,47 @@ +package mindustry.entities.bullet; + +import arc.graphics.*; +import arc.graphics.g2d.*; +import arc.math.*; +import arc.util.*; +import mindustry.content.*; +import mindustry.entities.*; +import mindustry.gen.*; +import mindustry.graphics.*; + +public class ShrapnelBulletType extends BulletType{ + public float length = 100f; + public float width = 20f; + public Color fromColor = Color.white, toColor = Pal.lancerLaser; + + public int serrations = 7; + public float serrationLenScl = 10f, serrationWidth = 4f, serrationSpacing = 8f, serrationSpaceOffset = 80f; + + public ShrapnelBulletType(){ + speed = 0.01f; + hitEffect = Fx.hitLancer; + shootEffect = smokeEffect = Fx.lightningShoot; + lifetime = 10f; + despawnEffect = Fx.none; + pierce = true; + } + + @Override + public void init(Bullet b){ + Damage.collideLine(b, b.team, hitEffect, b.x, b.y, b.rotation(), length); + } + + @Override + public void draw(Bullet b){ + Draw.color(fromColor, toColor, b.fin()); + for(int i = 0; i < serrations; i++){ + Tmp.v1.trns(b.rotation(), i * serrationSpacing); + float sl = Mathf.clamp(b.fout() - 0.5f) * (serrationSpaceOffset - i * serrationLenScl); + Drawf.tri(b.x + Tmp.v1.x, b.y + Tmp.v1.y, serrationWidth, sl, b.rotation() + 90); + Drawf.tri(b.x + Tmp.v1.x, b.y + Tmp.v1.y, serrationWidth, sl, b.rotation() - 90); + } + Drawf.tri(b.x, b.y, width * b.fout(), (length + 50), b.rotation()); + Drawf.tri(b.x, b.y, width * b.fout(), 10f, b.rotation() + 180f); + Draw.reset(); + } +} diff --git a/core/src/mindustry/entities/comp/BlockUnitComp.java b/core/src/mindustry/entities/comp/BlockUnitComp.java index 3af40d00f8..4ae698db2a 100644 --- a/core/src/mindustry/entities/comp/BlockUnitComp.java +++ b/core/src/mindustry/entities/comp/BlockUnitComp.java @@ -1,18 +1,20 @@ package mindustry.entities.comp; +import arc.graphics.g2d.*; import mindustry.annotations.Annotations.*; import mindustry.game.*; import mindustry.gen.*; +import mindustry.ui.*; -import static mindustry.Vars.tilesize; +import static mindustry.Vars.*; @Component abstract class BlockUnitComp implements Unitc{ @Import Team team; - @ReadOnly transient Tilec tile; + @ReadOnly transient Building tile; - public void tile(Tilec tile){ + public void tile(Building tile){ this.tile = tile; //sets up block stats @@ -30,7 +32,13 @@ abstract class BlockUnitComp implements Unitc{ } @Replace - public void kill(){ + @Override + public TextureRegion icon(){ + return tile.block.icon(Cicon.full); + } + + @Override + public void killed(){ tile.kill(); } diff --git a/core/src/mindustry/entities/comp/BuilderComp.java b/core/src/mindustry/entities/comp/BuilderComp.java index e13d5f12bc..64667334e9 100644 --- a/core/src/mindustry/entities/comp/BuilderComp.java +++ b/core/src/mindustry/entities/comp/BuilderComp.java @@ -28,7 +28,7 @@ abstract class BuilderComp implements Unitc{ @Import float x, y, rotation; - Queue plans = new Queue<>(); + @SyncLocal Queue plans = new Queue<>(); transient boolean building = true; @Override @@ -54,7 +54,7 @@ abstract class BuilderComp implements Unitc{ } } - Tilec core = core(); + Building core = core(); //nothing to build. if(buildPlan() == null) return; @@ -72,19 +72,19 @@ abstract class BuilderComp implements Unitc{ BuildPlan current = buildPlan(); - if(dst(current.tile()) > finalPlaceDst) return; + if(!within(current.tile(), finalPlaceDst)) return; Tile tile = world.tile(current.x, current.y); - if(dst(tile) <= finalPlaceDst){ + if(!within(tile, finalPlaceDst)){ rotation = Mathf.slerpDelta(rotation, angleTo(tile), 0.4f); } if(!(tile.block() instanceof BuildBlock)){ if(!current.initialized && !current.breaking && Build.validPlace(current.block, team(), current.x, current.y, current.rotation)){ - boolean hasAll = !Structs.contains(current.block.requirements, i -> !core.items().has(i.item)); + boolean hasAll = infinite || !Structs.contains(current.block.requirements, i -> core != null && !core.items.has(i.item)); - if(hasAll || infinite){ + if(hasAll){ Build.beginPlace(current.block, team(), current.x, current.y, current.rotation); }else{ current.stuck = true; @@ -100,25 +100,25 @@ abstract class BuilderComp implements Unitc{ return; } - if(tile.entity instanceof BuildEntity && !current.initialized){ + if(tile.build instanceof BuildEntity && !current.initialized){ Core.app.post(() -> Events.fire(new BuildSelectEvent(tile, team(), (Builderc)this, current.breaking))); current.initialized = true; } //if there is no core to build with or no build entity, stop building! - if((core == null && !infinite) || !(tile.entity instanceof BuildEntity)){ + if((core == null && !infinite) || !(tile.build instanceof BuildEntity)){ return; } //otherwise, update it. - BuildEntity entity = tile.ent(); + BuildEntity entity = tile.bc(); if(current.breaking){ - entity.deconstruct(this, core, 1f / entity.buildCost * Time.delta() * type().buildSpeed * state.rules.buildSpeedMultiplier); + entity.deconstruct(base(), core, 1f / entity.buildCost * Time.delta() * type().buildSpeed * state.rules.buildSpeedMultiplier); }else{ - if(entity.construct(this, core, 1f / entity.buildCost * Time.delta() * type().buildSpeed * state.rules.buildSpeedMultiplier, current.hasConfig)){ + if(entity.construct(base(), core, 1f / entity.buildCost * Time.delta() * type().buildSpeed * state.rules.buildSpeedMultiplier, current.hasConfig)){ if(current.hasConfig){ - Call.onTileConfig(null, tile.entity, current.config); + Call.tileConfig(null, tile.build, current.config); } } } @@ -147,11 +147,11 @@ abstract class BuilderComp implements Unitc{ } /** @return whether this request should be skipped, in favor of the next one. */ - boolean shouldSkip(BuildPlan request, @Nullable Tilec core){ + boolean shouldSkip(BuildPlan request, @Nullable Building core){ //requests that you have at least *started* are considered if(state.rules.infiniteResources || team().rules().infiniteResources || request.breaking || core == null) return false; //TODO these are bad criteria - return (request.stuck && !core.items().has(request.block.requirements)) || (Structs.contains(request.block.requirements, i -> !core.items().has(i.item)) && !request.initialized); + return (request.stuck && !core.items.has(request.block.requirements)) || (Structs.contains(request.block.requirements, i -> !core.items.has(i.item)) && !request.initialized); } void removeBuild(int x, int y, boolean breaking){ @@ -190,8 +190,8 @@ abstract class BuilderComp implements Unitc{ plans.remove(replace); } Tile tile = world.tile(place.x, place.y); - if(tile != null && tile.entity instanceof BuildEntity){ - place.progress = tile.ent().progress; + if(tile != null && tile.build instanceof BuildEntity){ + place.progress = tile.bc().progress; } if(tail){ plans.addLast(place); diff --git a/core/src/mindustry/entities/comp/TileComp.java b/core/src/mindustry/entities/comp/BuildingComp.java similarity index 79% rename from core/src/mindustry/entities/comp/TileComp.java rename to core/src/mindustry/entities/comp/BuildingComp.java index 7f3f938c1b..df71b5b800 100644 --- a/core/src/mindustry/entities/comp/TileComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -35,13 +35,13 @@ import mindustry.world.modules.*; import static mindustry.Vars.*; -@EntityDef(value = {Tilec.class}, isFinal = false, genio = false, serialize = false) -@Component -abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTreeObject, Displayable{ +@EntityDef(value = {Buildingc.class}, isFinal = false, genio = false, serialize = false) +@Component(base = true) +abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, QuadTreeObject, Displayable{ //region vars and initialization static final float timeToSleep = 60f * 1; - static final ObjectSet tmpTiles = new ObjectSet<>(); - static final Seq tempTileEnts = new Seq<>(); + static final ObjectSet tmpTiles = new ObjectSet<>(); + static final Seq tempTileEnts = new Seq<>(); static final Seq tempTiles = new Seq<>(); static int sleepingEntities = 0; @@ -50,7 +50,7 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree transient Tile tile; transient Block block; - transient Seq proximity = new Seq<>(8); + transient Seq proximity = new Seq<>(8); transient boolean updateFlow; transient byte dump; @@ -68,7 +68,7 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree private transient boolean initialized; /** Sets this tile entity data to this and adds it if necessary. */ - public Tilec init(Tile tile, Team team, boolean shouldAdd){ + public Building init(Tile tile, Team team, boolean shouldAdd){ if(!initialized){ create(tile.block(), team); } @@ -82,11 +82,11 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree created(); - return this; + return base(); } /** Sets up all the necessary variables, but does not add this entity anywhere. */ - public Tilec create(Block block, Team team){ + public Building create(Block block, Team team){ this.tile = emptyTile; this.block = block; this.team = team; @@ -99,17 +99,17 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree maxHealth(block.health); timer(new Interval(block.timers)); - cons = new ConsumeModule(this); + cons = new ConsumeModule(base()); if(block.hasItems) items = new ItemModule(); if(block.hasLiquids) liquids = new LiquidModule(); if(block.hasPower){ power = new PowerModule(); - power.graph.add(this); + power.graph.add(base()); } initialized = true; - return this; + return base(); } @Override @@ -174,17 +174,17 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree public void configure(Object value){ //save last used config block.lastConfig = value; - Call.onTileConfig(player, this, value); + Call.tileConfig(player, base(), value); } /** Configure from a server. */ public void configureAny(Object value){ - Call.onTileConfig(null, this, value); + Call.tileConfig(null, base(), value); } /** Deselect this tile from configuration. */ public void deselect(){ - if(!headless && control.input.frag.config.getSelectedTile() == this){ + if(!headless && control.input.frag.config.getSelectedTile() == base()){ control.input.frag.config.hideConfig(); } } @@ -200,11 +200,11 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree timeScaleDuration = Math.max(timeScaleDuration, duration); } - public Tilec nearby(int dx, int dy){ + public Building nearby(int dx, int dy){ return world.ent(tile.x + dx, tile.y + dy); } - public Tilec nearby(int rotation){ + public Building nearby(int rotation){ if(rotation == 0) return world.ent(tile.x + 1, tile.y); if(rotation == 1) return world.ent(tile.x, tile.y + 1); if(rotation == 2) return world.ent(tile.x - 1, tile.y); @@ -216,7 +216,7 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree return relativeTo(tile.x, tile.y); } - public byte relativeTo(Tilec tile){ + public byte relativeTo(Building tile){ return relativeTo(tile.tile()); } @@ -229,25 +229,25 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree } /** Multiblock front. */ - public @Nullable Tilec front(){ + public @Nullable Building front(){ int trns = block.size/2 + 1; return nearby(Geometry.d4(rotation()).x * trns, Geometry.d4(rotation()).y * trns); } /** Multiblock back. */ - public @Nullable Tilec back(){ + public @Nullable Building back(){ int trns = block.size/2 + 1; return nearby(Geometry.d4(rotation() + 2).x * trns, Geometry.d4(rotation() + 2).y * trns); } /** Multiblock left. */ - public @Nullable Tilec left(){ + public @Nullable Building left(){ int trns = block.size/2 + 1; return nearby(Geometry.d4(rotation() + 1).x * trns, Geometry.d4(rotation() + 1).y * trns); } /** Multiblock right. */ - public @Nullable Tilec right(){ + public @Nullable Building right(){ int trns = block.size/2 + 1; return nearby(Geometry.d4(rotation() + 3).x * trns, Geometry.d4(rotation() + 3).y * trns); } @@ -323,7 +323,7 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree } } - /** Returns the version of this TileEntity IO code.*/ + /** Returns the version of this Building IO code.*/ public byte version(){ return 0; } @@ -347,7 +347,7 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree /** Returns the amount of items this block can accept. */ public int acceptStack(Item item, int amount, Teamc source){ - if(acceptItem(this, item) && block.hasItems && (source == null || source.team() == team())){ + if(acceptItem(base(), item) && block.hasItems && (source == null || source.team() == team)){ return Math.min(getMaximumAccepted(item) - items.get(item), amount); }else{ return 0; @@ -382,11 +382,11 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree noSleep(); } - public boolean acceptPayload(Tilec source, Payload payload){ + public boolean acceptPayload(Building source, Payload payload){ return false; } - public void handlePayload(Tilec source, Payload payload){ + public void handlePayload(Building source, Payload payload){ } @@ -400,8 +400,8 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree int trns = block.size/2 + 1; Tile next = tile.getNearby(Geometry.d4(rotation()).x * trns, Geometry.d4(rotation()).y * trns); - if(next != null && next.entity != null && next.entity.team() == team() && next.entity.acceptPayload(this, todump)){ - next.entity.handlePayload(this, todump); + if(next != null && next.build != null && next.build.team() == team && next.build.acceptPayload(base(), todump)){ + next.build.handlePayload(base(), todump); return true; } @@ -419,10 +419,10 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree int dump = this.dump; for(int i = 0; i < proximity.size; i++){ - Tilec other = proximity.get((i + dump) % proximity.size); + Building other = proximity.get((i + dump) % proximity.size); - if(other.team() == team() && other.acceptPayload(this, todump)){ - other.handlePayload(this, todump); + if(other.team() == team && other.acceptPayload(base(), todump)){ + other.handlePayload(base(), todump); incrementDump(proximity.size); return true; } @@ -433,19 +433,19 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree return false; } - public void handleItem(Tilec source, Item item){ + public void handleItem(Building source, Item item){ items.add(item, 1); } - public boolean acceptItem(Tilec source, Item item){ + public boolean acceptItem(Building source, Item item){ return block.consumes.itemFilters.get(item.id) && items.get(item) < getMaximumAccepted(item); } - public boolean acceptLiquid(Tilec source, Liquid liquid, float amount){ + public boolean acceptLiquid(Building source, Liquid liquid, float amount){ return block.hasLiquids && liquids.get(liquid) + amount < block.liquidCapacity && block.consumes.liquidfilters.get(liquid.id); } - public void handleLiquid(Tilec source, Liquid liquid, float amount){ + public void handleLiquid(Building source, Liquid liquid, float amount){ liquids.add(liquid, amount); } @@ -454,11 +454,11 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree for(int i = 0; i < proximity.size; i++){ incrementDump(proximity.size); - Tilec other = proximity.get((i + dump) % proximity.size); - other = other.getLiquidDestination(this, liquid); + Building other = proximity.get((i + dump) % proximity.size); + other = other.getLiquidDestination(base(), liquid); - if(other != null && other.team() == team() && other.block().hasLiquids && canDumpLiquid(other, liquid) && other.liquids() != null){ - float ofract = other.liquids().get(liquid) / other.block().liquidCapacity; + if(other != null && other.team == team && other.block.hasLiquids && canDumpLiquid(other, liquid) && other.liquids != null){ + float ofract = other.liquids.get(liquid) / other.block.liquidCapacity; float fract = liquids.get(liquid) / block.liquidCapacity; if(ofract < fract) transferLiquid(other, (fract - ofract) * block.liquidCapacity / 2f, liquid); @@ -467,15 +467,15 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree } - public boolean canDumpLiquid(Tilec to, Liquid liquid){ + public boolean canDumpLiquid(Building to, Liquid liquid){ return true; } - public void transferLiquid(Tilec next, float amount, Liquid liquid){ - float flow = Math.min(next.block().liquidCapacity - next.liquids().get(liquid) - 0.001f, amount); + public void transferLiquid(Building next, float amount, Liquid liquid){ + float flow = Math.min(next.block.liquidCapacity - next.liquids.get(liquid) - 0.001f, amount); - if(next.acceptLiquid(this, liquid, flow)){ - next.handleLiquid(this, liquid, flow); + if(next.acceptLiquid(base(), liquid, flow)){ + next.handleLiquid(base(), liquid, flow); liquids.remove(liquid, flow); } } @@ -485,36 +485,36 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree if(next == null) return 0; - if(next.entity != null){ - return moveLiquid(next.entity, liquid); + if(next.build != null){ + return moveLiquid(next.build, liquid); }else if(leakResistance != 100f && !next.block().solid && !next.block().hasLiquids){ float leakAmount = liquids.get(liquid) / leakResistance; - Puddles.deposit(next, tile(), liquid, leakAmount); + Puddles.deposit(next, tile, liquid, leakAmount); liquids.remove(liquid, leakAmount); } return 0; } - public float moveLiquid(Tilec next, Liquid liquid){ + public float moveLiquid(Building next, Liquid liquid){ if(next == null) return 0; - next = next.getLiquidDestination(this, liquid); + next = next.getLiquidDestination(base(), liquid); - if(next.team() == team() && next.block().hasLiquids && liquids.get(liquid) > 0f){ + if(next.team() == team && next.block.hasLiquids && liquids.get(liquid) > 0f){ - if(next.acceptLiquid(this, liquid, 0f)){ - float ofract = next.liquids().get(liquid) / next.block().liquidCapacity; + if(next.acceptLiquid(base(), liquid, 0f)){ + float ofract = next.liquids().get(liquid) / next.block.liquidCapacity; float fract = liquids.get(liquid) / block.liquidCapacity * block.liquidPressure; float flow = Math.min(Mathf.clamp((fract - ofract) * (1f)) * (block.liquidCapacity), liquids.get(liquid)); - flow = Math.min(flow, next.block().liquidCapacity - next.liquids().get(liquid) - 0.001f); + flow = Math.min(flow, next.block.liquidCapacity - next.liquids().get(liquid) - 0.001f); - if(flow > 0f && ofract <= fract && next.acceptLiquid(this, liquid, flow)){ - next.handleLiquid(this, liquid, flow); + if(flow > 0f && ofract <= fract && next.acceptLiquid(base(), liquid, flow)){ + next.handleLiquid(base(), liquid, flow); liquids.remove(liquid, flow); return flow; }else if(ofract > 0.1f && fract > 0.1f){ //TODO these are incorrect effect positions - float fx = (x() + next.x()) / 2f, fy = (y() + next.y()) / 2f; + float fx = (x + next.x) / 2f, fy = (y + next.y) / 2f; Liquid other = next.liquids().current(); if((other.flammability > 0.3f && liquid.temperature > 0.7f) || (liquid.flammability > 0.3f && other.temperature > 0.7f)){ @@ -535,8 +535,8 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree return 0; } - public Tilec getLiquidDestination(Tilec from, Liquid liquid){ - return this; + public Building getLiquidDestination(Building from, Liquid liquid){ + return base(); } /** Tries to take the payload. Returns null if no payload is present. */ @@ -553,14 +553,14 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree for(int i = 0; i < proximity.size; i++){ incrementDump(proximity.size); - Tilec other = proximity.get((i + dump) % proximity.size); - if(other.team() == team() && other.acceptItem(this, item) && canDump(other, item)){ - other.handleItem(this, item); + Building other = proximity.get((i + dump) % proximity.size); + if(other.team() == team && other.acceptItem(base(), item) && canDump(other, item)){ + other.handleItem(base(), item); return; } } - handleItem(this, item); + handleItem(base(), item); } /** @@ -571,9 +571,9 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree for(int i = 0; i < proximity.size; i++){ incrementDump(proximity.size); - Tilec other = proximity.get((i + dump) % proximity.size); - if(other.team() == team() && other.acceptItem(this, item) && canDump(other, item)){ - other.handleItem(this, item); + Building other = proximity.get((i + dump) % proximity.size); + if(other.team() == team && other.acceptItem(base(), item) && canDump(other, item)){ + other.handleItem(base(), item); return true; } } @@ -598,23 +598,23 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree if(proximity.size == 0) return false; for(int i = 0; i < proximity.size; i++){ - Tilec other = proximity.get((i + dump) % proximity.size); + Building other = proximity.get((i + dump) % proximity.size); if(todump == null){ for(int ii = 0; ii < content.items().size; ii++){ Item item = content.item(ii); - if(other.team() == team() && items.has(item) && other.acceptItem(this, item) && canDump(other, item)){ - other.handleItem(this, item); + if(other.team() == team && items.has(item) && other.acceptItem(base(), item) && canDump(other, item)){ + other.handleItem(base(), item); items.remove(item, 1); incrementDump(proximity.size); return true; } } }else{ - if(other.team() == team() && other.acceptItem(this, todump) && canDump(other, todump)){ - other.handleItem(this, todump); + if(other.team() == team && other.acceptItem(base(), todump) && canDump(other, todump)){ + other.handleItem(base(), todump); items.remove(todump, 1); incrementDump(proximity.size); return true; @@ -632,15 +632,15 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree } /** Used for dumping items. */ - public boolean canDump(Tilec to, Item item){ + public boolean canDump(Building to, Item item){ return true; } /** Try offloading an item to a nearby container in its facing direction. Returns true if success. */ public boolean moveForward(Item item){ - Tilec other = front(); - if(other != null && other.team() == team() && other.acceptItem(this, item)){ - other.handleItem(this, item); + Building other = front(); + if(other != null && other.team() == team && other.acceptItem(base(), item)){ + other.handleItem(base(), item); return true; } return false; @@ -658,9 +658,9 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree public void updatePowerGraph(){ - for(Tilec other : getPowerConnections(tempTileEnts)){ + for(Building other : getPowerConnections(tempTileEnts)){ if(other.power() != null){ - other.power().graph.add(power.graph); + other.power().graph.addGraph(power.graph); } } } @@ -670,22 +670,22 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree return; } - power.graph.remove(this); + power.graph.remove(base()); for(int i = 0; i < power.links.size; i++){ Tile other = world.tile(power.links.get(i)); - if(other != null && other.entity != null && other.entity.power() != null){ - other.entity.power().links.removeValue(pos()); + if(other != null && other.build != null && other.build.power != null){ + other.build.power.links.removeValue(pos()); } } } - public Seq getPowerConnections(Seq out){ + public Seq getPowerConnections(Seq out){ out.clear(); if(power == null) return out; - for(Tilec other : proximity){ + for(Building other : proximity){ if(other != null && other.power() != null - && !(block.consumesPower && other.block().consumesPower && !block.outputsPower && !other.block().outputsPower) + && !(block.consumesPower && other.block.consumesPower && !block.outputsPower && !other.block.outputsPower) && !power.links.contains(other.pos())){ out.add(other); } @@ -693,7 +693,7 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree for(int i = 0; i < power.links.size; i++){ Tile link = world.tile(power.links.get(i)); - if(link != null && link.entity != null && link.entity.power() != null) out.add(link.entity); + if(link != null && link.build != null && link.build.power != null) out.add(link.build); } return out; } @@ -731,7 +731,7 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree int id = pos(); TextureRegion region = Block.cracks[block.size - 1][Mathf.clamp((int)((1f - healthf()) * Block.crackRegions), 0, Block.crackRegions-1)]; Draw.colorl(0.2f, 0.1f + (1f - healthf())* 0.6f); - Draw.rect(region, x(), y(), (id%4)*90); + Draw.rect(region, x, y, (id%4)*90); Draw.color(); } @@ -747,8 +747,8 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree public void drawTeamTop(){ if(block.teamRegion.found()){ - if(block.teamRegions[team.uid] == block.teamRegion) Draw.color(team.color); - Draw.rect(block.teamRegions[team.uid], x, y); + if(block.teamRegions[team.id] == block.teamRegion) Draw.color(team.color); + Draw.rect(block.teamRegions[team.id], x, y); Draw.color(); } } @@ -793,8 +793,9 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree int range = 10; tempTiles.clear(); Geometry.circle(tileX(), tileY(), range, (x, y) -> { - Tilec other = world.ent(x, y); - if(other != null && other.block() instanceof PowerNode && ((PowerNode)other.block()).linkValid(other, this) && !PowerNode.insulated(other, this) && !other.proximity().contains(this) && + Building other = world.ent(x, y); + if(other != null && other.block instanceof PowerNode && ((PowerNode)other.block).linkValid(other, base()) && !PowerNode.insulated(other, base()) + && !other.proximity().contains(this.base()) && !(block.outputsPower && proximity.contains(p -> p.power() != null && p.power().graph == other.power().graph))){ tempTiles.add(other.tile()); } @@ -802,8 +803,8 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree tempTiles.sort(Structs.comparingFloat(t -> t.dst2(tile))); if(!tempTiles.isEmpty()){ Tile toLink = tempTiles.first(); - if(!toLink.entity.power().links.contains(pos())){ - toLink.entity.configureAny(pos()); + if(!toLink.build.power.links.contains(pos())){ + toLink.build.configureAny(pos()); } } } @@ -813,15 +814,15 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree } /** Called every frame a unit is on this */ - public void unitOn(Unitc unit){ + public void unitOn(Unit unit){ } /** Called when a unit that spawned at this tile is removed. */ - public void unitRemoved(Unitc unit){ + public void unitRemoved(Unit unit){ } /** Called when arbitrary configuration is applied to a tile. */ - public void configured(@Nullable Playerc player, @Nullable Object value){ + public void configured(@Nullable Player player, @Nullable Object value){ //null is of type void.class; anonymous classes use their superclass. Class type = value == null ? void.class : value.getClass().isAnonymousClass() ? value.getClass().getSuperclass() : value.getClass(); @@ -831,7 +832,7 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree } /** Called when the block is tapped.*/ - public void tapped(Playerc player){ + public void tapped(Player player){ } @@ -981,13 +982,13 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree table.left(); for(Consume cons : block.consumes.all()){ if(cons.isOptional() && cons.isBoost()) continue; - cons.build(this, table); + cons.build(base(), table); } } public void displayBars(Table table){ - for(Func bar : block.bars.list()){ - table.add(bar.get(this)).growX(); + for(Func bar : block.bars.list()){ + table.add(bar.get(base())).growX(); table.row(); } } @@ -999,7 +1000,7 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree /** Update table alignment after configuring.*/ public void updateTableAlign(Table table){ - Vec2 pos = Core.input.mouseScreen(x, y - block().size * tilesize / 2f - 1); + Vec2 pos = Core.input.mouseScreen(x, y - block.size * tilesize / 2f - 1); table.setPosition(pos.x, pos.y, Align.top); } @@ -1012,24 +1013,24 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree * Called when another tile is tapped while this block is selected. * @return whether or not this block should be deselected. */ - public boolean onConfigureTileTapped(Tilec other){ - return this != other; + public boolean onConfigureTileTapped(Building other){ + return base() != other; } /** Returns whether this config menu should show when the specified player taps it. */ - public boolean shouldShowConfigure(Playerc player){ + public boolean shouldShowConfigure(Player player){ return true; } /** Whether this configuration should be hidden now. Called every frame the config is open. */ - public boolean shouldHideConfigure(Playerc player){ + public boolean shouldHideConfigure(Player player){ return false; } public void drawConfigure(){ Draw.color(Pal.accent); Lines.stroke(1f); - Lines.square(x, y, block().size * tilesize / 2f + 1f); + Lines.square(x, y, block.size * tilesize / 2f + 1f); Draw.reset(); } @@ -1042,12 +1043,16 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree return amount; } - public boolean collide(Bulletc other){ + public boolean collide(Bullet other){ return true; } - public void collision(Bulletc other){ + /** Handle a bullet collision. + * @return whether the bullet should be removed. */ + public boolean collision(Bullet other){ damage(other.damage() * other.type().tileDamageMultiplier); + + return true; } public void removeFromProximity(){ @@ -1056,15 +1061,15 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree Point2[] nearby = Edges.getEdges(block.size); for(Point2 point : nearby){ - Tilec other = world.ent(tile.x + point.x, tile.y + point.y); + Building other = world.ent(tile.x + point.x, tile.y + point.y); //remove this tile from all nearby tile's proximities if(other != null){ tmpTiles.add(other); } } - for(Tilec other : tmpTiles){ - other.proximity().remove(this, true); + for(Building other : tmpTiles){ + other.proximity.remove(base(), true); other.onProximityUpdate(); } } @@ -1075,31 +1080,31 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree Point2[] nearby = Edges.getEdges(block.size); for(Point2 point : nearby){ - Tilec other = world.ent(tile.x + point.x, tile.y + point.y); + Building other = world.ent(tile.x + point.x, tile.y + point.y); - if(other == null || !(other.tile().interactable(team()))) continue; + if(other == null || !(other.tile.interactable(team))) continue; //add this tile to proximity of nearby tiles - if(!other.proximity().contains(this, true)){ - other.proximity().add(this); + if(!other.proximity.contains(base(), true)){ + other.proximity.add(base()); } tmpTiles.add(other); } //using a set to prevent duplicates - for(Tilec tile : tmpTiles){ + for(Building tile : tmpTiles){ proximity.add(tile); } - for(Tilec other : tmpTiles){ + for(Building other : tmpTiles){ other.onProximityUpdate(); } onProximityAdded(); onProximityUpdate(); - for(Tilec other : tmpTiles){ + for(Building other : tmpTiles){ other.onProximityUpdate(); } } @@ -1120,7 +1125,31 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree @Replace @Override public boolean isValid(){ - return tile.entity == this && !dead(); + return tile.build == base() && !dead(); + } + + @Replace + @Override + public void kill(){ + Call.tileDestroyed(base()); + } + + @Replace + @Override + public void damage(float damage){ + if(dead()) return; + + if(Mathf.zero(state.rules.blockHealthMultiplier)){ + damage = health + 1; + }else{ + damage /= state.rules.blockHealthMultiplier; + } + + Call.tileDamage(base(), health - handleDamage(damage)); + + if(health <= 0){ + Call.tileDestroyed(base()); + } } @Override @@ -1152,7 +1181,7 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree } if(block.idleSound != Sounds.none && shouldIdleSound()){ - loops.play(block.idleSound, this, block.idleSoundVolume); + loops.play(block.idleSound, base(), block.idleSoundVolume); } updateTile(); diff --git a/core/src/mindustry/entities/comp/BulletComp.java b/core/src/mindustry/entities/comp/BulletComp.java index 70415cb415..3b0be13cd7 100644 --- a/core/src/mindustry/entities/comp/BulletComp.java +++ b/core/src/mindustry/entities/comp/BulletComp.java @@ -15,10 +15,11 @@ import mindustry.graphics.*; import static mindustry.Vars.*; @EntityDef(value = {Bulletc.class}, pooled = true, serialize = false) -@Component +@Component(base = true) abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Drawc, Shielderc, Ownerc, Velc, Bulletc, Timerc{ @Import Team team; @Import Entityc owner; + @Import float x,y; IntSeq collided = new IntSeq(6); Object data; @@ -27,31 +28,31 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw @Override public void getCollisions(Cons consumer){ - for(Team team : state.teams.enemiesOf(team)){ + for(Team team : team.enemies()){ consumer.get(teamIndex.tree(team)); } } @Override public void drawBullets(){ - type.draw(this); + type.draw(base()); } @Override public void add(){ - type.init(this); + type.init(base()); } @Override public void remove(){ - type.despawned(this); + type.despawned(base()); collided.clear(); } @Override public float damageMultiplier(){ - if(owner instanceof Unitc) return ((Unitc)owner).damageMultiplier() * state.rules.unitDamageMultiplier; - if(owner instanceof Tilec) return state.rules.blockDamageMultiplier; + if(owner instanceof Unit) return ((Unit)owner).damageMultiplier() * state.rules.unitDamageMultiplier; + if(owner instanceof Building) return state.rules.blockDamageMultiplier; return 1f; } @@ -74,24 +75,24 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw @Replace @Override public boolean collides(Hitboxc other){ - return type.collides && (other instanceof Teamc && ((Teamc)other).team() != team()) - && !(other instanceof Flyingc && ((((Flyingc)other).isFlying() && !type.collidesAir) || (((Flyingc)other).isGrounded() && !type.collidesGround))) + return type.collides && (other instanceof Teamc && ((Teamc)other).team() != team) + && !(other instanceof Flyingc && !((Flyingc)other).checkTarget(type.collidesAir, type.collidesGround)) && !(type.pierce && collided.contains(other.id())); //prevent multiple collisions } @MethodPriority(100) @Override public void collision(Hitboxc other, float x, float y){ - type.hit(this, x, y); + type.hit(base(), x, y); if(other instanceof Healthc){ Healthc h = (Healthc)other; h.damage(damage); } - if(other instanceof Unitc){ - Unitc unit = (Unitc)other; - unit.vel().add(Tmp.v3.set(other.x(), other.y()).sub(x, y).setLength(type.knockback / unit.mass())); + if(other instanceof Unit){ + Unit unit = (Unit)other; + unit.impulse(Tmp.v3.set(unit).sub(this.x, this.y).nor().scl(type.knockback * 80f)); unit.apply(type.status, type.statusDuration); } @@ -105,21 +106,25 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw @Override public void update(){ - type.update(this); + type.update(base()); - if(type.collidesTiles && type.collides){ + if(type.collidesTiles && type.collides && type.collidesGround){ world.raycastEach(world.toTile(lastX()), world.toTile(lastY()), tileX(), tileY(), (x, y) -> { - Tilec tile = world.ent(x, y); + Building tile = world.ent(x, y); if(tile == null) return false; - if(tile.collide(this) && type.collides(this, tile) && !tile.dead() && (type.collidesTeam || tile.team() != team())){ - if(tile.team() != team()){ - tile.collision(this); + if(tile.collide(base()) && type.collides(base(), tile) && !tile.dead() && (type.collidesTeam || tile.team != team)){ + boolean remove = false; + + if(tile.team != team){ + remove = tile.collision(base()); } - type.hitTile(this, tile); - remove(); + if(remove || type.collidesTeam){ + type.hitTile(base(), tile); + remove(); + } return true; } @@ -132,8 +137,8 @@ abstract class BulletComp implements Timedc, Damagec, Hitboxc, Teamc, Posc, Draw public void draw(){ Draw.z(Layer.bullet); - type.draw(this); - type.drawLight(this); + type.draw(base()); + type.drawLight(base()); } /** Sets the bullet's rotation in degrees. */ diff --git a/core/src/mindustry/entities/comp/CommanderComp.java b/core/src/mindustry/entities/comp/CommanderComp.java index 607b0968bf..5462014a16 100644 --- a/core/src/mindustry/entities/comp/CommanderComp.java +++ b/core/src/mindustry/entities/comp/CommanderComp.java @@ -16,7 +16,7 @@ abstract class CommanderComp implements Unitc{ @Import float x, y, rotation; transient @Nullable Formation formation; - transient Seq controlling = new Seq<>(); + transient Seq controlling = new Seq<>(); @Override public void update(){ @@ -42,12 +42,12 @@ abstract class CommanderComp implements Unitc{ clearCommand(); } - void command(Formation formation, Seq units){ + void command(Formation formation, Seq units){ clearCommand(); controlling.addAll(units); - for(Unitc unit : units){ - unit.controller(new FormationAI(this, formation)); + for(Unit unit : units){ + unit.controller(new FormationAI(base(), formation)); } this.formation = formation; @@ -67,8 +67,8 @@ abstract class CommanderComp implements Unitc{ void clearCommand(){ //reset controlled units - for(Unitc unit : controlling){ - if(unit.controller().isBeingControlled(this)){ + for(Unit unit : controlling){ + if(unit.controller().isBeingControlled(base())){ unit.controller(unit.type().createController()); } } diff --git a/core/src/mindustry/entities/comp/DecalComp.java b/core/src/mindustry/entities/comp/DecalComp.java index f1e6e21bc1..6db6b58f53 100644 --- a/core/src/mindustry/entities/comp/DecalComp.java +++ b/core/src/mindustry/entities/comp/DecalComp.java @@ -8,7 +8,7 @@ import mindustry.gen.*; import mindustry.graphics.*; @EntityDef(value = {Decalc.class}, pooled = true, serialize = false) -@Component +@Component(base = true) abstract class DecalComp implements Drawc, Timedc, Rotc, Posc{ @Import float x, y, rotation; @@ -19,10 +19,10 @@ abstract class DecalComp implements Drawc, Timedc, Rotc, Posc{ public void draw(){ Draw.z(Layer.scorch); - Draw.color(color); + Draw.mixcol(color, color.a); Draw.alpha(1f - Mathf.curve(fin(), 0.98f)); Draw.rect(region, x, y, rotation); - Draw.color(); + Draw.reset(); } @Replace diff --git a/core/src/mindustry/entities/comp/EffectComp.java b/core/src/mindustry/entities/comp/EffectStateComp.java similarity index 69% rename from core/src/mindustry/entities/comp/EffectComp.java rename to core/src/mindustry/entities/comp/EffectStateComp.java index 7ccd477596..3ad57d5d19 100644 --- a/core/src/mindustry/entities/comp/EffectComp.java +++ b/core/src/mindustry/entities/comp/EffectStateComp.java @@ -5,9 +5,9 @@ import mindustry.annotations.Annotations.*; import mindustry.entities.*; import mindustry.gen.*; -@EntityDef(value = {Effectc.class, Childc.class}, pooled = true, serialize = false) -@Component -abstract class EffectComp implements Posc, Drawc, Timedc, Rotc, Childc{ +@EntityDef(value = {EffectStatec.class, Childc.class}, pooled = true, serialize = false) +@Component(base = true) +abstract class EffectStateComp implements Posc, Drawc, Timedc, Rotc, Childc{ Color color = new Color(Color.white); Effect effect; Object data; diff --git a/core/src/mindustry/entities/comp/ElevationMoveComp.java b/core/src/mindustry/entities/comp/ElevationMoveComp.java index 6e8b30a1cb..af4b58571d 100644 --- a/core/src/mindustry/entities/comp/ElevationMoveComp.java +++ b/core/src/mindustry/entities/comp/ElevationMoveComp.java @@ -19,4 +19,5 @@ abstract class ElevationMoveComp implements Velc, Posc, Flyingc, Hitboxc{ collisions.move(this, cx, cy); } } + } diff --git a/core/src/mindustry/entities/comp/EntityComp.java b/core/src/mindustry/entities/comp/EntityComp.java index 0ae1732e87..3e49ea01ce 100644 --- a/core/src/mindustry/entities/comp/EntityComp.java +++ b/core/src/mindustry/entities/comp/EntityComp.java @@ -32,11 +32,19 @@ abstract class EntityComp{ return ((Object)this) == player || ((Object)this) instanceof Unitc && ((Unitc)((Object)this)).controller() == player; } + boolean isRemote(){ + return ((Object)this) instanceof Unitc && ((Unitc)((Object)this)).isPlayer() && !isLocal(); + } + boolean isNull(){ return false; } - T as(Class type){ + T base(){ + return (T)this; + } + + T as(){ return (T)this; } diff --git a/core/src/mindustry/entities/comp/FireComp.java b/core/src/mindustry/entities/comp/FireComp.java index eeaaf41218..74f5199ab6 100644 --- a/core/src/mindustry/entities/comp/FireComp.java +++ b/core/src/mindustry/entities/comp/FireComp.java @@ -14,7 +14,7 @@ import mindustry.world.*; import static mindustry.Vars.*; @EntityDef(value = {Firec.class}, pooled = true) -@Component +@Component(base = true) abstract class FireComp implements Timedc, Posc, Firec{ private static final float spreadChance = 0.05f, fireballChance = 0.07f; @@ -49,7 +49,7 @@ abstract class FireComp implements Timedc, Posc, Firec{ return; } - Tilec entity = tile.entity; + Building entity = tile.build; boolean damage = entity != null; float flammability = baseFlammability + puddleFlammability; @@ -59,7 +59,7 @@ abstract class FireComp implements Timedc, Posc, Firec{ } if(baseFlammability < 0 || block != tile.block()){ - baseFlammability = tile.entity == null ? 0 : tile.entity.getFlammability(); + baseFlammability = tile.build == null ? 0 : tile.build.getFlammability(); block = tile.block(); } @@ -97,6 +97,6 @@ abstract class FireComp implements Timedc, Posc, Firec{ @Override public void afterRead(){ - Fires.register(this); + Fires.register(base()); } } diff --git a/core/src/mindustry/entities/comp/FlyingComp.java b/core/src/mindustry/entities/comp/FlyingComp.java index f79fd3c3a1..68dd062da8 100644 --- a/core/src/mindustry/entities/comp/FlyingComp.java +++ b/core/src/mindustry/entities/comp/FlyingComp.java @@ -17,11 +17,16 @@ abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{ @Import float x, y; @Import Vec2 vel; - @SyncField(value = true, clamped = true) @SyncLocal float elevation; + @SyncLocal float elevation; private transient boolean wasFlying; + transient boolean hovering; transient float drownTime; transient float splashTimer; + boolean checkTarget(boolean targetAir, boolean targetGround){ + return (isGrounded() && targetGround) || (isFlying() && targetAir); + } + boolean isGrounded(){ return elevation < 0.001f; } @@ -31,7 +36,7 @@ abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{ } boolean canDrown(){ - return isGrounded(); + return isGrounded() && !hovering; } void landed(){ @@ -50,7 +55,7 @@ abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{ } float floorSpeedMultiplier(){ - Floor on = isFlying() ? Blocks.air.asFloor() : floorOn(); + Floor on = isFlying() || hovering ? Blocks.air.asFloor() : floorOn(); return on.speedMultiplier; } @@ -68,7 +73,7 @@ abstract class FlyingComp implements Posc, Velc, Healthc, Hitboxc{ wasFlying = isFlying(); } - if(isGrounded() && floor.isLiquid){ + if(!hovering && isGrounded() && floor.isLiquid){ if((splashTimer += Mathf.dst(deltaX(), deltaY())) >= 7f){ floor.walkEffect.at(x, y, 1f, floor.mapColor); splashTimer = 0f; diff --git a/core/src/mindustry/entities/comp/HealthComp.java b/core/src/mindustry/entities/comp/HealthComp.java index d906adb714..7d95d22964 100644 --- a/core/src/mindustry/entities/comp/HealthComp.java +++ b/core/src/mindustry/entities/comp/HealthComp.java @@ -82,7 +82,7 @@ abstract class HealthComp implements Entityc{ } void damageContinuous(float amount){ - damage(amount * Time.delta(), hitTime <= -20 + hitDuration); + damage(amount * Time.delta(), hitTime <= -10 + hitDuration); } void damageContinuousPierce(float amount){ @@ -93,8 +93,14 @@ abstract class HealthComp implements Entityc{ health = Mathf.clamp(health, 0, maxHealth); } + /** Heals by a flat amount. */ void heal(float amount){ health += amount; clampHealth(); } + + /** Heals by a 0-1 fraction of max health. */ + void healFract(float amount){ + heal(amount * maxHealth); + } } diff --git a/core/src/mindustry/entities/comp/HitboxComp.java b/core/src/mindustry/entities/comp/HitboxComp.java index 95fd21ce2e..29b458c429 100644 --- a/core/src/mindustry/entities/comp/HitboxComp.java +++ b/core/src/mindustry/entities/comp/HitboxComp.java @@ -1,6 +1,7 @@ package mindustry.entities.comp; import arc.func.*; +import arc.math.*; import arc.math.geom.QuadTree.*; import arc.math.geom.*; import mindustry.annotations.Annotations.*; @@ -48,6 +49,14 @@ abstract class HitboxComp implements Posc, QuadTreeObject{ return y - lastY; } + float deltaLen(){ + return Mathf.len(deltaX(), deltaY()); + } + + float deltaAngle(){ + return Mathf.angle(deltaX(), deltaY()); + } + boolean collides(Hitboxc other){ return true; } diff --git a/core/src/mindustry/entities/comp/ItemsComp.java b/core/src/mindustry/entities/comp/ItemsComp.java index 55a55fd20e..03e0b50e7c 100644 --- a/core/src/mindustry/entities/comp/ItemsComp.java +++ b/core/src/mindustry/entities/comp/ItemsComp.java @@ -7,7 +7,7 @@ import mindustry.type.*; @Component abstract class ItemsComp implements Posc{ - @ReadOnly ItemStack stack = new ItemStack(); + ItemStack stack = new ItemStack(); transient float itemTime; abstract int itemCapacity(); diff --git a/core/src/mindustry/entities/comp/LegsComp.java b/core/src/mindustry/entities/comp/LegsComp.java index 452452b844..e516c6befe 100644 --- a/core/src/mindustry/entities/comp/LegsComp.java +++ b/core/src/mindustry/entities/comp/LegsComp.java @@ -12,8 +12,10 @@ import mindustry.graphics.*; import mindustry.type.*; import mindustry.world.blocks.environment.*; +import static mindustry.Vars.*; + @Component -abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc, ElevationMovec{ +abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc{ @Import float x, y; @Import UnitType type; @@ -22,6 +24,12 @@ abstract class LegsComp implements Posc, Rotc, Hitboxc, Flyingc, Unitc, Elevatio transient float moveSpace; transient float baseRotation; + @Replace + @Override + public void move(float cx, float cy){ + collisions.moveCheck(this, cx, cy, !type.allowLegStep ? EntityCollisions::solid : EntityCollisions::legsSolid); + } + @Override public void update(){ if(Mathf.dst(deltaX(), deltaY()) > 0.001f){ diff --git a/core/src/mindustry/entities/comp/MechComp.java b/core/src/mindustry/entities/comp/MechComp.java index 7cf6db2373..0c0a6f4962 100644 --- a/core/src/mindustry/entities/comp/MechComp.java +++ b/core/src/mindustry/entities/comp/MechComp.java @@ -12,8 +12,8 @@ abstract class MechComp implements Posc, Flyingc, Hitboxc, Unitc, Mechc, Elevati @Override public void update(){ - float len = vel().len(); - baseRotation = Angles.moveToward(baseRotation, vel().angle(), type().baseRotateSpeed * Mathf.clamp(len / type().speed)); + float len = deltaLen(); + baseRotation = Angles.moveToward(baseRotation, deltaAngle(), type().baseRotateSpeed * Mathf.clamp(len / type().speed)); walkTime += Time.delta()*len; } } diff --git a/core/src/mindustry/entities/comp/MinerComp.java b/core/src/mindustry/entities/comp/MinerComp.java index eca9ef3ef6..781d9ebb83 100644 --- a/core/src/mindustry/entities/comp/MinerComp.java +++ b/core/src/mindustry/entities/comp/MinerComp.java @@ -17,17 +17,20 @@ import mindustry.world.*; import static mindustry.Vars.*; @Component -abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc{ +abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc, Unitc{ @Import float x, y, rotation; + @Import UnitType type; transient float mineTimer; - @Nullable Tile mineTile; + @Nullable @SyncLocal Tile mineTile; - abstract boolean canMine(Item item); + public boolean canMine(Item item){ + return type.mineTier >= item.hardness; + } - abstract float miningSpeed(); - - abstract boolean offloadImmediately(); + public boolean offloadImmediately(){ + return isPlayer(); + } boolean mining(){ return mineTile != null; @@ -35,9 +38,9 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc{ @Override public void update(){ - Tilec core = closestCore(); + Building core = closestCore(); - if(core != null && mineTile != null && mineTile.drop() != null && !acceptsItem(mineTile.drop()) && dst(core) < mineTransferRange){ + if(core != null && mineTile != null && mineTile.drop() != null && !acceptsItem(mineTile.drop()) && within(core, mineTransferRange)){ int accepted = core.acceptStack(item(), stack().amount, this); if(accepted > 0){ Call.transferItemTo(item(), accepted, @@ -55,12 +58,12 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc{ }else{ Item item = mineTile.drop(); rotation(Mathf.slerpDelta(rotation(), angleTo(mineTile.worldx(), mineTile.worldy()), 0.4f)); - mineTimer += Time.delta()*miningSpeed(); + mineTimer += Time.delta()*type.mineSpeed; if(mineTimer >= 50f + item.hardness*10f){ mineTimer = 0; - if(dst(core) < mineTransferRange && core.acceptStack(item, 1, this) == 1 && offloadImmediately()){ + if(within(core, mineTransferRange) && core.acceptStack(item, 1, this) == 1 && offloadImmediately()){ Call.transferItemTo(item, 1, mineTile.worldx() + Mathf.range(tilesize / 2f), mineTile.worldy() + Mathf.range(tilesize / 2f), core.tile()); @@ -92,6 +95,8 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc{ float ex = mineTile.worldx() + Mathf.sin(Time.time() + 48, swingScl, swingMag); float ey = mineTile.worldy() + Mathf.sin(Time.time() + 48, swingScl + 2f, swingMag); + Draw.z(Layer.flyingUnit + 0.1f); + Draw.color(Color.lightGray, Color.white, 1f - flashScl + Mathf.absin(Time.time(), 0.5f, flashScl)); Drawf.laser(team(), Core.atlas.find("minelaser"), Core.atlas.find("minelaser-end"), px, py, ex, ey, 0.75f); diff --git a/core/src/mindustry/entities/comp/PayloadComp.java b/core/src/mindustry/entities/comp/PayloadComp.java index fafbc99532..c655180e30 100644 --- a/core/src/mindustry/entities/comp/PayloadComp.java +++ b/core/src/mindustry/entities/comp/PayloadComp.java @@ -25,13 +25,13 @@ abstract class PayloadComp implements Posc, Rotc{ payloads.add(load); } - void pickup(Unitc unit){ + void pickup(Unit unit){ unit.remove(); payloads.add(new UnitPayload(unit)); Fx.unitPickup.at(unit); } - void pickup(Tilec tile){ + void pickup(Building tile){ tile.tile().remove(); payloads.add(new BlockPayload(tile)); Fx.unitPickup.at(tile); @@ -53,9 +53,9 @@ abstract class PayloadComp implements Posc, Rotc{ Tile on = tileOn(); //drop off payload on an acceptor if possible - if(on != null && on.entity != null && on.entity.acceptPayload(on.entity, payload)){ - Fx.unitDrop.at(on.entity); - on.entity.handlePayload(on.entity, payload); + if(on != null && on.build != null && on.build.acceptPayload(on.build, payload)){ + Fx.unitDrop.at(on.build); + on.build.handlePayload(on.build, payload); return true; } @@ -69,10 +69,10 @@ abstract class PayloadComp implements Posc, Rotc{ boolean dropUnit(UnitPayload payload){ //TODO create an effect here and/or make them be at a lower elevation - Unitc u = payload.unit; + Unit u = payload.unit; //can't drop ground units - if((tileOn() == null || tileOn().solid()) && u.elevation() < 0.1f){ + if((tileOn() == null || tileOn().solid()) && u.elevation < 0.1f){ return false; } @@ -87,11 +87,11 @@ abstract class PayloadComp implements Posc, Rotc{ /** @return whether the tile has been successfully placed. */ boolean dropBlock(BlockPayload payload){ - Tilec tile = payload.entity; + Building tile = payload.entity; int tx = Vars.world.toTile(x - tile.block().offset()), ty = Vars.world.toTile(y - tile.block().offset()); Tile on = Vars.world.tile(tx, ty); if(on != null && Build.validPlace(tile.block(), tile.team(), tx, ty, tile.rotation())){ - int rot = (int)((rotation() + 45f) / 90f) % 4; + int rot = (int)((rotation + 45f) / 90f) % 4; payload.place(on, rot); Fx.unitDrop.at(tile); diff --git a/core/src/mindustry/entities/comp/PhysicsComp.java b/core/src/mindustry/entities/comp/PhysicsComp.java index 8db4ab12ff..12972935ee 100644 --- a/core/src/mindustry/entities/comp/PhysicsComp.java +++ b/core/src/mindustry/entities/comp/PhysicsComp.java @@ -1,6 +1,7 @@ package mindustry.entities.comp; import arc.math.*; +import arc.math.geom.*; import mindustry.annotations.Annotations.*; import mindustry.async.PhysicsProcess.*; import mindustry.gen.*; @@ -11,6 +12,7 @@ import mindustry.gen.*; @Component abstract class PhysicsComp implements Velc, Hitboxc, Flyingc{ @Import float hitSize; + @Import Vec2 vel; transient PhysicRef physref; @@ -21,6 +23,10 @@ abstract class PhysicsComp implements Velc, Hitboxc, Flyingc{ void impulse(float x, float y){ float mass = mass(); - vel().add(x / mass, y / mass); + vel.add(x / mass, y / mass); + } + + void impulse(Vec2 v){ + impulse(v.x, v.y); } } diff --git a/core/src/mindustry/entities/comp/PlayerComp.java b/core/src/mindustry/entities/comp/PlayerComp.java index 63d27a8e95..8caf31c46c 100644 --- a/core/src/mindustry/entities/comp/PlayerComp.java +++ b/core/src/mindustry/entities/comp/PlayerComp.java @@ -9,10 +9,11 @@ import arc.util.*; import arc.util.ArcAnnotate.*; import arc.util.pooling.*; import mindustry.annotations.Annotations.*; +import mindustry.content.*; import mindustry.core.*; import mindustry.entities.units.*; -import mindustry.game.*; import mindustry.game.EventType.*; +import mindustry.game.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.net.Administration.*; @@ -20,23 +21,26 @@ import mindustry.net.*; import mindustry.net.Packets.*; import mindustry.ui.*; import mindustry.world.*; +import mindustry.world.blocks.storage.*; import mindustry.world.blocks.storage.CoreBlock.*; import static mindustry.Vars.*; @EntityDef(value = {Playerc.class}, serialize = false) -@Component +@Component(base = true) abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Drawc{ static final float deathDelay = 30f; - @NonNull @ReadOnly Unitc unit = Nulls.unit; + @Import float x, y; + + @NonNull @ReadOnly Unit unit = Nulls.unit; transient @Nullable NetConnection con; @ReadOnly Team team = Team.sharded; + @SyncLocal boolean admin, typing, shooting, boosting; + @SyncLocal float mouseX, mouseY; String name = "noname"; - boolean admin, typing, shooting, boosting; Color color = new Color(); - float mouseX, mouseY; transient float deathTimer; transient String lastText = ""; @@ -51,13 +55,20 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra } public @Nullable CoreEntity closestCore(){ - return state.teams.closestCore(x(), y(), team); + return state.teams.closestCore(x, y, team); } public @Nullable CoreEntity core(){ return team.core(); } + public TextureRegion icon(){ + //display default icon for dead players + if(dead()) return core() == null ? UnitTypes.alpha.icon(Cicon.full) : ((CoreBlock)core().block).unitType.icon(Cicon.full); + + return unit.icon(); + } + public void reset(){ team = state.rules.defaultTeam; admin = typing = false; @@ -68,6 +79,11 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra } } + @Override + public boolean isValidController(){ + return isAdded(); + } + @Replace public float clipSize(){ return unit.isNull() ? 20 : unit.type().hitsize * 2f; @@ -98,14 +114,15 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra //update some basic state to sync things if(unit.type().canBoost){ Tile tile = unit.tileOn(); - unit.elevation(Mathf.approachDelta(unit.elevation(), (tile != null && tile.solid()) || boosting ? 1f : 0f, 0.08f)); + unit.elevation(Mathf.approachDelta(unit.elevation, (tile != null && tile.solid()) || boosting ? 1f : 0f, 0.08f)); } }else if(core != null){ //have a small delay before death to prevent the camera from jumping around too quickly //(this is not for balance) deathTimer += Time.delta(); if(deathTimer >= deathDelay){ - core.requestSpawn((Playerc)this); + //request spawn - this happens serverside only + core.requestSpawn(base()); deathTimer = 0; } } @@ -114,6 +131,14 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra } + @Override + public void remove(){ + //clear unit upon removal + if(!unit.isNull()){ + clearUnit(); + } + } + public void team(Team team){ this.team = team; unit.team(team); @@ -123,7 +148,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra unit(Nulls.unit); } - public Unitc unit(){ + public Unit unit(){ return unit; } @@ -135,7 +160,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra return !(unit instanceof Builderc) ? Nulls.builder : (Builderc)unit; } - public void unit(Unitc unit){ + public void unit(Unit unit){ if(unit == null) throw new IllegalArgumentException("Unit cannot be null. Use clearUnit() instead."); if(this.unit == unit) return; if(this.unit != Nulls.unit){ @@ -148,7 +173,7 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra unit.controller(this); } - Events.fire(new UnitChangeEvent((Playerc)this, unit)); + Events.fire(new UnitChangeEvent(base(), unit)); } boolean dead(){ @@ -192,17 +217,17 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra if(!isLocal()){ Draw.color(0f, 0f, 0f, 0.3f); - Fill.rect(unit.x(), unit.y() + nameHeight - layout.height / 2, layout.width + 2, layout.height + 3); + Fill.rect(unit.x, unit.y + nameHeight - layout.height / 2, layout.width + 2, layout.height + 3); Draw.color(); font.setColor(color); - font.draw(name, unit.x(), unit.y() + nameHeight, 0, Align.center, false); + font.draw(name, unit.x, unit.y + nameHeight, 0, Align.center, false); if(admin){ float s = 3f; Draw.color(color.r * 0.5f, color.g * 0.5f, color.b * 0.5f, 1f); - Draw.rect(Icon.adminSmall.getRegion(), unit.x() + layout.width / 2f + 2 + 1, unit.y() + nameHeight - 1.5f, s, s); + Draw.rect(Icon.adminSmall.getRegion(), unit.x + layout.width / 2f + 2 + 1, unit.y + nameHeight - 1.5f, s, s); Draw.color(color); - Draw.rect(Icon.adminSmall.getRegion(), unit.x() + layout.width / 2f + 2 + 1, unit.y() + nameHeight - 1f, s, s); + Draw.rect(Icon.adminSmall.getRegion(), unit.x + layout.width / 2f + 2 + 1, unit.y + nameHeight - 1f, s, s); } } @@ -215,8 +240,8 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra layout.setText(font, text, Color.white, width, Align.bottom, true); Draw.color(0f, 0f, 0f, 0.3f * (textFadeTime <= 0 || lastText == null ? 1f : visualFadeTime)); - Fill.rect(unit.x(), unit.y() + textHeight + layout.height - layout.height/2f, layout.width + 2, layout.height + 3); - font.draw(text, unit.x() - width/2f, unit.y() + textHeight + layout.height, width, Align.center, true); + Fill.rect(unit.x, unit.y + textHeight + layout.height - layout.height/2f, layout.width + 2, layout.height + 3); + font.draw(text, unit.x - width/2f, unit.y + textHeight + layout.height, width, Align.center, true); } Draw.reset(); @@ -238,11 +263,11 @@ abstract class PlayerComp implements UnitController, Entityc, Syncc, Timerc, Dra } } - void sendMessage(String text, Playerc from){ - sendMessage(text, from, NetClient.colorizeName(from.id(), from.name())); + void sendMessage(String text, Player from){ + sendMessage(text, from, NetClient.colorizeName(from.id(), from.name)); } - void sendMessage(String text, Playerc from, String fromName){ + void sendMessage(String text, Player from, String fromName){ if(isLocal()){ if(ui != null){ ui.chatfrag.addMessage(text, fromName); diff --git a/core/src/mindustry/entities/comp/PuddleComp.java b/core/src/mindustry/entities/comp/PuddleComp.java index 909d074f19..5c29a04d57 100644 --- a/core/src/mindustry/entities/comp/PuddleComp.java +++ b/core/src/mindustry/entities/comp/PuddleComp.java @@ -18,7 +18,7 @@ import static mindustry.Vars.*; import static mindustry.entities.Puddles.*; @EntityDef(value = {Puddlec.class}, pooled = true) -@Component +@Component(base = true) abstract class PuddleComp implements Posc, Puddlec, Drawc{ private static final int maxGeneration = 2; private static final Color tmp = new Color(); @@ -68,7 +68,7 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{ //effects-only code if(amount >= maxLiquid / 2f && updateTime <= 0f){ Units.nearby(rect.setSize(Mathf.clamp(amount / (maxLiquid / 1.5f)) * 10f).setCenter(x, y), unit -> { - if(unit.isGrounded()){ + if(unit.isGrounded() && !unit.hovering){ unit.hitbox(rect2); if(rect.overlaps(rect2)){ unit.apply(liquid.effect, 60 * 2); @@ -80,11 +80,11 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{ } }); - if(liquid.temperature > 0.7f && (tile.entity != null) && Mathf.chance(0.3 * Time.delta())){ + if(liquid.temperature > 0.7f && (tile.build != null) && Mathf.chance(0.5)){ Fires.create(tile); } - updateTime = 20f; + updateTime = 40f; } updateTime -= Time.delta(); @@ -128,6 +128,6 @@ abstract class PuddleComp implements Posc, Puddlec, Drawc{ @Override public void afterRead(){ - Puddles.register(this); + Puddles.register(base()); } } diff --git a/core/src/mindustry/entities/comp/ShieldComp.java b/core/src/mindustry/entities/comp/ShieldComp.java index 204efff128..421bf1295f 100644 --- a/core/src/mindustry/entities/comp/ShieldComp.java +++ b/core/src/mindustry/entities/comp/ShieldComp.java @@ -34,7 +34,7 @@ abstract class ShieldComp implements Healthc, Posc{ shieldAlpha = 1f; } - float shieldDamage = Math.min(shield, amount); + float shieldDamage = Math.min(Math.max(shield, 0), amount); shield -= shieldDamage; amount -= shieldDamage; diff --git a/core/src/mindustry/entities/comp/StatusComp.java b/core/src/mindustry/entities/comp/StatusComp.java index 53cefee8fd..f244500262 100644 --- a/core/src/mindustry/entities/comp/StatusComp.java +++ b/core/src/mindustry/entities/comp/StatusComp.java @@ -13,7 +13,7 @@ import mindustry.gen.*; import mindustry.type.*; import mindustry.world.blocks.environment.*; -import static mindustry.Vars.content; +import static mindustry.Vars.*; @Component abstract class StatusComp implements Posc, Flyingc{ @@ -46,7 +46,7 @@ abstract class StatusComp implements Posc, Flyingc{ return; }else if(entry.effect.reactsWith(effect)){ //find opposite StatusEntry.tmp.effect = entry.effect; - entry.effect.getTransition((Unitc)this, effect, entry.time, duration, StatusEntry.tmp); + entry.effect.getTransition(base(), effect, entry.time, duration, StatusEntry.tmp); entry.time = StatusEntry.tmp.time; if(StatusEntry.tmp.effect != entry.effect){ @@ -128,15 +128,14 @@ abstract class StatusComp implements Posc, Flyingc{ speedMultiplier *= entry.effect.speedMultiplier; armorMultiplier *= entry.effect.armorMultiplier; damageMultiplier *= entry.effect.damageMultiplier; - //TODO ugly casting - entry.effect.update((Unitc)this, entry.time); + entry.effect.update(base(), entry.time); } } } public void draw(){ for(StatusEntry e : statuses){ - e.effect.draw((Unitc)this); + e.effect.draw(base()); } } diff --git a/core/src/mindustry/entities/comp/SyncComp.java b/core/src/mindustry/entities/comp/SyncComp.java index 550c2e8363..0fd3d06cae 100644 --- a/core/src/mindustry/entities/comp/SyncComp.java +++ b/core/src/mindustry/entities/comp/SyncComp.java @@ -22,8 +22,19 @@ abstract class SyncComp implements Entityc{ @Override public void update(){ - if(Vars.net.client() && !isLocal()){ + //interpolate the player if: + //- this is a client and the entity is everything except the local player + //- this is a server and the entity is a remote player + if((Vars.net.client() && !isLocal()) || isRemote()){ interpolate(); } } + + @Override + public void remove(){ + //notify client of removal + if(Vars.net.client()){ + Vars.netClient.addRemovedEntity(id()); + } + } } diff --git a/core/src/mindustry/entities/comp/TeamComp.java b/core/src/mindustry/entities/comp/TeamComp.java index 9f6791002d..ed03caca5c 100644 --- a/core/src/mindustry/entities/comp/TeamComp.java +++ b/core/src/mindustry/entities/comp/TeamComp.java @@ -17,15 +17,15 @@ abstract class TeamComp implements Posc{ return team.rules().cheat; } - public @Nullable Tilec core(){ + public @Nullable Building core(){ return team.core(); } - public @Nullable Tilec closestCore(){ + public @Nullable Building closestCore(){ return state.teams.closestCore(x, y, team); } - public @Nullable Tilec closestEnemyCore(){ + public @Nullable Building closestEnemyCore(){ return state.teams.closestEnemyCore(x, y, team); } } diff --git a/core/src/mindustry/entities/comp/TrailComp.java b/core/src/mindustry/entities/comp/TrailComp.java index 0109661a7c..420526256d 100644 --- a/core/src/mindustry/entities/comp/TrailComp.java +++ b/core/src/mindustry/entities/comp/TrailComp.java @@ -11,10 +11,12 @@ abstract class TrailComp implements Unitc{ @Import UnitType type; @Import float x, y, rotation; - transient Trail trail = new Trail(); + transient Trail trail = new Trail(6); @Override public void update(){ + trail.length = type.trailLength; + float scale = elevation(); float offset = type.engineOffset/2f + type.engineOffset/2f*scale; diff --git a/core/src/mindustry/entities/comp/UnitComp.java b/core/src/mindustry/entities/comp/UnitComp.java index c125cdb984..1a8fcf6861 100644 --- a/core/src/mindustry/entities/comp/UnitComp.java +++ b/core/src/mindustry/entities/comp/UnitComp.java @@ -1,6 +1,7 @@ package mindustry.entities.comp; import arc.*; +import arc.graphics.g2d.*; import arc.math.*; import arc.math.geom.*; import arc.scene.ui.layout.*; @@ -11,6 +12,7 @@ import mindustry.content.*; import mindustry.entities.*; import mindustry.entities.units.*; import mindustry.game.EventType.*; +import mindustry.game.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.type.*; @@ -20,15 +22,20 @@ import mindustry.world.blocks.environment.*; import static mindustry.Vars.*; -@Component +@Component(base = true) abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, Itemsc, Rotc, Unitc, Weaponsc, Drawc, Boundedc, Syncc, Shieldc, Displayable{ - @Import float x, y, rotation, elevation, maxHealth, drag, armor; + @Import boolean hovering; + @Import float x, y, rotation, elevation, maxHealth, drag, armor, hitSize, health; + @Import boolean dead; + @Import Team team; private UnitController controller; private UnitType type; boolean spawnedByCore; + transient float timer1, timer2; + public void moveAt(Vec2 vector){ moveAt(vector, type.accel); } @@ -59,13 +66,13 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I @Override public float bounds(){ - return hitSize() * 2f; + return hitSize * 2f; } @Override public void controller(UnitController next){ this.controller = next; - if(controller.unit() != this) controller.unit(this); + if(controller.unit() != base()) controller.unit(base()); } @Override @@ -85,16 +92,9 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I @Override public void type(UnitType type){ - this.type = type; - this.maxHealth = type.health; - this.drag = type.drag; - this.elevation = type.flying ? 1f : type.baseElevation; - this.armor = type.armor; + if(this.type == type) return; - heal(); - hitSize(type.hitsize); - controller(type.createController()); - setupWeapons(type); + setStats(type); } @Override @@ -118,21 +118,42 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I return controller instanceof AIController; } + private void setStats(UnitType type){ + this.type = type; + this.maxHealth = type.health; + this.drag = type.drag; + this.elevation = type.flying ? 1f : 0; + this.armor = type.armor; + this.hitSize = type.hitsize; + this.hovering = type.hovering; + + if(controller == null) controller(type.createController()); + if(mounts().length != type.weapons.size) setupWeapons(type); + } + + @Override + public void afterSync(){ + //set up type info after reading + setStats(this.type); + controller.unit(base()); + } + @Override public void afterRead(){ - //set up type info after reading - type(this.type); + afterSync(); + //reset controller state + controller(type.createController()); } @Override public void add(){ - teamIndex.updateCount(team(), 1); + teamIndex.updateCount(team, 1); } @Override public void remove(){ - teamIndex.updateCount(team(), -1); - controller.removed(this); + teamIndex.updateCount(team, -1); + controller.removed(base()); } @Override @@ -141,17 +162,17 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I Effects.shake(type.landShake, type.landShake, this); } - type.landed(this); + type.landed(base()); } @Override public void update(){ - type.update(this); + type.update(base()); - drag(type.drag * (isGrounded() ? (floorOn().dragMultiplier) : 1f)); + drag = type.drag * (isGrounded() ? (floorOn().dragMultiplier) : 1f); //apply knockback based on spawns - if(team() != state.rules.waveTeam){ + if(team != state.rules.waveTeam){ float relativeSize = state.rules.dropZoneRadius + bounds()/2f + 1f; for(Tile spawn : spawner.getSpawns()){ if(within(spawn.worldx(), spawn.worldy(), relativeSize)){ @@ -160,18 +181,43 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I } } + //simulate falling down + if(dead){ + //less drag when dead + drag = 0.01f; + + //standard fall smoke + if(Mathf.chanceDelta(0.1)){ + Tmp.v1.setToRandomDirection().scl(hitSize); + type.fallEffect.at(x + Tmp.v1.x, y + Tmp.v1.y); + } + + //thruster fall trail + if(Mathf.chanceDelta(0.2)){ + float offset = type.engineOffset/2f + type.engineOffset/2f*elevation; + float range = Mathf.range(type.engineSize); + type.fallThrusterEffect.at( + x + Angles.trnsx(rotation + 180, offset) + Mathf.range(range), + y + Angles.trnsy(rotation + 180, offset) + Mathf.range(range), + Mathf.random() + ); + } + + //move down + elevation -= type.fallSpeed * Time.delta(); + + if(isGrounded()){ + destroy(); + } + } + Tile tile = tileOn(); Floor floor = floorOn(); - if(tile != null && isGrounded()){ + if(tile != null && isGrounded() && !type.hovering){ //unit block update - if(tile.entity != null){ - tile.entity.unitOn(this); - } - - //kill when stuck in wall - if(tile.solid()){ - kill(); + if(tile.build != null){ + tile.build.unitOn(base()); } //apply damage @@ -180,18 +226,62 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I } } - controller.update(); + //AI only updates on the server + if(!net.client() && !dead){ + controller.updateUnit(); + } //remove units spawned by the core if(spawnedByCore && !isPlayer()){ - Fx.unitDespawn.at(x, y, 0, this); - remove(); + Call.unitDespawn(base()); } } + /** @return a preview icon for this unit. */ + public TextureRegion icon(){ + return type.icon(Cicon.full); + } + + /** Actually destroys the unit, removing it and creating explosions. **/ + public void destroy(){ + float explosiveness = 2f + item().explosiveness * stack().amount; + float flammability = item().flammability * stack().amount; + Damage.dynamicExplosion(x, y, flammability, explosiveness, 0f, bounds() / 2f, Pal.darkFlame); + + float shake = hitSize / 3f; + + Effects.scorch(x, y, (int)(hitSize / 5)); + Fx.explosion.at(this); + Effects.shake(shake, shake, this); + type.deathSound.at(this); + + Events.fire(new UnitDestroyEvent(base())); + + if(explosiveness > 7f && isLocal()){ + Events.fire(Trigger.suicideBomb); + } + + //if this unit crash landed (was flying), damage stuff in a radius + if(type.flying){ + Damage.damage(team,x, y, hitSize * 1.1f, hitSize * type.crashDamageMultiplier, true, false, true); + } + + if(!headless){ + for(int i = 0; i < type.wreckRegions.length; i++){ + if(type.wreckRegions[i].found()){ + float range = type.hitsize/4f; + Tmp.v1.rnd(range); + Effects.decal(type.wreckRegions[i], x + Tmp.v1.x, y + Tmp.v1.y, rotation - 90); + } + } + } + + remove(); + } + @Override public void display(Table table){ - type.display(this, table); + type.display(base(), table); } @Override @@ -201,49 +291,36 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I @Override public void draw(){ - type.draw(this); + type.draw(base()); } @Override public boolean isPlayer(){ - return controller instanceof Playerc; + return controller instanceof Player; } @Nullable - public Playerc getPlayer(){ - return isPlayer() ? (Playerc)controller : null; + public Player getPlayer(){ + return isPlayer() ? (Player)controller : null; } @Override public void killed(){ - float explosiveness = 2f + item().explosiveness * stack().amount; - float flammability = item().flammability * stack().amount; - Damage.dynamicExplosion(x, y, flammability, explosiveness, 0f, bounds() / 2f, Pal.darkFlame); + health = 0; + dead = true; - Effects.scorch(x, y, (int)(hitSize() / 5)); - Fx.explosion.at(this); - Effects.shake(2f, 2f, this); - type.deathSound.at(this); - - Events.fire(new UnitDestroyEvent(this)); - - if(explosiveness > 7f && isLocal()){ - Events.fire(Trigger.suicideBomb); + //don't waste time when the unit is already on the ground, just destroy it + if(isGrounded()){ + destroy(); } } @Override - public boolean canMine(Item item){ - return type.drillTier >= item.hardness; - } + @Replace + public void kill(){ + if(dead || net.client()) return; - @Override - public float miningSpeed(){ - return type.mineSpeed; - } - - @Override - public boolean offloadImmediately(){ - return false; + //deaths are synced; this calls killed() + Call.unitDeath(base()); } } diff --git a/core/src/mindustry/entities/comp/WaterMoveComp.java b/core/src/mindustry/entities/comp/WaterMoveComp.java index 07c607f6ab..f351ee74b1 100644 --- a/core/src/mindustry/entities/comp/WaterMoveComp.java +++ b/core/src/mindustry/entities/comp/WaterMoveComp.java @@ -17,9 +17,7 @@ abstract class WaterMoveComp implements Posc, Velc, Hitboxc, Flyingc{ @Override public void move(float cx, float cy){ if(isGrounded()){ - if(!EntityCollisions.waterSolid(tileX(), tileY())){ - collisions.move(this, cx, cy, EntityCollisions::waterSolid); - } + collisions.moveCheck(this, cx, cy, EntityCollisions::waterSolid); }else{ x += cx; y += cy; diff --git a/core/src/mindustry/entities/comp/WeaponsComp.java b/core/src/mindustry/entities/comp/WeaponsComp.java index 9eebad693f..d815a4d02a 100644 --- a/core/src/mindustry/entities/comp/WeaponsComp.java +++ b/core/src/mindustry/entities/comp/WeaponsComp.java @@ -17,12 +17,12 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc{ @Import float x, y, rotation; /** minimum cursor distance from unit, fixes 'cross-eyed' shooting */ - static final float minAimDst = 20f; + static final float minAimDst = 18f; /** temporary weapon sequence number */ static int sequenceNum = 0; /** weapon mount array, never null */ - @ReadOnly transient WeaponMount[] mounts = {}; + @SyncLocal WeaponMount[] mounts = {}; @ReadOnly transient float range, aimX, aimY; @ReadOnly transient boolean isRotate; boolean isShooting; @@ -84,44 +84,50 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc{ Weapon weapon = mount.weapon; mount.reload = Math.max(mount.reload - Time.delta(), 0); + //flip weapon shoot side for alternating weapons at half reload + if(weapon.otherSide != -1 && weapon.alternate && mount.side == weapon.flipSprite && + mount.reload + Time.delta() > weapon.reload/2f && mount.reload <= weapon.reload/2f){ + mounts[weapon.otherSide].side = !mounts[weapon.otherSide].side; + mount.side = !mount.side; + } + //rotate if applicable if(weapon.rotate && (mount.rotate || mount.shoot)){ - float axisXOffset = weapon.mirror ? 0f : weapon.x; - float axisX = this.x + Angles.trnsx(rotation, axisXOffset, weapon.y), - axisY = this.y + Angles.trnsy(rotation, axisXOffset, weapon.y); + float axisX = this.x + Angles.trnsx(rotation - 90, weapon.x, weapon.y), + axisY = this.y + Angles.trnsy(rotation - 90, weapon.x, weapon.y); - mount.targetRotation = Angles.angle(axisX, axisY, mount.aimX, mount.aimY) - rotation(); + mount.targetRotation = Angles.angle(axisX, axisY, mount.aimX, mount.aimY) - rotation; mount.rotation = Angles.moveToward(mount.rotation, mount.targetRotation, weapon.rotateSpeed * Time.delta()); }else{ mount.rotation = 0; mount.targetRotation = angleTo(mount.aimX, mount.aimY); } - if(mount.shoot && (ammo > 0 || !state.rules.unitAmmo || team().rules().infiniteAmmo)){ + //shoot if applicable + if(mount.shoot && //must be shooting + (ammo > 0 || !state.rules.unitAmmo || team().rules().infiniteAmmo) && //check ammo + (!weapon.alternate || mount.side == weapon.flipSprite) && + mount.reload <= 0.0001f && //reload has to be 0 + Angles.within(weapon.rotate ? mount.rotation : this.rotation, mount.targetRotation, mount.weapon.shootCone) //has to be within the cone + ){ + float rotation = this.rotation - 90; + float weaponRotation = rotation + (weapon.rotate ? mount.rotation : 0); - //shoot if applicable - if(mount.reload <= 0.0001f && Angles.within(weapon.rotate ? mount.rotation : this.rotation, mount.targetRotation, mount.weapon.shootCone)){ - for(int i : (weapon.mirror && !weapon.alternate ? Mathf.signs : Mathf.one)){ - i *= Mathf.sign(weapon.flipped) * (mount.weapon.mirror ? Mathf.sign(mount.side) : 1); + //m a t h - //m a t h - float weaponRotation = rotation + (weapon.rotate ? mount.rotation : 0); - float mountX = this.x + Angles.trnsx(rotation, weapon.x * i, weapon.y), - mountY = this.y + Angles.trnsy(rotation, weapon.x * i, weapon.y); - float shootX = mountX + Angles.trnsx(weaponRotation, weapon.shootX * i, weapon.shootY), - shootY = mountY + Angles.trnsy(weaponRotation, weapon.shootX * i, weapon.shootY); - float shootAngle = weapon.rotate ? weaponRotation + 90 : Angles.angle(shootX, shootY, mount.aimX, mount.aimY) + (this.rotation - angleTo(mount.aimX, mount.aimY)); + float mountX = this.x + Angles.trnsx(rotation, weapon.x, weapon.y), + mountY = this.y + Angles.trnsy(rotation, weapon.x, weapon.y); + float shootX = mountX + Angles.trnsx(weaponRotation, weapon.shootX, weapon.shootY), + shootY = mountY + Angles.trnsy(weaponRotation, weapon.shootX, weapon.shootY); + float shootAngle = weapon.rotate ? weaponRotation + 90 : Angles.angle(shootX, shootY, mount.aimX, mount.aimY) + (this.rotation - angleTo(mount.aimX, mount.aimY)); - shoot(weapon, shootX, shootY, mount.aimX, mount.aimY, shootAngle, -i); - } + shoot(weapon, shootX, shootY, mount.aimX, mount.aimY, shootAngle, Mathf.sign(weapon.x)); - if(mount.weapon.mirror) mount.side = !mount.side; - mount.reload = weapon.reload; + mount.reload = weapon.reload; - ammo --; - if(ammo < 0) ammo = 0; - } + ammo--; + if(ammo < 0) ammo = 0; } } } @@ -145,24 +151,18 @@ abstract class WeaponsComp implements Teamc, Posc, Rotc{ Angles.shotgun(weapon.shots, weapon.spacing, rotation, f -> bullet(weapon, x, y, f + Mathf.range(weapon.inaccuracy), lifeScl)); } - Tmp.v1.trns(rotation + 180f, ammo.recoil); - if(this instanceof Velc){ - //TODO apply force? - ((Velc)this).vel().add(Tmp.v1); + ((Velc)this).vel().add(Tmp.v1.trns(rotation + 180f, ammo.recoil)); } - - Tmp.v1.trns(rotation, 3f); boolean parentize = ammo.keepVelocity; Effects.shake(weapon.shake, weapon.shake, x, y); weapon.ejectEffect.at(x, y, rotation * side); - ammo.shootEffect.at(x + Tmp.v1.x, y + Tmp.v1.y, rotation, parentize ? this : null); - ammo.smokeEffect.at(x + Tmp.v1.x, y + Tmp.v1.y, rotation, parentize ? this : null); + ammo.shootEffect.at(x, y, rotation, parentize ? this : null); + ammo.smokeEffect.at(x, y, rotation, parentize ? this : null); } private void bullet(Weapon weapon, float x, float y, float angle, float lifescl){ - Tmp.v1.trns(angle, 3f); - weapon.bullet.create(this, team(), x + Tmp.v1.x, y + Tmp.v1.y, angle, (1f - weapon.velocityRnd) + Mathf.random(weapon.velocityRnd), lifescl); + weapon.bullet.create(this, team(), x, y, angle, (1f - weapon.velocityRnd) + Mathf.random(weapon.velocityRnd), lifescl); } } diff --git a/core/src/mindustry/entities/units/AIController.java b/core/src/mindustry/entities/units/AIController.java index 7e72c3f950..3a9d43e2b2 100644 --- a/core/src/mindustry/entities/units/AIController.java +++ b/core/src/mindustry/entities/units/AIController.java @@ -14,7 +14,7 @@ public class AIController implements UnitController{ protected static final Vec2 vec = new Vec2(); protected static final int timerTarget = 0; - protected Unitc unit; + protected Unit unit; protected Teamc target; protected Interval timer = new Interval(4); @@ -23,13 +23,13 @@ public class AIController implements UnitController{ } protected void targetClosestAllyFlag(BlockFlag flag){ - Tile target = Geometry.findClosest(unit.x(), unit.y(), indexer.getAllied(unit.team(), flag)); - if(target != null) this.target = target.entity; + Tile target = Geometry.findClosest(unit.x, unit.y, indexer.getAllied(unit.team, flag)); + if(target != null) this.target = target.build; } protected void targetClosestEnemyFlag(BlockFlag flag){ - Tile target = Geometry.findClosest(unit.x(), unit.y(), indexer.getEnemy(unit.team(), flag)); - if(target != null) this.target = target.entity; + Tile target = Geometry.findClosest(unit.x, unit.y, indexer.getEnemy(unit.team, flag)); + if(target != null) this.target = target.build; } protected boolean retarget(){ @@ -37,8 +37,7 @@ public class AIController implements UnitController{ } protected void targetClosest(){ - //TODO optimize! - Teamc newTarget = Units.closestTarget(unit.team(), unit.x(), unit.y(), Math.max(unit.range(), unit.type().range), u -> (unit.type().targetAir && u.isFlying()) || (unit.type().targetGround && !u.isFlying())); + Teamc newTarget = Units.closestTarget(unit.team, unit.x, unit.y, Math.max(unit.range(), unit.type().range), u -> (unit.type().targetAir && u.isFlying()) || (unit.type().targetGround && !u.isFlying())); if(newTarget != null){ target = newTarget; } @@ -49,13 +48,15 @@ public class AIController implements UnitController{ } @Override - public void unit(Unitc unit){ + public void unit(Unit unit){ + if(this.unit == unit) return; + this.unit = unit; init(); } @Override - public Unitc unit(){ + public Unit unit(){ return unit; } } diff --git a/core/src/mindustry/entities/units/UnitController.java b/core/src/mindustry/entities/units/UnitController.java index 03b5d1b989..63aec52ee3 100644 --- a/core/src/mindustry/entities/units/UnitController.java +++ b/core/src/mindustry/entities/units/UnitController.java @@ -2,24 +2,27 @@ package mindustry.entities.units; import mindustry.gen.*; -//TODO rename public interface UnitController{ - void unit(Unitc unit); - Unitc unit(); + void unit(Unit unit); + Unit unit(); + + default boolean isValidController(){ + return true; + } default void command(UnitCommand command){ } - default void update(){ + default void updateUnit(){ } - default void removed(Unitc unit){ + default void removed(Unit unit){ } - default boolean isBeingControlled(Unitc player){ + default boolean isBeingControlled(Unit player){ return false; } } diff --git a/core/src/mindustry/entities/units/WeaponMount.java b/core/src/mindustry/entities/units/WeaponMount.java index 882c850aa0..89becb6dcf 100644 --- a/core/src/mindustry/entities/units/WeaponMount.java +++ b/core/src/mindustry/entities/units/WeaponMount.java @@ -13,12 +13,12 @@ public class WeaponMount{ public float targetRotation; /** aiming position in world coordinates */ public float aimX, aimY; - /** side that's being shot - only valid for mirrors */ - public boolean side; /** whether to shoot right now */ public boolean shoot = false; /** whether to rotate to face the target right now */ public boolean rotate = false; + /** extra state for alternating weapons */ + public boolean side; public WeaponMount(Weapon weapon){ this.weapon = weapon; diff --git a/core/src/mindustry/game/DefaultWaves.java b/core/src/mindustry/game/DefaultWaves.java index eac0714591..f99049f41a 100644 --- a/core/src/mindustry/game/DefaultWaves.java +++ b/core/src/mindustry/game/DefaultWaves.java @@ -22,7 +22,7 @@ public class DefaultWaves{ unitScaling = 1.5f; }}, - new SpawnGroup(UnitTypes.wraith){{ + new SpawnGroup(UnitTypes.flare){{ begin = 12; end = 16; unitScaling = 1f; @@ -72,7 +72,7 @@ public class DefaultWaves{ effect = StatusEffects.overdrive; }}, - new SpawnGroup(UnitTypes.wraith){{ + new SpawnGroup(UnitTypes.flare){{ begin = 16; unitScaling = 1; spacing = 2; @@ -120,14 +120,14 @@ public class DefaultWaves{ end = 130; }}, - new SpawnGroup(UnitTypes.ghoul){{ + new SpawnGroup(UnitTypes.horizon){{ begin = 40; unitAmount = 2; spacing = 2; unitScaling = 2; }}, - new SpawnGroup(UnitTypes.wraith){{ + new SpawnGroup(UnitTypes.flare){{ begin = 50; unitAmount = 4; unitScaling = 3; @@ -135,7 +135,7 @@ public class DefaultWaves{ effect = StatusEffects.overdrive; }}, - new SpawnGroup(UnitTypes.revenant){{ + new SpawnGroup(UnitTypes.zenith){{ begin = 50; unitAmount = 2; unitScaling = 3; @@ -143,21 +143,21 @@ public class DefaultWaves{ max = 16; }}, - new SpawnGroup(UnitTypes.ghoul){{ + new SpawnGroup(UnitTypes.horizon){{ begin = 53; unitAmount = 2; unitScaling = 3; spacing = 4; }}, - new SpawnGroup(UnitTypes.eruptor){{ + new SpawnGroup(UnitTypes.atrax){{ begin = 31; unitAmount = 4; unitScaling = 1; spacing = 3; }}, - new SpawnGroup(UnitTypes.chaosArray){{ + new SpawnGroup(UnitTypes.siegeArray){{ begin = 41; unitAmount = 1; unitScaling = 1; @@ -171,14 +171,14 @@ public class DefaultWaves{ spacing = 40; }}, - new SpawnGroup(UnitTypes.lich){{ + new SpawnGroup(UnitTypes.antumbra){{ begin = 131; unitAmount = 1; unitScaling = 1; spacing = 40; }}, - new SpawnGroup(UnitTypes.ghoul){{ + new SpawnGroup(UnitTypes.horizon){{ begin = 90; unitAmount = 2; unitScaling = 3; diff --git a/core/src/mindustry/game/EventType.java b/core/src/mindustry/game/EventType.java index cad55d7931..8915a6917b 100644 --- a/core/src/mindustry/game/EventType.java +++ b/core/src/mindustry/game/EventType.java @@ -32,7 +32,6 @@ public class EventType{ update } - public static class TurnEvent{} public static class WinEvent{} public static class LoseEvent{} public static class LaunchEvent{} @@ -42,11 +41,11 @@ public class EventType{ public static class SaveLoadEvent{} public static class ClientCreateEvent{} public static class ServerLoadEvent{} - public static class ContentReloadEvent{} public static class DisposeEvent{} public static class PlayEvent{} public static class ResetEvent{} public static class WaveEvent{} + public static class TurnEvent{} /** Called when the player places a line, mobile or desktop.*/ public static class LineConfirmEvent{} /** Called when a turret recieves ammo, but only when the tutorial is active! */ @@ -60,6 +59,15 @@ public class EventType{ /** Called when a game begins and the world is loaded. */ public static class WorldLoadEvent{} + /** Called when a sector is destroyed by waves when you're not there. */ + public static class SectorLoseEvent{ + public final Sector sector; + + public SectorLoseEvent(Sector sector){ + this.sector = sector; + } + } + public static class LaunchItemEvent{ public final ItemStack stack; @@ -70,20 +78,20 @@ public class EventType{ public static class CommandIssueEvent{ - public final Tilec tile; + public final Building tile; public final UnitCommand command; - public CommandIssueEvent(Tilec tile, UnitCommand command){ + public CommandIssueEvent(Building tile, UnitCommand command){ this.tile = tile; this.command = command; } } public static class PlayerChatEvent{ - public final Playerc player; + public final Player player; public final String message; - public PlayerChatEvent(Playerc player, String message){ + public PlayerChatEvent(Player player, String message){ this.player = player; this.message = message; } @@ -121,12 +129,12 @@ public class EventType{ /** Called when the player withdraws items from a block. */ public static class WithdrawEvent{ - public final Tilec tile; - public final Playerc player; + public final Building tile; + public final Player player; public final Item item; public final int amount; - public WithdrawEvent(Tilec tile, Playerc player, Item item, int amount){ + public WithdrawEvent(Building tile, Player player, Item item, int amount){ this.tile = tile; this.player = player; this.item = item; @@ -136,12 +144,12 @@ public class EventType{ /** Called when a player deposits items to a block.*/ public static class DepositEvent{ - public final Tilec tile; - public final Playerc player; + public final Building tile; + public final Player player; public final Item item; public final int amount; - public DepositEvent(Tilec tile, Playerc player, Item item, int amount){ + public DepositEvent(Building tile, Player player, Item item, int amount){ this.tile = tile; this.player = player; this.item = item; @@ -151,10 +159,10 @@ public class EventType{ /** Called when the player taps a block. */ public static class TapEvent{ - public final Tilec tile; - public final Playerc player; + public final Building tile; + public final Player player; - public TapEvent(Tilec tile, Playerc player){ + public TapEvent(Building tile, Player player){ this.tile = tile; this.player = player; } @@ -162,11 +170,11 @@ public class EventType{ /** Called when the player sets a specific block. */ public static class TapConfigEvent{ - public final Tilec tile; - public final Playerc player; + public final Building tile; + public final Player player; public final Object value; - public TapConfigEvent(Tilec tile, Playerc player, Object value){ + public TapConfigEvent(Building tile, Player player, Object value){ this.tile = tile; this.player = player; this.value = value; @@ -182,10 +190,10 @@ public class EventType{ } /** Called from the logic thread. Do not access graphics here! */ - public static class TileChangeEvent{ + public static class BuildinghangeEvent{ public final Tile tile; - public TileChangeEvent(Tile tile){ + public BuildinghangeEvent(Tile tile){ this.tile = tile; } } @@ -234,10 +242,10 @@ public class EventType{ public static class BlockBuildEndEvent{ public final Tile tile; public final Team team; - public final @Nullable Unitc unit; + public final @Nullable Unit unit; public final boolean breaking; - public BlockBuildEndEvent(Tile tile, @Nullable Unitc unit, Team team, boolean breaking){ + public BlockBuildEndEvent(Tile tile, @Nullable Unit unit, Team team, boolean breaking){ this.tile = tile; this.team = team; this.unit = unit; @@ -274,26 +282,26 @@ public class EventType{ } public static class UnitDestroyEvent{ - public final Unitc unit; + public final Unit unit; - public UnitDestroyEvent(Unitc unit){ + public UnitDestroyEvent(Unit unit){ this.unit = unit; } } public static class UnitCreateEvent{ - public final Unitc unit; + public final Unit unit; - public UnitCreateEvent(Unitc unit){ + public UnitCreateEvent(Unit unit){ this.unit = unit; } } public static class UnitChangeEvent{ - public final Playerc player; - public final Unitc unit; + public final Player player; + public final Unit unit; - public UnitChangeEvent(Playerc player, Unitc unit){ + public UnitChangeEvent(Player player, Unit unit){ this.player = player; this.unit = unit; } @@ -301,42 +309,42 @@ public class EventType{ /** Called after connecting; when a player recieves world data and is ready to play.*/ public static class PlayerJoin{ - public final Playerc player; + public final Player player; - public PlayerJoin(Playerc player){ + public PlayerJoin(Player player){ this.player = player; } } /** Called when a player connects, but has not joined the game yet.*/ public static class PlayerConnect{ - public final Playerc player; + public final Player player; - public PlayerConnect(Playerc player){ + public PlayerConnect(Player player){ this.player = player; } } public static class PlayerLeave{ - public final Playerc player; + public final Player player; - public PlayerLeave(Playerc player){ + public PlayerLeave(Player player){ this.player = player; } } public static class PlayerBanEvent{ - public final Playerc player; + public final Player player; - public PlayerBanEvent(Playerc player){ + public PlayerBanEvent(Player player){ this.player = player; } } public static class PlayerUnbanEvent{ - public final Playerc player; + public final Player player; - public PlayerUnbanEvent(Playerc player){ + public PlayerUnbanEvent(Player player){ this.player = player; } } diff --git a/core/src/mindustry/game/Rules.java b/core/src/mindustry/game/Rules.java index f41a5bc6e0..83b0c67e6a 100644 --- a/core/src/mindustry/game/Rules.java +++ b/core/src/mindustry/game/Rules.java @@ -134,16 +134,16 @@ public class Rules{ final TeamRule[] values = new TeamRule[Team.all.length]; public TeamRule get(Team team){ - TeamRule out = values[team.uid]; - if(out == null) values[team.uid] = (out = new TeamRule()); + TeamRule out = values[team.id]; + if(out == null) values[team.id] = (out = new TeamRule()); return out; } @Override public void write(Json json){ for(Team team : Team.all){ - if(values[team.uid] != null){ - json.writeValue(team.uid + "", values[team.uid], TeamRule.class); + if(values[team.id] != null){ + json.writeValue(team.id + "", values[team.id], TeamRule.class); } } } diff --git a/core/src/mindustry/game/Schematic.java b/core/src/mindustry/game/Schematic.java index 7c33b2726b..01088826bb 100644 --- a/core/src/mindustry/game/Schematic.java +++ b/core/src/mindustry/game/Schematic.java @@ -9,7 +9,10 @@ import mindustry.content.*; import mindustry.mod.Mods.*; import mindustry.type.*; import mindustry.world.*; +import mindustry.world.blocks.power.*; import mindustry.world.blocks.storage.*; +import mindustry.world.consumers.*; +import mindustry.world.meta.*; import static mindustry.Vars.*; @@ -28,12 +31,22 @@ public class Schematic implements Publishable, Comparable{ this.height = height; } + public float powerProduction(){ + return tiles.sumf(s -> s.block instanceof PowerGenerator ? ((PowerGenerator)s.block).powerProduction : 0f); + } + + public float powerConsumption(){ + return tiles.sumf(s -> s.block.consumes.has(ConsumeType.power) ? s.block.consumes.getPower().usage : 0f); + } + public Seq requirements(){ IntIntMap amounts = new IntIntMap(); tiles.each(t -> { + if(t.block.buildVisibility == BuildVisibility.hidden) return; + for(ItemStack stack : t.block.requirements){ - amounts.getAndIncrement(stack.item.id, 0, stack.amount); + amounts.increment(stack.item.id, stack.amount); } }); Seq stacks = new Seq<>(); diff --git a/core/src/mindustry/game/Schematics.java b/core/src/mindustry/game/Schematics.java index 15aa953a20..5ddc9bb9da 100644 --- a/core/src/mindustry/game/Schematics.java +++ b/core/src/mindustry/game/Schematics.java @@ -55,6 +55,7 @@ public class Schematics implements Loadable{ private Seq all = new Seq<>(); private OrderedMap previews = new OrderedMap<>(); private ObjectSet errored = new ObjectSet<>(); + private ObjectMap> loadouts = new ObjectMap<>(); private FrameBuffer shadowBuffer; private Texture errorTexture; private long lastClearTime; @@ -69,12 +70,6 @@ public class Schematics implements Loadable{ } }); - Events.on(ContentReloadEvent.class, event -> { - previews.each((schem, m) -> m.dispose()); - previews.clear(); - load(); - }); - Events.on(ClientLoadEvent.class, event -> { Pixmap pixmap = Core.atlas.getPixmap("error").crop(); errorTexture = new Texture(pixmap); @@ -91,6 +86,8 @@ public class Schematics implements Loadable{ public void load(){ all.clear(); + loadLoadouts(); + for(Fi file : schematicDirectory.list()){ loadFile(file); } @@ -115,6 +112,10 @@ public class Schematics implements Loadable{ bases.load(); } + private void loadLoadouts(){ + Seq.with(Loadouts.basicShard, Loadouts.basicFoundation, Loadouts.basicNucleus).each(s -> checkLoadout(s,false)); + } + public void overwrite(Schematic target, Schematic newSchematic){ if(previews.containsKey(target)){ previews.get(target).dispose(); @@ -142,6 +143,7 @@ public class Schematics implements Loadable{ try{ Schematic s = read(file); all.add(s); + checkLoadout(s, true); //external file from workshop if(!s.file.parent().equals(schematicDirectory)){ @@ -281,6 +283,22 @@ public class Schematics implements Loadable{ .removeAll(s -> !s.block.isVisible() || !s.block.unlockedNow()); } + /** @return all the valid loadouts for a specific core type. */ + public Seq getLoadouts(CoreBlock block){ + return loadouts.get(block, Seq::new); + } + + /** Checks a schematic for deployment validity and adds it to the cache. */ + private void checkLoadout(Schematic s, boolean validate){ + Stile core = s.tiles.find(t -> t.block instanceof CoreBlock); + + //make sure a core exists, and that the schematic is small enough. + if(core == null || (validate && (s.width > core.block.size + maxLoadoutSchematicPad *2 || s.height > core.block.size + maxLoadoutSchematicPad *2))) return; + + //place in the cache + loadouts.get((CoreBlock)core.block, Seq::new).add(s); + } + /** Adds a schematic to the list, also copying it into the files.*/ public void add(Schematic schematic){ all.add(schematic); @@ -292,11 +310,14 @@ public class Schematics implements Loadable{ ui.showException(e); Log.err(e); } + + checkLoadout(schematic, true); all.sort(); } public void remove(Schematic s){ all.remove(s); + loadouts.each((block, seq) -> seq.remove(s)); if(s.file != null){ s.file.delete(); } @@ -324,7 +345,7 @@ public class Schematics implements Loadable{ boolean found = false; for(int cx = x; cx <= x2; cx++){ for(int cy = y; cy <= y2; cy++){ - Tilec linked = world.ent(cx, cy); + Building linked = world.ent(cx, cy); if(linked != null &&linked.block().isVisible() && !(linked.block() instanceof BuildBlock)){ int top = linked.block().size/2; @@ -352,10 +373,10 @@ public class Schematics implements Loadable{ IntSet counted = new IntSet(); for(int cx = ox; cx <= ox2; cx++){ for(int cy = oy; cy <= oy2; cy++){ - Tilec tile = world.ent(cx, cy); + Building tile = world.ent(cx, cy); if(tile != null && !counted.contains(tile.pos()) && !(tile.block() instanceof BuildBlock) - && (tile.block().isVisible() || (tile.block() instanceof CoreBlock && Core.settings.getBool("coreselect")))){ + && (tile.block().isVisible() || (tile.block() instanceof CoreBlock))){ Object config = tile.config(); tiles.add(new Stile(tile.block(), tile.tileX() + offsetX, tile.tileY() + offsetY, config, (byte)tile.rotation())); @@ -378,6 +399,13 @@ public class Schematics implements Loadable{ } } + /** Places the last launch loadout at the coordinates and fills it with the launch resources. */ + public static void placeLaunchLoadout(int x, int y){ + placeLoadout(universe.getLastLoadout(), x, y); + if(world.tile(x, y).build == null) throw new RuntimeException("No core at loadout coordinates!"); + world.tile(x, y).build.items.add(universe.getLaunchResources()); + } + public static void placeLoadout(Schematic schem, int x, int y){ placeLoadout(schem, x, y, state.rules.defaultTeam, Blocks.oreCopper); } @@ -394,8 +422,8 @@ public class Schematics implements Loadable{ tile.rotation(st.rotation); Object config = st.config; - if(tile.entity != null){ - tile.entity.configureAny(config); + if(tile.build != null){ + tile.build.configureAny(config); } if(st.block instanceof Drill){ @@ -414,8 +442,8 @@ public class Schematics implements Loadable{ tile.rotation(st.rotation); Object config = st.config; - if(tile.entity != null){ - tile.entity.configureAny(config); + if(tile.build != null){ + tile.build.configureAny(config); } }); } diff --git a/core/src/mindustry/game/SectorInfo.java b/core/src/mindustry/game/SectorInfo.java index 7361acdad7..b9d7502e6a 100644 --- a/core/src/mindustry/game/SectorInfo.java +++ b/core/src/mindustry/game/SectorInfo.java @@ -3,6 +3,7 @@ package mindustry.game; import arc.math.*; import arc.struct.*; import arc.util.*; +import arc.util.ArcAnnotate.*; import mindustry.content.*; import mindustry.type.*; import mindustry.world.*; @@ -12,10 +13,13 @@ import mindustry.world.modules.*; import static mindustry.Vars.*; public class SectorInfo{ - /** export window size in seconds */ - private static final int exportWindow = 60; + /** average window size in samples */ + private static final int valueWindow = 60; /** refresh period of export in ticks */ private static final float refreshPeriod = 60; + + /** Core input statistics. */ + public ObjectMap production = new ObjectMap<>(); /** Export statistics. */ public ObjectMap export = new ObjectMap<>(); /** Items stored in all cores. */ @@ -26,6 +30,10 @@ public class SectorInfo{ public int storageCapacity = 0; /** Whether a core is available here. */ public boolean hasCore = true; + /** Sector that was launched from. */ + public @Nullable Sector origin; + /** Time spent at this sector. Do not use unless you know what you're doing. */ + public transient float internalTimeSpent; /** Counter refresh state. */ private transient Interval time = new Interval(); @@ -68,20 +76,33 @@ public class SectorInfo{ hasCore = entity != null; bestCoreType = !hasCore ? Blocks.air : state.rules.defaultTeam.cores().max(e -> e.block.size).block; storageCapacity = entity != null ? entity.storageCapacity : 0; + + //update sector's internal time spent counter1 + state.rules.sector.setTimeSpent(internalTimeSpent); } - /** Update averages of various stats. */ + /** Update averages of various stats. + * Called every frame. */ public void update(){ + internalTimeSpent += Time.delta(); + + //time spent exceeds turn duration! + if(internalTimeSpent >= turnDuration && internalTimeSpent - Time.delta() < turnDuration){ + universe.displayTimeEnd(); + } + //create last stored core items if(lastCoreItems == null){ lastCoreItems = new int[content.items().size]; updateCoreDeltas(); } + CoreEntity ent = state.rules.defaultTeam.core(); + //refresh throughput if(time.get(refreshPeriod)){ - CoreEntity ent = state.rules.defaultTeam.core(); + //refresh export export.each((item, stat) -> { //initialize stat after loading if(!stat.loaded){ @@ -98,10 +119,38 @@ public class SectorInfo{ stat.mean = stat.means.rawMean(); }); + //refresh core items + for(Item item : content.items()){ + ExportStat stat = production.get(item, ExportStat::new); + if(!stat.loaded){ + stat.means.fill(stat.mean); + stat.loaded = true; + } + + //get item delta + //TODO is preventing negative production a good idea? + int delta = Math.max((ent == null ? 0 : ent.items.get(item)) - lastCoreItems[item.id], 0); + + //store means + stat.means.add(delta); + stat.mean = stat.means.rawMean(); + } + updateCoreDeltas(); } } + /** @return the items in this sector now, taking into account production and items recieved. */ + public ObjectIntMap getCurrentItems(Sector sector){ + ObjectIntMap map = new ObjectIntMap<>(); + map.putAll(coreItems); + long seconds = sector.getSecondsPassed(); + production.each((item, stat) -> map.increment(item, (int)(stat.mean * seconds))); + //increment based on recieved items + sector.getRecievedItems().each(stack -> map.increment(stack.item, stack.amount)); + return map; + } + private void updateCoreDeltas(){ CoreEntity ent = state.rules.defaultTeam.core(); for(int i = 0; i < lastCoreItems.length; i++){ @@ -117,8 +166,10 @@ public class SectorInfo{ public static class ExportStat{ public transient float counter; - public transient WindowedMean means = new WindowedMean(exportWindow); + public transient WindowedMean means = new WindowedMean(valueWindow); public transient boolean loaded; + + /** mean in terms of items produced per refresh rate (currently, per second) */ public float mean; } } diff --git a/core/src/mindustry/game/SpawnGroup.java b/core/src/mindustry/game/SpawnGroup.java index f3b2ff0756..ad2cf44592 100644 --- a/core/src/mindustry/game/SpawnGroup.java +++ b/core/src/mindustry/game/SpawnGroup.java @@ -60,8 +60,8 @@ public class SpawnGroup implements Serializable{ * Creates a unit, and assigns correct values based on this group's data. * This method does not add() the unit. */ - public Unitc createUnit(Team team, int wave){ - Unitc unit = type.create(team); + public Unit createUnit(Team team, int wave){ + Unit unit = type.create(team); if(effect != null){ unit.apply(effect, 999999f); diff --git a/core/src/mindustry/game/Stats.java b/core/src/mindustry/game/Stats.java index 931baa4dcd..4a03f6199e 100644 --- a/core/src/mindustry/game/Stats.java +++ b/core/src/mindustry/game/Stats.java @@ -39,7 +39,7 @@ public class Stats{ //weigh used fractions float frac = 0f; - Seq obtainable = Seq.select(zone.data.resources, i -> i instanceof Item && ((Item)i).type == ItemType.material).as(); + Seq obtainable = Seq.select(zone.data.resources, i -> i instanceof Item).as(); for(Item item : obtainable){ frac += Mathf.clamp((float)itemsDelivered.get(item, 0) / capacity) / (float)obtainable.size; } diff --git a/core/src/mindustry/game/Team.java b/core/src/mindustry/game/Team.java index 278a603d24..b82e8e1f12 100644 --- a/core/src/mindustry/game/Team.java +++ b/core/src/mindustry/game/Team.java @@ -4,18 +4,17 @@ import arc.*; import arc.graphics.*; import arc.math.*; import arc.struct.*; -import arc.util.*; import arc.util.ArcAnnotate.*; import mindustry.game.Rules.*; import mindustry.game.Teams.*; import mindustry.graphics.*; import mindustry.world.blocks.storage.CoreBlock.*; +import mindustry.world.modules.*; import static mindustry.Vars.*; public class Team implements Comparable{ - public final byte id; - public final int uid; + public final int id; public final Color color; public final Color[] palette; public boolean hasPalette; @@ -52,12 +51,10 @@ public class Team implements Comparable{ protected Team(int id, String name, Color color){ this.name = name; this.color = color; - this.id = (byte)id; + this.id = id; - int us = Pack.u(this.id); - uid = us; - if(us < 6) baseTeams[us] = this; - all[us] = this; + if(id < 6) baseTeams[id] = this; + all[id] = this; palette = new Color[3]; palette[0] = color; @@ -75,12 +72,18 @@ public class Team implements Comparable{ hasPalette = true; } + /** @return the core items for this team, or an empty item module. + * Never add to the resulting item module, as it is mutable. */ + public @NonNull ItemModule items(){ + return core() == null ? ItemModule.empty : core().items; + } + /** @return the team-specific rules. */ public TeamRule rules(){ return state.rules.teams.get(this); } - public Seq enemies(){ + public Team[] enemies(){ return state.teams.enemiesOf(this); } diff --git a/core/src/mindustry/game/Teams.java b/core/src/mindustry/game/Teams.java index fedfe2bb37..592aa9d444 100644 --- a/core/src/mindustry/game/Teams.java +++ b/core/src/mindustry/game/Teams.java @@ -4,7 +4,6 @@ import arc.func.*; import arc.math.geom.*; import arc.struct.*; import arc.util.ArcAnnotate.*; -import arc.util.*; import mindustry.ai.*; import mindustry.gen.*; import mindustry.world.blocks.storage.CoreBlock.*; @@ -23,13 +22,9 @@ public class Teams{ } public @Nullable CoreEntity closestEnemyCore(float x, float y, Team team){ - for(TeamData data : active){ - if(areEnemies(team, data.team)){ - CoreEntity tile = Geometry.findClosest(x, y, data.cores); - if(tile != null){ - return tile; - } - } + for(Team enemy : team.enemies()){ + CoreEntity tile = Geometry.findClosest(x, y, enemy.cores()); + if(tile != null) return tile; } return null; } @@ -38,7 +33,7 @@ public class Teams{ return Geometry.findClosest(x, y, get(team).cores); } - public Seq enemiesOf(Team team){ + public Team[] enemiesOf(Team team){ return get(team).enemies; } @@ -55,10 +50,10 @@ public class Teams{ return false; } - public void eachEnemyCore(Team team, Cons ret){ + public void eachEnemyCore(Team team, Cons ret){ for(TeamData data : active){ if(areEnemies(team, data.team)){ - for(Tilec tile : data.cores){ + for(Building tile : data.cores){ ret.get(tile); } } @@ -67,10 +62,10 @@ public class Teams{ /** Returns team data by type. */ public TeamData get(Team team){ - if(map[Pack.u(team.id)] == null){ - map[Pack.u(team.id)] = new TeamData(team); + if(map[team.id] == null){ + map[team.id] = new TeamData(team); } - return map[Pack.u(team.id)]; + return map[team.id]; } public Seq playerCores(){ @@ -135,20 +130,23 @@ public class Teams{ } for(TeamData data : active){ - data.enemies.clear(); + Seq enemies = new Seq<>(); + for(TeamData other : active){ if(areEnemies(data.team, other.team)){ - data.enemies.add(other.team); + enemies.add(other.team); } } + + data.enemies = enemies.toArray(Team.class); } } public class TeamData{ public final Seq cores = new Seq<>(); - public final Seq enemies = new Seq<>(); public final Team team; public final BaseAI ai; + public Team[] enemies = {}; public Queue blocks = new Queue<>(); public TeamData(Team team){ diff --git a/core/src/mindustry/game/Tutorial.java b/core/src/mindustry/game/Tutorial.java index d9f91623da..cfaa85a84c 100644 --- a/core/src/mindustry/game/Tutorial.java +++ b/core/src/mindustry/game/Tutorial.java @@ -31,7 +31,7 @@ public class Tutorial{ public Tutorial(){ Events.on(BlockBuildEndEvent.class, event -> { if(!event.breaking){ - blocksPlaced.getAndIncrement(event.tile.block(), 0, 1); + blocksPlaced.increment(event.tile.block(), 1); } }); @@ -162,7 +162,7 @@ public class Tutorial{ }, withdraw(() -> event("withdraw")){ void begin(){ - state.teams.playerCores().first().items().add(Items.copper, 10); + state.teams.playerCores().first().items.add(Items.copper, 10); } }, deposit(() -> event("deposit")), @@ -239,7 +239,7 @@ public class Tutorial{ //utility static void placeBlocks(){ - Tilec core = state.teams.playerCores().first(); + Building core = state.teams.playerCores().first(); for(int i = 0; i < blocksToBreak; i++){ world.tile(core.tile().x + blockOffset, core.tile().y + i).remove(); world.tile(core.tile().x + blockOffset, core.tile().y + i).setBlock(Blocks.scrapWall, state.rules.defaultTeam); @@ -247,7 +247,7 @@ public class Tutorial{ } static boolean blocksBroken(){ - Tilec core = state.teams.playerCores().first(); + Building core = state.teams.playerCores().first(); for(int i = 0; i < blocksToBreak; i++){ if(world.tile(core.tile().x + blockOffset, core.tile().y + i).block() == Blocks.scrapWall){ @@ -270,7 +270,7 @@ public class Tutorial{ } static int item(Item item){ - return state.rules.defaultTeam.data().noCores() ? 0 : state.rules.defaultTeam.core().items().get(item); + return state.rules.defaultTeam.data().noCores() ? 0 : state.rules.defaultTeam.core().items.get(item); } static boolean toggled(String name){ diff --git a/core/src/mindustry/game/Universe.java b/core/src/mindustry/game/Universe.java index 7cf7786382..105e2e4da8 100644 --- a/core/src/mindustry/game/Universe.java +++ b/core/src/mindustry/game/Universe.java @@ -4,12 +4,11 @@ import arc.*; import arc.math.*; import arc.struct.*; import arc.util.*; -import mindustry.*; import mindustry.content.*; +import mindustry.core.GameState.*; import mindustry.game.EventType.*; -import mindustry.game.SectorInfo.*; -import mindustry.io.*; import mindustry.type.*; +import mindustry.world.blocks.storage.*; import static mindustry.Vars.*; @@ -18,10 +17,19 @@ public class Universe{ private long seconds; private float secondCounter; private int turn; - private float turnCounter; + + private Schematic lastLoadout; + private Seq lastLaunchResources = new Seq<>(); public Universe(){ load(); + + //update base coverage on capture + Events.on(SectorCaptureEvent.class, e -> { + if(state.isCampaign()){ + state.getSector().planet.updateBaseCoverage(); + } + }); } /** Update regardless of whether the player is in the campaign. */ @@ -30,6 +38,10 @@ public class Universe{ updatePlanet(Planets.sun); } + public int turn(){ + return turn; + } + private void updatePlanet(Planet planet){ planet.position.setZero(); planet.addParentOffset(planet.position); @@ -41,6 +53,14 @@ public class Universe{ } } + public void displayTimeEnd(){ + if(!headless){ + state.set(State.paused); + + ui.announce("Next turn incoming."); + } + } + /** Update planet rotations, global time and relevant state. */ public void update(){ secondCounter += Time.delta() / 60f; @@ -55,13 +75,6 @@ public class Universe{ } } - //update turn state - happens only in-game - turnCounter += Time.delta(); - - if(turnCounter >= turnDuration){ - runTurn(); - } - if(state.hasSector()){ //update sector light float light = state.getSector().getLight(); @@ -73,74 +86,81 @@ public class Universe{ } } - public int[] getTotalExports(){ - int[] exports = new int[Vars.content.items().size]; - - for(Planet planet : content.planets()){ - for(Sector sector : planet.sectors){ - - //ignore the current sector if the player is in it right now - if(sector.hasBase() && !sector.isBeingPlayed()){ - SaveMeta meta = sector.save.meta; - - for(ObjectMap.Entry entry : meta.secinfo.export){ - //total is calculated by items/sec (value) * turn duration in seconds - int total = (int)(entry.value.mean * turnDuration / 60f); - - exports[entry.key.id] += total; - } - } - } - } - - return exports; + public Seq getLaunchResources(){ + lastLaunchResources = Core.settings.getJson("launch-resources", Seq.class, ItemStack.class, Seq::new); + return lastLaunchResources; } - public void runTurns(int amount){ - for(int i = 0; i < amount; i++){ - runTurn(); - } + public void updateLaunchResources(Seq stacks){ + this.lastLaunchResources = stacks; + Core.settings.putJson("launch-resources", ItemStack.class, lastLaunchResources); } - /** Runs a turn once. Resets turn counter. */ + /** Updates selected loadout for future deployment. */ + public void updateLoadout(CoreBlock block, Schematic schem){ + Core.settings.put("lastloadout-" + block.name, schem.file == null ? "" : schem.file.nameWithoutExtension()); + lastLoadout = schem; + } + + public Schematic getLastLoadout(){ + if(lastLoadout == null) lastLoadout = Loadouts.basicShard; + return lastLoadout; + } + + /** @return the last selected loadout for this specific core type. */ + public Schematic getLoadout(CoreBlock core){ + //for tools - schem + if(schematics == null) return Loadouts.basicShard; + + //find last used loadout file name + String file = Core.settings.getString("lastloadout-" + core.name, ""); + + //use default (first) schematic if not found + Seq all = schematics.getLoadouts(core); + Schematic schem = all.find(s -> s.file != null && s.file.nameWithoutExtension().equals(file)); + + return schem == null ? all.first() : schem; + } + + /** Runs possible events. Resets event counter. */ public void runTurn(){ - turn ++; - turnCounter = 0; + turn++; - //TODO EVENTS + a notification + int newSecondsPassed = (int)(turnDuration / 60); - //increment turns passed for sectors with waves - //TODO a turn passing may break the core; detect this, send an event and mark the sector as having no base! + //update relevant sectors for(Planet planet : content.planets()){ for(Sector sector : planet.sectors){ - //attacks happen even for sectors without bases - stuff still gets destroyed - if(!sector.isBeingPlayed() && sector.hasSave() && sector.hasWaves()){ - sector.setTurnsPassed(sector.getTurnsPassed() + 1); + if(sector.hasSave()){ + int spent = (int)(sector.getTimeSpent() / 60); + int actuallyPassed = Math.max(newSecondsPassed - spent, 0); + + //increment seconds passed for this sector by the time that just passed with this turn + if(!sector.isBeingPlayed()){ + sector.setSecondsPassed(sector.getSecondsPassed() + actuallyPassed); + + //check if the sector has been attacked too many times... + if(sector.hasBase() && sector.getSecondsPassed() * 60f > turnDuration * sectorDestructionTurns){ + //fire event for losing the sector + Events.fire(new SectorLoseEvent(sector)); + + //if so, just delete the save for now. it's lost. + //TODO don't delete it later maybe + sector.save.delete(); + sector.save = null; + } + } + + //reset time spent to 0 + sector.setTimeSpent(0f); } } } - - //calculate passive item generation - //TODO make exports only update for sector with items - //TODO items should be added directly to cores! - int[] exports = getTotalExports(); - for(int i = 0; i < exports.length; i++){ - //data.addItem(content.item(i), exports[i]); - } + //TODO events Events.fire(new TurnEvent()); - } - public int getTurn(){ - return turn; - } - - public int getSectorsAttacked(){ - int count = 0; - for(Planet planet : content.planets()){ - count += planet.sectors.count(s -> !s.isBeingPlayed() && s.hasSave() && s.hasWaves()); - } - return count; + save(); } public float secondsMod(float mod, float scale){ @@ -158,13 +178,11 @@ public class Universe{ private void save(){ Core.settings.put("utime", seconds); Core.settings.put("turn", turn); - Core.settings.put("turntime", turnCounter); } private void load(){ seconds = Core.settings.getLong("utime"); turn = Core.settings.getInt("turn"); - turnCounter = Core.settings.getFloat("turntime"); } } diff --git a/core/src/mindustry/graphics/BlockRenderer.java b/core/src/mindustry/graphics/BlockRenderer.java index 5a6b8d5208..dd66dd86e9 100644 --- a/core/src/mindustry/graphics/BlockRenderer.java +++ b/core/src/mindustry/graphics/BlockRenderer.java @@ -33,7 +33,7 @@ public class BlockRenderer implements Disposable{ private float brokenFade = 0f; private FrameBuffer shadows = new FrameBuffer(); private FrameBuffer dark = new FrameBuffer(); - private Seq outArray2 = new Seq<>(); + private Seq outArray2 = new Seq<>(); private Seq shadowEvents = new Seq<>(); private IntSet processedEntities = new IntSet(); private boolean displayStatus = false; @@ -82,7 +82,7 @@ public class BlockRenderer implements Disposable{ dark.end(); }); - Events.on(TileChangeEvent.class, event -> { + Events.on(BuildinghangeEvent.class, event -> { shadowEvents.add(event.tile); int avgx = (int)(camera.position.x / tilesize); @@ -192,27 +192,32 @@ public class BlockRenderer implements Disposable{ Tile tile = world.rawTile(x, y); Block block = tile.block(); //link to center - if(tile.entity != null) tile = tile.entity.tile(); + if(tile.build != null) tile = tile.build.tile(); - if(block != Blocks.air && block.cacheLayer == CacheLayer.normal && (tile.entity == null || !processedEntities.contains(tile.entity.id()))){ + if(block != Blocks.air && block.cacheLayer == CacheLayer.normal && (tile.build == null || !processedEntities.contains(tile.build.id()))){ if(block.expanded || !expanded){ tileview.add(tile); - if(tile.entity != null) processedEntities.add(tile.entity.id()); + if(tile.build != null) processedEntities.add(tile.build.id()); } //lights are drawn even in the expanded range - if(tile.entity != null){ + if(tile.build != null || tile.block().emitLight){ lightview.add(tile); } - if(tile.entity != null && tile.entity.power() != null && tile.entity.power().links.size > 0){ - for(Tilec other : tile.entity.getPowerConnections(outArray2)){ + if(tile.build != null && tile.build.power != null && tile.build.power.links.size > 0){ + for(Building other : tile.build.getPowerConnections(outArray2)){ if(other.block() instanceof PowerNode){ //TODO need a generic way to render connections! tileview.add(other.tile()); } } } } + + //special case for floors + if(block == Blocks.air && tile.floor().emitLight){ + lightview.add(tile); + } } } @@ -229,7 +234,7 @@ public class BlockRenderer implements Disposable{ for(int i = 0; i < tileview.size; i++){ Tile tile = tileview.items[i]; Block block = tile.block(); - Tilec entity = tile.entity; + Building entity = tile.build; Draw.z(Layer.block); @@ -257,15 +262,23 @@ public class BlockRenderer implements Disposable{ } } - //draw lights - for(int i = 0; i < lightview.size; i++){ - Tile tile = lightview.items[i]; - Tilec entity = tile.entity; + if(renderer.lights.enabled()){ + //draw lights + for(int i = 0; i < lightview.size; i++){ + Tile tile = lightview.items[i]; + Building entity = tile.build; - if(entity != null){ - entity.drawLight(); + if(entity != null){ + entity.drawLight(); + }else if(tile.block().emitLight){ + tile.block().drawEnvironmentLight(tile); + }else if(tile.floor().emitLight){ + tile.floor().drawEnvironmentLight(tile); + } } } + + } @Override diff --git a/core/src/mindustry/graphics/CacheLayer.java b/core/src/mindustry/graphics/CacheLayer.java index 5807db7490..00bd578dc4 100644 --- a/core/src/mindustry/graphics/CacheLayer.java +++ b/core/src/mindustry/graphics/CacheLayer.java @@ -2,7 +2,6 @@ package mindustry.graphics; import arc.*; import arc.graphics.*; -import arc.graphics.g2d.*; import arc.graphics.gl.*; import static mindustry.Vars.renderer; diff --git a/core/src/mindustry/graphics/Drawf.java b/core/src/mindustry/graphics/Drawf.java index b64ebc3877..05de2877d8 100644 --- a/core/src/mindustry/graphics/Drawf.java +++ b/core/src/mindustry/graphics/Drawf.java @@ -17,29 +17,6 @@ import static mindustry.Vars.*; public class Drawf{ - //an experiment, to be removed - public static void runes(float x, float y, int[] text){ - int height = 6, width = 5; - float scale = 3; - float th = height * scale, tw = width * scale; - float skewx = width * scale, skewy = 0; - - Draw.color(Pal.accent); - - for(int i = 0; i < text.length; i++){ - float ox = x + i*tw*width; - - for(int j = 0; j < width * height; j++){ - int cx = j % width, cy = j / width; - float rx = ox + cx * tw + skewx * cy, ry = y + cy * th; - - if((text[i] & (1 << j)) != 0){ - Fill.quad(rx, ry, rx + tw, ry, rx + tw + skewx, ry + th + skewy, rx + skewx, ry + th + skewy); - } - } - } - } - public static float text(){ float z = Draw.z(); if(renderer.pixelator.enabled()){ @@ -49,6 +26,10 @@ public class Drawf{ return z; } + public static void light(float x, float y, float radius, Color color, float opacity){ + renderer.lights.add(x, y, radius, color, opacity); + } + public static void light(Team team, float x, float y, float radius, Color color, float opacity){ if(allowLight(team)) renderer.lights.add(x, y, radius, color, opacity); } @@ -73,7 +54,7 @@ public class Drawf{ return team == Team.derelict || team == Vars.player.team() || state.rules.enemyLights; } - public static void selected(Tilec tile, Color color){ + public static void selected(Building tile, Color color){ selected(tile.tile(), color); } @@ -188,11 +169,11 @@ public class Drawf{ Draw.rect(Core.atlas.find("shape-3"), x, y - oy + length / 2f, width, length, width / 2f, oy, rotation - 90); } - public static void construct(Tilec t, UnlockableContent content, float rotation, float progress, float speed, float time){ + public static void construct(Building t, UnlockableContent content, float rotation, float progress, float speed, float time){ construct(t, content.icon(Cicon.full), rotation, progress, speed, time); } - public static void construct(Tilec t, TextureRegion region, float rotation, float progress, float speed, float time){ + public static void construct(Building t, TextureRegion region, float rotation, float progress, float speed, float time){ Shaders.build.region = region; Shaders.build.progress = progress; Shaders.build.color.set(Pal.accent); @@ -200,13 +181,13 @@ public class Drawf{ Shaders.build.time = -time / 20f; Draw.shader(Shaders.build); - Draw.rect(region, t.x(), t.y(), rotation); + Draw.rect(region, t.x, t.y, rotation); Draw.shader(); Draw.color(Pal.accent); Draw.alpha(speed); - Lines.lineAngleCenter(t.x() + Mathf.sin(time, 20f, Vars.tilesize / 2f * t.block().size - 2f), t.y(), 90, t.block().size * Vars.tilesize - 4f); + Lines.lineAngleCenter(t.x + Mathf.sin(time, 20f, Vars.tilesize / 2f * t.block().size - 2f), t.y, 90, t.block().size * Vars.tilesize - 4f); Draw.reset(); } diff --git a/core/src/mindustry/graphics/IndexedRenderer.java b/core/src/mindustry/graphics/IndexedRenderer.java index a82080cd34..60eeace8ed 100644 --- a/core/src/mindustry/graphics/IndexedRenderer.java +++ b/core/src/mindustry/graphics/IndexedRenderer.java @@ -12,29 +12,28 @@ public class IndexedRenderer implements Disposable{ private final static int vsize = 5; private Shader program = new Shader( - Strings.join("\n", - "attribute vec4 " + Shader.positionAttribute + ";", - "attribute vec4 " + Shader.colorAttribute + ";", - "attribute vec2 " + Shader.texcoordAttribute + "0;", - "uniform mat4 u_projTrans;", - "varying vec4 v_color;", - "varying vec2 v_texCoords;", - "", - "void main(){", - " v_color = " + Shader.colorAttribute + ";", - " v_color.a = v_color.a * (255.0/254.0);", - " v_texCoords = " + Shader.texcoordAttribute + "0;", - " gl_Position = u_projTrans * " + Shader.positionAttribute + ";", - "}"), - Strings.join("\n", - "varying lowp vec4 v_color;", - "varying vec2 v_texCoords;", - "uniform sampler2D u_texture;", - "", - "void main(){", - " gl_FragColor = v_color * texture2D(u_texture, v_texCoords);", + "attribute vec4 a_position;\n" + + "attribute vec4 a_color;\n" + + "attribute vec2 a_texCoord0;\n" + + "uniform mat4 u_projTrans;\n" + + "varying vec4 v_color;\n" + + "varying vec2 v_texCoords;\n" + + + "void main(){\n" + + " v_color = a_color;\n" + + " v_color.a = v_color.a * (255.0/254.0);\n" + + " v_texCoords = a_texCoord0;\n" + + " gl_Position = u_projTrans * a_position;\n" + + "}", + + "varying lowp vec4 v_color;\n" + + "varying vec2 v_texCoords;\n" + + "uniform sampler2D u_texture;\n" + + + "void main(){\n" + + " gl_FragColor = v_color * texture2D(u_texture, v_texCoords);\n" + "}" - )); + ); private Mesh mesh; private float[] tmpVerts = new float[vsize * 6]; private float[] vertices; diff --git a/core/src/mindustry/graphics/Layer.java b/core/src/mindustry/graphics/Layer.java index 5736aa19da..87892852f2 100644 --- a/core/src/mindustry/graphics/Layer.java +++ b/core/src/mindustry/graphics/Layer.java @@ -38,6 +38,9 @@ public class Layer{ //power lines power = 70, + //certain multi-legged units + legUnit = 75f, + //darkness over block clusters darkness = 80, diff --git a/core/src/mindustry/graphics/LightRenderer.java b/core/src/mindustry/graphics/LightRenderer.java index b8c93823b4..63cd3f2783 100644 --- a/core/src/mindustry/graphics/LightRenderer.java +++ b/core/src/mindustry/graphics/LightRenderer.java @@ -171,7 +171,7 @@ public class LightRenderer{ } public boolean enabled(){ - return state.rules.lighting; + return state.rules.lighting && state.rules.ambientLight.a > 0.00001f; } public void draw(){ diff --git a/core/src/mindustry/graphics/MenuRenderer.java b/core/src/mindustry/graphics/MenuRenderer.java index e8f8857591..f45e93daf1 100644 --- a/core/src/mindustry/graphics/MenuRenderer.java +++ b/core/src/mindustry/graphics/MenuRenderer.java @@ -30,7 +30,7 @@ public class MenuRenderer implements Disposable{ private float time = 0f; private float flyerRot = 45f; private int flyers = Mathf.chance(0.2) ? Mathf.random(35) : Mathf.random(15); - private UnitType flyerType = Structs.select(UnitTypes.wraith, UnitTypes.wraith, UnitTypes.ghoul, UnitTypes.phantom, UnitTypes.phantom, UnitTypes.revenant); + private UnitType flyerType = Structs.select(UnitTypes.flare, UnitTypes.flare, UnitTypes.horizon, UnitTypes.mono, UnitTypes.poly, UnitTypes.mega, UnitTypes.zenith); public MenuRenderer(){ Time.mark(); diff --git a/core/src/mindustry/graphics/MinimapRenderer.java b/core/src/mindustry/graphics/MinimapRenderer.java index b3d3dc2099..ab95e0f260 100644 --- a/core/src/mindustry/graphics/MinimapRenderer.java +++ b/core/src/mindustry/graphics/MinimapRenderer.java @@ -22,7 +22,7 @@ import static mindustry.Vars.*; public class MinimapRenderer implements Disposable{ private static final float baseSize = 16f; - private final Seq units = new Seq<>(); + private final Seq units = new Seq<>(); private Pixmap pixmap; private Texture texture; private TextureRegion region; @@ -36,7 +36,7 @@ public class MinimapRenderer implements Disposable{ }); //make sure to call on the graphics thread - Events.on(TileChangeEvent.class, event -> Core.app.post(() -> update(event.tile))); + Events.on(BuildinghangeEvent.class, event -> Core.app.post(() -> update(event.tile))); } public Pixmap getPixmap(){ @@ -87,7 +87,7 @@ public class MinimapRenderer implements Disposable{ rect.set((dx - sz) * tilesize, (dy - sz) * tilesize, sz * 2 * tilesize, sz * 2 * tilesize); - for(Unitc unit : units){ + for(Unit unit : units){ float rx = !withLabels ? (unit.x() - rect.x) / rect.width * w : unit.x() / (world.width() * tilesize) * w; float ry = !withLabels ? (unit.y() - rect.y) / rect.width * h : unit.y() / (world.height() * tilesize) * h; @@ -97,9 +97,9 @@ public class MinimapRenderer implements Disposable{ Draw.reset(); //only disable player names in multiplayer - if(withLabels && unit instanceof Playerc && net.active()){ - Playerc pl = (Playerc)unit; - drawLabel(x + rx, y + ry, pl.name(), unit.team().color); + if(withLabels && unit.isPlayer() && net.active()){ + Player pl = unit.getPlayer(); + drawLabel(x + rx, y + ry, pl.name, unit.team().color); } } diff --git a/core/src/mindustry/graphics/OverlayRenderer.java b/core/src/mindustry/graphics/OverlayRenderer.java index 23f5eeaa0f..d191574f1b 100644 --- a/core/src/mindustry/graphics/OverlayRenderer.java +++ b/core/src/mindustry/graphics/OverlayRenderer.java @@ -19,7 +19,7 @@ public class OverlayRenderer{ private static final float spawnerMargin = tilesize*11f; private static final Rect rect = new Rect(); private float buildFade, unitFade; - private Unitc lastSelect; + private Unit lastSelect; public void drawBottom(){ InputHandler input = control.input; @@ -36,12 +36,12 @@ public class OverlayRenderer{ public void drawTop(){ if(Core.settings.getBool("playerindicators")){ - for(Playerc player : Groups.player){ + for(Player player : Groups.player){ if(Vars.player != player && Vars.player.team() == player.team()){ if(!rect.setSize(Core.camera.width * 0.9f, Core.camera.height * 0.9f) - .setCenter(Core.camera.position.x, Core.camera.position.y).contains(player.x(), player.y())){ + .setCenter(Core.camera.position.x, Core.camera.position.y).contains(player.x, player.y)){ - Tmp.v1.set(player.x(), player.y()).sub(Core.camera.position.x, Core.camera.position.y).setLength(indicatorLength); + Tmp.v1.set(player.x, player.y).sub(Core.camera.position.x, Core.camera.position.y).setLength(indicatorLength); Lines.stroke(2f, player.team().color); Lines.lineAngle(Core.camera.position.x + Tmp.v1.x, Core.camera.position.y + Tmp.v1.y, Tmp.v1.angle(), 4f); @@ -67,7 +67,7 @@ public class OverlayRenderer{ InputHandler input = control.input; - Unitc select = input.selectedUnit(); + Unit select = input.selectedUnit(); if(!Core.input.keyDown(Binding.control)) select = null; unitFade = Mathf.lerpDelta(unitFade, Mathf.num(select != null), 0.1f); @@ -79,19 +79,19 @@ public class OverlayRenderer{ if(select instanceof BlockUnitc){ //special selection for block "units" - Fill.square(select.x(), select.y(), ((BlockUnitc)select).tile().block().size * tilesize/2f); + Fill.square(select.x, select.y, ((BlockUnitc)select).tile().block().size * tilesize/2f); }else{ Draw.rect(select.type().icon(Cicon.full), select.x(), select.y(), select.rotation() - 90); } Lines.stroke(unitFade); - Lines.square(select.x(), select.y(), select.hitSize() * 1.5f, Time.time() * 2f); + Lines.square(select.x, select.y, select.hitSize() * 1.5f, Time.time() * 2f); Draw.reset(); } //draw config selected block if(input.frag.config.isShown()){ - Tilec tile = input.frag.config.getSelectedTile(); + Building tile = input.frag.config.getSelectedTile(); tile.drawConfigure(); } @@ -107,9 +107,9 @@ public class OverlayRenderer{ float dst = core.dst(player); if(dst < state.rules.enemyCoreBuildRadius * 2.2f){ Draw.color(Color.darkGray); - Lines.circle(core.x(), core.y() - 2, state.rules.enemyCoreBuildRadius); + Lines.circle(core.x, core.y - 2, state.rules.enemyCoreBuildRadius); Draw.color(Pal.accent, core.team().color, 0.5f + Mathf.absin(Time.time(), 10f, 0.5f)); - Lines.circle(core.x(), core.y(), state.rules.enemyCoreBuildRadius); + Lines.circle(core.x, core.y, state.rules.enemyCoreBuildRadius); } }); } @@ -118,7 +118,7 @@ public class OverlayRenderer{ Draw.color(Color.gray, Color.lightGray, Mathf.absin(Time.time(), 8f, 1f)); for(Tile tile : spawner.getSpawns()){ - if(tile.within(player.x(), player.y(), state.rules.dropZoneRadius + spawnerMargin)){ + if(tile.within(player.x, player.y, state.rules.dropZoneRadius + spawnerMargin)){ Draw.alpha(Mathf.clamp(1f - (player.dst(tile) - state.rules.dropZoneRadius) / spawnerMargin)); Lines.dashCircle(tile.worldx(), tile.worldy(), state.rules.dropZoneRadius); } @@ -129,7 +129,7 @@ public class OverlayRenderer{ //draw selected block if(input.block == null && !Core.scene.hasMouse()){ Vec2 vec = Core.input.mouseWorld(input.getMouseX(), input.getMouseY()); - Tilec tile = world.entWorld(vec.x, vec.y); + Building tile = world.entWorld(vec.x, vec.y); if(tile != null && tile.team() == player.team()){ tile.drawSelect(); @@ -137,7 +137,7 @@ public class OverlayRenderer{ if(Core.input.keyDown(Binding.rotateplaced) && tile.block().rotate && tile.interactable(player.team())){ control.input.drawArrow(tile.block(), tile.tileX(), tile.tileY(), tile.rotation(), true); Draw.color(Pal.accent, 0.3f + Mathf.absin(4f, 0.2f)); - Fill.square(tile.x(), tile.y(), tile.block().size * tilesize/2f); + Fill.square(tile.x, tile.y, tile.block().size * tilesize/2f); Draw.color(); } } @@ -152,12 +152,12 @@ public class OverlayRenderer{ Lines.circle(v.x, v.y, 6 + Mathf.absin(Time.time(), 5f, 1f)); Draw.reset(); - Tilec tile = world.entWorld(v.x, v.y); - if(tile != null && tile.interactable(player.team()) && tile.acceptStack(player.unit().item(), player.unit().stack().amount, player.unit()) > 0){ + Building tile = world.entWorld(v.x, v.y); + if(tile != null && tile.interactable(player.team()) && tile.acceptStack(player.unit().item(), player.unit().stack.amount, player.unit()) > 0){ Lines.stroke(3f, Pal.gray); - Lines.square(tile.x(), tile.y(), tile.block().size * tilesize / 2f + 3 + Mathf.absin(Time.time(), 5f, 1f)); + Lines.square(tile.x, tile.y, tile.block().size * tilesize / 2f + 3 + Mathf.absin(Time.time(), 5f, 1f)); Lines.stroke(1f, Pal.place); - Lines.square(tile.x(), tile.y(), tile.block().size * tilesize / 2f + 2 + Mathf.absin(Time.time(), 5f, 1f)); + Lines.square(tile.x, tile.y, tile.block().size * tilesize / 2f + 2 + Mathf.absin(Time.time(), 5f, 1f)); Draw.reset(); } diff --git a/core/src/mindustry/graphics/Pal.java b/core/src/mindustry/graphics/Pal.java index a7f40ca968..84121a9893 100644 --- a/core/src/mindustry/graphics/Pal.java +++ b/core/src/mindustry/graphics/Pal.java @@ -8,6 +8,8 @@ public class Pal{ items = Color.valueOf("2ea756"), command = Color.valueOf("eab678"), + sap = Color.valueOf("665c9f"), + shield = Color.valueOf("ffd37f").a(0.7f), shieldIn = Color.black.cpy().a(0f), diff --git a/core/src/mindustry/graphics/Shaders.java b/core/src/mindustry/graphics/Shaders.java index 7823a5ee7a..fd418c9673 100644 --- a/core/src/mindustry/graphics/Shaders.java +++ b/core/src/mindustry/graphics/Shaders.java @@ -178,7 +178,6 @@ public class Shaders{ } public static class ShieldShader extends LoadShader{ - public Color color = Pal.accent.cpy(); public ShieldShader(){ super("shield", "screenspace"); @@ -188,12 +187,11 @@ public class Shaders{ public void apply(){ setUniformf("u_dp", Scl.scl(1f)); setUniformf("u_time", Time.time() / Scl.scl(1f)); - setUniformf("u_shieldcolor", color); setUniformf("u_offset", Core.camera.position.x - Core.camera.width / 2, Core.camera.position.y - Core.camera.height / 2); - setUniformf("u_texsize", Core.camera.width, - Core.camera.height); + setUniformf("u_texsize", Core.camera.width, Core.camera.height); + setUniformf("u_invsize", 1f/Core.camera.width, 1f/Core.camera.height); } } diff --git a/core/src/mindustry/graphics/Trail.java b/core/src/mindustry/graphics/Trail.java index 5093194020..e48cdda550 100644 --- a/core/src/mindustry/graphics/Trail.java +++ b/core/src/mindustry/graphics/Trail.java @@ -8,10 +8,16 @@ import arc.struct.*; import arc.util.pooling.*; public class Trail{ - private static final int length = 20; - private Seq points = new Seq<>(); + public int length; + + private final Seq points; private float lastX = -1, lastY = -1; + public Trail(int length){ + this.length = length; + points = new Seq<>(length); + } + public void draw(Color color, float width){ Draw.color(color); diff --git a/core/src/mindustry/graphics/g3d/PlanetGrid.java b/core/src/mindustry/graphics/g3d/PlanetGrid.java index 37a4d1ab15..e4972e3eb7 100644 --- a/core/src/mindustry/graphics/g3d/PlanetGrid.java +++ b/core/src/mindustry/graphics/g3d/PlanetGrid.java @@ -30,7 +30,7 @@ public class PlanetGrid{ PlanetGrid(int size){ this.size = size; - tiles = new Ptile[tileCount(size)]; + tiles = new Ptile[Buildingount(size)]; for(int i = 0; i < tiles.length; i++){ tiles[i] = new Ptile(i, i < 12 ? 5 : 6); } @@ -207,7 +207,7 @@ public class PlanetGrid{ return -1; } - static int tileCount(int size){ + static int Buildingount(int size){ return 10 * Mathf.pow(3, size) + 2; } diff --git a/core/src/mindustry/input/Binding.java b/core/src/mindustry/input/Binding.java index b4bacb68af..7389c18d87 100644 --- a/core/src/mindustry/input/Binding.java +++ b/core/src/mindustry/input/Binding.java @@ -34,7 +34,7 @@ public enum Binding implements KeyBind{ schematic_flip_y(KeyCode.x), schematic_menu(KeyCode.t), - category_prev(KeyCode.comma), + category_prev(KeyCode.comma, "blocks"), category_next(KeyCode.period), block_select_left(KeyCode.left), diff --git a/core/src/mindustry/input/DesktopInput.java b/core/src/mindustry/input/DesktopInput.java index b1c3e14b87..68fe8b32de 100644 --- a/core/src/mindustry/input/DesktopInput.java +++ b/core/src/mindustry/input/DesktopInput.java @@ -13,7 +13,6 @@ import arc.scene.ui.layout.*; import arc.util.ArcAnnotate.*; import arc.util.*; import mindustry.*; -import mindustry.content.*; import mindustry.entities.*; import mindustry.entities.units.*; import mindustry.game.EventType.*; @@ -22,10 +21,9 @@ import mindustry.gen.*; import mindustry.graphics.*; import mindustry.ui.*; import mindustry.world.*; -import mindustry.world.blocks.payloads.*; -import mindustry.world.meta.*; -import static arc.Core.scene; +import static arc.Core.*; +import static mindustry.Vars.net; import static mindustry.Vars.*; import static mindustry.input.PlaceMode.*; @@ -49,8 +47,12 @@ public class DesktopInput extends InputHandler{ @Override public void buildUI(Group group){ group.fill(t -> { - t.bottom().update(() -> t.getColor().a = Mathf.lerpDelta(t.getColor().a, player.builder().isBuilding() ? 1f : 0f, 0.15f)); - t.visible(() -> Core.settings.getBool("hints") && selectRequests.isEmpty()); + t.bottom(); + t.visible(() -> { + t.getColor().a = Mathf.lerpDelta(t.getColor().a, player.builder().isBuilding() ? 1f : 0f, 0.15f); + + return Core.settings.getBool("hints") && selectRequests.isEmpty() && t.getColor().a > 0.01f; + }); t.touchable(() -> t.getColor().a < 0.1f ? Touchable.disabled : Touchable.childrenOnly); t.table(Styles.black6, b -> { b.defaults().left(); @@ -199,9 +201,9 @@ public class DesktopInput extends InputHandler{ if(!scene.hasMouse()){ if(Core.input.keyDown(Binding.control) && Core.input.keyTap(Binding.select)){ - Unitc on = selectedUnit(); + Unit on = selectedUnit(); if(on != null){ - Call.onUnitControl(player, on); + Call.unitControl(player, on); shouldShoot = false; } } @@ -211,13 +213,13 @@ public class DesktopInput extends InputHandler{ updateMovement(player.unit()); if(Core.input.keyDown(Binding.respawn) && !player.unit().spawnedByCore()){ - Call.onUnitClear(player); + Call.unitClear(player); controlledType = null; } } if(Core.input.keyRelease(Binding.select)){ - isShooting = false; + player.shooting = false; } if(state.isGame() && Core.input.keyTap(Binding.minimap) && !scene.hasDialog() && !(scene.getKeyboardFocus() instanceof TextField)){ @@ -244,8 +246,8 @@ public class DesktopInput extends InputHandler{ mode = none; } - if(isShooting && !canShoot()){ - isShooting = false; + if(player.shooting && !canShoot()){ + player.shooting = false; } if(isPlacing() && player.isBuilder()){ @@ -272,8 +274,8 @@ public class DesktopInput extends InputHandler{ Tile cursor = tileAt(Core.input.mouseX(), Core.input.mouseY()); if(cursor != null){ - if(cursor.entity != null){ - cursorType = cursor.entity.getCursor(); + if(cursor.build != null){ + cursorType = cursor.build.getCursor(); } if(isPlacing() || !selectRequests.isEmpty()){ @@ -292,8 +294,8 @@ public class DesktopInput extends InputHandler{ cursorType = ui.unloadCursor; } - if(cursor.entity != null && cursor.interactable(player.team()) && !isPlacing() && Math.abs(Core.input.axisTap(Binding.rotate)) > 0 && Core.input.keyDown(Binding.rotateplaced) && cursor.block().rotate){ - Call.rotateBlock(player, cursor.entity, Core.input.axisTap(Binding.rotate) > 0); + if(cursor.build != null && cursor.interactable(player.team()) && !isPlacing() && Math.abs(Core.input.axisTap(Binding.rotate)) > 0 && Core.input.keyDown(Binding.rotateplaced) && cursor.block().rotate){ + Call.rotateBlock(player, cursor.build, Core.input.axisTap(Binding.rotate) > 0); } } @@ -329,6 +331,19 @@ public class DesktopInput extends InputHandler{ table.button(Icon.paste, Styles.clearPartiali, () -> { ui.schematics.show(); }); + + table.button(Icon.tree, Styles.clearPartiali, () -> { + ui.research.show(); + }).visible(() -> state.isCampaign()); + + table.button(Icon.map, Styles.clearPartiali, () -> { + ui.planet.show(); + }).visible(() -> state.isCampaign()); + + table.button(Icon.up, Styles.clearPartiali, () -> { + ui.planet.show(state.getSector(), player.team().core()); + }).visible(() -> state.isCampaign()) + .disabled(b -> player.team().core() == null || !player.team().core().items.has(player.team().core().block.requirements)); } void pollInput(){ @@ -445,12 +460,12 @@ public class DesktopInput extends InputHandler{ deleting = true; }else if(selected != null){ //only begin shooting if there's no cursor event - if(!tileTapped(selected.entity) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && (player.builder().plans().size == 0 || !player.builder().isBuilding()) && !droppingItem && + if(!tileTapped(selected.build) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && (player.builder().plans().size == 0 || !player.builder().isBuilding()) && !droppingItem && !tryBeginMine(selected) && player.miner().mineTile() == null && !Core.scene.hasKeyboard()){ - isShooting = shouldShoot; + player.shooting = shouldShoot; } }else if(!Core.scene.hasKeyboard()){ //if it's out of bounds, shooting is just fine - isShooting = shouldShoot; + player.shooting = shouldShoot; } }else if(Core.input.keyTap(Binding.deselect) && isPlacing()){ block = null; @@ -494,7 +509,7 @@ public class DesktopInput extends InputHandler{ removeSelection(selectX, selectY, cursorX, cursorY); } - tryDropItems(selected == null ? null : selected.entity, Core.input.mouseWorld().x, Core.input.mouseWorld().y); + tryDropItems(selected == null ? null : selected.build, Core.input.mouseWorld().x, Core.input.mouseWorld().y); if(sreq != null){ if(getRequest(sreq.x, sreq.y, sreq.block.size, sreq) != null){ @@ -546,7 +561,7 @@ public class DesktopInput extends InputHandler{ } } - protected void updateMovement(Unitc unit){ + protected void updateMovement(Unit unit){ boolean omni = !(unit instanceof WaterMovec); boolean legs = unit.isGrounded(); @@ -557,8 +572,8 @@ public class DesktopInput extends InputHandler{ boolean boosted = (unit instanceof Mechc && unit.isFlying()); movement.set(xa, ya).nor().scl(speed); - float mouseAngle = Angles.mouseAngle(unit.x(), unit.y()); - boolean aimCursor = omni && isShooting && unit.type().hasWeapons() && unit.type().faceTarget && !boosted && unit.type().rotateShooting; + float mouseAngle = Angles.mouseAngle(unit.x, unit.y); + boolean aimCursor = omni && player.shooting && unit.type().hasWeapons() && unit.type().faceTarget && !boosted && unit.type().rotateShooting; if(aimCursor){ unit.lookAt(mouseAngle); @@ -571,53 +586,44 @@ public class DesktopInput extends InputHandler{ if(omni){ unit.moveAt(movement); }else{ - unit.moveAt(Tmp.v2.trns(unit.rotation(), movement.len())); + unit.moveAt(Tmp.v2.trns(unit.rotation, movement.len())); if(!movement.isZero() && legs){ unit.vel().rotateTo(movement.angle(), unit.type().rotateSpeed * Time.delta()); } } unit.aim(unit.type().faceTarget ? Core.input.mouseWorld() : Tmp.v1.trns(unit.rotation(), Core.input.mouseWorld().dst(unit)).add(unit.x(), unit.y())); - unit.controlWeapons(true, isShooting && !boosted); + unit.controlWeapons(true, player.shooting && !boosted); - isBoosting = Core.input.keyDown(Binding.boost) && !movement.isZero(); - player.boosting(isBoosting); + player.boosting = Core.input.keyDown(Binding.boost) && !movement.isZero(); + player.mouseX = unit.aimX(); + player.mouseY = unit.aimY(); - //TODO netsync this if(unit instanceof Payloadc){ Payloadc pay = (Payloadc)unit; if(Core.input.keyTap(Binding.pickupCargo) && pay.payloads().size < unit.type().payloadCapacity){ - Unitc target = Units.closest(player.team(), pay.x(), pay.y(), 30f, u -> u.isAI() && u.isGrounded()); + Unit target = Units.closest(player.team(), pay.x(), pay.y(), unit.type().hitsize * 1.1f, u -> u.isAI() && u.isGrounded() && u.mass() < unit.mass()); if(target != null){ - pay.pickup(target); + Call.pickupUnitPayload(player, target); }else if(!pay.hasPayload()){ - Tilec tile = world.entWorld(pay.x(), pay.y()); - if(tile != null && tile.team() == unit.team() && tile.block().synthetic()){ - //pick up block directly - if(tile.block().buildVisibility != BuildVisibility.hidden && tile.block().size <= 2){ - pay.pickup(tile); - }else{ //pick up block payload - Payload taken = tile.takePayload(); - if(taken != null){ - pay.addPayload(taken); - Fx.unitPickup.at(tile); - } - } + Building tile = world.entWorld(pay.x(), pay.y()); + if(tile != null && tile.team() == unit.team){ + Call.pickupBlockPayload(player, tile); } } } if(Core.input.keyTap(Binding.dropCargo)){ + Call.dropPayload(player, player.x, player.y); pay.dropLastPayload(); } } if(unit instanceof Commanderc){ - if(Core.input.keyTap(Binding.command)){ - Call.onUnitCommand(player); + Call.unitCommand(player); } } } diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index 4d50e58c4d..e59784dd0b 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -33,8 +33,10 @@ import mindustry.ui.fragments.*; import mindustry.world.*; import mindustry.world.blocks.*; import mindustry.world.blocks.BuildBlock.*; +import mindustry.world.blocks.payloads.*; import mindustry.world.blocks.power.*; import mindustry.world.blocks.storage.CoreBlock.*; +import mindustry.world.meta.*; import java.util.*; @@ -47,7 +49,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ final static int maxLength = 100; final static Vec2 stackTrns = new Vec2(); final static Rect r1 = new Rect(), r2 = new Rect(); - final static Seq units = new Seq<>(); + final static Seq units = new Seq<>(); /** Distance on the back from where items originate. */ final static float backTrns = 3f; @@ -58,7 +60,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ public int rotation; public boolean droppingItem; public Group uiGroup; - public boolean isShooting, isBuilding = true, buildWasAutoPaused = false, isBoosting = false; + public boolean isBuilding = true, buildWasAutoPaused = false; public @Nullable UnitType controlledType; protected @Nullable Schematic lastSchematic; @@ -85,11 +87,11 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ @Remote(called = Loc.server, unreliable = true) public static void transferItemTo(Item item, int amount, float x, float y, Tile tile){ - if(tile == null || tile.entity == null || tile.entity.items() == null) return; + if(tile == null || tile.build == null || tile.build.items == null) return; for(int i = 0; i < Mathf.clamp(amount / 3, 1, 8); i++){ Time.run(i * 3, () -> createItemTransfer(item, amount, x, y, tile, () -> {})); } - tile.entity.items().add(item, amount); + tile.build.items.add(item, amount); } public static void createItemTransfer(Item item, int amount, float x, float y, Position to, Runnable done){ @@ -104,18 +106,63 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ player.builder().removeBuild(x, y, breaking); } + @Remote(targets = Loc.both, called = Loc.server, forward = true) + public static void pickupUnitPayload(Player player, Unit target){ + Unit unit = player.unit(); + Payloadc pay = (Payloadc)unit; + + if(target.isAI() && target.isGrounded() && pay.payloads().size < unit.type().payloadCapacity + && target.mass() < unit.mass() + && target.within(unit, unit.type().hitsize * 1.5f)){ + pay.pickup(target); + } + } + + @Remote(targets = Loc.both, called = Loc.server, forward = true) + public static void pickupBlockPayload(Player player, Building tile){ + Unit unit = player.unit(); + Payloadc pay = (Payloadc)unit; + + if(tile != null && tile.team() == unit.team && pay.payloads().size < unit.type().payloadCapacity + && unit.within(tile, tilesize * tile.block.size * 1.2f)){ + //pick up block directly + if(tile.block().buildVisibility != BuildVisibility.hidden && tile.block().size <= 2){ + pay.pickup(tile); + }else{ //pick up block payload + Payload taken = tile.takePayload(); + if(taken != null){ + pay.addPayload(taken); + Fx.unitPickup.at(tile); + } + } + } + } + + @Remote(targets = Loc.both, called = Loc.server, forward = true) + public static void dropPayload(Player player, float x, float y){ + Payloadc pay = (Payloadc)player.unit(); + + //allow a slight margin of error + if(pay.within(x, y, tilesize * 2f)){ + float prevx = pay.x(), prevy = pay.y(); + pay.set(x, y); + pay.dropLastPayload(); + pay.set(prevx, prevy); + } + } + @Remote(targets = Loc.client, called = Loc.server) - public static void dropItem(Playerc player, float angle){ - if(net.server() && player.unit().stack().amount <= 0){ + public static void dropItem(Player player, float angle){ + if(net.server() && player.unit().stack.amount <= 0){ throw new ValidateException(player, "Player cannot drop an item."); } - Fx.dropItem.at(player.x(), player.y(), angle, Color.white, player.unit().item()); + Fx.dropItem.at(player.x, player.y, angle, Color.white, player.unit().item()); player.unit().clearItem(); } @Remote(targets = Loc.both, called = Loc.server, forward = true, unreliable = true) - public static void rotateBlock(Playerc player, Tilec tile, boolean direction){ + public static void rotateBlock(Player player, Building tile, boolean direction){ if(net.server() && (!Units.canInteract(player, tile) || !netServer.admins.allowAction(player, ActionType.rotate, tile.tile(), action -> action.rotation = Mathf.mod(tile.rotation() + Mathf.sign(direction), 4)))){ throw new ValidateException(player, "Player cannot rotate a block."); @@ -127,20 +174,20 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } @Remote(targets = Loc.both, forward = true, called = Loc.server) - public static void transferInventory(Playerc player, Tilec tile){ + public static void transferInventory(Player player, Building tile){ if(player == null || tile == null) return; - if(net.server() && (player.unit().stack().amount <= 0 || !Units.canInteract(player, tile) || + if(net.server() && (player.unit().stack.amount <= 0 || !Units.canInteract(player, tile) || !netServer.admins.allowAction(player, ActionType.depositItem, tile.tile(), action -> { - action.itemAmount = player.unit().stack().amount; + action.itemAmount = player.unit().stack.amount; action.item = player.unit().item(); }))){ throw new ValidateException(player, "Player cannot transfer an item."); } Item item = player.unit().item(); - int amount = player.unit().stack().amount; + int amount = player.unit().stack.amount; int accepted = tile.acceptStack(item, amount, player.unit()); - player.unit().stack().amount -= accepted; + player.unit().stack.amount -= accepted; Core.app.post(() -> Events.fire(new DepositEvent(tile, player, item, accepted))); @@ -149,14 +196,14 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ createItemTransfer( item, amount, - player.x() + Angles.trnsx(player.unit().rotation() + 180f, backTrns), player.y() + Angles.trnsy(player.unit().rotation() + 180f, backTrns), - new Vec2(tile.x() + stackTrns.x, tile.y() + stackTrns.y), + player.x + Angles.trnsx(player.unit().rotation + 180f, backTrns), player.y + Angles.trnsy(player.unit().rotation + 180f, backTrns), + new Vec2(tile.x + stackTrns.x, tile.y + stackTrns.y), () -> tile.handleStack(item, accepted, player.unit()) ); } @Remote(targets = Loc.both, called = Loc.server, forward = true) - public static void onTileTapped(Playerc player, Tilec tile){ + public static void tileTapped(Player player, Building tile){ if(tile == null || player == null) return; if(net.server() && (!Units.canInteract(player, tile) || !netServer.admins.allowAction(player, ActionType.tapTile, tile.tile(), action -> {}))) throw new ValidateException(player, "Player cannot tap a tile."); @@ -165,7 +212,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } @Remote(targets = Loc.both, called = Loc.both, forward = true) - public static void onTileConfig(Playerc player, Tilec tile, @Nullable Object value){ + public static void tileConfig(Player player, Building tile, @Nullable Object value){ if(tile == null) return; if(net.server() && (!Units.canInteract(player, tile) || !netServer.admins.allowAction(player, ActionType.configure, tile.tile(), action -> action.config = value))) throw new ValidateException(player, "Player cannot configure a tile."); @@ -174,7 +221,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } @Remote(targets = Loc.both, called = Loc.server, forward = true) - public static void onUnitControl(Playerc player, @Nullable Unitc unit){ + public static void unitControl(Player player, @Nullable Unit unit){ //clear player unit when they possess a core if((unit instanceof BlockUnitc && ((BlockUnitc)unit).tile() instanceof CoreEntity)){ Fx.spawn.at(player); @@ -183,19 +230,19 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ }else if(unit == null){ //just clear the unit (is this used?) player.clearUnit(); //make sure it's AI controlled, so players can't overwrite each other - }else if(unit.isAI() && unit.team() == player.team()){ + }else if(unit.isAI() && unit.team == player.team()){ player.unit(unit); - Time.run(Fx.unitSpirit.lifetime, () -> Fx.unitControl.at(unit.x(), unit.y(), 0f, unit)); + Time.run(Fx.unitSpirit.lifetime, () -> Fx.unitControl.at(unit.x, unit.y, 0f, unit)); if(!player.dead()){ - Fx.unitSpirit.at(player.x(), player.y(), 0f, unit); + Fx.unitSpirit.at(player.x, player.y, 0f, unit); } } } @Remote(targets = Loc.both, called = Loc.server, forward = true) - public static void onUnitClear(Playerc player){ + public static void unitClear(Player player){ //no free core teleports? - if(!player.dead() && player.unit().spawnedByCore()) return; + if(!player.dead() && player.unit().spawnedByCore) return; Fx.spawn.at(player); player.clearUnit(); @@ -203,7 +250,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } @Remote(targets = Loc.both, called = Loc.server, forward = true) - public static void onUnitCommand(Playerc player){ + public static void unitCommand(Player player){ if(player.dead() || !(player.unit() instanceof Commanderc)) return; Commanderc commander = (Commanderc)player.unit(); @@ -212,13 +259,13 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ commander.clearCommand(); }else{ FormationPattern pattern = new SquareFormation(); - Formation formation = new Formation(new Vec3(player.x(), player.y(), player.unit().rotation()), pattern); + Formation formation = new Formation(new Vec3(player.x, player.y, player.unit().rotation), pattern); formation.slotAssignmentStrategy = new DistanceAssignmentStrategy(pattern); units.clear(); Fx.commandSend.at(player); - Units.nearby(player.team(), player.x(), player.y(), 200f, u -> { + Units.nearby(player.team(), player.x, player.y, 200f, u -> { if(u.isAI()){ units.add(u); } @@ -249,7 +296,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } public void update(){ - player.typing(ui.chatfrag.shown()); + player.typing = ui.chatfrag.shown(); if(player.isBuilder()){ player.builder().building(isBuilding); @@ -260,24 +307,24 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } if(controlledType != null && player.dead()){ - Unitc unit = Units.closest(player.team(), player.x(), player.y(), u -> !u.isPlayer() && u.type() == controlledType); + Unit unit = Units.closest(player.team(), player.x, player.y, u -> !u.isPlayer() && u.type() == controlledType); if(unit != null){ - Call.onUnitControl(player, unit); + Call.unitControl(player, unit); } } } public void checkUnit(){ if(controlledType != null){ - Unitc unit = Units.closest(player.team(), player.x(), player.y(), u -> !u.isPlayer() && u.type() == controlledType); + Unit unit = Units.closest(player.team(), player.x, player.y, u -> !u.isPlayer() && u.type() == controlledType); if(unit == null && controlledType == UnitTypes.block){ - unit = world.entWorld(player.x(), player.y()) instanceof ControlBlock ? ((ControlBlock)world.entWorld(player.x(), player.y())).unit() : null; + unit = world.entWorld(player.x, player.y) instanceof ControlBlock ? ((ControlBlock)world.entWorld(player.x, player.y)).unit() : null; } if(unit != null){ if(net.client()){ - Call.onUnitControl(player, unit); + Call.unitControl(player, unit); }else{ unit.controller(player); } @@ -327,7 +374,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ public boolean requestMatches(BuildPlan request){ Tile tile = world.tile(request.x, request.y); - return tile != null && tile.block() instanceof BuildBlock && tile.ent().cblock == request.block; + return tile != null && tile.block() instanceof BuildBlock && tile.bc().cblock == request.block; } public void drawBreaking(int x, int y){ @@ -481,7 +528,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ for(int x = dresult.x; x <= dresult.x2; x++){ for(int y = dresult.y; y <= dresult.y2; y++){ - Tile tile = world.tilec(x, y); + Tile tile = world.Building(x, y); if(tile == null || !validBreak(tile.x, tile.y)) continue; drawBreaking(tile.x, tile.y); @@ -597,7 +644,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ int wx = x1 + x * Mathf.sign(x2 - x1); int wy = y1 + y * Mathf.sign(y2 - y1); - Tile tile = world.tilec(wx, wy); + Tile tile = world.Building(wx, wy); if(tile == null) continue; @@ -663,7 +710,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } /** Handles tile tap events that are not platform specific. */ - boolean tileTapped(@Nullable Tilec tile){ + boolean tileTapped(@Nullable Building tile){ if(tile == null){ frag.inv.hide(); frag.config.hideConfig(); @@ -695,14 +742,14 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ //call tapped event if(!consumed && tile.interactable(player.team())){ - Call.onTileTapped(player, tile); + Call.tileTapped(player, tile); } //consume tap event if necessary if(tile.interactable(player.team()) && tile.block().consumesTap){ consumed = true; }else if(tile.interactable(player.team()) && tile.block().synthetic() && !consumed){ - if(tile.block().hasItems && tile.items().total() > 0){ + if(tile.block().hasItems && tile.items.total() > 0){ frag.inv.showFor(tile); consumed = true; showedInventory = true; @@ -726,7 +773,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } boolean canTapPlayer(float x, float y){ - return player.within(x, y, playerSelectRange) && player.unit().stack().amount > 0; + return player.within(x, y, playerSelectRange) && player.unit().stack.amount > 0; } /** Tries to begin mining a tile, returns true if successful. */ @@ -747,7 +794,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ && tile.block() == Blocks.air && player.dst(tile.worldx(), tile.worldy()) <= miningRange; } - Tilec entAt(float x, float y){ + Building entAt(float x, float y){ return world.ent(tileX(x), tileY(y)); } @@ -796,8 +843,8 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ return Core.input.mouseWorld(getMouseX(), getMouseY()).sub(x, y).angle(); } - public @Nullable Unitc selectedUnit(){ - Unitc unit = Units.closest(player.team(), Core.input.mouseWorld().x, Core.input.mouseWorld().y, 40f, Unitc::isAI); + public @Nullable Unit selectedUnit(){ + Unit unit = Units.closest(player.team(), Core.input.mouseWorld().x, Core.input.mouseWorld().y, 40f, Unit::isAI); if(unit != null){ unit.hitbox(Tmp.r1); Tmp.r1.grow(6f); @@ -806,7 +853,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ } } - Tilec tile = world.entWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y); + Building tile = world.entWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y); if(tile instanceof ControlBlock && tile.team() == player.team()){ return ((ControlBlock)tile).unit(); } @@ -865,15 +912,15 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ return droppingItem; } - public void tryDropItems(@Nullable Tilec tile, float x, float y){ - if(!droppingItem || player.unit().stack().amount <= 0 || canTapPlayer(x, y) || state.isPaused() ){ + public void tryDropItems(@Nullable Building tile, float x, float y){ + if(!droppingItem || player.unit().stack.amount <= 0 || canTapPlayer(x, y) || state.isPaused() ){ droppingItem = false; return; } droppingItem = false; - ItemStack stack = player.unit().stack(); + ItemStack stack = player.unit().stack; if(tile != null && tile.acceptStack(stack.item, stack.amount, player.unit()) > 0 && tile.interactable(player.team()) && tile.block().hasItems && player.unit().stack().amount > 0 && tile.interactable(player.team())){ Call.transferInventory(player, tile); @@ -925,7 +972,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ public void breakBlock(int x, int y){ Tile tile = world.tile(x, y); //TODO hacky - if(tile != null && tile.entity != null) tile = tile.entity.tile(); + if(tile != null && tile.build != null) tile = tile.build.tile(); player.builder().addBuild(new BuildPlan(tile.x, tile.y)); } @@ -1106,7 +1153,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ protected void updateTouch(){ if(Units.invalidateTarget(target, this) && - !(target instanceof Tilec && ((Tilec)target).damaged() && target.isValid() && target.team() == team && mech.canHeal && dst(target) < mech.range && !(((Tilec)target).block instanceof BuildBlock))){ + !(target instanceof Building && ((Building)target).damaged() && target.isValid() && target.team() == team && mech.canHeal && dst(target) < mech.range && !(((Building)target).block instanceof BuildBlock))){ target = null; } @@ -1121,7 +1168,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ if(moveTarget != null && !moveTarget.dead()){ targetX = moveTarget.getX(); targetY = moveTarget.getY(); - boolean tapping = moveTarget instanceof Tilec && moveTarget.team() == team; + boolean tapping = moveTarget instanceof Building && moveTarget.team() == team; attractDst = 0f; if(tapping){ @@ -1130,7 +1177,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ if(dst(moveTarget) <= 2f * Time.delta()){ if(tapping && !dead()){ - Tile tile = ((Tilec)moveTarget).tile; + Tile tile = ((Building)moveTarget).tile; tile.tapped(this); } @@ -1197,7 +1244,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{ mineTile(null); } } - }else if(target.isValid() || (target instanceof Tilec && ((Tilec)target).damaged() && target.team() == team && mech.canHeal && dst(target) < mech.range)){ + }else if(target.isValid() || (target instanceof Building && ((Building)target).damaged() && target.team() == team && mech.canHeal && dst(target) < mech.range)){ //rotate toward and shoot the target if(mech.faceTarget){ rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.2f); diff --git a/core/src/mindustry/input/MobileInput.java b/core/src/mindustry/input/MobileInput.java index 8320bb47d1..75c468f1fd 100644 --- a/core/src/mindustry/input/MobileInput.java +++ b/core/src/mindustry/input/MobileInput.java @@ -68,13 +68,13 @@ public class MobileInput extends InputHandler implements GestureListener{ /** Check and assign targets for a specific position. */ void checkTargets(float x, float y){ - Unitc unit = Units.closestEnemy(player.team(), x, y, 20f, u -> !u.dead()); + Unit unit = Units.closestEnemy(player.team(), x, y, 20f, u -> !u.dead); if(unit != null){ player.miner().mineTile(null); target = unit; }else{ - Tilec tile = world.entWorld(x, y); + Building tile = world.entWorld(x, y); if(tile != null && player.team().isEnemy(tile.team())){ player.miner().mineTile(null); @@ -454,7 +454,7 @@ public class MobileInput extends InputHandler implements GestureListener{ lastLineY = tileY; }else if(!tryTapPlayer(worldx, worldy) && Core.settings.getBool("keyboard")){ //shoot on touch down when in keyboard mode - isShooting = true; + player.shooting = true; } } @@ -496,9 +496,9 @@ public class MobileInput extends InputHandler implements GestureListener{ }else{ Tile tile = tileAt(screenX, screenY); - if(tile == null || tile.entity == null) return false; + if(tile == null || tile.build == null) return false; - tryDropItems(tile.entity, Core.input.mouseWorld(screenX, screenY).x, Core.input.mouseWorld(screenX, screenY).y); + tryDropItems(tile.build, Core.input.mouseWorld(screenX, screenY).x, Core.input.mouseWorld(screenX, screenY).y); } return false; } @@ -542,7 +542,7 @@ public class MobileInput extends InputHandler implements GestureListener{ //ignore off-screen taps if(cursor == null || Core.scene.hasMouse(x, y)) return false; - Tile linked = cursor.entity == null ? cursor : cursor.entity.tile(); + Tile linked = cursor.build == null ? cursor : cursor.build.tile(); checkTargets(worldx, worldy); @@ -555,7 +555,7 @@ public class MobileInput extends InputHandler implements GestureListener{ }else if(mode == breaking && validBreak(linked.x,linked.y) && !hasRequest(linked)){ //add to selection queue if it's a valid BREAK position selectRequests.add(new BuildPlan(linked.x, linked.y)); - }else if(!canTapPlayer(worldx, worldy) && !tileTapped(linked.entity)){ + }else if(!canTapPlayer(worldx, worldy) && !tileTapped(linked.build)){ tryBeginMine(cursor); } @@ -589,11 +589,11 @@ public class MobileInput extends InputHandler implements GestureListener{ if(Core.settings.getBool("keyboard")){ if(Core.input.keyRelease(Binding.select)){ - isShooting = false; + player.shooting = false; } - if(isShooting && !canShoot()){ - isShooting = false; + if(player.shooting && !canShoot()){ + player.shooting = false; } } diff --git a/core/src/mindustry/io/JsonIO.java b/core/src/mindustry/io/JsonIO.java index 6b44f56cdb..3629ddebae 100644 --- a/core/src/mindustry/io/JsonIO.java +++ b/core/src/mindustry/io/JsonIO.java @@ -47,6 +47,11 @@ public class JsonIO{ return json.toJson(object, object.getClass()); } + public static T copy(T object, T dest){ + json.copyFields(object, dest); + return dest; + } + public static T copy(T object){ return read((Class)object.getClass(), write(object)); } diff --git a/core/src/mindustry/io/SaveVersion.java b/core/src/mindustry/io/SaveVersion.java index 0e106b4c3a..e03a22b2a5 100644 --- a/core/src/mindustry/io/SaveVersion.java +++ b/core/src/mindustry/io/SaveVersion.java @@ -97,7 +97,7 @@ public abstract class SaveVersion extends SaveFileReader{ "viewpos", Tmp.v1.set(player == null ? Vec2.ZERO : player).toString(), "controlledType", headless || control.input.controlledType == null ? "null" : control.input.controlledType.name, "nocores", state.rules.defaultTeam.cores().isEmpty(), - "playerteam", player == null ? state.rules.defaultTeam.uid : player.team().uid + "playerteam", player == null ? state.rules.defaultTeam.id : player.team().id ).merge(tags)); } @@ -112,13 +112,18 @@ public abstract class SaveVersion extends SaveFileReader{ if(state.rules.spawns.isEmpty()) state.rules.spawns = defaultWaves.get(); lastReadBuild = map.getInt("build", -1); + //load time spent on sector into state + if(state.rules.sector != null){ + state.secinfo.internalTimeSpent = state.rules.sector.getStoredTimeSpent(); + } + if(!headless){ Tmp.v1.tryFromString(map.get("viewpos")); Core.camera.position.set(Tmp.v1); player.set(Tmp.v1); control.input.controlledType = content.getByName(ContentType.unit, map.get("controlledType", "")); - Team team = Team.get(map.getInt("playerteam", state.rules.defaultTeam.uid)); + Team team = Team.get(map.getInt("playerteam", state.rules.defaultTeam.id)); if(!net.client() && team != Team.derelict){ player.team(team); } @@ -164,15 +169,15 @@ public abstract class SaveVersion extends SaveFileReader{ stream.writeShort(tile.blockID()); //make note of whether there was an entity here - stream.writeBoolean(tile.entity != null); + stream.writeBoolean(tile.build != null); //only write the entity for multiblocks once - in the center - if(tile.entity != null){ + if(tile.build != null){ if(tile.isCenter()){ stream.writeBoolean(true); writeChunk(stream, true, out -> { - out.writeByte(tile.entity.version()); - tile.entity.writeAll(Writes.get(out)); + out.writeByte(tile.build.version()); + tile.build.writeAll(Writes.get(out)); }); }else{ stream.writeBoolean(false); @@ -249,7 +254,7 @@ public abstract class SaveVersion extends SaveFileReader{ try{ readChunk(stream, true, in -> { byte revision = in.readByte(); - tile.entity.readAll(Reads.get(in), revision); + tile.build.readAll(Reads.get(in), revision); }); }catch(Throwable e){ throw new IOException("Failed to read tile entity of block: " + block, e); @@ -326,10 +331,10 @@ public abstract class SaveVersion extends SaveFileReader{ public void readContentHeader(DataInput stream) throws IOException{ byte mapped = stream.readByte(); - MappableContent[][] map = new MappableContent[ContentType.values().length][0]; + MappableContent[][] map = new MappableContent[ContentType.all.length][0]; for(int i = 0; i < mapped; i++){ - ContentType type = ContentType.values()[stream.readByte()]; + ContentType type = ContentType.all[stream.readByte()]; short total = stream.readShort(); map[type.ordinal()] = new MappableContent[total]; diff --git a/core/src/mindustry/io/TypeIO.java b/core/src/mindustry/io/TypeIO.java index 641fc91b95..2e88a1bb71 100644 --- a/core/src/mindustry/io/TypeIO.java +++ b/core/src/mindustry/io/TypeIO.java @@ -104,27 +104,62 @@ public class TypeIO{ return Payload.read(read); } - //only for players! - public static void writeUnit(Writes write, Unitc unit){ + public static void writeMounts(Writes writes, WeaponMount[] mounts){ + writes.b(mounts.length); + for(WeaponMount m : mounts){ + writes.b((m.shoot ? 1 : 0) | (m.rotate ? 2 : 0)); + writes.f(m.aimX); + writes.f(m.aimY); + } + } + + public static WeaponMount[] readMounts(Reads read, WeaponMount[] mounts){ + byte len = read.b(); + for(int i = 0; i < len; i++){ + byte state = read.b(); + float ax = read.f(), ay = read.f(); + + if(i <= mounts.length - 1){ + WeaponMount m = mounts[i]; + m.aimX = ax; + m.aimY = ay; + m.shoot = (state & 1) != 0; + m.rotate = (state & 2) != 0; + } + } + + return mounts; + } + + //this is irrelevant. + static final WeaponMount[] noMounts = {}; + + public static WeaponMount[] readMounts(Reads read){ + read.skip(read.b() * (1 + 4 + 4)); + + return noMounts; + } + + public static void writeUnit(Writes write, Unit unit){ write.b(unit.isNull() ? 0 : unit instanceof BlockUnitc ? 1 : 2); //block units are special if(unit instanceof BlockUnitc){ write.i(((BlockUnitc)unit).tile().pos()); }else{ - write.i(unit.id()); + write.i(unit.id); } } - public static Unitc readUnit(Reads read){ + public static Unit readUnit(Reads read){ byte type = read.b(); int id = read.i(); //nothing if(type == 0) return Nulls.unit; if(type == 2){ //standard unit - Unitc unit = Groups.unit.getByID(id); + Unit unit = Groups.unit.getByID(id); return unit == null ? Nulls.unit : unit; }else if(type == 1){ //block - Tilec tile = world.ent(id); + Building tile = world.ent(id); return tile instanceof ControlBlock ? ((ControlBlock)tile).unit() : Nulls.unit; } return Nulls.unit; @@ -135,14 +170,14 @@ public class TypeIO{ } public static T readEntity(Reads read){ - return (T)Groups.all.getByID(read.i()); + return (T)Groups.sync.getByID(read.i()); } - public static void writeTilec(Writes write, Tilec tile){ + public static void writeBuilding(Writes write, Building tile){ write.i(tile == null ? -1 : tile.pos()); } - public static Tilec readTilec(Reads read){ + public static Building readBuilding(Reads read){ return world.ent(read.i()); } @@ -229,9 +264,9 @@ public class TypeIO{ public static void writeController(Writes write, UnitController control){ //no real unit controller state is written, only the type - if(control instanceof Playerc){ + if(control instanceof Player){ write.b(0); - write.i(((Playerc)control).id()); + write.i(((Player)control).id()); }else if(control instanceof FormationAI){ write.b(1); write.i(((FormationAI)control).leader.id()); @@ -244,9 +279,9 @@ public class TypeIO{ byte type = read.b(); if(type == 0){ //is player int id = read.i(); - Playerc player = Groups.player.getByID(id); - //local players will cause problems if assigned, since they may not know they are controlling the unit - if(player == null || player.isLocal()) return prev; + Player player = Groups.player.getByID(id); + //make sure player exists + if(player == null) return prev; return player; }else if(type == 1){ int id = read.i(); @@ -255,7 +290,7 @@ public class TypeIO{ //there are two cases here: //1: prev controller was not a player, carry on //2: prev controller was a player, so replace this controller with *anything else* - //...since AI doesn't update clientside it doesn't matter what + //...since AI doesn't update clientside it doesn't matter return (!(prev instanceof AIController) || (prev instanceof FormationAI)) ? new GroundAI() : prev; } } diff --git a/core/src/mindustry/io/legacy/LegacySaveVersion.java b/core/src/mindustry/io/legacy/LegacySaveVersion.java index 4e543c7be6..3af8e1fcb5 100644 --- a/core/src/mindustry/io/legacy/LegacySaveVersion.java +++ b/core/src/mindustry/io/legacy/LegacySaveVersion.java @@ -54,7 +54,7 @@ public abstract class LegacySaveVersion extends SaveVersion{ if(block == null) block = Blocks.air; //occupied by multiblock part - boolean occupied = tile.entity != null && !tile.isCenter() && (tile.entity.block() == block || block == Blocks.air); + boolean occupied = tile.build != null && !tile.isCenter() && (tile.build.block() == block || block == Blocks.air); //do not override occupied cells if(!occupied){ @@ -65,8 +65,8 @@ public abstract class LegacySaveVersion extends SaveVersion{ try{ readChunk(stream, true, in -> { byte version = in.readByte(); - //legacy impl of TileEntity#read() - tile.entity.health(stream.readUnsignedShort()); + //legacy impl of Building#read() + tile.build.health(stream.readUnsignedShort()); byte packedrot = stream.readByte(); byte team = Pack.leftByte(packedrot) == 8 ? stream.readByte() : Pack.leftByte(packedrot); byte rotation = Pack.rightByte(packedrot); @@ -74,13 +74,13 @@ public abstract class LegacySaveVersion extends SaveVersion{ tile.setTeam(Team.get(team)); tile.rotation(rotation); - if(tile.entity.items() != null) tile.entity.items().read(Reads.get(stream)); - if(tile.entity.power() != null) tile.entity.power().read(Reads.get(stream)); - if(tile.entity.liquids() != null) tile.entity.liquids().read(Reads.get(stream)); - if(tile.entity.cons() != null) tile.entity.cons().read(Reads.get(stream)); + if(tile.build.items != null) tile.build.items.read(Reads.get(stream)); + if(tile.build.power != null) tile.build.power.read(Reads.get(stream)); + if(tile.build.liquids != null) tile.build.liquids.read(Reads.get(stream)); + if(tile.build.cons() != null) tile.build.cons().read(Reads.get(stream)); //read only from subclasses! - tile.entity.read(Reads.get(in), version); + tile.build.read(Reads.get(in), version); }); }catch(Throwable e){ throw new IOException("Failed to read tile entity of block: " + block, e); diff --git a/core/src/mindustry/io/legacy/LegacyTypeTable.java b/core/src/mindustry/io/legacy/LegacyTypeTable.java deleted file mode 100644 index f232911503..0000000000 --- a/core/src/mindustry/io/legacy/LegacyTypeTable.java +++ /dev/null @@ -1,139 +0,0 @@ -package mindustry.io.legacy; - -/* -Latest data: [build 81] - -0 = Player -1 = Fire -2 = Puddle -3 = MinerDrone -4 = RepairDrone -5 = BuilderDrone -6 = GroundUnit -7 = GroundUnit -8 = GroundUnit -9 = GroundUnit -10 = GroundUnit -11 = FlyingUnit -12 = FlyingUnit -13 = Revenant - -Before removal of lightining/bullet: [build 80] - -0 = Player -1 = Fire -2 = Puddle -3 = Bullet -4 = Lightning -5 = MinerDrone -6 = RepairDrone -7 = BuilderDrone -8 = GroundUnit -9 = GroundUnit -10 = GroundUnit -11 = GroundUnit -12 = GroundUnit -13 = FlyingUnit -14 = FlyingUnit -15 = Revenant - -Before addition of new units: [build 79 and below] - -0 = Player -1 = Fire -2 = Puddle -3 = Bullet -4 = Lightning -5 = RepairDrone -6 = GroundUnit -7 = GroundUnit -8 = GroundUnit -9 = GroundUnit -10 = GroundUnit -11 = FlyingUnit -12 = FlyingUnit -13 = BuilderDrone -14 = Revenant - */ -public class LegacyTypeTable{ - /* - 0 = Player -1 = Fire -2 = Puddle -3 = Draug -4 = Spirit -5 = Phantom -6 = Dagger -7 = Crawler -8 = Titan -9 = Fortress -10 = Eruptor -11 = Wraith -12 = Ghoul -13 = Revenant - - private static final Prov[] build81Table = { - Playerc::new, - Fire::new, - Puddle::new, - MinerDrone::new, - RepairDrone::new, - BuilderDrone::new, - GroundUnit::new, - GroundUnit::new, - GroundUnit::new, - GroundUnit::new, - GroundUnit::new, - FlyingUnit::new, - FlyingUnit::new, - HoverUnit::new - }; - - private static final Prov[] build80Table = { - Playerc::new, - Fire::new, - Puddle::new, - Bullet::new, - Lightning::new, - MinerDrone::new, - RepairDrone::new, - BuilderDrone::new, - GroundUnit::new, - GroundUnit::new, - GroundUnit::new, - GroundUnit::new, - GroundUnit::new, - FlyingUnit::new, - FlyingUnit::new, - HoverUnit::new - }; - - private static final Prov[] build79Table = { - Playerc::new, - Fire::new, - Puddle::new, - Bullet::new, - Lightning::new, - RepairDrone::new, - GroundUnit::new, - GroundUnit::new, - GroundUnit::new, - GroundUnit::new, - GroundUnit::new, - FlyingUnit::new, - FlyingUnit::new, - BuilderDrone::new, - HoverUnit::new - }; - - public static Prov[] getTable(int build){ - if(build == -1 || build == 81){ - //return most recent one since that's probably it; not guaranteed - return build81Table; - }else if(build == 80){ - return build80Table; - }else{ - return build79Table; - } - }*/ -} diff --git a/core/src/mindustry/logic/LogicExecutor.java b/core/src/mindustry/logic/LogicExecutor.java index f702df855e..11f44bc26d 100644 --- a/core/src/mindustry/logic/LogicExecutor.java +++ b/core/src/mindustry/logic/LogicExecutor.java @@ -19,7 +19,7 @@ public class LogicExecutor{ if(counter >= instructions.length) counter = 0; } - Tilec device(short id){ + Building device(short id){ return null; //TODO } @@ -68,8 +68,8 @@ public class LogicExecutor{ } enum ReadOp{ - item((tile, id) -> tile.items() == null ? 0 : tile.items().get(id)), - itemTotal((tile, param) -> tile.items() == null ? 0 : tile.items().total()); + item((tile, id) -> tile.items == null ? 0 : tile.items.get(id)), + itemTotal((tile, param) -> tile.items == null ? 0 : tile.items.total()); final ReadOpLambda function; final String symbol; @@ -80,7 +80,7 @@ public class LogicExecutor{ } interface ReadOpLambda{ - int get(Tilec tile, int parameter); + int get(Building tile, int parameter); } } diff --git a/core/src/mindustry/maps/Map.java b/core/src/mindustry/maps/Map.java index a7af96e78c..e47e369140 100644 --- a/core/src/mindustry/maps/Map.java +++ b/core/src/mindustry/maps/Map.java @@ -202,7 +202,7 @@ public class Map implements Comparable, Publishable{ @Override public boolean prePublish(){ - tags.put("author", player.name()); + tags.put("author", player.name); ui.editor.editor.getTags().put("author", tags.get("author")); ui.editor.save(); diff --git a/core/src/mindustry/maps/Maps.java b/core/src/mindustry/maps/Maps.java index b10b8c6fd1..e71425539f 100644 --- a/core/src/mindustry/maps/Maps.java +++ b/core/src/mindustry/maps/Maps.java @@ -86,18 +86,6 @@ public class Maps{ maps.sort(); }); - Events.on(ContentReloadEvent.class, event -> { - reload(); - for(Map map : maps){ - try{ - map.texture = map.previewFile().exists() ? new Texture(map.previewFile()) : new Texture(MapIO.generatePreview(map)); - readCache(map); - }catch(Exception e){ - e.printStackTrace(); - } - } - }); - if(Core.assets != null){ ((CustomLoader) Core.assets.getLoader(Content.class)).loaded = this::createAllPreviews; } diff --git a/core/src/mindustry/maps/SectorDamage.java b/core/src/mindustry/maps/SectorDamage.java index 7d923313ef..cf0c785d45 100644 --- a/core/src/mindustry/maps/SectorDamage.java +++ b/core/src/mindustry/maps/SectorDamage.java @@ -3,7 +3,10 @@ package mindustry.maps; import arc.math.*; import arc.math.geom.*; import arc.struct.*; +import mindustry.ai.*; import mindustry.content.*; +import mindustry.entities.*; +import mindustry.gen.*; import mindustry.world.*; import mindustry.world.blocks.storage.*; @@ -11,15 +14,14 @@ import static mindustry.Vars.*; public class SectorDamage{ //direct damage is for testing only - private static final boolean direct = false; + private static final boolean direct = false, rubble = true; - //TODO amount of damage could be related to wave spacing - public static void apply(float turns){ + public static void apply(float fraction){ Tiles tiles = world.tiles; Queue frontier = new Queue<>(); float[][] values = new float[tiles.width][tiles.height]; - float damage = turns*50; + float damage = fraction*80; //arbitrary damage value //phase one: find all spawnpoints for(Tile tile : tiles){ @@ -29,6 +31,29 @@ public class SectorDamage{ } } + Building core = state.rules.defaultTeam.core(); + if(core != null && !frontier.isEmpty()){ + for(Tile spawner : frontier){ + //find path from spawn to core + Seq path = Astar.pathfind(spawner, core.tile, t -> t.cost, t -> !(t.block().isStatic() && t.solid())); + int amount = (int)(path.size * fraction); + for(int i = 0; i < amount; i++){ + Tile t = path.get(i); + Geometry.circle(t.x, t.y, tiles.width, tiles.height, 5, (cx, cy) -> { + Tile other = tiles.getn(cx, cy); + //just remove all the buildings in the way - as long as they're not cores! + if(other.build != null && other.team() == state.rules.defaultTeam && !(other.block() instanceof CoreBlock)){ + if(rubble && !other.floor().solid && !other.floor().isLiquid && Mathf.chance(0.4)){ + Effects.rubble(other.build.x, other.build.y, other.block().size); + } + + other.remove(); + } + }); + } + } + } + float falloff = (damage) / (Math.max(tiles.width, tiles.height) * Mathf.sqrt2); int peak = 0; @@ -47,20 +72,22 @@ public class SectorDamage{ float resultDamage = currDamage; //damage the tile if it's not friendly - if(other.entity != null && other.team() != state.rules.waveTeam){ - resultDamage -= other.entity.health(); + if(other.build != null && other.team() != state.rules.waveTeam){ + resultDamage -= other.build.health(); if(direct){ - other.entity.damage(currDamage); + other.build.damage(currDamage); }else{ //indirect damage happens at game load time - other.entity.health(other.entity.health() - currDamage); + other.build.health -= currDamage; + //don't kill the core! + if(other.block() instanceof CoreBlock) other.build.health = Math.max(other.build.health, 1f); //remove the block when destroyed - if(other.entity.health() < 0){ - //rubble currently disabled - //if(!other.floor().solid && !other.floor().isLiquid && Mathf.chance(0.4)){ - // Effects.rubble(other.entity.x(), other.entity.y(), other.block().size); - //} + if(other.build.health < 0){ + //rubble + if(rubble && !other.floor().solid && !other.floor().isLiquid && Mathf.chance(0.4)){ + Effects.rubble(other.build.x, other.build.y, other.block().size); + } other.remove(); } @@ -78,5 +105,7 @@ public class SectorDamage{ } } + + } } diff --git a/core/src/mindustry/maps/filters/RandomItemFilter.java b/core/src/mindustry/maps/filters/RandomItemFilter.java index c7b2d7e419..4c9537eca4 100644 --- a/core/src/mindustry/maps/filters/RandomItemFilter.java +++ b/core/src/mindustry/maps/filters/RandomItemFilter.java @@ -21,7 +21,7 @@ public class RandomItemFilter extends GenerateFilter{ if(tile.block() instanceof StorageBlock && !(tile.block() instanceof CoreBlock)){ for(ItemStack stack : drops){ if(Mathf.chance(chance)){ - tile.entity.items().add(stack.item, Math.min(Mathf.random(stack.amount), tile.block().itemCapacity)); + tile.build.items.add(stack.item, Math.min(Mathf.random(stack.amount), tile.block().itemCapacity)); } } } diff --git a/core/src/mindustry/maps/generators/BaseGenerator.java b/core/src/mindustry/maps/generators/BaseGenerator.java index db507d2239..3d8f11c4c2 100644 --- a/core/src/mindustry/maps/generators/BaseGenerator.java +++ b/core/src/mindustry/maps/generators/BaseGenerator.java @@ -44,6 +44,7 @@ public class BaseGenerator{ } } + //TODO limit base size float costBudget = 1000; Seq wallsSmall = content.blocks().select(b -> b instanceof Wall && b.size == 1); @@ -62,9 +63,9 @@ public class BaseGenerator{ Schematics.placeLoadout(coreschem.schematic, tile.x, tile.y, team, coreschem.required instanceof Item ? ores.get((Item)coreschem.required) : Blocks.oreCopper); //fill core with every type of item (even non-material) - Tilec entity = tile.entity; + Building entity = tile.build; for(Item item : content.items()){ - entity.items().add(item, entity.block().itemCapacity); + entity.items.add(item, entity.block().itemCapacity); } } @@ -129,9 +130,11 @@ public class BaseGenerator{ } public void postGenerate(){ + if(tiles == null) return; + for(Tile tile : tiles){ if(tile.isCenter() && tile.block() instanceof PowerNode){ - tile.entity.placed(); + tile.build.placed(); } } } diff --git a/core/src/mindustry/maps/generators/FileMapGenerator.java b/core/src/mindustry/maps/generators/FileMapGenerator.java index 76a297756a..e0b8bf3946 100644 --- a/core/src/mindustry/maps/generators/FileMapGenerator.java +++ b/core/src/mindustry/maps/generators/FileMapGenerator.java @@ -34,7 +34,7 @@ public class FileMapGenerator implements WorldGenerator{ if(tile.block() instanceof StorageBlock && !(tile.block() instanceof CoreBlock) && state.hasSector()){ for(Content content : state.getSector().data.resources){ if(content instanceof Item && Mathf.chance(0.3)){ - tile.entity.items().add((Item)content, Math.min(Mathf.random(500), tile.block().itemCapacity)); + tile.build.items.add((Item)content, Math.min(Mathf.random(500), tile.block().itemCapacity)); } } } @@ -54,15 +54,9 @@ public class FileMapGenerator implements WorldGenerator{ } if(tile.isCenter() && tile.block() instanceof CoreBlock && tile.team() == state.rules.defaultTeam && !anyCores){ - //TODO PLACE THE (CORRECT) LOADOUT - Schematics.placeLoadout(Loadouts.basicShard, tile.x, tile.y); + Schematics.placeLaunchLoadout(tile.x, tile.y); anyCores = true; } - - //add random decoration - //if(Mathf.chance(0.015) && !tile.floor().isLiquid && tile.block() == Blocks.air){ - // tile.setBlock(tile.floor().decoration); - //} } if(!anyCores){ diff --git a/core/src/mindustry/maps/generators/PlanetGenerator.java b/core/src/mindustry/maps/generators/PlanetGenerator.java index 132eaf9ae0..2ce0bbae27 100644 --- a/core/src/mindustry/maps/generators/PlanetGenerator.java +++ b/core/src/mindustry/maps/generators/PlanetGenerator.java @@ -1,13 +1,41 @@ package mindustry.maps.generators; import arc.math.geom.*; +import arc.util.noise.*; import mindustry.graphics.g3d.*; +import mindustry.graphics.g3d.PlanetGrid.*; import mindustry.type.*; +import mindustry.type.Sector.*; import mindustry.world.*; public abstract class PlanetGenerator extends BasicGenerator implements HexMesher{ protected Sector sector; + /** Should generate sector bases for a planet. */ + public void generateSector(Sector sector){ + Ptile tile = sector.tile; + + boolean any = false; + float noise = Noise.snoise3(tile.v.x, tile.v.y, tile.v.z, 0.001f, 0.5f); + + if(noise > 0.028){ + any = true; + } + + if(noise < 0.15){ + for(Ptile other : tile.tiles){ + if(sector.planet.getSector(other).is(SectorAttribute.base)){ + any = false; + break; + } + } + } + + if(any){ + sector.data.attributes |= (1 << SectorAttribute.base.ordinal()); + } + } + protected void genTile(Vec3 position, TileGen tile){ } diff --git a/core/src/mindustry/maps/planet/TODOPlanetGenerator.java b/core/src/mindustry/maps/planet/TODOPlanetGenerator.java index a3478e5e7a..648e113558 100644 --- a/core/src/mindustry/maps/planet/TODOPlanetGenerator.java +++ b/core/src/mindustry/maps/planet/TODOPlanetGenerator.java @@ -279,8 +279,7 @@ public class TODOPlanetGenerator extends PlanetGenerator{ } }); - //TODO PLACE CORRECT LOADOUT - Schematics.placeLoadout(Loadouts.advancedShard, spawn.x, spawn.y); + Schematics.placeLaunchLoadout(spawn.x, spawn.y); if(sector.hasEnemyBase()){ basegen.generate(tiles, enemies.map(r -> tiles.getn(r.x, r.y)), tiles.get(spawn.x, spawn.y), state.rules.waveTeam, sector); @@ -289,10 +288,22 @@ public class TODOPlanetGenerator extends PlanetGenerator{ } state.rules.waves = true; + + float difficulty = sector.baseCoverage; + + //scale up the spawning base on difficulty (this is just for testing) + for(SpawnGroup group : state.rules.spawns){ + group.unitAmount *= difficulty; + if(group.unitScaling != SpawnGroup.never){ + group.unitScaling *= difficulty; + } + } } @Override public void postGenerate(Tiles tiles){ - basegen.postGenerate(); + if(sector.hasEnemyBase()){ + basegen.postGenerate(); + } } } diff --git a/core/src/mindustry/mod/ContentParser.java b/core/src/mindustry/mod/ContentParser.java index 000d3d6521..d093918062 100644 --- a/core/src/mindustry/mod/ContentParser.java +++ b/core/src/mindustry/mod/ContentParser.java @@ -7,7 +7,6 @@ import arc.files.*; import arc.func.*; import arc.graphics.*; import arc.mock.*; -import arc.struct.Seq; import arc.struct.*; import arc.util.ArcAnnotate.*; import arc.util.*; diff --git a/core/src/mindustry/mod/Mod.java b/core/src/mindustry/mod/Mod.java index 5b4c31b7a0..eea38820c6 100644 --- a/core/src/mindustry/mod/Mod.java +++ b/core/src/mindustry/mod/Mod.java @@ -15,6 +15,11 @@ public class Mod{ } + /** Called on clientside mods. Load content here. */ + public void loadContent(){ + + } + /** Register any commands to be used on the server side, e.g. from the console. */ public void registerServerCommands(CommandHandler handler){ diff --git a/core/src/mindustry/mod/Mods.java b/core/src/mindustry/mod/Mods.java index 627836f414..e4758a20a3 100644 --- a/core/src/mindustry/mod/Mods.java +++ b/core/src/mindustry/mod/Mods.java @@ -45,7 +45,6 @@ public class Mods implements Loadable{ public Mods(){ Events.on(ClientLoadEvent.class, e -> Core.app.post(this::checkWarnings)); - Events.on(ContentReloadEvent.class, e -> Core.app.post(this::checkWarnings)); } /** Returns a file named 'config.json' in a special folder for the specified plugin. @@ -70,7 +69,7 @@ public class Mods implements Loadable{ /** @return the loaded mod found by class, or null if not found. */ public @Nullable LoadedMod getMod(Class type){ - return mods.find(m -> m.enabled() && m.main != null && m.main.getClass() == type);//loaded.find(l -> l.mod != null && l.mod.getClass() == type); + return mods.find(m -> m.enabled() && m.main != null && m.main.getClass() == type); } /** Imports an external mod file.*/ @@ -335,7 +334,6 @@ public class Mods implements Loadable{ for(Fi file : mod.root.list()){ //ignore special folders like bundles or sprites if(file.isDirectory() && !specialFolders.contains(file.name())){ - //TODO calling child/parent on these files will give you gibberish; create wrapper class. file.walk(f -> tree.addFile(mod.file.isDirectory() ? f.path().substring(1 + mod.file.path().length()) : zipFolder ? f.path().substring(parentName.length() + 1) : f.path(), f)); } @@ -424,42 +422,6 @@ public class Mods implements Loadable{ return mods.contains(LoadedMod::hasContentErrors) || (scripts != null && scripts.hasErrored()); } - /** Reloads all mod content. How does this even work? I refuse to believe that it functions correctly.*/ - public void reloadContent(){ - //epic memory leak - //TODO make it less epic - Core.atlas = new TextureAtlas(Core.files.internal("sprites/sprites.atlas")); - createdAtlas = true; - - mods.each(LoadedMod::dispose); - mods.clear(); - Core.bundle = I18NBundle.createBundle(Core.files.internal("bundles/bundle"), Core.bundle.getLocale()); - load(); - Sounds.dispose(); - Sounds.load(); - Core.assets.finishLoading(); - if(scripts != null){ - scripts.dispose(); - scripts = null; - } - content.clear(); - content.createBaseContent(); - content.loadColors(); - loadScripts(); - content.createModContent(); - loadAsync(); - loadSync(); - content.init(); - content.load(); - content.loadColors(); - Core.atlas.getTextures().each(t -> t.setFilter(Core.settings.getBool("linear") ? TextureFilter.linear : TextureFilter.nearest)); - requiresReload = false; - - loadIcons(); - - Events.fire(new ContentReloadEvent()); - } - /** This must be run on the main thread! */ public void loadScripts(){ Time.mark(); @@ -498,6 +460,17 @@ public class Mods implements Loadable{ /** Creates all the content found in mod files. */ public void loadContent(){ + //load class mod content first + for(LoadedMod mod : orderedMods()){ + //hidden mods can't load content + if(mod.main != null && !mod.meta.hidden){ + content.setCurrentMod(mod); + mod.main.loadContent(); + } + } + + content.setCurrentMod(null); + class LoadRun implements Comparable{ final ContentType type; final Fi file; @@ -621,7 +594,7 @@ public class Mods implements Loadable{ Fi metaf = zip.child("mod.json").exists() ? zip.child("mod.json") : zip.child("mod.hjson").exists() ? zip.child("mod.hjson") : zip.child("plugin.json"); if(!metaf.exists()){ Log.warn("Mod @ doesn't have a 'mod.json'/'mod.hjson'/'plugin.json' file, skipping.", sourceFile); - throw new IllegalArgumentException("No mod.json found."); + throw new IllegalArgumentException("Invalid file: No mod.json found."); } ModMeta meta = json.fromJson(ModMeta.class, Jval.read(metaf.readString()).toString(Jformat.plain)); @@ -645,9 +618,9 @@ public class Mods implements Loadable{ //make sure the main class exists before loading it; if it doesn't just don't put it there if(mainFile.exists()){ - //other platforms don't have standard java class loaders - if(!headless && Version.build != -1){ - throw new IllegalArgumentException("Java class mods are currently unsupported outside of custom builds."); + //mobile versions don't support class mods + if(mobile){ + throw new IllegalArgumentException("Java class mods are not supported on mobile."); } URLClassLoader classLoader = new URLClassLoader(new URL[]{sourceFile.file().toURI().toURL()}, ClassLoader.getSystemClassLoader()); diff --git a/core/src/mindustry/net/Administration.java b/core/src/mindustry/net/Administration.java index a9b5ff38c2..a24610fe3f 100644 --- a/core/src/mindustry/net/Administration.java +++ b/core/src/mindustry/net/Administration.java @@ -43,7 +43,7 @@ public class Administration{ //anti-spam addChatFilter((player, message) -> { long resetTime = Config.messageRateLimit.num() * 1000; - if(Config.antiSpam.bool() && !player.isLocal() && !player.admin()){ + if(Config.antiSpam.bool() && !player.isLocal() && !player.admin){ //prevent people from spamming messages quickly if(resetTime > 0 && Time.timeSinceMillis(player.getInfo().lastMessageTime) < resetTime){ //supress message @@ -51,7 +51,7 @@ public class Administration{ player.getInfo().messageInfractions ++; //kick player for spamming and prevent connection if they've done this several times if(player.getInfo().messageInfractions >= Config.messageSpamKick.num() && Config.messageSpamKick.num() != 0){ - player.con().kick("You have been kicked for spamming.", 1000 * 60 * 2); + player.con.kick("You have been kicked for spamming.", 1000 * 60 * 2); } return null; }else{ @@ -123,7 +123,7 @@ public class Administration{ } /** Filters out a chat message. */ - public @Nullable String filterMessage(Playerc player, String message){ + public @Nullable String filterMessage(Player player, String message){ String current = message; for(ChatFilter f : chatFilters){ current = f.filter(player, current); @@ -138,7 +138,7 @@ public class Administration{ } /** @return whether this action is allowed by the action filters. */ - public boolean allowAction(Playerc player, ActionType type, Tile tile, Cons setter){ + public boolean allowAction(Player player, ActionType type, Tile tile, Cons setter){ PlayerAction act = Pools.obtain(PlayerAction.class, PlayerAction::new); setter.get(act.set(player, type, tile)); for(ActionFilter filter : actionFilters){ @@ -655,7 +655,7 @@ public class Administration{ /** Handles chat messages from players and changes their contents. */ public interface ChatFilter{ /** @return the filtered message; a null string signals that the message should not be sent. */ - @Nullable String filter(Playerc player, String message); + @Nullable String filter(Player player, String message); } /** Allows or disallows player actions. */ @@ -679,7 +679,7 @@ public class Administration{ /** Defines a (potentially dangerous) action that a player has done in the world. * These objects are pooled; do not cache them! */ public static class PlayerAction implements Poolable{ - public @NonNull Playerc player; + public @NonNull Player player; public @NonNull ActionType type; public @NonNull Tile tile; @@ -694,7 +694,7 @@ public class Administration{ public @Nullable Item item; public int itemAmount; - public PlayerAction set(Playerc player, ActionType type, Tile tile){ + public PlayerAction set(Player player, ActionType type, Tile tile){ this.player = player; this.type = type; this.tile = tile; diff --git a/core/src/mindustry/net/CrashSender.java b/core/src/mindustry/net/CrashSender.java index 0fb44e1e62..1a64c76e2d 100644 --- a/core/src/mindustry/net/CrashSender.java +++ b/core/src/mindustry/net/CrashSender.java @@ -18,6 +18,7 @@ import java.io.*; import java.text.*; import java.util.*; +import static arc.Core.*; import static mindustry.Vars.net; public class CrashSender{ @@ -39,6 +40,11 @@ public class CrashSender{ try{ exception.printStackTrace(); + //try saving game data + try{ + settings.manualSave(); + }catch(Throwable ignored){} + //don't create crash logs for custom builds, as it's expected if(Version.build == -1 || (System.getProperty("user.name").equals("anuke") && "release".equals(Version.modifier))){ ret(); diff --git a/core/src/mindustry/net/Net.java b/core/src/mindustry/net/Net.java index f99ec4d495..5101d237ee 100644 --- a/core/src/mindustry/net/Net.java +++ b/core/src/mindustry/net/Net.java @@ -138,7 +138,7 @@ public class Net{ */ public void closeServer(){ for(NetConnection con : getConnections()){ - Call.onKick(con, KickReason.serverClose); + Call.kick(con, KickReason.serverClose); } provider.closeServer(); diff --git a/core/src/mindustry/net/NetConnection.java b/core/src/mindustry/net/NetConnection.java index 3fbc5ada21..d3f6ff051f 100644 --- a/core/src/mindustry/net/NetConnection.java +++ b/core/src/mindustry/net/NetConnection.java @@ -18,7 +18,7 @@ public abstract class NetConnection{ public final String address; public String uuid = "AAAAAAAA", usid = uuid; public boolean mobile, modclient; - public @Nullable Playerc player; + public @Nullable Player player; public @Nullable Unitc lastUnit; public Vec2 lastPosition = new Vec2(); @@ -46,7 +46,7 @@ public abstract class NetConnection{ info.lastKicked = Math.max(Time.millis() + 30 * 1000, info.lastKicked); } - Call.onKick(this, reason); + Call.kick(this, reason); Time.runTask(2f, this::close); @@ -66,7 +66,7 @@ public abstract class NetConnection{ info.timesKicked++; info.lastKicked = Math.max(Time.millis() + kickDuration, info.lastKicked); - Call.onKick(this, reason); + Call.kick(this, reason); Time.runTask(2f, this::close); diff --git a/core/src/mindustry/net/NetworkIO.java b/core/src/mindustry/net/NetworkIO.java index 6fce3740af..f4b4d3a61f 100644 --- a/core/src/mindustry/net/NetworkIO.java +++ b/core/src/mindustry/net/NetworkIO.java @@ -18,7 +18,7 @@ import static mindustry.Vars.*; public class NetworkIO{ - public static void writeWorld(Playerc player, OutputStream os){ + public static void writeWorld(Player player, OutputStream os){ try(DataOutputStream stream = new DataOutputStream(os)){ stream.writeUTF(JsonIO.write(state.rules)); @@ -27,7 +27,7 @@ public class NetworkIO{ stream.writeInt(state.wave); stream.writeFloat(state.wavetime); - stream.writeInt(player.id()); + stream.writeInt(player.id); player.write(Writes.get(stream)); SaveIO.getSaveWriter().writeContentHeader(stream); @@ -47,11 +47,11 @@ public class NetworkIO{ state.wave = stream.readInt(); state.wavetime = stream.readFloat(); - Groups.all.clear(); + Groups.clear(); int id = stream.readInt(); player.reset(); player.read(Reads.get(stream)); - player.id(id); + player.id = id; player.add(); SaveIO.getSaveWriter().readContentHeader(stream); @@ -64,7 +64,7 @@ public class NetworkIO{ } public static ByteBuffer writeServerData(){ - String name = (headless ? Config.name.string() : player.name()); + String name = (headless ? Config.name.string() : player.name); String description = headless && !Config.desc.string().equals("off") ? Config.desc.string() : ""; String map = state.map.name(); diff --git a/core/src/mindustry/net/Packet.java b/core/src/mindustry/net/Packet.java index f1f45d1ad9..9058637a66 100644 --- a/core/src/mindustry/net/Packet.java +++ b/core/src/mindustry/net/Packet.java @@ -5,14 +5,9 @@ import arc.util.pooling.Pool.Poolable; import java.nio.ByteBuffer; public interface Packet extends Poolable{ - default void read(ByteBuffer buffer){ - } - - default void write(ByteBuffer buffer){ - } - - default void reset(){ - } + default void read(ByteBuffer buffer){} + default void write(ByteBuffer buffer){} + default void reset(){} default boolean isImportant(){ return false; diff --git a/core/src/mindustry/net/ValidateException.java b/core/src/mindustry/net/ValidateException.java index 12a4ae4bdc..20bb15af6c 100644 --- a/core/src/mindustry/net/ValidateException.java +++ b/core/src/mindustry/net/ValidateException.java @@ -6,9 +6,9 @@ import mindustry.gen.*; * Thrown when a client sends invalid information. */ public class ValidateException extends RuntimeException{ - public final Playerc player; + public final Player player; - public ValidateException(Playerc player, String s){ + public ValidateException(Player player, String s){ super(s); this.player = player; } diff --git a/core/src/mindustry/type/Item.java b/core/src/mindustry/type/Item.java index bd9e28b66e..6558636343 100644 --- a/core/src/mindustry/type/Item.java +++ b/core/src/mindustry/type/Item.java @@ -12,8 +12,6 @@ import static mindustry.Vars.content; public class Item extends UnlockableContent{ public final Color color; - /** type of the item; used for tabs and core acceptance. default value is {@link ItemType#resource}. */ - public ItemType type = ItemType.resource; /** how explosive this item is. */ public float explosiveness = 0f; /** flammability above 0.3 makes this eleigible for item burners. */ diff --git a/core/src/mindustry/type/ItemStack.java b/core/src/mindustry/type/ItemStack.java index a8a765c4df..dad33a338b 100644 --- a/core/src/mindustry/type/ItemStack.java +++ b/core/src/mindustry/type/ItemStack.java @@ -59,6 +59,15 @@ public class ItemStack implements Comparable{ return stacks; } + public static void insert(Seq stacks, Item item, int amount){ + ItemStack stack = stacks.find(i -> i.item == item); + if(stack == null){ + stacks.add(new ItemStack(item, amount)); + }else{ + stack.amount += amount; + } + } + @Override public int compareTo(ItemStack itemStack){ return item.compareTo(itemStack.item); diff --git a/core/src/mindustry/type/ItemType.java b/core/src/mindustry/type/ItemType.java deleted file mode 100644 index 3d943c478a..0000000000 --- a/core/src/mindustry/type/ItemType.java +++ /dev/null @@ -1,8 +0,0 @@ -package mindustry.type; - -public enum ItemType{ - /** Not used for anything besides crafting inside blocks. */ - resource, - /** Can be used for constructing blocks. Only materials are accepted into the core. */ - material -} diff --git a/core/src/mindustry/type/Planet.java b/core/src/mindustry/type/Planet.java index e1b47919be..f27fc0aace 100644 --- a/core/src/mindustry/type/Planet.java +++ b/core/src/mindustry/type/Planet.java @@ -10,6 +10,7 @@ import arc.struct.*; import arc.util.ArcAnnotate.*; import arc.util.*; import arc.util.io.*; +import arc.util.noise.*; import mindustry.*; import mindustry.ctype.*; import mindustry.graphics.*; @@ -18,7 +19,7 @@ import mindustry.graphics.g3d.PlanetGrid.*; import mindustry.maps.generators.*; import mindustry.type.Sector.*; -import static mindustry.Vars.universe; +import static mindustry.Vars.*; public class Planet extends UnlockableContent{ /** Default spacing between planet orbits in world units. */ @@ -98,10 +99,6 @@ public class Planet extends UnlockableContent{ t.printStackTrace(); } } - - for(Sector sector : sectors){ - sector.generate(); - } }else{ sectors = new Seq<>(); } @@ -183,6 +180,24 @@ public class Planet extends UnlockableContent{ return in; } + /** Updates wave coverage of bases. */ + public void updateBaseCoverage(){ + for(Sector sector : sectors){ + float sum = 1f; + for(Sector other : sector.inRange(2)){ + if(other.is(SectorAttribute.base)){ + sum += 1f; + } + } + + if(sector.hasEnemyBase()){ + sum += 2f; + } + + sector.baseCoverage = sum; + } + } + /** @return the supplied matrix with transformation applied. */ public Mat3D getTransform(Mat3D mat){ return mat.setToTranslation(position).rotate(Vec3.Y, getRotation()); @@ -193,6 +208,21 @@ public class Planet extends UnlockableContent{ mesh = meshLoader.get(); } + @Override + public void init(){ + + if(generator != null){ + Noise.setSeed(id + 1); + + for(Sector sector : sectors){ + generator.generateSector(sector); + } + + updateBaseCoverage(); + } + + } + @Override public void dispose(){ if(mesh != null){ diff --git a/core/src/mindustry/type/Sector.java b/core/src/mindustry/type/Sector.java index db1389fe6a..f694358e9b 100644 --- a/core/src/mindustry/type/Sector.java +++ b/core/src/mindustry/type/Sector.java @@ -1,21 +1,25 @@ package mindustry.type; import arc.*; +import arc.func.*; import arc.math.geom.*; +import arc.struct.*; import arc.util.ArcAnnotate.*; import arc.util.*; import arc.util.io.*; -import arc.util.noise.*; import mindustry.*; import mindustry.ctype.*; import mindustry.game.Saves.*; import mindustry.graphics.g3d.PlanetGrid.*; import mindustry.world.*; -import static mindustry.Vars.world; +import static mindustry.Vars.*; /** A small section of a planet. */ public class Sector{ + private static final Seq tmpSeq1 = new Seq<>(), tmpSeq2 = new Seq<>(), tmpSeq3 = new Seq<>(); + private static final ObjectSet tmpSet = new ObjectSet<>(); + public final SectorRect rect; public final Plane plane; public final Planet planet; @@ -27,8 +31,7 @@ public class Sector{ public @Nullable SaveSlot save; public @Nullable SectorPreset preset; - /** Sector enemy hostility from 0 to 1 */ - public float hostility; + public float baseCoverage; //TODO implement a dynamic launch period public int launchPeriod = 10; @@ -42,6 +45,45 @@ public class Sector{ this.data = data; } + public Seq inRange(int range){ + //TODO cleanup/remove + if(true){ + tmpSeq1.clear(); + neighbors(tmpSeq1::add); + + return tmpSeq1; + } + + tmpSeq1.clear(); + tmpSeq2.clear(); + tmpSet.clear(); + + tmpSeq1.add(this); + tmpSet.add(this); + for(int i = 0; i < range; i++){ + while(!tmpSeq1.isEmpty()){ + Sector sec = tmpSeq1.pop(); + tmpSet.add(sec); + sec.neighbors(other -> { + if(tmpSet.add(other)){ + tmpSeq2.add(other); + } + }); + } + tmpSeq1.clear(); + tmpSeq1.addAll(tmpSeq2); + } + + tmpSeq3.clear().addAll(tmpSeq2); + return tmpSeq3; + } + + public void neighbors(Cons cons){ + for(Ptile tile : tile.tiles){ + cons.get(planet.getSector(tile)); + } + } + /** @return whether this sector can be landed on at all. * Only sectors adjacent to non-wave sectors can be landed on. * TODO also preset sectors*/ @@ -56,7 +98,7 @@ public class Sector{ /** @return whether the enemy has a generated base here. */ public boolean hasEnemyBase(){ - return hostility >= 0.02f && (save == null || save.meta.rules.waves); + return is(SectorAttribute.base) && (save == null || save.meta.rules.waves); } public boolean isBeingPlayed(){ @@ -77,11 +119,6 @@ public class Sector{ return save != null; } - public void generate(){ - //TODO use simplex and a seed - hostility = Math.max(Noise.snoise3(tile.v.x, tile.v.y, tile.v.z, 0.5f, 0.4f), 0); - } - public boolean locked(){ return !unlocked(); } @@ -110,6 +147,16 @@ public class Sector{ return false; } + //TODO this should be stored in a more efficient structure, and be updated each turn + public Seq getRecievedItems(){ + return Core.settings.getJson(key("recieved-items"), Seq.class, ItemStack.class, Seq::new); + } + + public void setRecievedItems(Seq stacks){ + Core.settings.putJson(key("recieved-items"), ItemStack.class, stacks); + } + + //TODO these methods should maybe move somewhere else and/or be contained in a data object public void setSpawnPosition(int position){ put("spawn-position", position); } @@ -120,12 +167,45 @@ public class Sector{ return Core.settings.getInt(key("spawn-position"), Point2.pack(world.width() / 2, world.height() / 2)); } - public void setTurnsPassed(int number){ - put("turns-passed", number); + /** @return time spent in this sector this turn in ticks. */ + public float getTimeSpent(){ + //return currently counting time spent if being played on + if(isBeingPlayed()) return state.secinfo.internalTimeSpent; + + //else return the stored value + return getStoredTimeSpent(); } - public int getTurnsPassed(){ - return Core.settings.getInt(key("turns-passed")); + public void setTimeSpent(float time){ + put("time-spent", time); + + //update counting time + if(isBeingPlayed()){ + state.secinfo.internalTimeSpent = time; + } + } + + public String displayTimeRemaining(){ + float amount = Vars.turnDuration - getTimeSpent(); + int seconds = (int)(amount / 60); + int sf = seconds % 60; + return (seconds / 60) + ":" + (sf < 10 ? "0" : "") + sf; + } + + /** @return the stored amount of time spent in this sector this turn in ticks. + * Do not use unless you know what you're doing. */ + public float getStoredTimeSpent(){ + return Core.settings.getFloat(key("time-spent")); + } + + public void setSecondsPassed(long number){ + put("seconds-passed", number); + } + + /** @return how much time has passed in this sector without the player resuming here. + * Used for resource production calculations. */ + public long getSecondsPassed(){ + return Core.settings.getLong(key("seconds-passed")); } private String key(String key){ @@ -243,6 +323,8 @@ public class Sector{ /** Has snow. */ snowy, /** Has sandstorms. */ - desert + desert, + /** Has an enemy base. */ + base } } diff --git a/core/src/mindustry/type/StatusEffect.java b/core/src/mindustry/type/StatusEffect.java index 632254a9de..2295fa6e0a 100644 --- a/core/src/mindustry/type/StatusEffect.java +++ b/core/src/mindustry/type/StatusEffect.java @@ -19,6 +19,8 @@ public class StatusEffect extends MappableContent{ public float speedMultiplier = 1f; /** Damage per frame. */ public float damage; + /** Chance of effect appearing. */ + public float effectChance = 0.15f; /** If true, the effect never disappears. */ public boolean permanent; /** Tint color of effect. */ @@ -44,15 +46,15 @@ public class StatusEffect extends MappableContent{ } /** Runs every tick on the affected unit while time is greater than 0. */ - public void update(Unitc unit, float time){ + public void update(Unit unit, float time){ if(damage > 0){ unit.damageContinuousPierce(damage); }else if(damage < 0){ //heal unit unit.heal(damage * Time.delta()); } - if(effect != Fx.none && Mathf.chanceDelta(0.15f)){ - effect.at(unit.x() + Mathf.range(unit.bounds() / 2f), unit.y() + Mathf.range(unit.bounds() / 2f)); + if(effect != Fx.none && Mathf.chanceDelta(effectChance)){ + effect.at(unit.x + Mathf.range(unit.bounds() / 2f), unit.y + Mathf.range(unit.bounds() / 2f)); } } @@ -73,7 +75,7 @@ public class StatusEffect extends MappableContent{ } } - public void draw(Unitc unit){ + public void draw(Unit unit){ } @@ -87,7 +89,7 @@ public class StatusEffect extends MappableContent{ * @param time The current status effect time * @param newTime The time that the new status effect will last */ - public StatusEntry getTransition(Unitc unit, StatusEffect to, float time, float newTime, StatusEntry result){ + public StatusEntry getTransition(Unit unit, StatusEffect to, float time, float newTime, StatusEntry result){ if(transitions.containsKey(to)){ transitions.get(to).handle(unit, time, newTime, result); return result; @@ -102,6 +104,6 @@ public class StatusEffect extends MappableContent{ } public interface TransitionHandler{ - void handle(Unitc unit, float time, float newTime, StatusEntry result); + void handle(Unit unit, float time, float newTime, StatusEntry result); } } diff --git a/core/src/mindustry/type/UnitType.java b/core/src/mindustry/type/UnitType.java index 473671f227..59389341ca 100644 --- a/core/src/mindustry/type/UnitType.java +++ b/core/src/mindustry/type/UnitType.java @@ -17,6 +17,7 @@ import mindustry.annotations.Annotations.*; import mindustry.content.*; import mindustry.ctype.*; import mindustry.entities.*; +import mindustry.entities.abilities.*; import mindustry.entities.units.*; import mindustry.game.*; import mindustry.gen.*; @@ -32,18 +33,27 @@ public class UnitType extends UnlockableContent{ private static final Vec2 legOffset = new Vec2(); public boolean flying; - public @NonNull Prov constructor; + public @NonNull Prov constructor; public @NonNull Prov defaultController = () -> !flying ? new GroundAI() : new FlyingAI(); public float speed = 1.1f, boostMultiplier = 1f, rotateSpeed = 5f, baseRotateSpeed = 5f; - public float drag = 0.3f, accel = 0.5f, landShake = 0f, rippleScale = 1f; + public float drag = 0.3f, accel = 0.5f, landShake = 0f, rippleScale = 1f, fallSpeed = 0.018f; public float health = 200f, range = -1, armor = 0f; + public float crashDamageMultiplier = 4f; public boolean targetAir = true, targetGround = true; public boolean faceTarget = true, rotateShooting = true, isCounted = true, lowAltitude = false; public boolean canBoost = false; + public boolean destructibleWreck = true; + public float groundLayer = Layer.groundUnit; public float sway = 1f; public int payloadCapacity = 1; public int commandLimit = 24; - public float baseElevation = 0f; + public float visualElevation = -1f; + public float deathShake = 2f; + public boolean allowLegStep = false; + public boolean hovering = false; + public Effect fallEffect = Fx.fallSmoke; + public Effect fallThrusterEffect = Fx.fallSmoke; + public Seq abilities = new Seq<>(); //TODO document public int legCount = 4, legGroupSize = 2; @@ -53,7 +63,7 @@ public class UnitType extends UnlockableContent{ public int itemCapacity = 30; public int ammoCapacity = 220; - public int drillTier = -1; + public int mineTier = -1; public float buildSpeed = 1f, mineSpeed = 1f; public float engineOffset = 5f, engineSize = 2.5f; @@ -62,8 +72,9 @@ public class UnitType extends UnlockableContent{ public float itemOffsetY = 3f; public float lightRadius = 60f, lightOpacity = 0.6f; public Color lightColor = Pal.powerLight; - public boolean drawCell = true, drawItems = true; + public boolean drawCell = true, drawItems = true, drawShields = true; public int parts = 0; + public int trailLength = 5; public ObjectSet immunities = new ObjectSet<>(); public Sound deathSound = Sounds.bang; @@ -71,8 +82,7 @@ public class UnitType extends UnlockableContent{ public Seq weapons = new Seq<>(); public TextureRegion baseRegion, legRegion, region, shadowRegion, cellRegion, occlusionRegion, jointRegion, footRegion, legBaseRegion, baseJointRegion; - public TextureRegion[] partRegions; - public TextureRegion[] partCellRegions; + public TextureRegion[] partRegions, partCellRegions, wreckRegions; public UnitType(String name){ super(name); @@ -84,11 +94,12 @@ public class UnitType extends UnlockableContent{ return defaultController.get(); } - public Unitc create(Team team){ - Unitc unit = constructor.get(); + public Unit create(Team team){ + Unit unit = constructor.get(); unit.team(team); unit.type(this); unit.ammo(ammoCapacity); //fill up on ammo upon creation + unit.heal(); return unit; } @@ -96,11 +107,17 @@ public class UnitType extends UnlockableContent{ return weapons.size > 0; } - public void update(Unitc unit){} + public void update(Unit unit){ + if(abilities.size > 0){ + for(mindustry.entities.abilities.Ability a : abilities){ + a.update(unit); + } + } + } - public void landed(Unitc unit){} + public void landed(Unit unit){} - public void display(Unitc unit, Table table){ + public void display(Unit unit, Table table){ table.table(t -> { t.left(); t.add(new Image(icon(Cicon.medium))).size(8 * 4); @@ -115,7 +132,7 @@ public class UnitType extends UnlockableContent{ bars.row(); if(state.rules.unitAmmo){ - bars.add(new Bar("blocks.ammo", Pal.ammo, () -> (float)unit.ammo() / ammoCapacity)); + bars.add(new Bar("blocks.ammo", Pal.ammo, () -> (float)unit.ammo / ammoCapacity)); bars.row(); } }).growX(); @@ -129,12 +146,37 @@ public class UnitType extends UnlockableContent{ @CallSuper @Override public void init(){ + if(constructor == null) throw new IllegalArgumentException("no constructor set up for unit '" + name + "'"); + //set up default range if(range < 0){ for(Weapon weapon : weapons){ range = Math.max(range, weapon.bullet.range()); } } + + //add mirrored weapon variants + Seq mapped = new Seq<>(); + for(Weapon w : weapons){ + mapped.add(w); + + //mirrors are copies with X values negated + if(w.mirror){ + Weapon copy = w.copy(); + copy.x *= -1; + copy.shootX *= -1; + copy.flipSprite = !copy.flipSprite; + mapped.add(copy); + + //since there are now two weapons, the reload time must be doubled + w.reload *= 2f; + copy.reload *= 2f; + + w.otherSide = mapped.size - 1; + copy.otherSide = mapped.size - 2; + } + } + this.weapons = mapped; } @CallSuper @@ -159,6 +201,11 @@ public class UnitType extends UnlockableContent{ partRegions[i] = Core.atlas.find(name + "-part" + i); partCellRegions[i] = Core.atlas.find(name + "-cell" + i); } + + wreckRegions = new TextureRegion[3]; + for(int i = 0; i < wreckRegions.length; i++){ + wreckRegions[i] = Core.atlas.find(name + "-wreck" + i); + } } @Override @@ -168,9 +215,9 @@ public class UnitType extends UnlockableContent{ //region drawing - public void draw(Unitc unit){ + public void draw(Unit unit){ Mechc legs = unit instanceof Mechc ? (Mechc)unit : null; - float z = unit.elevation() > 0.5f ? (lowAltitude ? Layer.flyingUnitLow : Layer.flyingUnit) : Layer.groundUnit; + float z = unit.elevation > 0.5f ? (lowAltitude ? Layer.flyingUnitLow : Layer.flyingUnit) : groundLayer; if(unit.controller().isBeingControlled(player.unit())){ drawControl(unit); @@ -184,21 +231,21 @@ public class UnitType extends UnlockableContent{ Draw.z(z - 0.02f); if(legs != null){ - drawMech(legs); + drawMech((Unit & Mechc)legs); float ft = Mathf.sin(legs.walkTime(), 3f, 3f); - legOffset.trns(legs.baseRotation(), 0f, Mathf.lerp(ft * 0.18f * sway, 0f, unit.elevation())); + legOffset.trns(legs.baseRotation(), 0f, Mathf.lerp(ft * 0.18f * sway, 0f, unit.elevation)); unit.trns(legOffset.x, legOffset.y); } if(unit instanceof Legsc){ - drawLegs((Legsc)unit); + drawLegs((Unit & Legsc)unit); } Draw.z(Math.min(z - 0.01f, Layer.bullet - 1f)); if(unit instanceof Payloadc){ - drawPayload((Payloadc)unit); + drawPayload((Unit & Payloadc)unit); } drawOcclusion(unit); @@ -211,45 +258,53 @@ public class UnitType extends UnlockableContent{ if(drawItems) drawItems(unit); drawLight(unit); - if(unit.shieldAlpha() > 0){ + if(unit.shieldAlpha > 0 && drawShields){ drawShield(unit); } if(legs != null){ unit.trns(-legOffset.x, -legOffset.y); } + + if(abilities.size > 0){ + for(Ability a : abilities){ + a.draw(unit); + Draw.reset(); + } + } } - public void drawPayload(Payloadc unit){ + public void drawPayload(T unit){ if(unit.hasPayload()){ Payload pay = unit.payloads().first(); - pay.set(unit.x(), unit.y(), unit.rotation()); + pay.set(unit.x, unit.y, unit.rotation); pay.draw(); } } - public void drawShield(Unitc unit){ + public void drawShield(Unit unit){ float alpha = unit.shieldAlpha(); float radius = unit.hitSize() * 1.3f; - Fill.light(unit.x(), unit.y(), Lines.circleVertices(radius), radius, Tmp.c1.set(Pal.shieldIn), Tmp.c2.set(Pal.shield).lerp(Color.white, Mathf.clamp(unit.hitTime() / 2f)).a(Pal.shield.a * alpha)); + Fill.light(unit.x, unit.y, Lines.circleVertices(radius), radius, Tmp.c1.set(Pal.shieldIn), Tmp.c2.set(Pal.shield).lerp(Color.white, Mathf.clamp(unit.hitTime() / 2f)).a(Pal.shield.a * alpha)); } - public void drawControl(Unitc unit){ + public void drawControl(Unit unit){ Draw.z(Layer.groundUnit - 2); Draw.color(Pal.accent, Color.white, Mathf.absin(4f, 0.3f)); - Lines.poly(unit.x(), unit.y(), 4, unit.hitSize() + 1.5f); + Lines.poly(unit.x, unit.y, 4, unit.hitSize + 1.5f); Draw.reset(); } - public void drawShadow(Unitc unit){ + public void drawShadow(Unit unit){ Draw.color(shadowColor); - Draw.rect(shadowRegion, unit.x() + shadowTX * unit.elevation(), unit.y() + shadowTY * unit.elevation(), unit.rotation() - 90); + float e = Math.max(unit.elevation, visualElevation); + Draw.rect(shadowRegion, unit.x + shadowTX * e, unit.y + shadowTY * e, unit.rotation - 90); Draw.color(); } - public void drawOcclusion(Unitc unit){ + public void drawOcclusion(Unit unit){ Draw.color(0, 0, 0, 0.4f); float rad = 1.6f; float size = Math.max(region.getWidth(), region.getHeight()) * Draw.scl; @@ -257,32 +312,32 @@ public class UnitType extends UnlockableContent{ Draw.color(); } - public void drawItems(Unitc unit){ + public void drawItems(Unit unit){ applyColor(unit); //draw back items - if(unit.hasItem() && unit.itemTime() > 0.01f){ - float size = (itemSize + Mathf.absin(Time.time(), 5f, 1f)) * unit.itemTime(); + if(unit.hasItem() && unit.itemTime > 0.01f){ + float size = (itemSize + Mathf.absin(Time.time(), 5f, 1f)) * unit.itemTime; Draw.mixcol(Pal.accent, Mathf.absin(Time.time(), 5f, 0.5f)); Draw.rect(unit.item().icon(Cicon.medium), - unit.x() + Angles.trnsx(unit.rotation() + 180f, itemOffsetY), - unit.y() + Angles.trnsy(unit.rotation() + 180f, itemOffsetY), - size, size, unit.rotation()); + unit.x + Angles.trnsx(unit.rotation + 180f, itemOffsetY), + unit.y + Angles.trnsy(unit.rotation + 180f, itemOffsetY), + size, size, unit.rotation); Draw.mixcol(); Lines.stroke(1f, Pal.accent); Lines.circle( - unit.x() + Angles.trnsx(unit.rotation() + 180f, itemOffsetY), - unit.y() + Angles.trnsy(unit.rotation() + 180f, itemOffsetY), - (3f + Mathf.absin(Time.time(), 5f, 1f)) * unit.itemTime()); + unit.x + Angles.trnsx(unit.rotation + 180f, itemOffsetY), + unit.y + Angles.trnsy(unit.rotation + 180f, itemOffsetY), + (3f + Mathf.absin(Time.time(), 5f, 1f)) * unit.itemTime); if(unit.isLocal()){ - Fonts.outline.draw(unit.stack().amount + "", - unit.x() + Angles.trnsx(unit.rotation() + 180f, itemOffsetY), - unit.y() + Angles.trnsy(unit.rotation() + 180f, itemOffsetY) - 3, - Pal.accent, 0.25f * unit.itemTime() / Scl.scl(1f), false, Align.center + Fonts.outline.draw(unit.stack.amount + "", + unit.x + Angles.trnsx(unit.rotation + 180f, itemOffsetY), + unit.y + Angles.trnsy(unit.rotation + 180f, itemOffsetY) - 3, + Pal.accent, 0.25f * unit.itemTime / Scl.scl(1f), false, Align.center ); } @@ -290,87 +345,81 @@ public class UnitType extends UnlockableContent{ } } - public void drawEngine(Unitc unit){ + public void drawEngine(Unit unit){ if(!unit.isFlying()) return; - float scale = unit.elevation(); + float scale = unit.elevation; float offset = engineOffset/2f + engineOffset/2f*scale; if(unit instanceof Trailc){ Trail trail = ((Trailc)unit).trail(); - trail.draw(unit.team().color, (engineSize + Mathf.absin(Time.time(), 2f, engineSize / 4f) * scale)); + trail.draw(unit.team.color, (engineSize + Mathf.absin(Time.time(), 2f, engineSize / 4f) * scale)); } - Draw.color(unit.team().color); + Draw.color(unit.team.color); Fill.circle( - unit.x() + Angles.trnsx(unit.rotation() + 180, offset), - unit.y() + Angles.trnsy(unit.rotation() + 180, offset), + unit.x + Angles.trnsx(unit.rotation + 180, offset), + unit.y + Angles.trnsy(unit.rotation + 180, offset), (engineSize + Mathf.absin(Time.time(), 2f, engineSize / 4f)) * scale ); Draw.color(Color.white); Fill.circle( - unit.x() + Angles.trnsx(unit.rotation() + 180, offset - 1f), - unit.y() + Angles.trnsy(unit.rotation() + 180, offset - 1f), + unit.x + Angles.trnsx(unit.rotation + 180, offset - 1f), + unit.y + Angles.trnsy(unit.rotation + 180, offset - 1f), (engineSize + Mathf.absin(Time.time(), 2f, engineSize / 4f)) / 2f * scale ); Draw.color(); } - public void drawWeapons(Unitc unit){ + public void drawWeapons(Unit unit){ applyColor(unit); - for(WeaponMount mount : unit.mounts()){ + for(WeaponMount mount : unit.mounts){ Weapon weapon = mount.weapon; - for(int i : (weapon.mirror ? Mathf.signs : Mathf.one)){ - i *= Mathf.sign(weapon.flipped); + float rotation = unit.rotation - 90; + float weaponRotation = rotation + (weapon.rotate ? mount.rotation : 0); + float width = weapon.region.getWidth(); + float recoil = -((mount.reload) / weapon.reload * weapon.recoil); - float rotation = unit.rotation() - 90; - float weaponRotation = rotation + (weapon.rotate ? mount.rotation : 0); - float width = i > 0 ? -weapon.region.getWidth() : weapon.region.getWidth(); - float recoil = -(mount.reload / weapon.reload * weapon.recoil) * (weapon.alternate ? Mathf.num(i == Mathf.sign(mount.side)) : 1); - - if(weapon.mirror) rotation = weaponRotation; - - Draw.rect(weapon.region, - unit.x() + Angles.trnsx(rotation, weapon.x * i, weapon.y) + Angles.trnsx(weaponRotation, 0, recoil), - unit.y() + Angles.trnsy(rotation, weapon.x * i, weapon.y) + Angles.trnsy(weaponRotation, 0, recoil), - width * Draw.scl * -Mathf.sign(weapon.flipSprite), - weapon.region.getHeight() * Draw.scl, - weaponRotation); - } + Draw.rect(weapon.region, + unit.x + Angles.trnsx(rotation, weapon.x, weapon.y) + Angles.trnsx(weaponRotation, 0, recoil), + unit.y + Angles.trnsy(rotation, weapon.x, weapon.y) + Angles.trnsy(weaponRotation, 0, recoil), + width * Draw.scl * -Mathf.sign(weapon.flipSprite), + weapon.region.getHeight() * Draw.scl, + weaponRotation); } Draw.reset(); } - public void drawBody(Unitc unit){ + public void drawBody(Unit unit){ applyColor(unit); - Draw.rect(region, unit, unit.rotation() - 90); + Draw.rect(region, unit, unit.rotation - 90); Draw.reset(); } - public void drawCell(Unitc unit){ + public void drawCell(Unit unit){ applyColor(unit); Draw.color(cellColor(unit)); - Draw.rect(cellRegion, unit, unit.rotation() - 90); + Draw.rect(cellRegion, unit, unit.rotation - 90); Draw.reset(); } - public Color cellColor(Unitc unit){ - return Tmp.c1.set(Color.black).lerp(unit.team().color, unit.healthf() + Mathf.absin(Time.time(), Math.max(unit.healthf() * 5f, 1f), 1f - unit.healthf())); + public Color cellColor(Unit unit){ + return Tmp.c1.set(Color.black).lerp(unit.team.color, unit.healthf() + Mathf.absin(Time.time(), Math.max(unit.healthf() * 5f, 1f), 1f - unit.healthf())); } - public void drawLight(Unitc unit){ + public void drawLight(Unit unit){ if(lightRadius > 0){ - Drawf.light(unit.team(), unit, lightRadius, lightColor, lightOpacity); + Drawf.light(unit.team, unit, lightRadius, lightColor, lightOpacity); } } - public void drawLegs(Legsc unit){ + public void drawLegs(T unit){ //Draw.z(Layer.groundUnit - 0.02f); Leg[] legs = unit.legs(); @@ -384,7 +433,7 @@ public class UnitType extends UnlockableContent{ //TODO should be below/above legs if(baseRegion.found()){ - Draw.rect(baseRegion, unit.x(), unit.y(), rotation); + Draw.rect(baseRegion, unit.x, unit.y, rotation); } //TODO figure out layering @@ -398,8 +447,8 @@ public class UnitType extends UnlockableContent{ Tmp.v1.set(leg.base).sub(leg.joint).inv().setLength(legExtension); - if(leg.moving && baseElevation > 0){ - float scl = baseElevation; + if(leg.moving && visualElevation > 0){ + float scl = visualElevation; float elev = Mathf.slope(1f - leg.stage) * scl; Draw.color(shadowColor); Draw.rect(footRegion, leg.base.x + shadowTX * elev, leg.base.y + shadowTY * elev, position.angleTo(leg.base)); @@ -426,14 +475,14 @@ public class UnitType extends UnlockableContent{ Draw.reset(); } - public void drawMech(Mechc unit){ + public void drawMech(T unit){ Draw.reset(); - Draw.mixcol(Color.white, unit.hitTime()); + Draw.mixcol(Color.white, unit.hitTime); - float e = unit.elevation(); + float e = unit.elevation; float sin = Mathf.lerp(Mathf.sin(unit.walkTime(), 3f, 1f), 0f, e); - float ft = sin*(2.5f + (unit.hitSize()-8f)/2f); + float ft = sin*(2.5f + (unit.hitSize-8f)/2f); float boostTrns = e * 2f; Floor floor = unit.isFlying() ? Blocks.air.asFloor() : unit.floorOn(); @@ -444,8 +493,8 @@ public class UnitType extends UnlockableContent{ for(int i : Mathf.signs){ Draw.rect(legRegion, - unit.x() + Angles.trnsx(unit.baseRotation(), ft * i - boostTrns, -boostTrns*i), - unit.y() + Angles.trnsy(unit.baseRotation(), ft * i - boostTrns, -boostTrns*i), + unit.x + Angles.trnsx(unit.baseRotation(), ft * i - boostTrns, -boostTrns*i), + unit.y + Angles.trnsy(unit.baseRotation(), ft * i - boostTrns, -boostTrns*i), legRegion.getWidth() * i * Draw.scl, legRegion.getHeight() * Draw.scl - Math.max(-sin * i, 0) * legRegion.getHeight() * 0.5f * Draw.scl, unit.baseRotation() - 90 + 35f*i*e); @@ -462,10 +511,10 @@ public class UnitType extends UnlockableContent{ Draw.mixcol(); } - public void applyColor(Unitc unit){ - Draw.mixcol(Color.white, unit.hitTime()); - if(unit.drownTime() > 0 && unit.floorOn().isDeep()){ - Draw.mixcol(unit.floorOn().mapColor, unit.drownTime() * 0.8f); + public void applyColor(Unit unit){ + Draw.mixcol(Color.white, unit.hitTime); + if(unit.drownTime > 0 && unit.floorOn().isDeep()){ + Draw.mixcol(unit.floorOn().mapColor, unit.drownTime * 0.8f); } } diff --git a/core/src/mindustry/type/Weapon.java b/core/src/mindustry/type/Weapon.java index 1dde54513f..c9f9505c2e 100644 --- a/core/src/mindustry/type/Weapon.java +++ b/core/src/mindustry/type/Weapon.java @@ -8,6 +8,7 @@ import mindustry.content.*; import mindustry.entities.*; import mindustry.entities.bullet.*; import mindustry.gen.*; +import mindustry.io.*; public class Weapon{ /** displayed weapon region */ @@ -16,12 +17,12 @@ public class Weapon{ public @NonNull BulletType bullet; /** shell ejection effect */ public Effect ejectEffect = Fx.none; - /** whether to mirror the weapon (draw two of them, which is the default) */ + /** whether to create a flipped copy of this weapon upon initialization. default: true */ public boolean mirror = true; - /** whether to flip the weapon's position/side on the ship (only valid when mirror is false) */ - public boolean flipped = false, flipSprite = false; + /** whether to flip the weapon's sprite when rendering */ + public boolean flipSprite = false; /** whether to shoot the weapons in different arms one after another, rather than all at once; only valid when mirror = true */ - public boolean alternate = false; + public boolean alternate = true; /** whether to rotate toward the target independently of unit */ public boolean rotate = false; /** rotation speed of weapon when rotation is enabled, in degrees/t*/ @@ -31,7 +32,7 @@ public class Weapon{ /** amount of shots per fire */ public int shots = 1; /** spacing in degrees between multiple shots, if applicable */ - public float spacing = 12f; + public float spacing = 0; /** inaccuracy of degrees of each shot */ public float inaccuracy = 0f; /** intensity and duration of each shot's screen shake */ @@ -50,6 +51,8 @@ public class Weapon{ public float shootCone = 5f; /** whether shooter rotation is ignored when shooting. */ public boolean ignoreRotation = false; + /** internal value used for alternation - do not change! */ + public int otherSide = -1; /** sound used for shooting */ public Sound shootSound = Sounds.pew; /** displayed region (autoloaded) */ @@ -63,6 +66,12 @@ public class Weapon{ this(""); } + public Weapon copy(){ + Weapon out = new Weapon(); + JsonIO.json().copyFields(this, out); + return out; + } + public void load(){ region = Core.atlas.find(name, Core.atlas.find("clear")); } diff --git a/core/src/mindustry/type/Weather.java b/core/src/mindustry/type/Weather.java index 3910b22017..6ea132e428 100644 --- a/core/src/mindustry/type/Weather.java +++ b/core/src/mindustry/type/Weather.java @@ -17,9 +17,9 @@ public abstract class Weather extends MappableContent{ //internals public Rand rand = new Rand(); - public Prov type = WeatherEntity::create; + public Prov type = WeatherState::create; - public Weather(String name, Prov type){ + public Weather(String name, Prov type){ super(name); this.type = type; } @@ -28,16 +28,16 @@ public abstract class Weather extends MappableContent{ super(name); } - public Weatherc create(){ + public WeatherState create(){ return create(1f); } - public Weatherc create(float intensity){ + public WeatherState create(float intensity){ return create(intensity, duration); } - public Weatherc create(float intensity, float duration){ - Weatherc entity = type.get(); + public WeatherState create(float intensity, float duration){ + WeatherState entity = type.get(); entity.intensity(intensity); entity.init(this); entity.life(duration); @@ -54,15 +54,15 @@ public abstract class Weather extends MappableContent{ if(e != null) e.remove(); } - public void update(Weatherc state){ + public void update(WeatherState state){ } - public void drawOver(Weatherc state){ + public void drawOver(WeatherState state){ } - public void drawUnder(Weatherc state){ + public void drawUnder(WeatherState state){ } @@ -107,9 +107,9 @@ public abstract class Weather extends MappableContent{ } } - @EntityDef(value = {Weatherc.class}, pooled = true, isFinal = false) - @Component - abstract static class WeatherComp implements Drawc{ + @EntityDef(value = {WeatherStatec.class}, pooled = true, isFinal = false) + @Component(base = true) + abstract static class WeatherStateComp implements Drawc{ private static final float fadeTime = 60 * 4; Weather weather; @@ -124,12 +124,12 @@ public abstract class Weather extends MappableContent{ if(life < fadeTime){ opacity = life / fadeTime; }else{ - opacity = Mathf.lerpDelta(opacity, 1f, 0.01f); + opacity = Mathf.lerpDelta(opacity, 1f, 0.004f); } life -= Time.delta(); - weather.update((Weatherc)this); + weather.update(base()); if(life < 0){ remove(); @@ -142,14 +142,14 @@ public abstract class Weather extends MappableContent{ Draw.draw(Layer.weather, () -> { weather.rand.setSeed(0); Draw.alpha(renderer.weatherAlpha() * opacity); - weather.drawOver((Weatherc)this); + weather.drawOver(base()); Draw.reset(); }); Draw.draw(Layer.debris, () -> { weather.rand.setSeed(0); Draw.alpha(renderer.weatherAlpha() * opacity); - weather.drawUnder((Weatherc)this); + weather.drawUnder(base()); Draw.reset(); }); } diff --git a/core/src/mindustry/ui/ContentDisplay.java b/core/src/mindustry/ui/ContentDisplay.java index 7208c42f41..524c1dfb7b 100644 --- a/core/src/mindustry/ui/ContentDisplay.java +++ b/core/src/mindustry/ui/ContentDisplay.java @@ -84,9 +84,6 @@ public class ContentDisplay{ table.left().defaults().fillX(); - table.add(Core.bundle.format("item.corestorable", item.type == ItemType.material ? Core.bundle.format("yes") : Core.bundle.format("no"))); - table.row(); - table.add(Core.bundle.format("item.explosiveness", (int)(item.explosiveness * 100))); table.row(); table.add(Core.bundle.format("item.flammability", (int)(item.flammability * 100))); diff --git a/core/src/mindustry/ui/CoreItemsDisplay.java b/core/src/mindustry/ui/CoreItemsDisplay.java index 11d0511376..cb9e92fd47 100644 --- a/core/src/mindustry/ui/CoreItemsDisplay.java +++ b/core/src/mindustry/ui/CoreItemsDisplay.java @@ -3,7 +3,6 @@ package mindustry.ui; import arc.scene.ui.layout.*; import arc.struct.*; import mindustry.*; -import mindustry.gen.*; import mindustry.type.*; import mindustry.world.blocks.storage.CoreBlock.*; @@ -22,7 +21,8 @@ public class CoreItemsDisplay extends Table{ void rebuild(){ clear(); - background(Tex.button); + background(Styles.black6); + margin(4); update(() -> { CoreEntity core = Vars.player.team().core(); @@ -40,10 +40,10 @@ public class CoreItemsDisplay extends Table{ CoreEntity core = Vars.player.team().core(); for(Item item : content.items()){ if(usedItems.contains(item)){ - image(item.icon(Cicon.medium)).padRight(4); - label(() -> core == null ? "0" : ui.formatAmount(core.items.get(item))).padRight(4); + image(item.icon(Cicon.small)).padRight(3); + label(() -> core == null ? "0" : ui.formatAmount(core.items.get(item))).padRight(3); - if(++i % 2 == 0){ + if(++i % 4 == 0){ row(); } } diff --git a/core/src/mindustry/ui/ItemsDisplay.java b/core/src/mindustry/ui/ItemsDisplay.java index 4781c4d677..351b3f17f2 100644 --- a/core/src/mindustry/ui/ItemsDisplay.java +++ b/core/src/mindustry/ui/ItemsDisplay.java @@ -30,7 +30,7 @@ public class ItemsDisplay extends Table{ t.marginRight(30f); t.left(); for(Item item : content.items()){ - if(item.type == ItemType.material && item.unlocked()){ + if(item.unlocked()){ t.label(() -> format(item)).left(); t.image(item.icon(Cicon.small)).size(8 * 3).padLeft(4).padRight(4); t.add(item.localizedName).color(Color.lightGray).left(); diff --git a/core/src/mindustry/ui/Styles.java b/core/src/mindustry/ui/Styles.java index d4838ae382..88fde61aab 100644 --- a/core/src/mindustry/ui/Styles.java +++ b/core/src/mindustry/ui/Styles.java @@ -23,7 +23,7 @@ import static mindustry.gen.Tex.*; @StyleDefaults public class Styles{ - public static Drawable black, black9, black8, black6, black3, none, flatDown, flatOver; + public static Drawable black, black9, black8, black6, black3, black5, none, flatDown, flatOver; public static ButtonStyle defaultb, waveb; public static TextButtonStyle defaultt, squaret, nodet, cleart, discordt, infot, clearPartialt, clearTogglet, clearToggleMenut, togglet, transt; public static ImageButtonStyle defaulti, nodei, righti, emptyi, emptytogglei, selecti, cleari, clearFulli, clearPartiali, clearPartial2i, clearTogglei, clearTransi, clearToggleTransi, clearTogglePartiali; @@ -40,6 +40,7 @@ public class Styles{ black9 = whiteui.tint(0f, 0f, 0f, 0.9f); black8 = whiteui.tint(0f, 0f, 0f, 0.8f); black6 = whiteui.tint(0f, 0f, 0f, 0.6f); + black5 = whiteui.tint(0f, 0f, 0f, 0.5f); black3 = whiteui.tint(0f, 0f, 0f, 0.3f); none = whiteui.tint(0f, 0f, 0f, 0f); flatDown = createFlatDown(); @@ -193,6 +194,9 @@ public class Styles{ down = flatDown; up = none; over = flatOver; + disabled = none; + imageDisabledColor = Color.gray; + imageUpColor = Color.white; }}; clearPartial2i = new ImageButtonStyle(){{ down = whiteui; diff --git a/core/src/mindustry/ui/dialogs/CustomGameDialog.java b/core/src/mindustry/ui/dialogs/CustomGameDialog.java index 1d7aa2d07b..f3f4e6b029 100644 --- a/core/src/mindustry/ui/dialogs/CustomGameDialog.java +++ b/core/src/mindustry/ui/dialogs/CustomGameDialog.java @@ -2,7 +2,6 @@ package mindustry.ui.dialogs; import arc.*; import arc.graphics.g2d.*; -import arc.math.*; import arc.scene.style.*; import arc.scene.ui.*; import arc.scene.ui.layout.*; diff --git a/core/src/mindustry/ui/dialogs/DatabaseDialog.java b/core/src/mindustry/ui/dialogs/DatabaseDialog.java index 9e2af57df8..3a12350a19 100644 --- a/core/src/mindustry/ui/dialogs/DatabaseDialog.java +++ b/core/src/mindustry/ui/dialogs/DatabaseDialog.java @@ -37,7 +37,7 @@ public class DatabaseDialog extends BaseDialog{ Seq[] allContent = Vars.content.getContentMap(); for(int j = 0; j < allContent.length; j++){ - ContentType type = ContentType.values()[j]; + ContentType type = ContentType.all[j]; Seq array = allContent[j].select(c -> c instanceof UnlockableContent && !((UnlockableContent)c).isHidden()); if(array.size == 0) continue; diff --git a/core/src/mindustry/ui/dialogs/JoinDialog.java b/core/src/mindustry/ui/dialogs/JoinDialog.java index fcd62af0b8..60d0926e2e 100644 --- a/core/src/mindustry/ui/dialogs/JoinDialog.java +++ b/core/src/mindustry/ui/dialogs/JoinDialog.java @@ -263,7 +263,7 @@ public class JoinDialog extends BaseDialog{ Core.settings.put("name", text); }).grow().pad(8).get().setMaxLength(maxNameLength); }else{ - t.add(player.name()).update(l -> l.setColor(player.color())).grow().pad(8); + t.add(player.name).update(l -> l.setColor(player.color())).grow().pad(8); } ImageButton button = t.button(Tex.whiteui, Styles.clearFulli, 40, () -> { @@ -379,7 +379,7 @@ public class JoinDialog extends BaseDialog{ } public void connect(String ip, int port){ - if(player.name().trim().isEmpty()){ + if(player.name.trim().isEmpty()){ ui.showInfo("$noname"); return; } diff --git a/core/src/mindustry/ui/dialogs/LaunchLoadoutDialog.java b/core/src/mindustry/ui/dialogs/LaunchLoadoutDialog.java new file mode 100644 index 0000000000..3042aba33d --- /dev/null +++ b/core/src/mindustry/ui/dialogs/LaunchLoadoutDialog.java @@ -0,0 +1,116 @@ +package mindustry.ui.dialogs; + +import arc.*; +import arc.func.*; +import arc.scene.ui.*; +import arc.scene.ui.layout.*; +import arc.struct.*; +import mindustry.game.*; +import mindustry.gen.*; +import mindustry.type.*; +import mindustry.ui.*; +import mindustry.ui.dialogs.SchematicsDialog.*; +import mindustry.world.blocks.storage.*; + +import static mindustry.Vars.*; + +/** Dialog for selecting loadout at sector launch. */ +public class LaunchLoadoutDialog extends BaseDialog{ + LoadoutDialog loadout = new LoadoutDialog(); + //total as a map + ObjectIntMap totalMap = new ObjectIntMap<>(); + //total required items + Seq total = new Seq<>(); + //currently selected schematic + Schematic selected; + //validity of loadout items + boolean valid; + + public LaunchLoadoutDialog(){ + super("$configure"); + } + + public void show(CoreBlock core, Building build, Runnable confirm){ + cont.clear(); + buttons.clear(); + totalMap.clear(); + + Seq stacks = universe.getLaunchResources(); + + addCloseButton(); + + //updates sum requirements + Runnable update = () -> { + totalMap.clear(); + total.clear(); + selected.requirements().each(i -> totalMap.increment(i.item, i.amount)); + universe.getLaunchResources().each(i -> totalMap.increment(i.item, i.amount)); + for(Item item : content.items()){ + if(totalMap.containsKey(item)) total.add(new ItemStack(item, totalMap.get(item))); + } + valid = build.items.has(total); + }; + + Cons rebuild = table -> { + table.clearChildren(); + int i = 0; + + for(ItemStack s : total){ + table.image(s.item.icon(Cicon.small)).left(); + table.add((build.items.has(s.item, s.amount)) ? "[lightgray]" + s.amount + "" : + "[scarlet]" + (Math.min(build.items.get(s.item), s.amount) + "[lightgray]/" + s.amount)).padLeft(2).left().padRight(4); + + if(++i % 4 == 0){ + table.row(); + } + } + }; + + Table items = new Table(); + + Runnable rebuildItems = () -> rebuild.get(items); + + buttons.button("$resources", Icon.terrain, () -> { + loadout.show(core.itemCapacity, stacks, stacks::clear, () -> {}, () -> { + universe.updateLaunchResources(stacks); + update.run(); + rebuildItems.run(); + }); + }); + + buttons.button("$launch.text", Icon.ok, () -> { + universe.updateLoadout(core, selected); + confirm.run(); + hide(); + }).disabled(b -> !valid); + + int cols = Math.max((int)(Core.graphics.getWidth() / Scl.scl(230)), 1); + ButtonGroup