diff --git a/build.gradle b/build.gradle index 014cf51bb1..5e3e6ec7f2 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ allprojects { appName = 'Mindustry' gdxVersion = '1.9.8' roboVMVersion = '2.3.0' - uCoreVersion = '6a727b957e' + uCoreVersion = '9969ed07b1' getVersionString = { String buildVersion = getBuildVersion() diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index f455ae3ab1..0896b7baf2 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -198,6 +198,7 @@ text.builtin=Built-In text.map.delete.confirm=Are you sure you want to delete this map? This action cannot be undone! text.map.random=[accent]Random Map text.map.nospawn=This map does not have any cores for the player to spawn in! Add a [ROYAL]blue[] core to this map in the editor. +text.map.invalid=Error loading map: corrupted or invalid map file. text.editor.brush=Brush text.editor.slope=\\ text.editor.openin=Open In Editor diff --git a/core/src/io/anuke/mindustry/content/Recipes.java b/core/src/io/anuke/mindustry/content/Recipes.java index e93b5a67f8..92d447acaf 100644 --- a/core/src/io/anuke/mindustry/content/Recipes.java +++ b/core/src/io/anuke/mindustry/content/Recipes.java @@ -3,6 +3,7 @@ package io.anuke.mindustry.content; import com.badlogic.gdx.utils.Array; import io.anuke.mindustry.content.blocks.*; import io.anuke.mindustry.game.Content; +import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.type.ContentList; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.Recipe; @@ -131,15 +132,15 @@ public class Recipes implements ContentList{ new Recipe(units, UnitBlocks.dronePad, new ItemStack(Items.tungsten, 70), new ItemStack(Items.lead, 110), new ItemStack(Items.silicon, 130)); new Recipe(units, UnitBlocks.fabricatorPad, new ItemStack(Items.carbide, 90), new ItemStack(Items.thorium, 80), new ItemStack(Items.lead, 110), new ItemStack(Items.silicon, 210)); - new Recipe(units, UnitBlocks.daggerPad, new ItemStack(Items.lead, 90), new ItemStack(Items.silicon, 80)); - new Recipe(units, UnitBlocks.titanPad, new ItemStack(Items.thorium, 90), new ItemStack(Items.lead, 140), new ItemStack(Items.silicon, 90)); + new Recipe(units, UnitBlocks.daggerPad, new ItemStack(Items.lead, 90), new ItemStack(Items.silicon, 80)).setMode(GameMode.noWaves); + new Recipe(units, UnitBlocks.titanPad, new ItemStack(Items.thorium, 90), new ItemStack(Items.lead, 140), new ItemStack(Items.silicon, 90)).setMode(GameMode.noWaves); - new Recipe(units, UnitBlocks.interceptorPad, new ItemStack(Items.titanium, 60), new ItemStack(Items.lead, 80), new ItemStack(Items.silicon, 90)); - new Recipe(units, UnitBlocks.monsoonPad, new ItemStack(Items.plastanium, 80), new ItemStack(Items.titanium, 100), new ItemStack(Items.lead, 130), new ItemStack(Items.silicon, 220)); + new Recipe(units, UnitBlocks.interceptorPad, new ItemStack(Items.titanium, 60), new ItemStack(Items.lead, 80), new ItemStack(Items.silicon, 90)).setMode(GameMode.noWaves); + new Recipe(units, UnitBlocks.monsoonPad, new ItemStack(Items.plastanium, 80), new ItemStack(Items.titanium, 100), new ItemStack(Items.lead, 130), new ItemStack(Items.silicon, 220)).setMode(GameMode.noWaves); new Recipe(units, UnitBlocks.repairPoint, new ItemStack(Items.lead, 30), new ItemStack(Items.tungsten, 30), new ItemStack(Items.silicon, 30)); new Recipe(units, UnitBlocks.resupplyPoint, new ItemStack(Items.lead, 30), new ItemStack(Items.tungsten, 30), new ItemStack(Items.silicon, 30)); - new Recipe(units, UnitBlocks.commandCenter, new ItemStack(Items.lead, 100), new ItemStack(Items.carbide, 100), new ItemStack(Items.silicon, 200)); + new Recipe(units, UnitBlocks.commandCenter, new ItemStack(Items.lead, 100), new ItemStack(Items.carbide, 100), new ItemStack(Items.silicon, 200)).setMode(GameMode.noWaves); //LIQUIDS new Recipe(liquid, LiquidBlocks.conduit, new ItemStack(Items.lead, 1)) diff --git a/core/src/io/anuke/mindustry/content/blocks/CraftingBlocks.java b/core/src/io/anuke/mindustry/content/blocks/CraftingBlocks.java index 9a7a9fdabd..c8e7a9f40d 100644 --- a/core/src/io/anuke/mindustry/content/blocks/CraftingBlocks.java +++ b/core/src/io/anuke/mindustry/content/blocks/CraftingBlocks.java @@ -21,11 +21,11 @@ public class CraftingBlocks extends BlockList implements ContentList{ health = 70; result = Items.carbide; craftTime = 45f; - burnDuration = 45f; + burnDuration = 46f; useFlux = true; consumes.items(new ItemStack[]{new ItemStack(Items.tungsten, 3)}); - consumes.item(Items.coal); + consumes.item(Items.coal).optional(true); }}; arcsmelter = new PowerSmelter("arc-smelter"){{ diff --git a/core/src/io/anuke/mindustry/core/World.java b/core/src/io/anuke/mindustry/core/World.java index ba0dfd1cc1..755d439faf 100644 --- a/core/src/io/anuke/mindustry/core/World.java +++ b/core/src/io/anuke/mindustry/core/World.java @@ -256,7 +256,18 @@ public class World extends Module{ EntityPhysics.resizeTree(0, 0, width * tilesize, height * tilesize); - generator.loadTileData(tiles, MapIO.readTileData(map, true), map.meta.hasOreGen(), 0); + try{ + generator.loadTileData(tiles, MapIO.readTileData(map, true), map.meta.hasOreGen(), 0); + } catch(Exception e){ + Log.err(e); + if(!headless){ + ui.showError("$text.map.invalid"); + threads.runDelay(() -> state.set(State.menu)); + invalidMap = true; + } + generating = false; + return; + } if(!headless && state.teams.get(players[0].getTeam()).cores.size == 0){ ui.showError("$text.map.nospawn"); diff --git a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java b/core/src/io/anuke/mindustry/entities/units/BaseUnit.java index b807542b5e..8a3b2696b6 100644 --- a/core/src/io/anuke/mindustry/entities/units/BaseUnit.java +++ b/core/src/io/anuke/mindustry/entities/units/BaseUnit.java @@ -133,7 +133,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ } public boolean targetHasFlag(BlockFlag flag){ - return target instanceof TileEntity && + return target instanceof TileEntity && ((TileEntity) target).tile.block().flags != null && ((TileEntity) target).tile.block().flags.contains(flag); } diff --git a/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java b/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java index 8386538d65..89bb5ede2f 100644 --- a/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java @@ -144,7 +144,7 @@ public class MinimapRenderer implements Disposable{ private int colorFor(Tile tile){ tile = tile.target(); - return ColorMapper.colorFor(tile.floor(), tile.block(), tile.getTeam(), tile.getElevation()); + return ColorMapper.colorFor(tile.floor(), tile.block(), tile.getTeam(), tile.getElevation(), tile.getCliffs()); } @Override diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java index 9fd32cde63..ac48267cf4 100644 --- a/core/src/io/anuke/mindustry/input/InputHandler.java +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -83,6 +83,7 @@ public abstract class InputHandler extends InputAdapter{ int sent = Mathf.clamp(accepted / 4, 1, 8); int removed = accepted / sent; int[] remaining = {accepted, accepted}; + Block block = tile.block(); for(int i = 0; i < sent; i++){ boolean end = i == sent - 1; @@ -92,6 +93,7 @@ public abstract class InputHandler extends InputAdapter{ ItemTransfer.create(stack.item, player.x + Angles.trnsx(player.rotation + 180f, backTrns), player.y + Angles.trnsy(player.rotation + 180f, backTrns), new Translator(tile.drawx() + stackTrns.x, tile.drawy() + stackTrns.y), () -> { + if(tile.block() != block) return; tile.block().handleStack(stack.item, removed, tile, player); remaining[1] -= removed; diff --git a/core/src/io/anuke/mindustry/maps/Sectors.java b/core/src/io/anuke/mindustry/maps/Sectors.java index 94087161fb..0bcdbffee9 100644 --- a/core/src/io/anuke/mindustry/maps/Sectors.java +++ b/core/src/io/anuke/mindustry/maps/Sectors.java @@ -182,7 +182,7 @@ public class Sectors{ GenResult result = world.generator().generateTile(sector.x, sector.y, toX, toY, false); - int color = ColorMapper.colorFor(result.floor, result.wall, Team.none, result.elevation); + int color = ColorMapper.colorFor(result.floor, result.wall, Team.none, result.elevation, (byte)0); pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, color); } } diff --git a/core/src/io/anuke/mindustry/maps/missions/WaveMission.java b/core/src/io/anuke/mindustry/maps/missions/WaveMission.java index 8a2441d1f7..f75450125e 100644 --- a/core/src/io/anuke/mindustry/maps/missions/WaveMission.java +++ b/core/src/io/anuke/mindustry/maps/missions/WaveMission.java @@ -19,7 +19,6 @@ public class WaveMission implements Mission{ @Override public Array getWaves(Sector sector){ - Array spawns = new Array<>(); return Waves.getSpawns(); } diff --git a/core/src/io/anuke/mindustry/net/Packets.java b/core/src/io/anuke/mindustry/net/Packets.java index e42e26f73b..1e77dce5d8 100644 --- a/core/src/io/anuke/mindustry/net/Packets.java +++ b/core/src/io/anuke/mindustry/net/Packets.java @@ -22,7 +22,7 @@ import static io.anuke.mindustry.Vars.world; public class Packets{ public enum KickReason{ - kick, invalidPassword, clientOutdated, serverOutdated, banned, gameover(true), recentKick, nameInUse, idInUse, fastShoot, nameEmpty, customClient; + kick, invalidPassword, clientOutdated, serverOutdated, banned, gameover(true), recentKick, nameInUse, idInUse, fastShoot, nameEmpty, customClient, sectorComplete(true); public final boolean quiet; KickReason(){ diff --git a/core/src/io/anuke/mindustry/type/Recipe.java b/core/src/io/anuke/mindustry/type/Recipe.java index b8040acabe..43814cc620 100644 --- a/core/src/io/anuke/mindustry/type/Recipe.java +++ b/core/src/io/anuke/mindustry/type/Recipe.java @@ -6,6 +6,7 @@ import com.badlogic.gdx.utils.ObjectMap; import com.badlogic.gdx.utils.OrderedMap; import io.anuke.mindustry.Vars; import io.anuke.mindustry.game.Content; +import io.anuke.mindustry.game.GameMode; import io.anuke.mindustry.game.UnlockableContent; import io.anuke.mindustry.ui.ContentDisplay; import io.anuke.mindustry.world.Block; @@ -33,6 +34,8 @@ public class Recipe implements UnlockableContent{ public final float cost; public boolean desktopOnly = false, debugOnly = false; + //the only gamemode in which the recipe shows up + public GameMode targetMode; private Block[] dependencies; private Recipe[] recipeDependencies; @@ -101,6 +104,11 @@ public class Recipe implements UnlockableContent{ } } + public Recipe setMode(GameMode mode){ + this.targetMode = mode; + return this; + } + public Recipe setDesktop(){ desktopOnly = true; return this; diff --git a/core/src/io/anuke/mindustry/ui/dialogs/GenViewDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/GenViewDialog.java index 830f2003b4..622f22f646 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/GenViewDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/GenViewDialog.java @@ -82,7 +82,7 @@ public class GenViewDialog extends FloatingDialog{ for(int i = 0; i < sectorSize; i++){ for(int j = 0; j < sectorSize; j++){ world.generator().generateTile(result, wx, wy, i, j, true, null); - pixmap.drawPixel(i, sectorSize - 1 - j, ColorMapper.colorFor(result.floor, result.wall, Team.none, result.elevation)); + pixmap.drawPixel(i, sectorSize - 1 - j, ColorMapper.colorFor(result.floor, result.wall, Team.none, result.elevation, (byte)0)); } } Gdx.app.postRunnable(() -> map.put(wx, wy, new Texture(pixmap))); diff --git a/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java index 79e18ea09e..16e178f254 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BlocksFragment.java @@ -7,11 +7,13 @@ import com.badlogic.gdx.math.Interpolation; import com.badlogic.gdx.utils.Array; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.TileEntity; +import io.anuke.mindustry.game.EventType.WorldLoadEvent; import io.anuke.mindustry.input.InputHandler; import io.anuke.mindustry.type.Category; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.Recipe; import io.anuke.ucore.core.Core; +import io.anuke.ucore.core.Events; import io.anuke.ucore.core.Graphics; import io.anuke.ucore.scene.Element; import io.anuke.ucore.scene.Group; @@ -87,6 +89,8 @@ public class BlocksFragment extends Fragment{ }).bottom().right().get(); }); + Events.on(WorldLoadEvent.class, this::rebuild); + rebuild(); } @@ -165,7 +169,7 @@ public class BlocksFragment extends Fragment{ //add actual recipes for(Recipe r : recipes){ - if((r.debugOnly && !debug) || (r.desktopOnly && mobile)) continue; + if((r.debugOnly && !debug) || (r.desktopOnly && mobile) || (r.targetMode != null && r.targetMode != state.mode)) continue; ImageButton image = new ImageButton(new TextureRegion(), "select"); diff --git a/core/src/io/anuke/mindustry/world/ColorMapper.java b/core/src/io/anuke/mindustry/world/ColorMapper.java index 20d0067f58..83e3cbbd82 100644 --- a/core/src/io/anuke/mindustry/world/ColorMapper.java +++ b/core/src/io/anuke/mindustry/world/ColorMapper.java @@ -7,6 +7,7 @@ import com.badlogic.gdx.utils.ObjectIntMap; import io.anuke.mindustry.game.Content; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.type.ContentList; +import io.anuke.ucore.util.Mathf; public class ColorMapper implements ContentList{ private static IntMap blockMap = new IntMap<>(); @@ -21,7 +22,7 @@ public class ColorMapper implements ContentList{ return colorMap.get(block, 0); } - public static int colorFor(Block floor, Block wall, Team team, int elevation){ + public static int colorFor(Block floor, Block wall, Team team, int elevation, byte cliffs){ if(wall.synthetic()){ return team.intColor; } @@ -33,6 +34,9 @@ public class ColorMapper implements ContentList{ tmpColor.set(color); float maxMult = 1f/Math.max(Math.max(tmpColor.r, tmpColor.g), tmpColor.b) ; float mul = Math.min(1.1f + elevation / 4f, maxMult); + if((cliffs & Mathf.pow2(6)) != 0){ + mul -= 0.5f; + } tmpColor.mul(mul, mul, mul, 1f); color = Color.rgba8888(tmpColor); } diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java b/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java index a8bec8c381..53bace015a 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java @@ -77,6 +77,12 @@ public class Conveyor extends Block{ @Override public void drawShadow(Tile tile){ + //fixes build block crash + if(!(tile.entity instanceof ConveyorEntity)){ + super.drawShadow(tile); + return; + } + ConveyorEntity entity = tile.entity(); if(entity.blendshadowrot == -1){ @@ -299,7 +305,7 @@ public class Conveyor extends Block{ @Override public synchronized int acceptStack(Item item, int amount, Tile tile, Unit source){ ConveyorEntity entity = tile.entity(); - return (int)(entity.minitem / itemSpace); + return Math.min((int)(entity.minitem / itemSpace), amount); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Drill.java b/core/src/io/anuke/mindustry/world/blocks/production/Drill.java index 0f363919e9..b4dd5b5956 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Drill.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Drill.java @@ -158,7 +158,7 @@ public class Drill extends Block{ } for(Tile other : tile.getLinkedTiles(tempTiles)){ - if(isValid(other) && other.floor().dropsItem(entity.dominantItem)){ + if(isValid(other) && getDrop(other) == entity.dominantItem){ entity.dominantItems ++; } } diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/Vault.java b/core/src/io/anuke/mindustry/world/blocks/storage/Vault.java index 73b8bbd003..09eedd0061 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/Vault.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/Vault.java @@ -1,6 +1,7 @@ package io.anuke.mindustry.world.blocks.storage; import com.badlogic.gdx.utils.Array; +import io.anuke.mindustry.content.Items; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Edges; @@ -54,7 +55,7 @@ public class Vault extends StorageBlock{ if(other == null || !(other.block() instanceof StorageBlock)) continue; - if(other.block() instanceof Vault){ + if(!(other.block() instanceof Vault)){ for(int ii = 0; ii < Item.all().size; ii++){ Item item = Item.getByID(ii); @@ -67,10 +68,10 @@ public class Vault extends StorageBlock{ } } }else{ + todump = Items.tungsten; if(other.block().acceptItem(todump, other, in) && canDump(tile, other, todump)){ - other.block().handleItem(todump, other, in); - tile.entity.items.remove(todump, 1); + other.block().handleItem(removeItem(tile, null), other, in); incrementDump(tile, proximity.size); return true; } diff --git a/core/src/io/anuke/mindustry/world/blocks/units/CommandCenter.java b/core/src/io/anuke/mindustry/world/blocks/units/CommandCenter.java index 83b4f6f4ab..524cd8d4f5 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/CommandCenter.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/CommandCenter.java @@ -10,6 +10,7 @@ import io.anuke.mindustry.entities.Player; import io.anuke.mindustry.entities.TileEntity; import io.anuke.mindustry.entities.units.BaseUnit; import io.anuke.mindustry.entities.units.UnitCommand; +import io.anuke.mindustry.game.Team; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Palette; import io.anuke.mindustry.world.Block; @@ -98,7 +99,9 @@ public class CommandCenter extends Block{ } } - for(BaseUnit unit : unitGroups[player.getTeam().ordinal()].all()){ + Team team = (player == null ? tile.getTeam() : player.getTeam()); + + for(BaseUnit unit : unitGroups[team.ordinal()].all()){ unit.onCommand(command); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/units/MechFactory.java b/core/src/io/anuke/mindustry/world/blocks/units/MechFactory.java index 35f7f3dfce..63d024c79c 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/MechFactory.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/MechFactory.java @@ -45,7 +45,7 @@ public class MechFactory extends Block{ @Remote(targets = Loc.both, called = Loc.server) public static void onMechFactoryTap(Player player, Tile tile){ - if(!checkValidTap(tile, player)) return; + if(player == null || !checkValidTap(tile, player)) return; MechFactoryEntity entity = tile.entity(); player.beginRespawning(entity); diff --git a/core/src/io/anuke/mindustry/world/blocks/units/UnitPad.java b/core/src/io/anuke/mindustry/world/blocks/units/UnitPad.java index dbfb60dcb3..40f241a84d 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/UnitPad.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/UnitPad.java @@ -38,7 +38,7 @@ import java.io.DataOutputStream; import java.io.IOException; public class UnitPad extends Block{ - protected float gracePeriodMultiplier = 16f; + protected float gracePeriodMultiplier = 19f; protected float speedupTime = 60f * 60f * 19; protected float maxSpeedup = 7f; diff --git a/ios/robovm.xml b/ios/robovm.xml index 31ffe9e1f2..851c59da6f 100644 --- a/ios/robovm.xml +++ b/ios/robovm.xml @@ -19,6 +19,7 @@ io.anuke.ucore.scene.** + io.anuke.mindustry.gen.Call io.anuke.mindustry.net.** com.android.okhttp.HttpHandler com.android.okhttp.HttpsHandler diff --git a/server/src/io/anuke/mindustry/server/ServerControl.java b/server/src/io/anuke/mindustry/server/ServerControl.java index 659e0e7dd3..8c52ba2314 100644 --- a/server/src/io/anuke/mindustry/server/ServerControl.java +++ b/server/src/io/anuke/mindustry/server/ServerControl.java @@ -41,15 +41,14 @@ public class ServerControl extends Module{ Settings.defaultList( "shufflemode", "normal", "bans", "", - "admins", "" + "admins", "", + "sectorid", 0 ); mode = ShuffleMode.valueOf(Settings.getString("shufflemode")); - Effects.setScreenShakeProvider((a, b) -> { - }); - Effects.setEffectProvider((a, b, c, d, e, f) -> { - }); + Effects.setScreenShakeProvider((a, b) -> {}); + Effects.setEffectProvider((a, b, c, d, e, f) -> {}); Sounds.setHeadless(true); String[] commands = {};