mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-02-11 03:08:38 +07:00
Auto-rebuilding enemy drones / GC improvements
This commit is contained in:
parent
273c74b275
commit
625fbdb2d7
Binary file not shown.
@ -792,8 +792,9 @@ public class Fx implements ContentList{
|
||||
Draw.color(Color.LIGHT_GRAY, Color.GRAY, e.fin());
|
||||
|
||||
for(int i : Mathf.signs){
|
||||
float ex = e.x, ey = e.y, fout = e.fout();
|
||||
Angles.randLenVectors(e.id, 4, 1f + e.finpow() * 11f, e.rotation + 90f * i, 20f, (x, y) -> {
|
||||
Fill.circle(e.x + x, e.y + y, e.fout() * 1.5f);
|
||||
Fill.circle(ex + x, ey + y, fout * 1.5f);
|
||||
});
|
||||
}
|
||||
|
||||
@ -816,8 +817,9 @@ public class Fx implements ContentList{
|
||||
Draw.color(Color.LIGHT_GRAY);
|
||||
|
||||
for(int i : Mathf.signs){
|
||||
float ex = e.x, ey = e.y, fout = e.fout();
|
||||
Angles.randLenVectors(e.id, 4, -e.finpow() * 15f, e.rotation + 90f * i, 25f, (x, y) -> {
|
||||
Fill.circle(e.x + x, e.y + y, e.fout() * 2f);
|
||||
Fill.circle(ex + x, ey + y, fout * 2f);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ public class Logic implements ApplicationListener{
|
||||
}
|
||||
|
||||
TeamData data = state.teams.get(tile.getTeam());
|
||||
data.brokenBlocks.addFirst(BrokenBlock.get(tile.x, tile.y, block.id, tile.rotation()));
|
||||
data.brokenBlocks.addFirst(BrokenBlock.get(tile.x, tile.y, tile.rotation(), block.id));
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -360,11 +360,11 @@ public class NetClient implements ApplicationListener{
|
||||
if(timer.get(0, playerSyncTime)){
|
||||
BuildRequest[] requests;
|
||||
//limit to 10 to prevent buffer overflows
|
||||
int usedRequests = Math.min(player.getPlaceQueue().size, 10);
|
||||
int usedRequests = Math.min(player.buildQueue().size, 10);
|
||||
|
||||
requests = new BuildRequest[usedRequests];
|
||||
for(int i = 0; i < usedRequests; i++){
|
||||
requests[i] = player.getPlaceQueue().get(i);
|
||||
requests[i] = player.buildQueue().get(i);
|
||||
}
|
||||
|
||||
Call.onClientShapshot(lastSent++, player.x, player.y,
|
||||
|
@ -282,7 +282,7 @@ public class NetServer implements ApplicationListener{
|
||||
player.isTyping = chatting;
|
||||
player.isBoosting = boosting;
|
||||
player.isShooting = shooting;
|
||||
player.getPlaceQueue().clear();
|
||||
player.buildQueue().clear();
|
||||
for(BuildRequest req : requests){
|
||||
Tile tile = world.tile(req.x, req.y);
|
||||
if(tile == null) continue;
|
||||
@ -292,7 +292,7 @@ public class NetServer implements ApplicationListener{
|
||||
}else if(!req.breaking && tile.block() == req.block && (!req.block.rotate || tile.rotation() == req.rotation)){
|
||||
continue;
|
||||
}
|
||||
player.getPlaceQueue().addLast(req);
|
||||
player.buildQueue().addLast(req);
|
||||
}
|
||||
|
||||
vector.set(x - player.getInterpolator().target.x, y - player.getInterpolator().target.y);
|
||||
|
@ -13,7 +13,6 @@ import io.anuke.mindustry.entities.traits.Entity;
|
||||
import static io.anuke.mindustry.Vars.collisions;
|
||||
|
||||
public class Entities{
|
||||
public static final int maxLeafObjects = 4;
|
||||
private static final Array<EntityGroup<?>> groupArray = new Array<>();
|
||||
private static final IntMap<EntityGroup<?>> groups = new IntMap<>();
|
||||
private static final Rectangle viewport = new Rectangle();
|
||||
|
@ -17,7 +17,7 @@ public class EntityGroup<T extends Entity>{
|
||||
private final Array<T> entitiesToRemove = new Array<>(false, 16);
|
||||
private final Array<T> entitiesToAdd = new Array<>(false, 16);
|
||||
private IntMap<T> map;
|
||||
private QuadTree<T> tree;
|
||||
private QuadTree tree;
|
||||
private Consumer<T> removeListener;
|
||||
private Consumer<T> addListener;
|
||||
|
||||
@ -27,7 +27,7 @@ public class EntityGroup<T extends Entity>{
|
||||
this.type = type;
|
||||
|
||||
if(useTree){
|
||||
tree = new QuadTree<>(Entities.maxLeafObjects, new Rectangle(0, 0, 0, 0));
|
||||
tree = new QuadTree<>(new Rectangle(0, 0, 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,7 +124,7 @@ public class EntityGroup<T extends Entity>{
|
||||
/** Resizes the internal quadtree, if it is enabled.*/
|
||||
public void resize(float x, float y, float w, float h){
|
||||
if(useTree){
|
||||
tree = new QuadTree<>(Entities.maxLeafObjects, new Rectangle(x, y, w, h));
|
||||
tree = new QuadTree<>(new Rectangle(x, y, w, h));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ public interface BuilderMinerTrait extends MinerTrait, BuilderTrait{
|
||||
updateBuilding();
|
||||
|
||||
//mine only when not building
|
||||
if(getCurrentRequest() == null){
|
||||
if(buildRequest() == null){
|
||||
updateMining();
|
||||
}
|
||||
}
|
||||
|
@ -35,21 +35,21 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
Unit unit = (Unit)this;
|
||||
//remove already completed build requests
|
||||
removal.clear();
|
||||
for(BuildRequest req : getPlaceQueue()){
|
||||
for(BuildRequest req : buildQueue()){
|
||||
removal.add(req);
|
||||
}
|
||||
|
||||
getPlaceQueue().clear();
|
||||
buildQueue().clear();
|
||||
|
||||
for(BuildRequest request : removal){
|
||||
if(!((request.breaking && world.tile(request.x, request.y).block() == Blocks.air) ||
|
||||
(!request.breaking && (world.tile(request.x, request.y).rotation() == request.rotation || !request.block.rotate)
|
||||
&& world.tile(request.x, request.y).block() == request.block))){
|
||||
getPlaceQueue().addLast(request);
|
||||
buildQueue().addLast(request);
|
||||
}
|
||||
}
|
||||
|
||||
BuildRequest current = getCurrentRequest();
|
||||
BuildRequest current = buildRequest();
|
||||
|
||||
if(current == null){
|
||||
return;
|
||||
@ -58,9 +58,9 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
Tile tile = world.tile(current.x, current.y);
|
||||
|
||||
if(dst(tile) > finalPlaceDst){
|
||||
if(getPlaceQueue().size > 1){
|
||||
getPlaceQueue().removeFirst();
|
||||
getPlaceQueue().addLast(current);
|
||||
if(buildQueue().size > 1){
|
||||
buildQueue().removeFirst();
|
||||
buildQueue().addLast(current);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -71,7 +71,7 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
}else if(canCreateBlocks() && current.breaking && Build.validBreak(getTeam(), current.x, current.y)){
|
||||
Call.beginBreak(getTeam(), current.x, current.y);
|
||||
}else{
|
||||
getPlaceQueue().removeFirst();
|
||||
buildQueue().removeFirst();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -115,7 +115,7 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
}
|
||||
|
||||
/** Returns the queue for storing build requests. */
|
||||
Queue<BuildRequest> getPlaceQueue();
|
||||
Queue<BuildRequest> buildQueue();
|
||||
|
||||
/** Build power, can be any float. 1 = builds recipes in normal time, 0 = doesn't build at all. */
|
||||
float getBuildPower(Tile tile);
|
||||
@ -126,7 +126,7 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
}
|
||||
|
||||
default void writeBuilding(DataOutput output) throws IOException{
|
||||
BuildRequest request = getCurrentRequest();
|
||||
BuildRequest request = buildRequest();
|
||||
|
||||
if(request != null){
|
||||
output.writeByte(request.breaking ? 1 : 0);
|
||||
@ -146,7 +146,7 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
}
|
||||
|
||||
default void readBuilding(DataInput input, boolean applyChanges) throws IOException{
|
||||
if(applyChanges) getPlaceQueue().clear();
|
||||
if(applyChanges) buildQueue().clear();
|
||||
|
||||
byte type = input.readByte();
|
||||
if(type != -1){
|
||||
@ -165,26 +165,26 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
request.progress = progress;
|
||||
|
||||
if(applyChanges){
|
||||
getPlaceQueue().addLast(request);
|
||||
buildQueue().addLast(request);
|
||||
}else if(isBuilding()){
|
||||
getCurrentRequest().progress = progress;
|
||||
buildRequest().progress = progress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Return whether this builder's place queue contains items. */
|
||||
default boolean isBuilding(){
|
||||
return getPlaceQueue().size != 0;
|
||||
return buildQueue().size != 0;
|
||||
}
|
||||
|
||||
/** Clears the placement queue. */
|
||||
default void clearBuilding(){
|
||||
getPlaceQueue().clear();
|
||||
buildQueue().clear();
|
||||
}
|
||||
|
||||
/** Add another build requests to the tail of the queue, if it doesn't exist there yet. */
|
||||
default void addBuildRequest(BuildRequest place){
|
||||
for(BuildRequest request : getPlaceQueue()){
|
||||
for(BuildRequest request : buildQueue()){
|
||||
if(request.x == place.x && request.y == place.y){
|
||||
return;
|
||||
}
|
||||
@ -193,15 +193,15 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
if(tile != null && tile.entity instanceof BuildEntity){
|
||||
place.progress = tile.<BuildEntity>entity().progress;
|
||||
}
|
||||
getPlaceQueue().addLast(place);
|
||||
buildQueue().addLast(place);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the build requests currently active, or the one at the top of the queue.
|
||||
* May return null.
|
||||
*/
|
||||
default BuildRequest getCurrentRequest(){
|
||||
return getPlaceQueue().size == 0 ? null : getPlaceQueue().first();
|
||||
default BuildRequest buildRequest(){
|
||||
return buildQueue().size == 0 ? null : buildQueue().first();
|
||||
}
|
||||
|
||||
//due to iOS weirdness, this is apparently required
|
||||
@ -215,7 +215,7 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
if(!isBuilding()) return;
|
||||
|
||||
Unit unit = (Unit)this;
|
||||
BuildRequest request = getCurrentRequest();
|
||||
BuildRequest request = buildRequest();
|
||||
Tile tile = world.tile(request.x, request.y);
|
||||
|
||||
if(dst(tile) > placeDistance && !state.isEditor()){
|
||||
|
@ -112,10 +112,8 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
this.state.set(state);
|
||||
}
|
||||
|
||||
public void retarget(Runnable run){
|
||||
if(timer.get(timerTarget, 20)){
|
||||
run.run();
|
||||
}
|
||||
public boolean retarget(){
|
||||
return timer.get(timerTarget, 20);
|
||||
}
|
||||
|
||||
/** Only runs when the unit has a target. */
|
||||
|
@ -32,7 +32,7 @@ public abstract class FlyingUnit extends BaseUnit{
|
||||
target = null;
|
||||
}
|
||||
|
||||
retarget(() -> {
|
||||
if(retarget()){
|
||||
targetClosest();
|
||||
|
||||
if(target == null) targetClosestEnemyFlag(BlockFlag.producer);
|
||||
@ -41,7 +41,7 @@ public abstract class FlyingUnit extends BaseUnit{
|
||||
if(target == null){
|
||||
setState(patrol);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if(target != null){
|
||||
attack(type.attackLength);
|
||||
@ -71,7 +71,7 @@ public abstract class FlyingUnit extends BaseUnit{
|
||||
},
|
||||
patrol = new UnitState(){
|
||||
public void update(){
|
||||
retarget(() -> {
|
||||
if(retarget()){
|
||||
targetClosest();
|
||||
targetClosestEnemyFlag(BlockFlag.target);
|
||||
|
||||
@ -81,7 +81,7 @@ public abstract class FlyingUnit extends BaseUnit{
|
||||
}
|
||||
|
||||
target = getClosestCore();
|
||||
});
|
||||
};
|
||||
|
||||
if(target != null){
|
||||
circle(60f + Mathf.absin(Time.time() + Mathf.randomSeed(id) * 1200f, 70f, 1200f));
|
||||
|
@ -176,7 +176,9 @@ public abstract class GroundUnit extends BaseUnit{
|
||||
target = null;
|
||||
}
|
||||
|
||||
retarget(this::targetClosest);
|
||||
if(retarget()){
|
||||
targetClosest();
|
||||
}
|
||||
}
|
||||
|
||||
protected void patrol(){
|
||||
|
@ -241,7 +241,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
}
|
||||
|
||||
@Override
|
||||
public Queue<BuildRequest> getPlaceQueue(){
|
||||
public Queue<BuildRequest> buildQueue(){
|
||||
return placeQueue;
|
||||
}
|
||||
|
||||
@ -428,8 +428,8 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
/** Draw all current build requests. Does not draw the beam effect, only the positions. */
|
||||
public void drawBuildRequests(){
|
||||
BuildRequest last = null;
|
||||
for(BuildRequest request : getPlaceQueue()){
|
||||
if(request.progress > 0.01f || (getCurrentRequest() == request && (dst(request.x * tilesize, request.y * tilesize) <= placeDistance || state.isEditor()))) continue;
|
||||
for(BuildRequest request : buildQueue()){
|
||||
if(request.progress > 0.01f || (buildRequest() == request && (dst(request.x * tilesize, request.y * tilesize) <= placeDistance || state.isEditor()))) continue;
|
||||
|
||||
if(request.breaking){
|
||||
Block block = world.ltile(request.x, request.y).block();
|
||||
|
@ -19,14 +19,14 @@ public abstract class BaseDrone extends FlyingUnit{
|
||||
if(health >= maxHealth()){
|
||||
state.set(attack);
|
||||
}else if(!targetHasFlag(BlockFlag.repair)){
|
||||
retarget(() -> {
|
||||
if(retarget()){
|
||||
Tile repairPoint = Geometry.findClosest(x, y, world.indexer.getAllied(team, BlockFlag.repair));
|
||||
if(repairPoint != null){
|
||||
target = repairPoint;
|
||||
}else{
|
||||
setState(getStartState());
|
||||
}
|
||||
});
|
||||
}
|
||||
}else{
|
||||
circle(40f);
|
||||
}
|
||||
|
@ -6,12 +6,15 @@ import io.anuke.arc.collection.IntIntMap;
|
||||
import io.anuke.arc.collection.Queue;
|
||||
import io.anuke.arc.math.Mathf;
|
||||
import io.anuke.arc.util.*;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.entities.EntityGroup;
|
||||
import io.anuke.mindustry.entities.traits.BuilderTrait;
|
||||
import io.anuke.mindustry.entities.traits.TargetTrait;
|
||||
import io.anuke.mindustry.entities.type.*;
|
||||
import io.anuke.mindustry.entities.units.UnitState;
|
||||
import io.anuke.mindustry.game.EventType.BuildSelectEvent;
|
||||
import io.anuke.mindustry.game.Teams.TeamData;
|
||||
import io.anuke.mindustry.gen.BrokenBlock;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
||||
@ -20,7 +23,6 @@ import java.io.*;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
//TODO follow players
|
||||
public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
||||
private static final StaticReset reset = new StaticReset();
|
||||
private static final IntIntMap totals = new IntIntMap();
|
||||
@ -43,12 +45,22 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
||||
BuildEntity entity = (BuildEntity)target;
|
||||
TileEntity core = getClosestCore();
|
||||
|
||||
if(entity != null && core != null && (entity.progress < 1f || entity.progress > 0f) && entity.tile.block() instanceof BuildBlock){ //building is valid
|
||||
if(isBuilding() && entity == null && isRebuild()){
|
||||
target = world.tile(buildRequest().x, buildRequest().y);
|
||||
circle(placeDistance * 0.7f);
|
||||
target = null;
|
||||
|
||||
BuildRequest request = buildRequest();
|
||||
|
||||
if(world.tile(request.x, request.y).entity instanceof BuildEntity){
|
||||
target = world.tile(request.x, request.y).entity;
|
||||
}
|
||||
}else if(entity != null && core != null && (entity.progress < 1f || entity.progress > 0f) && entity.tile.block() instanceof BuildBlock){ //building is valid
|
||||
if(!isBuilding() && dst(target) < placeDistance * 0.9f){ //within distance, begin placing
|
||||
if(isBreaking){
|
||||
getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y));
|
||||
buildQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y));
|
||||
}else{
|
||||
getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y, entity.tile.rotation(), entity.cblock));
|
||||
buildQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y, entity.tile.rotation(), entity.cblock));
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,7 +70,7 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
||||
if(playerTarget == null || playerTarget.getTeam() != team || !playerTarget.isValid()){
|
||||
playerTarget = null;
|
||||
|
||||
retarget(() -> {
|
||||
if(retarget()){
|
||||
float minDst = Float.POSITIVE_INFINITY;
|
||||
int minDrones = Integer.MAX_VALUE;
|
||||
|
||||
@ -75,7 +87,13 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if(getSpawner() != null){
|
||||
target = getSpawner();
|
||||
circle(40f);
|
||||
target = null;
|
||||
}
|
||||
}else{
|
||||
incDrones(playerTarget);
|
||||
TargetTrait prev = target;
|
||||
@ -103,7 +121,7 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
||||
BuilderDrone drone = (BuilderDrone)unit;
|
||||
if(drone.isBuilding()){
|
||||
//stop building if opposite building begins.
|
||||
BuildRequest req = drone.getCurrentRequest();
|
||||
BuildRequest req = drone.buildRequest();
|
||||
if(req.breaking != event.breaking && req.x == event.tile.x && req.y == event.tile.y){
|
||||
drone.clearBuilding();
|
||||
drone.target = null;
|
||||
@ -131,13 +149,17 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
||||
}
|
||||
}
|
||||
|
||||
boolean isRebuild(){
|
||||
return Vars.state.rules.enemyCheat && team == waveTeam;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getBuildPower(Tile tile){
|
||||
return type.buildPower;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Queue<BuildRequest> getPlaceQueue(){
|
||||
public Queue<BuildRequest> buildQueue(){
|
||||
return placeQueue;
|
||||
}
|
||||
|
||||
@ -147,8 +169,8 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
||||
|
||||
if(!isBuilding() && timer.get(timerTarget2, 15)){
|
||||
for(Player player : playerGroup.all()){
|
||||
if(player.getTeam() == team && player.getCurrentRequest() != null){
|
||||
BuildRequest req = player.getCurrentRequest();
|
||||
if(player.getTeam() == team && player.buildRequest() != null){
|
||||
BuildRequest req = player.buildRequest();
|
||||
Tile tile = world.tile(req.x, req.y);
|
||||
if(tile != null && tile.entity instanceof BuildEntity){
|
||||
BuildEntity b = tile.entity();
|
||||
@ -162,6 +184,16 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(isRebuild()){
|
||||
TeamData data = Vars.state.teams.get(team);
|
||||
if(!data.brokenBlocks.isEmpty()){
|
||||
long block = data.brokenBlocks.removeLast();
|
||||
|
||||
placeQueue.addFirst(new BuildRequest(BrokenBlock.x(block), BrokenBlock.y(block), BrokenBlock.rotation(block), content.block(BrokenBlock.block(block))));
|
||||
setState(build);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateBuilding();
|
||||
|
@ -52,13 +52,13 @@ public class MinerDrone extends BaseDrone implements MinerTrait{
|
||||
return;
|
||||
}
|
||||
|
||||
retarget(() -> {
|
||||
if(retarget()){
|
||||
findItem();
|
||||
|
||||
if(targetItem == null) return;
|
||||
|
||||
target = world.indexer.findClosestOre(x, y, targetItem);
|
||||
});
|
||||
};
|
||||
|
||||
if(target instanceof Tile){
|
||||
moveTo(type.range / 1.5f);
|
||||
|
@ -19,7 +19,9 @@ public class RepairDrone extends BaseDrone{
|
||||
|
||||
public void update(){
|
||||
|
||||
retarget(() -> target = Units.findDamagedTile(team, x, y));
|
||||
if(retarget()){
|
||||
target = Units.findDamagedTile(team, x, y);
|
||||
}
|
||||
|
||||
if(target != null){
|
||||
if(target.dst(RepairDrone.this) > type.range){
|
||||
|
@ -42,11 +42,17 @@ public class Teams{
|
||||
return enemiesOf(team).contains(other);
|
||||
}
|
||||
|
||||
public class TeamData{
|
||||
/** Allocates a new array with the active teams.
|
||||
* Never call in the main game loop.*/
|
||||
public Array<TeamData> getActive(){
|
||||
return Array.select(map, t -> t != null);
|
||||
}
|
||||
|
||||
public static class TeamData{
|
||||
public final ObjectSet<Tile> cores = new ObjectSet<>();
|
||||
public final LongQueue brokenBlocks = new LongQueue();
|
||||
public final EnumSet<Team> enemies;
|
||||
public final Team team;
|
||||
public LongQueue brokenBlocks = new LongQueue();
|
||||
|
||||
public TeamData(Team team, EnumSet<Team> enemies){
|
||||
this.team = team;
|
||||
|
@ -214,7 +214,7 @@ public class DesktopInput extends InputHandler{
|
||||
mode = placing;
|
||||
}else if(selected != null){
|
||||
//only begin shooting if there's no cursor event
|
||||
if(!tileTapped(selected) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && player.getPlaceQueue().size == 0 && !droppingItem &&
|
||||
if(!tileTapped(selected) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && player.buildQueue().size == 0 && !droppingItem &&
|
||||
!tryBeginMine(selected) && player.getMineTile() == null && !ui.chatfrag.chatOpen()){
|
||||
player.isShooting = true;
|
||||
}
|
||||
@ -222,7 +222,7 @@ public class DesktopInput extends InputHandler{
|
||||
player.isShooting = true;
|
||||
}
|
||||
}else if(Core.input.keyTap(Binding.deselect) && (block != null || mode != none || player.isBuilding()) &&
|
||||
!(player.getCurrentRequest() != null && player.getCurrentRequest().breaking && Core.keybinds.get(Binding.deselect) == Core.keybinds.get(Binding.break_block))){
|
||||
!(player.buildRequest() != null && player.buildRequest().breaking && Core.keybinds.get(Binding.deselect) == Core.keybinds.get(Binding.break_block))){
|
||||
if(block == null){
|
||||
player.clearBuilding();
|
||||
}
|
||||
|
@ -1,10 +1,12 @@
|
||||
package io.anuke.mindustry.io;
|
||||
|
||||
import io.anuke.arc.collection.EnumSet;
|
||||
import io.anuke.arc.collection.LongQueue;
|
||||
import io.anuke.arc.util.serialization.Json;
|
||||
import io.anuke.arc.util.serialization.JsonValue;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.game.Rules;
|
||||
import io.anuke.mindustry.game.SpawnGroup;
|
||||
import io.anuke.mindustry.game.*;
|
||||
import io.anuke.mindustry.game.Teams.TeamData;
|
||||
import io.anuke.mindustry.type.*;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@ -36,6 +38,25 @@ public class JsonIO{
|
||||
return Vars.content.getByName(ContentType.item, jsonData.asString());
|
||||
}
|
||||
});
|
||||
|
||||
setSerializer(TeamData.class, new Serializer<TeamData>(){
|
||||
@Override
|
||||
public void write(Json json, TeamData object, Class knownType){
|
||||
json.writeObjectStart();
|
||||
json.writeValue("brokenBlocks", object.brokenBlocks.toArray());
|
||||
json.writeValue("team", object.team.ordinal());
|
||||
json.writeObjectEnd();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TeamData read(Json json, JsonValue jsonData, Class type){
|
||||
long[] blocks = jsonData.get("brokenBlocks").asLongArray();
|
||||
Team team = Team.all[jsonData.getInt("team", 0)];
|
||||
TeamData out = new TeamData(team, EnumSet.of(new Team[]{}));
|
||||
out.brokenBlocks = new LongQueue(blocks);
|
||||
return out;
|
||||
}
|
||||
});
|
||||
}};
|
||||
|
||||
public static String write(Object object){
|
||||
|
@ -1,13 +1,14 @@
|
||||
package io.anuke.mindustry.io;
|
||||
|
||||
import io.anuke.arc.collection.Array;
|
||||
import io.anuke.arc.collection.StringMap;
|
||||
import io.anuke.arc.collection.*;
|
||||
import io.anuke.arc.util.Time;
|
||||
import io.anuke.arc.util.io.CounterInputStream;
|
||||
import io.anuke.mindustry.entities.Entities;
|
||||
import io.anuke.mindustry.entities.EntityGroup;
|
||||
import io.anuke.mindustry.entities.traits.*;
|
||||
import io.anuke.mindustry.game.*;
|
||||
import io.anuke.mindustry.game.Teams.TeamData;
|
||||
import io.anuke.mindustry.gen.BrokenBlock;
|
||||
import io.anuke.mindustry.maps.Map;
|
||||
import io.anuke.mindustry.type.ContentType;
|
||||
import io.anuke.mindustry.world.*;
|
||||
@ -64,6 +65,7 @@ public abstract class SaveVersion extends SaveFileReader{
|
||||
"wavetime", state.wavetime,
|
||||
"stats", JsonIO.write(state.stats),
|
||||
"rules", JsonIO.write(state.rules),
|
||||
"teamdata", JsonIO.write(state.teams.getActive().toArray(TeamData.class)),
|
||||
"width", world.width(),
|
||||
"height", world.height()
|
||||
).merge(tags));
|
||||
@ -77,6 +79,13 @@ public abstract class SaveVersion extends SaveFileReader{
|
||||
state.stats = JsonIO.read(Stats.class, map.get("stats", "{}"));
|
||||
state.rules = JsonIO.read(Rules.class, map.get("rules", "{}"));
|
||||
if(state.rules.spawns.isEmpty()) state.rules.spawns = defaultWaves.get();
|
||||
|
||||
//only broken blocks are transferred over right now; nothing else
|
||||
TeamData[] teams = JsonIO.read(TeamData[].class, map.get("teamdata", "[]"));
|
||||
for(TeamData data : teams){
|
||||
state.teams.get(data.team).brokenBlocks = data.brokenBlocks;
|
||||
}
|
||||
|
||||
Map worldmap = world.maps.byName(map.get("mapname", "\\\\\\"));
|
||||
world.setMap(worldmap == null ? new Map(StringMap.of(
|
||||
"name", map.get("mapname", "Unknown"),
|
||||
@ -92,13 +101,13 @@ public abstract class SaveVersion extends SaveFileReader{
|
||||
|
||||
//floor + overlay
|
||||
for(int i = 0; i < world.width() * world.height(); i++){
|
||||
Tile tile = world.tile(i % world.width(), i / world.width());
|
||||
Tile tile = world.rawTile(i % world.width(), i / world.width());
|
||||
stream.writeShort(tile.floorID());
|
||||
stream.writeShort(tile.overlayID());
|
||||
int consecutives = 0;
|
||||
|
||||
for(int j = i + 1; j < world.width() * world.height() && consecutives < 255; j++){
|
||||
Tile nextTile = world.tile(j % world.width(), j / world.width());
|
||||
Tile nextTile = world.rawTile(j % world.width(), j / world.width());
|
||||
|
||||
if(nextTile.floorID() != tile.floorID() || nextTile.overlayID() != tile.overlayID()){
|
||||
break;
|
||||
@ -113,7 +122,7 @@ public abstract class SaveVersion extends SaveFileReader{
|
||||
|
||||
//blocks
|
||||
for(int i = 0; i < world.width() * world.height(); i++){
|
||||
Tile tile = world.tile(i % world.width(), i / world.width());
|
||||
Tile tile = world.rawTile(i % world.width(), i / world.width());
|
||||
stream.writeShort(tile.blockID());
|
||||
|
||||
if(tile.entity != null){
|
||||
@ -126,7 +135,7 @@ public abstract class SaveVersion extends SaveFileReader{
|
||||
int consecutives = 0;
|
||||
|
||||
for(int j = i + 1; j < world.width() * world.height() && consecutives < 255; j++){
|
||||
Tile nextTile = world.tile(j % world.width(), j / world.width());
|
||||
Tile nextTile = world.rawTile(j % world.width(), j / world.width());
|
||||
|
||||
if(nextTile.blockID() != tile.blockID()){
|
||||
break;
|
||||
@ -264,6 +273,8 @@ public abstract class SaveVersion extends SaveFileReader{
|
||||
}
|
||||
|
||||
content.setTemporaryMapper(map);
|
||||
|
||||
remapContent();
|
||||
}
|
||||
|
||||
public void writeContentHeader(DataOutput stream) throws IOException{
|
||||
@ -287,4 +298,17 @@ public abstract class SaveVersion extends SaveFileReader{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** sometimes it's necessary to remap IDs after the content header is read.*/
|
||||
public void remapContent(){
|
||||
for(Team team : Team.all){
|
||||
if(state.teams.isActive(team)){
|
||||
LongQueue queue = state.teams.get(team).brokenBlocks;
|
||||
for(int i = 0; i < queue.size; i++){
|
||||
//remap broken block IDs
|
||||
queue.set(i, BrokenBlock.block(queue.get(i), content.block(BrokenBlock.block(queue.get(i))).id));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,7 @@ public class CustomRulesDialog extends FloatingDialog{
|
||||
|
||||
title("$rules.title.enemy");
|
||||
check("$rules.attack", b -> rules.attackMode = b, () -> rules.attackMode);
|
||||
check("$rules.enemyCheat", b -> rules.enemyCheat = b, () -> rules.enemyCheat);
|
||||
number("$rules.enemycorebuildradius", f -> rules.enemyCoreBuildRadius = f * tilesize, () -> Math.min(rules.enemyCoreBuildRadius / tilesize, 200));
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,6 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
sound.add("[LIGHT_GRAY]there is no sound implemented in v4 yet");
|
||||
|
||||
game.screenshakePref();
|
||||
game.checkPref("effects", true);
|
||||
if(mobile){
|
||||
game.checkPref("autotarget", true);
|
||||
}
|
||||
@ -212,6 +211,7 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
}
|
||||
}
|
||||
|
||||
graphics.checkPref("effects", true);
|
||||
graphics.checkPref("playerchat", true);
|
||||
graphics.checkPref("minimap", !mobile);
|
||||
graphics.checkPref("fps", false);
|
||||
|
Loading…
Reference in New Issue
Block a user