Replaced 'loadout' class with schematics / Small sound tweaks

This commit is contained in:
Anuken
2019-11-03 22:15:05 -05:00
parent 08d0a7ada7
commit 08b730a349
16 changed files with 115 additions and 175 deletions

View File

@ -1,10 +1,12 @@
package io.anuke.mindustry.content;
import io.anuke.mindustry.ctype.ContentList;
import io.anuke.mindustry.type.Loadout;
import io.anuke.mindustry.ctype.*;
import io.anuke.mindustry.game.*;
import java.io.*;
public class Loadouts implements ContentList{
public static Loadout
public static Schematic
basicShard,
advancedShard,
basicFoundation,
@ -12,43 +14,13 @@ public class Loadouts implements ContentList{
@Override
public void load(){
basicShard = new Loadout(
" ### ",
" #1# ",
" ### ",
" ^ ^ ",
" ## ## ",
" C# C# "
);
advancedShard = new Loadout(
" ### ",
" #1# ",
"#######",
"C#^ ^C#",
" ## ## ",
" C# C# "
);
basicFoundation = new Loadout(
" #### ",
" #### ",
" #2## ",
" #### ",
" ^^^^ ",
" ###### ",
" C#C#C# "
);
basicNucleus = new Loadout(
" ##### ",
" ##### ",
" ##3## ",
" ##### ",
" >#####< ",
" ^ ^ ^ ^ ",
"#### ####",
"C#C# C#C#"
);
try{
basicShard = Schematics.readBase64("bXNjaAB4nD2K2wqAIBiD5ymibnoRn6YnEP1BwUMoBL19FuJ2sbFvUFgYZDaJsLeQrkinN9UJHImsNzlYE7WrIUastuSbnlKx2VJJt+8IQGGKdfO/8J5yrGJSMegLg+YUIA==");
advancedShard = Schematics.readBase64("bXNjaAB4nD2LjQqAIAyET7OMIOhFfJqeYMxBgSkYCL199gu33fFtB4tOwUTaBCP5QpHFzwtl32DahBeKK1NwPq8hoOcUixwpY+CUxe3XIwBbB/pa6tadVCUP02hgHvp5vZq/0b7pBHPYFOQ=");
basicFoundation = Schematics.readBase64("bXNjaAB4nD1OSQ6DMBBzFhVu8BG+0X8MQyoiJTNSukj8nlCi2Adbtg/GA4OBF8oB00rvyE/9ykafqOIw58A7SWRKy1ZiShhZ5RcOLZhYS1hefQ1gRIeptH9jq/qW2lvc1d2tgWsOfVX/tOwE86AYBA==");
basicNucleus = Schematics.readBase64("bXNjaAB4nD2MUQqAIBBEJy0s6qOLdJXuYNtCgikYBd2+LNmdj308hkGHtkId7M4YFns4mk/yfB4a48602eDI+mlNznu0FMPFd0wYKCaewl8F0EOueqM+yKSLVfJrNKWnSw/FZGzEGXFG9sy/px4gEBW1");
}catch(IOException e){
throw new RuntimeException(e);
}
}
}

View File

@ -7,6 +7,7 @@ import io.anuke.arc.util.ArcAnnotate.*;
import io.anuke.mindustry.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.storage.*;
import static io.anuke.mindustry.Vars.*;
@ -39,6 +40,16 @@ public class Schematic implements Publishable, Comparable<Schematic>{
return stacks;
}
public boolean hasCore(){
return tiles.contains(s -> s.block instanceof CoreBlock);
}
public @NonNull CoreBlock findCore(){
CoreBlock block = (CoreBlock)tiles.find(s -> s.block instanceof CoreBlock).block;
if(block == null) throw new IllegalArgumentException("Schematic is missing a core!");
return block;
}
public String name(){
return tags.get("name", "unknown");
}

View File

@ -20,6 +20,8 @@ import io.anuke.mindustry.input.Placement.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.*;
import io.anuke.mindustry.world.blocks.production.*;
import io.anuke.mindustry.world.blocks.storage.*;
import java.io.*;
import java.util.zip.*;
@ -28,6 +30,8 @@ import static io.anuke.mindustry.Vars.*;
/** Handles schematics.*/
public class Schematics implements Loadable{
public static final String base64Header = "bXNjaAB";
private static final byte[] header = {'m', 's', 'c', 'h'};
private static final byte version = 0;
@ -231,6 +235,27 @@ public class Schematics implements Loadable{
.removeAll(s -> !s.block.isVisible() || !s.block.unlockedCur());
}
public void placeLoadout(Schematic schem, int x, int y){
Stile coreTile = schem.tiles.find(s -> s.block instanceof CoreBlock);
int ox = x - coreTile.x, oy = y - coreTile.y;
schem.tiles.each(st -> {
Tile tile = world.tile(st.x + ox, st.y + oy);
if(tile == null) return;
world.setBlock(tile, st.block, defaultTeam);
tile.rotation(st.rotation);
if(st.block.posConfig){
tile.configureAny(Pos.get(tile.x - st.x + Pos.x(st.config), tile.y - st.y + Pos.y(st.config)));
}else{
tile.configureAny(st.config);
}
if(st.block instanceof Drill){
tile.getLinkedTiles(t -> t.setOverlay(Blocks.oreCopper));
}
});
}
/** Adds a schematic to the list, also copying it into the files.*/
public void add(Schematic schematic){
all.add(schematic);
@ -328,13 +353,13 @@ public class Schematics implements Loadable{
}
}
//region IO methods
/** Loads a schematic from base64. May throw an exception. */
public Schematic readBase64(String schematic) throws IOException{
public static Schematic readBase64(String schematic) throws IOException{
return read(new ByteArrayInputStream(Base64Coder.decode(schematic)));
}
//region IO methods
public static Schematic read(FileHandle file) throws IOException{
Schematic s = read(new DataInputStream(file.read(1024)));
if(!s.tags.containsKey("name")){

View File

@ -33,7 +33,7 @@ public class Stats{
score += (float)((wavesLasted - zone.conditionWave) / zone.launchPeriod + 1) * 1.2f;
}
int capacity = zone.loadout.core().itemCapacity;
int capacity = zone.loadout.findCore().itemCapacity;
//weigh used fractions
float frac = 0f;

View File

@ -122,7 +122,7 @@ public class DesktopInput extends InputHandler{
drawSelected(sreq.x, sreq.y, sreq.block, getRequest(sreq.x, sreq.y, sreq.block.size, sreq) != null ? Pal.remove : Pal.accent);
}
if(Core.input.keyDown(Binding.schematic_select)){
if(Core.input.keyDown(Binding.schematic_select) && !ui.chatfrag.chatOpen()){
drawSelection(schemX, schemY, cursorX, cursorY, Vars.maxSchematicSize);
}
@ -305,7 +305,7 @@ public class DesktopInput extends InputHandler{
selectRequests.clear();
}
if(Core.input.keyRelease(Binding.schematic_select)){
if(Core.input.keyRelease(Binding.schematic_select) && !ui.chatfrag.chatOpen()){
lastSchematic = schematics.create(schemX, schemY, rawCursorX, rawCursorY);
useSchematic(lastSchematic);
if(selectRequests.isEmpty()){

View File

@ -1,11 +1,11 @@
package io.anuke.mindustry.maps.generators;
import io.anuke.mindustry.type.Loadout;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.world.*;
public abstract class Generator{
public int width, height;
protected Loadout loadout;
protected Schematic loadout;
public Generator(int width, int height){
this.width = width;
@ -15,7 +15,7 @@ public abstract class Generator{
public Generator(){
}
public void init(Loadout loadout){
public void init(Schematic loadout){
this.loadout = loadout;
}

View File

@ -5,6 +5,7 @@ import io.anuke.arc.math.*;
import io.anuke.arc.math.geom.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.io.*;
import io.anuke.mindustry.maps.*;
import io.anuke.mindustry.type.*;
@ -52,7 +53,7 @@ public class MapGenerator extends Generator{
}
@Override
public void init(Loadout loadout){
public void init(Schematic loadout){
this.loadout = loadout;
map = maps.loadInternalMap(mapName);
width = map.width;
@ -149,7 +150,7 @@ public class MapGenerator extends Generator{
throw new IllegalArgumentException("All zone maps must have a core.");
}
loadout.setup(core.x, core.y);
schematics.placeLoadout(loadout, core.x, core.y);
world.prepareTiles(tiles);
world.setMap(map);

View File

@ -5,6 +5,8 @@ import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.maps.generators.BasicGenerator;
import io.anuke.mindustry.world.Tile;
import static io.anuke.mindustry.Vars.schematics;
public class DesertWastesGenerator extends BasicGenerator{
public DesertWastesGenerator(int width, int height){
@ -42,6 +44,6 @@ public class DesertWastesGenerator extends BasicGenerator{
//scatter(tiles, Blocks.sandRocks, Blocks.creeptree, 1f);
tiles[endX][endY].setOverlay(Blocks.spawn);
loadout.setup(spawnX, spawnY);
schematics.placeLoadout(loadout, spawnX, spawnY);
}
}

View File

@ -5,6 +5,8 @@ import io.anuke.mindustry.content.Blocks;
import io.anuke.mindustry.maps.generators.BasicGenerator;
import io.anuke.mindustry.world.Tile;
import static io.anuke.mindustry.Vars.schematics;
public class OvergrowthGenerator extends BasicGenerator{
public OvergrowthGenerator(int width, int height){
@ -38,6 +40,6 @@ public class OvergrowthGenerator extends BasicGenerator{
//scatter(tiles, Blocks.sporePine, Blocks.whiteTreeDead, 1f);
tiles[endX][endY].setOverlay(Blocks.spawn);
loadout.setup(spawnX, spawnY);
schematics.placeLoadout(loadout, spawnX, spawnY);
}
}

View File

@ -39,7 +39,19 @@ public class ContentParser{
private ObjectMap<Class<?>, FieldParser> classParsers = new ObjectMap<Class<?>, FieldParser>(){{
put(Effect.class, (type, data) -> field(Fx.class, data));
put(StatusEffect.class, (type, data) -> field(StatusEffects.class, data));
put(Loadout.class, (type, data) -> field(Loadouts.class, data));
put(Schematic.class, (type, data) -> {
Object result = fieldOpt(Loadouts.class, data);
if(result != null){
return result;
}else{
String str = data.asString();
if(str.startsWith(Schematics.base64Header)){
return Schematics.readBase64(str);
}else{
return Schematics.read(Vars.tree.get("schematics/" + str + "." + Vars.schematicExtension));
}
}
});
put(Color.class, (type, data) -> Color.valueOf(data.asString()));
put(BulletType.class, (type, data) -> {
if(data.isString()){

View File

@ -1,113 +0,0 @@
package io.anuke.mindustry.type;
import io.anuke.arc.collection.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.ctype.Content;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.storage.*;
import static io.anuke.mindustry.Vars.*;
//TODO this class is a disappointment
public class Loadout extends Content{
private final Array<Tile> outArray = new Array<>();
private final IntMap<BlockEntry> entries = new IntMap<BlockEntry>(){{
put('>', new BlockEntry(Blocks.conveyor, 0));
put('^', new BlockEntry(Blocks.conveyor, 1));
put('<', new BlockEntry(Blocks.conveyor, 2));
put('v', new BlockEntry(Blocks.conveyor, 3));
put('1', new BlockEntry(Blocks.coreShard));
put('2', new BlockEntry(Blocks.coreFoundation));
put('3', new BlockEntry(Blocks.coreNucleus));
put('C', new BlockEntry(Blocks.mechanicalDrill, Blocks.oreCopper));
}};
private final IntMap<BlockEntry> blocks = new IntMap<>();
private Block core;
public Loadout(String... layout){
int coreX = -1, coreY = -1;
outer:
for(int y = 0; y < layout.length; y++){
for(int x = 0; x < layout[0].length(); x++){
char c = layout[y].charAt(x);
if(entries.get(c) != null && entries.get(c).block instanceof CoreBlock){
core = entries.get(c).block;
coreX = x;
coreY = y;
break outer;
}
}
}
if(coreX == -1) throw new IllegalArgumentException("Schematic does not have a core.");
for(int y = 0; y < layout.length; y++){
for(int x = 0; x < layout[0].length(); x++){
char c = layout[y].charAt(x);
if(entries.containsKey(c)){
BlockEntry entry = entries.get(c);
blocks.put(Pos.get(x - coreX, -(y - coreY)), entry);
}
}
}
}
public Loadout(){
}
public Block core(){
return core;
}
public void setup(int x, int y){
for(IntMap.Entry<BlockEntry> entry : blocks.entries()){
int rx = Pos.x(entry.key);
int ry = Pos.y(entry.key);
Tile tile = world.tile(x + rx, y + ry);
if(tile == null) continue;
world.setBlock(tile, entry.value.block, defaultTeam);
tile.rotation((byte)entry.value.rotation);
if(entry.value.ore != null){
for(Tile t : tile.getLinkedTiles(outArray)){
t.setOverlay(entry.value.ore);
}
}
}
}
@Override
public ContentType getContentType(){
return ContentType.loadout;
}
static class BlockEntry{
final Block block;
final Block ore;
final int rotation;
BlockEntry(Block block, Block ore){
this.block = block;
this.ore = ore;
this.rotation = 0;
}
BlockEntry(Block block, int rotation){
this.block = block;
this.ore = null;
this.rotation = rotation;
}
BlockEntry(Block block){
this.block = block;
this.ore = null;
this.rotation = 0;
}
}
}

View File

@ -26,7 +26,7 @@ public class Zone extends UnlockableContent{
public boolean alwaysUnlocked;
public int conditionWave = Integer.MAX_VALUE;
public int launchPeriod = 10;
public Loadout loadout = Loadouts.basicShard;
public Schematic loadout = Loadouts.basicShard;
public TextureRegion preview;
protected Array<ItemStack> baseLaunchCost = new Array<>();

View File

@ -153,7 +153,7 @@ public class SchematicsDialog extends FloatingDialog{
t.addImageTextButton("$schematic.copy.import", Icon.copySmall, style, () -> {
dialog.hide();
try{
Schematic s = schematics.readBase64(Core.app.getClipboardText());
Schematic s = Schematics.readBase64(Core.app.getClipboardText());
schematics.add(s);
setup();
ui.showInfoFade("$schematic.saved");

View File

@ -143,7 +143,7 @@ public class ZoneInfoDialog extends FloatingDialog{
cont.row();
cont.addButton(zone.canConfigure() ? "$configure" : Core.bundle.format("configure.locked", zone.configureObjective.display()),
() -> loadout.show(zone.loadout.core().itemCapacity, zone.getStartingItems(), zone::resetStartingItems, zone::updateLaunchCost, rebuildItems)
() -> loadout.show(zone.loadout.findCore().itemCapacity, zone.getStartingItems(), zone::resetStartingItems, zone::updateLaunchCost, rebuildItems)
).fillX().pad(3).disabled(b -> !zone.canConfigure());
cont.row();

View File

@ -16,7 +16,6 @@ import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
import static io.anuke.mindustry.Vars.*;
public class Build{
private static final Rectangle rect = new Rectangle();
/** Returns block type that was broken, or null if unsuccesful. */
@Remote(called = Loc.server)

View File

@ -7,6 +7,7 @@ import io.anuke.arc.Graphics.Cursor.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.*;
import io.anuke.arc.util.ArcAnnotate.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.effect.*;
@ -29,6 +30,10 @@ public class BuildBlock extends Block{
public static final int maxSize = 9;
private static final BuildBlock[] buildBlocks = new BuildBlock[maxSize];
private static long lastTime = 0;
private static int pitchSeq = 0;
private static long lastPlayed;
public BuildBlock(int size){
super("build" + size);
this.size = size;
@ -53,7 +58,7 @@ public class BuildBlock extends Block{
Effects.effect(Fx.breakBlock, tile.drawx(), tile.drawy(), block.size);
world.removeBlock(tile);
Events.fire(new BlockBuildEndEvent(tile, playerGroup.getByID(builderID), team, true));
Sounds.breaks.at(tile, Mathf.random(0.7f, 1.4f));
if(shouldPlay()) Sounds.breaks.at(tile, calcPitch(false));
}
@Remote(called = Loc.server)
@ -73,12 +78,36 @@ public class BuildBlock extends Block{
Effects.effect(Fx.placeBlock, tile.drawx(), tile.drawy(), block.size);
}
static boolean shouldPlay(){
if(Time.timeSinceMillis(lastPlayed) >= 32){
lastPlayed = Time.millis();
return true;
}else{
return false;
}
}
static float calcPitch(boolean up){
if(Time.timeSinceMillis(lastTime) < 16 * 30){
lastTime = Time.millis();
pitchSeq ++;
if(pitchSeq > 30){
pitchSeq = 0;
}
return 1f + Mathf.clamp(pitchSeq / 30f) * (up ? 1.9f : -0.4f);
}else{
pitchSeq = 0;
lastTime = Time.millis();
return Mathf.random(0.7f, 1.3f);
}
}
public static void constructed(Tile tile, Block block, int builderID, byte rotation, Team team, boolean skipConfig){
Call.onConstructFinish(tile, block, builderID, rotation, team, skipConfig);
tile.block().placed(tile);
Events.fire(new BlockBuildEndEvent(tile, playerGroup.getByID(builderID), team, false));
Sounds.place.at(tile, Mathf.random(0.7f, 1.4f));
if(shouldPlay()) Sounds.place.at(tile, calcPitch(true));
}
@Override