diff --git a/build.gradle b/build.gradle index 00b308c67f..cfc4e155fb 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ allprojects { appName = "Mindustry" gdxVersion = '1.9.8' aiVersion = '1.8.1' - uCoreVersion = '49d8aecf9c'; + uCoreVersion = 'e6a13f6507'; } repositories { diff --git a/core/assets-raw/sprites/icon-iron.png b/core/assets-raw/sprites/icon-iron.png index 3998196a99..46b05fb505 100644 Binary files a/core/assets-raw/sprites/icon-iron.png and b/core/assets-raw/sprites/icon-iron.png differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 43abd9ee43..f7f46f938e 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -32,6 +32,7 @@ text.hosts.discovering=Discovering LAN games text.server.refreshing=Refreshing server text.hosts.none=[lightgray]No LAN games found! text.host.invalid=[scarlet]Can't connect to host. +text.server.friendlyfire=Friendly Fire text.server.add=Add Server text.server.delete=Are you sure you want to delete this server? text.server.hostname=Host: {0} @@ -416,9 +417,9 @@ block.pump.fulldescription=Pumps liquids from a source block- usually water, lav block.fluxpump.name=fluxpump block.fluxpump.fulldescription=An advanced version of the pump. Stores more liquid and pumps liquid faster. block.smelter.name=smelter -block.smelter.fulldescription=The essential crafting block. When inputted 1x iron and 1x coal, outputs one steel. +block.smelter.fulldescription=The essential crafting block. When inputted 1 iron and 1 coal as fuel, outputs one steel. It is advised to input iron and coal on different belts to prevent clogging. block.crucible.name=crucible -block.crucible.fulldescription=An advanced crafting block. When inputted 1x titanium and 1x steel, outputs one dirium. +block.crucible.fulldescription=An advanced crafting block. When inputted 1 titanium, 1 steel and 1 coal as fuel, outputs one dirium. It is advised to input coal, steel and titanium on different belts to prevent clogging. block.coalpurifier.name=coal extractor block.coalpurifier.fulldescription=A basic extractor block. Outputs coal when supplied with large amounts of water and stone. block.titaniumpurifier.name=titanium extractor diff --git a/core/assets/sprites/sprites.png b/core/assets/sprites/sprites.png index 0882aaae5a..f45f6930d1 100644 Binary files a/core/assets/sprites/sprites.png and b/core/assets/sprites/sprites.png differ diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index 31e62f3f45..06f121405a 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -75,6 +75,7 @@ public class Control extends Module{ float respawntime; InputHandler input; + boolean friendlyFire; private InputProxy proxy; private float controlx, controly; @@ -218,14 +219,6 @@ public class Control extends Module{ saves.load(); } - - public Saves getSaves(){ - return saves; - } - - public boolean showCursor(){ - return controlling; - } public void reset(){ weapons.clear(); @@ -277,7 +270,26 @@ public class Control extends Module{ GameState.set(State.playing); } - + + public Saves getSaves(){ + return saves; + } + + public boolean showCursor(){ + return controlling; + } + + public boolean isFriendlyFire() { + return friendlyFire; + } + + public void setFriendlyFire(boolean friendlyFire) { + if(this.friendlyFire != friendlyFire && Net.active() && Net.server()){ + Vars.netServer.handleFriendlyFireChange(friendlyFire); + } + this.friendlyFire = friendlyFire; + } + public Tile getCore(){ return core; } diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index b2d3ea1c4e..1c53359df0 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -13,7 +13,7 @@ import io.anuke.mindustry.entities.SyncEntity; import io.anuke.mindustry.entities.enemies.Enemy; import io.anuke.mindustry.entities.enemies.EnemyType; import io.anuke.mindustry.graphics.Fx; -import io.anuke.mindustry.io.NetworkIO; +import io.anuke.mindustry.net.NetworkIO; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net.SendMode; import io.anuke.mindustry.net.Packets.*; @@ -319,6 +319,8 @@ public class NetClient extends Module { kicked = true; Gdx.app.postRunnable(ui.restart::show); }); + + Net.handle(FriendlyFireChangePacket.class, packet -> Vars.control.setFriendlyFire(packet.enabled)); } @Override diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index f73b14d351..ad1d7e02af 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -9,7 +9,7 @@ import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.SyncEntity; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.enemies.Enemy; -import io.anuke.mindustry.io.NetworkIO; +import io.anuke.mindustry.net.NetworkIO; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.net.Net.SendMode; import io.anuke.mindustry.net.Packets.*; @@ -220,6 +220,15 @@ public class NetServer extends Module{ Gdx.app.postRunnable(() -> Vars.ui.chatfrag.addMessage(message, null)); } + public void handleFriendlyFireChange(boolean enabled){ + FriendlyFireChangePacket packet = new FriendlyFireChangePacket(); + packet.enabled = enabled; + + sendMessage(enabled ? "[accent]Friendly fire enabled." : "[accent]Friendly fire disabled."); + + Net.send(packet, SendMode.tcp); + } + public void handleGameOver(){ Net.send(new GameOverPacket(), SendMode.tcp); Timers.runTask(30f, () -> GameState.set(State.menu)); @@ -303,7 +312,6 @@ public class NetServer extends Module{ current = ByteBuffer.wrap(bytes); //write the group ID so the client knows which group this is current.put((byte)group.getID()); - UCore.log(" Writing new packet: " + i); } SyncEntity entity = (SyncEntity) group.all().get(i); diff --git a/core/src/io/anuke/mindustry/entities/Player.java b/core/src/io/anuke/mindustry/entities/Player.java index b81b5531c5..e4d84f769f 100644 --- a/core/src/io/anuke/mindustry/entities/Player.java +++ b/core/src/io/anuke/mindustry/entities/Player.java @@ -50,6 +50,12 @@ public class Player extends SyncEntity{ @Override public boolean collides(SolidEntity other){ + if(other instanceof Bullet){ + Bullet b = (Bullet)other; + if(!Vars.control.isFriendlyFire() && b.owner instanceof Player){ + return false; + } + } return super.collides(other) && !isAndroid; } diff --git a/core/src/io/anuke/mindustry/io/NetworkIO.java b/core/src/io/anuke/mindustry/net/NetworkIO.java similarity index 96% rename from core/src/io/anuke/mindustry/io/NetworkIO.java rename to core/src/io/anuke/mindustry/net/NetworkIO.java index b4bffa9650..642ded251e 100644 --- a/core/src/io/anuke/mindustry/io/NetworkIO.java +++ b/core/src/io/anuke/mindustry/net/NetworkIO.java @@ -1,4 +1,4 @@ -package io.anuke.mindustry.io; +package io.anuke.mindustry.net; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.utils.ByteArray; @@ -19,7 +19,7 @@ import io.anuke.ucore.entities.Entities; import java.io.*; public class NetworkIO { - private static final int fileVersionID = 15; + private static final int fileVersionID = 16; public static void write(int playerID, ByteArray upgrades, OutputStream os){ @@ -38,6 +38,7 @@ public class NetworkIO { stream.writeFloat(Vars.control.getWaveCountdown()); //wave countdown stream.writeInt(Vars.control.enemyGroup.amount()); //enemy amount + stream.writeBoolean(Vars.control.isFriendlyFire()); //friendly fire state stream.writeInt(playerID); //player remap ID //--INVENTORY-- @@ -168,9 +169,11 @@ public class NetworkIO { int wave = stream.readInt(); float wavetime = stream.readFloat(); int enemies = stream.readInt(); + boolean friendlyfire = stream.readBoolean(); Vars.control.setWaveData(enemies, wave, wavetime); Vars.control.setMode(GameMode.values()[mode]); + Vars.control.setFriendlyFire(friendlyfire); int pid = stream.readInt(); diff --git a/core/src/io/anuke/mindustry/net/Packets.java b/core/src/io/anuke/mindustry/net/Packets.java index 24eb2b2bd9..0cdabc7280 100644 --- a/core/src/io/anuke/mindustry/net/Packets.java +++ b/core/src/io/anuke/mindustry/net/Packets.java @@ -137,4 +137,8 @@ public class Packets { public static class GameOverPacket{ } + + public static class FriendlyFireChangePacket{ + public boolean enabled; + } } diff --git a/core/src/io/anuke/mindustry/net/Registrator.java b/core/src/io/anuke/mindustry/net/Registrator.java index 27904dcc3b..a551a4c87e 100644 --- a/core/src/io/anuke/mindustry/net/Registrator.java +++ b/core/src/io/anuke/mindustry/net/Registrator.java @@ -39,6 +39,7 @@ public class Registrator { EntityRequestPacket.class, ConnectConfirmPacket.class, GameOverPacket.class, + FriendlyFireChangePacket.class, Class.class, byte[].class, diff --git a/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java b/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java index b1a2ce3854..f053a37e01 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java @@ -31,6 +31,13 @@ public class PlayerListFragment implements Fragment{ pane.setScrollingDisabled(true, false); pane.setFadeScrollBars(false); add(pane).grow(); + row(); + new table("pane"){{ + margin(12f); + get().addCheck("$text.server.friendlyfire", b -> { + Vars.control.setFriendlyFire(b); + }).growX().update(i -> i.setChecked(Vars.control.isFriendlyFire())).disabled(b -> Net.client()); + }}.pad(10f).growX().end(); }}.end(); update(t -> { diff --git a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java index fb6c983217..a21524988e 100644 --- a/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/types/distribution/Conveyor.java @@ -18,8 +18,6 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.AbstractList; -import java.util.Collections; -import java.util.Comparator; import java.util.List; import static io.anuke.mindustry.Vars.tilesize; @@ -74,6 +72,8 @@ public class Conveyor extends Block{ for(int i = 0; i < entity.convey.size; i ++){ ItemPos pos = pos1.set(entity.convey.get(i)); + + if(pos.item == null) continue; Tmp.v1.set(tilesize, 0).rotate(rotation * 90); Tmp.v2.set(-tilesize / 2, pos.x*tilesize/2).rotate(rotation * 90); @@ -97,6 +97,11 @@ public class Conveyor extends Block{ for(int i = 0; i < entity.convey.size; i ++){ int value = entity.convey.get(i); ItemPos pos = pos1.set(value); + + if(pos.item == null){ + removals.add(value); + continue; + } boolean canmove = i == entity.convey.size - 1 || !(pos2.set(entity.convey.get(i + 1)).y - pos.y < itemSpace * Timers.delta()); @@ -230,10 +235,10 @@ public class Conveyor extends Block{ } }; - Collections.sort(wrapper, new Comparator(){public int compare(Object a, Object b){ return compareItems((Integer)a, (Integer)b); }}); + wrapper.sort(Conveyor::compareItems); } - private static int compareItems(int a, int b){ + private static int compareItems(Integer a, Integer b){ pos1.set(a); pos2.set(b); return Float.compare(pos1.y, pos2.y); @@ -249,7 +254,12 @@ public class Conveyor extends Block{ ItemPos set(int value){ byte[] values = Bits.getBytes(value); - item = Item.getAllItems().get(values[0]); + + if(values[0] > Item.getAllItems().size) + item = null; + else + item = Item.getAllItems().get(values[0]); + x = values[1] / 127f; y = ((int)values[2] + 128) / 255f; seed = values[3];