Major refactoring of building, sound, inventory

This commit is contained in:
Anuken
2018-05-20 17:59:52 -04:00
parent de40df7f7b
commit c1a5482ad2
40 changed files with 348 additions and 991 deletions

View File

@@ -4,6 +4,7 @@ import com.squareup.javapoet.*;
import io.anuke.annotations.Annotations.Local; import io.anuke.annotations.Annotations.Local;
import io.anuke.annotations.Annotations.RemoteClient; import io.anuke.annotations.Annotations.RemoteClient;
import io.anuke.annotations.Annotations.RemoteServer; import io.anuke.annotations.Annotations.RemoteServer;
import io.anuke.annotations.Annotations.Unreliable;
import javax.annotation.processing.*; import javax.annotation.processing.*;
import javax.lang.model.SourceVersion; import javax.lang.model.SourceVersion;
@@ -22,7 +23,8 @@ import java.util.Set;
@SupportedAnnotationTypes({ @SupportedAnnotationTypes({
"io.anuke.annotations.Annotations.RemoteClient", "io.anuke.annotations.Annotations.RemoteClient",
"io.anuke.annotations.Annotations.RemoteServer", "io.anuke.annotations.Annotations.RemoteServer",
"io.anuke.annotations.Annotations.Local" "io.anuke.annotations.Annotations.Local",
"io.anuke.annotations.Annotations.Unreliable"
}) })
public class AnnotationProcessor extends AbstractProcessor { public class AnnotationProcessor extends AbstractProcessor {
private static final int maxPacketSize = 128; private static final int maxPacketSize = 128;
@@ -39,6 +41,19 @@ public class AnnotationProcessor extends AbstractProcessor {
"rtype rvalue = io.anuke.mindustry.Vars.playerGroup.getByID(rbuffer.getInt())" "rtype rvalue = io.anuke.mindustry.Vars.playerGroup.getByID(rbuffer.getInt())"
} }
}); });
put("String", new String[][]{
{
"rbuffer.putShort((short)rvalue.getBytes().length)",
"rbuffer.put(rvalue.getBytes())"
},
{
"short __rvalue_length = rbuffer.getShort()",
"byte[] __rvalue_bytes = new byte[__rvalue_length]",
"rbuffer.get(__rvalue_bytes)",
"rtype rvalue = new rtype(__rvalue_bytes)"
}
});
}}; }};
private Types typeUtils; private Types typeUtils;
@@ -109,6 +124,7 @@ public class AnnotationProcessor extends AbstractProcessor {
if(e.getAnnotation(annotation) == null) continue; if(e.getAnnotation(annotation) == null) continue;
boolean local = e.getAnnotation(Local.class) != null; boolean local = e.getAnnotation(Local.class) != null;
boolean unreliable = e.getAnnotation(Unreliable.class) != null;
ExecutableElement exec = (ExecutableElement)e; ExecutableElement exec = (ExecutableElement)e;
@@ -211,7 +227,8 @@ public class AnnotationProcessor extends AbstractProcessor {
} }
} }
method.addStatement("packet.writeLength = TEMP_BUFFER.position()"); method.addStatement("packet.writeLength = TEMP_BUFFER.position()");
method.addStatement("io.anuke.mindustry.net.Net.send(packet, io.anuke.mindustry.net.Net.SendMode.tcp)"); method.addStatement("io.anuke.mindustry.net.Net.send(packet, "+
(unreliable ? "io.anuke.mindustry.net.Net.SendMode.udp" : "io.anuke.mindustry.net.Net.SendMode.tcp")+")");
classBuilder.addMethod(method.build()); classBuilder.addMethod(method.build());

View File

@@ -14,7 +14,8 @@ import java.lang.annotation.Target;
* {@link RemoteServer}: Marks a method as able to be invoked remotely on a server from a client.<br> * {@link RemoteServer}: Marks a method as able to be invoked remotely on a server from a client.<br>
* {@link Local}: Makes this method get invoked locally as well as remotely.<br> * {@link Local}: Makes this method get invoked locally as well as remotely.<br>
*<br> *<br>
* All RemoteClient methods are put in the class CallClient, and all RemoteServer methods are put in the class CallServer.<br> * All RemoteClient methods are put in the class io.anuke.mindustry.gen.CallClient.<br>
* All RemoteServer methods are put in the class io.anuke.mindustry.gen.CallServer.<br>
*/ */
public class Annotations { public class Annotations {
@@ -35,4 +36,10 @@ public class Annotations {
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS) @Retention(RetentionPolicy.CLASS)
public @interface Local{} public @interface Local{}
/**Marks a method to be invoked unreliably, e.g. with UDP instead of TCP.
* This is faster, but is prone to packet loss and duplication.*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface Unreliable{}
} }

View File

@@ -46,13 +46,11 @@ public class PowerBlocks {
nuclearReactor = new NuclearReactor("nuclearreactor") {{ nuclearReactor = new NuclearReactor("nuclearreactor") {{
size = 3; size = 3;
health = 600; health = 600;
breaktime *= 2.3f;
}}, }},
fusionReactor = new FusionReactor("fusionreactor") {{ fusionReactor = new FusionReactor("fusionreactor") {{
size = 4; size = 4;
health = 600; health = 600;
breaktime *= 4f;
}}, }},
repairturret = new RepairTurret("repairturret") {{ repairturret = new RepairTurret("repairturret") {{

View File

@@ -60,7 +60,7 @@ public class ContentLoader {
Log.info("--- CONTENT INFO ---"); Log.info("--- CONTENT INFO ---");
Log.info("Blocks loaded: {0}\nItems loaded: {1}\nLiquids loaded: {2}\nUpgrades loaded: {3}\nUnits loaded: {4}\nAmmo types loaded: {5}\nStatus effects loaded: {6}\nRecipes loaded: {7}\nTotal content classes: {8}", Log.info("Blocks loaded: {0}\nItems loaded: {1}\nLiquids loaded: {2}\nUpgrades loaded: {3}\nUnits loaded: {4}\nAmmo types loaded: {5}\nStatus effects loaded: {6}\nRecipes loaded: {7}\nTotal content classes: {8}",
Block.getAllBlocks().size, Item.getAllItems().size, Liquid.getAllLiquids().size, Block.getAllBlocks().size, Item.getAllItems().size, Liquid.getAllLiquids().size,
Mech.getAllUpgrades().size, UnitType.getAllTypes().size, AmmoType.getAllTypes().size, StatusEffect.getAllEffects().size, Recipe.all().size, content.length); Mech.getAllUpgrades().size, UnitType.getAllTypes().size, AmmoType.getAllTypes().size, StatusEffect.getAllEffects().size, Recipe.getAllRecipes().size, content.length);
Log.info("-------------------"); Log.info("-------------------");
} }

View File

@@ -2,7 +2,10 @@ package io.anuke.mindustry.core;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input; import com.badlogic.gdx.Input;
import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.TimeUtils;
import io.anuke.mindustry.content.Mechs; import io.anuke.mindustry.content.Mechs;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Player;
@@ -20,7 +23,7 @@ import io.anuke.ucore.core.*;
import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.input.InputProxy; import io.anuke.ucore.input.InputProxy;
import io.anuke.ucore.modules.Module; import io.anuke.ucore.modules.Module;
import io.anuke.ucore.util.*; import io.anuke.ucore.util.Atlas;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
@@ -29,10 +32,14 @@ import static io.anuke.mindustry.Vars.*;
* Should <i>not</i> handle any logic-critical state. * Should <i>not</i> handle any logic-critical state.
* This class is not created in the headless server.*/ * This class is not created in the headless server.*/
public class Control extends Module{ public class Control extends Module{
/**Minimum period of time between the same sound being played.*/
private static final long minSoundPeriod = 30;
private boolean hiscore = false; private boolean hiscore = false;
private boolean wasPaused = false; private boolean wasPaused = false;
private Saves saves; private Saves saves;
private InputHandler[] inputs = {}; private InputHandler[] inputs = {};
private ObjectMap<Sound, Long> soundMap = new ObjectMap<>();
private Throwable error; private Throwable error;
private InputProxy proxy; private InputProxy proxy;
@@ -85,6 +92,15 @@ public class Control extends Module{
"ping.mp3", "tesla.mp3", "waveend.mp3", "railgun.mp3", "blast.mp3", "bang2.mp3"); "ping.mp3", "tesla.mp3", "waveend.mp3", "railgun.mp3", "blast.mp3", "bang2.mp3");
Sounds.setFalloff(9000f); Sounds.setFalloff(9000f);
Sounds.setPlayer(((sound, volume) -> {
long time = TimeUtils.millis();
long value = soundMap.get(sound, 0L);
if(TimeUtils.timeSinceMillis(value) >= minSoundPeriod){
threads.run(() -> sound.play(volume));
soundMap.put(sound, time);
}
}));
Musics.load("1.mp3", "2.mp3", "3.mp3", "4.mp3"); Musics.load("1.mp3", "2.mp3", "3.mp3", "4.mp3");

View File

@@ -3,15 +3,12 @@ package io.anuke.mindustry.core;
import io.anuke.mindustry.game.Difficulty; import io.anuke.mindustry.game.Difficulty;
import io.anuke.mindustry.game.EventType.StateChangeEvent; import io.anuke.mindustry.game.EventType.StateChangeEvent;
import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.game.GameMode;
import io.anuke.mindustry.game.Inventory;
import io.anuke.mindustry.game.TeamInfo; import io.anuke.mindustry.game.TeamInfo;
import io.anuke.ucore.core.Events; import io.anuke.ucore.core.Events;
public class GameState{ public class GameState{
private State state = State.menu; private State state = State.menu;
public final Inventory inventory = new Inventory();
public int wave = 1; public int wave = 1;
public float wavetime; public float wavetime;
public float extrawavetime; public float extrawavetime;

View File

@@ -17,8 +17,6 @@ import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.EntityGroup; import io.anuke.ucore.entities.EntityGroup;
import io.anuke.ucore.modules.Module; import io.anuke.ucore.modules.Module;
import java.sql.Time;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
/**Logic module. /**Logic module.
@@ -44,12 +42,6 @@ public class Logic extends Module {
public void play(){ public void play(){
state.wavetime = wavespace * state.difficulty.timeScaling * 2; state.wavetime = wavespace * state.difficulty.timeScaling * 2;
if(state.mode.infiniteResources){
state.inventory.fill();
}else{
state.inventory.clearItems();
}
Events.fire(PlayEvent.class); Events.fire(PlayEvent.class);
} }

View File

@@ -3,7 +3,6 @@ package io.anuke.mindustry.core;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.IntMap; import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.IntSet; import com.badlogic.gdx.utils.IntSet;
import io.anuke.mindustry.content.UpgradeRecipes;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.BulletType;
import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Player;
@@ -17,7 +16,7 @@ import io.anuke.mindustry.net.Packets.*;
import io.anuke.mindustry.resource.Recipe; import io.anuke.mindustry.resource.Recipe;
import io.anuke.mindustry.resource.Upgrade; import io.anuke.mindustry.resource.Upgrade;
import io.anuke.mindustry.resource.Weapon; import io.anuke.mindustry.resource.Weapon;
import io.anuke.mindustry.world.Placement; import io.anuke.mindustry.world.Build;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
@@ -153,8 +152,6 @@ public class NetClient extends Module {
}); });
Net.handleClient(StateSyncPacket.class, packet -> { Net.handleClient(StateSyncPacket.class, packet -> {
System.arraycopy(packet.items, 0, state.inventory.writeItems(), 0, packet.items.length);
state.enemies = packet.enemies; state.enemies = packet.enemies;
state.wavetime = packet.countdown; state.wavetime = packet.countdown;
state.wave = packet.wave; state.wave = packet.wave;
@@ -178,7 +175,7 @@ public class NetClient extends Module {
Net.handleClient(BreakPacket.class, (packet) -> { Net.handleClient(BreakPacket.class, (packet) -> {
Player placer = playerGroup.getByID(packet.playerid); Player placer = playerGroup.getByID(packet.playerid);
Placement.breakBlock(placer.team, packet.x, packet.y, true, Timers.get("breakblocksound", 10)); Build.breakBlock(placer.team, packet.x, packet.y, true, Timers.get("breakblocksound", 10));
}); });
Net.handleClient(EntitySpawnPacket.class, packet -> { Net.handleClient(EntitySpawnPacket.class, packet -> {
@@ -271,7 +268,6 @@ public class NetClient extends Module {
Net.handleClient(UpgradePacket.class, packet -> { Net.handleClient(UpgradePacket.class, packet -> {
Weapon weapon = Upgrade.getByID(packet.upgradeid); Weapon weapon = Upgrade.getByID(packet.upgradeid);
state.inventory.removeItems(UpgradeRecipes.get(weapon));
for(Player player : players) { for(Player player : players) {
player.upgrades.add(weapon); player.upgrades.add(weapon);
} }

View File

@@ -5,7 +5,6 @@ import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.TimeUtils; import com.badlogic.gdx.utils.TimeUtils;
import io.anuke.mindustry.Vars; import io.anuke.mindustry.Vars;
import io.anuke.mindustry.content.Mechs; import io.anuke.mindustry.content.Mechs;
import io.anuke.mindustry.content.UpgradeRecipes;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.BulletType; import io.anuke.mindustry.entities.BulletType;
import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Player;
@@ -21,7 +20,7 @@ import io.anuke.mindustry.resource.Recipe;
import io.anuke.mindustry.resource.Upgrade; import io.anuke.mindustry.resource.Upgrade;
import io.anuke.mindustry.resource.Weapon; import io.anuke.mindustry.resource.Weapon;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Placement; import io.anuke.mindustry.world.Build;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.BaseBulletType; import io.anuke.ucore.entities.BaseBulletType;
@@ -203,7 +202,7 @@ public class NetServer extends Module{
Recipe recipe = Recipe.getByID(packet.recipe); Recipe recipe = Recipe.getByID(packet.recipe);
Block block = recipe.result; Block block = recipe.result;
if(!Placement.validPlace(placer.team, packet.x, packet.y, block, packet.rotation)) return; if(!Build.validPlace(placer.team, packet.x, packet.y, block, packet.rotation)) return;
if(recipe == null || recipe.debugOnly != debug) return; if(recipe == null || recipe.debugOnly != debug) return;
@@ -215,8 +214,6 @@ public class NetServer extends Module{
return; return;
} }
state.inventory.removeItems(recipe.requirements);
//todo implement placing //todo implement placing
//Placement.placeBlock(placer, packet.x, packet.y, recipe, packet.rotation, true, false); //Placement.placeBlock(placer, packet.x, packet.y, recipe, packet.rotation, true, false);
@@ -233,7 +230,7 @@ public class NetServer extends Module{
Player placer = connections.get(id); Player placer = connections.get(id);
packet.playerid = placer.id; packet.playerid = placer.id;
if(!Placement.validBreak(placer.team, packet.x, packet.y)) return; if(!Build.validBreak(placer.team, packet.x, packet.y)) return;
Tile tile = world.tile(packet.x, packet.y); Tile tile = world.tile(packet.x, packet.y);
@@ -244,7 +241,7 @@ public class NetServer extends Module{
return; return;
} }
Block block = Placement.breakBlock(placer.team, packet.x, packet.y, true, false); Block block = Build.breakBlock(placer.team, packet.x, packet.y, true, false);
if(block != null) { if(block != null) {
TraceInfo trace = admins.getTraceByID(getUUID(id)); TraceInfo trace = admins.getTraceByID(getUUID(id));
@@ -283,9 +280,7 @@ public class NetServer extends Module{
Weapon weapon = Upgrade.getByID(packet.upgradeid); Weapon weapon = Upgrade.getByID(packet.upgradeid);
if(!state.inventory.hasItems(UpgradeRecipes.get(weapon))){ //todo verify upgrades with item requirements
return;
}
if (!player.upgrades.contains(weapon, true)){ if (!player.upgrades.contains(weapon, true)){
player.upgrades.add(weapon); player.upgrades.add(weapon);
@@ -293,7 +288,6 @@ public class NetServer extends Module{
return; return;
} }
state.inventory.removeItems(UpgradeRecipes.get(weapon));
Net.send(packet, SendMode.tcp); Net.send(packet, SendMode.tcp);
}); });
@@ -493,7 +487,6 @@ public class NetServer extends Module{
if(timer.get(timerStateSync, itemSyncTime)){ if(timer.get(timerStateSync, itemSyncTime)){
StateSyncPacket packet = new StateSyncPacket(); StateSyncPacket packet = new StateSyncPacket();
packet.items = state.inventory.readItems();
packet.countdown = state.wavetime; packet.countdown = state.wavetime;
packet.enemies = state.enemies; packet.enemies = state.enemies;
packet.wave = state.wave; packet.wave = state.wave;

View File

@@ -4,7 +4,6 @@ import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureWrap; import com.badlogic.gdx.graphics.Texture.TextureWrap;
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
@@ -12,7 +11,6 @@ import com.badlogic.gdx.utils.FloatArray;
import com.badlogic.gdx.utils.Pools; import com.badlogic.gdx.utils.Pools;
import io.anuke.mindustry.content.fx.Fx; import io.anuke.mindustry.content.fx.Fx;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.BlockPlacer.PlaceRequest;
import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.Unit; import io.anuke.mindustry.entities.Unit;
import io.anuke.mindustry.entities.effect.BelowLiquidEffect; import io.anuke.mindustry.entities.effect.BelowLiquidEffect;
@@ -22,14 +20,16 @@ import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Placement;
import io.anuke.ucore.core.*; import io.anuke.ucore.core.*;
import io.anuke.ucore.entities.EffectEntity; import io.anuke.ucore.entities.EffectEntity;
import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.Entity; import io.anuke.ucore.entities.Entity;
import io.anuke.ucore.entities.EntityGroup; import io.anuke.ucore.entities.EntityGroup;
import io.anuke.ucore.function.Callable; import io.anuke.ucore.function.Callable;
import io.anuke.ucore.graphics.*; import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Hue;
import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.graphics.Surface;
import io.anuke.ucore.modules.RendererModule; import io.anuke.ucore.modules.RendererModule;
import io.anuke.ucore.scene.utils.Cursors; import io.anuke.ucore.scene.utils.Cursors;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
@@ -206,13 +206,11 @@ public class Renderer extends RendererModule{
blocks.processBlocks(); blocks.processBlocks();
blocks.drawBlocks(Layer.block); blocks.drawBlocks(Layer.block);
//Graphics.surface(effectSurface, true);
Graphics.shader(Shaders.blockbuild, false); Graphics.shader(Shaders.blockbuild, false);
blocks.drawBlocks(Layer.placement); blocks.drawBlocks(Layer.placement);
Graphics.shader(); Graphics.shader();
//Graphics.flushSurface();
drawPlaceRequests(); Entities.drawWith(playerGroup, p -> true, Player::drawBuildRequests);
blocks.drawBlocks(Layer.overlay); blocks.drawBlocks(Layer.overlay);
@@ -227,35 +225,18 @@ public class Renderer extends RendererModule{
Entities.draw(airItemGroup); Entities.draw(airItemGroup);
Entities.draw(effectGroup); Entities.draw(effectGroup);
//drawShield();
overlays.draw(); overlays.draw();
if(pixelate) if(pixelate)
Graphics.flushSurface(); Graphics.flushSurface();
if(showPaths) drawDebug(); if(showPaths) drawDebug();
drawPlayerNames();
Entities.drawWith(playerGroup, p -> !p.isLocal && !p.isDead(), Player::drawName);
batch.end(); batch.end();
} }
private void drawPlaceRequests(){
Draw.color("accent");
for(Player player : playerGroup.all()) {
for (PlaceRequest request : player.getPlaceQueue()) {
if(Placement.validPlace(player.team, request.x, request.y, request.recipe.result, request.rotation)){
Lines.poly(request.x * tilesize + request.recipe.result.getPlaceOffset().x,
request.y * tilesize + request.recipe.result.getPlaceOffset().y,
4, request.recipe.result.size * tilesize /2f + Mathf.absin(Timers.time(), 3f, 1f));
}
}
}
Draw.color();
}
private void drawAllTeams(boolean flying){ private void drawAllTeams(boolean flying){
for(Team team : Team.values()){ for(Team team : Team.values()){
EntityGroup<BaseUnit> group = unitGroups[team.ordinal()]; EntityGroup<BaseUnit> group = unitGroups[team.ordinal()];
@@ -351,31 +332,6 @@ public class Renderer extends RendererModule{
Draw.color(); Draw.color();
} }
void drawPlayerNames(){
GlyphLayout layout = Pools.obtain(GlyphLayout.class);
Draw.tscl(0.25f/2);
for(Player player : playerGroup.all()){
if(!player.isLocal && !player.isDead()){
layout.setText(Core.font, player.name);
Draw.color(0f, 0f, 0f, 0.3f);
Draw.rect("blank", player.getDrawPosition().x, player.getDrawPosition().y + 8 - layout.height/2, layout.width + 2, layout.height + 2);
Draw.color();
Draw.tcolor(player.getColor());
Draw.text(player.name, player.getDrawPosition().x, player.getDrawPosition().y + 8);
if(player.isAdmin){
Draw.color(player.getColor());
float s = 3f;
Draw.rect("icon-admin-small", player.getDrawPosition().x + layout.width/2f + 2 + 1, player.getDrawPosition().y + 7f, s, s);
}
Draw.reset();
}
}
Pools.free(layout);
Draw.tscl(fontscale);
}
void drawShield(){ void drawShield(){
if(shieldGroup.size() == 0 && shieldDraws.size == 0) return; if(shieldGroup.size() == 0 && shieldDraws.size == 0) return;

View File

@@ -0,0 +1,154 @@
package io.anuke.mindustry.entities;
import com.badlogic.gdx.utils.Queue;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.resource.Recipe;
import io.anuke.mindustry.world.Build;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.types.BuildBlock;
import io.anuke.mindustry.world.blocks.types.BuildBlock.BuildEntity;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Fill;
import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.Angles;
import io.anuke.ucore.util.Geometry;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Translator;
import java.util.Arrays;
import static io.anuke.mindustry.Vars.world;
/**Interface for units that build thing.*/
public interface BlockBuilder {
//temporary static final values
Translator[] tmptr = {new Translator(), new Translator(), new Translator(), new Translator()};
float placeDistance = 80f;
/**Returns the queue for storing build requests.*/
Queue<BuildRequest> getPlaceQueue();
/**Clears the placement queue.*/
default void clearBuilding(){
getPlaceQueue().clear();
}
/**Add another build requests to the tail of the queue.*/
default void addBuildRequest(BuildRequest place){
getPlaceQueue().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();
}
/**Update building mechanism for this unit.*/
default void updateBuilding(Unit unit){
BuildRequest current = getCurrentRequest();
if(current == null) return; //nothing to do here
Tile tile = world.tile(current.x, current.y);
if(unit.distanceTo(tile) > placeDistance) { //out of range, skip it.
getPlaceQueue().removeFirst();
}else if(current.remove){
if(Build.validBreak(unit.team, current.x, current.y)){ //if it's valid, break it
current.removeProgress += 1f / tile.getBreakTime();
if(current.removeProgress >= 1f){
Build.breakBlock(unit.team, current.x, current.y, true, true);
}
}else{
//otherwise, skip it
getPlaceQueue().removeFirst();
}
}else{
if (!(tile.block() instanceof BuildBlock)) { //check if haven't started placing
if(Build.validPlace(unit.team, current.x, current.y, current.recipe.result, current.rotation)){
//if it's valid, place it
Build.placeBlock(unit.team, current.x, current.y, current.recipe, current.rotation);
}else{
//otherwise, skip it
getPlaceQueue().removeFirst();
}
}else{
//otherwise, update it.
BuildEntity entity = tile.entity();
entity.progress += 1f / entity.recipe.cost;
unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(entity), 0.4f);
}
}
}
/**Draw placement effects for an entity.*/
default void drawBuilding(Unit unit){
Tile tile = world.tile(getCurrentRequest().x, getCurrentRequest().y);
Draw.color(unit.distanceTo(tile) > placeDistance ? "placeInvalid" : "accent");
float focusLen = 3.8f + Mathf.absin(Timers.time(), 1.1f, 0.6f);
float px = unit.x + Angles.trnsx(unit.rotation, focusLen);
float py = unit.y + Angles.trnsy(unit.rotation, focusLen);
float sz = Vars.tilesize*tile.block().size/2f;
float ang = unit.angleTo(tile);
tmptr[0].set(tile.drawx() - sz, tile.drawy() - sz);
tmptr[1].set(tile.drawx() + sz, tile.drawy() - sz);
tmptr[2].set(tile.drawx() - sz, tile.drawy() + sz);
tmptr[3].set(tile.drawx() + sz, tile.drawy() + sz);
Arrays.sort(tmptr, (a, b) -> -Float.compare(Angles.angleDist(Angles.angle(unit.x, unit.y, a.x, a.y), ang),
Angles.angleDist(Angles.angle(unit.x, unit.y, b.x, b.y), ang)));
float x1 = tmptr[0].x, y1 = tmptr[0].y,
x3 = tmptr[1].x, y3 = tmptr[1].y;
Translator close = Geometry.findClosest(unit.x, unit.y, tmptr);
float x2 = close.x, y2 = close.y;
Draw.alpha(0.3f + Mathf.absin(Timers.time(), 0.9f, 0.2f));
Fill.tri(px, py, x2, y2, x1, y1);
Fill.tri(px, py, x2, y2, x3, y3);
Draw.alpha(1f);
Lines.line(px, py, x1, y1);
Lines.line(px, py, x3, y3);
Fill.circle(px, py, 1.5f + Mathf.absin(Timers.time(), 1f, 1.8f));
Draw.color();
}
/**Class for storing build requests. Can be either a place or remove request.*/
class BuildRequest {
public final int x, y, rotation;
public final Recipe recipe;
public final boolean remove;
float removeProgress;
/**This creates a build request.*/
public BuildRequest(int x, int y, int rotation, Recipe recipe) {
this.x = x;
this.y = y;
this.rotation = rotation;
this.recipe = recipe;
this.remove = false;
}
/**This creates a remove request.*/
public BuildRequest(int x, int y) {
this.x = x;
this.y = y;
this.rotation = -1;
this.recipe = null;
this.remove = true;
}
}
}

View File

@@ -1,21 +0,0 @@
package io.anuke.mindustry.entities;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.resource.Recipe;
public interface BlockPlacer {
void addPlaceBlock(PlaceRequest place);
Team getTeam();
class PlaceRequest{
public final int x, y, rotation;
public final Recipe recipe;
public PlaceRequest(int x, int y, int rotation, Recipe recipe) {
this.x = x;
this.y = y;
this.rotation = rotation;
this.recipe = recipe;
}
}
}

View File

@@ -10,6 +10,8 @@ import io.anuke.ucore.function.Callable;
import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
/**This class should not be used anymore, as the animation does not fit the style well.*/
@Deprecated
public class ItemAnimationEffect extends TimedEntity { public class ItemAnimationEffect extends TimedEntity {
private static final float size = 5f; private static final float size = 5f;

View File

@@ -1,10 +1,11 @@
package io.anuke.mindustry.entities; package io.anuke.mindustry.entities;
import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Pools;
import com.badlogic.gdx.utils.Queue; import com.badlogic.gdx.utils.Queue;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.content.Mechs; import io.anuke.mindustry.content.Mechs;
import io.anuke.mindustry.content.Weapons; import io.anuke.mindustry.content.Weapons;
import io.anuke.mindustry.content.fx.ExplosionFx; import io.anuke.mindustry.content.fx.ExplosionFx;
@@ -14,18 +15,11 @@ import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.NetEvents; import io.anuke.mindustry.net.NetEvents;
import io.anuke.mindustry.resource.*; import io.anuke.mindustry.resource.*;
import io.anuke.mindustry.world.Placement;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.types.BuildBlock;
import io.anuke.mindustry.world.blocks.types.BuildBlock.BuildEntity;
import io.anuke.mindustry.world.blocks.types.Floor; import io.anuke.mindustry.world.blocks.types.Floor;
import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.*;
import io.anuke.ucore.core.Inputs;
import io.anuke.ucore.core.Settings;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.SolidEntity; import io.anuke.ucore.entities.SolidEntity;
import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Fill;
import io.anuke.ucore.graphics.Lines; import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.*; import io.anuke.ucore.util.*;
@@ -33,17 +27,13 @@ import java.io.DataInputStream;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Arrays;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;
public class Player extends Unit implements BlockPlacer{ public class Player extends Unit implements BlockBuilder {
static final float speed = 1.1f; private static final float speed = 1.1f;
static final float dashSpeed = 1.8f; private static final float dashSpeed = 1.8f;
public static final float placeDistance = 80f; private static final Vector2 movement = new Vector2();
static final int timerRegen = 3;
static final Translator[] tmptr = {new Translator(), new Translator(), new Translator(), new Translator()};
public String name = "name"; public String name = "name";
public String uuid; public String uuid;
@@ -61,12 +51,10 @@ public class Player extends Unit implements BlockPlacer{
public int playerIndex = 0; public int playerIndex = 0;
public boolean isLocal = false; public boolean isLocal = false;
public Timer timer = new Timer(4); public Timer timer = new Timer(4);
public float walktime;
public float respawntime;
private Queue<PlaceRequest> placeQueue = new Queue<>(); private float walktime;
private Tile currentPlace; private float respawntime;
private Vector2 movement = new Vector2(); private Queue<BuildRequest> placeQueue = new Queue<>();
public Player(){ public Player(){
hitbox.setSize(5); hitbox.setSize(5);
@@ -110,11 +98,6 @@ public class Player extends Unit implements BlockPlacer{
} }
} }
@Override
public void addPlaceBlock(PlaceRequest req){
placeQueue.addFirst(req);
}
@Override @Override
public boolean collides(SolidEntity other){ public boolean collides(SolidEntity other){
return !isDead() && super.collides(other) && !mech.flying; return !isDead() && super.collides(other) && !mech.flying;
@@ -227,45 +210,49 @@ public class Player extends Unit implements BlockPlacer{
@Override @Override
public void drawOver(){ public void drawOver(){
if(!isShooting() && currentPlace != null) { if(!isShooting() && getCurrentRequest() != null) {
Draw.color(distanceTo(currentPlace) > placeDistance ? "placeInvalid" : "accent"); drawBuilding(this);
float focusLen = 3.8f + Mathf.absin(Timers.time(), 1.1f, 0.6f);
float px = x + Angles.trnsx(rotation, focusLen);
float py = y + Angles.trnsy(rotation, focusLen);
Tile tile = currentPlace;
float sz = Vars.tilesize*tile.block().size/2f;
float ang = angleTo(tile);
tmptr[0].set(tile.drawx() - sz, tile.drawy() - sz);
tmptr[1].set(tile.drawx() + sz, tile.drawy() - sz);
tmptr[2].set(tile.drawx() - sz, tile.drawy() + sz);
tmptr[3].set(tile.drawx() + sz, tile.drawy() + sz);
Arrays.sort(tmptr, (a, b) -> -Float.compare(Angles.angleDist(Angles.angle(x, y, a.x, a.y), ang),
Angles.angleDist(Angles.angle(x, y, b.x, b.y), ang)));
float x1 = tmptr[0].x, y1 = tmptr[0].y,
x3 = tmptr[1].x, y3 = tmptr[1].y;
Translator close = Geometry.findClosest(x, y, tmptr);
float x2 = close.x, y2 = close.y;
Draw.alpha(0.3f + Mathf.absin(Timers.time(), 0.9f, 0.2f));
Fill.tri(px, py, x2, y2, x1, y1);
Fill.tri(px, py, x2, y2, x3, y3);
Draw.alpha(1f);
Lines.line(px, py, x1, y1);
Lines.line(px, py, x3, y3);
Fill.circle(px, py, 1.5f + Mathf.absin(Timers.time(), 1f, 1.8f));
Draw.color();
} }
} }
public void drawName(){
GlyphLayout layout = Pools.obtain(GlyphLayout.class);
Draw.tscl(0.25f/2);
layout.setText(Core.font, name);
Draw.color(0f, 0f, 0f, 0.3f);
Draw.rect("blank", getDrawPosition().x, getDrawPosition().y + 8 - layout.height/2, layout.width + 2, layout.height + 2);
Draw.color();
Draw.tcolor(color);
Draw.text(name, getDrawPosition().x, getDrawPosition().y + 8);
if(isAdmin){
Draw.color(color);
float s = 3f;
Draw.rect("icon-admin-small", getDrawPosition().x + layout.width/2f + 2 + 1, getDrawPosition().y + 7f, s, s);
}
Draw.reset();
Pools.free(layout);
Draw.tscl(fontscale);
}
public void drawBuildRequests(){
for (BuildRequest request : getPlaceQueue()) {
if(request.remove){
Draw.color("placeInvalid");
Tile tile = world.tile(request.x, request.y);
Lines.poly(tile.drawx(), tile.drawy(),
4, tile.block().size * tilesize /2f + Mathf.absin(Timers.time(), 3f, 1f));
}else{
Draw.color("accent");
Lines.poly(request.x * tilesize + request.recipe.result.getPlaceOffset().x,
request.y * tilesize + request.recipe.result.getPlaceOffset().y,
4, request.recipe.result.size * tilesize /2f + Mathf.absin(Timers.time(), 3f, 1f));
}
}
}
@Override @Override
public void update(){ public void update(){
@@ -300,6 +287,7 @@ public class Player extends Unit implements BlockPlacer{
y = Mathf.clamp(y, 0, world.height() * tilesize); y = Mathf.clamp(y, 0, world.height() * tilesize);
} }
/**Resets all values of the player.*/
public void reset(){ public void reset(){
weapon = Weapons.blaster; weapon = Weapons.blaster;
team = Team.blue; team = Team.blue;
@@ -316,12 +304,11 @@ public class Player extends Unit implements BlockPlacer{
return control.input(playerIndex).canShoot() && control.input(playerIndex).isShooting() && inventory.hasAmmo(); return control.input(playerIndex).canShoot() && control.input(playerIndex).isShooting() && inventory.hasAmmo();
} }
public Queue<PlaceRequest> getPlaceQueue(){ public Queue<BuildRequest> getPlaceQueue(){
return placeQueue; return placeQueue;
} }
protected void updateMech(){ protected void updateMech(){
Tile tile = world.tileWorld(x, y); Tile tile = world.tileWorld(x, y);
//if player is in solid block //if player is in solid block
@@ -330,29 +317,7 @@ public class Player extends Unit implements BlockPlacer{
} }
if(!isShooting()) { if(!isShooting()) {
//update placing queue updateBuilding(this);
if(currentPlace != null) {
Tile check = currentPlace;
if (!(check.block() instanceof BuildBlock)) {
currentPlace = null;
}else if(distanceTo(check) <= placeDistance){
BuildEntity entity = check.entity();
entity.progress += 1f / entity.recipe.cost;
rotation = Mathf.slerpDelta(rotation, angleTo(entity), 0.4f);
}
}else if(placeQueue.size > 0){
PlaceRequest check = placeQueue.last();
if(distanceTo(world.tile(check.x, check.y)) <= placeDistance &&
Placement.validPlace(team, check.x, check.y, check.recipe.result, check.rotation)){
placeQueue.removeLast();
Placement.placeBlock(team, check.x, check.y, check.recipe, check.rotation, true, true);
currentPlace = world.tile(check.x, check.y);
}
}
} }
if(ui.chatfrag.chatOpen()) return; if(ui.chatfrag.chatOpen()) return;
@@ -365,11 +330,6 @@ public class Player extends Unit implements BlockPlacer{
speed *= ((1f-carrySlowdown) + (inventory.hasItem() ? (float)inventory.getItem().amount/inventory.capacity(): 1f) * carrySlowdown); speed *= ((1f-carrySlowdown) + (inventory.hasItem() ? (float)inventory.getItem().amount/inventory.capacity(): 1f) * carrySlowdown);
if(health < maxhealth && timer.get(timerRegen, 20))
health ++;
health = Mathf.clamp(health, -1, maxhealth);
movement.set(0, 0); movement.set(0, 0);
String section = "player_" + (playerIndex + 1); String section = "player_" + (playerIndex + 1);
@@ -524,18 +484,4 @@ public class Player extends Unit implements BlockPlacer{
interpolator.read(this.x, this.y, x, y, rot, baseRot, time); interpolator.read(this.x, this.y, x, y, rot, baseRot, time);
} }
@Override
public void interpolate() {
super.interpolate();
Interpolator i = interpolator;
float tx = x + Angles.trnsx(rotation + 180f, 4f);
float ty = y + Angles.trnsy(rotation + 180f, 4f);
}
public Color getColor(){
return color;
}
} }

View File

@@ -3,12 +3,13 @@ package io.anuke.mindustry.entities;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
import io.anuke.ucore.util.Mathf; import io.anuke.ucore.util.Mathf;
/**Class for predicting shoot angles based on velocities of targets.*/
public class Predict { public class Predict {
private static Vector2 vec = new Vector2(); private static Vector2 vec = new Vector2();
private static Vector2 vresult = new Vector2(); private static Vector2 vresult = new Vector2();
/**Returns resulting predicted vector. /**Returns resulting predicted vector.
* Don't call from multiple threads, ever.*/ * Don't call from multiple threads.*/
public static Vector2 intercept(float srcx, float srcy, float dstx, float dsty, float dstvx, float dstvy, float v) { public static Vector2 intercept(float srcx, float srcy, float dstx, float dsty, float dstvx, float dstvy, float v) {
float tx = dstx - srcx, float tx = dstx - srcx,
ty = dsty - srcy, ty = dsty - srcy,
@@ -37,7 +38,6 @@ public class Predict {
return sol; return sol;
} }
private static Vector2 quad(float a, float b, float c) { private static Vector2 quad(float a, float b, float c) {
Vector2 sol = null; Vector2 sol = null;
if (Math.abs(a) < 1e-6) { if (Math.abs(a) < 1e-6) {

View File

@@ -3,6 +3,7 @@ package io.anuke.mindustry.entities;
import io.anuke.mindustry.content.StatusEffects; import io.anuke.mindustry.content.StatusEffects;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
/**Class for controlling status effects on an entity.*/
public class StatusController { public class StatusController {
private static final TransitionResult globalResult = new TransitionResult(); private static final TransitionResult globalResult = new TransitionResult();

View File

@@ -1,578 +0,0 @@
package io.anuke.mindustry.game;
import com.badlogic.gdx.math.GridPoint2;
import io.anuke.mindustry.content.Items;
import io.anuke.mindustry.content.blocks.Blocks;
import io.anuke.mindustry.content.blocks.DistributionBlocks;
import io.anuke.mindustry.content.blocks.WeaponBlocks;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.world.Block;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.scene.builders.button;
import io.anuke.ucore.scene.builders.label;
import io.anuke.ucore.scene.builders.table;
import io.anuke.ucore.scene.ui.ImageButton;
import io.anuke.ucore.scene.ui.Label;
import io.anuke.ucore.scene.ui.TextButton;
import io.anuke.ucore.util.Bundles;
import io.anuke.ucore.util.Tmp;
import static io.anuke.mindustry.Vars.*;
public class Tutorial{
private Stage stage;
private Label info;
private TextButton next, prev;
public Tutorial(){
reset();
}
public boolean active(){
return world.getMap() != null && world.getMap().name.equals("tutorial") && !state.is(State.menu);
}
public void buildUI(table table){
table.atop();
new table("pane"){{
atop();
margin(12);
info = new label(()->stage.text).pad(10f).padBottom(5f).width(340f).colspan(2).get();
info.setWrap(true);
row();
prev = new button("$text.tutorial.back", ()->{
if(!prev.isDisabled())
move(false);
}).left().get();
next = new button("$text.tutorial.next", ()->{
if(!next.isDisabled())
move(true);
}).right().get();
}}.end();
prev.margin(16);
next.margin(16);
prev.setDisabled(()->!canMove(false) || !stage.canBack);
next.setDisabled(()->!stage.canForward);
}
public void update(){
stage.update(this);
//info.setText(stage.text);
if(stage.showBlock){
/*
Tile tile = world.tile(world.getCore().x + stage.blockPlaceX, world.getCore().y + stage.blockPlaceY);
if(tile.block() == stage.targetBlock && (tile.getRotation() == stage.blockRotation || stage.blockRotation == -1)){
move(true);
}*/
}
}
public void reset(){
stage = Stage.values()[0];
stage.onSwitch();
}
public void complete(){
//new TextDialog("Congratulations!", "You have completed the tutorial!").padText(Unit.dp.inPixels(10f)).show();
state.set(State.menu);
reset();
}
void move(boolean forward){
//TODO
}
boolean canMove(boolean forward){
return true;
}
public boolean showTarget(){
return stage == Stage.shoot;
}
public boolean canPlace(){
return stage.canPlace;
}
public boolean showBlock(){
return stage.showBlock;
}
public Block getPlaceBlock(){
return stage.targetBlock;
}
public GridPoint2 getPlacePoint(){
return Tmp.g1.set(stage.blockPlaceX, stage.blockPlaceY);
}
public int getPlaceRotation(){
return stage.blockRotation;
}
public void setDefaultBlocks(int corex, int corey){
world.tile(corex, corey - 2).setBlock(Blocks.air);
world.tile(corex, corey - 3).setBlock(Blocks.air);
world.tile(corex, corey - 3).setFloor(Blocks.stone);
world.tile(corex + 1, corey - 8).setFloor(Blocks.iron);
world.tile(corex - 1, corey - 8).setFloor(Blocks.coal);
int r = 10;
for(int x = -r; x <= r; x ++){
for(int y = -r; y <= r; y ++){
if(world.tile(corex + x, corey + y).block() == Blocks.rock){
world.tile(corex + x, corey + y).setBlock(Blocks.air);
}
}
}
}
public enum Stage{
intro{
{
}
},
moveDesktop{
{
desktopOnly = true;
}
},
shoot{
{
desktopOnly = true;
}
},
moveAndroid{
{
androidOnly = true;
}
},
placeSelect{
{
canBack = false;
canPlace = true;
}
void onSwitch(){
ui.<ImageButton>find("sectionbuttondistribution").fireClick();
}
},
placeConveyorDesktop{
{
desktopOnly = true;
canPlace = true;
showBlock = true;
canForward = false;
blockRotation = 1;
blockPlaceX = 0;
blockPlaceY = -2;
targetBlock = DistributionBlocks.conveyor;
}
},
placeConveyorAndroid{
{
androidOnly = true;
canPlace = true;
showBlock = true;
canForward = false;
blockRotation = 1;
blockPlaceX = 0;
blockPlaceY = -2;
targetBlock = DistributionBlocks.conveyor;
}
},
placeConveyorAndroidInfo{
{
androidOnly = true;
canBack = false;
}
void onSwitch(){
//player.recipe = null;
}
},
placeDrill{
{
canPlace = true;
canBack = false;
showBlock = true;
canForward = false;
blockPlaceX = 0;
blockPlaceY = -3;
//targetBlock = ProductionBlocks.stonedrill;
}
void onSwitch(){
ui.<ImageButton>find("sectionbuttonproduction").fireClick();
}
},
blockInfo{
{
canBack = true;
}
},
deselectDesktop{
{
desktopOnly = true;
canBack = false;
}
},
deselectAndroid{
{
androidOnly = true;
canBack = false;
}
},
drillPlaced{
{
canBack = false;
}
void onSwitch(){
}
},
drillInfo{
{
}
},
drillPlaced2{
{
}
},
moreDrills{
{
canBack = false;
}
void onSwitch(){
/*
for(int flip : new int[]{1, -1}){
world.tile(world.getCore().x + flip, world.getCore().y - 2).setBlock(DistributionBlocks.conveyor, 2 * flip);
world.tile(world.getCore().x + flip*2, world.getCore().y - 2).setBlock(DistributionBlocks.conveyor, 2 * flip);
world.tile(world.getCore().x + flip*2, world.getCore().y - 3).setBlock(DistributionBlocks.conveyor, 2 * flip);
world.tile(world.getCore().x + flip*2, world.getCore().y - 3).setBlock(DistributionBlocks.conveyor, 1);
world.tile(world.getCore().x + flip*2, world.getCore().y - 4).setFloor(Blocks.stone);
world.tile(world.getCore().x + flip*2, world.getCore().y - 4).setBlock(ProductionBlocks.stonedrill);
}*/
}
},
deleteBlock{
{
canBack = false;
canForward = false;
showBlock = true;
targetBlock = Blocks.air;
blockPlaceX = 2;
blockPlaceY = -2;
desktopOnly = true;
}
},
deleteBlockAndroid{
{
canBack = false;
canForward = false;
showBlock = true;
targetBlock = Blocks.air;
blockPlaceX = 2;
blockPlaceY = -2;
androidOnly = true;
}
},
placeTurret{
{
canBack = false;
canForward = false;
showBlock = true;
canPlace = true;
targetBlock = WeaponBlocks.doubleturret;
blockPlaceX = 2;
blockPlaceY = 2;
}
void onSwitch(){
ui.<ImageButton>find("sectionbuttonweapon").fireClick();
}
},
placedTurretAmmo{
{
canBack = false;
}
void onSwitch(){
for(int i = 0; i < 4; i ++){
//world.tile(world.getCore().x + 2, world.getCore().y - 2 + i).setBlock(DistributionBlocks.conveyor, 1);
}
}
},
turretExplanation{
{
canBack = false;
}
},
waves{
{
}
},
coreDestruction{
{
}
},
pausingDesktop{
{
desktopOnly = true;
}
},
pausingAndroid{
{
androidOnly = true;
}
},
//TODO re-add tutorial on weapons
spawnWave{
float warmup = 0f;
{
canBack = false;
canForward = false;
}
void update(Tutorial t){
warmup += Timers.delta();
if(state.enemies == 0 && warmup > 60f){
t.move(true);
}
}
void onSwitch(){
warmup = 0f;
logic.runWave();
}
},
pumpDesc{
{
canBack = false;
}
},
pumpPlace{
{
canBack = false;
canForward = false;
showBlock = true;
canPlace = true;
//targetBlock = ProductionBlocks.pump;
blockPlaceX = 6;
blockPlaceY = -2;
}
void onSwitch(){
ui.<ImageButton>find("sectionbuttonproduction").fireClick();
state.inventory.addItem(Items.steel, 60);
state.inventory.addItem(Items.iron, 60);
}
},
conduitUse{
{
canBack = false;
canForward = false;
showBlock = true;
canPlace = true;
//targetBlock = DistributionBlocks.conduit;
blockPlaceX = 5;
blockPlaceY = -2;
blockRotation = 2;
}
void onSwitch(){
ui.<ImageButton>find("sectionbuttondistribution").fireClick();
//world.tile(blockPlaceX + world.getCore().x, blockPlaceY + world.getCore().y).setBlock(Blocks.air);
}
},
conduitUse2{
{
canBack = false;
canForward = false;
showBlock = true;
canPlace = true;
//targetBlock = DistributionBlocks.conduit;
//blockPlaceX = 4;
blockPlaceY = -2;
blockRotation = 1;
}
void onSwitch(){
//world.tile(blockPlaceX + world.getCore().x, blockPlaceY + world.getCore().y).setBlock(Blocks.air);
}
},
conduitUse3{
{
canBack = false;
canForward = false;
showBlock = true;
canPlace = true;
//targetBlock = DistributionBlocks.conduit;
blockPlaceX = 4;
blockPlaceY = -1;
blockRotation = 1;
}
void onSwitch(){
//world.tile(blockPlaceX + world.getCore().x, blockPlaceY + world.getCore().y).setBlock(Blocks.air);
}
},
generator{
{
canBack = false;
canForward = false;
showBlock = true;
canPlace = true;
//targetBlock = ProductionBlocks.combustiongenerator;
blockPlaceX = 4;
blockPlaceY = 0;
}
void onSwitch(){
//world.tile(blockPlaceX + world.getCore().x, blockPlaceY + world.getCore().y).setBlock(Blocks.air);
ui.<ImageButton>find("sectionbuttonpower").fireClick();
state.inventory.addItem(Items.steel, 60);
state.inventory.addItem(Items.iron, 60);
}
},
generatorExplain{
{
canBack = false;
}
},
lasers{
{
canBack = false;
canForward = false;
showBlock = true;
canPlace = true;
blockPlaceX = 4;
blockPlaceY = 4;
blockRotation = 2;
//targetBlock = DistributionBlocks.powerlaser;
}
void onSwitch(){
ui.<ImageButton>find("sectionbuttonpower").fireClick();
}
},
laserExplain{
{
canBack = false;
}
},
laserMore{
{
canBack = false;
}
},
healingTurret{
{
canBack = false;
canForward = false;
showBlock = true;
canPlace = true;
canBack = false;
blockPlaceX = 1;
blockPlaceY = 4;
//targetBlock = DefenseBlocks.repairturret;
}
void onSwitch(){
ui.<ImageButton>find("sectionbuttonpower").fireClick();
}
},
healingTurretExplain{
{
canBack = false;
}
},
smeltery{
{
canBack = false;
canForward = false;
showBlock = true;
canPlace = true;
canBack = false;
blockPlaceX = 0;
blockPlaceY = -7;
//targetBlock = ProductionBlocks.smelter;
}
void onSwitch(){
state.inventory.addItem(Items.stone, 40);
state.inventory.addItem(Items.iron, 40);
ui.<ImageButton>find("sectionbuttoncrafting").fireClick();
}
},
smelterySetup{
{
canBack = false;
}
void onSwitch(){
/*
for(int i = 0; i < 5; i ++){
world.tile(world.getCore().x, world.getCore().y - 6 + i).setBlock(DistributionBlocks.conveyor, 1);
}
world.tile(world.getCore().x, world.getCore().y - 6 + 1).setBlock(DistributionBlocks.tunnel, 3);
world.tile(world.getCore().x, world.getCore().y - 6 + 2).setBlock(DefenseBlocks.stonewall, 0);
world.tile(world.getCore().x, world.getCore().y - 6 + 3).setBlock(DistributionBlocks.tunnel, 1);
world.tile(world.getCore().x+1, world.getCore().y - 8).setBlock(ProductionBlocks.irondrill);
world.tile(world.getCore().x-1, world.getCore().y - 8).setBlock(ProductionBlocks.coaldrill);
world.tile(world.getCore().x+1, world.getCore().y - 7).setBlock(DistributionBlocks.conveyor, 2);
world.tile(world.getCore().x-1, world.getCore().y - 7).setBlock(DistributionBlocks.conveyor, 0);*/
}
},
tunnelExplain{
{
canBack = false;
}
},
end{
{
canBack = false;
}
};
public final String text = Bundles.getNotNull("tutorial."+name()+".text");
boolean androidOnly;
boolean desktopOnly;
boolean canBack = true;
boolean canForward = true;
boolean canPlace = false;
boolean showBlock = false;
int blockPlaceX = 0;
int blockPlaceY = 0;
int blockRotation = -1;
Block targetBlock = null;
void update(Tutorial t){};
void onSwitch(){}
}
}

View File

@@ -45,7 +45,7 @@ public class OverlayRenderer {
int tiley = input.getBlockY(); int tiley = input.getBlockY();
//draw placement box //draw placement box
if ((input.recipe != null && state.inventory.hasItems(input.recipe.requirements) && (!ui.hasMouse() || mobile) if ((input.recipe != null && (!ui.hasMouse() || mobile)
&& input.drawPlace())) { && input.drawPlace())) {
input.placeMode.draw(input, input.getBlockX(), input.placeMode.draw(input, input.getBlockX(),
@@ -55,7 +55,7 @@ public class OverlayRenderer {
input.breakMode.draw(input, tilex, tiley, 0, 0); input.breakMode.draw(input, tilex, tiley, 0, 0);
} else if (input.breakMode.delete && input.drawPlace() } else if (input.breakMode.delete && input.drawPlace()
&& (input.recipe == null || !state.inventory.hasItems(input.recipe.requirements)) && (input.recipe == null)
&& (input.placeMode.delete || input.breakMode.both || !mobile)) { && (input.placeMode.delete || input.breakMode.both || !mobile)) {
if (input.breakMode == PlaceMode.holdDelete) if (input.breakMode == PlaceMode.holdDelete)

View File

@@ -7,7 +7,6 @@ import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.NetEvents; import io.anuke.mindustry.net.NetEvents;
import io.anuke.mindustry.resource.ItemStack;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Graphics; import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.core.Inputs; import io.anuke.ucore.core.Inputs;
@@ -98,28 +97,12 @@ public class AndroidInput extends InputHandler{
mousex = Gdx.graphics.getWidth()/2; mousex = Gdx.graphics.getWidth()/2;
mousey = Gdx.graphics.getHeight()/2; mousey = Gdx.graphics.getHeight()/2;
} }
@Override
public boolean cursorNear(){
return true;
}
public Tile selected(){ public Tile selected(){
Vector2 vec = Graphics.world(mousex, mousey); Vector2 vec = Graphics.world(mousex, mousey);
return world.tile(Mathf.scl2(vec.x, tilesize), Mathf.scl2(vec.y, tilesize)); return world.tile(Mathf.scl2(vec.x, tilesize), Mathf.scl2(vec.y, tilesize));
} }
public void breakBlock(){
Tile tile = selected();
breaktime += Timers.delta();
if(breaktime >= tile.block().breaktime){
brokeBlock = true;
breakBlock(tile.x, tile.y, true);
breaktime = 0f;
}
}
@Override @Override
public void update(){ public void update(){
enableHold = breakMode == PlaceMode.holdDelete; enableHold = breakMode == PlaceMode.holdDelete;
@@ -150,15 +133,6 @@ public class AndroidInput extends InputHandler{
if(sel == null) if(sel == null)
return; return;
if(warmup > warmupDelay && validBreak(sel.x, sel.y)){
breaktime += Timers.delta();
if(breaktime > selected().block().breaktime){
breakBlock();
breaktime = 0;
}
}
mousex = lx; mousex = lx;
mousey = ly; mousey = ly;
}else{ }else{
@@ -169,23 +143,6 @@ public class AndroidInput extends InputHandler{
mousey = Mathf.clamp(mousey, 0, Gdx.graphics.getHeight()); mousey = Mathf.clamp(mousey, 0, Gdx.graphics.getHeight());
} }
} }
@Override
public boolean tryPlaceBlock(int x, int y, boolean sound){
if(recipe != null &&
validPlace(x, y, recipe.result) && cursorNear() &&
state.inventory.hasItems(recipe.requirements)){
placeBlock(x, y, recipe, rotation, true, sound);
for(ItemStack stack : recipe.requirements){
state.inventory.removeItem(stack);
}
return true;
}
return false;
}
public boolean breaking(){ public boolean breaking(){
return recipe == null; return recipe == null;

View File

@@ -21,7 +21,6 @@ public class DesktopInput extends InputHandler{
float mousex, mousey; float mousex, mousey;
float endx, endy; float endx, endy;
private float controlx, controly; private float controlx, controly;
private boolean enableHold = false;
private boolean beganBreak; private boolean beganBreak;
private boolean controlling; private boolean controlling;
private final int index; private final int index;
@@ -178,17 +177,6 @@ public class DesktopInput extends InputHandler{
recipe = null; recipe = null;
} }
//block breaking
if(enableHold && Inputs.keyDown(section,"break") && cursor != null && validBreak(tilex(), tiley())){
breaktime += Timers.delta();
if(breaktime >= cursor.getBreakTime()){
breakBlock(cursor.x, cursor.y, true);
breaktime = 0f;
}
}else{
breaktime = 0f;
}
if(recipe != null){ if(recipe != null){
showCursor = validPlace(tilex(), tiley(), recipe.result) && cursorNear(); showCursor = validPlace(tilex(), tiley(), recipe.result) && cursorNear();
} }

View File

@@ -47,7 +47,7 @@ public class GestureHandler extends GestureAdapter{
if(input.isCursorVisible() && !Inputs.keyDown("select")) return false; if(input.isCursorVisible() && !Inputs.keyDown("select")) return false;
if(!input.isCursorVisible() && !(input.recipe != null if(!input.isCursorVisible() && !(input.recipe != null
&& input.placeMode.lockCamera && state.inventory.hasItems(input.recipe.requirements)) && && input.placeMode.lockCamera) &&
!(input.recipe == null && input.breakMode.lockCamera)){ !(input.recipe == null && input.breakMode.lockCamera)){
float dx = deltaX*Core.camera.zoom/Core.cameraScale, dy = deltaY*Core.camera.zoom/Core.cameraScale; float dx = deltaX*Core.camera.zoom/Core.cameraScale, dy = deltaY*Core.camera.zoom/Core.cameraScale;
input.player.x -= dx; input.player.x -= dx;

View File

@@ -4,16 +4,14 @@ import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputAdapter; import com.badlogic.gdx.InputAdapter;
import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
import io.anuke.mindustry.entities.BlockPlacer.PlaceRequest; import io.anuke.mindustry.entities.BlockBuilder.BuildRequest;
import io.anuke.mindustry.entities.ItemAnimationEffect; import io.anuke.mindustry.entities.ItemAnimationEffect;
import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.NetEvents;
import io.anuke.mindustry.resource.ItemStack; import io.anuke.mindustry.resource.ItemStack;
import io.anuke.mindustry.resource.Recipe; import io.anuke.mindustry.resource.Recipe;
import io.anuke.mindustry.ui.fragments.OverlayFragment; import io.anuke.mindustry.ui.fragments.OverlayFragment;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Placement; import io.anuke.mindustry.world.Build;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Core; import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Graphics; import io.anuke.ucore.core.Graphics;
@@ -158,25 +156,20 @@ public abstract class InputHandler extends InputAdapter{
return true; return true;
} }
public boolean tryPlaceBlock(int x, int y, boolean sound){ public boolean tryPlaceBlock(int x, int y){
if(recipe != null && if(recipe != null &&
validPlace(x, y, recipe.result) && !ui.hasMouse() && cursorNear() && validPlace(x, y, recipe.result) && !ui.hasMouse() && cursorNear()){
state.inventory.hasItems(recipe.requirements)){
placeBlock(x, y, recipe, rotation, true, sound); placeBlock(x, y, recipe, rotation);
for(ItemStack stack : recipe.requirements){
state.inventory.removeItem(stack);
}
return true; return true;
} }
return false; return false;
} }
public boolean tryDeleteBlock(int x, int y, boolean sound){ public boolean tryDeleteBlock(int x, int y){
if(cursorNear() && validBreak(x, y)){ if(cursorNear() && validBreak(x, y)){
breakBlock(x, y, sound); breakBlock(x, y);
return true; return true;
} }
return false; return false;
@@ -189,7 +182,7 @@ public abstract class InputHandler extends InputAdapter{
public boolean validPlace(int x, int y, Block type){ public boolean validPlace(int x, int y, Block type){
for(Tile tile : state.teams.get(player.team).cores){ for(Tile tile : state.teams.get(player.team).cores){
if(tile.distanceTo(x * tilesize, y * tilesize) < coreBuildRange){ if(tile.distanceTo(x * tilesize, y * tilesize) < coreBuildRange){
return Placement.validPlace(player.team, x, y, type, rotation) && return Build.validPlace(player.team, x, y, type, rotation) &&
Vector2.dst(player.x, player.y, x * tilesize, y * tilesize) < Player.placeDistance; Vector2.dst(player.x, player.y, x * tilesize, y * tilesize) < Player.placeDistance;
} }
} }
@@ -198,35 +191,16 @@ public abstract class InputHandler extends InputAdapter{
} }
public boolean validBreak(int x, int y){ public boolean validBreak(int x, int y){
return Placement.validBreak(player.team, x, y); return Build.validBreak(player.team, x, y);
} }
public void placeBlock(int x, int y, Recipe recipe, int rotation, boolean effects, boolean sound){ public void placeBlock(int x, int y, Recipe recipe, int rotation){
//todo multiplayer support //todo multiplayer support
player.addPlaceBlock(new PlaceRequest(x, y, rotation, recipe)); player.addBuildRequest(new BuildRequest(x, y, rotation, recipe));
/*
if(!Net.client()){ //is server or singleplayer
threads.run(() -> Placement.placeBlock(player.team, x, y, recipe, rotation, effects, sound));
}
if(Net.active()){
NetEvents.handlePlace(player, x, y, recipe, rotation);
}
//todo fix this, call placed()
if(!Net.client()){
//Tile tile = world.tile(x, y);
//if(tile != null) threads.run(() -> result.placed(tile));
}*/
} }
public void breakBlock(int x, int y, boolean sound){ public void breakBlock(int x, int y){
if(!Net.client()){ //todo multiplayer support
threads.run(() -> Placement.breakBlock(player.team, x, y, true, sound)); player.addBuildRequest(new BuildRequest(x, y));
}
if(Net.active()){
NetEvents.handleBreak(x, y);
}
} }
} }

View File

@@ -8,7 +8,7 @@ import com.badlogic.gdx.math.Vector2;
import io.anuke.mindustry.graphics.Shaders; import io.anuke.mindustry.graphics.Shaders;
import io.anuke.mindustry.ui.fragments.ToolFragment; import io.anuke.mindustry.ui.fragments.ToolFragment;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Placement; import io.anuke.mindustry.world.Build;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Graphics; import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.core.Timers; import io.anuke.ucore.core.Timers;
@@ -55,7 +55,7 @@ public enum PlaceMode{
} }
public void tapped(InputHandler input, int tilex, int tiley){ public void tapped(InputHandler input, int tilex, int tiley){
input.tryPlaceBlock(tilex, tiley, true); input.tryPlaceBlock(tilex, tiley);
} }
}, },
touch{ touch{
@@ -67,7 +67,7 @@ public enum PlaceMode{
} }
public void tapped(InputHandler input, int x, int y){ public void tapped(InputHandler input, int x, int y){
input.tryPlaceBlock(x, y, true); input.tryPlaceBlock(x, y);
} }
}, },
none{ none{
@@ -110,7 +110,7 @@ public enum PlaceMode{
} }
public void tapped(InputHandler input, int x, int y){ public void tapped(InputHandler input, int x, int y){
input.tryDeleteBlock(x, y, true); input.tryDeleteBlock(x, y);
} }
}, },
areaDelete{ areaDelete{
@@ -172,7 +172,7 @@ public enum PlaceMode{
tilex = this.rtilex; tiley = this.rtiley; tilex = this.rtilex; tiley = this.rtiley;
endx = this.rendx; endy = this.rendy; endx = this.rendx; endy = this.rendy;
input.player.getPlaceQueue().clear(); input.player.clearBuilding();
if(mobile){ if(mobile){
ToolFragment t = input.frag.tool; ToolFragment t = input.frag.tool;
@@ -186,13 +186,10 @@ public enum PlaceMode{
} }
} }
boolean first = true;
for(int cx = tilex; cx <= endx; cx ++){ for(int cx = tilex; cx <= endx; cx ++){
for(int cy = tiley; cy <= endy; cy ++){ for(int cy = tiley; cy <= endy; cy ++){
if(input.tryDeleteBlock(cx, cy, first)){ input.tryDeleteBlock(cx, cy);
first = false;
}
} }
} }
} }
@@ -283,7 +280,7 @@ public enum PlaceMode{
int wx = tilex + px * Mathf.sign(endx - tilex), int wx = tilex + px * Mathf.sign(endx - tilex),
wy = tiley + py * Mathf.sign(endy - tiley); wy = tiley + py * Mathf.sign(endy - tiley);
if(!Placement.validPlace(input.player.team, wx, wy, block, rotation)){ if(!Build.validPlace(input.player.team, wx, wy, block, rotation)){
Draw.color("placeInvalid"); Draw.color("placeInvalid");
}else{ }else{
Draw.color("accent"); Draw.color("accent");
@@ -315,22 +312,21 @@ public enum PlaceMode{
process(input, tilex, tiley, endx, endy); process(input, tilex, tiley, endx, endy);
input.rotation = this.rotation; input.rotation = this.rotation;
input.player.getPlaceQueue().clear(); input.player.clearBuilding();
boolean first = true; boolean first = true;
for(int x = 0; x <= Math.abs(this.rendx - this.rtilex); x += input.recipe.result.size){ for(int x = 0; x <= Math.abs(this.rendx - this.rtilex); x += input.recipe.result.size){
for(int y = 0; y <= Math.abs(this.rendy - this.rtiley); y += input.recipe.result.size){ for(int y = 0; y <= Math.abs(this.rendy - this.rtiley); y += input.recipe.result.size){
if(input.tryPlaceBlock( input.tryPlaceBlock(
tilex + x * Mathf.sign(endx - tilex), tilex + x * Mathf.sign(endx - tilex),
tiley + y * Mathf.sign(endy - tiley), first)){ tiley + y * Mathf.sign(endy - tiley));
first = false;
}
} }
} }
} }
void process(InputHandler input, int tilex, int tiley, int endx, int endy){ void process(InputHandler input, int tilex, int tiley, int endx, int endy){
//todo hold shift to snap
/* /*
if(Math.abs(tilex - endx) > Math.abs(tiley - endy)){ if(Math.abs(tilex - endx) > Math.abs(tiley - endy)){
endy = tiley; endy = tiley;

View File

@@ -27,7 +27,7 @@ public class NetEvents {
} }
@RemoteServer @RemoteServer
public static void notifySomethingFromClient(Player player, int x, float y){ public static void notifySomethingFromClient(Player player, int x, float y, String asdsad, long l){
} }

View File

@@ -11,7 +11,6 @@ import io.anuke.mindustry.gen.CallClient;
import io.anuke.mindustry.io.Version; import io.anuke.mindustry.io.Version;
import io.anuke.mindustry.net.Packet.ImportantPacket; import io.anuke.mindustry.net.Packet.ImportantPacket;
import io.anuke.mindustry.net.Packet.UnimportantPacket; import io.anuke.mindustry.net.Packet.UnimportantPacket;
import io.anuke.mindustry.resource.Item;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.EntityGroup; import io.anuke.ucore.entities.EntityGroup;
@@ -136,17 +135,13 @@ public class Packets {
} }
public static class StateSyncPacket implements Packet, UnimportantPacket{ public static class StateSyncPacket implements Packet, UnimportantPacket{
public int[] items; //todo fix item syncing
public float countdown, time; public float countdown, time;
public int enemies, wave; public int enemies, wave;
public long timestamp; public long timestamp;
@Override @Override
public void write(ByteBuffer buffer) { public void write(ByteBuffer buffer) {
for(int i = 0; i < items.length; i ++){
buffer.putInt(items[i]);
}
buffer.putFloat(countdown); buffer.putFloat(countdown);
buffer.putFloat(time); buffer.putFloat(time);
buffer.putShort((short)enemies); buffer.putShort((short)enemies);
@@ -156,12 +151,6 @@ public class Packets {
@Override @Override
public void read(ByteBuffer buffer) { public void read(ByteBuffer buffer) {
items = new int[Item.getAllItems().size];
for(int i = 0; i < items.length; i ++){
items[i] = buffer.getInt();
}
countdown = buffer.getFloat(); countdown = buffer.getFloat();
time = buffer.getFloat(); time = buffer.getFloat();
enemies = buffer.getShort(); enemies = buffer.getShort();

View File

@@ -1,4 +0,0 @@
package io.anuke.mindustry.resource;
public interface CarryItem {
}

View File

@@ -1,6 +1,6 @@
package io.anuke.mindustry.resource; package io.anuke.mindustry.resource;
public class ItemStack implements CarryItem{ public class ItemStack{
public Item item; public Item item;
public int amount; public int amount;

View File

@@ -1,15 +0,0 @@
package io.anuke.mindustry.resource;
public class LiquidStack implements CarryItem{
public Liquid liquid;
public float amount;
public LiquidStack(Liquid liquid, float amount){
this.liquid = liquid;
this.amount = amount;
}
public boolean equals(LiquidStack other){
return other != null && other.liquid == liquid && other.amount == amount;
}
}

View File

@@ -54,7 +54,7 @@ public class Recipe {
return r; return r;
} }
public static Array<Recipe> all(){ public static Array<Recipe> getAllRecipes(){
return allRecipes; return allRecipes;
} }

View File

@@ -29,7 +29,7 @@ public class ColorPickDialog extends Dialog{
cons.accept(color); cons.accept(color);
hide(); hide();
}).size(44, 48).pad(0).padBottom(-5.1f).get(); }).size(44, 48).pad(0).padBottom(-5.1f).get();
button.setChecked(players[0].getColor().equals(color)); button.setChecked(players[0].color.equals(color));
button.getStyle().imageUpColor = color; button.getStyle().imageUpColor = color;
if(i%4 == 3){ if(i%4 == 3){

View File

@@ -42,7 +42,7 @@ public class HostDialog extends FloatingDialog{
Settings.save(); Settings.save();
}); });
}).size(50f, 54f).get(); }).size(50f, 54f).get();
button.update(() -> button.getStyle().imageUpColor = player.getColor()); button.update(() -> button.getStyle().imageUpColor = player.color);
}).width(w).height(70f).pad(4).colspan(3); }).width(w).height(70f).pad(4).colspan(3);
content().row(); content().row();

View File

@@ -222,7 +222,7 @@ public class JoinDialog extends FloatingDialog {
Settings.save(); Settings.save();
}); });
}).size(50f, 54f).get(); }).size(50f, 54f).get();
button.update(() -> button.getStyle().imageUpColor = player.getColor()); button.update(() -> button.getStyle().imageUpColor = player.color);
}).width(w).height(70f).pad(4); }).width(w).height(70f).pad(4);
content().row(); content().row();
content().add(pane).width(w + 34).pad(0); content().add(pane).width(w + 34).pad(0);

View File

@@ -17,7 +17,6 @@ import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.BlockStats; import io.anuke.mindustry.world.BlockStats;
import io.anuke.ucore.graphics.Draw; import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Hue;
import io.anuke.ucore.scene.Element; import io.anuke.ucore.scene.Element;
import io.anuke.ucore.scene.Group; import io.anuke.ucore.scene.Group;
import io.anuke.ucore.scene.actions.Actions; import io.anuke.ucore.scene.actions.Actions;
@@ -40,6 +39,16 @@ public class BlocksFragment implements Fragment{
private boolean shown = true; private boolean shown = true;
private Recipe hoveredDescriptionRecipe; private Recipe hoveredDescriptionRecipe;
private IntSet itemset = new IntSet(); private IntSet itemset = new IntSet();
private int[] tmpItems;
{
int size = 0;
for(Item ignored : Item.getAllItems()){
size ++;
}
tmpItems = new int[size];
}
public void build(Group parent){ public void build(Group parent){
InputHandler input = control.input(0); InputHandler input = control.input(0);
@@ -55,7 +64,7 @@ public class BlocksFragment implements Fragment{
itemtable = new Table("button"); itemtable = new Table("button");
itemtable.setVisible(() -> input.recipe == null && !state.mode.infiniteResources); itemtable.setVisible(() -> input.recipe == null && !state.mode.infiniteResources);
itemtable.update(() -> { itemtable.update(() -> {
int[] items = state.inventory.readItems(); int[] items = tmpItems;
for(int i = 0; i < items.length; i ++){ for(int i = 0; i < items.length; i ++){
if(itemset.contains(items[i]) != (items[i] > 0)){ if(itemset.contains(items[i]) != (items[i] > 0)){
updateItems(); updateItems();
@@ -186,10 +195,9 @@ public class BlocksFragment implements Fragment{
table.add(image).size(size + 8); table.add(image).size(size + 8);
image.update(() -> { image.update(() -> {
boolean has = (state.inventory.hasItems(r.requirements));
image.setTouchable(Touchable.enabled); image.setTouchable(Touchable.enabled);
for(Element e : istack.getChildren()){ for(Element e : istack.getChildren()){
e.setColor(has ? Color.WHITE : Hue.lightness(0.33f)); e.setColor(Color.WHITE);
} }
for(Player player : players){ for(Player player : players){
@@ -287,7 +295,7 @@ public class BlocksFragment implements Fragment{
Label reqlabel = new Label(""); Label reqlabel = new Label("");
reqlabel.update(()->{ reqlabel.update(()->{
int current = state.inventory.getAmount(stack.item); int current = stack.amount;
String text = Mathf.clamp(current, 0, stack.amount) + "/" + stack.amount; String text = Mathf.clamp(current, 0, stack.amount) + "/" + stack.amount;
reqlabel.setColor(current < stack.amount ? Colors.get("missingitems") : Color.WHITE); reqlabel.setColor(current < stack.amount ? Colors.get("missingitems") : Color.WHITE);
@@ -364,7 +372,7 @@ public class BlocksFragment implements Fragment{
}; };
int index = 0; int index = 0;
int[] items = state.inventory.readItems(); int[] items = tmpItems;
for(int i = 0; i < items.length; i ++){ for(int i = 0; i < items.length; i ++){
int amount = items[i]; int amount = items[i];

View File

@@ -118,7 +118,7 @@ public class PlayerListFragment implements Fragment{
}); });
button.add(stack).size(h); button.add(stack).size(h);
button.labelWrap("[#" + player.getColor().toString().toUpperCase() + "]" + player.name).width(170f).pad(10); button.labelWrap("[#" + player.color.toString().toUpperCase() + "]" + player.name).width(170f).pad(10);
button.add().grow(); button.add().grow();
button.addImage("icon-admin").size(14*2).visible(() -> player.isAdmin && !(!player.isLocal && Net.server())).padRight(5); button.addImage("icon-admin").size(14*2).visible(() -> player.isAdmin && !(!player.isLocal && Net.server())).padRight(5);

View File

@@ -3,7 +3,6 @@ package io.anuke.mindustry.ui.fragments;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Align; import com.badlogic.gdx.utils.Align;
import static io.anuke.mindustry.Vars.*;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.input.InputHandler; import io.anuke.mindustry.input.InputHandler;
import io.anuke.mindustry.input.PlaceMode; import io.anuke.mindustry.input.PlaceMode;
@@ -12,6 +11,8 @@ import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.scene.Group; import io.anuke.ucore.scene.Group;
import io.anuke.ucore.scene.ui.layout.Table; import io.anuke.ucore.scene.ui.layout.Table;
import static io.anuke.mindustry.Vars.*;
public class ToolFragment implements Fragment{ public class ToolFragment implements Fragment{
private Table tools; private Table tools;
private InputHandler input; private InputHandler input;
@@ -52,7 +53,7 @@ public class ToolFragment implements Fragment{
}); });
tools.setVisible(() -> tools.setVisible(() ->
!state.is(State.menu) && mobile && ((input.recipe != null && state.inventory.hasItems(input.recipe.requirements) && !state.is(State.menu) && mobile && ((input.recipe != null &&
input.placeMode == PlaceMode.cursor) || confirming) input.placeMode == PlaceMode.cursor) || confirming)
); );

View File

@@ -68,8 +68,6 @@ public class Block extends BaseBlock {
public boolean liquid; public boolean liquid;
/**whether this floor can be placed on.*/ /**whether this floor can be placed on.*/
public boolean placeableOn = true; public boolean placeableOn = true;
/**time it takes to break*/
public float breaktime = 18;
/**tile entity health*/ /**tile entity health*/
public int health = 40; public int health = 40;
/**base block explosiveness*/ /**base block explosiveness*/

View File

@@ -7,15 +7,15 @@ import io.anuke.mindustry.content.blocks.Blocks;
import io.anuke.mindustry.content.fx.Fx; import io.anuke.mindustry.content.fx.Fx;
import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.resource.ItemStack;
import io.anuke.mindustry.resource.Recipe; import io.anuke.mindustry.resource.Recipe;
import io.anuke.mindustry.world.blocks.types.BuildBlock.BuildEntity; import io.anuke.mindustry.world.blocks.types.BuildBlock.BuildEntity;
import io.anuke.ucore.core.Effects; import io.anuke.ucore.core.Effects;
import io.anuke.ucore.entities.Entities; import io.anuke.ucore.entities.Entities;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.tilesize;
import static io.anuke.mindustry.Vars.world;
public class Placement { public class Build {
private static final Rectangle rect = new Rectangle(); private static final Rectangle rect = new Rectangle();
private static Array<Tile> tempTiles = new Array<>(); private static Array<Tile> tempTiles = new Array<>();
@@ -28,17 +28,9 @@ public class Placement {
Block block = tile.isLinked() ? tile.getLinked().block() : tile.block(); Block block = tile.isLinked() ? tile.getLinked().block() : tile.block();
Recipe result = Recipe.getByResult(block); Recipe result = Recipe.getByResult(block);
if(result != null){ //todo add break results to core inventory
for(ItemStack stack : result.requirements){
state.inventory.addItem(stack.item, (int)(stack.amount * breakDropAmount));
}
}
if(tile.block().drops != null){ if(sound) Effects.sound("break", x * tilesize, y * tilesize);
state.inventory.addItem(tile.block().drops.item, tile.block().drops.amount);
}
if(sound) threads.run(() -> Effects.sound("break", x * tilesize, y * tilesize));
if(!tile.block().isMultiblock() && !tile.isLinked()){ if(!tile.block().isMultiblock() && !tile.isLinked()){
tile.setBlock(Blocks.air); tile.setBlock(Blocks.air);
@@ -56,7 +48,8 @@ public class Placement {
return block; return block;
} }
public static void placeBlock(Team team, int x, int y, Recipe recipe, int rotation, boolean effects, boolean sound){ /**Places a BuildBlock at this location. Call validPlace first.*/
public static void placeBlock(Team team, int x, int y, Recipe recipe, int rotation){
Tile tile = world.tile(x, y); Tile tile = world.tile(x, y);
Block result = recipe.result; Block result = recipe.result;
@@ -86,23 +79,16 @@ public class Placement {
toplace.setTeam(team); toplace.setTeam(team);
} }
} }
if(effects) Effects.effect(Fx.none, worldx * tilesize, worldy * tilesize);
} }
} }
}else if(effects){
Effects.effect(Fx.none, x * tilesize, y * tilesize);
}
if(effects && sound){
threads.run(() -> Effects.sound("place", x * tilesize, y * tilesize));
} }
} }
/**Returns whether a tile can be placed at this location by this team.*/
public static boolean validPlace(Team team, int x, int y, Block type, int rotation){ public static boolean validPlace(Team team, int x, int y, Block type, int rotation){
Recipe recipe = Recipe.getByResult(type); Recipe recipe = Recipe.getByResult(type);
if(recipe == null || !state.inventory.hasItems(recipe.requirements)){ if(recipe == null){
return false; return false;
} }
@@ -121,7 +107,7 @@ public class Placement {
if (e == null) return; //not sure why this happens? if (e == null) return; //not sure why this happens?
Rectangle rect = e.hitbox.getRect(e.x, e.y); Rectangle rect = e.hitbox.getRect(e.x, e.y);
if (Placement.rect.overlaps(rect) && !e.isFlying()) { if (Build.rect.overlaps(rect) && !e.isFlying()) {
result[0] = true; result[0] = true;
} }
}); });
@@ -160,13 +146,12 @@ public class Placement {
return false; return false;
} }
/**Returns whether the tile at this position is breakable by this team*/
public static boolean validBreak(Team team, int x, int y) { public static boolean validBreak(Team team, int x, int y) {
Tile tile = world.tile(x, y); Tile tile = world.tile(x, y);
if (tile == null || tile.block().unbreakable) return false; return tile != null && !tile.block().unbreakable
&& (!tile.isLinked() || !tile.getLinked().block().unbreakable) && tile.breakable() && (tile.getTeam() == Team.none || tile.getTeam() == team);
return (!tile.isLinked() || !tile.getLinked().block().unbreakable) && tile.breakable()
&& (tile.getTeam() == Team.none || tile.getTeam() == team);
} }
} }

View File

@@ -6,6 +6,7 @@ import com.badlogic.gdx.utils.reflect.ClassReflection;
import io.anuke.mindustry.content.blocks.Blocks; import io.anuke.mindustry.content.blocks.Blocks;
import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.resource.Recipe;
import io.anuke.mindustry.world.blocks.types.Floor; import io.anuke.mindustry.world.blocks.types.Floor;
import io.anuke.mindustry.world.blocks.types.modules.InventoryModule; import io.anuke.mindustry.world.blocks.types.modules.InventoryModule;
import io.anuke.mindustry.world.blocks.types.modules.LiquidModule; import io.anuke.mindustry.world.blocks.types.modules.LiquidModule;
@@ -132,10 +133,14 @@ public class Tile implements Position{
this.team = (byte)team.ordinal(); this.team = (byte)team.ordinal();
} }
/**Returns the breaktime of the block, <i>or</i> the breaktime of the linked block, if this tile is linked.*/ /**Returns the break time of the block, <i>or</i> the breaktime of the linked block, if this tile is linked.*/
public float getBreakTime(){ public float getBreakTime(){
Block block = block(); Block block = target().block();
return link == 0 ? block.breaktime : getLinked().block().breaktime; if(Recipe.getByResult(block) != null){
return Recipe.getByResult(block).cost;
}else{
return 15f;
}
} }
public void setBlock(Block type, int rotation){ public void setBlock(Block type, int rotation){

View File

@@ -8,7 +8,6 @@ public class Rock extends Block {
super(name); super(name);
shadow = name+"shadow"; shadow = name+"shadow";
breakable = true; breakable = true;
breaktime = 10;
alwaysReplace = true; alwaysReplace = true;
} }
} }