This commit is contained in:
Anuken
2019-08-01 10:38:16 -04:00
45 changed files with 251 additions and 80 deletions

View File

@@ -0,0 +1,94 @@
package io.anuke.annotations;
import com.squareup.javapoet.*;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;
import javax.tools.StandardLocation;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class AssetsAnnotationProcessor extends AbstractProcessor{
/** Name of the base package to put all the generated classes. */
private static final String packageName = "io.anuke.mindustry.gen";
private int round;
@Override
public synchronized void init(ProcessingEnvironment processingEnv){
super.init(processingEnv);
//put all relevant utils into utils class
Utils.typeUtils = processingEnv.getTypeUtils();
Utils.elementUtils = processingEnv.getElementUtils();
Utils.filer = processingEnv.getFiler();
Utils.messager = processingEnv.getMessager();
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv){
if(round++ != 0) return false; //only process 1 round
try{
String path = Paths.get(Utils.filer.createResource(StandardLocation.CLASS_OUTPUT, "no", "no")
.toUri().toURL().toString().substring("file:".length()))
.getParent().getParent().getParent().getParent().getParent().getParent().toString();
process("Sounds", path + "/assets/sounds", "io.anuke.arc.audio.Sound", "newSound");
process("Musics", path + "/assets/music", "io.anuke.arc.audio.Music", "newMusic");
return true;
}catch(Exception e){
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
public Set<String> getSupportedAnnotationTypes() {
return Collections.singleton("*");
}
void process(String classname, String path, String rtype, String loadMethod) throws Exception{
TypeSpec.Builder type = TypeSpec.classBuilder(classname).addModifiers(Modifier.PUBLIC);
MethodSpec.Builder load = MethodSpec.methodBuilder("load").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
MethodSpec.Builder dispose = MethodSpec.methodBuilder("dispose").addModifiers(Modifier.PUBLIC, Modifier.STATIC);
HashSet<String> names = new HashSet<>();
Files.list(Paths.get(path)).forEach(p -> {
String fname = p.getFileName().toString();
String name = p.getFileName().toString();
name = name.substring(0, name.indexOf("."));
if(names.contains(name)){
Utils.messager.printMessage(Kind.ERROR, "Duplicate file name: " + p.toString() + "!");
}else{
names.add(name);
}
if(SourceVersion.isKeyword(name)){
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);
dispose.addStatement(name + ".dispose()");
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());
//cons.consume(type, fname, name);
});
type.addMethod(load.build());
type.addMethod(dispose.build());
JavaFile.builder(packageName, type.build()).build().writeTo(Utils.filer);
}
}

View File

@@ -1,4 +1,5 @@
io.anuke.annotations.RemoteMethodAnnotationProcessor
io.anuke.annotations.SerializeAnnotationProcessor
io.anuke.annotations.StructAnnotationProcessor
io.anuke.annotations.CallSuperAnnotationProcessor
io.anuke.annotations.CallSuperAnnotationProcessor
io.anuke.annotations.AssetsAnnotationProcessor

Binary file not shown.

BIN
core/assets/music/menu.mp3 Normal file

Binary file not shown.

BIN
core/assets/sounds/back.ogg Normal file

Binary file not shown.

BIN
core/assets/sounds/bang.mp3 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.

BIN
core/assets/sounds/die.mp3 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.

BIN
core/assets/sounds/ping.mp3 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.

View File

@@ -1,12 +1,12 @@
package io.anuke.mindustry;
import io.anuke.arc.*;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.util.Log;
import io.anuke.arc.util.Time;
import io.anuke.arc.math.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.core.*;
import io.anuke.mindustry.game.EventType.GameLoadEvent;
import io.anuke.mindustry.io.BundleLoader;
import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.io.*;
import static io.anuke.mindustry.Vars.*;
@@ -26,6 +26,9 @@ public class Mindustry extends ApplicationCore{
Vars.init();
Log.setUseColors(false);
BundleLoader.load();
Musics.load();
Sounds.load();
content.load();
content.loadColors();

View File

@@ -33,6 +33,7 @@ import static io.anuke.mindustry.Vars.*;
*/
public class Control implements ApplicationListener{
public final Saves saves;
public final MusicControl music;
private Interval timer = new Interval(2);
private boolean hiscore = false;
@@ -42,6 +43,7 @@ public class Control implements ApplicationListener{
public Control(){
batch = new SpriteBatch();
saves = new Saves();
music = new MusicControl();
data = new GlobalData();
Unit.dp.product = settings.getInt("uiscale", 100) / 100f;
@@ -228,6 +230,8 @@ public class Control implements ApplicationListener{
public void dispose(){
content.dispose();
Net.dispose();
Musics.dispose();
Sounds.dispose();
ui.editor.dispose();
}
@@ -307,6 +311,19 @@ public class Control implements ApplicationListener{
//autosave global data if it's modified
data.checkSave();
if(state.is(State.menu)){
if(ui.deploy.isShown()){
music.silence(); //TODO deploy music
}else if(ui.editor.isShown()){
music.play(Musics.editor);
}else{
music.play(Musics.menu);
}
}else{
//TODO game music
music.silence();
}
if(!state.is(State.menu)){
input.update();

View File

@@ -60,6 +60,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
}
unit.onSuperDeath();
unit.type.deathSound.at(unit);
//visual only.
if(Net.client()){

View File

@@ -257,6 +257,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
dead = true;
Events.fire(new BlockDestroyEvent(tile));
block.breakSound.at(tile);
block.onDestroyed(tile);
world.removeBlock(tile);
remove();

View File

@@ -20,6 +20,7 @@ import io.anuke.mindustry.entities.units.Statuses;
import io.anuke.mindustry.game.EventType.UnitDestroyEvent;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.game.Teams.TeamData;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.mindustry.net.Interpolator;
import io.anuke.mindustry.net.Net;
@@ -108,6 +109,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
Effects.effect(Fx.explosion, this);
Effects.shake(2f, 2f, this);
Sounds.bang.at(this);
item.amount = 0;
drownTime = 0f;
status.clear();

View File

@@ -0,0 +1,40 @@
package io.anuke.mindustry.game;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.audio.*;
import io.anuke.arc.math.*;
import io.anuke.arc.util.*;
/** Controls playback of multiple music tracks.*/
public class MusicControl{
private static final float finTime = 80f, foutTime = 80f;
private @Nullable Music current;
public void play(@Nullable Music music){
if(current == null && music != null){
current = music;
current.setLooping(true);
current.setVolume(0f);
current.play();
}else if(current == music && music != null){
current.setVolume(Mathf.clamp(current.getVolume() + Time.delta()/finTime));
}else if(current != null){
current.setVolume(Mathf.clamp(current.getVolume() - Time.delta()/foutTime));
if(current.getVolume() <= 0.01f){
current.stop();
current = null;
if(music != null){
current = music;
current.setVolume(0f);
current.setLooping(true);
current.play();
}
}
}
}
public void silence(){
play(null);
}
}

View File

@@ -50,12 +50,12 @@ public class CrashSender{
try{
File file = new File(OS.getAppDataDirectoryString(Vars.appName), "crashes/crash-report-" + DateTimeFormatter.ofPattern("MM_dd_yyyy_HH_mm_ss").format(LocalDateTime.now()) + ".txt");
new File(OS.getAppDataDirectoryString(Vars.appName)).mkdir();
Files.write(file.toPath(), parseException(exception).getBytes());
Files.createDirectories(Paths.get(OS.getAppDataDirectoryString(Vars.appName), "crashes"));
Files.write(file.toPath(), parseException(exception).getBytes());
writeListener.accept(file);
}catch(Throwable ignored){
}catch(Throwable e){
e.printStackTrace();
Log.err("Failed to save local crash report.");
}

View File

@@ -1,14 +1,16 @@
package io.anuke.mindustry.type;
import io.anuke.arc.Core;
import io.anuke.arc.collection.ObjectSet;
import io.anuke.arc.function.Supplier;
import io.anuke.arc.graphics.g2d.TextureRegion;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.mindustry.content.Items;
import io.anuke.mindustry.entities.type.BaseUnit;
import io.anuke.arc.*;
import io.anuke.arc.audio.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.function.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.ui.ContentDisplay;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.ui.*;
public class UnitType extends UnlockableContent{
public final TypeID typeID;
@@ -35,6 +37,7 @@ public class UnitType extends UnlockableContent{
public Weapon weapon;
public float weaponOffsetY, engineOffset = 6f, engineSize = 2f;
public ObjectSet<StatusEffect> immunities = new ObjectSet<>();
public Sound deathSound = Sounds.bang;
public TextureRegion iconRegion, legRegion, baseRegion, region;

View File

@@ -1,22 +1,20 @@
package io.anuke.mindustry.type;
import io.anuke.annotations.Annotations.Loc;
import io.anuke.annotations.Annotations.Remote;
import io.anuke.arc.Core;
import io.anuke.arc.graphics.g2d.TextureRegion;
import io.anuke.arc.math.Angles;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.util.Time;
import io.anuke.arc.util.Tmp;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.content.Fx;
import io.anuke.mindustry.entities.Effects;
import io.anuke.mindustry.entities.Effects.Effect;
import io.anuke.mindustry.entities.bullet.Bullet;
import io.anuke.mindustry.entities.bullet.BulletType;
import io.anuke.mindustry.entities.traits.ShooterTrait;
import io.anuke.mindustry.entities.type.Player;
import io.anuke.mindustry.gen.Call;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.*;
import io.anuke.arc.audio.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.Effects.*;
import io.anuke.mindustry.entities.bullet.*;
import io.anuke.mindustry.entities.traits.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.gen.Sounds;
import io.anuke.mindustry.net.Net;
public class Weapon{
@@ -56,6 +54,8 @@ public class Weapon{
/** whether shooter rotation is ignored when shooting. */
public boolean ignoreRotation = false;
public Sound shootSound = Sounds.shoot;
public TextureRegion region;
protected Weapon(String name){
@@ -69,6 +69,7 @@ public class Weapon{
@Remote(targets = Loc.server, called = Loc.both, unreliable = true)
public static void onPlayerShootWeapon(Player player, float x, float y, float rotation, boolean left){
if(player == null) return;
//clients do not see their own shoot events: they are simulated completely clientside to prevent laggy visuals
//messing with the firerate or any other stats does not affect the server (take that, script kiddies!)
@@ -91,6 +92,7 @@ public class Weapon{
float baseX = shooter.getX(), baseY = shooter.getY();
Weapon weapon = shooter.getWeapon();
weapon.shootSound.at(x, y);
sequenceNum = 0;
if(weapon.shotDelay > 0.01f){

View File

@@ -1,18 +1,17 @@
package io.anuke.mindustry.ui.dialogs;
import io.anuke.arc.Core;
import io.anuke.arc.Events;
import io.anuke.arc.input.KeyCode;
import io.anuke.arc.scene.ui.Dialog;
import io.anuke.arc.scene.ui.ScrollPane;
import io.anuke.arc.util.Align;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.game.EventType.ResizeEvent;
import io.anuke.mindustry.graphics.Pal;
import io.anuke.arc.*;
import io.anuke.arc.input.*;
import io.anuke.arc.scene.event.*;
import io.anuke.arc.scene.ui.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.core.GameState.*;
import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.net.Net;
import static io.anuke.mindustry.Vars.iconsize;
import static io.anuke.mindustry.Vars.state;
import static io.anuke.mindustry.Vars.*;
public class FloatingDialog extends Dialog{
private boolean wasPaused;
@@ -32,7 +31,9 @@ public class FloatingDialog extends Dialog{
state.set(State.playing);
}
}
Sounds.back.play();
});
ClickListener.clicked = () -> Sounds.press.play();
shown(() -> {
if(shouldPause && !state.is(State.menu)){

View File

@@ -1,38 +1,36 @@
package io.anuke.mindustry.world;
import io.anuke.annotations.Annotations.CallSuper;
import io.anuke.arc.Core;
import io.anuke.arc.Graphics.Cursor;
import io.anuke.arc.Graphics.Cursor.SystemCursor;
import io.anuke.arc.collection.Array;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.*;
import io.anuke.arc.Graphics.*;
import io.anuke.arc.Graphics.Cursor.*;
import io.anuke.arc.audio.*;
import io.anuke.arc.collection.EnumSet;
import io.anuke.arc.function.BooleanProvider;
import io.anuke.arc.function.Function;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.collection.*;
import io.anuke.arc.function.*;
import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.graphics.g2d.TextureAtlas.AtlasRegion;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.arc.util.Align;
import io.anuke.arc.util.Time;
import io.anuke.arc.util.pooling.Pools;
import io.anuke.mindustry.entities.Damage;
import io.anuke.mindustry.entities.bullet.Bullet;
import io.anuke.mindustry.entities.effect.Puddle;
import io.anuke.mindustry.entities.effect.RubbleDecal;
import io.anuke.arc.graphics.g2d.TextureAtlas.*;
import io.anuke.arc.math.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.arc.util.pooling.*;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.bullet.*;
import io.anuke.mindustry.entities.effect.*;
import io.anuke.mindustry.entities.type.Unit;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.game.UnlockableContent;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.input.InputHandler.PlaceDraw;
import io.anuke.mindustry.input.InputHandler.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.ui.Bar;
import io.anuke.mindustry.ui.ContentDisplay;
import io.anuke.mindustry.world.blocks.Floor;
import io.anuke.mindustry.world.blocks.OverlayFloor;
import io.anuke.mindustry.ui.*;
import io.anuke.mindustry.world.blocks.*;
import io.anuke.mindustry.world.consumers.*;
import io.anuke.mindustry.world.meta.*;
import java.util.Arrays;
import java.util.*;
import static io.anuke.mindustry.Vars.*;
@@ -98,6 +96,8 @@ public class Block extends BlockStorage{
public boolean outlineIcon = false;
/** Whether this block has a shadow under it. */
public boolean hasShadow = true;
/** Sounds made when this block breaks.*/
public Sound breakSound = Sounds.die;
/** Cost of constructing this block. */
public ItemStack[] buildRequirements = new ItemStack[]{};

View File

@@ -15,7 +15,7 @@ import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.game.EventType.BlockBuildEndEvent;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.world.Block;
@@ -54,6 +54,7 @@ public class BuildBlock extends Block{
Effects.effect(Fx.breakBlock, tile.drawx(), tile.drawy(), block.size);
world.removeBlock(tile);
Events.fire(new BlockBuildEndEvent(tile, team, true));
Sounds.breaks.at(tile);
}
@Remote(called = Loc.server)
@@ -74,6 +75,7 @@ public class BuildBlock extends Block{
Core.app.post(() -> tile.block().playerPlaced(tile));
}
Core.app.post(() -> Events.fire(new BlockBuildEndEvent(tile, team, false)));
Sounds.place.at(tile);
}
@Override

View File

@@ -9,7 +9,7 @@ project.ext.assetsDir = new File("../core/assets")
def IKVM_DIR = System.env.IKVM_HOME
def getTarget = { return project.hasProperty("target") ? project.properties["target"] : "windows" }
task run(dependsOn: classes, type: JavaExec) {
task run(dependsOn: classes, type: JavaExec){
main = project.mainClassName
classpath = sourceSets.main.runtimeClasspath
standardInput = System.in
@@ -29,20 +29,23 @@ task run(dependsOn: classes, type: JavaExec) {
}
}
task dist(type: Jar, dependsOn: classes) {
task dist(type: Jar, dependsOn: classes){
from files(sourceSets.main.output.classesDirs)
from files(sourceSets.main.output.resourcesDir)
from {configurations.compile.collect {zipTree(it)}}
from files(project.assetsDir);
from files(project.assetsDir)
//use target = all for all platforms
def target = getTarget()
if(target == "windows") exclude('**.so', "**.dylib")
if(target.contains("windows")){
def prefix = target.contains("32") ? "64" : ""
exclude('**.so', "**.dylib", "sdl-arc${prefix}.dll", "gdx${prefix}.dll", "gdx-freetype${prefix}.dll")
}
if(target == "mac") exclude('**.so', "**.dll")
if(target == "linux") exclude('**.dll', "**.dylib")
archivesBaseName = appName + "-" + target
manifest {
manifest{
attributes 'Main-Class': project.mainClassName
}
}
@@ -61,7 +64,8 @@ task ikdist{
doLast{
def filename = "$appName-windows-${version}"
def folder = "build/libs/$filename"
def args = ["mono", "$IKVM_DIR/ikvmc.exe", "-target:winexe", "-static", "-out:build/libs/${filename}.exe", "build/libs/${filename}.jar"]
def baseArgs = System.properties['os.name'].toLowerCase().contains('windows') ? [] : ["mono"]
def args = baseArgs + ["$IKVM_DIR/ikvmc.exe", "-target:winexe", "-static", "-out:build/libs/${filename}.exe", "build/libs/${filename}.jar"]
if(file("../core/assets/sprites/icon.ico").exists()){
args += ["-win32icon:../core/assets/sprites/icon.ico"]
}else if(file("../core/assets/icons/icon.ico").exists()){
@@ -78,7 +82,7 @@ task ikdist{
}
copy{
from "$IKVM_DIR/libraries"
from(getTarget().contains("32") ? "$IKVM_DIR/libraries_32" : "$IKVM_DIR/libraries")
into folder
}
}

View File

@@ -41,7 +41,7 @@ public class DesktopPlatform extends Platform{
}
static void handleCrash(Throwable e){
Consumer<Runnable> dialog = r -> new Thread(r).start();
Consumer<Runnable> dialog = Runnable::run;
boolean badGPU = false;
if(e.getMessage() != null && (e.getMessage().contains("Couldn't create window") || e.getMessage().contains("OpenGL 2.0 or higher"))){
@@ -58,7 +58,7 @@ public class DesktopPlatform extends Platform{
CrashSender.send(e, file -> {
if(!fbgp){
dialog.accept(() -> message("A crash has occured. It has been saved in:\n" + file.getAbsolutePath()));
dialog.accept(() -> message("A crash has occured. It has been saved in:\n" + file.getAbsolutePath() + "\n" + (e.getMessage() == null ? "" : "\n" + e.getMessage())));
}
});
}