Compare commits

..

21 Commits
v85 ... v87

Author SHA1 Message Date
Anuken
9e0de644c4 more iOS fixes 2019-08-15 20:59:45 -04:00
Anuken
393bdfccaf iOS map export 2019-08-15 20:45:30 -04:00
Anuken
56c39799c8 things 2019-08-15 20:02:35 -04:00
Anuken
7f2a1374e4 Fixed truncated sounds 2019-08-15 14:16:41 -04:00
Anuken
6fa0ac56ac files 2019-08-15 13:33:23 -04:00
Anuken
89ee04c942 Machine ambient sounds 2019-08-15 13:32:36 -04:00
Anuken
c058163ab4 no 2019-08-15 00:12:06 -04:00
Anuken
2832dc69ef Random shoot sound pitch 2019-08-14 23:27:24 -04:00
Anuken
cb2e2ab9b2 OpenAL cleanup+refactor 2019-08-14 23:01:51 -04:00
Anuken
f342c38c62 openal stuff 2019-08-14 21:48:36 -04:00
Anuken
811e456f8f OpenAL audio backend for SDL 2019-08-14 20:50:26 -04:00
Anuken
000503d674 Update build.gradle 2019-08-14 13:53:23 -04:00
Anuken
d0bd29cfa0 fixed unnecessary asset copying 2019-08-14 13:47:16 -04:00
Anuken
d56565990e Fixed iOS audio issues 2019-08-14 13:10:29 -04:00
Anuken
b68734d679 iOS-specific format loading 2019-08-14 11:03:36 -04:00
Anuken
bf21c94bd7 Bugfixes 2019-08-14 10:27:10 -04:00
Anuken
b6b9685d57 wiki build script update 2019-08-13 23:53:22 -04:00
Anuken
f8adbda9c5 updated roboVM to 2.3.7 2019-08-13 23:26:25 -04:00
Anuken
c9178c3f2f Fixed power nodes in multiplayer 2019-08-13 22:47:31 -04:00
Anuken
84786c12d8 Bugfixes 2019-08-13 18:15:40 -04:00
Anuken
335b6ae0cc bundle 2019-08-13 17:48:19 -04:00
93 changed files with 1483 additions and 259 deletions

1
.gitignore vendored
View File

@@ -10,6 +10,7 @@ logs/
/desktop/mindustry-maps/ /desktop/mindustry-maps/
/desktop/gifexport/ /desktop/gifexport/
/core/lib/ /core/lib/
/ios/assets/
/core/assets-raw/sprites/generated/ /core/assets-raw/sprites/generated/
/core/assets-raw/sprites_out/ /core/assets-raw/sprites_out/
/annotations/build/ /annotations/build/

View File

@@ -79,7 +79,8 @@ public class AssetsAnnotationProcessor extends AbstractProcessor{
name = name + "s"; name = name + "s";
} }
load.addStatement(name + " = io.anuke.arc.Core.audio."+loadMethod+"(io.anuke.arc.Core.files.internal($S))", path.substring(path.lastIndexOf("/") + 1) + "/" + fname); load.addStatement(name + " = io.anuke.arc.Core.audio."+loadMethod+"(io.anuke.arc.Core.files.internal(io.anuke.arc.Core.app.getType() != io.anuke.arc.Application.ApplicationType.iOS ? $S : $S))",
path.substring(path.lastIndexOf("/") + 1) + "/" + fname, (path.substring(path.lastIndexOf("/") + 1) + "/" + fname).replace(".ogg", ".caf"));
dispose.addStatement(name + ".dispose()"); dispose.addStatement(name + ".dispose()");
dispose.addStatement(name + " = null"); dispose.addStatement(name + " = null");
type.addField(FieldSpec.builder(ClassName.bestGuess(rtype), name, Modifier.STATIC, Modifier.PUBLIC).initializer("new io.anuke.arc.audio.mock.Mock" + rtype.substring(rtype.lastIndexOf(".") + 1)+ "()").build()); type.addField(FieldSpec.builder(ClassName.bestGuess(rtype), name, Modifier.STATIC, Modifier.PUBLIC).initializer("new io.anuke.arc.audio.mock.Mock" + rtype.substring(rtype.lastIndexOf(".") + 1)+ "()").build());

View File

@@ -8,7 +8,7 @@ buildscript{
} }
dependencies{ dependencies{
classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.6' classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.7'
classpath "com.badlogicgames.gdx:gdx-tools:1.9.10" classpath "com.badlogicgames.gdx:gdx-tools:1.9.10"
classpath "com.badlogicgames.packr:packr:2.1-SNAPSHOT" classpath "com.badlogicgames.packr:packr:2.1-SNAPSHOT"
} }
@@ -23,7 +23,7 @@ allprojects{
if(!project.hasProperty("versionType")) versionType = 'official' if(!project.hasProperty("versionType")) versionType = 'official'
appName = 'Mindustry' appName = 'Mindustry'
gdxVersion = '1.9.10' gdxVersion = '1.9.10'
roboVMVersion = '2.3.6' roboVMVersion = '2.3.7'
arcHash = null arcHash = null
debugged = { debugged = {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@@ -514,6 +514,7 @@ setting.lasers.name = Show Power Lasers
setting.pixelate.name = Pixelate[lightgray] (disables animations) setting.pixelate.name = Pixelate[lightgray] (disables animations)
setting.minimap.name = Show Minimap setting.minimap.name = Show Minimap
setting.musicvol.name = Music Volume setting.musicvol.name = Music Volume
setting.ambientvol.name = Ambient Volume
setting.mutemusic.name = Mute Music setting.mutemusic.name = Mute Music
setting.sfxvol.name = SFX Volume setting.sfxvol.name = SFX Volume
setting.mutesound.name = Mute Sound setting.mutesound.name = Mute Sound

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
core/assets/sounds/break.ogg Executable file → Normal file

Binary file not shown.

Binary file not shown.

BIN
core/assets/sounds/buttonClick.ogg Executable file → Normal file

Binary file not shown.

BIN
core/assets/sounds/click.ogg Executable file → Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
core/assets/sounds/door.ogg Executable file → Normal file

Binary file not shown.

BIN
core/assets/sounds/drill.ogg Executable file → Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
core/assets/sounds/message.ogg Executable file → Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
core/assets/sounds/thruster.ogg Executable file → Normal file

Binary file not shown.

BIN
core/assets/sounds/unlock.ogg Executable file → Normal file

Binary file not shown.

Binary file not shown.

BIN
core/assets/sounds/windowHide.ogg Executable file → Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 575 KiB

After

Width:  |  Height:  |  Size: 575 KiB

12
core/convert_sounds.sh Executable file
View File

@@ -0,0 +1,12 @@
#convert from stereo to mono
cd assets/sounds/
for i in *.ogg; do
echo $i
ffmpeg -i "$i" -ac 1 "OUT_$i"
done
find . -type f ! -name "OUT_*" -delete
for file in OUT_*; do mv "$file" "${file#OUT_}"; done;
cd ../../

View File

@@ -133,6 +133,7 @@ public class Vars{
public static GlobalData data; public static GlobalData data;
public static EntityCollisions collisions; public static EntityCollisions collisions;
public static DefaultWaves defaultWaves; public static DefaultWaves defaultWaves;
public static LoopControl loops;
public static Control control; public static Control control;
public static Logic logic; public static Logic logic;
@@ -181,6 +182,7 @@ public class Vars{
content.setVerbose(); content.setVerbose();
} }
loops = new LoopControl();
defaultWaves = new DefaultWaves(); defaultWaves = new DefaultWaves();
collisions = new EntityCollisions(); collisions = new EntityCollisions();

View File

@@ -1608,8 +1608,8 @@ public class Blocks implements ContentList{
shootDuration = 220f; shootDuration = 220f;
powerUse = 14f; powerUse = 14f;
shootSound = Sounds.laserbig; shootSound = Sounds.laserbig;
idleSound = Sounds.beam; activeSound = Sounds.beam;
idleSoundVolume = 2f; activeSoundVolume = 2f;
health = 200 * size * size; health = 200 * size * size;
consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.5f)).update(false); consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.5f)).update(false);

View File

@@ -734,7 +734,7 @@ public class Fx implements ContentList{
shootSmallFlame = new Effect(32f, e -> { shootSmallFlame = new Effect(32f, e -> {
Draw.color(Pal.lightFlame, Pal.darkFlame, Color.GRAY, e.fin()); Draw.color(Pal.lightFlame, Pal.darkFlame, Color.GRAY, e.fin());
Angles.randLenVectors(e.id, 8, e.finpow() * 44f, e.rotation, 10f, (x, y) -> { Angles.randLenVectors(e.id, 8, e.finpow() * 60f, e.rotation, 10f, (x, y) -> {
Fill.circle(e.x + x, e.y + y, 0.65f + e.fout() * 1.5f); Fill.circle(e.x + x, e.y + y, 0.65f + e.fout() * 1.5f);
}); });
@@ -744,7 +744,7 @@ public class Fx implements ContentList{
shootPyraFlame = new Effect(33f, e -> { shootPyraFlame = new Effect(33f, e -> {
Draw.color(Pal.lightPyraFlame, Pal.darkPyraFlame, Color.GRAY, e.fin()); Draw.color(Pal.lightPyraFlame, Pal.darkPyraFlame, Color.GRAY, e.fin());
Angles.randLenVectors(e.id, 10, e.finpow() * 50f, e.rotation, 10f, (x, y) -> { Angles.randLenVectors(e.id, 10, e.finpow() * 70f, e.rotation, 10f, (x, y) -> {
Fill.circle(e.x + x, e.y + y, 0.65f + e.fout() * 1.6f); Fill.circle(e.x + x, e.y + y, 0.65f + e.fout() * 1.6f);
}); });

View File

@@ -196,7 +196,7 @@ public class UnitTypes implements ContentList{
mass = 5f; mass = 5f;
hitsize = 20f; hitsize = 20f;
rotatespeed = 0.06f; rotatespeed = 0.06f;
health = 4000; health = 3000;
weapon = new Weapon("chaos"){{ weapon = new Weapon("chaos"){{
length = 8f; length = 8f;
reload = 50f; reload = 50f;
@@ -220,7 +220,7 @@ public class UnitTypes implements ContentList{
mass = 5f; mass = 5f;
hitsize = 20f; hitsize = 20f;
rotatespeed = 0.06f; rotatespeed = 0.06f;
health = 10000; health = 9000;
weapon = new Weapon("eradication"){{ weapon = new Weapon("eradication"){{
length = 13f; length = 13f;
reload = 30f; reload = 30f;
@@ -313,7 +313,7 @@ public class UnitTypes implements ContentList{
}}; }};
lich = new UnitType("lich", Revenant.class, Revenant::new){{ lich = new UnitType("lich", Revenant.class, Revenant::new){{
health = 7000; health = 6000;
mass = 20f; mass = 20f;
hitsize = 40f; hitsize = 40f;
speed = 0.01f; speed = 0.01f;
@@ -346,7 +346,7 @@ public class UnitTypes implements ContentList{
}}; }};
reaper = new UnitType("reaper", Revenant.class, Revenant::new){{ reaper = new UnitType("reaper", Revenant.class, Revenant::new){{
health = 13000; health = 11000;
mass = 30f; mass = 30f;
hitsize = 56f; hitsize = 56f;
speed = 0.01f; speed = 0.01f;

View File

@@ -127,7 +127,7 @@ public class Control implements ApplicationListener{
Call.onGameOver(event.winner); Call.onGameOver(event.winner);
if(state.rules.zone != null && !Net.client()){ if(state.rules.zone != null && !Net.client()){
//remove zone save on game over //remove zone save on game over
if(saves.getZoneSlot() != null){ if(saves.getZoneSlot() != null && !state.rules.tutorial){
saves.getZoneSlot().delete(); saves.getZoneSlot().delete();
} }
} }
@@ -392,6 +392,7 @@ public class Control implements ApplicationListener{
data.checkSave(); data.checkSave();
music.update(); music.update();
loops.update();
if(!state.is(State.menu)){ if(!state.is(State.menu)){
input.update(); input.update();
@@ -415,7 +416,7 @@ public class Control implements ApplicationListener{
Platform.instance.updateRPC(); Platform.instance.updateRPC();
} }
if(Core.input.keyTap(Binding.pause) && !ui.restart.isShown() && (state.is(State.paused) || state.is(State.playing))){ if(Core.input.keyTap(Binding.pause) && !scene.hasDialog() && !ui.restart.isShown() && (state.is(State.paused) || state.is(State.playing))){
state.set(state.is(State.playing) ? State.paused : State.playing); state.set(state.is(State.playing) ? State.paused : State.playing);
} }

View File

@@ -5,7 +5,7 @@ import io.anuke.annotations.Annotations.Remote;
import io.anuke.arc.ApplicationListener; import io.anuke.arc.ApplicationListener;
import io.anuke.arc.Events; import io.anuke.arc.Events;
import io.anuke.arc.collection.ObjectSet.ObjectSetIterator; import io.anuke.arc.collection.ObjectSet.ObjectSetIterator;
import io.anuke.arc.util.Time; import io.anuke.arc.util.*;
import io.anuke.mindustry.content.*; import io.anuke.mindustry.content.*;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.*; import io.anuke.mindustry.entities.*;

View File

@@ -176,6 +176,7 @@ public class NetClient implements ApplicationListener{
public static void onKick(KickReason reason){ public static void onKick(KickReason reason){
netClient.disconnectQuietly(); netClient.disconnectQuietly();
state.set(State.menu); state.set(State.menu);
logic.reset();
if(!reason.quiet){ if(!reason.quiet){
if(reason.extraText() != null){ if(reason.extraText() != null){

View File

@@ -1,30 +1,28 @@
package io.anuke.mindustry.core; package io.anuke.mindustry.core;
import io.anuke.arc.*; import io.anuke.arc.*;
import io.anuke.arc.files.FileHandle; import io.anuke.arc.files.*;
import io.anuke.arc.function.Consumer; import io.anuke.arc.function.*;
import io.anuke.arc.function.Predicate;
import io.anuke.arc.graphics.*; import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.graphics.glutils.FrameBuffer; import io.anuke.arc.graphics.glutils.*;
import io.anuke.arc.math.Mathf; import io.anuke.arc.math.*;
import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.*;
import io.anuke.arc.math.geom.Vector2;
import io.anuke.arc.scene.ui.layout.*; import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*; import io.anuke.arc.util.*;
import io.anuke.arc.util.pooling.Pools; import io.anuke.arc.util.pooling.*;
import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.content.*;
import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.GameState.*;
import io.anuke.mindustry.entities.*; import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.effect.GroundEffectEntity; import io.anuke.mindustry.entities.effect.*;
import io.anuke.mindustry.entities.effect.GroundEffectEntity.GroundEffect; import io.anuke.mindustry.entities.effect.GroundEffectEntity.*;
import io.anuke.mindustry.entities.impl.EffectEntity; import io.anuke.mindustry.entities.impl.*;
import io.anuke.mindustry.entities.traits.*; import io.anuke.mindustry.entities.traits.*;
import io.anuke.mindustry.entities.type.*; import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.game.EventType.DisposeEvent; import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.*;
import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.world.blocks.defense.ForceProjector.ShieldEntity; import io.anuke.mindustry.world.blocks.defense.ForceProjector.*;
import static io.anuke.arc.Core.*; import static io.anuke.arc.Core.*;
import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.Vars.*;

View File

@@ -87,7 +87,8 @@ public class MapEditorDialog extends Dialog implements Disposable{
t.row(); t.row();
t.addImageTextButton("$editor.import", "icon-load-map", isize, () -> if(!ios){
t.addImageTextButton("$editor.import", "icon-load-map", isize, () ->
createDialog("$editor.import", createDialog("$editor.import",
"$editor.importmap", "$editor.importmap.description", "icon-load-map", (Runnable)loadDialog::show, "$editor.importmap", "$editor.importmap.description", "icon-load-map", (Runnable)loadDialog::show,
"$editor.importfile", "$editor.importfile.description", "icon-file", (Runnable)() -> "$editor.importfile", "$editor.importfile.description", "icon-file", (Runnable)() ->
@@ -115,24 +116,43 @@ public class MapEditorDialog extends Dialog implements Disposable{
Log.err(e); Log.err(e);
} }
}), true, FileChooser.pngFiles)) }), true, FileChooser.pngFiles))
); );
}
t.addImageTextButton("$editor.export", "icon-save-map", isize, () -> Cell cell = t.addImageTextButton("$editor.export", "icon-save-map", isize, () -> {
Platform.instance.showFileChooser("$editor.savemap", "Map Files", file -> { if(!ios){
file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension); Platform.instance.showFileChooser("$editor.savemap", "Map Files", file -> {
FileHandle result = file; file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension);
FileHandle result = file;
ui.loadAnd(() -> {
try{
if(!editor.getTags().containsKey("name")){
editor.getTags().put("name", result.nameWithoutExtension());
}
MapIO.writeMap(result, editor.createMap(result));
}catch(Exception e){
ui.showError(Core.bundle.format("editor.errorsave", Strings.parseException(e, true)));
Log.err(e);
}
});
}, false, FileChooser.mapFiles);
}else{
ui.loadAnd(() -> { ui.loadAnd(() -> {
try{ try{
if(!editor.getTags().containsKey("name")){ FileHandle result = Core.files.local(editor.getTags().get("name", "unknown") + "." + mapExtension);
editor.getTags().put("name", result.nameWithoutExtension());
}
MapIO.writeMap(result, editor.createMap(result)); MapIO.writeMap(result, editor.createMap(result));
Platform.instance.shareFile(result);
}catch(Exception e){ }catch(Exception e){
ui.showError(Core.bundle.format("editor.errorsave", Strings.parseException(e, true))); ui.showError(Core.bundle.format("editor.errorsave", Strings.parseException(e, true)));
Log.err(e); Log.err(e);
} }
}); });
}, false, FileChooser.mapFiles)); }
});
if(ios){
cell.size(swidth * 2f + 10, 60f).colspan(2);
}
}); });
menu.cont.row(); menu.cont.row();

View File

@@ -6,6 +6,7 @@ import io.anuke.arc.function.Consumer;
import io.anuke.arc.function.Predicate; import io.anuke.arc.function.Predicate;
import io.anuke.arc.math.geom.QuadTree; import io.anuke.arc.math.geom.QuadTree;
import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Rectangle;
import io.anuke.arc.util.*;
import io.anuke.mindustry.entities.traits.Entity; import io.anuke.mindustry.entities.traits.Entity;
public class EntityGroup<T extends Entity>{ public class EntityGroup<T extends Entity>{
@@ -170,8 +171,10 @@ public class EntityGroup<T extends Entity>{
} }
public void clear(){ public void clear(){
for(T entity : entityArray) for(T entity : entityArray){
entity.removed();
entity.setGroup(null); entity.setGroup(null);
}
for(T entity : entitiesToAdd) for(T entity : entitiesToAdd)
entity.setGroup(null); entity.setGroup(null);

View File

@@ -20,8 +20,7 @@ import io.anuke.mindustry.world.modules.*;
import java.io.*; import java.io.*;
import static io.anuke.mindustry.Vars.tileGroup; import static io.anuke.mindustry.Vars.*;
import static io.anuke.mindustry.Vars.world;
public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
public static final float timeToSleep = 60f * 4; //4 seconds to fall asleep public static final float timeToSleep = 60f * 4; //4 seconds to fall asleep
@@ -70,8 +69,8 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
x = tile.drawx(); x = tile.drawx();
y = tile.drawy(); y = tile.drawy();
block = tile.block(); block = tile.block();
if(block.idleSound != Sounds.none){ if(block.activeSound != Sounds.none){
sound = new SoundLoop(block.idleSound, block.idleSoundVolume); sound = new SoundLoop(block.activeSound, block.activeSoundVolume);
} }
health = block.health; health = block.health;
@@ -298,7 +297,11 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
} }
if(sound != null){ if(sound != null){
sound.update(x, y, block.shouldIdleSound(tile)); sound.update(x, y, block.shouldActiveSound(tile));
}
if(block.idleSound != Sounds.none && block.shouldIdleSound(tile)){
loops.play(block.idleSound, this, block.idleSoundVolume);
} }
Block previous = block; Block previous = block;

View File

@@ -0,0 +1,61 @@
package io.anuke.mindustry.game;
import io.anuke.arc.*;
import io.anuke.arc.audio.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.math.*;
import io.anuke.arc.math.geom.*;
import io.anuke.mindustry.*;
public class LoopControl{
private ObjectMap<Sound, SoundData> sounds = new ObjectMap<>();
public void play(Sound sound, Position pos, float volume){
if(Vars.headless) return;
float baseVol = sound.calcFalloff(pos.getX(), pos.getY());
float vol = baseVol * volume;
SoundData data = sounds.getOr(sound, SoundData::new);
data.volume += vol;
data.volume = Mathf.clamp(data.volume, 0f, 1f);
data.total += baseVol;
data.sum.add(pos.getX() * baseVol, pos.getY() * baseVol);
}
public void update(){
float avol = Core.settings.getInt("ambientvol", 100) / 100f;
sounds.each((sound, data) -> {
data.curVolume = Mathf.lerpDelta(data.curVolume, data.volume * avol, 0.2f);
boolean play = data.curVolume > 0.01f;
float pan = Mathf.isZero(data.total, 0.0001f) ? 0f : sound.calcPan(data.sum.x / data.total, data.sum.y / data.total);
if(data.soundID <= 0){
if(play){
data.soundID = sound.loop(data.curVolume, 1f, pan);
}
}else{
if(data.curVolume <= 0.01f){
sound.stop(data.soundID);
data.soundID = -1;
return;
}
sound.setPan(data.soundID, pan, data.curVolume);
}
data.volume = 0f;
data.total = 0f;
data.sum.setZero();
});
}
private class SoundData{
float volume;
float total;
Vector2 sum = new Vector2();
int soundID;
float curVolume;
}
}

View File

@@ -9,7 +9,7 @@ public class SoundLoop{
private static final float fadeSpeed = 0.05f; private static final float fadeSpeed = 0.05f;
private final Sound sound; private final Sound sound;
private long id = -1; private int id = -1;
private float volume, baseVolume; private float volume, baseVolume;
public SoundLoop(Sound sound, float baseVolume){ public SoundLoop(Sound sound, float baseVolume){

View File

@@ -2,6 +2,7 @@ package io.anuke.mindustry.io;
import io.anuke.arc.collection.*; import io.anuke.arc.collection.*;
import io.anuke.arc.util.serialization.*; import io.anuke.arc.util.serialization.*;
import io.anuke.arc.util.serialization.Json.*;
import io.anuke.mindustry.*; import io.anuke.mindustry.*;
import io.anuke.mindustry.content.*; import io.anuke.mindustry.content.*;
import io.anuke.mindustry.game.*; import io.anuke.mindustry.game.*;
@@ -11,10 +12,13 @@ import io.anuke.mindustry.world.*;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class JsonIO{ public class JsonIO{
private static CustomJson json = new CustomJson(); private static CustomJson jsonBase = new CustomJson();
private static Json json = new Json(){{
apply(this);
}};
public static String write(Object object){ public static String write(Object object){
return json.toJson(object); return json.toJson(object, object.getClass());
} }
public static <T> T copy(T object){ public static <T> T copy(T object){
@@ -26,66 +30,50 @@ public class JsonIO{
} }
public static <T> T read(Class<T> type, T base, String string){ public static <T> T read(Class<T> type, T base, String string){
return json.fromBaseJson(type, base, string); return jsonBase.fromBaseJson(type, base, string);
} }
public static String print(String in){ public static String print(String in){
return json.prettyPrint(in); return json.prettyPrint(in);
} }
static class CustomJson extends Json{ private static void apply(Json json){
private Object baseObject; json.setIgnoreUnknownFields(true);
json.setElementType(Rules.class, "spawns", SpawnGroup.class);
json.setElementType(Rules.class, "loadout", ItemStack.class);
{ json.setSerializer(Zone.class, new Serializer<Zone>(){
setIgnoreUnknownFields(true); @Override
setElementType(Rules.class, "spawns", SpawnGroup.class); public void write(Json json, Zone object, Class knownType){
setElementType(Rules.class, "loadout", ItemStack.class); json.writeValue(object.name);
setSerializer(Zone.class, new Serializer<Zone>(){
@Override
public void write(Json json, Zone object, Class knownType){
json.writeValue(object.name);
}
@Override
public Zone read(Json json, JsonValue jsonData, Class type){
return Vars.content.getByName(ContentType.zone, jsonData.asString());
}
});
setSerializer(Item.class, new Serializer<Item>(){
@Override
public void write(Json json, Item object, Class knownType){
json.writeValue(object.name);
}
@Override
public Item read(Json json, JsonValue jsonData, Class type){
if(jsonData.asString() == null) return Items.copper;
Item i = Vars.content.getByName(ContentType.item, jsonData.asString());
return i == null ? Items.copper : i;
}
});
//TODO extremely hacky and disgusting
for(Block block : Vars.content.blocks()){
Class type = block.getClass();
if(type.isAnonymousClass()) type = type.getSuperclass();
setSerializer(type, new Serializer<Block>(){
@Override
public void write(Json json, Block object, Class knownType){
json.writeValue(object.name);
}
@Override
public Block read(Json json, JsonValue jsonData, Class type){
return Vars.content.getByName(ContentType.block, jsonData.asString());
}
});
} }
setSerializer(Block.class, new Serializer<Block>(){ @Override
public Zone read(Json json, JsonValue jsonData, Class type){
return Vars.content.getByName(ContentType.zone, jsonData.asString());
}
});
json.setSerializer(Item.class, new Serializer<Item>(){
@Override
public void write(Json json, Item object, Class knownType){
json.writeValue(object.name);
}
@Override
public Item read(Json json, JsonValue jsonData, Class type){
if(jsonData.asString() == null) return Items.copper;
Item i = Vars.content.getByName(ContentType.item, jsonData.asString());
return i == null ? Items.copper : i;
}
});
//TODO extremely hacky and disgusting
for(Block block : Vars.content.blocks()){
Class type = block.getClass();
if(type.isAnonymousClass()) type = type.getSuperclass();
json.setSerializer(type, new Serializer<Block>(){
@Override @Override
public void write(Json json, Block object, Class knownType){ public void write(Json json, Block object, Class knownType){
json.writeValue(object.name); json.writeValue(object.name);
@@ -96,40 +84,60 @@ public class JsonIO{
return Vars.content.getByName(ContentType.block, jsonData.asString()); return Vars.content.getByName(ContentType.block, jsonData.asString());
} }
}); });
}
setSerializer(TeamData.class, new Serializer<TeamData>(){ json.setSerializer(Block.class, new Serializer<Block>(){
@Override @Override
public void write(Json json, TeamData object, Class knownType){ public void write(Json json, Block object, Class knownType){
json.writeObjectStart(); json.writeValue(object.name);
json.writeValue("brokenBlocks", object.brokenBlocks.toArray()); }
json.writeValue("team", object.team.ordinal());
json.writeObjectEnd();
}
@Override @Override
public TeamData read(Json json, JsonValue jsonData, Class type){ public Block read(Json json, JsonValue jsonData, Class type){
long[] blocks = jsonData.get("brokenBlocks").asLongArray(); return Vars.content.getByName(ContentType.block, jsonData.asString());
Team team = Team.all[jsonData.getInt("team", 0)]; }
TeamData out = new TeamData(team, EnumSet.of(new Team[]{})); });
out.brokenBlocks = new LongQueue(blocks);
return out;
}
});
setSerializer(ItemStack.class, new Serializer<ItemStack>(){ json.setSerializer(TeamData.class, new Serializer<TeamData>(){
@Override @Override
public void write(Json json, ItemStack object, Class knownType){ public void write(Json json, TeamData object, Class knownType){
json.writeObjectStart(); json.writeObjectStart();
json.writeValue("item", object.item); json.writeValue("brokenBlocks", object.brokenBlocks.toArray());
json.writeValue("amount", object.amount); json.writeValue("team", object.team.ordinal());
json.writeObjectEnd(); json.writeObjectEnd();
} }
@Override @Override
public ItemStack read(Json json, JsonValue jsonData, Class type){ public TeamData read(Json json, JsonValue jsonData, Class type){
return new ItemStack(json.getSerializer(Item.class).read(json, jsonData.get("item"), Item.class), jsonData.getInt("amount")); long[] blocks = jsonData.get("brokenBlocks").asLongArray();
} Team team = Team.all[jsonData.getInt("team", 0)];
}); TeamData out = new TeamData(team, EnumSet.of(new Team[]{}));
out.brokenBlocks = new LongQueue(blocks);
return out;
}
});
json.setSerializer(ItemStack.class, new Serializer<ItemStack>(){
@Override
public void write(Json json, ItemStack object, Class knownType){
json.writeObjectStart();
json.writeValue("item", object.item);
json.writeValue("amount", object.amount);
json.writeObjectEnd();
}
@Override
public ItemStack read(Json json, JsonValue jsonData, Class type){
return new ItemStack(json.getSerializer(Item.class).read(json, jsonData.get("item"), Item.class), jsonData.getInt("amount"));
}
});
}
static class CustomJson extends Json{
private Object baseObject;
{
apply(this);
} }
@Override @Override

View File

@@ -14,9 +14,7 @@ public abstract class SaveFileReader{
protected final DataOutputStream dataBytes = new DataOutputStream(byteOutput); protected final DataOutputStream dataBytes = new DataOutputStream(byteOutput);
protected final ReusableByteOutStream byteOutputSmall = new ReusableByteOutStream(); protected final ReusableByteOutStream byteOutputSmall = new ReusableByteOutStream();
protected final DataOutputStream dataBytesSmall = new DataOutputStream(byteOutputSmall); protected final DataOutputStream dataBytesSmall = new DataOutputStream(byteOutputSmall);
protected final ObjectMap<String, String> fallback = ObjectMap.of( protected final ObjectMap<String, String> fallback = ObjectMap.of();
);
protected void region(String name, DataInput stream, CounterInputStream counter, IORunner<DataInput> cons) throws IOException{ protected void region(String name, DataInput stream, CounterInputStream counter, IORunner<DataInput> cons) throws IOException{
counter.resetCount(); counter.resetCount();

View File

@@ -92,7 +92,7 @@ public class Weapon{
float baseX = shooter.getX(), baseY = shooter.getY(); float baseX = shooter.getX(), baseY = shooter.getY();
Weapon weapon = shooter.getWeapon(); Weapon weapon = shooter.getWeapon();
weapon.shootSound.at(x, y); weapon.shootSound.at(x, y, Mathf.random(0.8f, 1.0f));
sequenceNum = 0; sequenceNum = 0;
if(weapon.shotDelay > 0.01f){ if(weapon.shotDelay > 0.01f){

View File

@@ -176,7 +176,7 @@ public class Zone extends UnlockableContent{
@Override @Override
public void load(){ public void load(){
if(Core.files.internal("zones/" + name + ".png").exists()){ if(Core.files.internal("zones/" + name + ".png").exists() && !headless){
preview = new Texture(Core.files.internal("zones/" + name + ".png")); preview = new Texture(Core.files.internal("zones/" + name + ".png"));
} }
} }

View File

@@ -25,7 +25,9 @@ public class MultiReqImage extends Stack{
if(valid != null){ if(valid != null){
valid.visible(true); valid.visible(true);
}else{ }else{
displays.get((int)(time) % displays.size).visible(true); if(displays.size > 0){
displays.get((int)(time) % displays.size).visible(true);
}
} }
} }
} }

View File

@@ -43,7 +43,7 @@ public class MapsDialog extends FloatingDialog{
void setup(){ void setup(){
buttons.clearChildren(); buttons.clearChildren();
if(Core.graphics.isPortrait()){ if(Core.graphics.isPortrait() && !ios){
buttons.addImageTextButton("$back", "icon-arrow-left", iconsize, this::hide).size(210f*2f, 64f).colspan(2); buttons.addImageTextButton("$back", "icon-arrow-left", iconsize, this::hide).size(210f*2f, 64f).colspan(2);
buttons.row(); buttons.row();
}else{ }else{
@@ -60,54 +60,56 @@ public class MapsDialog extends FloatingDialog{
}); });
}).size(210f, 64f); }).size(210f, 64f);
buttons.addImageTextButton("$editor.importmap", "icon-load", iconsize, () -> { if(!ios){
Platform.instance.showFileChooser("$editor.importmap", "Map File", file -> { buttons.addImageTextButton("$editor.importmap", "icon-load", iconsize, () -> {
world.maps.tryCatchMapError(() -> { Platform.instance.showFileChooser("$editor.importmap", "Map File", file -> {
if(MapIO.isImage(file)){ world.maps.tryCatchMapError(() -> {
ui.showError("$editor.errorimage"); if(MapIO.isImage(file)){
return; ui.showError("$editor.errorimage");
} return;
}
Map map; Map map;
if(file.extension().equalsIgnoreCase(mapExtension)){ if(file.extension().equalsIgnoreCase(mapExtension)){
map = MapIO.createMap(file, true); map = MapIO.createMap(file, true);
}else{ }else{
map = world.maps.makeLegacyMap(file); map = world.maps.makeLegacyMap(file);
} }
//when you attempt to import a save, it will have no name, so generate one //when you attempt to import a save, it will have no name, so generate one
String name = map.tags.getOr("name", () -> { String name = map.tags.getOr("name", () -> {
String result = "unknown"; String result = "unknown";
int number = 0; int number = 0;
while(world.maps.byName(result + number++) != null); while(world.maps.byName(result + number++) != null) ;
return result + number; return result + number;
});
//this will never actually get called, but it remains just in case
if(name == null){
ui.showError("$editor.errorname");
return;
}
Map conflict = world.maps.all().find(m -> m.name().equals(name));
if(conflict != null && !conflict.custom){
ui.showInfo(Core.bundle.format("editor.import.exists", name));
}else if(conflict != null){
ui.showConfirm("$confirm", "$editor.overwrite.confirm", () -> {
world.maps.tryCatchMapError(() -> {
world.maps.importMap(file);
setup();
});
}); });
}else{
world.maps.importMap(map.file);
setup();
}
}); //this will never actually get called, but it remains just in case
}, true, FileChooser.anyMapFiles); if(name == null){
}).size(210f, 64f); ui.showError("$editor.errorname");
return;
}
Map conflict = world.maps.all().find(m -> m.name().equals(name));
if(conflict != null && !conflict.custom){
ui.showInfo(Core.bundle.format("editor.import.exists", name));
}else if(conflict != null){
ui.showConfirm("$confirm", "$editor.overwrite.confirm", () -> {
world.maps.tryCatchMapError(() -> {
world.maps.importMap(file);
setup();
});
});
}else{
world.maps.importMap(map.file);
setup();
}
});
}, true, FileChooser.anyMapFiles);
}).size(210f, 64f);
}
cont.clear(); cont.clear();

View File

@@ -108,6 +108,7 @@ public class PausedDialog extends FloatingDialog{
if(control.saves.getCurrent() == null || !control.saves.getCurrent().isAutosave() || state.rules.tutorial){ if(control.saves.getCurrent() == null || !control.saves.getCurrent().isAutosave() || state.rules.tutorial){
state.set(State.menu); state.set(State.menu);
logic.reset();
return; return;
} }
@@ -119,6 +120,7 @@ public class PausedDialog extends FloatingDialog{
ui.showError("[accent]" + Core.bundle.get("savefail")); ui.showError("[accent]" + Core.bundle.get("savefail"));
} }
state.set(State.menu); state.set(State.menu);
logic.reset();
}); });
} }
} }

View File

@@ -126,6 +126,7 @@ public class SettingsMenuDialog extends SettingsDialog{
void addSettings(){ void addSettings(){
sound.sliderPref("musicvol", bundle.get("setting.musicvol.name", "Music Volume"), 100, 0, 100, 1, i -> i + "%"); sound.sliderPref("musicvol", bundle.get("setting.musicvol.name", "Music Volume"), 100, 0, 100, 1, i -> i + "%");
sound.sliderPref("sfxvol", bundle.get("setting.sfxvol.name", "SFX Volume"), 100, 0, 100, 1, i -> i + "%"); sound.sliderPref("sfxvol", bundle.get("setting.sfxvol.name", "SFX Volume"), 100, 0, 100, 1, i -> i + "%");
sound.sliderPref("ambientvol", bundle.get("setting.ambientvol.name", "Ambient Volume"), 100, 0, 100, 1, i -> i + "%");
game.screenshakePref(); game.screenshakePref();
if(mobile){ if(mobile){

View File

@@ -58,7 +58,7 @@ public class ZoneInfoDialog extends FloatingDialog{
rebuildItems.run(); rebuildItems.run();
cont.table(cont -> { cont.pane(cont -> {
if(zone.locked()){ if(zone.locked()){
cont.addImage("icon-locked"); cont.addImage("icon-locked");
cont.row(); cont.row();
@@ -138,6 +138,7 @@ public class ZoneInfoDialog extends FloatingDialog{
() -> loadout.show(zone.loadout.core().itemCapacity, zone::getStartingItems, zone::resetStartingItems, zone::updateLaunchCost, rebuildItems, item -> data.getItem(item) > 0 && item.type == ItemType.material) () -> loadout.show(zone.loadout.core().itemCapacity, zone::getStartingItems, zone::resetStartingItems, zone::updateLaunchCost, rebuildItems, item -> data.getItem(item) > 0 && item.type == ItemType.material)
).fillX().pad(3).disabled(b -> !zone.canConfigure()); ).fillX().pad(3).disabled(b -> !zone.canConfigure());
} }
cont.marginRight(12f);
}); });
cont.row(); cont.row();

View File

@@ -66,6 +66,7 @@ public class MenuFragment extends Fragment{
//info icon //info icon
if(mobile){ if(mobile){
parent.fill(c -> c.bottom().left().addButton("", "info", ui.about::show).size(84, 45)); parent.fill(c -> c.bottom().left().addButton("", "info", ui.about::show).size(84, 45));
parent.fill(c -> c.bottom().right().addButton("", "discord", ui.discord::show).size(84, 45));
} }
String versionText = "[#ffffffba]" + ((Version.build == -1) ? "[#fc8140aa]custom build" : Version.modifier + " build " + Version.build); String versionText = "[#ffffffba]" + ((Version.build == -1) ? "[#fc8140aa]custom build" : Version.modifier + " build " + Version.build);

View File

@@ -25,6 +25,7 @@ import io.anuke.mindustry.game.*;
import io.anuke.mindustry.gen.*; import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.input.InputHandler.*; import io.anuke.mindustry.input.InputHandler.*;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.type.*; import io.anuke.mindustry.type.*;
import io.anuke.mindustry.ui.*; import io.anuke.mindustry.ui.*;
import io.anuke.mindustry.world.blocks.*; import io.anuke.mindustry.world.blocks.*;
@@ -100,7 +101,13 @@ public class Block extends BlockStorage{
public boolean hasShadow = true; public boolean hasShadow = true;
/** Sounds made when this block breaks.*/ /** Sounds made when this block breaks.*/
public Sound breakSound = Sounds.boom; public Sound breakSound = Sounds.boom;
/** The sound that this block makes while active.*/
/** The sound that this block makes while active. One sound loop. Do not overuse.*/
public Sound activeSound = Sounds.none;
/** Active sound base volume. */
public float activeSoundVolume = 0.5f;
/** The sound that this block makes while idle. Uses one sound loop for all blocks.*/
public Sound idleSound = Sounds.none; public Sound idleSound = Sounds.none;
/** Idle sound base volume. */ /** Idle sound base volume. */
public float idleSoundVolume = 0.5f; public float idleSoundVolume = 0.5f;
@@ -211,6 +218,11 @@ public class Block extends BlockStorage{
return progressIncrease; return progressIncrease;
} }
/** @return whether this block should play its active sound.*/
public boolean shouldActiveSound(Tile tile){
return false;
}
/** @return whether this block should play its idle sound.*/ /** @return whether this block should play its idle sound.*/
public boolean shouldIdleSound(Tile tile){ public boolean shouldIdleSound(Tile tile){
return canProduce(tile); return canProduce(tile);
@@ -282,6 +294,15 @@ public class Block extends BlockStorage{
/** Called after the block is placed by this client. */ /** Called after the block is placed by this client. */
@CallSuper @CallSuper
public void playerPlaced(Tile tile){ public void playerPlaced(Tile tile){
if(outputsPower && !consumesPower){
PowerNode.lastPlaced = tile.pos();
}
}
/** Called after the block is placed by anyone. */
@CallSuper
public void placed(Tile tile){
if(Net.client()) return;
if((consumesPower && !outputsPower) || (!consumesPower && outputsPower)){ if((consumesPower && !outputsPower) || (!consumesPower && outputsPower)){
int range = 10; int range = 10;
@@ -289,7 +310,7 @@ public class Block extends BlockStorage{
Geometry.circle(tile.x, tile.y, range, (x, y) -> { Geometry.circle(tile.x, tile.y, range, (x, y) -> {
Tile other = world.ltile(x, y); Tile other = world.ltile(x, y);
if(other != null && other.block instanceof PowerNode && ((PowerNode)other.block).linkValid(other, tile) && !other.entity.proximity().contains(tile) && if(other != null && other.block instanceof PowerNode && ((PowerNode)other.block).linkValid(other, tile) && !other.entity.proximity().contains(tile) &&
!(outputsPower && tile.entity.proximity().contains(p -> p.entity != null && p.entity.power != null && p.entity.power.graph == other.entity.power.graph))){ !(outputsPower && tile.entity.proximity().contains(p -> p.entity != null && p.entity.power != null && p.entity.power.graph == other.entity.power.graph))){
tempTiles.add(other); tempTiles.add(other);
} }
}); });
@@ -298,19 +319,11 @@ public class Block extends BlockStorage{
Call.linkPowerNodes(null, tempTiles.first(), tile); Call.linkPowerNodes(null, tempTiles.first(), tile);
} }
} }
if(outputsPower && !consumesPower){
PowerNode.lastPlaced = tile.pos();
}
} }
public void removed(Tile tile){ public void removed(Tile tile){
} }
/** Called after the block is placed by anyone. */
public void placed(Tile tile){
}
/** Called every frame a unit is on this tile. */ /** Called every frame a unit is on this tile. */
public void unitOn(Tile tile, Unit unit){ public void unitOn(Tile tile, Unit unit){
} }

View File

@@ -54,7 +54,7 @@ public class BuildBlock extends Block{
Effects.effect(Fx.breakBlock, tile.drawx(), tile.drawy(), block.size); Effects.effect(Fx.breakBlock, tile.drawx(), tile.drawy(), block.size);
world.removeBlock(tile); world.removeBlock(tile);
Events.fire(new BlockBuildEndEvent(tile, team, true)); Events.fire(new BlockBuildEndEvent(tile, team, true));
Sounds.breaks.at(tile); Sounds.breaks.at(tile, Mathf.random(0.7f, 1.4f));
} }
@Remote(called = Loc.server) @Remote(called = Loc.server)
@@ -75,7 +75,7 @@ public class BuildBlock extends Block{
Core.app.post(() -> tile.block().playerPlaced(tile)); Core.app.post(() -> tile.block().playerPlaced(tile));
} }
Core.app.post(() -> Events.fire(new BlockBuildEndEvent(tile, team, false))); Core.app.post(() -> Events.fire(new BlockBuildEndEvent(tile, team, false)));
Sounds.place.at(tile); Sounds.place.at(tile, Mathf.random(0.7f, 1.4f));
} }
@Override @Override

View File

@@ -105,7 +105,7 @@ public class LaserTurret extends PowerTurret{
} }
@Override @Override
public boolean shouldIdleSound(Tile tile){ public boolean shouldActiveSound(Tile tile){
LaserTurretEntity entity = tile.entity(); LaserTurretEntity entity = tile.entity();
return entity.bulletLife > 0 && entity.bullet != null; return entity.bulletLife > 0 && entity.bullet != null;

View File

@@ -5,6 +5,7 @@ import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.bullet.*; import io.anuke.mindustry.entities.bullet.*;
import io.anuke.mindustry.entities.effect.*; import io.anuke.mindustry.entities.effect.*;
import io.anuke.mindustry.entities.type.*; import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.type.*; import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.consumers.*; import io.anuke.mindustry.world.consumers.*;
@@ -19,6 +20,7 @@ public abstract class LiquidTurret extends Turret{
public LiquidTurret(String name){ public LiquidTurret(String name){
super(name); super(name);
hasLiquids = true; hasLiquids = true;
activeSound = Sounds.spray;
} }
/** Initializes accepted ammo map. Format: [liquid1, bullet1, liquid2, bullet2...] */ /** Initializes accepted ammo map. Format: [liquid1, bullet1, liquid2, bullet2...] */
@@ -44,6 +46,12 @@ public abstract class LiquidTurret extends Turret{
}); });
} }
@Override
public boolean shouldActiveSound(Tile tile){
TurretEntity entity = tile.entity();
return entity.target != null && hasAmmo(tile);
}
@Override @Override
protected boolean validateTarget(Tile tile){ protected boolean validateTarget(Tile tile){
TurretEntity entity = tile.entity(); TurretEntity entity = tile.entity();
@@ -79,7 +87,7 @@ public abstract class LiquidTurret extends Turret{
Effects.effect(type.shootEffect, entity.liquids.current().color, tile.drawx() + tr.x, tile.drawy() + tr.y, entity.rotation); Effects.effect(type.shootEffect, entity.liquids.current().color, tile.drawx() + tr.x, tile.drawy() + tr.y, entity.rotation);
Effects.effect(type.smokeEffect, entity.liquids.current().color, tile.drawx() + tr.x, tile.drawy() + tr.y, entity.rotation); Effects.effect(type.smokeEffect, entity.liquids.current().color, tile.drawx() + tr.x, tile.drawy() + tr.y, entity.rotation);
shootSound.at(tile); //shootSound.at(tile);
if(shootShake > 0){ if(shootShake > 0){
Effects.shake(shootShake, shootShake, tile.entity); Effects.shake(shootShake, shootShake, tile.entity);

View File

@@ -279,7 +279,7 @@ public abstract class Turret extends Block{
Effects.effect(shootEffect, tile.drawx() + tr.x, tile.drawy() + tr.y, entity.rotation); Effects.effect(shootEffect, tile.drawx() + tr.x, tile.drawy() + tr.y, entity.rotation);
Effects.effect(smokeEffect, tile.drawx() + tr.x, tile.drawy() + tr.y, entity.rotation); Effects.effect(smokeEffect, tile.drawx() + tr.x, tile.drawy() + tr.y, entity.rotation);
shootSound.at(tile); shootSound.at(tile, Mathf.random(0.9f, 1.1f));
if(shootShake > 0){ if(shootShake > 0){
Effects.shake(shootShake, shootShake, tile.entity); Effects.shake(shootShake, shootShake, tile.entity);

View File

@@ -1,19 +1,17 @@
package io.anuke.mindustry.world.blocks.distribution; package io.anuke.mindustry.world.blocks.distribution;
import io.anuke.arc.Core; import io.anuke.arc.*;
import io.anuke.arc.collection.LongArray; import io.anuke.arc.collection.*;
import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.*;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.math.geom.*; import io.anuke.arc.math.geom.*;
import io.anuke.arc.util.*; import io.anuke.arc.util.*;
import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.Layer; import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.input.InputHandler.PlaceDraw; import io.anuke.mindustry.input.InputHandler.*;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.meta.*; import io.anuke.mindustry.world.meta.*;
import java.io.*; import java.io.*;
@@ -41,6 +39,9 @@ public class Conveyor extends Block{
group = BlockGroup.transportation; group = BlockGroup.transportation;
hasItems = true; hasItems = true;
itemCapacity = 4; itemCapacity = 4;
idleSound = Sounds.conveyor;
idleSoundVolume = 0.004f;
} }
private static int compareItems(long a, long b){ private static int compareItems(long a, long b){
@@ -76,6 +77,12 @@ public class Conveyor extends Block{
tilesize * entity.blendsclx, tilesize * entity.blendscly, rotation * 90); tilesize * entity.blendsclx, tilesize * entity.blendscly, rotation * 90);
} }
@Override
public boolean shouldIdleSound(Tile tile){
ConveyorEntity entity = tile.entity();
return entity.clogHeat <= 0.5f ;
}
@Override @Override
public void onProximityUpdate(Tile tile){ public void onProximityUpdate(Tile tile){
super.onProximityUpdate(tile); super.onProximityUpdate(tile);

View File

@@ -11,6 +11,7 @@ import io.anuke.arc.util.*;
import io.anuke.mindustry.entities.type.*; import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.gen.*; import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.ui.*; import io.anuke.mindustry.ui.*;
import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.*; import io.anuke.mindustry.world.blocks.*;
@@ -106,6 +107,14 @@ public class PowerNode extends PowerBlock{
Call.linkPowerNodes(null, tile, before); Call.linkPowerNodes(null, tile, before);
} }
lastPlaced = tile.pos();
super.playerPlaced(tile);
}
@Override
public void placed(Tile tile){
if(Net.client()) return;
Predicate<Tile> valid = other -> other != null && other != tile && ((!other.block().outputsPower && other.block().consumesPower) || (other.block().outputsPower && !other.block().consumesPower)) && linkValid(tile, other) Predicate<Tile> valid = other -> other != null && other != tile && ((!other.block().outputsPower && other.block().consumesPower) || (other.block().outputsPower && !other.block().consumesPower)) && linkValid(tile, other)
&& !other.entity.proximity().contains(tile) && other.entity.power.graph != tile.entity.power.graph; && !other.entity.proximity().contains(tile) && other.entity.power.graph != tile.entity.power.graph;
@@ -120,8 +129,7 @@ public class PowerNode extends PowerBlock{
tempTiles.sort(Structs.comparingFloat(t -> t.dst2(tile))); tempTiles.sort(Structs.comparingFloat(t -> t.dst2(tile)));
tempTiles.each(valid, other -> Call.linkPowerNodes(null, tile, other)); tempTiles.each(valid, other -> Call.linkPowerNodes(null, tile, other));
lastPlaced = tile.pos(); super.placed(tile);
super.playerPlaced(tile);
} }
@Override @Override

View File

@@ -29,11 +29,6 @@ public class ThermalGenerator extends PowerGenerator{
drawPlaceText(Core.bundle.formatFloat("bar.efficiency", sumAttribute(Attribute.heat, x, y) * 100, 1), x, y, valid); drawPlaceText(Core.bundle.formatFloat("bar.efficiency", sumAttribute(Attribute.heat, x, y) * 100, 1), x, y, valid);
} }
@Override
public void placed(Tile tile){
super.placed(tile);
}
@Override @Override
public void onProximityAdded(Tile tile){ public void onProximityAdded(Tile tile){
super.onProximityAdded(tile); super.onProximityAdded(tile);

View File

@@ -10,6 +10,7 @@ import io.anuke.mindustry.content.*;
import io.anuke.mindustry.entities.*; import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.Effects.*; import io.anuke.mindustry.entities.Effects.*;
import io.anuke.mindustry.entities.type.*; import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.type.*; import io.anuke.mindustry.type.*;
import io.anuke.mindustry.ui.*; import io.anuke.mindustry.ui.*;
@@ -65,8 +66,8 @@ public class Drill extends Block{
liquidCapacity = 5f; liquidCapacity = 5f;
hasItems = true; hasItems = true;
//idleSound = Sounds.drill; idleSound = Sounds.drill;
//idleSoundVolume = 0.5f; idleSoundVolume = 0.004f;
} }
@Override @Override

View File

@@ -1,21 +1,18 @@
package io.anuke.mindustry.world.blocks.production; package io.anuke.mindustry.world.blocks.production;
import io.anuke.arc.function.Consumer; import io.anuke.arc.function.*;
import io.anuke.arc.function.Supplier; import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.*;
import io.anuke.arc.math.Mathf; import io.anuke.arc.util.*;
import io.anuke.arc.util.Time; import io.anuke.mindustry.content.*;
import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.Effects.*;
import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.type.*; import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.consumers.*;
import io.anuke.mindustry.world.consumers.ConsumeLiquidBase; import io.anuke.mindustry.world.meta.*;
import io.anuke.mindustry.world.consumers.ConsumeType;
import io.anuke.mindustry.world.meta.BlockStat;
import io.anuke.mindustry.world.meta.StatUnit;
import java.io.*; import java.io.*;
@@ -37,6 +34,8 @@ public class GenericCrafter extends Block{
solid = true; solid = true;
hasItems = true; hasItems = true;
health = 60; health = 60;
idleSound = Sounds.machine;
idleSoundVolume = 0.03f;
} }
@Override @Override
@@ -58,6 +57,11 @@ public class GenericCrafter extends Block{
} }
} }
@Override
public boolean shouldIdleSound(Tile tile){
return tile.entity.cons.valid();
}
@Override @Override
public void init(){ public void init(){
outputsLiquid = outputLiquid != null; outputsLiquid = outputLiquid != null;

View File

@@ -30,8 +30,8 @@ public class CoreBlock extends StorageBlock{
update = true; update = true;
hasItems = true; hasItems = true;
flags = EnumSet.of(BlockFlag.target, BlockFlag.producer); flags = EnumSet.of(BlockFlag.target, BlockFlag.producer);
idleSound = Sounds.respawning; activeSound = Sounds.respawning;
idleSoundVolume = 1f; activeSoundVolume = 1f;
} }
@Remote(called = Loc.server) @Remote(called = Loc.server)
@@ -79,6 +79,7 @@ public class CoreBlock extends StorageBlock{
@Override @Override
public void placed(Tile tile){ public void placed(Tile tile){
super.placed(tile);
state.teams.get(tile.getTeam()).cores.add(tile); state.teams.get(tile.getTeam()).cores.add(tile);
} }
@@ -155,7 +156,7 @@ public class CoreBlock extends StorageBlock{
} }
@Override @Override
public boolean shouldIdleSound(Tile tile){ public boolean shouldActiveSound(Tile tile){
CoreEntity entity = tile.entity(); CoreEntity entity = tile.entity();
return entity.spawnPlayer != null; return entity.spawnPlayer != null;

View File

@@ -37,10 +37,7 @@ task dist(type: Jar, dependsOn: classes){
//use target = all for all platforms //use target = all for all platforms
def target = getTarget() def target = getTarget()
if(target.contains("windows")){ if(target.contains("windows")) exclude('**.so', "**.dylib")
def prefix = target.contains("32") ? "64" : ""
exclude('**.so', "**.dylib", "sdl-arc${prefix}.dll", "gdx${prefix}.dll", "gdx-freetype${prefix}.dll", "**/music/**", "**/sounds/**")
}
if(target == "mac") exclude('**.so', "**.dll") if(target == "mac") exclude('**.so', "**.dll")
if(target == "linux") exclude('**.dll', "**.dylib") if(target == "linux") exclude('**.dll', "**.dylib")
archivesBaseName = appName + "-" + target archivesBaseName = appName + "-" + target
@@ -81,16 +78,6 @@ task ikdist{
into file(folder) into file(folder)
} }
copy{
from files("../core/assets/music")
into file(folder + "/music")
}
copy{
from files("../core/assets/sounds")
into file(folder + "/sounds")
}
copy{ copy{
from(getTarget().contains("32") ? "$IKVM_DIR/libraries_32" : "$IKVM_DIR/libraries") from(getTarget().contains("32") ? "$IKVM_DIR/libraries_32" : "$IKVM_DIR/libraries")
into folder into folder

View File

@@ -1,6 +1,7 @@
package io.anuke.mindustry.desktopsdl; package io.anuke.mindustry.desktopsdl;
import club.minnced.discord.rpc.*; import club.minnced.discord.rpc.*;
import io.anuke.arc.backends.sdl.jni.SDL;
import io.anuke.arc.collection.*; import io.anuke.arc.collection.*;
import io.anuke.arc.files.*; import io.anuke.arc.files.*;
import io.anuke.arc.function.*; import io.anuke.arc.function.*;
@@ -10,7 +11,6 @@ import io.anuke.mindustry.core.GameState.*;
import io.anuke.mindustry.core.*; import io.anuke.mindustry.core.*;
import io.anuke.mindustry.net.*; import io.anuke.mindustry.net.*;
import io.anuke.mindustry.ui.dialogs.*; import io.anuke.mindustry.ui.dialogs.*;
import sdl.*;
import java.net.*; import java.net.*;
import java.util.*; import java.util.*;

View File

@@ -7,6 +7,38 @@ ext{
mainClassName = "io.anuke.mindustry.IOSLauncher" mainClassName = "io.anuke.mindustry.IOSLauncher"
} }
task copyAssets(){
doLast{
delete{
delete "assets/"
}
copy{
from "../core/assets"
into "assets/"
}
exec{
commandLine "sh", "./convert_audio.sh", "assets/sounds"
}
exec{
commandLine "sh", "./convert_audio.sh", "assets/music"
}
delete{
delete fileTree('assets') {
include '**/*.ogg'
}
}
}
}
createIPA.dependsOn copyAssets
launchIPhoneSimulator.dependsOn copyAssets
launchIOSDevice.dependsOn copyAssets
launchIPadSimulator.dependsOn copyAssets
launchIPhoneSimulator.dependsOn build launchIPhoneSimulator.dependsOn build
launchIPadSimulator.dependsOn build launchIPadSimulator.dependsOn build
launchIOSDevice.dependsOn build launchIOSDevice.dependsOn build

7
ios/convert_audio.sh Executable file
View File

@@ -0,0 +1,7 @@
#!/usr/bin/bash
#convert ogg to .caf files for iOS
for i in $1/*.ogg; do
echo $i
ffmpeg -i "$i" "${i%.*}.caf"
done

View File

@@ -7,7 +7,7 @@
<iosInfoPList>Info.plist.xml</iosInfoPList> <iosInfoPList>Info.plist.xml</iosInfoPList>
<resources> <resources>
<resource> <resource>
<directory>../core/assets</directory> <directory>../ios/assets</directory>
<includes> <includes>
<include>**</include> <include>**</include>
</includes> </includes>

View File

@@ -1,5 +1 @@
@Echo Off java -jar server.jar
Set "JV="
For /F "Tokens=3" %%A In ('java -version 2^>^&1') Do If Not Defined JV Set "JV=%%~A"
If /I "%JV%"=="not" (Echo Java is not installed, this server requires Java to run.) Else (start java -jar server.jar)
Pause

View File

@@ -5,5 +5,5 @@ cd ../Mindustry-Wiki-Generator
./gradlew run ./gradlew run
cd ../wiki cd ../wiki
git add . git add .
git commit -m "Update to match commit ${TRAVIS_COMMIT}" git commit -m "Update to match build ${TRAVIS_TAG}"
git push https://Anuken:${GH_PUSH_TOKEN}@github.com/MindustryGame/wiki git push https://Anuken:${GH_PUSH_TOKEN}@github.com/MindustryGame/wiki