Merge branch '4.0' of https://github.com/Anuken/Mindustry into 4.0
This commit is contained in:
@@ -27,7 +27,7 @@ allprojects {
|
|||||||
gdxVersion = '1.9.8'
|
gdxVersion = '1.9.8'
|
||||||
roboVMVersion = '2.3.0'
|
roboVMVersion = '2.3.0'
|
||||||
aiVersion = '1.8.1'
|
aiVersion = '1.8.1'
|
||||||
uCoreVersion = 'e7a37cff68'
|
uCoreVersion = '2241e5402e'
|
||||||
|
|
||||||
getVersionString = {
|
getVersionString = {
|
||||||
String buildVersion = getBuildVersion()
|
String buildVersion = getBuildVersion()
|
||||||
|
|||||||
BIN
core/assets-raw/sprites/blocks/power/turbine-generator-top.png
Normal file
BIN
core/assets-raw/sprites/blocks/power/turbine-generator-top.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 219 B |
@@ -1,7 +1,6 @@
|
|||||||
text.about=Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]
|
text.about=Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]
|
||||||
text.credits=Credits
|
text.credits=Credits
|
||||||
text.discord=Join the mindustry discord!
|
text.discord=Join the mindustry discord!
|
||||||
text.changes=[SCARLET]Attention!\n[]Some important game mechanics have been changed.\n\n- [accent]Teleporters[] now use power.\n- [accent]Smelteries[] and [accent]crucibles[] now have a maximum item capacity.\n- [accent]Crucibles[] now require coal as fuel.
|
|
||||||
text.link.discord.description=the official Mindustry discord chatroom
|
text.link.discord.description=the official Mindustry discord chatroom
|
||||||
text.link.github.description=Game source code
|
text.link.github.description=Game source code
|
||||||
text.link.dev-builds.description=Unstable development builds
|
text.link.dev-builds.description=Unstable development builds
|
||||||
@@ -151,7 +150,7 @@ text.save.rename=Rename
|
|||||||
text.save.rename.text=New name:
|
text.save.rename.text=New name:
|
||||||
text.selectslot=Select a save.
|
text.selectslot=Select a save.
|
||||||
text.slot=[accent]Slot {0}
|
text.slot=[accent]Slot {0}
|
||||||
text.save.corrupted=[orange]Save file corrupted or invalid!
|
text.save.corrupted=[orange]Save file corrupted or invalid!\nIf you have just updated your game, this is probably a change in the save format and [scarlet]not[] a bug.
|
||||||
text.empty=<empty>
|
text.empty=<empty>
|
||||||
text.on=On
|
text.on=On
|
||||||
text.off=Off
|
text.off=Off
|
||||||
@@ -266,23 +265,16 @@ text.upgrades=Upgrades
|
|||||||
text.purchased=[LIME]Created!
|
text.purchased=[LIME]Created!
|
||||||
text.weapons=Weapons
|
text.weapons=Weapons
|
||||||
text.paused=Paused
|
text.paused=Paused
|
||||||
text.respawn=Respawning in
|
text.yes=Yes
|
||||||
|
text.no=No
|
||||||
text.info.title=[accent]Info
|
text.info.title=[accent]Info
|
||||||
text.error.title=[crimson]An error has occured
|
text.error.title=[crimson]An error has occured
|
||||||
text.error.crashmessage=[SCARLET]An unexpected error has occured, which would have caused a crash.\n[]Please report the exact circumstances under which this error occured to the developer: \n[ORANGE]anukendev@gmail.com[]
|
text.error.crashmessage=[SCARLET]An unexpected error has occured, which would have caused a crash.\n[]Please report the exact circumstances under which this error occured to the developer: \n[ORANGE]anukendev@gmail.com[]
|
||||||
text.error.crashtitle=An error has occured
|
text.error.crashtitle=An error has occured
|
||||||
text.mode.break=Break mode: {0}
|
|
||||||
text.mode.place=Place mode: {0}
|
|
||||||
placemode.hold.name=line
|
|
||||||
placemode.areadelete.name=area
|
|
||||||
placemode.touchdelete.name=touch
|
|
||||||
placemode.holddelete.name=hold
|
|
||||||
placemode.none.name=none
|
|
||||||
placemode.touch.name=touch
|
|
||||||
placemode.cursor.name=cursor
|
|
||||||
text.blocks.blockinfo=Block Info
|
text.blocks.blockinfo=Block Info
|
||||||
text.blocks.powercapacity=Power Capacity
|
text.blocks.powercapacity=Power Capacity
|
||||||
text.blocks.powershot=Power/Shot
|
text.blocks.powershot=Power/Shot
|
||||||
|
text.blocks.targetsair=Targets Air
|
||||||
text.blocks.itemspeed=Units Moved
|
text.blocks.itemspeed=Units Moved
|
||||||
text.blocks.shootrange=Range
|
text.blocks.shootrange=Range
|
||||||
text.blocks.size=Size
|
text.blocks.size=Size
|
||||||
@@ -541,3 +533,4 @@ block.liquid-tank.name=Liquid Tank
|
|||||||
block.liquid-junction.name=Liquid Junction
|
block.liquid-junction.name=Liquid Junction
|
||||||
block.bridge-conduit.name=Bridge Conduit
|
block.bridge-conduit.name=Bridge Conduit
|
||||||
block.rotary-pump.name=Rotary Pump
|
block.rotary-pump.name=Rotary Pump
|
||||||
|
block.nuclear-reactor.name=Nuclear Reactor
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 131 KiB After Width: | Height: | Size: 131 KiB |
@@ -39,7 +39,7 @@ public class Vars{
|
|||||||
//respawn time in frames
|
//respawn time in frames
|
||||||
public static final float respawnduration = 60*4;
|
public static final float respawnduration = 60*4;
|
||||||
//time between waves in frames (on normal mode)
|
//time between waves in frames (on normal mode)
|
||||||
public static final float wavespace = 60*60*1.5f;
|
public static final float wavespace = 60*60*2f;
|
||||||
//waves can last no longer than 3 minutes, otherwise the next one spawns
|
//waves can last no longer than 3 minutes, otherwise the next one spawns
|
||||||
public static final float maxwavespace = 60*60*4f;
|
public static final float maxwavespace = 60*60*4f;
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ public class Pathfinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean passable(Tile tile, Team team){
|
private boolean passable(Tile tile, Team team){
|
||||||
return (tile.getWallID() == 0 && tile.cliffs == 0 && !tile.floor().solid && !(tile.floor().isLiquid && (tile.floor().damageTaken > 0 || tile.floor().drownTime > 0)))
|
return (tile.getWallID() == 0 && !tile.floor().isLiquid && tile.cliffs == 0 && !tile.floor().solid && !(tile.floor().isLiquid && (tile.floor().damageTaken > 0 || tile.floor().drownTime > 0)))
|
||||||
|| (tile.breakable() && (tile.getTeam() != team)) || !tile.solid();
|
|| (tile.breakable() && (tile.getTeam() != team)) || !tile.solid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,11 +21,13 @@ public class Items implements ContentList{
|
|||||||
tungsten = new Item("tungsten", Color.valueOf("a0b0c8")) {{
|
tungsten = new Item("tungsten", Color.valueOf("a0b0c8")) {{
|
||||||
type = ItemType.material;
|
type = ItemType.material;
|
||||||
hardness = 1;
|
hardness = 1;
|
||||||
|
cost = 0.75f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
lead = new Item("lead", Color.valueOf("8e85a2")) {{
|
lead = new Item("lead", Color.valueOf("8e85a2")) {{
|
||||||
type = ItemType.material;
|
type = ItemType.material;
|
||||||
hardness = 1;
|
hardness = 1;
|
||||||
|
cost = 0.6f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
coal = new Item("coal", Color.valueOf("272727")) {{
|
coal = new Item("coal", Color.valueOf("272727")) {{
|
||||||
@@ -41,6 +43,7 @@ public class Items implements ContentList{
|
|||||||
titanium = new Item("titanium", Color.valueOf("8da1e3")) {{
|
titanium = new Item("titanium", Color.valueOf("8da1e3")) {{
|
||||||
type = ItemType.material;
|
type = ItemType.material;
|
||||||
hardness = 3;
|
hardness = 3;
|
||||||
|
cost = 1.1f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
thorium = new Item("thorium", Color.valueOf("f9a3c7")) {{
|
thorium = new Item("thorium", Color.valueOf("f9a3c7")) {{
|
||||||
@@ -48,20 +51,24 @@ public class Items implements ContentList{
|
|||||||
explosiveness = 0.1f;
|
explosiveness = 0.1f;
|
||||||
hardness = 4;
|
hardness = 4;
|
||||||
radioactivity = 0.5f;
|
radioactivity = 0.5f;
|
||||||
|
cost = 1.2f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
silicon = new Item("silicon", Color.valueOf("53565c")) {{
|
silicon = new Item("silicon", Color.valueOf("53565c")) {{
|
||||||
type = ItemType.material;
|
type = ItemType.material;
|
||||||
|
cost = 0.9f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
plastanium = new Item("plastanium", Color.valueOf("e9ead3")) {{
|
plastanium = new Item("plastanium", Color.valueOf("e9ead3")) {{
|
||||||
type = ItemType.material;
|
type = ItemType.material;
|
||||||
flammability = 0.1f;
|
flammability = 0.1f;
|
||||||
explosiveness = 0.1f;
|
explosiveness = 0.1f;
|
||||||
|
cost = 1.5f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
phasematter = new Item("phase-matter", Color.valueOf("f4ba6e")) {{
|
phasematter = new Item("phase-matter", Color.valueOf("f4ba6e")) {{
|
||||||
type = ItemType.material;
|
type = ItemType.material;
|
||||||
|
cost = 1.5f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
surgealloy = new Item("surge-alloy", Color.valueOf("b4d5c7")) {{
|
surgealloy = new Item("surge-alloy", Color.valueOf("b4d5c7")) {{
|
||||||
|
|||||||
@@ -101,6 +101,8 @@ public class Recipes implements ContentList{
|
|||||||
new Recipe(power, PowerBlocks.solarPanel, new ItemStack(Items.lead, 20), new ItemStack(Items.silicon, 30));
|
new Recipe(power, PowerBlocks.solarPanel, new ItemStack(Items.lead, 20), new ItemStack(Items.silicon, 30));
|
||||||
new Recipe(power, PowerBlocks.largeSolarPanel, new ItemStack(Items.lead, 200), new ItemStack(Items.silicon, 290), new ItemStack(Items.phasematter, 30));
|
new Recipe(power, PowerBlocks.largeSolarPanel, new ItemStack(Items.lead, 200), new ItemStack(Items.silicon, 290), new ItemStack(Items.phasematter, 30));
|
||||||
|
|
||||||
|
//generators - other
|
||||||
|
new Recipe(power, PowerBlocks.nuclearReactor, new ItemStack(Items.lead, 600), new ItemStack(Items.silicon, 400), new ItemStack(Items.carbide, 300), new ItemStack(Items.thorium, 300));
|
||||||
|
|
||||||
//new Recipe(distribution, StorageBlocks.core, new ItemStack(Items.carbide, 50));
|
//new Recipe(distribution, StorageBlocks.core, new ItemStack(Items.carbide, 50));
|
||||||
new Recipe(distribution, StorageBlocks.unloader, new ItemStack(Items.carbide, 40), new ItemStack(Items.silicon, 50));
|
new Recipe(distribution, StorageBlocks.unloader, new ItemStack(Items.carbide, 40), new ItemStack(Items.silicon, 50));
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ public class StatusEffects implements ContentList {
|
|||||||
overdrive = new StatusEffect(6f) {
|
overdrive = new StatusEffect(6f) {
|
||||||
{
|
{
|
||||||
armorMultiplier = 0.95f;
|
armorMultiplier = 0.95f;
|
||||||
speedMultiplier = 1.4f;
|
speedMultiplier = 1.05f;
|
||||||
damageMultiplier = 1.4f;
|
damageMultiplier = 1.4f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public class UnitTypes implements ContentList {
|
|||||||
|
|
||||||
vtol = new UnitType("vtol", Vtol.class, Vtol::new){{
|
vtol = new UnitType("vtol", Vtol.class, Vtol::new){{
|
||||||
speed = 0.3f;
|
speed = 0.3f;
|
||||||
maxVelocity = 2.1f;
|
maxVelocity = 1.9f;
|
||||||
drag = 0.01f;
|
drag = 0.01f;
|
||||||
isFlying = true;
|
isFlying = true;
|
||||||
}};
|
}};
|
||||||
@@ -50,7 +50,7 @@ public class UnitTypes implements ContentList {
|
|||||||
monsoon = new UnitType("monsoon", Monsoon.class, Monsoon::new){{
|
monsoon = new UnitType("monsoon", Monsoon.class, Monsoon::new){{
|
||||||
health = 230;
|
health = 230;
|
||||||
speed = 0.2f;
|
speed = 0.2f;
|
||||||
maxVelocity = 1.5f;
|
maxVelocity = 1.4f;
|
||||||
drag = 0.01f;
|
drag = 0.01f;
|
||||||
isFlying = true;
|
isFlying = true;
|
||||||
weapon = Weapons.bomber;
|
weapon = Weapons.bomber;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public class Weapons implements ContentList {
|
|||||||
|
|
||||||
chainBlaster = new Weapon("chain-blaster") {{
|
chainBlaster = new Weapon("chain-blaster") {{
|
||||||
length = 1.5f;
|
length = 1.5f;
|
||||||
reload = 20f;
|
reload = 30f;
|
||||||
roundrobin = true;
|
roundrobin = true;
|
||||||
ejectEffect = ShootFx.shellEjectSmall;
|
ejectEffect = ShootFx.shellEjectSmall;
|
||||||
setAmmo(AmmoTypes.bulletLead, AmmoTypes.bulletCarbide, AmmoTypes.bulletTungsten, AmmoTypes.bulletSilicon, AmmoTypes.bulletThorium);
|
setAmmo(AmmoTypes.bulletLead, AmmoTypes.bulletCarbide, AmmoTypes.bulletTungsten, AmmoTypes.bulletSilicon, AmmoTypes.bulletThorium);
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ public class Blocks extends BlockList implements ContentList{
|
|||||||
|
|
||||||
for(int i = 1; i <= 6; i ++){
|
for(int i = 1; i <= 6; i ++){
|
||||||
new BuildBlock("build" + i);
|
new BuildBlock("build" + i);
|
||||||
new BreakBlock("break" + i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
space = new Floor("space") {{
|
space = new Floor("space") {{
|
||||||
|
|||||||
@@ -52,9 +52,10 @@ public class CraftingBlocks extends BlockList implements ContentList {
|
|||||||
flameColor = Color.valueOf("ffef99");
|
flameColor = Color.valueOf("ffef99");
|
||||||
}};
|
}};
|
||||||
|
|
||||||
plastaniumCompressor = new PlasteelCompressor("plastanium-compressor") {{
|
plastaniumCompressor = new PlastaniumCompressor("plastanium-compressor") {{
|
||||||
inputLiquid = Liquids.oil;
|
inputLiquid = Liquids.oil;
|
||||||
inputItem = new ItemStack(Items.carbide, 1);
|
inputItem = new ItemStack(Items.titanium, 2);
|
||||||
|
hasItems = true;
|
||||||
liquidUse = 0.3f;
|
liquidUse = 0.3f;
|
||||||
liquidCapacity = 60f;
|
liquidCapacity = 60f;
|
||||||
powerUse = 0.5f;
|
powerUse = 0.5f;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class PowerBlocks extends BlockList implements ContentList {
|
|||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load() {
|
||||||
combustionGenerator = new BurnerGenerator("combustion-generator") {{
|
combustionGenerator = new BurnerGenerator("combustion-generator") {{
|
||||||
powerOutput = 0.06f;
|
powerOutput = 0.09f;
|
||||||
powerCapacity = 40f;
|
powerCapacity = 40f;
|
||||||
itemDuration = 40f;
|
itemDuration = 40f;
|
||||||
}};
|
}};
|
||||||
@@ -22,14 +22,17 @@ public class PowerBlocks extends BlockList implements ContentList {
|
|||||||
maxLiquidGenerate = 0.5f;
|
maxLiquidGenerate = 0.5f;
|
||||||
powerPerLiquid = 0.08f;
|
powerPerLiquid = 0.08f;
|
||||||
powerCapacity = 40f;
|
powerCapacity = 40f;
|
||||||
|
powerPerLiquid = 0.25f;
|
||||||
generateEffect = BlockFx.redgeneratespark;
|
generateEffect = BlockFx.redgeneratespark;
|
||||||
size = 2;
|
size = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
turbineGenerator = new TurbineGenerator("turbine-generator") {{
|
turbineGenerator = new TurbineGenerator("turbine-generator") {{
|
||||||
powerOutput = 0.15f;
|
powerOutput = 0.28f;
|
||||||
powerCapacity = 40f;
|
powerCapacity = 40f;
|
||||||
itemDuration = 30f;
|
itemDuration = 30f;
|
||||||
|
powerPerLiquid = 0.7f;
|
||||||
|
auxLiquidUse = 0.05f;
|
||||||
size = 2;
|
size = 2;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
@@ -50,7 +53,8 @@ public class PowerBlocks extends BlockList implements ContentList {
|
|||||||
|
|
||||||
nuclearReactor = new NuclearReactor("nuclear-reactor") {{
|
nuclearReactor = new NuclearReactor("nuclear-reactor") {{
|
||||||
size = 3;
|
size = 3;
|
||||||
health = 600;
|
health = 700;
|
||||||
|
powerMultiplier = 0.8f;
|
||||||
}};
|
}};
|
||||||
|
|
||||||
fusionReactor = new FusionReactor("fusion-reactor") {{
|
fusionReactor = new FusionReactor("fusion-reactor") {{
|
||||||
|
|||||||
@@ -83,16 +83,17 @@ public class TurretBlocks extends BlockList implements ContentList {
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
lancer = new LaserTurret("lancer") {{
|
lancer = new LaserTurret("lancer") {{
|
||||||
range = 70f;
|
range = 90f;
|
||||||
chargeTime = 70f;
|
chargeTime = 60f;
|
||||||
chargeMaxDelay = 30f;
|
chargeMaxDelay = 30f;
|
||||||
chargeEffects = 7;
|
chargeEffects = 7;
|
||||||
shootType = AmmoTypes.lancerLaser;
|
shootType = AmmoTypes.lancerLaser;
|
||||||
recoil = 2f;
|
recoil = 2f;
|
||||||
reload = 130f;
|
reload = 100f;
|
||||||
cooldown = 0.03f;
|
cooldown = 0.03f;
|
||||||
powerUsed = 20f;
|
powerUsed = 20f;
|
||||||
powerCapacity = 60f;
|
powerCapacity = 60f;
|
||||||
|
shootShake = 2f;
|
||||||
shootEffect = ShootFx.lancerLaserShoot;
|
shootEffect = ShootFx.lancerLaserShoot;
|
||||||
smokeEffect = ShootFx.lancerLaserShootSmoke;
|
smokeEffect = ShootFx.lancerLaserShootSmoke;
|
||||||
chargeEffect = ShootFx.lancerLaserCharge;
|
chargeEffect = ShootFx.lancerLaserCharge;
|
||||||
@@ -131,7 +132,7 @@ public class TurretBlocks extends BlockList implements ContentList {
|
|||||||
|
|
||||||
salvo = new BurstTurret("salvo") {{
|
salvo = new BurstTurret("salvo") {{
|
||||||
size = 2;
|
size = 2;
|
||||||
range = 110f;
|
range = 120f;
|
||||||
ammoTypes = new AmmoType[]{AmmoTypes.bulletTungsten, AmmoTypes.bulletCarbide, AmmoTypes.bulletPyratite, AmmoTypes.bulletThorium, AmmoTypes.bulletSilicon};
|
ammoTypes = new AmmoType[]{AmmoTypes.bulletTungsten, AmmoTypes.bulletCarbide, AmmoTypes.bulletPyratite, AmmoTypes.bulletThorium, AmmoTypes.bulletSilicon};
|
||||||
reload = 40f;
|
reload = 40f;
|
||||||
restitution = 0.03f;
|
restitution = 0.03f;
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ import io.anuke.mindustry.entities.bullet.Bullet;
|
|||||||
import io.anuke.mindustry.entities.bullet.BulletType;
|
import io.anuke.mindustry.entities.bullet.BulletType;
|
||||||
import io.anuke.mindustry.entities.bullet.LiquidBulletType;
|
import io.anuke.mindustry.entities.bullet.LiquidBulletType;
|
||||||
import io.anuke.mindustry.entities.effect.Fire;
|
import io.anuke.mindustry.entities.effect.Fire;
|
||||||
|
import io.anuke.mindustry.entities.effect.ItemDrop;
|
||||||
import io.anuke.mindustry.entities.effect.Lightning;
|
import io.anuke.mindustry.entities.effect.Lightning;
|
||||||
import io.anuke.mindustry.gen.CallEntity;
|
|
||||||
import io.anuke.mindustry.graphics.Palette;
|
import io.anuke.mindustry.graphics.Palette;
|
||||||
import io.anuke.mindustry.type.ContentList;
|
import io.anuke.mindustry.type.ContentList;
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.Item;
|
||||||
@@ -96,7 +96,7 @@ public class TurretBullets extends BulletList implements ContentList {
|
|||||||
Color[] colors = {Palette.lancerLaser.cpy().mul(1f, 1f, 1f, 0.4f), Palette.lancerLaser, Color.WHITE};
|
Color[] colors = {Palette.lancerLaser.cpy().mul(1f, 1f, 1f, 0.4f), Palette.lancerLaser, Color.WHITE};
|
||||||
float[] tscales = {1f, 0.7f, 0.5f, 0.2f};
|
float[] tscales = {1f, 0.7f, 0.5f, 0.2f};
|
||||||
float[] lenscales = {1f, 1.1f, 1.13f, 1.14f};
|
float[] lenscales = {1f, 1.1f, 1.13f, 1.14f};
|
||||||
float length = 70f;
|
float length = 90f;
|
||||||
|
|
||||||
{
|
{
|
||||||
hiteffect = BulletFx.hitLancer;
|
hiteffect = BulletFx.hitLancer;
|
||||||
@@ -258,7 +258,7 @@ public class TurretBullets extends BulletList implements ContentList {
|
|||||||
if(amountDropped > 0){
|
if(amountDropped > 0){
|
||||||
float angle = b.angle() + Mathf.range(100f);
|
float angle = b.angle() + Mathf.range(100f);
|
||||||
float vs = Mathf.random(0f, 4f);
|
float vs = Mathf.random(0f, 4f);
|
||||||
CallEntity.createItemDrop(Item.getByID(i), amountDropped, b.x, b.y, Angles.trnsx(angle, vs), Angles.trnsy(angle, vs));
|
ItemDrop.create(Item.getByID(i), amountDropped, b.x, b.y, Angles.trnsx(angle, vs), Angles.trnsy(angle, vs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package io.anuke.mindustry.core;
|
package io.anuke.mindustry.core;
|
||||||
|
|
||||||
import com.badlogic.gdx.utils.*;
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
import com.badlogic.gdx.utils.ObjectSet;
|
||||||
|
import com.badlogic.gdx.utils.OrderedMap;
|
||||||
|
import com.badlogic.gdx.utils.OrderedSet;
|
||||||
import io.anuke.mindustry.content.*;
|
import io.anuke.mindustry.content.*;
|
||||||
import io.anuke.mindustry.content.blocks.*;
|
import io.anuke.mindustry.content.blocks.*;
|
||||||
import io.anuke.mindustry.content.bullets.*;
|
import io.anuke.mindustry.content.bullets.*;
|
||||||
@@ -28,6 +31,7 @@ public class ContentLoader {
|
|||||||
private static boolean loaded = false;
|
private static boolean loaded = false;
|
||||||
private static ObjectSet<Array<? extends Content>> contentSet = new OrderedSet<>();
|
private static ObjectSet<Array<? extends Content>> contentSet = new OrderedSet<>();
|
||||||
private static OrderedMap<String, Array<Content>> contentMap = new OrderedMap<>();
|
private static OrderedMap<String, Array<Content>> contentMap = new OrderedMap<>();
|
||||||
|
private static ObjectSet<Consumer<Content>> initialization = new ObjectSet<>();
|
||||||
private static ContentList[] content = {
|
private static ContentList[] content = {
|
||||||
//effects
|
//effects
|
||||||
new BlockFx(),
|
new BlockFx(),
|
||||||
@@ -132,11 +136,15 @@ public class ContentLoader {
|
|||||||
|
|
||||||
/**Initializes all content with the specified function.*/
|
/**Initializes all content with the specified function.*/
|
||||||
public static void initialize(Consumer<Content> callable){
|
public static void initialize(Consumer<Content> callable){
|
||||||
|
if(initialization.contains(callable)) return;
|
||||||
|
|
||||||
for(Array<? extends Content> arr : contentSet){
|
for(Array<? extends Content> arr : contentSet){
|
||||||
for(Content content : arr){
|
for(Content content : arr){
|
||||||
callable.accept(content);
|
callable.accept(content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initialization.add(callable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void dispose(){
|
public static void dispose(){
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ import io.anuke.mindustry.entities.TileEntity;
|
|||||||
import io.anuke.mindustry.game.Content;
|
import io.anuke.mindustry.game.Content;
|
||||||
import io.anuke.mindustry.game.ContentDatabase;
|
import io.anuke.mindustry.game.ContentDatabase;
|
||||||
import io.anuke.mindustry.game.EventType.*;
|
import io.anuke.mindustry.game.EventType.*;
|
||||||
import io.anuke.mindustry.input.MobileInput;
|
|
||||||
import io.anuke.mindustry.input.DefaultKeybinds;
|
import io.anuke.mindustry.input.DefaultKeybinds;
|
||||||
import io.anuke.mindustry.input.DesktopInput;
|
import io.anuke.mindustry.input.DesktopInput;
|
||||||
import io.anuke.mindustry.input.InputHandler;
|
import io.anuke.mindustry.input.InputHandler;
|
||||||
|
import io.anuke.mindustry.input.MobileInput;
|
||||||
import io.anuke.mindustry.io.Map;
|
import io.anuke.mindustry.io.Map;
|
||||||
import io.anuke.mindustry.io.Saves;
|
import io.anuke.mindustry.io.Saves;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
@@ -162,7 +162,7 @@ public class Control extends Module{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addPlayer(int index){
|
public void addPlayer(int index){
|
||||||
if(players.length < index + 1){
|
if(players.length != index + 1){
|
||||||
Player[] old = players;
|
Player[] old = players;
|
||||||
players = new Player[index + 1];
|
players = new Player[index + 1];
|
||||||
System.arraycopy(old, 0, players, 0, old.length);
|
System.arraycopy(old, 0, players, 0, old.length);
|
||||||
@@ -285,8 +285,11 @@ public class Control extends Module{
|
|||||||
@Override
|
@Override
|
||||||
public void dispose(){
|
public void dispose(){
|
||||||
Platform.instance.onGameExit();
|
Platform.instance.onGameExit();
|
||||||
|
ContentLoader.dispose();
|
||||||
Net.dispose();
|
Net.dispose();
|
||||||
ui.editor.dispose();
|
ui.editor.dispose();
|
||||||
|
inputs = new InputHandler[]{};
|
||||||
|
players = new Player[]{};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -311,7 +314,7 @@ public class Control extends Module{
|
|||||||
if(!Settings.has("4.0-warning")){
|
if(!Settings.has("4.0-warning")){
|
||||||
Settings.putBool("4.0-warning", true);
|
Settings.putBool("4.0-warning", true);
|
||||||
|
|
||||||
Timers.runTask(5f, () -> {
|
Timers.run(5f, () -> {
|
||||||
FloatingDialog dialog = new FloatingDialog("[orange]WARNING![]");
|
FloatingDialog dialog = new FloatingDialog("[orange]WARNING![]");
|
||||||
dialog.buttons().addButton("$text.ok", dialog::hide).size(100f, 60f);
|
dialog.buttons().addButton("$text.ok", dialog::hide).size(100f, 60f);
|
||||||
dialog.content().add("The beta version you are about to play should be considered very unstable, and is [accent]not representative of the final 4.0 release.[]\n\n " +
|
dialog.content().add("The beta version you are about to play should be considered very unstable, and is [accent]not representative of the final 4.0 release.[]\n\n " +
|
||||||
@@ -321,6 +324,18 @@ public class Control extends Module{
|
|||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!Settings.has("4.0-no-sound")){
|
||||||
|
Settings.putBool("4.0-no-sound", true);
|
||||||
|
|
||||||
|
Timers.run(4f, () -> {
|
||||||
|
FloatingDialog dialog = new FloatingDialog("[orange]Attention![]");
|
||||||
|
dialog.buttons().addButton("$text.ok", dialog::hide).size(100f, 60f);
|
||||||
|
dialog.content().add("You might have noticed that 4.0 does not have any sound.\nThis is [orange]intentional![] Sound will be added in a later update.\n\n[LIGHT_GRAY](now stop reporting this as a bug)").wrap().width(500f);
|
||||||
|
dialog.show();
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Called from main logic thread.*/
|
/**Called from main logic thread.*/
|
||||||
@@ -355,7 +370,7 @@ public class Control extends Module{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//check unlocks every 2 seconds
|
//check unlocks every 2 seconds
|
||||||
if(!state.mode.infiniteResources && !state.mode.disableWaveTimer && Timers.get("timerCheckUnlock", 120)){
|
if(!state.mode.infiniteResources && Timers.get("timerCheckUnlock", 120)){
|
||||||
checkUnlockableBlocks();
|
checkUnlockableBlocks();
|
||||||
|
|
||||||
//save if the db changed, but don't save unlocks
|
//save if the db changed, but don't save unlocks
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ public class GameState{
|
|||||||
|
|
||||||
public int wave = 1;
|
public int wave = 1;
|
||||||
public float wavetime;
|
public float wavetime;
|
||||||
public float extrawavetime;
|
|
||||||
public int enemies = 0;
|
|
||||||
public boolean gameOver = false;
|
public boolean gameOver = false;
|
||||||
public GameMode mode = GameMode.waves;
|
public GameMode mode = GameMode.waves;
|
||||||
public Difficulty difficulty = Difficulty.normal;
|
public Difficulty difficulty = Difficulty.normal;
|
||||||
|
|||||||
@@ -70,9 +70,7 @@ public class Logic extends Module {
|
|||||||
|
|
||||||
public void reset(){
|
public void reset(){
|
||||||
state.wave = 1;
|
state.wave = 1;
|
||||||
state.extrawavetime = maxwavespace * state.difficulty.maxTimeScaling;
|
|
||||||
state.wavetime = wavespace * state.difficulty.timeScaling;
|
state.wavetime = wavespace * state.difficulty.timeScaling;
|
||||||
state.enemies = 0;
|
|
||||||
state.gameOver = false;
|
state.gameOver = false;
|
||||||
state.teams = new TeamInfo();
|
state.teams = new TeamInfo();
|
||||||
state.teams.add(Team.blue, true);
|
state.teams.add(Team.blue, true);
|
||||||
@@ -89,7 +87,6 @@ public class Logic extends Module {
|
|||||||
state.spawner.spawnEnemies();
|
state.spawner.spawnEnemies();
|
||||||
state.wave ++;
|
state.wave ++;
|
||||||
state.wavetime = wavespace * state.difficulty.timeScaling;
|
state.wavetime = wavespace * state.difficulty.timeScaling;
|
||||||
state.extrawavetime = maxwavespace * state.difficulty.maxTimeScaling;
|
|
||||||
|
|
||||||
Events.fire(WaveEvent.class);
|
Events.fire(WaveEvent.class);
|
||||||
}
|
}
|
||||||
@@ -133,15 +130,10 @@ public class Logic extends Module {
|
|||||||
if(!state.is(State.paused) || Net.active()){
|
if(!state.is(State.paused) || Net.active()){
|
||||||
|
|
||||||
if(!state.mode.disableWaveTimer){
|
if(!state.mode.disableWaveTimer){
|
||||||
|
state.wavetime -= Timers.delta();
|
||||||
if(state.enemies <= 0){
|
|
||||||
if(!world.getMap().name.equals("tutorial")) state.wavetime -= Timers.delta();
|
|
||||||
}else{
|
|
||||||
state.extrawavetime -= Timers.delta();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!Net.client() && (state.wavetime <= 0 || state.extrawavetime <= 0)){
|
if(!Net.client() && state.wavetime <= 0){
|
||||||
runWave();
|
runWave();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -219,6 +219,7 @@ public class NetClient extends Module {
|
|||||||
new Random().nextBytes(bytes);
|
new Random().nextBytes(bytes);
|
||||||
String result = new String(Base64Coder.encode(bytes));
|
String result = new String(Base64Coder.encode(bytes));
|
||||||
Settings.putString("usid-" + ip, result);
|
Settings.putString("usid-" + ip, result);
|
||||||
|
Settings.save();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -352,8 +353,10 @@ public class NetClient extends Module {
|
|||||||
if(entity == null){
|
if(entity == null){
|
||||||
entity = (SyncTrait) TypeTrait.getTypeByID(typeID).get(); //create entity from supplier
|
entity = (SyncTrait) TypeTrait.getTypeByID(typeID).get(); //create entity from supplier
|
||||||
entity.resetID(id);
|
entity.resetID(id);
|
||||||
|
if(!netClient.isEntityUsed(entity.getID())){
|
||||||
add = true;
|
add = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//read the entity
|
//read the entity
|
||||||
entity.read(input, timestamp);
|
entity.read(input, timestamp);
|
||||||
@@ -363,7 +366,7 @@ public class NetClient extends Module {
|
|||||||
throw new RuntimeException("Error reading entity of type '"+ group.getType() + "': Read length mismatch [write=" + readLength + ", read=" + (netClient.byteStream.position() - position - 1)+ "]");
|
throw new RuntimeException("Error reading entity of type '"+ group.getType() + "': Read length mismatch [write=" + readLength + ", read=" + (netClient.byteStream.position() - position - 1)+ "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(add && !netClient.isEntityUsed(entity.getID())){
|
if(add){
|
||||||
entity.add();
|
entity.add();
|
||||||
netClient.addRemovedEntity(entity.getID());
|
netClient.addRemovedEntity(entity.getID());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ public class NetServer extends Module{
|
|||||||
NetConnection connection = Net.getConnection(id);
|
NetConnection connection = Net.getConnection(id);
|
||||||
if(player == null || connection == null || packet.snapid < connection.lastRecievedClientSnapshot) return;
|
if(player == null || connection == null || packet.snapid < connection.lastRecievedClientSnapshot) return;
|
||||||
|
|
||||||
boolean verifyPosition = !player.isDead() && !debug && headless && !player.mech.flying;
|
boolean verifyPosition = !player.isDead() && !debug && headless && !player.mech.flying && player.getCarrier() == null;
|
||||||
|
|
||||||
if(connection.lastRecievedClientTime == 0) connection.lastRecievedClientTime = TimeUtils.millis() - 16;
|
if(connection.lastRecievedClientTime == 0) connection.lastRecievedClientTime = TimeUtils.millis() - 16;
|
||||||
|
|
||||||
@@ -191,6 +191,10 @@ public class NetServer extends Module{
|
|||||||
player.setMineTile(packet.mining);
|
player.setMineTile(packet.mining);
|
||||||
player.isBoosting = packet.boosting;
|
player.isBoosting = packet.boosting;
|
||||||
player.isShooting = packet.shooting;
|
player.isShooting = packet.shooting;
|
||||||
|
player.getPlaceQueue().clear();
|
||||||
|
if(packet.currentRequest != null){
|
||||||
|
player.getPlaceQueue().addLast(packet.currentRequest);
|
||||||
|
}
|
||||||
|
|
||||||
vector.set(packet.x - player.getInterpolator().target.x, packet.y - player.getInterpolator().target.y);
|
vector.set(packet.x - player.getInterpolator().target.x, packet.y - player.getInterpolator().target.y);
|
||||||
|
|
||||||
@@ -485,14 +489,18 @@ public class NetServer extends Module{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(other == null || other.isAdmin){
|
if(other == null || (other.isAdmin && other != player)){ //fun fact: this means you can ban yourself
|
||||||
Log.err("{0} attempted to perform admin action on nonexistant or admin player.", player.name);
|
Log.err("{0} attempted to perform admin action on nonexistant or admin player.", player.name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ip = player.con.address;
|
String ip = player.con.address;
|
||||||
|
|
||||||
if(action == AdminAction.ban){
|
if(action == AdminAction.wave) {
|
||||||
|
//no verification is done, so admins can hypothetically spam waves
|
||||||
|
//not a real issue, because server owners may want to do just that
|
||||||
|
state.wavetime = 0f;
|
||||||
|
}else if(action == AdminAction.ban){
|
||||||
netServer.admins.banPlayerIP(ip);
|
netServer.admins.banPlayerIP(ip);
|
||||||
netServer.kick(other.con.id, KickReason.banned);
|
netServer.kick(other.con.id, KickReason.banned);
|
||||||
Log.info("&lc{0} has banned {1}.", player.name, other.name);
|
Log.info("&lc{0} has banned {1}.", player.name, other.name);
|
||||||
|
|||||||
@@ -192,10 +192,7 @@ public class Renderer extends RendererModule{
|
|||||||
|
|
||||||
batch.setProjectionMatrix(camera.combined);
|
batch.setProjectionMatrix(camera.combined);
|
||||||
|
|
||||||
if(pixelate)
|
|
||||||
Graphics.surface(pixelSurface, false);
|
Graphics.surface(pixelSurface, false);
|
||||||
else
|
|
||||||
batch.begin();
|
|
||||||
|
|
||||||
drawPadding();
|
drawPadding();
|
||||||
|
|
||||||
@@ -222,6 +219,7 @@ public class Renderer extends RendererModule{
|
|||||||
Graphics.endShaders();
|
Graphics.endShaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
drawAllTeams(false);
|
drawAllTeams(false);
|
||||||
|
|
||||||
blocks.skipLayer(Layer.turret);
|
blocks.skipLayer(Layer.turret);
|
||||||
@@ -236,18 +234,21 @@ public class Renderer extends RendererModule{
|
|||||||
drawAndInterpolate(playerGroup, p -> true, Player::drawBuildRequests);
|
drawAndInterpolate(playerGroup, p -> true, Player::drawBuildRequests);
|
||||||
overlays.drawTop();
|
overlays.drawTop();
|
||||||
|
|
||||||
if(pixelate)
|
|
||||||
Graphics.flushSurface();
|
Graphics.flushSurface();
|
||||||
|
|
||||||
if(showPaths && debug) drawDebug();
|
if(showPaths && debug) drawDebug();
|
||||||
|
|
||||||
drawAndInterpolate(playerGroup, p -> !p.isLocal && !p.isDead(), Player::drawName);
|
|
||||||
|
|
||||||
batch.end();
|
batch.end();
|
||||||
|
|
||||||
if(showFog){
|
if(showFog){
|
||||||
fog.draw();
|
fog.draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
batch.begin();
|
||||||
|
EntityDraw.setClip(false);
|
||||||
|
drawAndInterpolate(playerGroup, p -> !p.isDead() && !p.isLocal, Player::drawName);
|
||||||
|
EntityDraw.setClip(true);
|
||||||
|
batch.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawAllTeams(boolean flying){
|
private void drawAllTeams(boolean flying){
|
||||||
@@ -257,7 +258,7 @@ public class Renderer extends RendererModule{
|
|||||||
if(group.count(p -> p.isFlying() == flying) +
|
if(group.count(p -> p.isFlying() == flying) +
|
||||||
playerGroup.count(p -> p.isFlying() == flying && p.getTeam() == team) == 0 && flying) continue;
|
playerGroup.count(p -> p.isFlying() == flying && p.getTeam() == team) == 0 && flying) continue;
|
||||||
|
|
||||||
drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying, Unit::drawUnder);
|
drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawUnder);
|
||||||
drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawUnder);
|
drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawUnder);
|
||||||
|
|
||||||
Shaders.outline.color.set(team.color);
|
Shaders.outline.color.set(team.color);
|
||||||
@@ -265,13 +266,13 @@ public class Renderer extends RendererModule{
|
|||||||
|
|
||||||
Graphics.beginShaders(Shaders.outline);
|
Graphics.beginShaders(Shaders.outline);
|
||||||
Graphics.shader(Shaders.mix, true);
|
Graphics.shader(Shaders.mix, true);
|
||||||
drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying);
|
drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead());
|
||||||
drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team);
|
drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team);
|
||||||
Graphics.shader();
|
Graphics.shader();
|
||||||
blocks.drawTeamBlocks(Layer.turret, team);
|
blocks.drawTeamBlocks(Layer.turret, team);
|
||||||
Graphics.endShaders();
|
Graphics.endShaders();
|
||||||
|
|
||||||
drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying, Unit::drawOver);
|
drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawOver);
|
||||||
drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawOver);
|
drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawOver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -306,12 +307,19 @@ public class Renderer extends RendererModule{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO extremely hacky
|
||||||
|
if(t instanceof Player && ((Player) t).getCarry() != null && ((Player) t).getCarry() instanceof Player && ((Player) ((Player) t).getCarry()).isLocal){
|
||||||
|
((Player) t).x = ((Player) t).getCarry().getX();
|
||||||
|
((Player) t).y = ((Player) t).getCarry().getY();
|
||||||
|
}
|
||||||
|
|
||||||
drawer.accept(t);
|
drawer.accept(t);
|
||||||
|
|
||||||
if(threads.doInterpolate() && threads.isEnabled()) {
|
|
||||||
t.setX(lastx);
|
t.setX(lastx);
|
||||||
t.setY(lasty);
|
t.setY(lasty);
|
||||||
|
|
||||||
|
if(threads.doInterpolate() && threads.isEnabled()) {
|
||||||
|
|
||||||
if (t instanceof SolidTrait) {
|
if (t instanceof SolidTrait) {
|
||||||
((SolidTrait) t).setRotation(lastrot);
|
((SolidTrait) t).setRotation(lastrot);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ public class ThreadHandler {
|
|||||||
private final Array<Runnable> toRun = new Array<>();
|
private final Array<Runnable> toRun = new Array<>();
|
||||||
private final ThreadProvider impl;
|
private final ThreadProvider impl;
|
||||||
private float delta = 1f;
|
private float delta = 1f;
|
||||||
private long frame = 0;
|
private float smoothDelta = 1f;
|
||||||
|
private long frame = 0, lastDeltaUpdate;
|
||||||
private float framesSinceUpdate;
|
private float framesSinceUpdate;
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
|
|
||||||
@@ -29,7 +30,7 @@ public class ThreadHandler {
|
|||||||
|
|
||||||
Timers.setDeltaProvider(() -> {
|
Timers.setDeltaProvider(() -> {
|
||||||
float result = impl.isOnThread() ? delta : Gdx.graphics.getDeltaTime()*60f;
|
float result = impl.isOnThread() ? delta : Gdx.graphics.getDeltaTime()*60f;
|
||||||
return Math.min(Float.isNaN(result) ? 1f : result, 12f);
|
return Math.min(Float.isNaN(result) ? 1f : result, 15f);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +63,7 @@ public class ThreadHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getTPS(){
|
public int getTPS(){
|
||||||
return (int)(60/delta);
|
return (int)(60/smoothDelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getFrameID(){
|
public long getFrameID(){
|
||||||
@@ -138,8 +139,6 @@ public class ThreadHandler {
|
|||||||
long elapsed = TimeUtils.nanosToMillis(TimeUtils.timeSinceNanos(time));
|
long elapsed = TimeUtils.nanosToMillis(TimeUtils.timeSinceNanos(time));
|
||||||
long target = (long) ((1000) / 60f);
|
long target = (long) ((1000) / 60f);
|
||||||
|
|
||||||
delta = Math.max(elapsed, target) / 1000f * 60f;
|
|
||||||
|
|
||||||
if (elapsed < target) {
|
if (elapsed < target) {
|
||||||
impl.sleep(target - elapsed);
|
impl.sleep(target - elapsed);
|
||||||
}
|
}
|
||||||
@@ -151,6 +150,14 @@ public class ThreadHandler {
|
|||||||
rendered = false;
|
rendered = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
long actuallyElapsed = TimeUtils.nanosToMillis(TimeUtils.timeSinceNanos(time));
|
||||||
|
delta = Math.max(actuallyElapsed, target) / 1000f * 60f;
|
||||||
|
|
||||||
|
if(TimeUtils.timeSinceMillis(lastDeltaUpdate) > 1000){
|
||||||
|
lastDeltaUpdate = TimeUtils.millis();
|
||||||
|
smoothDelta = delta;
|
||||||
|
}
|
||||||
|
|
||||||
frame ++;
|
frame ++;
|
||||||
framesSinceUpdate = 0;
|
framesSinceUpdate = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,8 +92,6 @@ public class UI extends SceneModule{
|
|||||||
|
|
||||||
Settings.setErrorHandler(()-> Timers.run(1f, ()-> showError("[crimson]Failed to access local storage.\nSettings will not be saved.")));
|
Settings.setErrorHandler(()-> Timers.run(1f, ()-> showError("[crimson]Failed to access local storage.\nSettings will not be saved.")));
|
||||||
|
|
||||||
Settings.defaults("pixelate", true);
|
|
||||||
|
|
||||||
Dialog.closePadR = -1;
|
Dialog.closePadR = -1;
|
||||||
Dialog.closePadT = 5;
|
Dialog.closePadT = 5;
|
||||||
|
|
||||||
|
|||||||
@@ -100,6 +100,10 @@ public class World extends Module{
|
|||||||
return tiles[0].length;
|
return tiles[0].length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int toPacked(int x, int y){
|
||||||
|
return x + y *width();
|
||||||
|
}
|
||||||
|
|
||||||
public Tile tile(int packed){
|
public Tile tile(int packed){
|
||||||
return tiles == null ? null : tile(packed % width(), packed / width());
|
return tiles == null ? null : tile(packed % width(), packed / width());
|
||||||
}
|
}
|
||||||
@@ -112,6 +116,10 @@ public class World extends Module{
|
|||||||
return tiles[x][y];
|
return tiles[x][y];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Tile rawTile(int x, int y){
|
||||||
|
return tiles[x][y];
|
||||||
|
}
|
||||||
|
|
||||||
public Tile tileWorld(float x, float y){
|
public Tile tileWorld(float x, float y){
|
||||||
return tile(Mathf.scl2(x, tilesize), Mathf.scl2(y, tilesize));
|
return tile(Mathf.scl2(x, tilesize), Mathf.scl2(y, tilesize));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -268,6 +268,11 @@ public class MapEditor{
|
|||||||
|
|
||||||
public void resize(int width, int height){
|
public void resize(int width, int height){
|
||||||
map = new MapTileData(width, height);
|
map = new MapTileData(width, height);
|
||||||
|
for (int x = 0; x < map.width(); x++) {
|
||||||
|
for (int y = 0; y < map.height(); y++) {
|
||||||
|
map.write(x, y, DataPosition.floor, (byte)Blocks.stone.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
renderer.resize(width, height);
|
renderer.resize(width, height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -369,8 +369,8 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
public void updateSelectedBlock(){
|
public void updateSelectedBlock(){
|
||||||
Block block = editor.getDrawBlock();
|
Block block = editor.getDrawBlock();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(Block test : Block.all()){
|
for(int j = 0; j < Block.all().size; j ++){
|
||||||
if(block == test){
|
if(block.id == j){
|
||||||
blockgroup.getButtons().get(i).setChecked(true);
|
blockgroup.getButtons().get(i).setChecked(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ public class MapRenderer implements Disposable{
|
|||||||
while(it.hasNext){
|
while(it.hasNext){
|
||||||
int i = it.next();
|
int i = it.next();
|
||||||
int x = i % width;
|
int x = i % width;
|
||||||
int y = i / height;
|
int y = i / width;
|
||||||
render(x, y);
|
render(x, y);
|
||||||
}
|
}
|
||||||
updates.clear();
|
updates.clear();
|
||||||
|
|||||||
@@ -30,10 +30,7 @@ import io.anuke.ucore.entities.EntityGroup;
|
|||||||
import io.anuke.ucore.entities.trait.SolidTrait;
|
import io.anuke.ucore.entities.trait.SolidTrait;
|
||||||
import io.anuke.ucore.graphics.Draw;
|
import io.anuke.ucore.graphics.Draw;
|
||||||
import io.anuke.ucore.graphics.Lines;
|
import io.anuke.ucore.graphics.Lines;
|
||||||
import io.anuke.ucore.util.Angles;
|
import io.anuke.ucore.util.*;
|
||||||
import io.anuke.ucore.util.Mathf;
|
|
||||||
import io.anuke.ucore.util.ThreadQueue;
|
|
||||||
import io.anuke.ucore.util.Timer;
|
|
||||||
|
|
||||||
import java.io.DataInput;
|
import java.io.DataInput;
|
||||||
import java.io.DataOutput;
|
import java.io.DataOutput;
|
||||||
@@ -58,6 +55,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
|||||||
public float boostHeat;
|
public float boostHeat;
|
||||||
public Color color = new Color();
|
public Color color = new Color();
|
||||||
public Mech mech;
|
public Mech mech;
|
||||||
|
public int spawner;
|
||||||
|
|
||||||
public NetConnection con;
|
public NetConnection con;
|
||||||
public int playerIndex = 0;
|
public int playerIndex = 0;
|
||||||
@@ -66,7 +64,6 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
|||||||
public TargetTrait target;
|
public TargetTrait target;
|
||||||
public TargetTrait moveTarget;
|
public TargetTrait moveTarget;
|
||||||
|
|
||||||
private boolean respawning;
|
|
||||||
private float walktime;
|
private float walktime;
|
||||||
private Queue<BuildRequest> placeQueue = new ThreadQueue<>();
|
private Queue<BuildRequest> placeQueue = new ThreadQueue<>();
|
||||||
private Tile mining;
|
private Tile mining;
|
||||||
@@ -178,6 +175,11 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
|||||||
return mech.weapon.getAmmoType(item) != null && inventory.canAcceptAmmo(mech.weapon.getAmmoType(item));
|
return mech.weapon.getAmmoType(item) != null && inventory.canAcceptAmmo(mech.weapon.getAmmoType(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void added() {
|
||||||
|
baseRotation = 90f;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addAmmo(Item item) {
|
public void addAmmo(Item item) {
|
||||||
inventory.addAmmo(mech.weapon.getAmmoType(item));
|
inventory.addAmmo(mech.weapon.getAmmoType(item));
|
||||||
@@ -202,7 +204,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
|||||||
public void damage(float amount){
|
public void damage(float amount){
|
||||||
CallEntity.onPlayerDamage(this, calculateDamage(amount));
|
CallEntity.onPlayerDamage(this, calculateDamage(amount));
|
||||||
|
|
||||||
if(health <= 0 && !dead && isLocal){
|
if(health <= 0 && !dead){
|
||||||
CallEntity.onPlayerDeath(this);
|
CallEntity.onPlayerDeath(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -225,7 +227,6 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
|||||||
if(player == null) return;
|
if(player == null) return;
|
||||||
|
|
||||||
player.dead = true;
|
player.dead = true;
|
||||||
player.respawning = false;
|
|
||||||
player.placeQueue.clear();
|
player.placeQueue.clear();
|
||||||
|
|
||||||
player.dropCarry();
|
player.dropCarry();
|
||||||
@@ -438,12 +439,10 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
|||||||
if(isDead()){
|
if(isDead()){
|
||||||
isBoosting = false;
|
isBoosting = false;
|
||||||
boostHeat = 0f;
|
boostHeat = 0f;
|
||||||
CoreEntity entity = (CoreEntity)getClosestCore();
|
updateRespawning();
|
||||||
|
|
||||||
if (!respawning && entity != null) {
|
|
||||||
entity.trySetPlayer(this);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
|
}else{
|
||||||
|
spawner = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isLocal){
|
if(!isLocal){
|
||||||
@@ -451,6 +450,11 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
|||||||
updateBuilding(this); //building happens even with non-locals
|
updateBuilding(this); //building happens even with non-locals
|
||||||
status.update(this); //status effect updating also happens with non locals for effect purposes
|
status.update(this); //status effect updating also happens with non locals for effect purposes
|
||||||
|
|
||||||
|
if(getCarrier() != null){
|
||||||
|
x = getCarrier().getX();
|
||||||
|
y = getCarrier().getY();
|
||||||
|
}
|
||||||
|
|
||||||
if(Net.server()){
|
if(Net.server()){
|
||||||
updateShooting(); //server simulates player shooting
|
updateShooting(); //server simulates player shooting
|
||||||
}
|
}
|
||||||
@@ -532,11 +536,16 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
|||||||
|
|
||||||
movement.limit(speed);
|
movement.limit(speed);
|
||||||
|
|
||||||
|
if(getCarrier() == null){
|
||||||
velocity.add(movement);
|
velocity.add(movement);
|
||||||
|
|
||||||
float prex = x, prey = y;
|
float prex = x, prey = y;
|
||||||
updateVelocityStatus(mech.drag, 10f);
|
updateVelocityStatus(mech.drag, 10f);
|
||||||
moved = distanceTo(prex, prey) > 0.01f;
|
moved = distanceTo(prex, prey) > 0.01f;
|
||||||
|
}else{
|
||||||
|
velocity.setZero();
|
||||||
|
x = Mathf.lerpDelta(x, getCarrier().getX(), 0.1f);
|
||||||
|
y = Mathf.lerpDelta(y, getCarrier().getY(), 0.1f);
|
||||||
|
}
|
||||||
|
|
||||||
if(!isShooting()){
|
if(!isShooting()){
|
||||||
if(!movement.isZero()) {
|
if(!movement.isZero()) {
|
||||||
@@ -610,7 +619,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
|||||||
if (target == null) {
|
if (target == null) {
|
||||||
isShooting = false;
|
isShooting = false;
|
||||||
target = Units.getClosestTarget(team, x, y, inventory.getAmmoRange());
|
target = Units.getClosestTarget(team, x, y, inventory.getAmmoRange());
|
||||||
} else {
|
} else if(target.isValid()){
|
||||||
//rotate toward and shoot the target
|
//rotate toward and shoot the target
|
||||||
rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.2f);
|
rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.2f);
|
||||||
|
|
||||||
@@ -649,7 +658,6 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
|||||||
inventory.clear();
|
inventory.clear();
|
||||||
placeQueue.clear();
|
placeQueue.clear();
|
||||||
dead = true;
|
dead = true;
|
||||||
respawning = false;
|
|
||||||
trail.clear();
|
trail.clear();
|
||||||
health = maxHealth();
|
health = maxHealth();
|
||||||
|
|
||||||
@@ -660,12 +668,21 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
|||||||
return isShooting && inventory.hasAmmo() && (!isBoosting || mech.flying);
|
return isShooting && inventory.hasAmmo() && (!isBoosting || mech.flying);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRespawning(){
|
public void updateRespawning(){
|
||||||
respawning = true;
|
|
||||||
|
if (spawner != -1 && world.tile(spawner) != null && world.tile(spawner).entity instanceof SpawnerTrait) {
|
||||||
|
((SpawnerTrait) world.tile(spawner).entity).updateSpawning(this);
|
||||||
|
}else{
|
||||||
|
CoreEntity entity = (CoreEntity)getClosestCore();
|
||||||
|
if(entity != null){
|
||||||
|
this.spawner = entity.tile.id();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRespawning(boolean respawning){
|
public void beginRespawning(SpawnerTrait spawner){
|
||||||
this.respawning = respawning;
|
this.spawner = spawner.getTile().packedPosition();
|
||||||
|
this.dead = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -697,12 +714,18 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
|||||||
public void readSave(DataInput stream) throws IOException {
|
public void readSave(DataInput stream) throws IOException {
|
||||||
boolean local = stream.readBoolean();
|
boolean local = stream.readBoolean();
|
||||||
|
|
||||||
if(local){
|
if(local && !headless){
|
||||||
byte mechid = stream.readByte();
|
byte mechid = stream.readByte();
|
||||||
int index = stream.readByte();
|
int index = stream.readByte();
|
||||||
players[index].readSaveSuper(stream);
|
players[index].readSaveSuper(stream);
|
||||||
players[index].mech = Upgrade.getByID(mechid);
|
players[index].mech = Upgrade.getByID(mechid);
|
||||||
players[index].dead = false;
|
players[index].dead = false;
|
||||||
|
}else if(local){
|
||||||
|
byte mechid = stream.readByte();
|
||||||
|
stream.readByte();
|
||||||
|
readSaveSuper(stream);
|
||||||
|
mech = Upgrade.getByID(mechid);
|
||||||
|
dead = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -722,6 +745,9 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
|||||||
buffer.writeByte(mech.id);
|
buffer.writeByte(mech.id);
|
||||||
buffer.writeBoolean(isBoosting);
|
buffer.writeBoolean(isBoosting);
|
||||||
buffer.writeInt(mining == null ? -1 : mining.packedPosition());
|
buffer.writeInt(mining == null ? -1 : mining.packedPosition());
|
||||||
|
buffer.writeInt(spawner);
|
||||||
|
|
||||||
|
writeBuilding(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -735,6 +761,10 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
|||||||
mech = Upgrade.getByID(buffer.readByte());
|
mech = Upgrade.getByID(buffer.readByte());
|
||||||
boolean boosting = buffer.readBoolean();
|
boolean boosting = buffer.readBoolean();
|
||||||
int mine = buffer.readInt();
|
int mine = buffer.readInt();
|
||||||
|
spawner = buffer.readInt();
|
||||||
|
|
||||||
|
readBuilding(buffer, !isLocal);
|
||||||
|
|
||||||
interpolator.read(lastx, lasty, x, y, time, rotation);
|
interpolator.read(lastx, lasty, x, y, time, rotation);
|
||||||
rotation = lastrot;
|
rotation = lastrot;
|
||||||
|
|
||||||
|
|||||||
@@ -131,6 +131,10 @@ public class TileEntity extends BaseEntity implements TargetTrait {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Tile getTile(){
|
||||||
|
return tile;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Team getTeam() {
|
public Team getTeam() {
|
||||||
return tile.getTeam();
|
return tile.getTeam();
|
||||||
|
|||||||
@@ -132,6 +132,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
@Override
|
@Override
|
||||||
public void readSave(DataInput stream) throws IOException {
|
public void readSave(DataInput stream) throws IOException {
|
||||||
byte team = stream.readByte();
|
byte team = stream.readByte();
|
||||||
|
boolean dead = stream.readBoolean();
|
||||||
float x = stream.readFloat();
|
float x = stream.readFloat();
|
||||||
float y = stream.readFloat();
|
float y = stream.readFloat();
|
||||||
byte xv = stream.readByte();
|
byte xv = stream.readByte();
|
||||||
@@ -141,6 +142,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
|
|
||||||
this.status.readSave(stream);
|
this.status.readSave(stream);
|
||||||
this.inventory.readSave(stream);
|
this.inventory.readSave(stream);
|
||||||
|
this.dead = dead;
|
||||||
this.team = Team.all[team];
|
this.team = Team.all[team];
|
||||||
this.health = health;
|
this.health = health;
|
||||||
this.x = x;
|
this.x = x;
|
||||||
@@ -151,6 +153,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
|
|
||||||
public void writeSave(DataOutput stream, boolean net) throws IOException {
|
public void writeSave(DataOutput stream, boolean net) throws IOException {
|
||||||
stream.writeByte(team.ordinal());
|
stream.writeByte(team.ordinal());
|
||||||
|
stream.writeBoolean(isDead());
|
||||||
stream.writeFloat(net ? interpolator.target.x : x);
|
stream.writeFloat(net ? interpolator.target.x : x);
|
||||||
stream.writeFloat(net ? interpolator.target.y : y);
|
stream.writeFloat(net ? interpolator.target.y : y);
|
||||||
stream.writeByte((byte)(Mathf.clamp(velocity.x, -maxAbsVelocity, maxAbsVelocity) * velocityPercision));
|
stream.writeByte((byte)(Mathf.clamp(velocity.x, -maxAbsVelocity, maxAbsVelocity) * velocityPercision));
|
||||||
@@ -196,7 +199,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
public void avoidOthers(float avoidRange){
|
public void avoidOthers(float avoidRange){
|
||||||
|
|
||||||
EntityPhysics.getNearby(getGroup(), x, y, avoidRange*2f, t -> {
|
EntityPhysics.getNearby(getGroup(), x, y, avoidRange*2f, t -> {
|
||||||
if(t == this || (t instanceof Unit && (((Unit) t).isDead() || (((Unit) t).isFlying() != isFlying())))) return;
|
if(t == this || (t instanceof Unit && (((Unit) t).isDead() || (((Unit) t).isFlying() != isFlying()) || ((Unit) t).getCarrier() == this) || getCarrier() == t)) return;
|
||||||
float dst = distanceTo(t);
|
float dst = distanceTo(t);
|
||||||
if(dst > avoidRange) return;
|
if(dst > avoidRange) return;
|
||||||
velocity.add(moveVector.set(x, y).sub(t.getX(), t.getY()).setLength(1f * (1f - (dst / avoidRange))));
|
velocity.add(moveVector.set(x, y).sub(t.getX(), t.getY()).setLength(1f * (1f - (dst / avoidRange))));
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable
|
|||||||
|
|
||||||
/**Start a fire on the tile. If there already is a file there, refreshes its lifetime.*/
|
/**Start a fire on the tile. If there already is a file there, refreshes its lifetime.*/
|
||||||
public static void create(Tile tile){
|
public static void create(Tile tile){
|
||||||
if(Net.client()) return; //not clientside.
|
if(Net.client() || tile == null) return; //not clientside.
|
||||||
|
|
||||||
Fire fire = map.get(tile.packedPosition());
|
Fire fire = map.get(tile.packedPosition());
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable
|
|||||||
|
|
||||||
/**Attempts to extinguish a fire by shortening its life. If there is no fire here, does nothing.*/
|
/**Attempts to extinguish a fire by shortening its life. If there is no fire here, does nothing.*/
|
||||||
public static void extinguish(Tile tile, float intensity) {
|
public static void extinguish(Tile tile, float intensity) {
|
||||||
if (map.containsKey(tile.packedPosition())) {
|
if (tile != null && map.containsKey(tile.packedPosition())) {
|
||||||
map.get(tile.packedPosition()).time += intensity * Timers.delta();
|
map.get(tile.packedPosition()).time += intensity * Timers.delta();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,8 +57,7 @@ public class ItemDrop extends SolidEntity implements SaveTrait, SyncTrait, DrawT
|
|||||||
return drop;
|
return drop;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(called = Loc.server, in = In.entities)
|
public static void create(Item item, int amount, float x, float y, float velocityX, float velocityY){
|
||||||
public static void createItemDrop(Item item, int amount, float x, float y, float velocityX, float velocityY){
|
|
||||||
create(item, amount, x, y, 0).getVelocity().set(velocityX, velocityY);
|
create(item, amount, x, y, 0).getVelocity().set(velocityX, velocityY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,6 +68,9 @@ public class ItemDrop extends SolidEntity implements SaveTrait, SyncTrait, DrawT
|
|||||||
Effects.effect(UnitFx.pickup, drop);
|
Effects.effect(UnitFx.pickup, drop);
|
||||||
}
|
}
|
||||||
itemGroup.removeByID(itemid);
|
itemGroup.removeByID(itemid);
|
||||||
|
if(Net.client()){
|
||||||
|
netClient.addRemovedEntity(itemid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Internal use only!*/
|
/**Internal use only!*/
|
||||||
|
|||||||
@@ -8,25 +8,29 @@ import io.anuke.mindustry.content.fx.BlockFx;
|
|||||||
import io.anuke.mindustry.entities.Player;
|
import io.anuke.mindustry.entities.Player;
|
||||||
import io.anuke.mindustry.entities.TileEntity;
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
import io.anuke.mindustry.entities.Unit;
|
import io.anuke.mindustry.entities.Unit;
|
||||||
import io.anuke.mindustry.gen.CallBlocks;
|
|
||||||
import io.anuke.mindustry.gen.CallEntity;
|
import io.anuke.mindustry.gen.CallEntity;
|
||||||
import io.anuke.mindustry.graphics.Palette;
|
import io.anuke.mindustry.graphics.Palette;
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.Item;
|
||||||
import io.anuke.mindustry.type.Recipe;
|
import io.anuke.mindustry.type.Recipe;
|
||||||
import io.anuke.mindustry.world.Build;
|
import io.anuke.mindustry.world.Build;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.mindustry.world.blocks.BreakBlock;
|
|
||||||
import io.anuke.mindustry.world.blocks.BreakBlock.BreakEntity;
|
|
||||||
import io.anuke.mindustry.world.blocks.BuildBlock;
|
import io.anuke.mindustry.world.blocks.BuildBlock;
|
||||||
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
||||||
import io.anuke.ucore.core.Effects;
|
import io.anuke.ucore.core.Effects;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
|
import io.anuke.ucore.entities.trait.Entity;
|
||||||
import io.anuke.ucore.graphics.Draw;
|
import io.anuke.ucore.graphics.Draw;
|
||||||
import io.anuke.ucore.graphics.Fill;
|
import io.anuke.ucore.graphics.Fill;
|
||||||
import io.anuke.ucore.graphics.Lines;
|
import io.anuke.ucore.graphics.Lines;
|
||||||
import io.anuke.ucore.graphics.Shapes;
|
import io.anuke.ucore.graphics.Shapes;
|
||||||
import io.anuke.ucore.util.*;
|
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.io.DataInput;
|
||||||
|
import java.io.DataOutput;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.tilesize;
|
import static io.anuke.mindustry.Vars.tilesize;
|
||||||
@@ -34,7 +38,7 @@ import static io.anuke.mindustry.Vars.tmptr;
|
|||||||
import static io.anuke.mindustry.Vars.world;
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
/**Interface for units that build, break or mine things.*/
|
/**Interface for units that build, break or mine things.*/
|
||||||
public interface BuilderTrait {
|
public interface BuilderTrait extends Entity{
|
||||||
//these are not instance variables!
|
//these are not instance variables!
|
||||||
float placeDistance = 140f;
|
float placeDistance = 140f;
|
||||||
float mineDistance = 70f;
|
float mineDistance = 70f;
|
||||||
@@ -54,6 +58,49 @@ public interface BuilderTrait {
|
|||||||
/**Build power, can be any float. 1 = builds recipes in normal time, 0 = doesn't build at all.*/
|
/**Build power, can be any float. 1 = builds recipes in normal time, 0 = doesn't build at all.*/
|
||||||
float getBuildPower(Tile tile);
|
float getBuildPower(Tile tile);
|
||||||
|
|
||||||
|
default void writeBuilding(DataOutput output) throws IOException{
|
||||||
|
BuildRequest request = getCurrentRequest();
|
||||||
|
|
||||||
|
if(request != null){
|
||||||
|
output.writeByte(request.remove ? 1 : 0);
|
||||||
|
output.writeInt(world.toPacked(request.x, request.y));
|
||||||
|
if(!request.remove){
|
||||||
|
output.writeByte(request.recipe.id);
|
||||||
|
output.writeByte(request.rotation);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
output.writeByte(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default void readBuilding(DataInput input) throws IOException{
|
||||||
|
readBuilding(input, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void readBuilding(DataInput input, boolean applyChanges) throws IOException{
|
||||||
|
synchronized (getPlaceQueue()) {
|
||||||
|
if(applyChanges) getPlaceQueue().clear();
|
||||||
|
|
||||||
|
byte type = input.readByte();
|
||||||
|
if (type != -1) {
|
||||||
|
int position = input.readInt();
|
||||||
|
BuildRequest request;
|
||||||
|
|
||||||
|
if (type == 1) { //remove
|
||||||
|
request = new BuildRequest(position % world.width(), position / world.width());
|
||||||
|
} else { //place
|
||||||
|
byte recipe = input.readByte();
|
||||||
|
byte rotation = input.readByte();
|
||||||
|
request = new BuildRequest(position % world.width(), position / world.width(), rotation, Recipe.getByID(recipe));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(applyChanges){
|
||||||
|
getPlaceQueue().addLast(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**Return whether this builder's place queue contains items.*/
|
/**Return whether this builder's place queue contains items.*/
|
||||||
default boolean isBuilding(){
|
default boolean isBuilding(){
|
||||||
return getPlaceQueue().size != 0;
|
return getPlaceQueue().size != 0;
|
||||||
@@ -77,12 +124,8 @@ public interface BuilderTrait {
|
|||||||
|
|
||||||
/**Clears the placement queue.*/
|
/**Clears the placement queue.*/
|
||||||
default void clearBuilding(){
|
default void clearBuilding(){
|
||||||
if(this instanceof Player) {
|
|
||||||
CallBlocks.onBuildDeselect((Player) this);
|
|
||||||
}else{
|
|
||||||
getPlaceQueue().clear();
|
getPlaceQueue().clear();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**Add another build requests to the tail of the queue, if it doesn't exist there yet.*/
|
/**Add another build requests to the tail of the queue, if it doesn't exist there yet.*/
|
||||||
default void addBuildRequest(BuildRequest place){
|
default void addBuildRequest(BuildRequest place){
|
||||||
@@ -119,75 +162,40 @@ public interface BuilderTrait {
|
|||||||
setMineTile(null);
|
setMineTile(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TileEntity core = unit.getClosestCore();
|
||||||
|
|
||||||
|
//if there is no core to build with, stop building!
|
||||||
|
if(core == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Tile tile = world.tile(current.x, current.y);
|
Tile tile = world.tile(current.x, current.y);
|
||||||
|
|
||||||
if(unit.distanceTo(tile) > placeDistance || //out of range, skip it
|
if (!(tile.block() instanceof BuildBlock)) {
|
||||||
(current.lastEntity != null && current.lastEntity.isDead())) { //build/destroy request has died, skip it
|
if(!current.remove && Build.validPlace(unit.getTeam(), current.x, current.y, current.recipe.result, current.rotation)) {
|
||||||
getPlaceQueue().removeFirst();
|
Build.beginPlace(unit.getTeam(), current.x, current.y, current.recipe, current.rotation);
|
||||||
}else if(current.remove){
|
}else if(current.remove && Build.validBreak(unit.getTeam(), current.x, current.y)){
|
||||||
|
Build.beginBreak(unit.getTeam(), current.x, current.y);
|
||||||
if (!(tile.block() instanceof BreakBlock)) { //check if haven't started placing
|
|
||||||
if(Build.validBreak(unit.getTeam(), current.x, current.y)){
|
|
||||||
|
|
||||||
//if it's valid, place it
|
|
||||||
if(!current.requested && unit instanceof Player){
|
|
||||||
CallBlocks.breakBlock((Player)unit, unit.getTeam(), current.x, current.y);
|
|
||||||
current.requested = true;
|
|
||||||
}
|
|
||||||
}else{
|
}else{
|
||||||
//otherwise, skip it
|
|
||||||
getPlaceQueue().removeFirst();
|
getPlaceQueue().removeFirst();
|
||||||
}
|
|
||||||
}else{
|
|
||||||
TileEntity core = unit.getClosestCore();
|
|
||||||
|
|
||||||
//if there is no core to build with, stop building!
|
|
||||||
if(core == null){
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//otherwise, update it.
|
|
||||||
BreakEntity entity = tile.entity();
|
|
||||||
current.lastEntity = entity;
|
|
||||||
|
|
||||||
entity.addProgress(core, unit, 1f / entity.breakTime * Timers.delta() * getBuildPower(tile));
|
|
||||||
unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(entity), 0.4f);
|
|
||||||
getCurrentRequest().progress = entity.progress();
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
if (!(tile.block() instanceof BuildBlock)) { //check if haven't started placing
|
|
||||||
if(Build.validPlace(unit.getTeam(), current.x, current.y, current.recipe.result, current.rotation)){
|
|
||||||
|
|
||||||
//if it's valid, place it
|
|
||||||
if(!current.requested && unit instanceof Player){
|
|
||||||
CallBlocks.placeBlock((Player)unit, unit.getTeam(), current.x, current.y, current.recipe, current.rotation);
|
|
||||||
current.requested = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}else{
|
|
||||||
//otherwise, skip it
|
|
||||||
getPlaceQueue().removeFirst();
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
TileEntity core = unit.getClosestCore();
|
|
||||||
|
|
||||||
//if there is no core to build with, stop building!
|
|
||||||
if(core == null){
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//otherwise, update it.
|
//otherwise, update it.
|
||||||
BuildEntity entity = tile.entity();
|
BuildEntity entity = tile.entity();
|
||||||
current.lastEntity = entity;
|
|
||||||
|
|
||||||
entity.addProgress(core.items, 1f / entity.recipe.cost * Timers.delta() * getBuildPower(tile));
|
//deconstructing is 2x as fast
|
||||||
if(unit instanceof Player){
|
if(current.remove){
|
||||||
entity.lastBuilder = (Player)unit;
|
entity.deconstruct(unit, core, 2f / entity.buildCost * Timers.delta() * getBuildPower(tile));
|
||||||
|
}else{
|
||||||
|
entity.construct(unit, core, 1f / entity.buildCost * Timers.delta() * getBuildPower(tile));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(unit.distanceTo(tile) <= placeDistance){
|
||||||
unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(entity), 0.4f);
|
unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(entity), 0.4f);
|
||||||
getCurrentRequest().progress = entity.progress();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
current.progress = entity.progress();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Do not call directly.*/
|
/**Do not call directly.*/
|
||||||
@@ -233,7 +241,11 @@ public interface BuilderTrait {
|
|||||||
|
|
||||||
Tile tile = world.tile(request.x, request.y);
|
Tile tile = world.tile(request.x, request.y);
|
||||||
|
|
||||||
Draw.color(unit.distanceTo(tile) > placeDistance || request.remove ? Palette.remove : Palette.accent);
|
if(unit.distanceTo(tile) > placeDistance){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Draw.color(Palette.accent);
|
||||||
float focusLen = 3.8f + Mathf.absin(Timers.time(), 1.1f, 0.6f);
|
float focusLen = 3.8f + Mathf.absin(Timers.time(), 1.1f, 0.6f);
|
||||||
float px = unit.x + Angles.trnsx(unit.rotation, focusLen);
|
float px = unit.x + Angles.trnsx(unit.rotation, focusLen);
|
||||||
float py = unit.y + Angles.trnsy(unit.rotation, focusLen);
|
float py = unit.y + Angles.trnsy(unit.rotation, focusLen);
|
||||||
@@ -302,9 +314,6 @@ public interface BuilderTrait {
|
|||||||
public final Recipe recipe;
|
public final Recipe recipe;
|
||||||
public final boolean remove;
|
public final boolean remove;
|
||||||
|
|
||||||
public boolean requested;
|
|
||||||
public TileEntity lastEntity;
|
|
||||||
|
|
||||||
public float progress;
|
public float progress;
|
||||||
|
|
||||||
/**This creates a build request.*/
|
/**This creates a build request.*/
|
||||||
|
|||||||
@@ -32,14 +32,14 @@ public interface CarryTrait extends TeamTrait, SolidTrait, TargetTrait{
|
|||||||
CallEntity.setCarryOf(this instanceof Player ? (Player)this : null, this, unit);
|
CallEntity.setCarryOf(this instanceof Player ? (Player)this : null, this, unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(called = Loc.server, targets = Loc.both, forward = true, in = In.entities)
|
@Remote(called = Loc.both, targets = Loc.both, forward = true, in = In.entities)
|
||||||
static void dropSelf(Player player){
|
static void dropSelf(Player player){
|
||||||
if(player.getCarrier() != null){
|
if(player.getCarrier() != null){
|
||||||
player.getCarrier().dropCarry();
|
player.getCarrier().dropCarry();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(called = Loc.server, targets = Loc.both, forward = true, in = In.entities)
|
@Remote(called = Loc.both, targets = Loc.both, forward = true, in = In.entities)
|
||||||
static void setCarryOf(Player player, CarryTrait trait, CarriableTrait unit){
|
static void setCarryOf(Player player, CarryTrait trait, CarriableTrait unit){
|
||||||
if(player != null){ //when a server recieves this called from a player, set the carrier to the player.
|
if(player != null){ //when a server recieves this called from a player, set the carrier to the player.
|
||||||
trait = player;
|
trait = player;
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package io.anuke.mindustry.entities.traits;
|
||||||
|
|
||||||
|
import io.anuke.mindustry.entities.Unit;
|
||||||
|
import io.anuke.mindustry.world.Tile;
|
||||||
|
|
||||||
|
public interface SpawnerTrait {
|
||||||
|
Tile getTile();
|
||||||
|
void updateSpawning(Unit unit);
|
||||||
|
float getSpawnProgress();
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ import io.anuke.mindustry.entities.Unit;
|
|||||||
import io.anuke.mindustry.entities.Units;
|
import io.anuke.mindustry.entities.Units;
|
||||||
import io.anuke.mindustry.entities.effect.ScorchDecal;
|
import io.anuke.mindustry.entities.effect.ScorchDecal;
|
||||||
import io.anuke.mindustry.entities.traits.ShooterTrait;
|
import io.anuke.mindustry.entities.traits.ShooterTrait;
|
||||||
|
import io.anuke.mindustry.entities.traits.SpawnerTrait;
|
||||||
import io.anuke.mindustry.entities.traits.TargetTrait;
|
import io.anuke.mindustry.entities.traits.TargetTrait;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.game.TeamInfo.TeamData;
|
import io.anuke.mindustry.game.TeamInfo.TeamData;
|
||||||
@@ -52,7 +53,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
|||||||
|
|
||||||
protected boolean isWave;
|
protected boolean isWave;
|
||||||
protected Squad squad;
|
protected Squad squad;
|
||||||
protected int spawner = -1;
|
protected int spawner;
|
||||||
|
|
||||||
/**Initialize the type and team of this unit. Only call once!*/
|
/**Initialize the type and team of this unit. Only call once!*/
|
||||||
public void init(UnitType type, Team team){
|
public void init(UnitType type, Team team){
|
||||||
@@ -62,8 +63,8 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
|||||||
this.team = team;
|
this.team = team;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSpawner(UnitFactoryEntity spawner) {
|
public void setSpawner(Tile tile) {
|
||||||
this.spawner = spawner.tile.packedPosition();
|
this.spawner = tile.packedPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnitType getType() {
|
public UnitType getType() {
|
||||||
@@ -92,6 +93,19 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
|||||||
((TileEntity)target).tile.block().flags.contains(flag);
|
((TileEntity)target).tile.block().flags.contains(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateRespawning(){
|
||||||
|
if(spawner == -1) return;
|
||||||
|
|
||||||
|
Tile tile = world.tile(spawner);
|
||||||
|
if(tile != null && tile.entity != null){
|
||||||
|
if(tile.entity instanceof SpawnerTrait){
|
||||||
|
((SpawnerTrait) tile.entity).updateSpawning(this);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
spawner = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void setState(UnitState state){
|
public void setState(UnitState state){
|
||||||
this.state.set(state);
|
this.state.set(state);
|
||||||
}
|
}
|
||||||
@@ -162,6 +176,11 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid() {
|
||||||
|
return super.isValid() && isAdded();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Timer getTimer() {
|
public Timer getTimer() {
|
||||||
return timer;
|
return timer;
|
||||||
@@ -249,6 +268,11 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
|||||||
|
|
||||||
if(hitTime < 0) hitTime = 0;
|
if(hitTime < 0) hitTime = 0;
|
||||||
|
|
||||||
|
if(isDead()){
|
||||||
|
updateRespawning();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(Net.client()){
|
if(Net.client()){
|
||||||
interpolate();
|
interpolate();
|
||||||
status.update(this);
|
status.update(this);
|
||||||
@@ -317,7 +341,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
|||||||
hitboxTile.setSize(type.hitsizeTile);
|
hitboxTile.setSize(type.hitsizeTile);
|
||||||
state.set(getStartState());
|
state.set(getStartState());
|
||||||
|
|
||||||
heal();
|
health(maxHealth());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -348,6 +372,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
|||||||
public void write(DataOutput data) throws IOException{
|
public void write(DataOutput data) throws IOException{
|
||||||
super.writeSave(data);
|
super.writeSave(data);
|
||||||
data.writeByte(type.id);
|
data.writeByte(type.id);
|
||||||
|
data.writeInt(spawner);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -355,6 +380,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
|||||||
float lastx = x, lasty = y, lastrot = rotation;
|
float lastx = x, lasty = y, lastrot = rotation;
|
||||||
super.readSave(data);
|
super.readSave(data);
|
||||||
this.type = UnitType.getByID(data.readByte());
|
this.type = UnitType.getByID(data.readByte());
|
||||||
|
this.spawner = data.readInt();
|
||||||
|
|
||||||
interpolator.read(lastx, lasty, x, y, time, rotation);
|
interpolator.read(lastx, lasty, x, y, time, rotation);
|
||||||
rotation = lastrot;
|
rotation = lastrot;
|
||||||
@@ -368,7 +394,9 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
|||||||
public static void onUnitDeath(BaseUnit unit){
|
public static void onUnitDeath(BaseUnit unit){
|
||||||
if(unit == null) return;
|
if(unit == null) return;
|
||||||
|
|
||||||
|
if(Net.server() || !Net.active()){
|
||||||
UnitDrops.dropItems(unit);
|
UnitDrops.dropItems(unit);
|
||||||
|
}
|
||||||
|
|
||||||
float explosiveness = 2f + (unit.inventory.hasItem() ? unit.inventory.getItem().item.explosiveness * unit.inventory.getItem().amount : 0f);
|
float explosiveness = 2f + (unit.inventory.hasItem() ? unit.inventory.getItem().item.explosiveness * unit.inventory.getItem().amount : 0f);
|
||||||
float flammability = (unit.inventory.hasItem() ? unit.inventory.getItem().item.flammability * unit.inventory.getItem().amount : 0f);
|
float flammability = (unit.inventory.hasItem() ? unit.inventory.getItem().item.flammability * unit.inventory.getItem().amount : 0f);
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import static io.anuke.mindustry.Vars.world;
|
|||||||
|
|
||||||
public abstract class FlyingUnit extends BaseUnit implements CarryTrait{
|
public abstract class FlyingUnit extends BaseUnit implements CarryTrait{
|
||||||
protected static Translator vec = new Translator();
|
protected static Translator vec = new Translator();
|
||||||
protected static float maxAim = 30f;
|
|
||||||
protected static float wobblyness = 0.6f;
|
protected static float wobblyness = 0.6f;
|
||||||
|
|
||||||
protected Trail trail = new Trail(8);
|
protected Trail trail = new Trail(8);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package io.anuke.mindustry.entities.units;
|
|||||||
|
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.content.Items;
|
import io.anuke.mindustry.content.Items;
|
||||||
import io.anuke.mindustry.gen.CallEntity;
|
import io.anuke.mindustry.entities.effect.ItemDrop;
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.Item;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
@@ -21,9 +21,9 @@ public class UnitDrops {
|
|||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
for(Item item : dropTable){
|
for(Item item : dropTable){
|
||||||
if(Mathf.chance(0.2)){
|
if(Mathf.chance(0.03)){
|
||||||
int amount = Mathf.random(1, 5);
|
int amount = Mathf.random(20, 40);
|
||||||
CallEntity.createItemDrop(item, amount, unit.x + Mathf.range(2f), unit.y + Mathf.range(2f),
|
ItemDrop.create(item, amount, unit.x + Mathf.range(2f), unit.y + Mathf.range(2f),
|
||||||
unit.getVelocity().x + Mathf.range(3f), unit.getVelocity().y + Mathf.range(3f));
|
unit.getVelocity().x + Mathf.range(3f), unit.getVelocity().y + Mathf.range(3f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import io.anuke.mindustry.gen.CallEntity;
|
|||||||
import io.anuke.mindustry.graphics.Palette;
|
import io.anuke.mindustry.graphics.Palette;
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.Item;
|
||||||
import io.anuke.mindustry.type.ItemStack;
|
import io.anuke.mindustry.type.ItemStack;
|
||||||
import io.anuke.mindustry.type.Recipe;
|
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.mindustry.world.blocks.BuildBlock;
|
import io.anuke.mindustry.world.blocks.BuildBlock;
|
||||||
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
||||||
@@ -206,26 +205,19 @@ public class Drone extends FlyingUnit implements BuilderTrait {
|
|||||||
public void write(DataOutput data) throws IOException {
|
public void write(DataOutput data) throws IOException {
|
||||||
super.write(data);
|
super.write(data);
|
||||||
data.writeInt(mineTile == null ? -1 : mineTile.packedPosition());
|
data.writeInt(mineTile == null ? -1 : mineTile.packedPosition());
|
||||||
data.writeInt(placeQueue.size == 0 ? -1 : world.tile(placeQueue.last().x, placeQueue.last().y).packedPosition());
|
writeBuilding(data);
|
||||||
data.writeByte(placeQueue.size == 0 ? -1 : placeQueue.last().recipe.id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(DataInput data, long time) throws IOException {
|
public void read(DataInput data, long time) throws IOException {
|
||||||
super.read(data, time);
|
super.read(data, time);
|
||||||
int mined = data.readInt();
|
int mined = data.readInt();
|
||||||
int pp = data.readInt();
|
|
||||||
byte rid = data.readByte();
|
readBuilding(data);
|
||||||
|
|
||||||
if(mined != -1){
|
if(mined != -1){
|
||||||
mineTile = world.tile(mined);
|
mineTile = world.tile(mined);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pp != -1){
|
|
||||||
Tile tile = world.tile(pp);
|
|
||||||
placeQueue.clear();
|
|
||||||
placeQueue.addLast(new BuildRequest(tile.x, tile.y, tile.getRotation(), Recipe.getByID(rid)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public final UnitState
|
public final UnitState
|
||||||
|
|||||||
@@ -4,12 +4,13 @@ import io.anuke.ucore.util.Bundles;
|
|||||||
|
|
||||||
public enum GameMode{
|
public enum GameMode{
|
||||||
waves,
|
waves,
|
||||||
sandbox{
|
//disabled for technical reasons
|
||||||
|
/*sandbox{
|
||||||
{
|
{
|
||||||
infiniteResources = true;
|
infiniteResources = true;
|
||||||
disableWaveTimer = true;
|
disableWaveTimer = true;
|
||||||
}
|
}
|
||||||
},
|
},*/
|
||||||
freebuild{
|
freebuild{
|
||||||
{
|
{
|
||||||
disableWaveTimer = true;
|
disableWaveTimer = true;
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ public class WaveCreator{
|
|||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.vtol){{
|
new SpawnGroup(UnitTypes.vtol){{
|
||||||
begin = 4;
|
begin = 12;
|
||||||
end = 6;
|
end = 14;
|
||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.scout){{
|
new SpawnGroup(UnitTypes.scout){{
|
||||||
@@ -29,7 +29,7 @@ public class WaveCreator{
|
|||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.titan){{
|
new SpawnGroup(UnitTypes.titan){{
|
||||||
begin = 8;
|
begin = 9;
|
||||||
spacing = 3;
|
spacing = 3;
|
||||||
unitScaling = 2;
|
unitScaling = 2;
|
||||||
|
|
||||||
@@ -71,7 +71,7 @@ public class WaveCreator{
|
|||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.vtol){{
|
new SpawnGroup(UnitTypes.vtol){{
|
||||||
begin = 14;
|
begin = 16;
|
||||||
unitScaling = 2;
|
unitScaling = 2;
|
||||||
spacing = 2;
|
spacing = 2;
|
||||||
|
|
||||||
@@ -100,7 +100,7 @@ public class WaveCreator{
|
|||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.scout){{
|
new SpawnGroup(UnitTypes.scout){{
|
||||||
begin = 25;
|
begin = 35;
|
||||||
spacing = 3;
|
spacing = 3;
|
||||||
unitAmount = 4;
|
unitAmount = 4;
|
||||||
groupAmount = 2;
|
groupAmount = 2;
|
||||||
@@ -120,9 +120,10 @@ public class WaveCreator{
|
|||||||
}},
|
}},
|
||||||
|
|
||||||
new SpawnGroup(UnitTypes.monsoon){{
|
new SpawnGroup(UnitTypes.monsoon){{
|
||||||
begin = 35;
|
begin = 40;
|
||||||
ammoItem = Items.blastCompound;
|
ammoItem = Items.blastCompound;
|
||||||
unitAmount = 2;
|
unitAmount = 2;
|
||||||
|
spacing = 2;
|
||||||
unitScaling = 3;
|
unitScaling = 3;
|
||||||
max = 8;
|
max = 8;
|
||||||
}},
|
}},
|
||||||
|
|||||||
@@ -59,35 +59,40 @@ public class BlockRenderer{
|
|||||||
|
|
||||||
Graphics.surface(renderer.effectSurface);
|
Graphics.surface(renderer.effectSurface);
|
||||||
|
|
||||||
for(int x = -rangex - expandr; x <= rangex + expandr; x++){
|
int avgx = Mathf.scl(camera.position.x, tilesize);
|
||||||
for(int y = -rangey - expandr; y <= rangey + expandr; y++){
|
int avgy = Mathf.scl(camera.position.y, tilesize);
|
||||||
int worldx = Mathf.scl(camera.position.x, tilesize) + x;
|
|
||||||
int worldy = Mathf.scl(camera.position.y, tilesize) + y;
|
|
||||||
boolean expanded = (x < -rangex || x > rangex || y < -rangey || y > rangey);
|
|
||||||
|
|
||||||
Tile tile = world.tile(worldx, worldy);
|
int minx = Math.max(avgx - rangex - expandr, 0);
|
||||||
|
int miny = Math.max(avgy - rangey - expandr, 0);
|
||||||
|
int maxx = Math.min(world.width() - 1, avgx + rangex + expandr);
|
||||||
|
int maxy = Math.min(world.height() - 1, avgy+ rangey + expandr);
|
||||||
|
|
||||||
if(tile != null){
|
for(int x = minx; x <= maxx; x++){
|
||||||
|
for(int y = miny; y <= maxy; y++){
|
||||||
|
boolean expanded = (Math.abs(x - avgx) > rangex || Math.abs(y - avgy) > rangey);
|
||||||
|
|
||||||
|
synchronized (Tile.tileSetLock) {
|
||||||
|
Tile tile = world.rawTile(x, y);
|
||||||
|
|
||||||
|
if (tile != null) {
|
||||||
Block block = tile.block();
|
Block block = tile.block();
|
||||||
|
|
||||||
if(!expanded && block != Blocks.air && world.isAccessible(worldx, worldy)){
|
if (!expanded && block != Blocks.air && world.isAccessible(x, y)) {
|
||||||
synchronized (Tile.tileSetLock) {
|
|
||||||
tile.block().drawShadow(tile);
|
tile.block().drawShadow(tile);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(!(block instanceof StaticBlock)){
|
if (!(block instanceof StaticBlock)) {
|
||||||
if(block != Blocks.air){
|
if (block != Blocks.air) {
|
||||||
if(!expanded){
|
if (!expanded) {
|
||||||
addRequest(tile, Layer.block);
|
addRequest(tile, Layer.block);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(block.expanded || !expanded){
|
if (block.expanded || !expanded) {
|
||||||
if(block.layer != null && block.isLayer(tile)){
|
if (block.layer != null && block.isLayer(tile)) {
|
||||||
addRequest(tile, block.layer);
|
addRequest(tile, block.layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(block.layer2 != null && block.isLayer2(tile)){
|
if (block.layer2 != null && block.isLayer2(tile)) {
|
||||||
addRequest(tile, block.layer2);
|
addRequest(tile, block.layer2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,6 +101,7 @@ public class BlockRenderer{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//TODO this actually isn't necessary
|
//TODO this actually isn't necessary
|
||||||
Draw.color(0, 0, 0, 0.15f);
|
Draw.color(0, 0, 0, 0.15f);
|
||||||
|
|||||||
@@ -123,14 +123,12 @@ public class FogRenderer implements Disposable{
|
|||||||
Graphics.shader();
|
Graphics.shader();
|
||||||
|
|
||||||
Graphics.begin();
|
Graphics.begin();
|
||||||
|
|
||||||
Core.batch.draw(renderer.pixelSurface.texture(), px, py + vh, vw, -vh);
|
Core.batch.draw(renderer.pixelSurface.texture(), px, py + vh, vw, -vh);
|
||||||
Graphics.end();
|
Graphics.end();
|
||||||
|
|
||||||
if(Core.batch instanceof ClipSpriteBatch){
|
if(Core.batch instanceof ClipSpriteBatch){
|
||||||
((ClipSpriteBatch) Core.batch).enableClip(true);
|
((ClipSpriteBatch) Core.batch).enableClip(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Texture getTexture(){
|
public Texture getTexture(){
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import io.anuke.ucore.core.Graphics;
|
|||||||
import io.anuke.ucore.core.Settings;
|
import io.anuke.ucore.core.Settings;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
import io.anuke.ucore.function.Callable;
|
import io.anuke.ucore.function.Callable;
|
||||||
import io.anuke.ucore.graphics.CapStyle;
|
|
||||||
import io.anuke.ucore.graphics.Draw;
|
import io.anuke.ucore.graphics.Draw;
|
||||||
import io.anuke.ucore.graphics.Fill;
|
import io.anuke.ucore.graphics.Fill;
|
||||||
import io.anuke.ucore.graphics.Lines;
|
import io.anuke.ucore.graphics.Lines;
|
||||||
@@ -123,11 +122,11 @@ public class OverlayRenderer {
|
|||||||
drawbars.run();
|
drawbars.run();
|
||||||
|
|
||||||
if(values[0] > 0){
|
if(values[0] > 0){
|
||||||
drawEncloser(target.drawx(), target.drawy() + block.size * tilesize/2f + 2f + values[0]/2f - 0.5f + (values[0] > 2 ? 0.5f : 0), values[0]);
|
drawEncloser(target.drawx(), target.drawy() + block.size * tilesize/2f + 2f, values[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(values[1] > 0){
|
if(values[1] > 0){
|
||||||
drawEncloser(target.drawx(), target.drawy() - block.size * tilesize/2f - 2f - values[1]/2f - 0.5f, values[1]);
|
drawEncloser(target.drawx(), target.drawy() - block.size * tilesize/2f - 2f - values[1], values[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
doDraw[0] = true;
|
doDraw[0] = true;
|
||||||
@@ -182,7 +181,7 @@ public class OverlayRenderer {
|
|||||||
y = (int)(y + 0.0001f);
|
y = (int)(y + 0.0001f);
|
||||||
}
|
}
|
||||||
|
|
||||||
drawEncloser(x, y - 8f, 2f);
|
drawEncloser(x, y - 9f, 2f);
|
||||||
drawBar(Palette.healthstats, x, y - 8f, unit.healthf());
|
drawBar(Palette.healthstats, x, y - 8f, unit.healthf());
|
||||||
drawBar(Palette.ammo, x, y - 9f, unit.getAmmoFraction());
|
drawBar(Palette.ammo, x, y - 9f, unit.getAmmoFraction());
|
||||||
}
|
}
|
||||||
@@ -208,15 +207,11 @@ public class OverlayRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void drawEncloser(float x, float y, float height){
|
void drawEncloser(float x, float y, float height){
|
||||||
x -= 0.5f;
|
|
||||||
y += 0.5f - (height-1f)/2f;
|
|
||||||
|
|
||||||
float len = 3;
|
float len = 3;
|
||||||
|
|
||||||
Lines.stroke(2f + height);
|
|
||||||
Draw.color(Palette.bar);
|
Draw.color(Palette.bar);
|
||||||
Lines.line(x - len - 0.5f, y, x + len + 1.5f, y, CapStyle.none);
|
Fill.crect(x - len - 1, y - 1, len*2f + 2f, height + 2f);
|
||||||
|
Draw.color();
|
||||||
Draw.reset();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package io.anuke.mindustry.graphics;
|
package io.anuke.mindustry.graphics;
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color;
|
import com.badlogic.gdx.graphics.Color;
|
||||||
|
import com.badlogic.gdx.math.Vector2;
|
||||||
import com.badlogic.gdx.utils.FloatArray;
|
import com.badlogic.gdx.utils.FloatArray;
|
||||||
import io.anuke.ucore.graphics.Draw;
|
import io.anuke.ucore.graphics.Draw;
|
||||||
import io.anuke.ucore.graphics.Fill;
|
import io.anuke.ucore.graphics.Fill;
|
||||||
@@ -9,14 +10,20 @@ import io.anuke.ucore.util.Mathf;
|
|||||||
|
|
||||||
/**Class that renders a trail.*/
|
/**Class that renders a trail.*/
|
||||||
public class Trail {
|
public class Trail {
|
||||||
|
private final static float maxJump = 15f;
|
||||||
private final int length;
|
private final int length;
|
||||||
private final FloatArray points = new FloatArray();
|
private final FloatArray points = new FloatArray();
|
||||||
|
private float lastX, lastY;
|
||||||
|
|
||||||
public Trail(int length){
|
public Trail(int length){
|
||||||
this.length = length;
|
this.length = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void update(float curx, float cury){
|
public synchronized void update(float curx, float cury){
|
||||||
|
if(Vector2.dst(curx, cury, lastX, lastY) >= maxJump){
|
||||||
|
points.clear();
|
||||||
|
}
|
||||||
|
|
||||||
points.add(curx, cury);
|
points.add(curx, cury);
|
||||||
|
|
||||||
if(points.size > length*2) {
|
if(points.size > length*2) {
|
||||||
@@ -24,6 +31,9 @@ public class Trail {
|
|||||||
System.arraycopy(items, 2, items, 0, points.size - 2);
|
System.arraycopy(items, 2, items, 0, points.size - 2);
|
||||||
points.size -= 2;
|
points.size -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lastX = curx;
|
||||||
|
lastY = cury;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void clear(){
|
public synchronized void clear(){
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ public class DefaultKeybinds {
|
|||||||
new Category("General"),
|
new Category("General"),
|
||||||
"move_x", new Axis(Input.A, Input.D),
|
"move_x", new Axis(Input.A, Input.D),
|
||||||
"move_y", new Axis(Input.S, Input.W),
|
"move_y", new Axis(Input.S, Input.W),
|
||||||
"select", Input.MOUSE_LEFT,
|
//"select", Input.MOUSE_LEFT,
|
||||||
"break", Input.MOUSE_RIGHT,
|
//"break", Input.MOUSE_RIGHT,
|
||||||
"shoot", Input.MOUSE_LEFT,
|
//"shoot", Input.MOUSE_LEFT,
|
||||||
"rotate", new Axis(Input.SCROLL),
|
"rotate", new Axis(Input.SCROLL),
|
||||||
"dash", Input.SHIFT_LEFT,
|
"dash", Input.SHIFT_LEFT,
|
||||||
"drop_unit", Input.SHIFT_LEFT,
|
"drop_unit", Input.SHIFT_LEFT,
|
||||||
@@ -39,8 +39,7 @@ public class DefaultKeybinds {
|
|||||||
"chat_history_prev", Input.UP,
|
"chat_history_prev", Input.UP,
|
||||||
"chat_history_next", Input.DOWN,
|
"chat_history_next", Input.DOWN,
|
||||||
"chat_scroll", new Axis(Input.SCROLL),
|
"chat_scroll", new Axis(Input.SCROLL),
|
||||||
"console", Input.GRAVE,
|
"console", Input.GRAVE
|
||||||
"block_logs", Input.I
|
|
||||||
);
|
);
|
||||||
|
|
||||||
KeyBinds.defaultSection(section, DeviceType.controller,
|
KeyBinds.defaultSection(section, DeviceType.controller,
|
||||||
@@ -49,9 +48,9 @@ public class DefaultKeybinds {
|
|||||||
"move_y", new Axis(Input.CONTROLLER_L_STICK_VERTICAL_AXIS),
|
"move_y", new Axis(Input.CONTROLLER_L_STICK_VERTICAL_AXIS),
|
||||||
"cursor_x", new Axis(Input.CONTROLLER_R_STICK_HORIZONTAL_AXIS),
|
"cursor_x", new Axis(Input.CONTROLLER_R_STICK_HORIZONTAL_AXIS),
|
||||||
"cursor_y", new Axis(Input.CONTROLLER_R_STICK_VERTICAL_AXIS),
|
"cursor_y", new Axis(Input.CONTROLLER_R_STICK_VERTICAL_AXIS),
|
||||||
"select", Input.CONTROLLER_R_BUMPER,
|
//"select", Input.CONTROLLER_R_BUMPER,
|
||||||
"break", Input.CONTROLLER_L_BUMPER,
|
//"break", Input.CONTROLLER_L_BUMPER,
|
||||||
"shoot", Input.CONTROLLER_R_TRIGGER,
|
//"shoot", Input.CONTROLLER_R_TRIGGER,
|
||||||
"dash", Input.CONTROLLER_Y,
|
"dash", Input.CONTROLLER_Y,
|
||||||
"rotate_alt", new Axis(Input.CONTROLLER_DPAD_RIGHT, Input.CONTROLLER_DPAD_LEFT),
|
"rotate_alt", new Axis(Input.CONTROLLER_DPAD_RIGHT, Input.CONTROLLER_DPAD_LEFT),
|
||||||
"rotate", new Axis(Input.CONTROLLER_A, Input.CONTROLLER_B),
|
"rotate", new Axis(Input.CONTROLLER_A, Input.CONTROLLER_B),
|
||||||
|
|||||||
@@ -300,14 +300,14 @@ public class DesktopInput extends InputHandler{
|
|||||||
if(player.playerIndex > 0){
|
if(player.playerIndex > 0){
|
||||||
controlling = true;
|
controlling = true;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if(Inputs.keyTap(section,"select")){
|
if(Inputs.keyTap(section,"select")){
|
||||||
Inputs.getProcessor().touchDown((int)getMouseX(), (int)getMouseY(), player.playerIndex, Buttons.LEFT);
|
Inputs.getProcessor().touchDown((int)getMouseX(), (int)getMouseY(), player.playerIndex, Buttons.LEFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Inputs.keyRelease(section,"select")){
|
if(Inputs.keyRelease(section,"select")){
|
||||||
Inputs.getProcessor().touchUp((int)getMouseX(), (int)getMouseY(), player.playerIndex, Buttons.LEFT);
|
Inputs.getProcessor().touchUp((int)getMouseX(), (int)getMouseY(), player.playerIndex, Buttons.LEFT);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
float xa = Inputs.getAxis(section, "cursor_x");
|
float xa = Inputs.getAxis(section, "cursor_x");
|
||||||
float ya = Inputs.getAxis(section, "cursor_y");
|
float ya = Inputs.getAxis(section, "cursor_y");
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ public abstract class InputHandler extends InputAdapter{
|
|||||||
if(tile.block().acceptStack(stack.item, stack.amount, tile, player) > 0 && tile.block().hasItems){
|
if(tile.block().acceptStack(stack.item, stack.amount, tile, player) > 0 && tile.block().hasItems){
|
||||||
CallBlocks.transferInventory(player, tile);
|
CallBlocks.transferInventory(player, tile);
|
||||||
}else{
|
}else{
|
||||||
CallEntity.dropItem(player, player.angleTo(x, y));
|
CallEntity.dropItem(player.angleTo(x, y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,7 +267,7 @@ public abstract class InputHandler extends InputAdapter{
|
|||||||
player.addBuildRequest(new BuildRequest(tile.x, tile.y));
|
player.addBuildRequest(new BuildRequest(tile.x, tile.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(targets = Loc.both, called = Loc.server, in = In.entities)
|
@Remote(targets = Loc.client, called = Loc.server, in = In.entities)
|
||||||
public static void dropItem(Player player, float angle){
|
public static void dropItem(Player player, float angle){
|
||||||
if(Net.server() && !player.inventory.hasItem()){
|
if(Net.server() && !player.inventory.hasItem()){
|
||||||
throw new ValidateException(player, "Player cannot drop an item.");
|
throw new ValidateException(player, "Player cannot drop an item.");
|
||||||
|
|||||||
@@ -353,7 +353,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
if(tile != null){
|
if(tile != null){
|
||||||
|
|
||||||
//draw placing
|
//draw placing
|
||||||
if(mode == placing) {
|
if(mode == placing && recipe != null) {
|
||||||
NormalizeDrawResult dresult = PlaceUtils.normalizeDrawArea(recipe.result, lineStartX, lineStartY, tile.x, tile.y, true, maxLength, lineScale);
|
NormalizeDrawResult dresult = PlaceUtils.normalizeDrawArea(recipe.result, lineStartX, lineStartY, tile.x, tile.y, true, maxLength, lineScale);
|
||||||
|
|
||||||
Lines.rect(dresult.x, dresult.y, dresult.x2 - dresult.x, dresult.y2 - dresult.y);
|
Lines.rect(dresult.x, dresult.y, dresult.x2 - dresult.x, dresult.y2 - dresult.y);
|
||||||
@@ -465,7 +465,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
|
|
||||||
if (tile == null) return false;
|
if (tile == null) return false;
|
||||||
|
|
||||||
if(mode == placing) {
|
if(mode == placing && recipe != null) {
|
||||||
|
|
||||||
//normalize area
|
//normalize area
|
||||||
NormalizeResult result = PlaceUtils.normalizeArea(lineStartX, lineStartY, tile.x, tile.y, rotation, true, 100);
|
NormalizeResult result = PlaceUtils.normalizeArea(lineStartX, lineStartY, tile.x, tile.y, rotation, true, 100);
|
||||||
@@ -599,6 +599,10 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
selection.clear();
|
selection.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(lineMode && mode == placing && recipe == null){
|
||||||
|
lineMode = false;
|
||||||
|
}
|
||||||
|
|
||||||
//if there is no mode and there's a recipe, switch to placing
|
//if there is no mode and there's a recipe, switch to placing
|
||||||
if(recipe != null && mode == none){
|
if(recipe != null && mode == none){
|
||||||
mode = placing;
|
mode = placing;
|
||||||
|
|||||||
@@ -49,11 +49,14 @@ public class Saves {
|
|||||||
if(time > Settings.getInt("saveinterval")*60) {
|
if(time > Settings.getInt("saveinterval")*60) {
|
||||||
saving = true;
|
saving = true;
|
||||||
|
|
||||||
exec.submit(() -> {
|
Timers.run(2f, () -> {
|
||||||
|
try {
|
||||||
SaveIO.saveToSlot(current.index);
|
SaveIO.saveToSlot(current.index);
|
||||||
current.meta = SaveIO.getData(current.index);
|
current.meta = SaveIO.getData(current.index);
|
||||||
|
}catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
saving = false;
|
saving = false;
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
time = 0;
|
time = 0;
|
||||||
|
|||||||
@@ -144,6 +144,16 @@ public class TypeIO {
|
|||||||
return world.tile(buffer.getInt());
|
return world.tile(buffer.getInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WriteClass(Block.class)
|
||||||
|
public static void writeBlock(ByteBuffer buffer, Block block){
|
||||||
|
buffer.put((byte)block.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReadClass(Block.class)
|
||||||
|
public static Block readBlock(ByteBuffer buffer){
|
||||||
|
return Block.getByID(buffer.get());
|
||||||
|
}
|
||||||
|
|
||||||
@WriteClass(KickReason.class)
|
@WriteClass(KickReason.class)
|
||||||
public static void writeKick(ByteBuffer buffer, KickReason reason){
|
public static void writeKick(ByteBuffer buffer, KickReason reason){
|
||||||
buffer.put((byte)reason.ordinal());
|
buffer.put((byte)reason.ordinal());
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import io.anuke.ucore.entities.Entities;
|
|||||||
import io.anuke.ucore.entities.EntityGroup;
|
import io.anuke.ucore.entities.EntityGroup;
|
||||||
import io.anuke.ucore.entities.trait.Entity;
|
import io.anuke.ucore.entities.trait.Entity;
|
||||||
import io.anuke.ucore.util.Bits;
|
import io.anuke.ucore.util.Bits;
|
||||||
import io.anuke.ucore.util.Log;
|
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
@@ -51,7 +50,6 @@ public class Save16 extends SaveFileVersion {
|
|||||||
|
|
||||||
state.difficulty = Difficulty.values()[difficulty];
|
state.difficulty = Difficulty.values()[difficulty];
|
||||||
state.mode = GameMode.values()[mode];
|
state.mode = GameMode.values()[mode];
|
||||||
state.enemies = 0; //TODO display enemies correctly!
|
|
||||||
state.wave = wave;
|
state.wave = wave;
|
||||||
state.wavetime = wavetime;
|
state.wavetime = wavetime;
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ public class Net{
|
|||||||
private static boolean active;
|
private static boolean active;
|
||||||
private static boolean clientLoaded;
|
private static boolean clientLoaded;
|
||||||
private static Array<Object> packetQueue = new Array<>();
|
private static Array<Object> packetQueue = new Array<>();
|
||||||
private static ObjectMap<Class<?>, Consumer> listeners = new ObjectMap<>();
|
|
||||||
private static ObjectMap<Class<?>, Consumer> clientListeners = new ObjectMap<>();
|
private static ObjectMap<Class<?>, Consumer> clientListeners = new ObjectMap<>();
|
||||||
private static ObjectMap<Class<?>, BiConsumer<Integer, Object>> serverListeners = new ObjectMap<>();
|
private static ObjectMap<Class<?>, BiConsumer<Integer, Object>> serverListeners = new ObjectMap<>();
|
||||||
private static ClientProvider clientProvider;
|
private static ClientProvider clientProvider;
|
||||||
@@ -146,11 +145,6 @@ public class Net{
|
|||||||
Net.serverProvider = provider;
|
Net.serverProvider = provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Registers a common listener for when an object is recieved. Fired on both client and serve.r*/
|
|
||||||
public static <T> void handle(Class<T> type, Consumer<T> listener){
|
|
||||||
listeners.put(type, listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**Registers a client listener for when an object is recieved.*/
|
/**Registers a client listener for when an object is recieved.*/
|
||||||
public static <T> void handleClient(Class<T> type, Consumer<T> listener){
|
public static <T> void handleClient(Class<T> type, Consumer<T> listener){
|
||||||
clientListeners.put(type, listener);
|
clientListeners.put(type, listener);
|
||||||
@@ -178,12 +172,10 @@ public class Net{
|
|||||||
streams.remove(builder.id);
|
streams.remove(builder.id);
|
||||||
handleClientReceived(builder.build());
|
handleClientReceived(builder.build());
|
||||||
}
|
}
|
||||||
}else if(clientListeners.get(object.getClass()) != null ||
|
}else if(clientListeners.get(object.getClass()) != null){
|
||||||
listeners.get(object.getClass()) != null){
|
|
||||||
|
|
||||||
if(clientLoaded || ((object instanceof Packet) && ((Packet) object).isImportant())){
|
if(clientLoaded || ((object instanceof Packet) && ((Packet) object).isImportant())){
|
||||||
if(clientListeners.get(object.getClass()) != null) clientListeners.get(object.getClass()).accept(object);
|
if(clientListeners.get(object.getClass()) != null) clientListeners.get(object.getClass()).accept(object);
|
||||||
if(listeners.get(object.getClass()) != null) listeners.get(object.getClass()).accept(object);
|
|
||||||
synchronized (packetPoolLock) {
|
synchronized (packetPoolLock) {
|
||||||
Pooling.free(object);
|
Pooling.free(object);
|
||||||
}
|
}
|
||||||
@@ -203,9 +195,8 @@ public class Net{
|
|||||||
/**Call to handle a packet being recieved for the server.*/
|
/**Call to handle a packet being recieved for the server.*/
|
||||||
public static void handleServerReceived(int connection, Object object){
|
public static void handleServerReceived(int connection, Object object){
|
||||||
|
|
||||||
if(serverListeners.get(object.getClass()) != null || listeners.get(object.getClass()) != null){
|
if(serverListeners.get(object.getClass()) != null){
|
||||||
if(serverListeners.get(object.getClass()) != null) serverListeners.get(object.getClass()).accept(connection, object);
|
if(serverListeners.get(object.getClass()) != null) serverListeners.get(object.getClass()).accept(connection, object);
|
||||||
if(listeners.get(object.getClass()) != null) listeners.get(object.getClass()).accept(object);
|
|
||||||
synchronized (packetPoolLock) {
|
synchronized (packetPoolLock) {
|
||||||
Pooling.free(object);
|
Pooling.free(object);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import com.badlogic.gdx.utils.TimeUtils;
|
|||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
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.traits.BuilderTrait.BuildRequest;
|
||||||
import io.anuke.mindustry.io.Version;
|
import io.anuke.mindustry.io.Version;
|
||||||
|
import io.anuke.mindustry.type.Recipe;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.ucore.io.IOUtils;
|
import io.anuke.ucore.io.IOUtils;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
@@ -122,6 +124,7 @@ public class Packets {
|
|||||||
public float x, y, pointerX, pointerY, rotation, baseRotation, xv, yv;
|
public float x, y, pointerX, pointerY, rotation, baseRotation, xv, yv;
|
||||||
public Tile mining;
|
public Tile mining;
|
||||||
public boolean boosting, shooting;
|
public boolean boosting, shooting;
|
||||||
|
public BuildRequest currentRequest;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(ByteBuffer buffer) {
|
public void write(ByteBuffer buffer) {
|
||||||
@@ -145,6 +148,19 @@ public class Packets {
|
|||||||
buffer.putShort((short)(player.baseRotation*2));
|
buffer.putShort((short)(player.baseRotation*2));
|
||||||
|
|
||||||
buffer.putInt(player.getMineTile() == null ? -1 : player.getMineTile().packedPosition());
|
buffer.putInt(player.getMineTile() == null ? -1 : player.getMineTile().packedPosition());
|
||||||
|
|
||||||
|
BuildRequest request = player.getCurrentRequest();
|
||||||
|
|
||||||
|
if(request != null){
|
||||||
|
buffer.put(request.remove ? (byte)1 : 0);
|
||||||
|
buffer.putInt(world.toPacked(request.x, request.y));
|
||||||
|
if(!request.remove){
|
||||||
|
buffer.put((byte)request.recipe.id);
|
||||||
|
buffer.put((byte)request.rotation);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
buffer.put((byte)-1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -164,6 +180,21 @@ public class Packets {
|
|||||||
rotation = buffer.getShort()/2f;
|
rotation = buffer.getShort()/2f;
|
||||||
baseRotation = buffer.getShort()/2f;
|
baseRotation = buffer.getShort()/2f;
|
||||||
mining = world.tile(buffer.getInt());
|
mining = world.tile(buffer.getInt());
|
||||||
|
|
||||||
|
byte type = buffer.get();
|
||||||
|
if (type != -1) {
|
||||||
|
int position = buffer.getInt();
|
||||||
|
|
||||||
|
if (type == 1) { //remove
|
||||||
|
currentRequest = new BuildRequest(position % world.width(), position / world.width());
|
||||||
|
} else { //place
|
||||||
|
byte recipe = buffer.get();
|
||||||
|
byte rotation = buffer.get();
|
||||||
|
currentRequest = new BuildRequest(position % world.width(), position / world.width(), rotation, Recipe.getByID(recipe));
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
currentRequest = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +210,7 @@ public class Packets {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public enum AdminAction{
|
public enum AdminAction{
|
||||||
kick, ban, trace
|
kick, ban, trace, wave
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Marks the beginning of a stream.*/
|
/**Marks the beginning of a stream.*/
|
||||||
|
|||||||
@@ -4,19 +4,20 @@ import com.badlogic.gdx.Gdx;
|
|||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||||
import com.badlogic.gdx.utils.Align;
|
import com.badlogic.gdx.utils.Align;
|
||||||
import io.anuke.mindustry.game.Difficulty;
|
import io.anuke.mindustry.game.Difficulty;
|
||||||
import io.anuke.mindustry.game.EventType.ResizeEvent;
|
|
||||||
import io.anuke.mindustry.game.GameMode;
|
import io.anuke.mindustry.game.GameMode;
|
||||||
import io.anuke.mindustry.io.Map;
|
import io.anuke.mindustry.io.Map;
|
||||||
import io.anuke.mindustry.ui.BorderImage;
|
import io.anuke.mindustry.ui.BorderImage;
|
||||||
import io.anuke.ucore.core.Events;
|
|
||||||
import io.anuke.ucore.core.Settings;
|
import io.anuke.ucore.core.Settings;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
import io.anuke.ucore.graphics.Draw;
|
import io.anuke.ucore.graphics.Draw;
|
||||||
import io.anuke.ucore.scene.event.Touchable;
|
import io.anuke.ucore.scene.event.Touchable;
|
||||||
|
import io.anuke.ucore.scene.ui.ButtonGroup;
|
||||||
import io.anuke.ucore.scene.ui.ImageButton;
|
import io.anuke.ucore.scene.ui.ImageButton;
|
||||||
import io.anuke.ucore.scene.ui.ScrollPane;
|
import io.anuke.ucore.scene.ui.ScrollPane;
|
||||||
|
import io.anuke.ucore.scene.ui.TextButton;
|
||||||
import io.anuke.ucore.scene.ui.layout.Table;
|
import io.anuke.ucore.scene.ui.layout.Table;
|
||||||
import io.anuke.ucore.scene.utils.Cursors;
|
import io.anuke.ucore.scene.utils.Cursors;
|
||||||
|
import io.anuke.ucore.scene.utils.Elements;
|
||||||
import io.anuke.ucore.util.Bundles;
|
import io.anuke.ucore.util.Bundles;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ public class LevelDialog extends FloatingDialog{
|
|||||||
|
|
||||||
int maxwidth = (Gdx.graphics.getHeight() > Gdx.graphics.getHeight() ? 2 : 4);
|
int maxwidth = (Gdx.graphics.getHeight() > Gdx.graphics.getHeight() ? 2 : 4);
|
||||||
|
|
||||||
/*Table selmode = new Table();
|
Table selmode = new Table();
|
||||||
ButtonGroup<TextButton> group = new ButtonGroup<>();
|
ButtonGroup<TextButton> group = new ButtonGroup<>();
|
||||||
selmode.add("$text.level.mode").padRight(15f);
|
selmode.add("$text.level.mode").padRight(15f);
|
||||||
|
|
||||||
@@ -50,14 +51,13 @@ public class LevelDialog extends FloatingDialog{
|
|||||||
TextButton[] b = {null};
|
TextButton[] b = {null};
|
||||||
b[0] = Elements.newButton("$mode." + mode.name() + ".name", "toggle", () -> state.mode = mode);
|
b[0] = Elements.newButton("$mode." + mode.name() + ".name", "toggle", () -> state.mode = mode);
|
||||||
b[0].update(() -> b[0].setChecked(state.mode == mode));
|
b[0].update(() -> b[0].setChecked(state.mode == mode));
|
||||||
b[0].setDisabled(true);
|
|
||||||
group.add(b[0]);
|
group.add(b[0]);
|
||||||
selmode.add(b[0]).size(130f, 54f);
|
selmode.add(b[0]).size(130f, 54f);
|
||||||
}
|
}
|
||||||
selmode.addButton("?", this::displayGameModeHelp).size(50f, 54f).padLeft(18f);
|
selmode.addButton("?", this::displayGameModeHelp).size(50f, 54f).padLeft(18f);
|
||||||
|
|
||||||
content().add(selmode);
|
content().add(selmode);
|
||||||
content().row();*/
|
content().row();
|
||||||
|
|
||||||
Difficulty[] ds = Difficulty.values();
|
Difficulty[] ds = Difficulty.values();
|
||||||
|
|
||||||
|
|||||||
@@ -181,6 +181,8 @@ public class BlockInventoryFragment extends Fragment {
|
|||||||
|
|
||||||
@Remote(called = Loc.server, targets = Loc.both, in = In.blocks, forward = true)
|
@Remote(called = Loc.server, targets = Loc.both, in = In.blocks, forward = true)
|
||||||
public static void requestItem(Player player, Tile tile, Item item, int amount){
|
public static void requestItem(Player player, Tile tile, Item item, int amount){
|
||||||
|
if(player == null) return;
|
||||||
|
|
||||||
int removed = tile.block().removeStack(tile, item, amount);
|
int removed = tile.block().removeStack(tile, item, amount);
|
||||||
|
|
||||||
player.inventory.addItem(item, removed);
|
player.inventory.addItem(item, removed);
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
|||||||
import com.badlogic.gdx.math.Interpolation;
|
import com.badlogic.gdx.math.Interpolation;
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
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.TileEntity;
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
import io.anuke.mindustry.input.InputHandler;
|
import io.anuke.mindustry.input.InputHandler;
|
||||||
import io.anuke.mindustry.type.Category;
|
import io.anuke.mindustry.type.Category;
|
||||||
@@ -190,7 +189,7 @@ public class BlocksFragment extends Fragment{
|
|||||||
Stack istack = new Stack();
|
Stack istack = new Stack();
|
||||||
for(TextureRegion region : regions){
|
for(TextureRegion region : regions){
|
||||||
Image u = new Image(region);
|
Image u = new Image(region);
|
||||||
u.update(() -> u.setColor(image.isDisabled() ? Color.GRAY : Color.WHITE));
|
u.update(() -> u.setColor(istack.getColor()));
|
||||||
istack.add(u);
|
istack.add(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,35 +235,21 @@ public class BlocksFragment extends Fragment{
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
image.setDisabled(() -> {
|
|
||||||
TileEntity entity = players[0].getClosestCore();
|
|
||||||
|
|
||||||
if(entity == null) return true;
|
|
||||||
|
|
||||||
for(ItemStack s : r.requirements){
|
|
||||||
if(!entity.items.hasItem(s.item, Mathf.ceil(s.amount/2f))){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
recipeTable.add(image).size(size + 8);
|
recipeTable.add(image).size(size + 8);
|
||||||
|
|
||||||
image.update(() -> {
|
image.update(() -> {
|
||||||
if(!image.isDisabled()) {
|
image.setChecked(r == control.input(0).recipe);
|
||||||
for (Player player : players) {
|
TileEntity entity = players[0].getClosestCore();
|
||||||
if (control.input(player.playerIndex).recipe == r) {
|
|
||||||
image.setChecked(true);
|
if(entity == null) return;
|
||||||
|
|
||||||
|
for(ItemStack s : r.requirements){
|
||||||
|
if(!entity.items.hasItem(s.item, Mathf.ceil(s.amount))){
|
||||||
|
istack.setColor(Color.GRAY);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}/*else{
|
istack.setColor(Color.WHITE);
|
||||||
if(control.input(0).recipe == r){
|
|
||||||
control.input(0).recipe = null;
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
image.setChecked(false);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (i % rows == rows - 1) {
|
if (i % rows == rows - 1) {
|
||||||
|
|||||||
@@ -2,14 +2,14 @@ package io.anuke.mindustry.ui.fragments;
|
|||||||
|
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
import com.badlogic.gdx.files.FileHandle;
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
import io.anuke.mindustry.content.bullets.TurretBullets;
|
|
||||||
import io.anuke.mindustry.entities.Player;
|
import io.anuke.mindustry.entities.Player;
|
||||||
import io.anuke.mindustry.entities.TileEntity;
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
import io.anuke.mindustry.entities.bullet.Bullet;
|
import io.anuke.mindustry.entities.effect.ItemDrop;
|
||||||
import io.anuke.mindustry.entities.units.BaseUnit;
|
import io.anuke.mindustry.entities.units.BaseUnit;
|
||||||
import io.anuke.mindustry.entities.units.UnitType;
|
import io.anuke.mindustry.entities.units.UnitType;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
|
import io.anuke.mindustry.type.Item;
|
||||||
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
import io.anuke.ucore.entities.EntityGroup;
|
import io.anuke.ucore.entities.EntityGroup;
|
||||||
@@ -59,13 +59,13 @@ public class DebugFragment extends Fragment {
|
|||||||
row();
|
row();
|
||||||
new button("noclip", "toggle", () -> noclip = !noclip);
|
new button("noclip", "toggle", () -> noclip = !noclip);
|
||||||
row();
|
row();
|
||||||
new button("fire", () -> {
|
new button("items", () -> {
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
Bullet.create(TurretBullets.fireball, player, player.x, player.y, Mathf.random(360f));
|
ItemDrop.create(Item.all().random(), 5, player.x, player.y, Mathf.random(360f));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
row();
|
row();
|
||||||
new button("team", "toggle", () -> player.toggleTeam());
|
new button("team", "toggle", player::toggleTeam);
|
||||||
row();
|
row();
|
||||||
new button("blocks", "toggle", () -> showBlockDebug = !showBlockDebug);
|
new button("blocks", "toggle", () -> showBlockDebug = !showBlockDebug);
|
||||||
row();
|
row();
|
||||||
@@ -185,7 +185,7 @@ public class DebugFragment extends Fragment {
|
|||||||
result.append(player.id);
|
result.append(player.id);
|
||||||
result.append("\n");
|
result.append("\n");
|
||||||
result.append(" cid: ");
|
result.append(" cid: ");
|
||||||
result.append(player.con.id);
|
result.append(player.con == null ? -1 : player.con.id);
|
||||||
result.append("\n");
|
result.append("\n");
|
||||||
result.append(" dead: ");
|
result.append(" dead: ");
|
||||||
result.append(player.isDead());
|
result.append(player.isDead());
|
||||||
|
|||||||
@@ -7,7 +7,10 @@ import com.badlogic.gdx.math.Interpolation;
|
|||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
import com.badlogic.gdx.utils.Scaling;
|
import com.badlogic.gdx.utils.Scaling;
|
||||||
import io.anuke.mindustry.core.GameState.State;
|
import io.anuke.mindustry.core.GameState.State;
|
||||||
|
import io.anuke.mindustry.game.Team;
|
||||||
|
import io.anuke.mindustry.gen.Call;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
|
import io.anuke.mindustry.net.Packets.AdminAction;
|
||||||
import io.anuke.mindustry.type.Recipe;
|
import io.anuke.mindustry.type.Recipe;
|
||||||
import io.anuke.mindustry.ui.IntFormat;
|
import io.anuke.mindustry.ui.IntFormat;
|
||||||
import io.anuke.mindustry.ui.Minimap;
|
import io.anuke.mindustry.ui.Minimap;
|
||||||
@@ -288,10 +291,11 @@ public class HudFragment extends Fragment{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private String getEnemiesRemaining() {
|
private String getEnemiesRemaining() {
|
||||||
if(state.enemies == 1) {
|
int enemies = unitGroups[Team.red.ordinal()].size();
|
||||||
return Bundles.format("text.enemies.single", state.enemies);
|
if(enemies == 1) {
|
||||||
|
return Bundles.format("text.enemies.single", enemies);
|
||||||
} else {
|
} else {
|
||||||
return Bundles.format("text.enemies", state.enemies);
|
return Bundles.format("text.enemies", enemies);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,7 +314,7 @@ public class HudFragment extends Fragment{
|
|||||||
|
|
||||||
row();
|
row();
|
||||||
|
|
||||||
new label(() -> state.enemies > 0 ?
|
new label(() -> unitGroups[Team.red.ordinal()].size() > 0 && state.mode.disableWaveTimer ?
|
||||||
getEnemiesRemaining() :
|
getEnemiesRemaining() :
|
||||||
(state.mode.disableWaveTimer) ? "$text.waiting"
|
(state.mode.disableWaveTimer) ? "$text.waiting"
|
||||||
: timef.get((int) (state.wavetime / 60f)))
|
: timef.get((int) (state.wavetime / 60f)))
|
||||||
@@ -329,14 +333,17 @@ public class HudFragment extends Fragment{
|
|||||||
|
|
||||||
private void playButton(float uheight){
|
private void playButton(float uheight){
|
||||||
new imagebutton("icon-play", 30f, () -> {
|
new imagebutton("icon-play", 30f, () -> {
|
||||||
|
if(Net.client() && players[0].isAdmin){
|
||||||
|
Call.onAdminRequest(players[0], AdminAction.wave);
|
||||||
|
}else {
|
||||||
state.wavetime = 0f;
|
state.wavetime = 0f;
|
||||||
|
}
|
||||||
}).height(uheight).fillX().right().padTop(-8f).padBottom(-12f).padLeft(-15).padRight(-10).width(40f).update(l->{
|
}).height(uheight).fillX().right().padTop(-8f).padBottom(-12f).padLeft(-15).padRight(-10).width(40f).update(l->{
|
||||||
boolean vis = state.mode.disableWaveTimer && (Net.server() || !Net.active());
|
boolean vis = state.mode.disableWaveTimer && ((Net.server() || players[0].isAdmin) || !Net.active());
|
||||||
boolean paused = state.is(State.paused) || !vis;
|
boolean paused = state.is(State.paused) || !vis;
|
||||||
|
|
||||||
l.setVisible(vis);
|
|
||||||
l.getStyle().imageUp = Core.skin.getDrawable(vis ? "icon-play" : "clear");
|
l.getStyle().imageUp = Core.skin.getDrawable(vis ? "icon-play" : "clear");
|
||||||
l.setTouchable(!paused ? Touchable.enabled : Touchable.disabled);
|
l.setTouchable(!paused ? Touchable.enabled : Touchable.disabled);
|
||||||
});
|
}).visible(() -> state.mode.disableWaveTimer && ((Net.server() || players[0].isAdmin) || !Net.active()) && unitGroups[Team.red.ordinal()].size() == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,9 +70,19 @@ public class PlayerListFragment extends Fragment{
|
|||||||
if(!checkmap.containsKey(player) || checkmap.get(player, false) != player.isAdmin){
|
if(!checkmap.containsKey(player) || checkmap.get(player, false) != player.isAdmin){
|
||||||
rebuild = true;
|
rebuild = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
for(Player player : checkmap.keys()){
|
||||||
|
if(!player.isAdded()){
|
||||||
|
rebuild = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(rebuild){
|
||||||
|
rebuild();
|
||||||
|
checkmap.clear();
|
||||||
|
for(Player player : playerGroup.all()){
|
||||||
checkmap.put(player, player.isAdmin);
|
checkmap.put(player, player.isAdmin);
|
||||||
}
|
}
|
||||||
if(rebuild) rebuild();
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
visible(() -> visible);
|
visible(() -> visible);
|
||||||
|
|||||||
@@ -198,6 +198,8 @@ public abstract class BaseBlock {
|
|||||||
|
|
||||||
/**Try dumping a specific item near the tile.*/
|
/**Try dumping a specific item near the tile.*/
|
||||||
public boolean tryDump(Tile tile, Item todump){
|
public boolean tryDump(Tile tile, Item todump){
|
||||||
|
if(tile.entity == null || !hasItems) return false;
|
||||||
|
|
||||||
int size = tile.block().size;
|
int size = tile.block().size;
|
||||||
|
|
||||||
GridPoint2[] nearby = Edges.getEdges(size);
|
GridPoint2[] nearby = Edges.getEdges(size);
|
||||||
|
|||||||
@@ -432,7 +432,7 @@ public class Block extends BaseBlock implements Content{
|
|||||||
|
|
||||||
if(shadowRegions != null) {
|
if(shadowRegions != null) {
|
||||||
Draw.rect(shadowRegions[(Mathf.randomSeed(tile.id(), 0, variants - 1))], tile.worldx(), tile.worldy());
|
Draw.rect(shadowRegions[(Mathf.randomSeed(tile.id(), 0, variants - 1))], tile.worldx(), tile.worldy());
|
||||||
}else{
|
}else if(shadowRegion != null){
|
||||||
Draw.rect(shadowRegion, tile.drawx(), tile.drawy());
|
Draw.rect(shadowRegion, tile.drawx(), tile.drawy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,11 @@
|
|||||||
package io.anuke.mindustry.world;
|
package io.anuke.mindustry.world;
|
||||||
|
|
||||||
import com.badlogic.gdx.math.Rectangle;
|
import com.badlogic.gdx.math.Rectangle;
|
||||||
import io.anuke.annotations.Annotations.Loc;
|
|
||||||
import io.anuke.annotations.Annotations.Remote;
|
|
||||||
import io.anuke.mindustry.content.blocks.Blocks;
|
import io.anuke.mindustry.content.blocks.Blocks;
|
||||||
import io.anuke.mindustry.entities.Player;
|
|
||||||
import io.anuke.mindustry.entities.Units;
|
import io.anuke.mindustry.entities.Units;
|
||||||
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
|
|
||||||
import io.anuke.mindustry.game.EventType.BlockBuildEvent;
|
import io.anuke.mindustry.game.EventType.BlockBuildEvent;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.net.In;
|
|
||||||
import io.anuke.mindustry.net.Net;
|
|
||||||
import io.anuke.mindustry.type.Recipe;
|
import io.anuke.mindustry.type.Recipe;
|
||||||
import io.anuke.mindustry.world.blocks.BreakBlock;
|
|
||||||
import io.anuke.mindustry.world.blocks.BreakBlock.BreakEntity;
|
|
||||||
import io.anuke.mindustry.world.blocks.BuildBlock;
|
|
||||||
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
||||||
import io.anuke.ucore.core.Events;
|
import io.anuke.ucore.core.Events;
|
||||||
import io.anuke.ucore.entities.Entities;
|
import io.anuke.ucore.entities.Entities;
|
||||||
@@ -26,17 +17,12 @@ public class Build {
|
|||||||
private static final Rectangle hitrect = new Rectangle();
|
private static final Rectangle hitrect = new Rectangle();
|
||||||
|
|
||||||
/**Returns block type that was broken, or null if unsuccesful.*/
|
/**Returns block type that was broken, or null if unsuccesful.*/
|
||||||
@Remote(targets = Loc.both, forward = true, called = Loc.server, in = In.blocks)
|
//@Remote(targets = Loc.both, forward = true, called = Loc.server, in = In.blocks)
|
||||||
public static void breakBlock(Player player, Team team, int x, int y){
|
public static void beginBreak(Team team, int x, int y){
|
||||||
if(Net.server()){
|
|
||||||
if(!validBreak(team, x, y)){
|
if(!validBreak(team, x, y)){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
team = player.getTeam();
|
|
||||||
//throw new ValidateException(player, "An invalid block has been broken.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Tile tile = world.tile(x, y);
|
Tile tile = world.tile(x, y);
|
||||||
|
|
||||||
//just in case
|
//just in case
|
||||||
@@ -46,26 +32,10 @@ public class Build {
|
|||||||
|
|
||||||
Block previous = tile.block();
|
Block previous = tile.block();
|
||||||
|
|
||||||
//remote players only
|
Block sub = Block.getByName("build" + previous.size);
|
||||||
if(player != null && !player.isLocal){
|
|
||||||
player.getPlaceQueue().clear();
|
|
||||||
player.getPlaceQueue().addFirst(new BuildRequest(x, y));
|
|
||||||
}
|
|
||||||
|
|
||||||
Block sub = Block.getByName("break" + previous.size);
|
|
||||||
|
|
||||||
if(previous instanceof BuildBlock){
|
|
||||||
BuildEntity build = tile.entity();
|
|
||||||
|
|
||||||
tile.setBlock(sub);
|
tile.setBlock(sub);
|
||||||
tile.setTeam(team);
|
tile.<BuildEntity>entity().setDeconstruct(previous);
|
||||||
|
|
||||||
BreakEntity breake = tile.entity();
|
|
||||||
breake.set(build.recipe.result);
|
|
||||||
breake.progress = 1.0 - build.progress;
|
|
||||||
}else {
|
|
||||||
tile.setBlock(sub);
|
|
||||||
tile.<BreakEntity>entity().set(previous);
|
|
||||||
tile.setTeam(team);
|
tile.setTeam(team);
|
||||||
|
|
||||||
if (previous.isMultiblock()) {
|
if (previous.isMultiblock()) {
|
||||||
@@ -86,21 +56,16 @@ public class Build {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Places a BuildBlock at this location. Call validPlace first.*/
|
/**Places a BuildBlock at this location.*/
|
||||||
@Remote(targets = Loc.both, forward = true, called = Loc.server, in = In.blocks)
|
//@Remote(targets = Loc.both, forward = true, called = Loc.server, in = In.blocks)
|
||||||
public static void placeBlock(Player player, Team team, int x, int y, Recipe recipe, int rotation){
|
public static void beginPlace(Team team, int x, int y, Recipe recipe, int rotation){
|
||||||
if(Net.server()){
|
|
||||||
if(!validPlace(team, x, y, recipe.result, rotation)){
|
if(!validPlace(team, x, y, recipe.result, rotation)){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
team = player.getTeam();
|
|
||||||
//throw new ValidateException(player, "An invalid block has been placed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Tile tile = world.tile(x, y);
|
Tile tile = world.tile(x, y);
|
||||||
|
|
||||||
//just in case
|
//just in case
|
||||||
@@ -109,26 +74,10 @@ public class Build {
|
|||||||
Block result = recipe.result;
|
Block result = recipe.result;
|
||||||
Block previous = tile.block();
|
Block previous = tile.block();
|
||||||
|
|
||||||
//remote players only
|
|
||||||
if(player != null && !player.isLocal){
|
|
||||||
player.getPlaceQueue().clear();
|
|
||||||
player.getPlaceQueue().addFirst(new BuildRequest(x, y, rotation, recipe));
|
|
||||||
}
|
|
||||||
|
|
||||||
Block sub = Block.getByName("build" + result.size);
|
Block sub = Block.getByName("build" + result.size);
|
||||||
|
|
||||||
if(previous instanceof BreakBlock){
|
|
||||||
BreakEntity breake = tile.entity();
|
|
||||||
|
|
||||||
tile.setBlock(sub);
|
|
||||||
tile.setTeam(team);
|
|
||||||
|
|
||||||
BuildEntity build = tile.entity();
|
|
||||||
build.set(breake.previous, recipe);
|
|
||||||
build.progress = 1.0 - breake.progress;
|
|
||||||
}else{
|
|
||||||
tile.setBlock(sub, rotation);
|
tile.setBlock(sub, rotation);
|
||||||
tile.<BuildEntity>entity().set(previous, recipe);
|
tile.<BuildEntity>entity().setConstruct(previous, recipe);
|
||||||
tile.setTeam(team);
|
tile.setTeam(team);
|
||||||
|
|
||||||
if (result.isMultiblock()) {
|
if (result.isMultiblock()) {
|
||||||
@@ -149,11 +98,9 @@ public class Build {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Team fteam = team;
|
|
||||||
|
|
||||||
threads.runDelay(() -> Events.fire(BlockBuildEvent.class, fteam, tile));
|
threads.runDelay(() -> Events.fire(BlockBuildEvent.class, team, tile));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Returns whether a tile can be placed at this location by this team.*/
|
/**Returns whether a tile can be placed at this location by this team.*/
|
||||||
@@ -199,13 +146,17 @@ public class Build {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!type.canPlaceOn(tile)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int offsetx = -(type.size - 1) / 2;
|
int offsetx = -(type.size - 1) / 2;
|
||||||
int offsety = -(type.size - 1) / 2;
|
int offsety = -(type.size - 1) / 2;
|
||||||
for (int dx = 0; dx < type.size; dx++) {
|
for (int dx = 0; dx < type.size; dx++) {
|
||||||
for (int dy = 0; dy < type.size; dy++) {
|
for (int dy = 0; dy < type.size; dy++) {
|
||||||
Tile other = world.tile(x + dx + offsetx, y + dy + offsety);
|
Tile other = world.tile(x + dx + offsetx, y + dy + offsety);
|
||||||
if (other == null || (other.block() != Blocks.air && !other.block().alwaysReplace)
|
if (other == null || (other.block() != Blocks.air && !other.block().alwaysReplace)
|
||||||
|| !type.canPlaceOn(other) || other.cliffs != 0 || !other.floor().placeableOn ||
|
|| other.cliffs != 0 || !other.floor().placeableOn ||
|
||||||
(tile.floor().liquidDrop != null && !type.floating)) {
|
(tile.floor().liquidDrop != null && !type.floating)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -226,7 +177,7 @@ public class Build {
|
|||||||
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);
|
||||||
|
|
||||||
return tile != null && !tile.block().unbreakable && !(tile.target().block() instanceof BreakBlock)
|
return tile != null && !tile.block().unbreakable
|
||||||
&& (!tile.isLinked() || !tile.getLinked().block().unbreakable) && tile.breakable() && (tile.getTeam() == Team.none || tile.getTeam() == team);
|
&& (!tile.isLinked() || !tile.getLinked().block().unbreakable) && tile.breakable() && (tile.getTeam() == Team.none || tile.getTeam() == team);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,8 +27,9 @@ public class Tile implements PosTrait, TargetTrait {
|
|||||||
public static final Object tileSetLock = new Object();
|
public static final Object tileSetLock = new Object();
|
||||||
|
|
||||||
/**Block ID data.*/
|
/**Block ID data.*/
|
||||||
private byte floor, wall;
|
private Block wall;
|
||||||
/**Rotation, 0-3. Also used to store offload location.*/
|
private Floor floor;
|
||||||
|
/**Rotation, 0-3. Also used to store offload location for routers, in which case it can be any number.*/
|
||||||
private byte rotation;
|
private byte rotation;
|
||||||
/**Team ordinal.*/
|
/**Team ordinal.*/
|
||||||
private byte team;
|
private byte team;
|
||||||
@@ -52,15 +53,15 @@ public class Tile implements PosTrait, TargetTrait {
|
|||||||
|
|
||||||
public Tile(int x, int y, byte floor, byte wall){
|
public Tile(int x, int y, byte floor, byte wall){
|
||||||
this(x, y);
|
this(x, y);
|
||||||
this.floor = floor;
|
this.floor = (Floor) Block.getByID(floor);
|
||||||
this.wall = wall;
|
this.wall = Block.getByID(wall);
|
||||||
changed();
|
changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tile(int x, int y, byte floor, byte wall, byte rotation, byte team, byte elevation){
|
public Tile(int x, int y, byte floor, byte wall, byte rotation, byte team, byte elevation){
|
||||||
this(x, y);
|
this(x, y);
|
||||||
this.floor = floor;
|
this.floor =(Floor) Block.getByID(floor);
|
||||||
this.wall = wall;
|
this.wall = Block.getByID(wall);
|
||||||
this.rotation = rotation;
|
this.rotation = rotation;
|
||||||
this.elevation = elevation;
|
this.elevation = elevation;
|
||||||
changed();
|
changed();
|
||||||
@@ -72,11 +73,11 @@ public class Tile implements PosTrait, TargetTrait {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public byte getWallID(){
|
public byte getWallID(){
|
||||||
return wall;
|
return (byte)wall.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte getFloorID(){
|
public byte getFloorID(){
|
||||||
return floor;
|
return (byte)floor.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Return relative rotation to a coordinate. Returns -1 if the coordinate is not near this tile.*/
|
/**Return relative rotation to a coordinate. Returns -1 if the coordinate is not near this tile.*/
|
||||||
@@ -129,11 +130,11 @@ public class Tile implements PosTrait, TargetTrait {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Floor floor(){
|
public Floor floor(){
|
||||||
return (Floor)Block.getByID(getFloorID());
|
return floor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Block block(){
|
public Block block(){
|
||||||
return Block.getByID(getWallID());
|
return wall;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Team getTeam(){
|
public Team getTeam(){
|
||||||
@@ -161,7 +162,7 @@ public class Tile implements PosTrait, TargetTrait {
|
|||||||
public void setBlock(Block type, int rotation){
|
public void setBlock(Block type, int rotation){
|
||||||
synchronized (tileSetLock) {
|
synchronized (tileSetLock) {
|
||||||
if(rotation < 0) rotation = (-rotation + 2);
|
if(rotation < 0) rotation = (-rotation + 2);
|
||||||
this.wall = (byte)type.id;
|
this.wall = type;
|
||||||
this.link = 0;
|
this.link = 0;
|
||||||
setRotation((byte) (rotation % 4));
|
setRotation((byte) (rotation % 4));
|
||||||
changed();
|
changed();
|
||||||
@@ -170,14 +171,14 @@ public class Tile implements PosTrait, TargetTrait {
|
|||||||
|
|
||||||
public void setBlock(Block type){
|
public void setBlock(Block type){
|
||||||
synchronized (tileSetLock) {
|
synchronized (tileSetLock) {
|
||||||
this.wall = (byte)type.id;
|
this.wall = type;
|
||||||
this.link = 0;
|
this.link = 0;
|
||||||
changed();
|
changed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFloor(Block type){
|
public void setFloor(Floor type){
|
||||||
this.floor = (byte)type.id;
|
this.floor = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRotation(byte rotation){
|
public void setRotation(byte rotation){
|
||||||
@@ -254,6 +255,25 @@ public class Tile implements PosTrait, TargetTrait {
|
|||||||
return tmpArray;
|
return tmpArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**Returns the list of all tiles linked to this multiblock if it were this block, or an empty array if it's not a multiblock.
|
||||||
|
* This array contains all linked tiles, including this tile itself.*/
|
||||||
|
public synchronized Array<Tile> getLinkedTilesAs(Block block, Array<Tile> tmpArray){
|
||||||
|
tmpArray.clear();
|
||||||
|
if(block.isMultiblock()){
|
||||||
|
int offsetx = -(block.size-1)/2;
|
||||||
|
int offsety = -(block.size-1)/2;
|
||||||
|
for(int dx = 0; dx < block.size; dx ++){
|
||||||
|
for(int dy = 0; dy < block.size; dy ++){
|
||||||
|
Tile other = world.tile(x + dx + offsetx, y + dy + offsety);
|
||||||
|
tmpArray.add(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
tmpArray.add(this);
|
||||||
|
}
|
||||||
|
return tmpArray;
|
||||||
|
}
|
||||||
|
|
||||||
/**Returns the block the multiblock is linked to, or null if it is not linked to any block.*/
|
/**Returns the block the multiblock is linked to, or null if it is not linked to any block.*/
|
||||||
public Tile getLinked(){
|
public Tile getLinked(){
|
||||||
if(link == 0){
|
if(link == 0){
|
||||||
|
|||||||
@@ -1,205 +0,0 @@
|
|||||||
package io.anuke.mindustry.world.blocks;
|
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
|
||||||
import io.anuke.annotations.Annotations.Loc;
|
|
||||||
import io.anuke.annotations.Annotations.Remote;
|
|
||||||
import io.anuke.mindustry.content.fx.ExplosionFx;
|
|
||||||
import io.anuke.mindustry.content.fx.Fx;
|
|
||||||
import io.anuke.mindustry.entities.Player;
|
|
||||||
import io.anuke.mindustry.entities.TileEntity;
|
|
||||||
import io.anuke.mindustry.entities.Unit;
|
|
||||||
import io.anuke.mindustry.entities.effect.RubbleDecal;
|
|
||||||
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
|
|
||||||
import io.anuke.mindustry.game.Team;
|
|
||||||
import io.anuke.mindustry.gen.CallBlocks;
|
|
||||||
import io.anuke.mindustry.graphics.Layer;
|
|
||||||
import io.anuke.mindustry.graphics.Palette;
|
|
||||||
import io.anuke.mindustry.graphics.Shaders;
|
|
||||||
import io.anuke.mindustry.input.CursorType;
|
|
||||||
import io.anuke.mindustry.net.In;
|
|
||||||
import io.anuke.mindustry.type.ItemStack;
|
|
||||||
import io.anuke.mindustry.type.Recipe;
|
|
||||||
import io.anuke.mindustry.world.BarType;
|
|
||||||
import io.anuke.mindustry.world.Block;
|
|
||||||
import io.anuke.mindustry.world.Tile;
|
|
||||||
import io.anuke.mindustry.world.meta.BlockBar;
|
|
||||||
import io.anuke.ucore.core.Effects;
|
|
||||||
import io.anuke.ucore.core.Graphics;
|
|
||||||
import io.anuke.ucore.graphics.Draw;
|
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.world;
|
|
||||||
|
|
||||||
public class BreakBlock extends Block {
|
|
||||||
private static final float decaySpeedScl = 6f;
|
|
||||||
|
|
||||||
public BreakBlock(String name) {
|
|
||||||
super(name);
|
|
||||||
solidifes = true;
|
|
||||||
update = true;
|
|
||||||
size = Integer.parseInt(name.charAt(name.length()-1) + "");
|
|
||||||
health = 1;
|
|
||||||
layer = Layer.placement;
|
|
||||||
consumesTap = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSolidFor(Tile tile) {
|
|
||||||
BreakEntity entity = tile.entity();
|
|
||||||
return entity.previous == null || entity.previous.solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public CursorType getCursor(Tile tile) {
|
|
||||||
return CursorType.hand;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void tapped(Tile tile, Player player) {
|
|
||||||
CallBlocks.onBreakSelect(player, tile);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBars(){
|
|
||||||
bars.replace(new BlockBar(BarType.health, true, tile -> (float)tile.<BreakEntity>entity().progress));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroyed(Tile tile){
|
|
||||||
Effects.effect(ExplosionFx.blockExplosionSmoke, tile);
|
|
||||||
|
|
||||||
if(!tile.floor().solid && !tile.floor().isLiquid){
|
|
||||||
RubbleDecal.create(tile.drawx(), tile.drawy(), size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterDestroyed(Tile tile, TileEntity e){
|
|
||||||
BreakEntity entity = (BreakEntity)e;
|
|
||||||
|
|
||||||
if(entity.previous.synthetic()){
|
|
||||||
tile.setBlock(entity.previous);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void draw(Tile tile){
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void drawLayer(Tile tile) {
|
|
||||||
BreakEntity entity = tile.entity();
|
|
||||||
|
|
||||||
Shaders.blockbuild.color = Palette.remove;
|
|
||||||
|
|
||||||
if(entity.previous == null) return;
|
|
||||||
|
|
||||||
for(TextureRegion region : entity.previous.getBlockIcon()){
|
|
||||||
Shaders.blockbuild.region = region;
|
|
||||||
Shaders.blockbuild.progress = (float)(1f-entity.progress); //progress reversed
|
|
||||||
Shaders.blockbuild.apply();
|
|
||||||
|
|
||||||
Draw.rect(region, tile.drawx(), tile.drawy(), entity.previous.rotate ? tile.getRotation() * 90 : 0);
|
|
||||||
|
|
||||||
Graphics.flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void drawShadow(Tile tile) {
|
|
||||||
BreakEntity entity = tile.entity();
|
|
||||||
|
|
||||||
if(entity.previous instanceof BreakBlock || entity.previous == null || entity.previous.shadowRegion == null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
entity.previous.drawShadow(tile);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void update(Tile tile) {
|
|
||||||
BreakEntity entity = tile.entity();
|
|
||||||
|
|
||||||
if(entity.progress >= 1f){
|
|
||||||
CallBlocks.onBreakFinish(tile);
|
|
||||||
}else if(entity.progress < 0f){
|
|
||||||
CallBlocks.onBreakDeath(tile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TileEntity getEntity() {
|
|
||||||
return new BreakEntity();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Remote(called = Loc.server, in = In.blocks)
|
|
||||||
public static void onBreakDeath(Tile tile){
|
|
||||||
BreakEntity entity = tile.entity();
|
|
||||||
|
|
||||||
Team team = tile.getTeam();
|
|
||||||
tile.setBlock(entity.previous);
|
|
||||||
tile.setTeam(team);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Remote(called = Loc.server, in = In.blocks)
|
|
||||||
public static void onBreakFinish(Tile tile){
|
|
||||||
|
|
||||||
if(tile.entity instanceof BreakEntity){
|
|
||||||
BreakEntity entity = tile.entity();
|
|
||||||
Effects.effect(Fx.breakBlock, tile.drawx(), tile.drawy(), entity.previous.size);
|
|
||||||
}
|
|
||||||
|
|
||||||
world.removeBlock(tile);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Remote(called = Loc.both, targets = Loc.both, in = In.blocks, forward = true)
|
|
||||||
public static void onBreakSelect(Player player, Tile tile){
|
|
||||||
if(player == null || !(tile.entity instanceof BreakEntity)) return;
|
|
||||||
|
|
||||||
player.getPlaceQueue().clear();
|
|
||||||
player.addBuildRequest(new BuildRequest(tile.x, tile.y));
|
|
||||||
}
|
|
||||||
|
|
||||||
public class BreakEntity extends TileEntity{
|
|
||||||
private double[] accumulator;
|
|
||||||
|
|
||||||
public double progress = 0;
|
|
||||||
public Block previous;
|
|
||||||
public float breakTime;
|
|
||||||
|
|
||||||
public void addProgress(TileEntity core, Unit unit, double add){
|
|
||||||
Recipe recipe = Recipe.getByResult(previous);
|
|
||||||
|
|
||||||
if(recipe != null) {
|
|
||||||
ItemStack[] requirements = recipe.requirements;
|
|
||||||
|
|
||||||
for (int i = 0; i < requirements.length; i++) {
|
|
||||||
accumulator[i] += requirements[i].amount * add / 2f; //add scaled amount progressed to the accumulator
|
|
||||||
int amount = (int) (accumulator[i]); //get amount
|
|
||||||
|
|
||||||
if (amount > 0) { //if it's positive, add it to the core
|
|
||||||
int accepting = core.tile.block().acceptStack(requirements[i].item, amount, core.tile, unit);
|
|
||||||
core.tile.block().handleStack(requirements[i].item, amount, core.tile, unit);
|
|
||||||
|
|
||||||
accumulator[i] -= accepting;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
progress += add;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float progress(){
|
|
||||||
return (float)progress;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void set(Block previous){
|
|
||||||
this.previous = previous;
|
|
||||||
if(Recipe.getByResult(previous) != null){
|
|
||||||
this.accumulator = new double[Recipe.getByResult(previous).requirements.length];
|
|
||||||
this.breakTime = Recipe.getByResult(previous).cost;
|
|
||||||
}else{
|
|
||||||
this.breakTime = 20f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,6 +7,7 @@ import io.anuke.mindustry.content.fx.ExplosionFx;
|
|||||||
import io.anuke.mindustry.content.fx.Fx;
|
import io.anuke.mindustry.content.fx.Fx;
|
||||||
import io.anuke.mindustry.entities.Player;
|
import io.anuke.mindustry.entities.Player;
|
||||||
import io.anuke.mindustry.entities.TileEntity;
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
|
import io.anuke.mindustry.entities.Unit;
|
||||||
import io.anuke.mindustry.entities.effect.RubbleDecal;
|
import io.anuke.mindustry.entities.effect.RubbleDecal;
|
||||||
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
|
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
@@ -16,6 +17,7 @@ import io.anuke.mindustry.graphics.Palette;
|
|||||||
import io.anuke.mindustry.graphics.Shaders;
|
import io.anuke.mindustry.graphics.Shaders;
|
||||||
import io.anuke.mindustry.input.CursorType;
|
import io.anuke.mindustry.input.CursorType;
|
||||||
import io.anuke.mindustry.net.In;
|
import io.anuke.mindustry.net.In;
|
||||||
|
import io.anuke.mindustry.type.ItemStack;
|
||||||
import io.anuke.mindustry.type.Recipe;
|
import io.anuke.mindustry.type.Recipe;
|
||||||
import io.anuke.mindustry.world.BarType;
|
import io.anuke.mindustry.world.BarType;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
@@ -25,16 +27,15 @@ import io.anuke.mindustry.world.meta.BlockBar;
|
|||||||
import io.anuke.ucore.core.Effects;
|
import io.anuke.ucore.core.Effects;
|
||||||
import io.anuke.ucore.core.Graphics;
|
import io.anuke.ucore.core.Graphics;
|
||||||
import io.anuke.ucore.graphics.Draw;
|
import io.anuke.ucore.graphics.Draw;
|
||||||
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.threads;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class BuildBlock extends Block {
|
public class BuildBlock extends Block {
|
||||||
private static final float decaySpeedScl = 6f;
|
|
||||||
|
|
||||||
public BuildBlock(String name) {
|
public BuildBlock(String name) {
|
||||||
super(name);
|
super(name);
|
||||||
update = true;
|
update = true;
|
||||||
@@ -48,7 +49,7 @@ public class BuildBlock extends Block {
|
|||||||
@Override
|
@Override
|
||||||
public boolean isSolidFor(Tile tile) {
|
public boolean isSolidFor(Tile tile) {
|
||||||
BuildEntity entity = tile.entity();
|
BuildEntity entity = tile.entity();
|
||||||
return entity.recipe.result.solid || entity.previous.solid;
|
return entity == null || entity.recipe == null || entity.recipe.result.solid || entity.previous.solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -58,7 +59,13 @@ public class BuildBlock extends Block {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tapped(Tile tile, Player player) {
|
public void tapped(Tile tile, Player player) {
|
||||||
CallBlocks.onBuildSelect(player, tile);
|
BuildEntity entity = tile.entity();
|
||||||
|
|
||||||
|
//if the target is constructible, begin constructing
|
||||||
|
if(entity.recipe != null){
|
||||||
|
player.clearBuilding();
|
||||||
|
player.addBuildRequest(new BuildRequest(tile.x, tile.y, tile.getRotation(), entity.recipe));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -79,7 +86,7 @@ public class BuildBlock extends Block {
|
|||||||
public void afterDestroyed(Tile tile, TileEntity e){
|
public void afterDestroyed(Tile tile, TileEntity e){
|
||||||
BuildEntity entity = (BuildEntity)e;
|
BuildEntity entity = (BuildEntity)e;
|
||||||
|
|
||||||
if(entity.previous.synthetic()){
|
if(entity.previous != null && entity.previous.synthetic()){
|
||||||
tile.setBlock(entity.previous);
|
tile.setBlock(entity.previous);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,10 +95,13 @@ public class BuildBlock extends Block {
|
|||||||
public void draw(Tile tile){
|
public void draw(Tile tile){
|
||||||
BuildEntity entity = tile.entity();
|
BuildEntity entity = tile.entity();
|
||||||
|
|
||||||
if(entity.previous.synthetic()) {
|
//When breaking, don't draw the previous block... since it's the thing you were breaking
|
||||||
for (TextureRegion region : entity.previous.getBlockIcon()) {
|
if(entity.recipe != null && entity.previous == entity.recipe.result){
|
||||||
Draw.rect(region, tile.drawx(), tile.drawy(), entity.recipe.result.rotate ? tile.getRotation() * 90 : 0);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (TextureRegion region : entity.previous.getBlockIcon()) {
|
||||||
|
Draw.rect(region, tile.drawx(), tile.drawy(), entity.previous.rotate ? tile.getRotation() * 90 : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,12 +111,16 @@ public class BuildBlock extends Block {
|
|||||||
|
|
||||||
Shaders.blockbuild.color = Palette.accent;
|
Shaders.blockbuild.color = Palette.accent;
|
||||||
|
|
||||||
for(TextureRegion region : entity.recipe.result.getBlockIcon()){
|
Block target = entity.recipe == null ? entity.previous : entity.recipe.result;
|
||||||
|
|
||||||
|
if(target == null) return;
|
||||||
|
|
||||||
|
for(TextureRegion region : target.getBlockIcon()){
|
||||||
Shaders.blockbuild.region = region;
|
Shaders.blockbuild.region = region;
|
||||||
Shaders.blockbuild.progress = (float)entity.progress;
|
Shaders.blockbuild.progress = (float)entity.progress;
|
||||||
Shaders.blockbuild.apply();
|
Shaders.blockbuild.apply();
|
||||||
|
|
||||||
Draw.rect(region, tile.drawx(), tile.drawy(), entity.recipe.result.rotate ? tile.getRotation() * 90 : 0);
|
Draw.rect(region, tile.drawx(), tile.drawy(), target.rotate ? tile.getRotation() * 90 : 0);
|
||||||
|
|
||||||
Graphics.flush();
|
Graphics.flush();
|
||||||
}
|
}
|
||||||
@@ -116,26 +130,16 @@ public class BuildBlock extends Block {
|
|||||||
public void drawShadow(Tile tile) {
|
public void drawShadow(Tile tile) {
|
||||||
BuildEntity entity = tile.entity();
|
BuildEntity entity = tile.entity();
|
||||||
|
|
||||||
if(entity.recipe != null && entity.recipe.result != null){
|
if(entity.recipe != null){
|
||||||
entity.recipe.result.drawShadow(tile);
|
entity.recipe.result.drawShadow(tile);
|
||||||
|
}else if(entity.previous != null){
|
||||||
|
entity.previous.drawShadow(tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Tile tile) {
|
public void update(Tile tile) {
|
||||||
BuildEntity entity = tile.entity();
|
|
||||||
|
|
||||||
if(entity.progress >= 1f){
|
|
||||||
CallBlocks.onBuildFinish(tile, entity.lastBuilder);
|
|
||||||
}else if(entity.progress < 0f){
|
|
||||||
CallBlocks.onBuildDeath(tile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!entity.updated){
|
|
||||||
entity.progress -= 1f/entity.recipe.cost/decaySpeedScl;
|
|
||||||
}
|
|
||||||
|
|
||||||
entity.updated = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -144,73 +148,86 @@ public class BuildBlock extends Block {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Remote(called = Loc.server, in = In.blocks)
|
@Remote(called = Loc.server, in = In.blocks)
|
||||||
public static void onBuildDeath(Tile tile){
|
public static void onDeconstructFinish(Tile tile, Block block){
|
||||||
if(tile.entity == null) return;
|
Effects.effect(Fx.breakBlock, tile.drawx(), tile.drawy(), block.size);
|
||||||
tile.entity.damage(tile.entity.health + 1);
|
world.removeBlock(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(called = Loc.server, in = In.blocks)
|
@Remote(called = Loc.server, in = In.blocks)
|
||||||
public static void onBuildFinish(Tile tile, Player lastBuilder){
|
public static void onConstructFinish(Tile tile, Block block, int builderID, byte rotation){
|
||||||
if(tile.entity == null || !(tile.entity instanceof BuildEntity)) return;
|
|
||||||
BuildEntity entity = tile.entity();
|
|
||||||
|
|
||||||
Team team = tile.getTeam();
|
Team team = tile.getTeam();
|
||||||
tile.setBlock(entity.recipe.result);
|
tile.setBlock(block);
|
||||||
tile.setTeam(team);
|
tile.setTeam(team);
|
||||||
Effects.effect(Fx.placeBlock, tile.drawx(), tile.drawy(), entity.recipe.result.size);
|
tile.setRotation(rotation);
|
||||||
|
Effects.effect(Fx.placeBlock, tile.drawx(), tile.drawy(), block.size);
|
||||||
|
|
||||||
//last builder was this local client player, call placed()
|
//last builder was this local client player, call placed()
|
||||||
if(lastBuilder != null && lastBuilder.isLocal){
|
if(!headless && builderID == players[0].id){
|
||||||
//this is run delayed, since if this is called on the server, all clients need to recieve the onBuildFinish()
|
//this is run delayed, since if this is called on the server, all clients need to recieve the onBuildFinish()
|
||||||
//event first before they can recieve the placed() event modification results
|
//event first before they can recieve the placed() event modification results
|
||||||
threads.runDelay(() -> tile.block().placed(tile));
|
threads.runDelay(() -> tile.block().placed(tile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(called = Loc.both, targets = Loc.both, in = In.blocks, forward = true)
|
|
||||||
public static void onBuildSelect(Player player, Tile tile){
|
|
||||||
if(player == null || !(tile.entity instanceof BuildEntity)) return;
|
|
||||||
|
|
||||||
BuildEntity entity = tile.entity();
|
|
||||||
|
|
||||||
player.getPlaceQueue().clear();
|
|
||||||
player.addBuildRequest(new BuildRequest(tile.x, tile.y, tile.getRotation(), entity.recipe));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Remote(called = Loc.server, targets = Loc.both, in = In.blocks, forward = true)
|
|
||||||
public static void onBuildDeselect(Player player){
|
|
||||||
if(player == null) return;
|
|
||||||
|
|
||||||
player.getPlaceQueue().clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class BuildEntity extends TileEntity{
|
public class BuildEntity extends TileEntity{
|
||||||
|
/**The recipe of the block that is being constructed.
|
||||||
|
* If there is no recipe for this block, as is the case with rocks, 'previous' is used.*/
|
||||||
public Recipe recipe;
|
public Recipe recipe;
|
||||||
|
|
||||||
public double progress = 0;
|
public double progress = 0;
|
||||||
public double lastProgress;
|
public double lastProgress;
|
||||||
|
public double buildCost;
|
||||||
|
/**The block that used to be here.
|
||||||
|
* If a non-recipe block is being deconstructed, this is the block that is being deconstructed.*/
|
||||||
public Block previous;
|
public Block previous;
|
||||||
public Player lastBuilder;
|
|
||||||
|
|
||||||
private double[] accumulator;
|
private double[] accumulator;
|
||||||
private boolean updated;
|
|
||||||
|
|
||||||
public void addProgress(InventoryModule inventory, double amount){
|
public void construct(Unit builder, TileEntity core, double amount){
|
||||||
double maxProgress = checkRequired(inventory, amount);
|
double maxProgress = checkRequired(core.items, amount);
|
||||||
|
|
||||||
for (int i = 0; i < recipe.requirements.length; i++) {
|
for (int i = 0; i < recipe.requirements.length; i++) {
|
||||||
accumulator[i] += recipe.requirements[i].amount*maxProgress; //add min amount progressed to the accumulator
|
accumulator[i] += recipe.requirements[i].amount*maxProgress; //add min amount progressed to the accumulator
|
||||||
}
|
}
|
||||||
|
|
||||||
maxProgress = checkRequired(inventory, maxProgress);
|
maxProgress = checkRequired(core.items, maxProgress);
|
||||||
|
|
||||||
progress += maxProgress;
|
progress = Mathf.clamp(progress + maxProgress);
|
||||||
|
|
||||||
lastProgress = maxProgress;
|
lastProgress = maxProgress;
|
||||||
updated = true;
|
|
||||||
|
if(progress >= 1f){
|
||||||
|
CallBlocks.onConstructFinish(tile, recipe.result, builder.getID(), tile.getRotation());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public double checkRequired(InventoryModule inventory, double amount){
|
public void deconstruct(Unit builder, TileEntity core, double amount){
|
||||||
|
Recipe recipe = Recipe.getByResult(previous);
|
||||||
|
|
||||||
|
if(recipe != null) {
|
||||||
|
ItemStack[] requirements = recipe.requirements;
|
||||||
|
|
||||||
|
for (int i = 0; i < requirements.length; i++) {
|
||||||
|
accumulator[i] += requirements[i].amount * amount / 2f; //add scaled amount progressed to the accumulator
|
||||||
|
int accumulated = (int) (accumulator[i]); //get amount
|
||||||
|
|
||||||
|
if (amount > 0) { //if it's positive, add it to the core
|
||||||
|
int accepting = core.tile.block().acceptStack(requirements[i].item, accumulated, core.tile, builder);
|
||||||
|
core.tile.block().handleStack(requirements[i].item, accumulated, core.tile, builder);
|
||||||
|
|
||||||
|
accumulator[i] -= accepting;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
progress = Mathf.clamp(progress - amount);
|
||||||
|
|
||||||
|
if(progress <= 0){
|
||||||
|
CallBlocks.onDeconstructFinish(tile, recipe == null ? previous : recipe.result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private double checkRequired(InventoryModule inventory, double amount){
|
||||||
double maxProgress = amount;
|
double maxProgress = amount;
|
||||||
|
|
||||||
for(int i = 0; i < recipe.requirements.length; i ++){
|
for(int i = 0; i < recipe.requirements.length; i ++){
|
||||||
@@ -239,11 +256,23 @@ public class BuildBlock extends Block {
|
|||||||
return (float)progress;
|
return (float)progress;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(Block previous, Recipe recipe){
|
public void setConstruct(Block previous, Recipe recipe){
|
||||||
updated = true;
|
|
||||||
this.recipe = recipe;
|
this.recipe = recipe;
|
||||||
this.previous = previous;
|
this.previous = previous;
|
||||||
this.accumulator = new double[recipe.requirements.length];
|
this.accumulator = new double[recipe.requirements.length];
|
||||||
|
this.buildCost = recipe.cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeconstruct(Block previous){
|
||||||
|
this.previous = previous;
|
||||||
|
this.progress = 1f;
|
||||||
|
if(Recipe.getByResult(previous) != null){
|
||||||
|
this.recipe = Recipe.getByResult(previous);
|
||||||
|
this.accumulator = new double[Recipe.getByResult(previous).requirements.length];
|
||||||
|
this.buildCost = Recipe.getByResult(previous).cost;
|
||||||
|
}else{
|
||||||
|
this.buildCost = 20f; //default no-recipe build cost is 20
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -41,6 +41,13 @@ public class ItemTurret extends CooledTurret {
|
|||||||
return Math.min((int)((maxAmmo - entity.totalAmmo) / ammoMap.get(item).quantityMultiplier), amount);
|
return Math.min((int)((maxAmmo - entity.totalAmmo) / ammoMap.get(item).quantityMultiplier), amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleStack(Item item, int amount, Tile tile, Unit source){
|
||||||
|
for (int i = 0; i < amount; i++) {
|
||||||
|
handleItem(item, tile, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//currently can't remove items from turrets.
|
//currently can't remove items from turrets.
|
||||||
@Override
|
@Override
|
||||||
public int removeStack(Tile tile, Item item, int amount) {
|
public int removeStack(Tile tile, Item item, int amount) {
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ public abstract class Turret extends Block{
|
|||||||
stats.add(BlockStat.inaccuracy, (int)inaccuracy, StatUnit.degrees);
|
stats.add(BlockStat.inaccuracy, (int)inaccuracy, StatUnit.degrees);
|
||||||
stats.add(BlockStat.reload, 60f/reload, StatUnit.seconds);
|
stats.add(BlockStat.reload, 60f/reload, StatUnit.seconds);
|
||||||
stats.add(BlockStat.shots, shots, StatUnit.none);
|
stats.add(BlockStat.shots, shots, StatUnit.none);
|
||||||
|
stats.add(BlockStat.targetsAir, targetAir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import io.anuke.mindustry.content.fx.ShootFx;
|
|||||||
import io.anuke.mindustry.entities.Player;
|
import io.anuke.mindustry.entities.Player;
|
||||||
import io.anuke.mindustry.entities.TileEntity;
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
import io.anuke.mindustry.entities.bullet.Bullet;
|
import io.anuke.mindustry.entities.bullet.Bullet;
|
||||||
|
import io.anuke.mindustry.entities.effect.ItemDrop;
|
||||||
import io.anuke.mindustry.gen.CallBlocks;
|
import io.anuke.mindustry.gen.CallBlocks;
|
||||||
import io.anuke.mindustry.gen.CallEntity;
|
|
||||||
import io.anuke.mindustry.graphics.Layer;
|
import io.anuke.mindustry.graphics.Layer;
|
||||||
import io.anuke.mindustry.graphics.Palette;
|
import io.anuke.mindustry.graphics.Palette;
|
||||||
import io.anuke.mindustry.net.In;
|
import io.anuke.mindustry.net.In;
|
||||||
@@ -241,7 +241,7 @@ public class MassDriver extends Block {
|
|||||||
if(amountDropped > 0){
|
if(amountDropped > 0){
|
||||||
float angle = Mathf.range(180f);
|
float angle = Mathf.range(180f);
|
||||||
float vs = Mathf.random(0f, 4f);
|
float vs = Mathf.random(0f, 4f);
|
||||||
CallEntity.createItemDrop(Item.getByID(i), amountDropped, bullet.x, bullet.y, Angles.trnsx(angle, vs), Angles.trnsy(angle, vs));
|
ItemDrop.create(Item.getByID(i), amountDropped, bullet.x, bullet.y, Angles.trnsx(angle, vs), Angles.trnsy(angle, vs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package io.anuke.mindustry.world.blocks.power;
|
package io.anuke.mindustry.world.blocks.power;
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color;
|
import com.badlogic.gdx.graphics.Color;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||||
import io.anuke.mindustry.content.fx.BlockFx;
|
import io.anuke.mindustry.content.fx.BlockFx;
|
||||||
import io.anuke.mindustry.entities.TileEntity;
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.Item;
|
||||||
@@ -29,6 +30,7 @@ public abstract class ItemGenerator extends PowerGenerator {
|
|||||||
protected Effect generateEffect = BlockFx.generatespark, explodeEffect =
|
protected Effect generateEffect = BlockFx.generatespark, explodeEffect =
|
||||||
BlockFx.generatespark;
|
BlockFx.generatespark;
|
||||||
protected Color heatColor = Color.valueOf("ff9b59");
|
protected Color heatColor = Color.valueOf("ff9b59");
|
||||||
|
protected TextureRegion topRegion;
|
||||||
|
|
||||||
public ItemGenerator(String name) {
|
public ItemGenerator(String name) {
|
||||||
super(name);
|
super(name);
|
||||||
@@ -36,6 +38,12 @@ public abstract class ItemGenerator extends PowerGenerator {
|
|||||||
hasItems = true;
|
hasItems = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void load() {
|
||||||
|
super.load();
|
||||||
|
topRegion = Draw.region(name + "-top");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setStats() {
|
public void setStats() {
|
||||||
super.setStats();
|
super.setStats();
|
||||||
@@ -61,7 +69,7 @@ public abstract class ItemGenerator extends PowerGenerator {
|
|||||||
float alpha = (entity.items.totalItems() > 0 ? 1f : Mathf.clamp(entity.generateTime));
|
float alpha = (entity.items.totalItems() > 0 ? 1f : Mathf.clamp(entity.generateTime));
|
||||||
alpha = alpha * 0.7f + Mathf.absin(Timers.time(), 12f, 0.3f) * alpha;
|
alpha = alpha * 0.7f + Mathf.absin(Timers.time(), 12f, 0.3f) * alpha;
|
||||||
Draw.alpha(alpha);
|
Draw.alpha(alpha);
|
||||||
Draw.rect(name + "-top", tile.worldx(), tile.worldy());
|
Draw.rect(topRegion, tile.drawx(), tile.drawy());
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import io.anuke.mindustry.world.Tile;
|
|||||||
import io.anuke.mindustry.world.meta.BlockBar;
|
import io.anuke.mindustry.world.meta.BlockBar;
|
||||||
import io.anuke.mindustry.world.meta.BlockStat;
|
import io.anuke.mindustry.world.meta.BlockStat;
|
||||||
import io.anuke.mindustry.world.meta.StatUnit;
|
import io.anuke.mindustry.world.meta.StatUnit;
|
||||||
|
import io.anuke.mindustry.world.meta.values.LiquidFilterValue;
|
||||||
import io.anuke.ucore.core.Effects;
|
import io.anuke.ucore.core.Effects;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
import io.anuke.ucore.graphics.Draw;
|
import io.anuke.ucore.graphics.Draw;
|
||||||
@@ -38,6 +39,7 @@ public class NuclearReactor extends PowerGenerator {
|
|||||||
protected float heating = 0.009f; //heating per frame
|
protected float heating = 0.009f; //heating per frame
|
||||||
protected float coolantPower = 0.015f; //how much heat decreases per coolant unit
|
protected float coolantPower = 0.015f; //how much heat decreases per coolant unit
|
||||||
protected float smokeThreshold = 0.3f; //threshold at which block starts smoking
|
protected float smokeThreshold = 0.3f; //threshold at which block starts smoking
|
||||||
|
protected float maxLiquidUse = 1f; //max liquid use per frame
|
||||||
protected int explosionRadius = 19;
|
protected int explosionRadius = 19;
|
||||||
protected int explosionDamage = 135;
|
protected int explosionDamage = 135;
|
||||||
protected float flashThreshold = 0.46f; //heat threshold at which the lights start flashing
|
protected float flashThreshold = 0.46f; //heat threshold at which the lights start flashing
|
||||||
@@ -49,6 +51,7 @@ public class NuclearReactor extends PowerGenerator {
|
|||||||
liquidCapacity = 50;
|
liquidCapacity = 50;
|
||||||
powerCapacity = 80f;
|
powerCapacity = 80f;
|
||||||
hasItems = true;
|
hasItems = true;
|
||||||
|
hasLiquids = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -62,6 +65,7 @@ public class NuclearReactor extends PowerGenerator {
|
|||||||
public void setStats(){
|
public void setStats(){
|
||||||
super.setStats();
|
super.setStats();
|
||||||
stats.add(BlockStat.inputItem, generateItem);
|
stats.add(BlockStat.inputItem, generateItem);
|
||||||
|
stats.add(BlockStat.inputLiquid, new LiquidFilterValue(liquid -> liquid.temperature <= 0.5f));
|
||||||
stats.add(BlockStat.maxPowerGeneration, powerMultiplier*60f, StatUnit.powerSecond);
|
stats.add(BlockStat.maxPowerGeneration, powerMultiplier*60f, StatUnit.powerSecond);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,12 +89,12 @@ public class NuclearReactor extends PowerGenerator {
|
|||||||
|
|
||||||
if(entity.liquids.liquid.temperature <= 0.5f){ //is coolant
|
if(entity.liquids.liquid.temperature <= 0.5f){ //is coolant
|
||||||
float pow = coolantPower * entity.liquids.liquid.heatCapacity; //heat depleted per unit of liquid
|
float pow = coolantPower * entity.liquids.liquid.heatCapacity; //heat depleted per unit of liquid
|
||||||
float maxUsed = Math.min(entity.liquids.amount, entity.heat / pow); //max that can be cooled in terms of liquid
|
float maxUsed = Math.min(Math.min(entity.liquids.amount, entity.heat / pow), maxLiquidUse * Timers.delta()); //max that can be cooled in terms of liquid
|
||||||
entity.heat -= maxUsed * pow;
|
entity.heat -= maxUsed * pow;
|
||||||
entity.liquids.amount -= maxUsed;
|
entity.liquids.amount -= maxUsed;
|
||||||
}else{ //is heater
|
}else{ //is heater
|
||||||
float heat = coolantPower * entity.liquids.liquid.heatCapacity / 4f; //heat created per unit of liquid
|
float heat = coolantPower * entity.liquids.liquid.heatCapacity / 4f; //heat created per unit of liquid
|
||||||
float maxUsed = Math.min(entity.liquids.amount, (1f - entity.heat) / heat); //max liquid used
|
float maxUsed = Math.min(Math.min(entity.liquids.amount, (1f - entity.heat) / heat), maxLiquidUse * Timers.delta()); //max liquid used
|
||||||
entity.heat += maxUsed * heat;
|
entity.heat += maxUsed * heat;
|
||||||
entity.liquids.amount -= maxUsed;
|
entity.liquids.amount -= maxUsed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,12 @@ public class PowerDistributor extends PowerBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected boolean shouldDistribute(Tile tile, Tile other) {
|
protected boolean shouldDistribute(Tile tile, Tile other) {
|
||||||
return !(other.block() instanceof PowerGenerator) || other.entity.power.amount / other.block().powerCapacity < tile.entity.power.amount / powerCapacity;
|
other = other.target();
|
||||||
|
//only generators can distribute to other generators
|
||||||
|
return (!(other.block() instanceof PowerGenerator) || tile.block() instanceof PowerGenerator)
|
||||||
|
&& other.entity != null
|
||||||
|
&& other.block().hasPower
|
||||||
|
&& other.entity.power.amount / other.block().powerCapacity < tile.entity.power.amount / powerCapacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -129,14 +129,14 @@ public class PowerNode extends PowerBlock{
|
|||||||
Tile link = world.tile(x, y);
|
Tile link = world.tile(x, y);
|
||||||
if(link != null) link = link.target();
|
if(link != null) link = link.target();
|
||||||
|
|
||||||
if(link != tile && linkValid(tile, link)){
|
if(link != tile && linkValid(tile, link, false)){
|
||||||
boolean linked = linked(tile, link);
|
boolean linked = linked(tile, link);
|
||||||
Draw.color(linked ? Palette.place : Palette.breakInvalid);
|
Draw.color(linked ? Palette.place : Palette.breakInvalid);
|
||||||
|
|
||||||
Lines.square(link.drawx(), link.drawy(),
|
Lines.square(link.drawx(), link.drawy(),
|
||||||
link.block().size * tilesize / 2f + 1f + (linked ? 0f : Mathf.absin(Timers.time(), 4f, 1f)));
|
link.block().size * tilesize / 2f + 1f + (linked ? 0f : Mathf.absin(Timers.time(), 4f, 1f)));
|
||||||
|
|
||||||
if(entity.links.size >= maxNodes && !linked){
|
if((entity.links.size >= maxNodes || (link.block() instanceof PowerNode && ((DistributorEntity)link.entity).links.size >= ((PowerNode)link.block()).maxNodes)) && !linked){
|
||||||
Draw.color();
|
Draw.color();
|
||||||
Draw.rect("cross-" + link.block().size, link.drawx(), link.drawy());
|
Draw.rect("cross-" + link.block().size, link.drawx(), link.drawy());
|
||||||
}
|
}
|
||||||
@@ -190,11 +190,13 @@ public class PowerNode extends PowerBlock{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected boolean shouldDistribute(Tile tile, Tile other) {
|
protected boolean shouldDistribute(Tile tile, Tile other) {
|
||||||
return other.entity.power.amount / other.block().powerCapacity <= tile.entity.power.amount / powerCapacity;
|
return other.entity.power.amount / other.block().powerCapacity <= tile.entity.power.amount / powerCapacity &&
|
||||||
|
!(other.block() instanceof PowerGenerator); //do not distribute to power generators
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean shouldLeechPower(Tile tile, Tile other){
|
protected boolean shouldLeechPower(Tile tile, Tile other){
|
||||||
return !(other.block() instanceof PowerNode)
|
return !(other.block() instanceof PowerNode)
|
||||||
|
&& other.block() instanceof PowerDistributor //only suck power from batteries and power generators
|
||||||
&& other.entity.power.amount / other.block().powerCapacity > tile.entity.power.amount / powerCapacity;
|
&& other.entity.power.amount / other.block().powerCapacity > tile.entity.power.amount / powerCapacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,6 +244,10 @@ public class PowerNode extends PowerBlock{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected boolean linkValid(Tile tile, Tile link){
|
protected boolean linkValid(Tile tile, Tile link){
|
||||||
|
return linkValid(tile, link, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean linkValid(Tile tile, Tile link, boolean checkMaxNodes){
|
||||||
if(!(tile != link && link != null && link.block().hasPower)) return false;
|
if(!(tile != link && link != null && link.block().hasPower)) return false;
|
||||||
|
|
||||||
if(link.block() instanceof PowerNode){
|
if(link.block() instanceof PowerNode){
|
||||||
@@ -250,7 +256,7 @@ public class PowerNode extends PowerBlock{
|
|||||||
return Vector2.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy()) <= Math.max(laserRange * tilesize,
|
return Vector2.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy()) <= Math.max(laserRange * tilesize,
|
||||||
((PowerNode)link.block()).laserRange * tilesize) - tilesize/2f
|
((PowerNode)link.block()).laserRange * tilesize) - tilesize/2f
|
||||||
+ (link.block().size-1)*tilesize/2f + (tile.block().size-1)*tilesize/2f &&
|
+ (link.block().size-1)*tilesize/2f + (tile.block().size-1)*tilesize/2f &&
|
||||||
(oe.links.size < ((PowerNode)link.block()).maxNodes || oe.links.contains(tile.packedPosition()));
|
(!checkMaxNodes || (oe.links.size < ((PowerNode)link.block()).maxNodes || oe.links.contains(tile.packedPosition())));
|
||||||
}else{
|
}else{
|
||||||
return Vector2.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy())
|
return Vector2.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy())
|
||||||
<= laserRange * tilesize - tilesize/2f + (link.block().size-1)*tilesize;
|
<= laserRange * tilesize - tilesize/2f + (link.block().size-1)*tilesize;
|
||||||
@@ -276,8 +282,9 @@ public class PowerNode extends PowerBlock{
|
|||||||
return new DistributorEntity();
|
return new DistributorEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(targets = Loc.both, called = Loc.both, in = In.blocks, forward = true)
|
@Remote(targets = Loc.both, called = Loc.server, in = In.blocks, forward = true)
|
||||||
public static void linkPowerDistributors(Player player, Tile tile, Tile other){
|
public static void linkPowerDistributors(Player player, Tile tile, Tile other){
|
||||||
|
|
||||||
DistributorEntity entity = tile.entity();
|
DistributorEntity entity = tile.entity();
|
||||||
|
|
||||||
if(!entity.links.contains(other.packedPosition())){
|
if(!entity.links.contains(other.packedPosition())){
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ public class Drill extends Block{
|
|||||||
protected Liquid inputLiquid = Liquids.water;
|
protected Liquid inputLiquid = Liquids.water;
|
||||||
/**Whether the liquid is required to drill. If false, then it will be used as a speed booster.*/
|
/**Whether the liquid is required to drill. If false, then it will be used as a speed booster.*/
|
||||||
protected boolean liquidRequired = false;
|
protected boolean liquidRequired = false;
|
||||||
/**How many times faster the drill will progress when booster by liquid.*/
|
/**How many times faster the drill will progress when boosted by liquid.*/
|
||||||
protected float liquidBoostIntensity = 1.3f;
|
protected float liquidBoostIntensity = 1.6f;
|
||||||
/**Speed at which the drill speeds up.*/
|
/**Speed at which the drill speeds up.*/
|
||||||
protected float warmupSpeed = 0.02f;
|
protected float warmupSpeed = 0.02f;
|
||||||
|
|
||||||
@@ -224,7 +224,7 @@ public class Drill extends Block{
|
|||||||
@Override
|
@Override
|
||||||
public boolean canPlaceOn(Tile tile) {
|
public boolean canPlaceOn(Tile tile) {
|
||||||
if(isMultiblock()){
|
if(isMultiblock()){
|
||||||
for(Tile other : tile.getLinkedTiles(drawTiles)){
|
for(Tile other : tile.getLinkedTilesAs(this, drawTiles)){
|
||||||
if(isValid(other)){
|
if(isValid(other)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import io.anuke.mindustry.world.Tile;
|
|||||||
import io.anuke.ucore.graphics.Draw;
|
import io.anuke.ucore.graphics.Draw;
|
||||||
import io.anuke.ucore.util.Mathf;
|
import io.anuke.ucore.util.Mathf;
|
||||||
|
|
||||||
public class PlasteelCompressor extends GenericCrafter {
|
public class PlastaniumCompressor extends GenericCrafter {
|
||||||
|
|
||||||
public PlasteelCompressor(String name) {
|
public PlastaniumCompressor(String name) {
|
||||||
super(name);
|
super(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ public class Pump extends LiquidBlock{
|
|||||||
public boolean canPlaceOn(Tile tile) {
|
public boolean canPlaceOn(Tile tile) {
|
||||||
if(isMultiblock()){
|
if(isMultiblock()){
|
||||||
Liquid last = null;
|
Liquid last = null;
|
||||||
for(Tile other : tile.getLinkedTiles(drawTiles)){
|
for(Tile other : tile.getLinkedTilesAs(this, drawTiles)){
|
||||||
//can't place pump on block with multiple liquids
|
//can't place pump on block with multiple liquids
|
||||||
if(last != null && other.floor().liquidDrop != last){
|
if(last != null && other.floor().liquidDrop != last){
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ public class SolidPump extends Pump {
|
|||||||
@Override
|
@Override
|
||||||
public boolean canPlaceOn(Tile tile) {
|
public boolean canPlaceOn(Tile tile) {
|
||||||
if(isMultiblock()){
|
if(isMultiblock()){
|
||||||
for(Tile other : tile.getLinkedTiles(drawTiles)){
|
for(Tile other : tile.getLinkedTilesAs(this, drawTiles)){
|
||||||
if(isValid(other)){
|
if(isValid(other)){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import io.anuke.mindustry.entities.Player;
|
|||||||
import io.anuke.mindustry.entities.TileEntity;
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
import io.anuke.mindustry.entities.Unit;
|
import io.anuke.mindustry.entities.Unit;
|
||||||
import io.anuke.mindustry.entities.Units;
|
import io.anuke.mindustry.entities.Units;
|
||||||
|
import io.anuke.mindustry.entities.traits.SpawnerTrait;
|
||||||
import io.anuke.mindustry.entities.units.BaseUnit;
|
import io.anuke.mindustry.entities.units.BaseUnit;
|
||||||
import io.anuke.mindustry.entities.units.UnitType;
|
import io.anuke.mindustry.entities.units.UnitType;
|
||||||
import io.anuke.mindustry.gen.CallBlocks;
|
import io.anuke.mindustry.gen.CallBlocks;
|
||||||
@@ -21,6 +22,7 @@ import io.anuke.mindustry.net.In;
|
|||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.Item;
|
||||||
import io.anuke.mindustry.type.ItemType;
|
import io.anuke.mindustry.type.ItemType;
|
||||||
|
import io.anuke.mindustry.world.BarType;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.mindustry.world.meta.BlockFlag;
|
import io.anuke.mindustry.world.meta.BlockFlag;
|
||||||
import io.anuke.ucore.core.Effects;
|
import io.anuke.ucore.core.Effects;
|
||||||
@@ -64,6 +66,13 @@ public class CoreBlock extends StorageBlock {
|
|||||||
flags = EnumSet.of(BlockFlag.resupplyPoint, BlockFlag.target);
|
flags = EnumSet.of(BlockFlag.resupplyPoint, BlockFlag.target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBars() {
|
||||||
|
super.setBars();
|
||||||
|
|
||||||
|
bars.remove(BarType.inventory);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load() {
|
public void load() {
|
||||||
super.load();
|
super.load();
|
||||||
@@ -132,7 +141,7 @@ public class CoreBlock extends StorageBlock {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean acceptItem(Item item, Tile tile, Tile source) {
|
public boolean acceptItem(Item item, Tile tile, Tile source) {
|
||||||
return tile.entity.items.items[item.id]< itemCapacity && item.type == ItemType.material;
|
return tile.entity.items.items[item.id] < itemCapacity && item.type == ItemType.material;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -192,14 +201,13 @@ public class CoreBlock extends StorageBlock {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!found) {
|
if(!found){
|
||||||
|
|
||||||
BaseUnit unit = droneType.create(tile.getTeam());
|
BaseUnit unit = droneType.create(tile.getTeam());
|
||||||
entity.droneID = unit.id;
|
unit.setSpawner(tile);
|
||||||
unit.setDead(true);
|
unit.setDead(true);
|
||||||
unit.setGroup(unitGroups[unit.getTeam().ordinal()]);
|
unit.add();
|
||||||
CallBlocks.onCoreUnitSet(tile, unit);
|
|
||||||
unit.setGroup(null);
|
entity.droneID = unit.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,18 +251,17 @@ public class CoreBlock extends StorageBlock {
|
|||||||
entity.currentUnit.rotation = 90f;
|
entity.currentUnit.rotation = 90f;
|
||||||
entity.currentUnit.setNet(tile.drawx(), tile.drawy());
|
entity.currentUnit.setNet(tile.drawx(), tile.drawy());
|
||||||
entity.currentUnit.add();
|
entity.currentUnit.add();
|
||||||
|
|
||||||
if(entity.currentUnit instanceof Player){
|
|
||||||
((Player) entity.currentUnit).baseRotation = 90f;
|
|
||||||
}
|
|
||||||
|
|
||||||
entity.currentUnit = null;
|
entity.currentUnit = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Remote(called = Loc.server, in = In.blocks)
|
||||||
|
public static void setCoreSolid(Tile tile, boolean solid){
|
||||||
|
CoreEntity entity = tile.entity();
|
||||||
|
entity.solid = solid;
|
||||||
|
}
|
||||||
|
/*
|
||||||
@Remote(called = Loc.server, in = In.blocks)
|
@Remote(called = Loc.server, in = In.blocks)
|
||||||
public static void onCoreUnitSet(Tile tile, Unit player){
|
public static void onCoreUnitSet(Tile tile, Unit player){
|
||||||
if(player == null) return;
|
|
||||||
|
|
||||||
CoreEntity entity = tile.entity();
|
CoreEntity entity = tile.entity();
|
||||||
entity.currentUnit = player;
|
entity.currentUnit = player;
|
||||||
entity.progress = 0f;
|
entity.progress = 0f;
|
||||||
@@ -264,14 +271,8 @@ public class CoreBlock extends StorageBlock {
|
|||||||
((Player) player).setRespawning(true);
|
((Player) player).setRespawning(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
@Remote(called = Loc.server, in = In.blocks)
|
public class CoreEntity extends TileEntity implements SpawnerTrait{
|
||||||
public static void setCoreSolid(Tile tile, boolean solid){
|
|
||||||
CoreEntity entity = tile.entity();
|
|
||||||
entity.solid = solid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CoreEntity extends TileEntity{
|
|
||||||
public Unit currentUnit;
|
public Unit currentUnit;
|
||||||
int droneID = -1;
|
int droneID = -1;
|
||||||
boolean solid = true;
|
boolean solid = true;
|
||||||
@@ -280,12 +281,20 @@ public class CoreBlock extends StorageBlock {
|
|||||||
float time;
|
float time;
|
||||||
float heat;
|
float heat;
|
||||||
|
|
||||||
public void trySetPlayer(Player player){
|
@Override
|
||||||
|
public void updateSpawning(Unit unit) {
|
||||||
if(currentUnit == null){
|
if(currentUnit == null){
|
||||||
CallBlocks.onCoreUnitSet(tile, player);
|
currentUnit = unit;
|
||||||
|
progress = 0f;
|
||||||
|
unit.set(tile.drawx(), tile.drawy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getSpawnProgress() {
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(DataOutputStream stream) throws IOException {
|
public void write(DataOutputStream stream) throws IOException {
|
||||||
stream.writeBoolean(solid);
|
stream.writeBoolean(solid);
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ import io.anuke.mindustry.content.Mechs;
|
|||||||
import io.anuke.mindustry.content.fx.Fx;
|
import io.anuke.mindustry.content.fx.Fx;
|
||||||
import io.anuke.mindustry.entities.Player;
|
import io.anuke.mindustry.entities.Player;
|
||||||
import io.anuke.mindustry.entities.TileEntity;
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
|
import io.anuke.mindustry.entities.Unit;
|
||||||
import io.anuke.mindustry.entities.Units;
|
import io.anuke.mindustry.entities.Units;
|
||||||
|
import io.anuke.mindustry.entities.traits.SpawnerTrait;
|
||||||
import io.anuke.mindustry.gen.CallBlocks;
|
import io.anuke.mindustry.gen.CallBlocks;
|
||||||
import io.anuke.mindustry.graphics.Palette;
|
import io.anuke.mindustry.graphics.Palette;
|
||||||
import io.anuke.mindustry.graphics.Shaders;
|
import io.anuke.mindustry.graphics.Shaders;
|
||||||
@@ -52,7 +54,7 @@ public class MechFactory extends Block{
|
|||||||
public void tapped(Tile tile, Player player) {
|
public void tapped(Tile tile, Player player) {
|
||||||
|
|
||||||
if(checkValidTap(tile, player)){
|
if(checkValidTap(tile, player)){
|
||||||
CallBlocks.onMechFactoryBegin(player, tile);
|
CallBlocks.onMechFactoryTap(player, tile);
|
||||||
}else if(player.isLocal && mobile){
|
}else if(player.isLocal && mobile){
|
||||||
player.moveTarget = tile.entity;
|
player.moveTarget = tile.entity;
|
||||||
}
|
}
|
||||||
@@ -115,7 +117,7 @@ public class MechFactory extends Block{
|
|||||||
entity.heat = Mathf.lerpDelta(entity.heat, 1f, 0.1f);
|
entity.heat = Mathf.lerpDelta(entity.heat, 1f, 0.1f);
|
||||||
entity.progress += 1f / buildTime;
|
entity.progress += 1f / buildTime;
|
||||||
|
|
||||||
entity.time += entity.heat;
|
entity.time += 0.5f;
|
||||||
|
|
||||||
if(entity.progress >= 1f){
|
if(entity.progress >= 1f){
|
||||||
CallBlocks.onMechFactoryDone(tile);
|
CallBlocks.onMechFactoryDone(tile);
|
||||||
@@ -134,19 +136,12 @@ public class MechFactory extends Block{
|
|||||||
return new MechFactoryEntity();
|
return new MechFactoryEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(targets = Loc.both, called = Loc.server, in = In.blocks, forward = true)
|
@Remote(targets = Loc.both, called = Loc.server, in = In.blocks)
|
||||||
public static void onMechFactoryBegin(Player player, Tile tile){
|
public static void onMechFactoryTap(Player player, Tile tile){
|
||||||
if(!checkValidTap(tile, player)) return;
|
if(!checkValidTap(tile, player)) return;
|
||||||
|
|
||||||
MechFactoryEntity entity = tile.entity();
|
MechFactoryEntity entity = tile.entity();
|
||||||
entity.progress = 0f;
|
player.beginRespawning(entity);
|
||||||
entity.player = player;
|
|
||||||
|
|
||||||
player.rotation = 90f;
|
|
||||||
player.baseRotation = 90f;
|
|
||||||
player.set(entity.x, entity.y);
|
|
||||||
player.setDead(true);
|
|
||||||
player.setRespawning(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(called = Loc.server, in = In.blocks)
|
@Remote(called = Loc.server, in = In.blocks)
|
||||||
@@ -154,6 +149,9 @@ public class MechFactory extends Block{
|
|||||||
MechFactoryEntity entity = tile.entity();
|
MechFactoryEntity entity = tile.entity();
|
||||||
|
|
||||||
Effects.effect(Fx.spawn, entity);
|
Effects.effect(Fx.spawn, entity);
|
||||||
|
|
||||||
|
if(entity.player == null) return;
|
||||||
|
|
||||||
Mech result = ((MechFactory)tile.block()).mech;
|
Mech result = ((MechFactory)tile.block()).mech;
|
||||||
|
|
||||||
if(entity.player.mech == result){
|
if(entity.player.mech == result){
|
||||||
@@ -176,12 +174,32 @@ public class MechFactory extends Block{
|
|||||||
Math.abs(player.y - tile.drawy()) <= tile.block().size * tilesize / 2f && entity.player == null;
|
Math.abs(player.y - tile.drawy()) <= tile.block().size * tilesize / 2f && entity.player == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MechFactoryEntity extends TileEntity{
|
public class MechFactoryEntity extends TileEntity implements SpawnerTrait{
|
||||||
public Player player;
|
Player player;
|
||||||
public float progress;
|
float progress;
|
||||||
public float time;
|
float time;
|
||||||
public float heat;
|
float heat;
|
||||||
public boolean open;
|
boolean open;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateSpawning(Unit unit) {
|
||||||
|
if(!(unit instanceof Player)) throw new IllegalArgumentException("Mech factories only accept player respawners.");
|
||||||
|
|
||||||
|
if(player == null){
|
||||||
|
progress = 0f;
|
||||||
|
player = (Player)unit;
|
||||||
|
|
||||||
|
player.rotation = 90f;
|
||||||
|
player.baseRotation = 90f;
|
||||||
|
player.set(x, y);
|
||||||
|
player.beginRespawning(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getSpawnProgress() {
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(DataOutputStream stream) throws IOException {
|
public void write(DataOutputStream stream) throws IOException {
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ import io.anuke.mindustry.Vars;
|
|||||||
import io.anuke.mindustry.content.fx.Fx;
|
import io.anuke.mindustry.content.fx.Fx;
|
||||||
import io.anuke.mindustry.entities.Player;
|
import io.anuke.mindustry.entities.Player;
|
||||||
import io.anuke.mindustry.entities.TileEntity;
|
import io.anuke.mindustry.entities.TileEntity;
|
||||||
|
import io.anuke.mindustry.entities.Unit;
|
||||||
import io.anuke.mindustry.entities.Units;
|
import io.anuke.mindustry.entities.Units;
|
||||||
|
import io.anuke.mindustry.entities.traits.SpawnerTrait;
|
||||||
import io.anuke.mindustry.gen.CallBlocks;
|
import io.anuke.mindustry.gen.CallBlocks;
|
||||||
import io.anuke.mindustry.graphics.Palette;
|
import io.anuke.mindustry.graphics.Palette;
|
||||||
import io.anuke.mindustry.graphics.Shaders;
|
import io.anuke.mindustry.graphics.Shaders;
|
||||||
@@ -28,6 +30,7 @@ import java.io.IOException;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
|
//TODO re-implement properly
|
||||||
public class Reconstructor extends Block{
|
public class Reconstructor extends Block{
|
||||||
protected float departTime = 30f;
|
protected float departTime = 30f;
|
||||||
protected float arriveTime = 40f;
|
protected float arriveTime = 40f;
|
||||||
@@ -117,9 +120,9 @@ public class Reconstructor extends Block{
|
|||||||
if(entity.current != null){
|
if(entity.current != null){
|
||||||
float progress = entity.departing ? entity.updateTime : (1f - entity.updateTime);
|
float progress = entity.departing ? entity.updateTime : (1f - entity.updateTime);
|
||||||
|
|
||||||
Player player = entity.current;
|
//Player player = entity.current;
|
||||||
|
|
||||||
TextureRegion region = player.mech.iconRegion;
|
TextureRegion region = entity.current.getIconRegion();
|
||||||
|
|
||||||
Shaders.build.region = region;
|
Shaders.build.region = region;
|
||||||
Shaders.build.progress = progress;
|
Shaders.build.progress = progress;
|
||||||
@@ -157,7 +160,7 @@ public class Reconstructor extends Block{
|
|||||||
if(entity.departing){
|
if(entity.departing){
|
||||||
//force respawn if there's suddenly nothing to link to
|
//force respawn if there's suddenly nothing to link to
|
||||||
if(!validLink(tile, entity.link)){
|
if(!validLink(tile, entity.link)){
|
||||||
entity.current.setRespawning(false);
|
//entity.current.setRespawning(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,7 +171,7 @@ public class Reconstructor extends Block{
|
|||||||
//no power? death.
|
//no power? death.
|
||||||
if(other.power.amount < powerPerTeleport){
|
if(other.power.amount < powerPerTeleport){
|
||||||
entity.current.setDead(true);
|
entity.current.setDead(true);
|
||||||
entity.current.setRespawning(false);
|
//entity.current.setRespawning(false);
|
||||||
entity.current = null;
|
entity.current = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -263,8 +266,8 @@ public class Reconstructor extends Block{
|
|||||||
player.rotation = 90f;
|
player.rotation = 90f;
|
||||||
player.baseRotation = 90f;
|
player.baseRotation = 90f;
|
||||||
player.setDead(true);
|
player.setDead(true);
|
||||||
player.setRespawning(true);
|
// player.setRespawning(true);
|
||||||
player.setRespawning();
|
//player.setRespawning();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Remote(targets = Loc.both, called = Loc.server, in = In.blocks, forward = true)
|
@Remote(targets = Loc.both, called = Loc.server, in = In.blocks, forward = true)
|
||||||
@@ -300,12 +303,22 @@ public class Reconstructor extends Block{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ReconstructorEntity extends TileEntity{
|
public class ReconstructorEntity extends TileEntity implements SpawnerTrait{
|
||||||
public Player current;
|
Unit current;
|
||||||
public float updateTime;
|
float updateTime;
|
||||||
public float time;
|
float time;
|
||||||
public int link;
|
int link;
|
||||||
public boolean solid = true, departing;
|
boolean solid = true, departing;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateSpawning(Unit unit) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getSpawnProgress() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(DataOutputStream stream) throws IOException {
|
public void write(DataOutputStream stream) throws IOException {
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ public class UnitFactory extends Block {
|
|||||||
|
|
||||||
if(!Net.client()) {
|
if(!Net.client()) {
|
||||||
BaseUnit unit = factory.type.create(tile.getTeam());
|
BaseUnit unit = factory.type.create(tile.getTeam());
|
||||||
unit.setSpawner(entity);
|
unit.setSpawner(tile);
|
||||||
unit.set(tile.drawx(), tile.drawy());
|
unit.set(tile.drawx(), tile.drawy());
|
||||||
unit.add();
|
unit.add();
|
||||||
unit.getVelocity().y = factory.launchVelocity;
|
unit.getVelocity().y = factory.launchVelocity;
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import io.anuke.mindustry.io.MapTileData.TileDataMarker;
|
|||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.Item;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
|
import io.anuke.mindustry.world.blocks.Floor;
|
||||||
import io.anuke.ucore.noise.RidgedPerlin;
|
import io.anuke.ucore.noise.RidgedPerlin;
|
||||||
import io.anuke.ucore.noise.Simplex;
|
import io.anuke.ucore.noise.Simplex;
|
||||||
import io.anuke.ucore.util.Geometry;
|
import io.anuke.ucore.util.Geometry;
|
||||||
@@ -133,7 +134,7 @@ public class WorldGenerator {
|
|||||||
if(entry.noise.octaveNoise2D(2, 0.7, 1f / (2 + i*2), x, y)/2f +
|
if(entry.noise.octaveNoise2D(2, 0.7, 1f / (2 + i*2), x, y)/2f +
|
||||||
entry.ridge.getValue(x, y, 1f / (28 + i*4)) >= 2.0f - entry.frequency*4.0f
|
entry.ridge.getValue(x, y, 1f / (28 + i*4)) >= 2.0f - entry.frequency*4.0f
|
||||||
&& entry.ridge.getValue(x+9999, y+9999, 1f/100f) > 0.4){
|
&& entry.ridge.getValue(x+9999, y+9999, 1f/100f) > 0.4){
|
||||||
tile.setFloor(OreBlocks.get(tile.floor(), entry.item));
|
tile.setFloor((Floor) OreBlocks.get(tile.floor(), entry.item));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ public enum BlockStat {
|
|||||||
shots(StatCategory.shooting),
|
shots(StatCategory.shooting),
|
||||||
reload(StatCategory.shooting),
|
reload(StatCategory.shooting),
|
||||||
powerShot(StatCategory.shooting),
|
powerShot(StatCategory.shooting),
|
||||||
|
targetsAir(StatCategory.shooting)
|
||||||
|
,
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,7 @@ import com.badlogic.gdx.utils.OrderedMap;
|
|||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.Item;
|
||||||
import io.anuke.mindustry.type.ItemStack;
|
import io.anuke.mindustry.type.ItemStack;
|
||||||
import io.anuke.mindustry.type.Liquid;
|
import io.anuke.mindustry.type.Liquid;
|
||||||
import io.anuke.mindustry.world.meta.values.ItemValue;
|
import io.anuke.mindustry.world.meta.values.*;
|
||||||
import io.anuke.mindustry.world.meta.values.LiquidValue;
|
|
||||||
import io.anuke.mindustry.world.meta.values.NumberValue;
|
|
||||||
import io.anuke.mindustry.world.meta.values.StringValue;
|
|
||||||
import io.anuke.ucore.util.Bundles;
|
import io.anuke.ucore.util.Bundles;
|
||||||
import io.anuke.ucore.util.Log;
|
import io.anuke.ucore.util.Log;
|
||||||
|
|
||||||
@@ -24,6 +21,11 @@ public class BlockStats {
|
|||||||
add(stat, new NumberValue(value, unit));
|
add(stat, new NumberValue(value, unit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**Adds a single y/n boolean value.*/
|
||||||
|
public void add(BlockStat stat, boolean value){
|
||||||
|
add(stat, new BooleanValue(value));
|
||||||
|
}
|
||||||
|
|
||||||
/**Adds an item value.*/
|
/**Adds an item value.*/
|
||||||
public void add(BlockStat stat, Item item){
|
public void add(BlockStat stat, Item item){
|
||||||
add(stat, new ItemValue(new ItemStack(item, 1)));
|
add(stat, new ItemValue(new ItemStack(item, 1)));
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package io.anuke.mindustry.world.meta.values;
|
||||||
|
|
||||||
|
import io.anuke.mindustry.world.meta.StatValue;
|
||||||
|
import io.anuke.ucore.scene.ui.layout.Table;
|
||||||
|
|
||||||
|
public class BooleanValue implements StatValue {
|
||||||
|
private final boolean value;
|
||||||
|
|
||||||
|
public BooleanValue(boolean value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void display(Table table) {
|
||||||
|
table.add(!value ? "$text.no" : "$text.yes");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,9 +26,6 @@ public class ByteSerializer implements Serialization {
|
|||||||
throw new RuntimeException("Unregistered class: " + ClassReflection.getSimpleName(o.getClass()));
|
throw new RuntimeException("Unregistered class: " + ClassReflection.getSimpleName(o.getClass()));
|
||||||
byteBuffer.put(id);
|
byteBuffer.put(id);
|
||||||
((Packet) o).write(byteBuffer);
|
((Packet) o).write(byteBuffer);
|
||||||
synchronized (packetPoolLock) {
|
|
||||||
Pooling.free(o);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import io.anuke.mindustry.net.NetworkIO;
|
|||||||
import io.anuke.mindustry.net.Packets.Connect;
|
import io.anuke.mindustry.net.Packets.Connect;
|
||||||
import io.anuke.mindustry.net.Packets.Disconnect;
|
import io.anuke.mindustry.net.Packets.Disconnect;
|
||||||
import io.anuke.ucore.function.Consumer;
|
import io.anuke.ucore.function.Consumer;
|
||||||
|
import io.anuke.ucore.util.Pooling;
|
||||||
import io.anuke.ucore.util.Strings;
|
import io.anuke.ucore.util.Strings;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -26,6 +27,7 @@ import java.nio.channels.ClosedSelectorException;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
import static io.anuke.mindustry.net.Net.packetPoolLock;
|
||||||
|
|
||||||
public class KryoClient implements ClientProvider{
|
public class KryoClient implements ClientProvider{
|
||||||
Client client;
|
Client client;
|
||||||
@@ -134,6 +136,10 @@ public class KryoClient implements ClientProvider{
|
|||||||
}else{
|
}else{
|
||||||
client.sendUDP(object);
|
client.sendUDP(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
synchronized (packetPoolLock) {
|
||||||
|
Pooling.free(object);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -6,9 +6,7 @@ import io.anuke.ucore.util.ColorCodes;
|
|||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.headless;
|
import static io.anuke.mindustry.Vars.headless;
|
||||||
|
|
||||||
@@ -65,25 +63,4 @@ public class KryoCore {
|
|||||||
private static int calculateLag() {
|
private static int calculateLag() {
|
||||||
return fakeLagMin + (int)(Math.random() * (fakeLagMax - fakeLagMin));
|
return fakeLagMin + (int)(Math.random() * (fakeLagMax - fakeLagMin));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**Executes something in a potentially unreliable way. Used to simulate lag and packet errors with UDP.*/
|
|
||||||
public static void recieveUnreliable(Runnable run){
|
|
||||||
if(fakeLag && threadPool == null){
|
|
||||||
threadPool = Executors.newScheduledThreadPool(1, r -> {
|
|
||||||
Thread t = Executors.defaultThreadFactory().newThread(r);
|
|
||||||
t.setDaemon(true);
|
|
||||||
return t;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if(fakeLag){
|
|
||||||
do {
|
|
||||||
if (Math.random() >= fakeLagDrop) {
|
|
||||||
threadPool.schedule(run, calculateLag(), TimeUnit.MILLISECONDS);
|
|
||||||
}
|
|
||||||
} while (Math.random() < fakeLagDuplicate);
|
|
||||||
}else{
|
|
||||||
run.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,7 @@ import io.anuke.mindustry.net.Net.SendMode;
|
|||||||
import io.anuke.mindustry.net.Net.ServerProvider;
|
import io.anuke.mindustry.net.Net.ServerProvider;
|
||||||
import io.anuke.mindustry.net.NetConnection;
|
import io.anuke.mindustry.net.NetConnection;
|
||||||
import io.anuke.mindustry.net.NetworkIO;
|
import io.anuke.mindustry.net.NetworkIO;
|
||||||
import io.anuke.mindustry.net.Packets.Connect;
|
import io.anuke.mindustry.net.Packets.*;
|
||||||
import io.anuke.mindustry.net.Packets.Disconnect;
|
|
||||||
import io.anuke.mindustry.net.Packets.StreamBegin;
|
|
||||||
import io.anuke.mindustry.net.Packets.StreamChunk;
|
|
||||||
import io.anuke.mindustry.net.Streamable;
|
import io.anuke.mindustry.net.Streamable;
|
||||||
import io.anuke.ucore.UCore;
|
import io.anuke.ucore.UCore;
|
||||||
import io.anuke.ucore.core.Timers;
|
import io.anuke.ucore.core.Timers;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import io.anuke.mindustry.entities.Player;
|
|||||||
import io.anuke.mindustry.game.Difficulty;
|
import io.anuke.mindustry.game.Difficulty;
|
||||||
import io.anuke.mindustry.game.EventType.GameOverEvent;
|
import io.anuke.mindustry.game.EventType.GameOverEvent;
|
||||||
import io.anuke.mindustry.game.GameMode;
|
import io.anuke.mindustry.game.GameMode;
|
||||||
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.gen.Call;
|
import io.anuke.mindustry.gen.Call;
|
||||||
import io.anuke.mindustry.io.Map;
|
import io.anuke.mindustry.io.Map;
|
||||||
import io.anuke.mindustry.io.SaveIO;
|
import io.anuke.mindustry.io.SaveIO;
|
||||||
@@ -138,7 +139,7 @@ public class ServerControl extends Module {
|
|||||||
Log.info("Stopped server.");
|
Log.info("Stopped server.");
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.register("host", "[mapname] [mode]", "Open the server with a specific map.", arg -> {
|
handler.register("host", "[mode] [mapname]", "Open the server with a specific map.", arg -> {
|
||||||
if(state.is(State.playing)){
|
if(state.is(State.playing)){
|
||||||
err("Already hosting. Type 'stop' to stop hosting first.");
|
err("Already hosting. Type 'stop' to stop hosting first.");
|
||||||
return;
|
return;
|
||||||
@@ -147,34 +148,39 @@ public class ServerControl extends Module {
|
|||||||
Map result = null;
|
Map result = null;
|
||||||
|
|
||||||
if(arg.length > 0) {
|
if(arg.length > 0) {
|
||||||
String search = arg[0];
|
|
||||||
for (Map map : world.maps().all()) {
|
|
||||||
if (map.name.equalsIgnoreCase(search))
|
|
||||||
result = map;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(result == null){
|
|
||||||
err("No map with name &y'{0}'&lr found.", search);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GameMode mode;
|
GameMode mode;
|
||||||
try{
|
try{
|
||||||
mode = arg.length < 2 ? GameMode.waves : GameMode.valueOf(arg[1]);
|
mode = GameMode.valueOf(arg[0]);
|
||||||
}catch (IllegalArgumentException e){
|
}catch (IllegalArgumentException e){
|
||||||
err("No gamemode '{0}' found.", arg[1]);
|
err("No gamemode '{0}' found.", arg[0]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
info("Loading map...");
|
info("Loading map...");
|
||||||
state.mode = mode;
|
state.mode = mode;
|
||||||
|
|
||||||
|
if(arg.length > 1) {
|
||||||
|
String search = arg[1];
|
||||||
|
for (Map map : world.maps().all()) {
|
||||||
|
if (map.name.equalsIgnoreCase(search))
|
||||||
|
result = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == null) {
|
||||||
|
err("No map with name &y'{0}'&lr found.", search);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
logic.reset();
|
logic.reset();
|
||||||
world.loadMap(result);
|
world.loadMap(result);
|
||||||
|
}else{
|
||||||
|
Log.info("&ly&fiNo map specified, so a procedural one was generated.");
|
||||||
|
world.loadProceduralMap();
|
||||||
|
}
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
world.loadProceduralMap();
|
|
||||||
Log.info("&ly&fiNo map specified, so a procedural one was generated.");
|
Log.info("&ly&fiNo map specified, so a procedural one was generated.");
|
||||||
|
world.loadProceduralMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
logic.play();
|
logic.play();
|
||||||
@@ -194,10 +200,10 @@ public class ServerControl extends Module {
|
|||||||
if(state.is(State.menu)){
|
if(state.is(State.menu)){
|
||||||
info("&lyStatus: &rserver closed");
|
info("&lyStatus: &rserver closed");
|
||||||
}else{
|
}else{
|
||||||
info("&lyStatus: &lcPlaying on map &fi{0}&fb &lb/&lc Wave {1} &lb/&lc {2}",
|
info("&lyStatus: &lcPlaying on map &fi{0}&fb &lb/&lc Wave {1} &lb/&lc {2} &lb/&lc {3}",
|
||||||
Strings.capitalize(world.getMap().name), state.wave, Strings.capitalize(state.difficulty.name()));
|
Strings.capitalize(world.getMap().name), state.wave, Strings.capitalize(state.difficulty.name()), Strings.capitalize(state.mode.name()));
|
||||||
if(state.enemies > 0){
|
if(state.mode.disableWaveTimer){
|
||||||
info("&ly{0} enemies remaining.", state.enemies);
|
info("&ly{0} enemies.", unitGroups[Team.red.ordinal()].size());
|
||||||
}else{
|
}else{
|
||||||
info("&ly{0} seconds until next wave.", (int)(state.wavetime / 60));
|
info("&ly{0} seconds until next wave.", (int)(state.wavetime / 60));
|
||||||
}
|
}
|
||||||
@@ -221,7 +227,7 @@ public class ServerControl extends Module {
|
|||||||
if(playerGroup.size() > 0) {
|
if(playerGroup.size() > 0) {
|
||||||
info("&lyPlayers: {0}", playerGroup.size());
|
info("&lyPlayers: {0}", playerGroup.size());
|
||||||
for (Player p : playerGroup.all()) {
|
for (Player p : playerGroup.all()) {
|
||||||
print(" &y{0} / Connection {1} / IP: {2}", p.name, p.con, p.con.address);
|
print(" &y{0} / Connection {1} / IP: {2}", p.name, p.con.id, p.con.address);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
info("&lyNo players connected.");
|
info("&lyNo players connected.");
|
||||||
@@ -464,6 +470,7 @@ public class ServerControl extends Module {
|
|||||||
|
|
||||||
if(target != null){
|
if(target != null){
|
||||||
netServer.admins.adminPlayer(target.uuid, target.usid);
|
netServer.admins.adminPlayer(target.uuid, target.usid);
|
||||||
|
target.isAdmin = true;
|
||||||
info("Admin-ed player by ID: {0} / {1}", target.uuid, arg[0]);
|
info("Admin-ed player by ID: {0} / {1}", target.uuid, arg[0]);
|
||||||
}else{
|
}else{
|
||||||
info("Nobody with that name could be found.");
|
info("Nobody with that name could be found.");
|
||||||
@@ -487,6 +494,7 @@ public class ServerControl extends Module {
|
|||||||
|
|
||||||
if(target != null){
|
if(target != null){
|
||||||
netServer.admins.unAdminPlayer(target.uuid);
|
netServer.admins.unAdminPlayer(target.uuid);
|
||||||
|
target.isAdmin = false;
|
||||||
info("Un-admin-ed player by ID: {0} / {1}", target.uuid, arg[0]);
|
info("Un-admin-ed player by ID: {0} / {1}", target.uuid, arg[0]);
|
||||||
}else{
|
}else{
|
||||||
info("Nobody with that name could be found.");
|
info("Nobody with that name could be found.");
|
||||||
@@ -509,8 +517,6 @@ public class ServerControl extends Module {
|
|||||||
handler.register("runwave", "Trigger the next wave.", arg -> {
|
handler.register("runwave", "Trigger the next wave.", arg -> {
|
||||||
if(!state.is(State.playing)) {
|
if(!state.is(State.playing)) {
|
||||||
err("Not hosting. Host a game first.");
|
err("Not hosting. Host a game first.");
|
||||||
}else if(state.enemies > 0){
|
|
||||||
err("There are still {0} enemies remaining.", state.enemies);
|
|
||||||
}else{
|
}else{
|
||||||
logic.runWave();
|
logic.runWave();
|
||||||
info("Wave spawned.");
|
info("Wave spawned.");
|
||||||
|
|||||||
Reference in New Issue
Block a user