Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33d4ab9edb | ||
|
|
f7f2b3438c | ||
|
|
0ed7934df0 | ||
|
|
55920e6242 | ||
|
|
820920e5f9 | ||
|
|
8e21c627a7 | ||
|
|
6973ed7d55 | ||
|
|
0980495a28 | ||
|
|
5c6b659ce3 | ||
|
|
35e263223d | ||
|
|
07ba378095 | ||
|
|
6e10f86546 | ||
|
|
fc6ee11ffe | ||
|
|
84cd87370f | ||
|
|
822fe9ab7a | ||
|
|
57b22a9cab | ||
|
|
278c4f17e5 | ||
|
|
b0d4607798 | ||
|
|
3f7dc66ac0 | ||
|
|
1c2b1fb757 | ||
|
|
eb31483a15 | ||
|
|
8fb7cdaba6 | ||
|
|
61d81046ae | ||
|
|
0c3d7e09e0 | ||
|
|
a9f9ddcacf | ||
|
|
a559c3581e | ||
|
|
dd5389c738 | ||
|
|
ac25e17286 | ||
|
|
9de4c89e76 | ||
|
|
2f6846d8c3 | ||
|
|
c3e60531c4 | ||
|
|
44aff82a6c | ||
|
|
7619e7643d | ||
|
|
353ef05b93 | ||
|
|
2801e4ed80 | ||
|
|
173dd0a90e | ||
|
|
e5412aeb1b | ||
|
|
0eec955a3d | ||
|
|
47038ac06d | ||
|
|
8041c305ad | ||
|
|
e0d249898e |
@@ -1,5 +1,7 @@
|
|||||||
package mindustry.annotations.impl;
|
package mindustry.annotations.impl;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
|
import arc.audio.*;
|
||||||
import arc.files.*;
|
import arc.files.*;
|
||||||
import arc.scene.style.*;
|
import arc.scene.style.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
@@ -118,9 +120,31 @@ public class AssetsProcess extends BaseProcessor{
|
|||||||
void processSounds(String classname, String path, String rtype) throws Exception{
|
void processSounds(String classname, String path, String rtype) throws Exception{
|
||||||
TypeSpec.Builder type = TypeSpec.classBuilder(classname).addModifiers(Modifier.PUBLIC);
|
TypeSpec.Builder type = TypeSpec.classBuilder(classname).addModifiers(Modifier.PUBLIC);
|
||||||
MethodSpec.Builder loadBegin = MethodSpec.methodBuilder("load").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
|
MethodSpec.Builder loadBegin = MethodSpec.methodBuilder("load").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
|
||||||
|
CodeBlock.Builder staticb = CodeBlock.builder();
|
||||||
|
|
||||||
|
type.addField(FieldSpec.builder(IntMap.class, "idToSound", Modifier.STATIC, Modifier.PRIVATE).initializer("new IntMap()").build());
|
||||||
|
type.addField(FieldSpec.builder(ObjectIntMap.class, "soundToId", Modifier.STATIC, Modifier.PRIVATE).initializer("new ObjectIntMap()").build());
|
||||||
|
|
||||||
|
type.addMethod(MethodSpec.methodBuilder("getSoundId")
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||||
|
.addParameter(Sound.class, "sound")
|
||||||
|
.returns(int.class)
|
||||||
|
.addStatement("return soundToId.get(sound, -1)").build());
|
||||||
|
|
||||||
|
type.addMethod(MethodSpec.methodBuilder("getSound")
|
||||||
|
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||||
|
.addParameter(int.class, "id")
|
||||||
|
.returns(Sound.class)
|
||||||
|
.addStatement("return (Sound)idToSound.get(id, () -> Sounds.none)").build());
|
||||||
|
|
||||||
HashSet<String> names = new HashSet<>();
|
HashSet<String> names = new HashSet<>();
|
||||||
Fi.get(path).walk(p -> {
|
Seq<Fi> files = new Seq<>();
|
||||||
|
Fi.get(path).walk(files::add);
|
||||||
|
|
||||||
|
files.sortComparing(Fi::name);
|
||||||
|
int id = 0;
|
||||||
|
|
||||||
|
for(Fi p : files){
|
||||||
String name = p.nameWithoutExtension();
|
String name = p.nameWithoutExtension();
|
||||||
|
|
||||||
if(names.contains(name)){
|
if(names.contains(name)){
|
||||||
@@ -133,14 +157,20 @@ public class AssetsProcess extends BaseProcessor{
|
|||||||
|
|
||||||
String filepath = path.substring(path.lastIndexOf("/") + 1) + p.path().substring(p.path().lastIndexOf(path) + path.length());
|
String filepath = path.substring(path.lastIndexOf("/") + 1) + p.path().substring(p.path().lastIndexOf(path) + path.length());
|
||||||
|
|
||||||
String filename = "\"" + filepath + "\"";
|
staticb.addStatement("soundToId.put($L, $L)", name, id);
|
||||||
loadBegin.addStatement("arc.Core.assets.load(" + filename + ", " + rtype + ".class).loaded = a -> " + name + " = (" + rtype + ")a", filepath, filepath.replace(".ogg", ".mp3"));
|
|
||||||
|
|
||||||
type.addField(FieldSpec.builder(ClassName.bestGuess(rtype), name, Modifier.STATIC, Modifier.PUBLIC).initializer("new arc.audio." + rtype.substring(rtype.lastIndexOf(".") + 1) + "()").build());
|
loadBegin.addStatement("$T.assets.load($S, $L.class).loaded = a -> { $L = ($L)a; soundToId.put(a, $L); idToSound.put($L, a); }",
|
||||||
});
|
Core.class, filepath, rtype, name, rtype, id, id);
|
||||||
|
|
||||||
|
type.addField(FieldSpec.builder(ClassName.bestGuess(rtype), name, Modifier.STATIC, Modifier.PUBLIC).initializer("new " + rtype + "()").build());
|
||||||
|
|
||||||
|
id ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
type.addStaticBlock(staticb.build());
|
||||||
|
|
||||||
if(classname.equals("Sounds")){
|
if(classname.equals("Sounds")){
|
||||||
type.addField(FieldSpec.builder(ClassName.bestGuess(rtype), "none", Modifier.STATIC, Modifier.PUBLIC).initializer("new arc.audio." + rtype.substring(rtype.lastIndexOf(".") + 1) + "()").build());
|
type.addField(FieldSpec.builder(ClassName.bestGuess(rtype), "none", Modifier.STATIC, Modifier.PUBLIC).initializer("new " + rtype + "()").build());
|
||||||
}
|
}
|
||||||
|
|
||||||
type.addMethod(loadBegin.build());
|
type.addMethod(loadBegin.build());
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.sun.tools.javac.code.Attribute.Enum;
|
|||||||
import com.sun.tools.javac.code.Attribute.Error;
|
import com.sun.tools.javac.code.Attribute.Error;
|
||||||
import com.sun.tools.javac.code.Attribute.Visitor;
|
import com.sun.tools.javac.code.Attribute.Visitor;
|
||||||
import com.sun.tools.javac.code.Attribute.*;
|
import com.sun.tools.javac.code.Attribute.*;
|
||||||
|
import com.sun.tools.javac.code.Scope.*;
|
||||||
import com.sun.tools.javac.code.Type;
|
import com.sun.tools.javac.code.Type;
|
||||||
import com.sun.tools.javac.code.Symbol.*;
|
import com.sun.tools.javac.code.Symbol.*;
|
||||||
import com.sun.tools.javac.code.Type.ArrayType;
|
import com.sun.tools.javac.code.Type.ArrayType;
|
||||||
@@ -64,36 +65,13 @@ public class AnnotationProxyMaker{
|
|||||||
LinkedHashMap map = new LinkedHashMap();
|
LinkedHashMap map = new LinkedHashMap();
|
||||||
ClassSymbol cl = (ClassSymbol)this.anno.type.tsym;
|
ClassSymbol cl = (ClassSymbol)this.anno.type.tsym;
|
||||||
|
|
||||||
//try to use Java 8 API for this if possible
|
for(Symbol s : cl.members().getSymbols(LookupKind.NON_RECURSIVE)){
|
||||||
try{
|
if(s.getKind() == ElementKind.METHOD){
|
||||||
Class entryClass = Class.forName("com.sun.tools.javac.code.Scope$Entry");
|
MethodSymbol var4 = (MethodSymbol)s;
|
||||||
Object members = cl.members();
|
Attribute var5 = var4.getDefaultValue();
|
||||||
Field field = members.getClass().getField("elems");
|
if(var5 != null){
|
||||||
Object elems = field.get(members);
|
map.put(var4, var5);
|
||||||
Field siblingField = entryClass.getField("sibling");
|
|
||||||
Field symField = entryClass.getField("sym");
|
|
||||||
for(Object currEntry = elems; currEntry != null; currEntry = siblingField.get(currEntry)){
|
|
||||||
handleSymbol((Symbol)symField.get(currEntry), map);
|
|
||||||
}
|
|
||||||
|
|
||||||
}catch(Throwable e){
|
|
||||||
//otherwise try other API
|
|
||||||
|
|
||||||
try{
|
|
||||||
Class lookupClass = Class.forName("com.sun.tools.javac.code.Scope$LookupKind");
|
|
||||||
Field nonRecField = lookupClass.getField("NON_RECURSIVE");
|
|
||||||
Object nonRec = nonRecField.get(null);
|
|
||||||
Scope scope = cl.members();
|
|
||||||
Method getSyms = scope.getClass().getMethod("getSymbols", lookupClass);
|
|
||||||
Iterable<Symbol> it = (Iterable<Symbol>)getSyms.invoke(scope, nonRec);
|
|
||||||
Iterator<Symbol> i = it.iterator();
|
|
||||||
while(i.hasNext()){
|
|
||||||
handleSymbol(i.next(), map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}catch(Throwable death){
|
|
||||||
//I tried
|
|
||||||
throw new RuntimeException(death);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,17 +82,6 @@ public class AnnotationProxyMaker{
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSymbol(Symbol sym, LinkedHashMap map){
|
|
||||||
|
|
||||||
if(sym.getKind() == ElementKind.METHOD){
|
|
||||||
MethodSymbol var4 = (MethodSymbol)sym;
|
|
||||||
Attribute var5 = var4.getDefaultValue();
|
|
||||||
if(var5 != null){
|
|
||||||
map.put(var4, var5);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Object generateValue(MethodSymbol var1, Attribute var2){
|
private Object generateValue(MethodSymbol var1, Attribute var2){
|
||||||
AnnotationProxyMaker.ValueVisitor var3 = new AnnotationProxyMaker.ValueVisitor(var1);
|
AnnotationProxyMaker.ValueVisitor var3 = new AnnotationProxyMaker.ValueVisitor(var1);
|
||||||
return var3.getValue(var2);
|
return var3.getValue(var2);
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ import java.lang.Class;
|
|||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper over Element with added utility functions.
|
||||||
|
* I would have preferred to use extension methods for this, but Java doesn't have any.
|
||||||
|
* */
|
||||||
public class Selement<T extends Element>{
|
public class Selement<T extends Element>{
|
||||||
public final T e;
|
public final T e;
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ allprojects{
|
|||||||
if(!project.hasProperty("versionType")) versionType = 'official'
|
if(!project.hasProperty("versionType")) versionType = 'official'
|
||||||
appName = 'Mindustry'
|
appName = 'Mindustry'
|
||||||
steamworksVersion = '0b86023401880bb5e586bc404bedbaae9b1f1c94'
|
steamworksVersion = '0b86023401880bb5e586bc404bedbaae9b1f1c94'
|
||||||
rhinoVersion = '55bf0dac1cfa7770672fd26112512c733ca9d5dc'
|
rhinoVersion = '9f792d202471fb3789eab7bb261fec13d67287e2'
|
||||||
|
|
||||||
loadVersionProps = {
|
loadVersionProps = {
|
||||||
return new Properties().with{p -> p.load(file('../core/assets/version.properties').newReader()); return p }
|
return new Properties().with{p -> p.load(file('../core/assets/version.properties').newReader()); return p }
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ customgame = Custom Game
|
|||||||
newgame = New Game
|
newgame = New Game
|
||||||
none = <none>
|
none = <none>
|
||||||
none.found = [lightgray]<none found>
|
none.found = [lightgray]<none found>
|
||||||
|
none.inmap = [lightgray]<none in map>
|
||||||
minimap = Minimap
|
minimap = Minimap
|
||||||
position = Position
|
position = Position
|
||||||
close = Close
|
close = Close
|
||||||
@@ -995,6 +996,7 @@ rules.wavetimer = Wave Timer
|
|||||||
rules.waves = Waves
|
rules.waves = Waves
|
||||||
rules.attack = Attack Mode
|
rules.attack = Attack Mode
|
||||||
rules.buildai = AI Building
|
rules.buildai = AI Building
|
||||||
|
rules.cleanupdeadteams = Clean Up Defeated Team Buildings (PvP)
|
||||||
rules.corecapture = Capture Core On Destruction
|
rules.corecapture = Capture Core On Destruction
|
||||||
rules.polygoncoreprotection = Polygonal Core Protection
|
rules.polygoncoreprotection = Polygonal Core Protection
|
||||||
rules.enemyCheat = Infinite AI (Red Team) Resources
|
rules.enemyCheat = Infinite AI (Red Team) Resources
|
||||||
|
|||||||
@@ -100,7 +100,8 @@ joingame = 게임 참여
|
|||||||
customgame = 사용자 지정 게임
|
customgame = 사용자 지정 게임
|
||||||
newgame = 새 게임
|
newgame = 새 게임
|
||||||
none = < 없음 >
|
none = < 없음 >
|
||||||
none.found = [lightgray]< 없거나 찾을 수 없음 >
|
none.found = [lightgray]< 찾을 수 없음 >
|
||||||
|
none.inmap = [lightgray]< 맵에 없음 >
|
||||||
minimap = 미니맵
|
minimap = 미니맵
|
||||||
position = 위치
|
position = 위치
|
||||||
close = 닫기
|
close = 닫기
|
||||||
|
|||||||
BIN
core/assets/sounds/mineDeploy.ogg
Normal file
BIN
core/assets/sounds/mineDeploy.ogg
Normal file
Binary file not shown.
BIN
core/assets/sounds/plantBreak.ogg
Normal file
BIN
core/assets/sounds/plantBreak.ogg
Normal file
Binary file not shown.
BIN
core/assets/sounds/rockBreak.ogg
Normal file
BIN
core/assets/sounds/rockBreak.ogg
Normal file
Binary file not shown.
@@ -55,7 +55,7 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform
|
|||||||
Log.info("[GL] Max texture size: @", maxTextureSize);
|
Log.info("[GL] Max texture size: @", maxTextureSize);
|
||||||
Log.info("[GL] Using @ context.", gl30 != null ? "OpenGL 3" : "OpenGL 2");
|
Log.info("[GL] Using @ context.", gl30 != null ? "OpenGL 3" : "OpenGL 2");
|
||||||
if(maxTextureSize < 4096) Log.warn("[GL] Your maximum texture size is below the recommended minimum of 4096. This will cause severe performance issues.");
|
if(maxTextureSize < 4096) Log.warn("[GL] Your maximum texture size is below the recommended minimum of 4096. This will cause severe performance issues.");
|
||||||
Log.info("[JAVA] Version: @", System.getProperty("java.version"));
|
Log.info("[JAVA] Version: @", OS.javaVersion);
|
||||||
|
|
||||||
Time.setDeltaProvider(() -> {
|
Time.setDeltaProvider(() -> {
|
||||||
float result = Core.graphics.getDeltaTime() * 60f;
|
float result = Core.graphics.getDeltaTime() * 60f;
|
||||||
|
|||||||
@@ -24,10 +24,8 @@ import mindustry.logic.*;
|
|||||||
import mindustry.maps.Map;
|
import mindustry.maps.Map;
|
||||||
import mindustry.maps.*;
|
import mindustry.maps.*;
|
||||||
import mindustry.mod.*;
|
import mindustry.mod.*;
|
||||||
import mindustry.net.Net;
|
|
||||||
import mindustry.net.*;
|
import mindustry.net.*;
|
||||||
import mindustry.service.*;
|
import mindustry.service.*;
|
||||||
import mindustry.world.*;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.charset.*;
|
import java.nio.charset.*;
|
||||||
@@ -113,8 +111,6 @@ public class Vars implements Loadable{
|
|||||||
public static final float tilePayload = tilesize * tilesize;
|
public static final float tilePayload = tilesize * tilesize;
|
||||||
/** icon sizes for UI */
|
/** icon sizes for UI */
|
||||||
public static final float iconXLarge = 8*6f, iconLarge = 8*5f, iconMed = 8*4f, iconSmall = 8*3f;
|
public static final float iconXLarge = 8*6f, iconLarge = 8*5f, iconMed = 8*4f, iconSmall = 8*3f;
|
||||||
/** tile used in certain situations, instead of null */
|
|
||||||
public static Tile emptyTile;
|
|
||||||
/** for map generator dialog */
|
/** for map generator dialog */
|
||||||
public static boolean updateEditorOnChange = false;
|
public static boolean updateEditorOnChange = false;
|
||||||
/** all choosable player colors in join/host dialog */
|
/** all choosable player colors in join/host dialog */
|
||||||
@@ -278,7 +274,6 @@ public class Vars implements Loadable{
|
|||||||
schematicDirectory = dataDirectory.child("schematics/");
|
schematicDirectory = dataDirectory.child("schematics/");
|
||||||
bebuildDirectory = dataDirectory.child("be_builds/");
|
bebuildDirectory = dataDirectory.child("be_builds/");
|
||||||
emptyMap = new Map(new StringMap());
|
emptyMap = new Map(new StringMap());
|
||||||
emptyTile = null;
|
|
||||||
|
|
||||||
if(tree == null) tree = new FileTree();
|
if(tree == null) tree = new FileTree();
|
||||||
if(mods == null) mods = new Mods();
|
if(mods == null) mods = new Mods();
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ public class BlockIndexer{
|
|||||||
private Seq<Building> breturnArray = new Seq<>(Building.class);
|
private Seq<Building> breturnArray = new Seq<>(Building.class);
|
||||||
|
|
||||||
public BlockIndexer(){
|
public BlockIndexer(){
|
||||||
|
clearFlags();
|
||||||
|
|
||||||
Events.on(TilePreChangeEvent.class, event -> {
|
Events.on(TilePreChangeEvent.class, event -> {
|
||||||
removeIndex(event.tile);
|
removeIndex(event.tile);
|
||||||
@@ -62,11 +63,7 @@ public class BlockIndexer{
|
|||||||
flagMap = new TileArray[Team.all.length][BlockFlag.all.length];
|
flagMap = new TileArray[Team.all.length][BlockFlag.all.length];
|
||||||
activeTeams = new Seq<>(Team.class);
|
activeTeams = new Seq<>(Team.class);
|
||||||
|
|
||||||
for(int i = 0; i < flagMap.length; i++){
|
clearFlags();
|
||||||
for(int j = 0; j < BlockFlag.all.length; j++){
|
|
||||||
flagMap[i][j] = new TileArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
allOres.clear();
|
allOres.clear();
|
||||||
ores = new IntSeq[content.items().size][][];
|
ores = new IntSeq[content.items().size][][];
|
||||||
@@ -106,7 +103,7 @@ public class BlockIndexer{
|
|||||||
|
|
||||||
public void removeIndex(Tile tile){
|
public void removeIndex(Tile tile){
|
||||||
var team = tile.team();
|
var team = tile.team();
|
||||||
if(team != Team.derelict && tile.isCenter()){
|
if(tile.build != null && tile.isCenter()){
|
||||||
var flags = tile.block().flags;
|
var flags = tile.block().flags;
|
||||||
var data = team.data();
|
var data = team.data();
|
||||||
|
|
||||||
@@ -160,6 +157,14 @@ public class BlockIndexer{
|
|||||||
return blocksPresent != null && blocksPresent[block.id];
|
return blocksPresent != null && blocksPresent[block.id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void clearFlags(){
|
||||||
|
for(int i = 0; i < flagMap.length; i++){
|
||||||
|
for(int j = 0; j < BlockFlag.all.length; j++){
|
||||||
|
flagMap[i][j] = new TileArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private TileArray[] getFlagged(Team team){
|
private TileArray[] getFlagged(Team team){
|
||||||
return flagMap[team.id];
|
return flagMap[team.id];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public class BuilderAI extends AIController{
|
|||||||
@Nullable Unit following;
|
@Nullable Unit following;
|
||||||
@Nullable Teamc enemy;
|
@Nullable Teamc enemy;
|
||||||
float retreatTimer;
|
float retreatTimer;
|
||||||
|
@Nullable BlockPlan lastPlan;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateMovement(){
|
public void updateMovement(){
|
||||||
@@ -43,6 +44,7 @@ public class BuilderAI extends AIController{
|
|||||||
//set to follower's first build plan, whatever that is
|
//set to follower's first build plan, whatever that is
|
||||||
unit.plans.clear();
|
unit.plans.clear();
|
||||||
unit.plans.addFirst(following.buildPlan());
|
unit.plans.addFirst(following.buildPlan());
|
||||||
|
lastPlan = null;
|
||||||
}else if(unit.buildPlan() == null){
|
}else if(unit.buildPlan() == null){
|
||||||
//not following anyone or building
|
//not following anyone or building
|
||||||
if(timer.get(timerTarget4, 40)){
|
if(timer.get(timerTarget4, 40)){
|
||||||
@@ -78,10 +80,11 @@ public class BuilderAI extends AIController{
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean valid =
|
boolean valid =
|
||||||
(req.tile() != null && req.tile().build instanceof ConstructBuild cons && cons.current == req.block) ||
|
!(lastPlan != null && lastPlan.removed) &&
|
||||||
(req.breaking ?
|
((req.tile() != null && req.tile().build instanceof ConstructBuild cons && cons.current == req.block) ||
|
||||||
Build.validBreak(unit.team(), req.x, req.y) :
|
(req.breaking ?
|
||||||
Build.validPlace(req.block, unit.team(), req.x, req.y, req.rotation));
|
Build.validBreak(unit.team(), req.x, req.y) :
|
||||||
|
Build.validPlace(req.block, unit.team(), req.x, req.y, req.rotation)));
|
||||||
|
|
||||||
if(valid){
|
if(valid){
|
||||||
//move toward the request
|
//move toward the request
|
||||||
@@ -89,6 +92,7 @@ public class BuilderAI extends AIController{
|
|||||||
}else{
|
}else{
|
||||||
//discard invalid request
|
//discard invalid request
|
||||||
unit.plans.removeFirst();
|
unit.plans.removeFirst();
|
||||||
|
lastPlan = null;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
|
|
||||||
@@ -127,6 +131,7 @@ public class BuilderAI extends AIController{
|
|||||||
if(world.tile(block.x, block.y) != null && world.tile(block.x, block.y).block().id == block.block){
|
if(world.tile(block.x, block.y) != null && world.tile(block.x, block.y).block().id == block.block){
|
||||||
blocks.removeFirst();
|
blocks.removeFirst();
|
||||||
}else if(Build.validPlace(content.block(block.block), unit.team(), block.x, block.y, block.rotation)){ //it's valid.
|
}else if(Build.validPlace(content.block(block.block), unit.team(), block.x, block.y, block.rotation)){ //it's valid.
|
||||||
|
lastPlan = block;
|
||||||
//add build request.
|
//add build request.
|
||||||
unit.addBuild(new BuildPlan(block.x, block.y, block.rotation, content.block(block.block), block.config));
|
unit.addBuild(new BuildPlan(block.x, block.y, block.rotation, content.block(block.block), block.config));
|
||||||
//shift build plan to tail so next unit builds something else.
|
//shift build plan to tail so next unit builds something else.
|
||||||
|
|||||||
@@ -235,7 +235,6 @@ public class Blocks implements ContentList{
|
|||||||
magmarock = new Floor("magmarock"){{
|
magmarock = new Floor("magmarock"){{
|
||||||
attributes.set(Attribute.heat, 0.75f);
|
attributes.set(Attribute.heat, 0.75f);
|
||||||
attributes.set(Attribute.water, -0.75f);
|
attributes.set(Attribute.water, -0.75f);
|
||||||
updateEffect = Fx.magmasmoke;
|
|
||||||
blendGroup = basalt;
|
blendGroup = basalt;
|
||||||
|
|
||||||
emitLight = true;
|
emitLight = true;
|
||||||
@@ -369,6 +368,7 @@ public class Blocks implements ContentList{
|
|||||||
|
|
||||||
sporeCluster = new Prop("spore-cluster"){{
|
sporeCluster = new Prop("spore-cluster"){{
|
||||||
variants = 3;
|
variants = 3;
|
||||||
|
breakSound = Sounds.plantBreak;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
boulder = new Prop("boulder"){{
|
boulder = new Prop("boulder"){{
|
||||||
@@ -426,6 +426,9 @@ public class Blocks implements ContentList{
|
|||||||
|
|
||||||
darkMetal = new StaticWall("dark-metal");
|
darkMetal = new StaticWall("dark-metal");
|
||||||
|
|
||||||
|
Seq.with(metalFloor, metalFloorDamaged, metalFloor2, metalFloor3, metalFloor4, metalFloor5, darkPanel1, darkPanel2, darkPanel3, darkPanel4, darkPanel5, darkPanel6)
|
||||||
|
.each(b -> b.asFloor().wall = darkMetal);
|
||||||
|
|
||||||
pebbles = new DoubleOverlayFloor("pebbles");
|
pebbles = new DoubleOverlayFloor("pebbles");
|
||||||
|
|
||||||
tendrils = new OverlayFloor("tendrils");
|
tendrils = new OverlayFloor("tendrils");
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ public class StatusEffects implements ContentList{
|
|||||||
|
|
||||||
affinity(blasted, ((unit, result, time) -> {
|
affinity(blasted, ((unit, result, time) -> {
|
||||||
unit.damagePierce(transitionDamage);
|
unit.damagePierce(transitionDamage);
|
||||||
result.set(freezing, time);
|
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}};
|
}};
|
||||||
@@ -75,7 +74,6 @@ public class StatusEffects implements ContentList{
|
|||||||
if(unit.team == state.rules.waveTeam){
|
if(unit.team == state.rules.waveTeam){
|
||||||
Events.fire(Trigger.shock);
|
Events.fire(Trigger.shock);
|
||||||
}
|
}
|
||||||
result.set(wet, time);
|
|
||||||
}));
|
}));
|
||||||
opposite(burning, melting);
|
opposite(burning, melting);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1780,6 +1780,7 @@ public class UnitTypes implements ContentList{
|
|||||||
shots = 3;
|
shots = 3;
|
||||||
shotDelay = 7f;
|
shotDelay = 7f;
|
||||||
x = y = shootX = shootY = 0f;
|
x = y = shootX = shootY = 0f;
|
||||||
|
shootSound = Sounds.mineDeploy;
|
||||||
|
|
||||||
bullet = new BasicBulletType(){{
|
bullet = new BasicBulletType(){{
|
||||||
sprite = "mine-bullet";
|
sprite = "mine-bullet";
|
||||||
@@ -2150,6 +2151,8 @@ public class UnitTypes implements ContentList{
|
|||||||
shootY = 7f;
|
shootY = 7f;
|
||||||
recoil = 4f;
|
recoil = 4f;
|
||||||
cooldownTime = reload - 10f;
|
cooldownTime = reload - 10f;
|
||||||
|
//TODO better sound
|
||||||
|
shootSound = Sounds.laser;
|
||||||
|
|
||||||
bullet = new EmpBulletType(){{
|
bullet = new EmpBulletType(){{
|
||||||
float rad = 100f;
|
float rad = 100f;
|
||||||
@@ -2182,6 +2185,7 @@ public class UnitTypes implements ContentList{
|
|||||||
hitShake = 4f;
|
hitShake = 4f;
|
||||||
trailRotation = true;
|
trailRotation = true;
|
||||||
status = StatusEffects.electrified;
|
status = StatusEffects.electrified;
|
||||||
|
hitSound = Sounds.plasmaboom;
|
||||||
|
|
||||||
trailEffect = new Effect(16f, e -> {
|
trailEffect = new Effect(16f, e -> {
|
||||||
color(Pal.heal);
|
color(Pal.heal);
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ public class Logic implements ApplicationListener{
|
|||||||
BlockPlan b = it.next();
|
BlockPlan b = it.next();
|
||||||
Block block = content.block(b.block);
|
Block block = content.block(b.block);
|
||||||
if(event.tile.block().bounds(event.tile.x, event.tile.y, Tmp.r1).overlaps(block.bounds(b.x, b.y, Tmp.r2))){
|
if(event.tile.block().bounds(event.tile.x, event.tile.y, Tmp.r1).overlaps(block.bounds(b.x, b.y, Tmp.r2))){
|
||||||
|
b.removed = true;
|
||||||
it.remove();
|
it.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,25 +129,7 @@ public class Logic implements ApplicationListener{
|
|||||||
|
|
||||||
Events.on(SectorCaptureEvent.class, e -> {
|
Events.on(SectorCaptureEvent.class, e -> {
|
||||||
if(!net.client() && e.sector == state.getSector() && e.sector.isBeingPlayed()){
|
if(!net.client() && e.sector == state.getSector() && e.sector.isBeingPlayed()){
|
||||||
for(Tile tile : world.tiles){
|
state.rules.waveTeam.data().destroyToDerelict();
|
||||||
//convert all blocks to neutral, randomly killing them
|
|
||||||
if(tile.isCenter() && tile.build != null && tile.build.team == state.rules.waveTeam){
|
|
||||||
Building b = tile.build;
|
|
||||||
Call.setTeam(b, Team.derelict);
|
|
||||||
Time.run(Mathf.random(0f, 60f * 6f), () -> {
|
|
||||||
if(Mathf.chance(0.25)){
|
|
||||||
b.kill();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//kill all units
|
|
||||||
Groups.unit.each(u -> {
|
|
||||||
if(u.team == state.rules.waveTeam){
|
|
||||||
Time.run(Mathf.random(0f, 60f * 5f), u::kill);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -162,6 +145,12 @@ public class Logic implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//listen to core changes; if all cores have been destroyed, set to derelict.
|
||||||
|
Events.on(CoreChangeEvent.class, e -> Core.app.post(() -> {
|
||||||
|
if(state.rules.cleanupDeadTeams && state.rules.pvp && !e.core.isAdded() && e.core.team != Team.derelict && e.core.team.cores().isEmpty()){
|
||||||
|
e.core.team.data().destroyToDerelict();
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Adds starting items, resets wave time, and sets state to playing. */
|
/** Adds starting items, resets wave time, and sets state to playing. */
|
||||||
|
|||||||
@@ -159,6 +159,22 @@ public class NetClient implements ApplicationListener{
|
|||||||
clientPacketReliable(type, contents);
|
clientPacketReliable(type, contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO enable in build 129
|
||||||
|
/*
|
||||||
|
@Remote(variants = Variant.both, unreliable = true)
|
||||||
|
public static void sound(Sound sound, float volume, float pitch, float pan){
|
||||||
|
if(sound == null) return;
|
||||||
|
|
||||||
|
sound.play(volume * Core.settings.getInt("sfxvol") / 100f, pitch, pan);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Remote(variants = Variant.both, unreliable = true)
|
||||||
|
public static void soundAt(Sound sound, float x, float y, float volume, float pitch){
|
||||||
|
if(sound == null) return;
|
||||||
|
|
||||||
|
sound.at(x, y, pitch, volume);
|
||||||
|
}*/
|
||||||
|
|
||||||
@Remote(variants = Variant.both, unreliable = true)
|
@Remote(variants = Variant.both, unreliable = true)
|
||||||
public static void effect(Effect effect, float x, float y, float rotation, Color color){
|
public static void effect(Effect effect, float x, float y, float rotation, Color color){
|
||||||
if(effect == null) return;
|
if(effect == null) return;
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import static arc.scene.actions.Actions.*;
|
|||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class UI implements ApplicationListener, Loadable{
|
public class UI implements ApplicationListener, Loadable{
|
||||||
private static String billions, millions, thousands;
|
public static String billions, millions, thousands;
|
||||||
|
|
||||||
public static PixmapPacker packer;
|
public static PixmapPacker packer;
|
||||||
|
|
||||||
|
|||||||
@@ -525,8 +525,7 @@ public class World{
|
|||||||
|
|
||||||
private class Context implements WorldContext{
|
private class Context implements WorldContext{
|
||||||
|
|
||||||
Context(){
|
Context(){}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Tile tile(int index){
|
public Tile tile(int index){
|
||||||
@@ -579,7 +578,7 @@ public class World{
|
|||||||
|
|
||||||
for(GenerateFilter filter : filters){
|
for(GenerateFilter filter : filters){
|
||||||
filter.randomize();
|
filter.randomize();
|
||||||
input.begin(filter, width(), height(), (x, y) -> tiles.getn(x, y));
|
input.begin(width(), height(), (x, y) -> tiles.getn(x, y));
|
||||||
filter.apply(tiles, input);
|
filter.apply(tiles, input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import mindustry.game.*;
|
|||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.io.*;
|
import mindustry.io.*;
|
||||||
|
import mindustry.maps.*;
|
||||||
import mindustry.maps.filters.*;
|
import mindustry.maps.filters.*;
|
||||||
import mindustry.maps.filters.GenerateFilter.*;
|
import mindustry.maps.filters.GenerateFilter.*;
|
||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
@@ -26,12 +27,6 @@ import static mindustry.Vars.*;
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class MapGenerateDialog extends BaseDialog{
|
public class MapGenerateDialog extends BaseDialog{
|
||||||
final Prov<GenerateFilter>[] filterTypes = new Prov[]{
|
|
||||||
NoiseFilter::new, ScatterFilter::new, TerrainFilter::new, DistortFilter::new,
|
|
||||||
RiverNoiseFilter::new, OreFilter::new, OreMedianFilter::new, MedianFilter::new,
|
|
||||||
BlendFilter::new, MirrorFilter::new, ClearFilter::new, CoreSpawnFilter::new,
|
|
||||||
EnemySpawnFilter::new, SpawnPathFilter::new
|
|
||||||
};
|
|
||||||
final boolean applied;
|
final boolean applied;
|
||||||
|
|
||||||
Pixmap pixmap;
|
Pixmap pixmap;
|
||||||
@@ -158,7 +153,7 @@ public class MapGenerateDialog extends BaseDialog{
|
|||||||
long[] writeTiles = new long[editor.width() * editor.height()];
|
long[] writeTiles = new long[editor.width() * editor.height()];
|
||||||
|
|
||||||
for(GenerateFilter filter : filters){
|
for(GenerateFilter filter : filters){
|
||||||
input.begin(filter, editor.width(), editor.height(), editor::tile);
|
input.begin(editor.width(), editor.height(), editor::tile);
|
||||||
|
|
||||||
//write to buffer
|
//write to buffer
|
||||||
for(int x = 0; x < editor.width(); x++){
|
for(int x = 0; x < editor.width(); x++){
|
||||||
@@ -333,7 +328,7 @@ public class MapGenerateDialog extends BaseDialog{
|
|||||||
p.marginRight(14);
|
p.marginRight(14);
|
||||||
p.defaults().size(195f, 56f);
|
p.defaults().size(195f, 56f);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(var gen : filterTypes){
|
for(var gen : Maps.allFilterTypes){
|
||||||
var filter = gen.get();
|
var filter = gen.get();
|
||||||
var icon = filter.icon();
|
var icon = filter.icon();
|
||||||
|
|
||||||
@@ -414,7 +409,7 @@ public class MapGenerateDialog extends BaseDialog{
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(var filter : copy){
|
for(var filter : copy){
|
||||||
input.begin(filter, editor.width(), editor.height(), (x, y) -> unpack(buffer1[Mathf.clamp(x / scaling, 0, pixmap.width -1) + w* Mathf.clamp(y / scaling, 0, pixmap.height -1)]));
|
input.begin(editor.width(), editor.height(), (x, y) -> unpack(buffer1[Mathf.clamp(x / scaling, 0, pixmap.width -1) + w* Mathf.clamp(y / scaling, 0, pixmap.height -1)]));
|
||||||
|
|
||||||
//read from buffer1 and write to buffer2
|
//read from buffer1 and write to buffer2
|
||||||
pixmap.each((px, py) -> {
|
pixmap.each((px, py) -> {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package mindustry.entities.abilities;
|
package mindustry.entities.abilities;
|
||||||
|
|
||||||
import arc.*;
|
import arc.*;
|
||||||
|
import arc.audio.*;
|
||||||
import arc.graphics.*;
|
import arc.graphics.*;
|
||||||
import arc.graphics.g2d.*;
|
import arc.graphics.g2d.*;
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
@@ -19,6 +20,7 @@ public class EnergyFieldAbility extends Ability{
|
|||||||
public float damage = 1, reload = 100, range = 60;
|
public float damage = 1, reload = 100, range = 60;
|
||||||
public Effect healEffect = Fx.heal, hitEffect = Fx.hitLaserBlast, damageEffect = Fx.chainLightning;
|
public Effect healEffect = Fx.heal, hitEffect = Fx.hitLaserBlast, damageEffect = Fx.chainLightning;
|
||||||
public StatusEffect status = StatusEffects.electrified;
|
public StatusEffect status = StatusEffects.electrified;
|
||||||
|
public Sound shootSound = Sounds.spark;
|
||||||
public float statusDuration = 60f * 6f;
|
public float statusDuration = 60f * 6f;
|
||||||
public float x, y;
|
public float x, y;
|
||||||
public boolean hitBuildings = true;
|
public boolean hitBuildings = true;
|
||||||
@@ -139,6 +141,10 @@ public class EnergyFieldAbility extends Ability{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(anyNearby){
|
||||||
|
shootSound.at(unit);
|
||||||
|
}
|
||||||
|
|
||||||
timer = 0f;
|
timer = 0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,8 +232,8 @@ public class BulletType extends Content implements Cloneable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(entity instanceof Unit unit){
|
if(entity instanceof Unit unit){
|
||||||
Tmp.v3.set(unit).sub(b.x, b.y).nor().scl(knockback * 80f);
|
Tmp.v3.set(unit).sub(b).nor().scl(knockback * 80f);
|
||||||
if(impact) Tmp.v3.setAngle(b.rotation());
|
if(impact) Tmp.v3.setAngle(b.rotation() + (knockback < 0 ? 180f : 0f));
|
||||||
unit.impulse(Tmp.v3);
|
unit.impulse(Tmp.v3);
|
||||||
unit.apply(status, statusDuration);
|
unit.apply(status, statusDuration);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import static mindustry.Vars.*;
|
|||||||
|
|
||||||
@Component
|
@Component
|
||||||
abstract class BoundedComp implements Velc, Posc, Healthc, Flyingc{
|
abstract class BoundedComp implements Velc, Posc, Healthc, Flyingc{
|
||||||
static final float warpDst = 40f;
|
static final float warpDst = 30f;
|
||||||
|
|
||||||
@Import float x, y;
|
@Import float x, y;
|
||||||
|
|
||||||
|
|||||||
@@ -106,7 +106,6 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
|
|
||||||
/** Sets up all the necessary variables, but does not add this entity anywhere. */
|
/** Sets up all the necessary variables, but does not add this entity anywhere. */
|
||||||
public Building create(Block block, Team team){
|
public Building create(Block block, Team team){
|
||||||
this.tile = emptyTile;
|
|
||||||
this.block = block;
|
this.block = block;
|
||||||
this.team = team;
|
this.team = team;
|
||||||
|
|
||||||
@@ -1443,7 +1442,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
|||||||
@Override
|
@Override
|
||||||
public void killed(){
|
public void killed(){
|
||||||
Events.fire(new BlockDestroyEvent(tile));
|
Events.fire(new BlockDestroyEvent(tile));
|
||||||
block.breakSound.at(tile);
|
block.destroySound.at(tile);
|
||||||
onDestroyed();
|
onDestroyed();
|
||||||
tile.remove();
|
tile.remove();
|
||||||
remove();
|
remove();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package mindustry.entities.comp;
|
|||||||
|
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
|
import arc.util.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
import mindustry.async.PhysicsProcess.*;
|
import mindustry.async.PhysicsProcess.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ public class Rules{
|
|||||||
public float enemyCoreBuildRadius = 400f;
|
public float enemyCoreBuildRadius = 400f;
|
||||||
/** If true, no-build zones are calculated based on the closest core. */
|
/** If true, no-build zones are calculated based on the closest core. */
|
||||||
public boolean polygonCoreProtection = false;
|
public boolean polygonCoreProtection = false;
|
||||||
|
/** If true, dead teams in PvP automatically have their blocks & units converted to derelict upon death. */
|
||||||
|
public boolean cleanupDeadTeams = true;
|
||||||
/** Radius around enemy wave drop zones.*/
|
/** Radius around enemy wave drop zones.*/
|
||||||
public float dropZoneRadius = 300f;
|
public float dropZoneRadius = 300f;
|
||||||
/** Time between waves in ticks. */
|
/** Time between waves in ticks. */
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package mindustry.game;
|
package mindustry.game;
|
||||||
|
|
||||||
import arc.func.*;
|
import arc.func.*;
|
||||||
|
import arc.math.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.struct.Queue;
|
import arc.struct.Queue;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
@@ -260,6 +261,34 @@ public class Teams{
|
|||||||
this.ai = new BaseAI(this);
|
this.ai = new BaseAI(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Destroys this team's presence on the map, killing part of its buildings and converting everything to 'derelict'. */
|
||||||
|
public void destroyToDerelict(){
|
||||||
|
|
||||||
|
//grab all buildings from quadtree.
|
||||||
|
var builds = new Seq<Building>();
|
||||||
|
if(buildings != null){
|
||||||
|
buildings.getObjects(builds);
|
||||||
|
}
|
||||||
|
|
||||||
|
//convert all team tiles to neutral, randomly killing them
|
||||||
|
for(var b : builds){
|
||||||
|
//TODO this may cause a lot of packet spam, optimize?
|
||||||
|
Call.setTeam(b, Team.derelict);
|
||||||
|
|
||||||
|
if(Mathf.chance(0.25)){
|
||||||
|
Time.run(Mathf.random(0f, 60f * 6f), b::kill);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//kill all units randomly
|
||||||
|
units.each(u -> Time.run(Mathf.random(0f, 60f * 5f), () -> {
|
||||||
|
//ensure unit hasn't switched teams for whatever reason
|
||||||
|
if(u.team == team){
|
||||||
|
u.kill();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Seq<Unit> unitCache(UnitType type){
|
public Seq<Unit> unitCache(UnitType type){
|
||||||
if(unitsByType == null || unitsByType.length <= type.id || unitsByType[type.id] == null) return null;
|
if(unitsByType == null || unitsByType.length <= type.id || unitsByType[type.id] == null) return null;
|
||||||
@@ -320,6 +349,7 @@ public class Teams{
|
|||||||
public static class BlockPlan{
|
public static class BlockPlan{
|
||||||
public final short x, y, rotation, block;
|
public final short x, y, rotation, block;
|
||||||
public final Object config;
|
public final Object config;
|
||||||
|
public boolean removed;
|
||||||
|
|
||||||
public BlockPlan(int x, int y, short rotation, short block, Object config){
|
public BlockPlan(int x, int y, short rotation, short block, Object config){
|
||||||
this.x = (short)x;
|
this.x = (short)x;
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
|
|
||||||
for(int pos : positions){
|
for(int pos : positions){
|
||||||
if(req.x == Point2.x(pos) && req.y == Point2.y(pos)){
|
if(req.x == Point2.x(pos) && req.y == Point2.y(pos)){
|
||||||
|
req.removed = true;
|
||||||
it.remove();
|
it.remove();
|
||||||
continue outer;
|
continue outer;
|
||||||
}
|
}
|
||||||
@@ -893,6 +894,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
Block block = content.block(req.block);
|
Block block = content.block(req.block);
|
||||||
if(block.bounds(req.x, req.y, Tmp.r2).overlaps(Tmp.r1)){
|
if(block.bounds(req.x, req.y, Tmp.r2).overlaps(Tmp.r1)){
|
||||||
removed.add(Point2.pack(req.x, req.y));
|
removed.add(Point2.pack(req.x, req.y));
|
||||||
|
req.removed = true;
|
||||||
broken.remove();
|
broken.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package mindustry.io;
|
package mindustry.io;
|
||||||
|
|
||||||
|
import arc.util.*;
|
||||||
import arc.util.serialization.*;
|
import arc.util.serialization.*;
|
||||||
import arc.util.serialization.Json.*;
|
import arc.util.serialization.Json.*;
|
||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.ctype.*;
|
import mindustry.ctype.*;
|
||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
|
import mindustry.maps.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
import mindustry.world.meta.*;
|
import mindustry.world.meta.*;
|
||||||
@@ -215,6 +217,12 @@ public class JsonIO{
|
|||||||
return item != null ? item : liquid;
|
return item != null ? item : liquid;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//use short names for all filter types
|
||||||
|
for(var filter : Maps.allFilterTypes){
|
||||||
|
var i = filter.get();
|
||||||
|
json.addClassTag(Strings.camelize(i.getClass().getSimpleName().replace("Filter", "")), i.getClass());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class CustomJson extends Json{
|
static class CustomJson extends Json{
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package mindustry.io;
|
package mindustry.io;
|
||||||
|
|
||||||
|
import arc.audio.*;
|
||||||
import arc.graphics.*;
|
import arc.graphics.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
@@ -501,6 +502,15 @@ public class TypeIO{
|
|||||||
return id == -1 ? null : content.item(id);
|
return id == -1 ? null : content.item(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//note that only the standard sound constants in Sounds are supported; modded sounds are not.
|
||||||
|
public static void writeSound(Writes write, Sound sound){
|
||||||
|
write.s(Sounds.getSoundId(sound));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Sound readSound(Reads read){
|
||||||
|
return Sounds.getSound(read.s());
|
||||||
|
}
|
||||||
|
|
||||||
public static void writeWeather(Writes write, Weather item){
|
public static void writeWeather(Writes write, Weather item){
|
||||||
write.s(item == null ? -1 : item.id);
|
write.s(item == null ? -1 : item.id);
|
||||||
}
|
}
|
||||||
@@ -633,7 +643,7 @@ public class TypeIO{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Representes a building that has not been resolved yet. */
|
/** Represents a building that has not been resolved yet. */
|
||||||
public static class BuildingBox{
|
public static class BuildingBox{
|
||||||
public int pos;
|
public int pos;
|
||||||
|
|
||||||
|
|||||||
@@ -363,6 +363,9 @@ public class LExecutor{
|
|||||||
float x1 = World.unconv(exec.numf(p1)), y1 = World.unconv(exec.numf(p2)), d1 = World.unconv(exec.numf(p3));
|
float x1 = World.unconv(exec.numf(p1)), y1 = World.unconv(exec.numf(p2)), d1 = World.unconv(exec.numf(p3));
|
||||||
|
|
||||||
switch(type){
|
switch(type){
|
||||||
|
case idle -> {
|
||||||
|
ai.control = type;
|
||||||
|
}
|
||||||
case move, stop, approach -> {
|
case move, stop, approach -> {
|
||||||
ai.control = type;
|
ai.control = type;
|
||||||
ai.moveX = x1;
|
ai.moveX = x1;
|
||||||
|
|||||||
@@ -24,23 +24,30 @@ import mindustry.world.*;
|
|||||||
import mindustry.world.blocks.storage.*;
|
import mindustry.world.blocks.storage.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class Maps{
|
public class Maps{
|
||||||
|
/** All generation filter types. */
|
||||||
|
public static Prov<GenerateFilter>[] allFilterTypes = new Prov[]{
|
||||||
|
NoiseFilter::new, ScatterFilter::new, TerrainFilter::new, DistortFilter::new,
|
||||||
|
RiverNoiseFilter::new, OreFilter::new, OreMedianFilter::new, MedianFilter::new,
|
||||||
|
BlendFilter::new, MirrorFilter::new, ClearFilter::new, CoreSpawnFilter::new,
|
||||||
|
EnemySpawnFilter::new, SpawnPathFilter::new
|
||||||
|
};
|
||||||
|
|
||||||
/** List of all built-in maps. Filenames only. */
|
/** List of all built-in maps. Filenames only. */
|
||||||
private static String[] defaultMapNames = {"maze", "fortress", "labyrinth", "islands", "tendrils", "caldera", "wasteland", "shattered", "fork", "triad", "mudFlats", "moltenLake", "archipelago", "debrisField", "veins", "glacier", "passage"};
|
private static String[] defaultMapNames = {"maze", "fortress", "labyrinth", "islands", "tendrils", "caldera", "wasteland", "shattered", "fork", "triad", "mudFlats", "moltenLake", "archipelago", "debrisField", "veins", "glacier", "passage"};
|
||||||
/** Maps tagged as PvP */
|
/** Maps tagged as PvP */
|
||||||
static final String[] pvpMaps = {"veins", "glacier", "passage"};
|
private static String[] pvpMaps = {"veins", "glacier", "passage"};
|
||||||
|
|
||||||
/** All maps stored in an ordered array. */
|
/** All maps stored in an ordered array. */
|
||||||
private Seq<Map> maps = new Seq<>();
|
private Seq<Map> maps = new Seq<>();
|
||||||
/** Serializer for meta. */
|
|
||||||
private Json json = new Json();
|
|
||||||
|
|
||||||
private ShuffleMode shuffleMode = ShuffleMode.all;
|
private ShuffleMode shuffleMode = ShuffleMode.all;
|
||||||
private @Nullable MapProvider shuffler;
|
private @Nullable MapProvider shuffler;
|
||||||
|
|
||||||
private AsyncExecutor executor = new AsyncExecutor(2);
|
private ExecutorService executor = Threads.executor(3);
|
||||||
private ObjectSet<Map> previewList = new ObjectSet<>();
|
private ObjectSet<Map> previewList = new ObjectSet<>();
|
||||||
|
|
||||||
public ShuffleMode getShuffleMode(){
|
public ShuffleMode getShuffleMode(){
|
||||||
@@ -352,20 +359,20 @@ public class Maps{
|
|||||||
if(groups == null) return "[]";
|
if(groups == null) return "[]";
|
||||||
|
|
||||||
StringWriter buffer = new StringWriter();
|
StringWriter buffer = new StringWriter();
|
||||||
json.setWriter(new JsonWriter(buffer));
|
JsonIO.json.setWriter(new JsonWriter(buffer));
|
||||||
|
|
||||||
json.writeArrayStart();
|
JsonIO.json.writeArrayStart();
|
||||||
for(int i = 0; i < groups.size; i++){
|
for(int i = 0; i < groups.size; i++){
|
||||||
json.writeObjectStart(SpawnGroup.class, SpawnGroup.class);
|
JsonIO.json.writeObjectStart(SpawnGroup.class, SpawnGroup.class);
|
||||||
groups.get(i).write(json);
|
groups.get(i).write(JsonIO.json);
|
||||||
json.writeObjectEnd();
|
JsonIO.json.writeObjectEnd();
|
||||||
}
|
}
|
||||||
json.writeArrayEnd();
|
JsonIO.json.writeArrayEnd();
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Seq<SpawnGroup> readWaves(String str){
|
public Seq<SpawnGroup> readWaves(String str){
|
||||||
return str == null ? null : str.equals("[]") ? new Seq<>() : Seq.with(json.fromJson(SpawnGroup[].class, str));
|
return str == null ? null : str.equals("[]") ? new Seq<>() : Seq.with(JsonIO.json.fromJson(SpawnGroup[].class, str));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadPreviews(){
|
public void loadPreviews(){
|
||||||
|
|||||||
@@ -75,8 +75,7 @@ public abstract class GenerateFilter{
|
|||||||
|
|
||||||
/** localized display name */
|
/** localized display name */
|
||||||
public String name(){
|
public String name(){
|
||||||
var s = simpleName();
|
return Core.bundle.get("filter." + simpleName());
|
||||||
return Core.bundle.get("filter." + s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public char icon(){
|
public char icon(){
|
||||||
@@ -100,14 +99,12 @@ public abstract class GenerateFilter{
|
|||||||
|
|
||||||
//utility generation functions
|
//utility generation functions
|
||||||
|
|
||||||
//TODO would be nice if these functions used the seed and ditched "in" completely; simplex should be stateless
|
|
||||||
|
|
||||||
protected float noise(GenerateInput in, float scl, float mag){
|
protected float noise(GenerateInput in, float scl, float mag){
|
||||||
return (float)Simplex.noise2d(seed, 1f, 0f, 1f / scl, in.x, in.y) * mag;
|
return Simplex.noise2d(seed, 1f, 0f, 1f / scl, in.x, in.y) * mag;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float noise(GenerateInput in, float scl, float mag, float octaves, float persistence){
|
protected float noise(GenerateInput in, float scl, float mag, float octaves, float persistence){
|
||||||
return (float)Simplex.noise2d(seed, octaves, persistence, 1f / scl, in.x, in.y) * mag;
|
return Simplex.noise2d(seed, octaves, persistence, 1f / scl, in.x, in.y) * mag;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected float rnoise(float x, float y, float scl, float mag){
|
protected float rnoise(float x, float y, float scl, float mag){
|
||||||
@@ -141,7 +138,7 @@ public abstract class GenerateFilter{
|
|||||||
this.y = y;
|
this.y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void begin(GenerateFilter filter, int width, int height, TileProvider buffer){
|
public void begin(int width, int height, TileProvider buffer){
|
||||||
this.buffer = buffer;
|
this.buffer = buffer;
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ public abstract class PlanetGenerator extends BasicGenerator implements HexMeshe
|
|||||||
@Override
|
@Override
|
||||||
protected float noise(float x, float y, double octaves, double falloff, double scl, double mag){
|
protected float noise(float x, float y, double octaves, double falloff, double scl, double mag){
|
||||||
Vec3 v = sector.rect.project(x, y);
|
Vec3 v = sector.rect.project(x, y);
|
||||||
return (float)Simplex.noise3d(0, octaves, falloff, 1f / scl, v.x, v.y, v.z) * (float)mag;
|
return Simplex.noise3d(0, octaves, falloff, 1f / scl, v.x, v.y, v.z) * (float)mag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return the scaling factor for sector rects. */
|
/** @return the scaling factor for sector rects. */
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
|
|||||||
|
|
||||||
float rawHeight(Vec3 position){
|
float rawHeight(Vec3 position){
|
||||||
position = Tmp.v33.set(position).scl(scl);
|
position = Tmp.v33.set(position).scl(scl);
|
||||||
return (Mathf.pow((float)Simplex.noise3d(seed, 7, 0.5f, 1f/3f, position.x, position.y, position.z), 2.3f) + waterOffset) / (1f + waterOffset);
|
return (Mathf.pow(Simplex.noise3d(seed, 7, 0.5f, 1f/3f, position.x, position.y, position.z), 2.3f) + waterOffset) / (1f + waterOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -127,12 +127,12 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
|
|||||||
position = Tmp.v33.set(position).scl(scl);
|
position = Tmp.v33.set(position).scl(scl);
|
||||||
float rad = scl;
|
float rad = scl;
|
||||||
float temp = Mathf.clamp(Math.abs(position.y * 2f) / (rad));
|
float temp = Mathf.clamp(Math.abs(position.y * 2f) / (rad));
|
||||||
float tnoise = (float)Simplex.noise3d(seed, 7, 0.56, 1f/3f, position.x, position.y + 999f, position.z);
|
float tnoise = Simplex.noise3d(seed, 7, 0.56, 1f/3f, position.x, position.y + 999f, position.z);
|
||||||
temp = Mathf.lerp(temp, tnoise, 0.5f);
|
temp = Mathf.lerp(temp, tnoise, 0.5f);
|
||||||
height *= 1.2f;
|
height *= 1.2f;
|
||||||
height = Mathf.clamp(height);
|
height = Mathf.clamp(height);
|
||||||
|
|
||||||
float tar = (float)Simplex.noise3d(seed, 4, 0.55f, 1f/2f, position.x, position.y + 999f, position.z) * 0.3f + Tmp.v31.dst(0, 0, 1f) * 0.2f;
|
float tar = Simplex.noise3d(seed, 4, 0.55f, 1f/2f, position.x, position.y + 999f, position.z) * 0.3f + Tmp.v31.dst(0, 0, 1f) * 0.2f;
|
||||||
|
|
||||||
Block res = arr[Mathf.clamp((int)(temp * arr.length), 0, arr[0].length - 1)][Mathf.clamp((int)(height * arr[0].length), 0, arr[0].length - 1)];
|
Block res = arr[Mathf.clamp((int)(temp * arr.length), 0, arr[0].length - 1)][Mathf.clamp((int)(height * arr[0].length), 0, arr[0].length - 1)];
|
||||||
if(tar > 0.5f){
|
if(tar > 0.5f){
|
||||||
@@ -145,7 +145,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
|
|||||||
@Override
|
@Override
|
||||||
protected float noise(float x, float y, double octaves, double falloff, double scl, double mag){
|
protected float noise(float x, float y, double octaves, double falloff, double scl, double mag){
|
||||||
Vec3 v = sector.rect.project(x, y).scl(5f);
|
Vec3 v = sector.rect.project(x, y).scl(5f);
|
||||||
return (float)Simplex.noise3d(seed, octaves, falloff, 1f / scl, v.x, v.y, v.z) * (float)mag;
|
return Simplex.noise3d(seed, octaves, falloff, 1f / scl, v.x, v.y, v.z) * (float)mag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -162,12 +162,27 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
|
|||||||
connected.add(this);
|
connected.add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void con(int x1, int y1, int x2, int y2){
|
||||||
|
float nscl = rand.random(100f, 140f) * 6f;
|
||||||
|
int stroke = rand.random(3, 9);
|
||||||
|
brush(pathfind(x1, y1, x2, y2, tile -> (tile.solid() ? 50f : 0f) + noise(tile.x, tile.y, 2, 0.4f, 1f / nscl) * 500, Astar.manhattan), stroke);
|
||||||
|
}
|
||||||
|
|
||||||
void connect(Room to){
|
void connect(Room to){
|
||||||
if(!connected.add(to)) return;
|
if(!connected.add(to)) return;
|
||||||
|
|
||||||
float nscl = rand.random(100f, 140f);
|
Vec2 midpoint = Tmp.v1.set(to.x, to.y).add(x, y).scl(0.5f);
|
||||||
int stroke = rand.random(3, 9);
|
rand.nextFloat();
|
||||||
brush(pathfind(x, y, to.x, to.y, tile -> (tile.solid() ? 5f : 0f) + noise(tile.x, tile.y, 2, 0.4, 1f / nscl) * 500, Astar.manhattan), stroke);
|
|
||||||
|
//add randomized offset to avoid straight lines
|
||||||
|
midpoint.add(Tmp.v2.setToRandomDirection(rand).scl(Tmp.v1.dst(x, y)));
|
||||||
|
|
||||||
|
midpoint.sub(width/2f, height/2f).limit(width / 2f / Mathf.sqrt3).add(width/2f, height/2f);
|
||||||
|
|
||||||
|
int mx = (int)midpoint.x, my = (int)midpoint.y;
|
||||||
|
|
||||||
|
con(x, y, mx, my);
|
||||||
|
con(mx, my, to.x, to.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,8 +259,6 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
|
|||||||
cells(1);
|
cells(1);
|
||||||
distort(10f, 6f);
|
distort(10f, 6f);
|
||||||
|
|
||||||
inverseFloodFill(tiles.getn(spawn.x, spawn.y));
|
|
||||||
|
|
||||||
Seq<Block> ores = Seq.with(Blocks.oreCopper, Blocks.oreLead);
|
Seq<Block> ores = Seq.with(Blocks.oreCopper, Blocks.oreLead);
|
||||||
float poles = Math.abs(sector.tile.v.y);
|
float poles = Math.abs(sector.tile.v.y);
|
||||||
float nmag = 0.5f;
|
float nmag = 0.5f;
|
||||||
@@ -296,6 +309,8 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
|
|||||||
|
|
||||||
median(2);
|
median(2);
|
||||||
|
|
||||||
|
inverseFloodFill(tiles.getn(spawn.x, spawn.y));
|
||||||
|
|
||||||
tech();
|
tech();
|
||||||
|
|
||||||
pass((x, y) -> {
|
pass((x, y) -> {
|
||||||
|
|||||||
@@ -29,18 +29,17 @@ public class CrashSender{
|
|||||||
report += "Report this at " + Vars.reportIssueURL + "\n\n";
|
report += "Report this at " + Vars.reportIssueURL + "\n\n";
|
||||||
}
|
}
|
||||||
return report
|
return report
|
||||||
+ "Version: " + Version.combined() + (Vars.headless ? " (Server)" : "") + "\n"
|
+ "Version: " + Version.combined() + (Vars.headless ? " (Server)" : "") + "\n"
|
||||||
+ "OS: " + System.getProperty("os.name") + " x" + (OS.is64Bit ? "64" : "32") + "\n"
|
+ "OS: " + OS.osName + " x" + (OS.osArchBits) + " (" + OS.osArch + ")\n"
|
||||||
+ "Java Version: " + System.getProperty("java.version") + "\n"
|
+ "Java Version: " + OS.javaVersion + "\n"
|
||||||
+ "Java Architecture: " + System.getProperty("sun.arch.data.model") + "\n"
|
+ (mods == null ? "<no mod init>" : mods.list().size + " Mods" + (mods.list().isEmpty() ? "" : ": " + mods.list().toString(", ", mod -> mod.name + ":" + mod.meta.version)))
|
||||||
+ (mods == null ? "<no mod init>" : mods.list().size + " Mods" + (mods.list().isEmpty() ? "" : ": " + mods.list().toString(", ", mod -> mod.name + ":" + mod.meta.version)))
|
+ "\n\n" + error;
|
||||||
+ "\n\n" + error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void log(Throwable exception){
|
public static void log(Throwable exception){
|
||||||
try{
|
try{
|
||||||
Core.settings.getDataDirectory().child("crashes").child("crash_" + System.currentTimeMillis() + ".txt")
|
Core.settings.getDataDirectory().child("crashes").child("crash_" + System.currentTimeMillis() + ".txt")
|
||||||
.writeString(createReport(Strings.neatError(exception)));
|
.writeString(createReport(Strings.neatError(exception)));
|
||||||
}catch(Throwable ignored){
|
}catch(Throwable ignored){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,7 +59,7 @@ public class CrashSender{
|
|||||||
}catch(Throwable ignored){}
|
}catch(Throwable ignored){}
|
||||||
|
|
||||||
//don't create crash logs for custom builds, as it's expected
|
//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))){
|
if(Version.build == -1 || (OS.username.equals("anuke") && !"steam".equals(Version.modifier))){
|
||||||
ret();
|
ret();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,10 +140,10 @@ public class CrashSender{
|
|||||||
ex(() -> value.addChild("server", new JsonValue(fs)));
|
ex(() -> value.addChild("server", new JsonValue(fs)));
|
||||||
ex(() -> value.addChild("players", new JsonValue(Groups.player.size())));
|
ex(() -> value.addChild("players", new JsonValue(Groups.player.size())));
|
||||||
ex(() -> value.addChild("state", new JsonValue(Vars.state.getState().name())));
|
ex(() -> value.addChild("state", new JsonValue(Vars.state.getState().name())));
|
||||||
ex(() -> value.addChild("os", new JsonValue(System.getProperty("os.name") + "x" + (OS.is64Bit ? "64" : "32"))));
|
ex(() -> value.addChild("os", new JsonValue(OS.osName + " x" + OS.osArchBits + " " + OS.osVersion)));
|
||||||
ex(() -> value.addChild("trace", new JsonValue(parseException(exception))));
|
ex(() -> value.addChild("trace", new JsonValue(parseException(exception))));
|
||||||
ex(() -> value.addChild("javaVersion", new JsonValue(System.getProperty("java.version"))));
|
ex(() -> value.addChild("javaVersion", new JsonValue(OS.javaVersion)));
|
||||||
ex(() -> value.addChild("javaArch", new JsonValue(System.getProperty("sun.arch.data.model"))));
|
ex(() -> value.addChild("javaArch", new JsonValue(OS.osArchBits)));
|
||||||
|
|
||||||
Log.info("Sending crash report.");
|
Log.info("Sending crash report.");
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ public class StatusEffect extends UnlockableContent{
|
|||||||
if(reloadMultiplier != 1) stats.addPercent(Stat.reloadMultiplier, reloadMultiplier);
|
if(reloadMultiplier != 1) stats.addPercent(Stat.reloadMultiplier, reloadMultiplier);
|
||||||
if(buildSpeedMultiplier != 1) stats.addPercent(Stat.buildSpeedMultiplier, buildSpeedMultiplier);
|
if(buildSpeedMultiplier != 1) stats.addPercent(Stat.buildSpeedMultiplier, buildSpeedMultiplier);
|
||||||
if(damage > 0) stats.add(Stat.damage, damage * 60f, StatUnit.perSecond);
|
if(damage > 0) stats.add(Stat.damage, damage * 60f, StatUnit.perSecond);
|
||||||
if(damage < 0) stats.add(Stat.healing, -(damage * 60f), StatUnit.perSecond);
|
if(damage < 0) stats.add(Stat.healing, -damage * 60f, StatUnit.perSecond);
|
||||||
|
|
||||||
boolean reacts = false;
|
boolean reacts = false;
|
||||||
|
|
||||||
|
|||||||
@@ -249,7 +249,7 @@ public class Weapon implements Cloneable{
|
|||||||
unit.vel.add(Tmp.v1.trns(unit.rotation + 180f, mount.bullet.type.recoil));
|
unit.vel.add(Tmp.v1.trns(unit.rotation + 180f, mount.bullet.type.recoil));
|
||||||
if(shootSound != Sounds.none && !headless){
|
if(shootSound != Sounds.none && !headless){
|
||||||
if(mount.sound == null) mount.sound = new SoundLoop(shootSound, 1f);
|
if(mount.sound == null) mount.sound = new SoundLoop(shootSound, 1f);
|
||||||
mount.sound.update(x, y, true);
|
mount.sound.update(bulletX, bulletY, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@@ -285,8 +285,7 @@ public class Weapon implements Cloneable{
|
|||||||
can && //must be able to shoot
|
can && //must be able to shoot
|
||||||
(!useAmmo || unit.ammo > 0 || !state.rules.unitAmmo || unit.team.rules().infiniteAmmo) && //check ammo
|
(!useAmmo || unit.ammo > 0 || !state.rules.unitAmmo || unit.team.rules().infiniteAmmo) && //check ammo
|
||||||
(!alternate || mount.side == flipSprite) &&
|
(!alternate || mount.side == flipSprite) &&
|
||||||
//TODO checking for velocity this way isn't entirely correct
|
unit.vel.len() >= mount.weapon.minShootVelocity && //check velocity requirements
|
||||||
(unit.vel.len() >= mount.weapon.minShootVelocity || (net.active() && !unit.isLocal())) && //check velocity requirements
|
|
||||||
mount.reload <= 0.0001f && //reload has to be 0
|
mount.reload <= 0.0001f && //reload has to be 0
|
||||||
Angles.within(rotate ? mount.rotation : unit.rotation, mount.targetRotation, mount.weapon.shootCone) //has to be within the cone
|
Angles.within(rotate ? mount.rotation : unit.rotation, mount.targetRotation, mount.weapon.shootCone) //has to be within the cone
|
||||||
){
|
){
|
||||||
@@ -324,6 +323,9 @@ public class Weapon implements Cloneable{
|
|||||||
Time.run(sequenceNum * shotDelay + firstShotDelay, () -> {
|
Time.run(sequenceNum * shotDelay + firstShotDelay, () -> {
|
||||||
if(!unit.isAdded()) return;
|
if(!unit.isAdded()) return;
|
||||||
mount.bullet = bullet(unit, shootX + unit.x - baseX, shootY + unit.y - baseY, f + Mathf.range(inaccuracy), lifeScl);
|
mount.bullet = bullet(unit, shootX + unit.x - baseX, shootY + unit.y - baseY, f + Mathf.range(inaccuracy), lifeScl);
|
||||||
|
if(!continuous){
|
||||||
|
shootSound.at(shootX, shootY, Mathf.random(soundPitchMin, soundPitchMax));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
sequenceNum++;
|
sequenceNum++;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -236,8 +236,12 @@ public class Fonts{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static TextureRegionDrawable getGlyph(Font font, char glyph){
|
public static TextureRegionDrawable getGlyph(Font font, char glyph){
|
||||||
Glyph g = font.getData().getGlyph(glyph);
|
Glyph found = font.getData().getGlyph(glyph);
|
||||||
if(g == null) throw new IllegalArgumentException("No glyph: " + glyph + " (" + (int)glyph + ")");
|
if(found == null){
|
||||||
|
Log.warn("No icon found for glyph: @ (@)", glyph, (int)glyph);
|
||||||
|
found = font.getData().getGlyph('F');
|
||||||
|
}
|
||||||
|
Glyph g = found;
|
||||||
|
|
||||||
float size = Math.max(g.width, g.height);
|
float size = Math.max(g.width, g.height);
|
||||||
TextureRegionDrawable draw = new TextureRegionDrawable(new TextureRegion(font.getRegion().texture, g.u, g.v2, g.u2, g.v)){
|
TextureRegionDrawable draw = new TextureRegionDrawable(new TextureRegion(font.getRegion().texture, g.u, g.v2, g.u2, g.v)){
|
||||||
|
|||||||
@@ -55,20 +55,30 @@ public class Links{
|
|||||||
|
|
||||||
private static String report(){
|
private static String report(){
|
||||||
return "https://github.com/Anuken/Mindustry/issues/new?assignees=&labels=bug&body=" +
|
return "https://github.com/Anuken/Mindustry/issues/new?assignees=&labels=bug&body=" +
|
||||||
Strings.encode(Strings.format(
|
Strings.encode(Strings.format(
|
||||||
"**Platform**: `@`\n" +
|
"""
|
||||||
"\n**Build**: `@`\n" +
|
**Platform**: `@`
|
||||||
"\n**Issue**: *Explain your issue in detail.*\n" +
|
|
||||||
"\n**Steps to reproduce**: *How you happened across the issue, and what exactly you did to make the bug happen.*\n" +
|
**Build**: `@`
|
||||||
"\n**Link(s) to mod(s) used**: `@`\n" +
|
|
||||||
"\n**Save file**: *The (zipped) save file you were playing on when the bug happened. THIS IS REQUIRED FOR ANY ISSUE HAPPENING IN-GAME, REGARDLESS OF WHETHER YOU THINK IT HAPPENS EVERYWHERE. DO NOT DELETE OR OMIT THIS LINE UNLESS YOU ARE SURE THAT THE ISSUE DOES NOT HAPPEN IN-GAME.*\n" +
|
**Issue**: *Explain your issue in detail.*
|
||||||
"\n**Crash report**: *The contents of relevant crash report files. REQUIRED if you are reporting a crash.*\n" +
|
|
||||||
"\n---\n" +
|
**Steps to reproduce**: *How you happened across the issue, and what exactly you did to make the bug happen.*
|
||||||
"\n*Place an X (no spaces) between the brackets to confirm that you have read the line below.*" +
|
|
||||||
"\n- [ ] **I have updated to the latest release (https://github.com/Anuken/Mindustry/releases) to make sure my issue has not been fixed.**" +
|
**Link(s) to mod(s) used**: `@`
|
||||||
"\n- [ ] **I have searched the closed and open issues to make sure that this problem has not already been reported.**",
|
|
||||||
OS.isAndroid ? "Android " + Core.app.getVersion() : (System.getProperty("os.name") + (OS.is64Bit ? " x64" : " x32")),
|
**Save file**: *The (zipped) save file you were playing on when the bug happened. THIS IS REQUIRED FOR ANY ISSUE HAPPENING IN-GAME, REGARDLESS OF WHETHER YOU THINK IT HAPPENS EVERYWHERE. DO NOT DELETE OR OMIT THIS LINE UNLESS YOU ARE SURE THAT THE ISSUE DOES NOT HAPPEN IN-GAME.*
|
||||||
Version.combined(),
|
|
||||||
Vars.mods.list().any() ? Vars.mods.list().select(LoadedMod::enabled).map(l -> l.meta.author + "/" + l.name + ":" + l.meta.version) : "none"));
|
**Crash report**: *The contents of relevant crash report files. REQUIRED if you are reporting a crash.*
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*Place an X (no spaces) between the brackets to confirm that you have read the line below.*
|
||||||
|
- [ ] **I have updated to the latest release (https://github.com/Anuken/Mindustry/releases) to make sure my issue has not been fixed.**
|
||||||
|
- [ ] **I have searched the closed and open issues to make sure that this problem has not already been reported.**
|
||||||
|
""",
|
||||||
|
OS.isAndroid ? "Android " + Core.app.getVersion() : (OS.osName + " x" + OS.osArchBits),
|
||||||
|
Version.combined(),
|
||||||
|
Vars.mods.list().any() ? Vars.mods.list().select(LoadedMod::enabled).map(l -> l.meta.author + "/" + l.name + ":" + l.meta.version) : "none"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,6 +142,7 @@ public class CustomRulesDialog extends BaseDialog{
|
|||||||
check("@rules.reactorexplosions", b -> rules.reactorExplosions = b, () -> rules.reactorExplosions);
|
check("@rules.reactorexplosions", b -> rules.reactorExplosions = b, () -> rules.reactorExplosions);
|
||||||
check("@rules.schematic", b -> rules.schematicsAllowed = b, () -> rules.schematicsAllowed);
|
check("@rules.schematic", b -> rules.schematicsAllowed = b, () -> rules.schematicsAllowed);
|
||||||
check("@rules.coreincinerates", b -> rules.coreIncinerates = b, () -> rules.coreIncinerates);
|
check("@rules.coreincinerates", b -> rules.coreIncinerates = b, () -> rules.coreIncinerates);
|
||||||
|
check("@rules.cleanupdeadteams", b -> rules.cleanupDeadTeams = b, () -> rules.cleanupDeadTeams, () -> rules.pvp);
|
||||||
number("@rules.buildcostmultiplier", false, f -> rules.buildCostMultiplier = f, () -> rules.buildCostMultiplier, () -> !rules.infiniteResources);
|
number("@rules.buildcostmultiplier", false, f -> rules.buildCostMultiplier = f, () -> rules.buildCostMultiplier, () -> !rules.infiniteResources);
|
||||||
number("@rules.buildspeedmultiplier", f -> rules.buildSpeedMultiplier = f, () -> rules.buildSpeedMultiplier, 0.001f, 50f);
|
number("@rules.buildspeedmultiplier", f -> rules.buildSpeedMultiplier = f, () -> rules.buildSpeedMultiplier, 0.001f, 50f);
|
||||||
number("@rules.deconstructrefundmultiplier", false, f -> rules.deconstructRefundMultiplier = f, () -> rules.deconstructRefundMultiplier, () -> !rules.infiniteResources);
|
number("@rules.deconstructrefundmultiplier", false, f -> rules.deconstructRefundMultiplier = f, () -> rules.deconstructRefundMultiplier, () -> !rules.infiniteResources);
|
||||||
|
|||||||
@@ -80,9 +80,7 @@ public class ModsDialog extends BaseDialog{
|
|||||||
}
|
}
|
||||||
|
|
||||||
shown(this::setup);
|
shown(this::setup);
|
||||||
if(mobile){
|
onResize(this::setup);
|
||||||
onResize(this::setup);
|
|
||||||
}
|
|
||||||
|
|
||||||
Events.on(ResizeEvent.class, event -> {
|
Events.on(ResizeEvent.class, event -> {
|
||||||
if(currentContent != null){
|
if(currentContent != null){
|
||||||
@@ -144,10 +142,10 @@ public class ModsDialog extends BaseDialog{
|
|||||||
|
|
||||||
void setup(){
|
void setup(){
|
||||||
float h = 110f;
|
float h = 110f;
|
||||||
float w = Math.min(Core.graphics.getWidth() / 1.1f, 520f);
|
float w = Math.min(Core.graphics.getWidth() / Scl.scl(1.05f), 520f);
|
||||||
|
|
||||||
cont.clear();
|
cont.clear();
|
||||||
cont.defaults().width(Math.min(Core.graphics.getWidth() / 1.2f, 556f)).pad(4);
|
cont.defaults().width(Math.min(Core.graphics.getWidth() / Scl.scl(1.05f), 556f)).pad(4);
|
||||||
cont.add("@mod.reloadrequired").visible(mods::requiresReload).center().get().setAlignment(Align.center);
|
cont.add("@mod.reloadrequired").visible(mods::requiresReload).center().get().setAlignment(Align.center);
|
||||||
cont.row();
|
cont.row();
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import arc.scene.ui.layout.Stack;
|
|||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
|
import mindustry.core.*;
|
||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
@@ -200,9 +201,9 @@ public class BlockInventoryFragment extends Fragment{
|
|||||||
private String round(float f){
|
private String round(float f){
|
||||||
f = (int)f;
|
f = (int)f;
|
||||||
if(f >= 1000000){
|
if(f >= 1000000){
|
||||||
return (int)(f / 1000000f) + "[gray]" + Core.bundle.getOrNull("unit.millions") + "[]";
|
return (int)(f / 1000000f) + "[gray]" + UI.millions;
|
||||||
}else if(f >= 1000){
|
}else if(f >= 1000){
|
||||||
return (int)(f / 1000) + Core.bundle.getOrNull("unit.thousands");
|
return (int)(f / 1000) + UI.thousands;
|
||||||
}else{
|
}else{
|
||||||
return (int)f + "";
|
return (int)f + "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,8 +190,10 @@ public class Block extends UnlockableContent{
|
|||||||
public int outlinedIcon = -1;
|
public int outlinedIcon = -1;
|
||||||
/** Whether this block has a shadow under it. */
|
/** Whether this block has a shadow under it. */
|
||||||
public boolean hasShadow = true;
|
public boolean hasShadow = true;
|
||||||
/** Sounds made when this block breaks.*/
|
/** Sounds made when this block is destroyed.*/
|
||||||
public Sound breakSound = Sounds.boom;
|
public Sound destroySound = Sounds.boom;
|
||||||
|
/** Sound made when this block is deconstructed. */
|
||||||
|
public Sound breakSound = Sounds.breaks;
|
||||||
/** How reflective this block is. */
|
/** How reflective this block is. */
|
||||||
public float albedo = 0f;
|
public float albedo = 0f;
|
||||||
/** Environmental passive light color. */
|
/** Environmental passive light color. */
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
package mindustry.world;
|
|
||||||
|
|
||||||
public class TileData{
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,7 @@ import mindustry.content.*;
|
|||||||
|
|
||||||
public class TileGen{
|
public class TileGen{
|
||||||
public Block floor;
|
public Block floor;
|
||||||
public Block block ;
|
public Block block;
|
||||||
public Block overlay;
|
public Block overlay;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -41,13 +41,14 @@ public class ConstructBlock extends Block{
|
|||||||
health = 20;
|
health = 20;
|
||||||
consumesTap = true;
|
consumesTap = true;
|
||||||
solidifes = true;
|
solidifes = true;
|
||||||
|
inEditor = false;
|
||||||
consBlocks[size - 1] = this;
|
consBlocks[size - 1] = this;
|
||||||
sync = true;
|
sync = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a ConstructBlock by size. */
|
/** Returns a ConstructBlock by size. */
|
||||||
public static ConstructBlock get(int size){
|
public static ConstructBlock get(int size){
|
||||||
if(size > maxBlockSize) throw new IllegalArgumentException("No. Don't place ConstructBlock of size greater than " + maxBlockSize);
|
if(size > maxBlockSize) throw new IllegalArgumentException("No. Don't place ConstructBlocks of size greater than " + maxBlockSize);
|
||||||
return consBlocks[size - 1];
|
return consBlocks[size - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +58,7 @@ public class ConstructBlock extends Block{
|
|||||||
block.breakEffect.at(tile.drawx(), tile.drawy(), block.size, block.mapColor);
|
block.breakEffect.at(tile.drawx(), tile.drawy(), block.size, block.mapColor);
|
||||||
Events.fire(new BlockBuildEndEvent(tile, builder, team, true, null));
|
Events.fire(new BlockBuildEndEvent(tile, builder, team, true, null));
|
||||||
tile.remove();
|
tile.remove();
|
||||||
if(shouldPlay()) Sounds.breaks.at(tile, calcPitch(false));
|
if(shouldPlay()) block.breakSound.at(tile, calcPitch(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(called = Loc.server)
|
@Remote(called = Loc.server)
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import mindustry.gen.*;
|
|||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.input.*;
|
import mindustry.input.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.ui.*;
|
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
import mindustry.world.blocks.*;
|
import mindustry.world.blocks.*;
|
||||||
import mindustry.world.meta.*;
|
import mindustry.world.meta.*;
|
||||||
@@ -247,7 +246,7 @@ public class Conveyor extends Block implements Autotiler{
|
|||||||
|
|
||||||
if(ys[i] > nextMax) ys[i] = nextMax;
|
if(ys[i] > nextMax) ys[i] = nextMax;
|
||||||
if(ys[i] > 0.5 && i > 0) mid = i - 1;
|
if(ys[i] > 0.5 && i > 0) mid = i - 1;
|
||||||
xs[i] = Mathf.approachDelta(xs[i], 0, speed*2);
|
xs[i] = Mathf.approach(xs[i], 0, moved*2);
|
||||||
|
|
||||||
if(ys[i] >= 1f && pass(ids[i])){
|
if(ys[i] >= 1f && pass(ids[i])){
|
||||||
//align X position if passing forwards
|
//align X position if passing forwards
|
||||||
@@ -263,7 +262,7 @@ public class Conveyor extends Block implements Autotiler{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(minitem < itemSpace + (blendbits == 1 ? 0.3f : 0f)){
|
if(minitem < itemSpace + (blendbits == 1 ? 0.3f : 0f)){
|
||||||
clogHeat = Mathf.lerpDelta(clogHeat, 1f, 0.02f);
|
clogHeat = Mathf.approachDelta(clogHeat, 1f, 1f / 60f);
|
||||||
}else{
|
}else{
|
||||||
clogHeat = 0f;
|
clogHeat = 0f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,8 +52,6 @@ public class Floor extends Block{
|
|||||||
public boolean playerUnmineable = false;
|
public boolean playerUnmineable = false;
|
||||||
/** Group of blocks that this block does not draw edges on. */
|
/** Group of blocks that this block does not draw edges on. */
|
||||||
public Block blendGroup = this;
|
public Block blendGroup = this;
|
||||||
/** Effect displayed when randomly updated. */
|
|
||||||
public Effect updateEffect = Fx.none;
|
|
||||||
/** Array of affinities to certain things. */
|
/** Array of affinities to certain things. */
|
||||||
public Attributes attributes = new Attributes();
|
public Attributes attributes = new Attributes();
|
||||||
/** Whether this ore generates in maps by default. */
|
/** Whether this ore generates in maps by default. */
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public class OreBlock extends OverlayFloor{
|
|||||||
/** For mod use only!*/
|
/** For mod use only!*/
|
||||||
public OreBlock(String name){
|
public OreBlock(String name){
|
||||||
super(name);
|
super(name);
|
||||||
|
this.useColor = true;
|
||||||
variants = 3;
|
variants = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,18 @@ import arc.*;
|
|||||||
import arc.graphics.g2d.*;
|
import arc.graphics.g2d.*;
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
|
import mindustry.gen.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
|
|
||||||
public class Prop extends Block{
|
public class Prop extends Block{
|
||||||
|
|
||||||
public Prop(String name){
|
public Prop(String name){
|
||||||
super(name);
|
super(name);
|
||||||
breakable = true;
|
breakable = true;
|
||||||
alwaysReplace = true;
|
alwaysReplace = true;
|
||||||
instantDeconstruct = true;
|
instantDeconstruct = true;
|
||||||
breakEffect = Fx.breakProp;
|
breakEffect = Fx.breakProp;
|
||||||
|
breakSound = Sounds.rockBreak;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ public class LegacyBlock extends Block{
|
|||||||
|
|
||||||
public LegacyBlock(String name){
|
public LegacyBlock(String name){
|
||||||
super(name);
|
super(name);
|
||||||
|
inEditor = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Removes this block from the world, or replaces it with something else. */
|
/** Removes this block from the world, or replaces it with something else. */
|
||||||
|
|||||||
@@ -249,18 +249,6 @@ public class LogicBlock extends Block{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onProximityAdded(){
|
|
||||||
super.onProximityAdded();
|
|
||||||
|
|
||||||
//unbox buildings after reading
|
|
||||||
for(var v : executor.vars){
|
|
||||||
if(v.objval instanceof BuildingBox b){
|
|
||||||
v.objval = world.build(b.pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String findLinkName(Block block){
|
public String findLinkName(Block block){
|
||||||
String bname = getLinkName(block);
|
String bname = getLinkName(block);
|
||||||
Bits taken = new Bits(links.size);
|
Bits taken = new Bits(links.size);
|
||||||
@@ -595,7 +583,7 @@ public class LogicBlock extends Block{
|
|||||||
for(int i = 0; i < varcount; i++){
|
for(int i = 0; i < varcount; i++){
|
||||||
BVar dest = asm.getVar(names[i]);
|
BVar dest = asm.getVar(names[i]);
|
||||||
if(dest != null && !dest.constant){
|
if(dest != null && !dest.constant){
|
||||||
dest.value = values[i];
|
dest.value = values[i] instanceof BuildingBox box ? world.build(box.pos) : values[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import arc.util.*;
|
|||||||
import arc.util.io.*;
|
import arc.util.io.*;
|
||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
|
import mindustry.ui.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
@@ -47,6 +48,12 @@ public interface Payload extends Position{
|
|||||||
/** @return icon describing the contents. */
|
/** @return icon describing the contents. */
|
||||||
TextureRegion icon();
|
TextureRegion icon();
|
||||||
|
|
||||||
|
/** @deprecated use icon() instead. */
|
||||||
|
@Deprecated
|
||||||
|
default TextureRegion icon(Cicon icon){
|
||||||
|
return icon();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default float getX(){
|
default float getX(){
|
||||||
return x();
|
return x();
|
||||||
|
|||||||
@@ -15,7 +15,10 @@ import mindustry.world.draw.*;
|
|||||||
import mindustry.world.meta.*;
|
import mindustry.world.meta.*;
|
||||||
|
|
||||||
public class GenericCrafter extends Block{
|
public class GenericCrafter extends Block{
|
||||||
|
/** Written to outputItems as a single-element array if outputItems is null. */
|
||||||
public @Nullable ItemStack outputItem;
|
public @Nullable ItemStack outputItem;
|
||||||
|
/** Overwrites outputItem if not null. */
|
||||||
|
public @Nullable ItemStack[] outputItems;
|
||||||
public @Nullable LiquidStack outputLiquid;
|
public @Nullable LiquidStack outputLiquid;
|
||||||
|
|
||||||
public float craftTime = 80;
|
public float craftTime = 80;
|
||||||
@@ -45,8 +48,8 @@ public class GenericCrafter extends Block{
|
|||||||
super.setStats();
|
super.setStats();
|
||||||
stats.add(Stat.productionTime, craftTime / 60f, StatUnit.seconds);
|
stats.add(Stat.productionTime, craftTime / 60f, StatUnit.seconds);
|
||||||
|
|
||||||
if(outputItem != null){
|
if(outputItems != null){
|
||||||
stats.add(Stat.output, StatValues.items(craftTime, outputItem));
|
stats.add(Stat.output, StatValues.items(craftTime, outputItems));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(outputLiquid != null){
|
if(outputLiquid != null){
|
||||||
@@ -64,6 +67,9 @@ public class GenericCrafter extends Block{
|
|||||||
@Override
|
@Override
|
||||||
public void init(){
|
public void init(){
|
||||||
outputsLiquid = outputLiquid != null;
|
outputsLiquid = outputLiquid != null;
|
||||||
|
if(outputItems == null && outputItem != null){
|
||||||
|
outputItems = new ItemStack[]{outputItem};
|
||||||
|
}
|
||||||
super.init();
|
super.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +80,7 @@ public class GenericCrafter extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean outputsItems(){
|
public boolean outputsItems(){
|
||||||
return outputItem != null;
|
return outputItems != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GenericCrafterBuild extends Building{
|
public class GenericCrafterBuild extends Building{
|
||||||
@@ -95,8 +101,12 @@ public class GenericCrafter extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean shouldConsume(){
|
public boolean shouldConsume(){
|
||||||
if(outputItem != null && items.get(outputItem.item) + outputItem.amount > itemCapacity){
|
if(outputItems != null){
|
||||||
return false;
|
for(ItemStack output : outputItems){
|
||||||
|
if(items.get(output.item) + output.amount > itemCapacity){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return (outputLiquid == null || !(liquids.get(outputLiquid.liquid) >= liquidCapacity - 0.001f)) && enabled;
|
return (outputLiquid == null || !(liquids.get(outputLiquid.liquid) >= liquidCapacity - 0.001f)) && enabled;
|
||||||
}
|
}
|
||||||
@@ -119,9 +129,11 @@ public class GenericCrafter extends Block{
|
|||||||
if(progress >= 1f){
|
if(progress >= 1f){
|
||||||
consume();
|
consume();
|
||||||
|
|
||||||
if(outputItem != null){
|
if(outputItems != null){
|
||||||
for(int i = 0; i < outputItem.amount; i++){
|
for(ItemStack output : outputItems){
|
||||||
offload(outputItem.item);
|
for(int i = 0; i < output.amount; i++){
|
||||||
|
offload(output.item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,8 +145,10 @@ public class GenericCrafter extends Block{
|
|||||||
progress %= 1f;
|
progress %= 1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(outputItem != null && timer(timerDump, dumpTime / timeScale)){
|
if(outputItems != null && timer(timerDump, dumpTime / timeScale)){
|
||||||
dump(outputItem.item);
|
for(ItemStack output : outputItems){
|
||||||
|
dump(output.item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(outputLiquid != null){
|
if(outputLiquid != null){
|
||||||
|
|||||||
@@ -281,7 +281,7 @@ public class CoreBlock extends StorageBlock{
|
|||||||
@Override
|
@Override
|
||||||
public void afterDestroyed(){
|
public void afterDestroyed(){
|
||||||
if(state.rules.coreCapture){
|
if(state.rules.coreCapture){
|
||||||
tile.setBlock(block, lastDamage);
|
tile.setNet(block, lastDamage, 0);
|
||||||
//core is invincible for several seconds to prevent recapture
|
//core is invincible for several seconds to prevent recapture
|
||||||
((CoreBuild)tile.build).iframes = captureInvicibility;
|
((CoreBuild)tile.build).iframes = captureInvicibility;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ public class Reconstructor extends UnitBlock{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStats(){
|
public void setStats(){
|
||||||
|
stats.timePeriod = constructTime;
|
||||||
super.setStats();
|
super.setStats();
|
||||||
|
|
||||||
stats.add(Stat.productionTime, constructTime / 60f, StatUnit.seconds);
|
stats.add(Stat.productionTime, constructTime / 60f, StatUnit.seconds);
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ public class StatValues{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
c.add("@none.found");
|
c.add("@none.inmap");
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
c.add("@stat.showinmap");
|
c.add("@stat.showinmap");
|
||||||
|
|||||||
@@ -10,4 +10,4 @@ kapt.include.compile.classpath=false
|
|||||||
kotlin.stdlib.default.dependency=false
|
kotlin.stdlib.default.dependency=false
|
||||||
#needed for android compilation
|
#needed for android compilation
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
archash=b8db131172548e1f10ba86392e09819c34296711
|
archash=626d16628b5c1f69a4a8cbd720eb99bb278e8a1f
|
||||||
|
|||||||
@@ -278,7 +278,7 @@ public class ServerControl implements ApplicationListener{
|
|||||||
|
|
||||||
handler.register("version", "Displays server version info.", arg -> {
|
handler.register("version", "Displays server version info.", arg -> {
|
||||||
info("Version: Mindustry @-@ @ / build @", Version.number, Version.modifier, Version.type, Version.build + (Version.revision == 0 ? "" : "." + Version.revision));
|
info("Version: Mindustry @-@ @ / build @", Version.number, Version.modifier, Version.type, Version.build + (Version.revision == 0 ? "" : "." + Version.revision));
|
||||||
info("Java Version: @", System.getProperty("java.version"));
|
info("Java Version: @", OS.javaVersion);
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.register("exit", "Exit the server application.", arg -> {
|
handler.register("exit", "Exit the server application.", arg -> {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "ALEX",
|
"name": "ALEX",
|
||||||
"address": ["alexmindustryhub.ddns.net:6568", "alexmindustry.ddns.net:6568", "alexmindustry.ddns.net:6569", "alexmindustryattac.ddns.net:25800","alexmindustryturbo.ddns.net:25854","alexmindustryhex.ddns.net:25587"]
|
"address": ["alexmindustryhub.ddns.net:6568", "alexmindustry.ddns.net:25586", "alexmindustry.ddns.net:25587", "alexmindustryattac.ddns.net:25800","alexmindustryturbo.ddns.net:25581","alexmindustryhex.ddns.net:25583"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Minty [subzero]",
|
"name": "Minty [subzero]",
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Omega",
|
"name": "Omega",
|
||||||
"address": ["178.170.47.34:20204", "157.90.213.2:30308", "157.90.180.53:25738"]
|
"address": ["178.170.47.34:20204", "157.90.213.2:30308", "157.90.180.53:25738", "185.86.230.61:25578"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "md.obvilionnetwork.ru",
|
"name": "md.obvilionnetwork.ru",
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Omega",
|
"name": "Omega",
|
||||||
"address": ["157.90.180.53:25777", "redstonneur1256.ml"]
|
"address": ["185.86.230.61:25571", "185.86.230.61:25570", "185.86.230.62:25572"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "MeowLand",
|
"name": "MeowLand",
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class GenericModTest{
|
|||||||
static void grabMod(String url){
|
static void grabMod(String url){
|
||||||
//clear older mods
|
//clear older mods
|
||||||
ApplicationTests.testDataFolder.deleteDirectory();
|
ApplicationTests.testDataFolder.deleteDirectory();
|
||||||
Http.get(url).error(Assertions::fail).block(httpResponse -> {
|
Http.get(url).error(Assertions::fail).timeout(20000).block(httpResponse -> {
|
||||||
try{
|
try{
|
||||||
ApplicationTests.testDataFolder.child("mods").child("test_mod." + (url.endsWith("jar") ? "jar" : "zip")).writeBytes(Streams.copyBytes(httpResponse.getResultAsStream()));
|
ApplicationTests.testDataFolder.child("mods").child("test_mod." + (url.endsWith("jar") ? "jar" : "zip")).writeBytes(Streams.copyBytes(httpResponse.getResultAsStream()));
|
||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
|
|||||||
@@ -598,7 +598,7 @@ public class Generators{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Generates a scorch pixmap based on parameters. Thread safe, unless multiple scorch generators are running in parallel. */
|
/** Generates a scorch pixmap based on parameters. Thread safe. */
|
||||||
public static class ScorchGenerator{
|
public static class ScorchGenerator{
|
||||||
public int size = 80, seed = 0, color = Color.whiteRgba;
|
public int size = 80, seed = 0, color = Color.whiteRgba;
|
||||||
public double scale = 18, pow = 2, octaves = 4, pers = 0.4, add = 2, nscl = 4.5f;
|
public double scale = 18, pow = 2, octaves = 4, pers = 0.4, add = 2, nscl = 4.5f;
|
||||||
|
|||||||
Reference in New Issue
Block a user