Modding improvements

This commit is contained in:
Anuken
2019-10-01 21:33:51 -04:00
parent 8ccdba5be2
commit 5b8c237a1e
10 changed files with 144 additions and 94 deletions
@@ -781,7 +781,7 @@ public class Blocks implements ContentList{
}}; }};
copperWallLarge = new Wall("copper-wall-large"){{ copperWallLarge = new Wall("copper-wall-large"){{
requirements(Category.defense, ItemStack.mult(copperWall.buildRequirements, 4)); requirements(Category.defense, ItemStack.mult(copperWall.requirements, 4));
health = 80 * 4 * wallHealthMultiplier; health = 80 * 4 * wallHealthMultiplier;
size = 2; size = 2;
}}; }};
@@ -792,7 +792,7 @@ public class Blocks implements ContentList{
}}; }};
titaniumWallLarge = new Wall("titanium-wall-large"){{ titaniumWallLarge = new Wall("titanium-wall-large"){{
requirements(Category.defense, ItemStack.mult(titaniumWall.buildRequirements, 4)); requirements(Category.defense, ItemStack.mult(titaniumWall.requirements, 4));
health = 110 * wallHealthMultiplier * 4; health = 110 * wallHealthMultiplier * 4;
size = 2; size = 2;
}}; }};
@@ -803,7 +803,7 @@ public class Blocks implements ContentList{
}}; }};
thoriumWallLarge = new Wall("thorium-wall-large"){{ thoriumWallLarge = new Wall("thorium-wall-large"){{
requirements(Category.defense, ItemStack.mult(thoriumWall.buildRequirements, 4)); requirements(Category.defense, ItemStack.mult(thoriumWall.requirements, 4));
health = 200 * wallHealthMultiplier * 4; health = 200 * wallHealthMultiplier * 4;
size = 2; size = 2;
}}; }};
@@ -814,7 +814,7 @@ public class Blocks implements ContentList{
}}; }};
phaseWallLarge = new DeflectorWall("phase-wall-large"){{ phaseWallLarge = new DeflectorWall("phase-wall-large"){{
requirements(Category.defense, ItemStack.mult(phaseWall.buildRequirements, 4)); requirements(Category.defense, ItemStack.mult(phaseWall.requirements, 4));
health = 150 * 4 * wallHealthMultiplier; health = 150 * 4 * wallHealthMultiplier;
size = 2; size = 2;
}}; }};
@@ -825,7 +825,7 @@ public class Blocks implements ContentList{
}}; }};
surgeWallLarge = new SurgeWall("surge-wall-large"){{ surgeWallLarge = new SurgeWall("surge-wall-large"){{
requirements(Category.defense, ItemStack.mult(surgeWall.buildRequirements, 4)); requirements(Category.defense, ItemStack.mult(surgeWall.requirements, 4));
health = 230 * 4 * wallHealthMultiplier; health = 230 * 4 * wallHealthMultiplier;
size = 2; size = 2;
}}; }};
@@ -836,7 +836,7 @@ public class Blocks implements ContentList{
}}; }};
doorLarge = new Door("door-large"){{ doorLarge = new Door("door-large"){{
requirements(Category.defense, ItemStack.mult(door.buildRequirements, 4)); requirements(Category.defense, ItemStack.mult(door.requirements, 4));
openfx = Fx.dooropenlarge; openfx = Fx.dooropenlarge;
closefx = Fx.doorcloselarge; closefx = Fx.doorcloselarge;
health = 100 * 4 * wallHealthMultiplier; health = 100 * 4 * wallHealthMultiplier;
@@ -303,9 +303,9 @@ public class TechTree implements ContentList{
} }
private TechNode node(Block block, Runnable children){ private TechNode node(Block block, Runnable children){
ItemStack[] requirements = new ItemStack[block.buildRequirements.length]; ItemStack[] requirements = new ItemStack[block.requirements.length];
for(int i = 0; i < requirements.length; i++){ for(int i = 0; i < requirements.length; i++){
requirements[i] = new ItemStack(block.buildRequirements[i].item, 30 + block.buildRequirements[i].amount * 6); requirements[i] = new ItemStack(block.requirements[i].item, 30 + block.requirements[i].amount * 6);
} }
return new TechNode(block, requirements, children); return new TechNode(block, requirements, children);
@@ -58,37 +58,11 @@ public class ContentLoader{
list.load(); list.load();
} }
setupMapping();
if(mods != null){ if(mods != null){
mods.loadContent(); mods.loadContent();
} }
setupMapping(); //check up ID mapping, make sure it's linear
loaded = true;
}
private void setupMapping(){
for(ContentType type : ContentType.values()){
contentNameMap[type.ordinal()].clear();
}
for(ContentType type : ContentType.values()){
for(Content c : contentMap[type.ordinal()]){
if(c instanceof MappableContent){
String name = ((MappableContent)c).name;
if(contentNameMap[type.ordinal()].containsKey(name)){
throw new IllegalArgumentException("Two content objects cannot have the same name! (issue: '" + name + "')");
}
contentNameMap[type.ordinal()].put(name, (MappableContent)c);
}
}
}
//set up ID mapping
for(Array<Content> arr : contentMap){ for(Array<Content> arr : contentMap){
for(int i = 0; i < arr.size; i++){ for(int i = 0; i < arr.size; i++){
int id = arr.get(i).id; int id = arr.get(i).id;
@@ -97,6 +71,8 @@ public class ContentLoader{
} }
} }
} }
loaded = true;
} }
/** Logs content statistics.*/ /** Logs content statistics.*/
@@ -125,6 +101,7 @@ public class ContentLoader{
for(ContentType type : ContentType.values()){ for(ContentType type : ContentType.values()){
for(Content content : contentMap[type.ordinal()]){ for(Content content : contentMap[type.ordinal()]){
//TODO catch error and display it per mod
callable.accept(content); callable.accept(content);
} }
} }
@@ -154,6 +131,14 @@ public class ContentLoader{
public void handleContent(Content content){ public void handleContent(Content content){
contentMap[content.getContentType().ordinal()].add(content); contentMap[content.getContentType().ordinal()].add(content);
}
public void handleMappableContent(MappableContent content){
if(contentNameMap[content.getContentType().ordinal()].containsKey(content.name)){
throw new IllegalArgumentException("Two content objects cannot have the same name! (issue: '" + content.name + "')");
}
contentNameMap[content.getContentType().ordinal()].put(content.name, content);
} }
public void setTemporaryMapper(MappableContent[][] temporaryMapper){ public void setTemporaryMapper(MappableContent[][] temporaryMapper){
@@ -1,10 +1,13 @@
package io.anuke.mindustry.game; package io.anuke.mindustry.game;
import io.anuke.mindustry.*;
public abstract class MappableContent extends Content{ public abstract class MappableContent extends Content{
public final String name; public final String name;
public MappableContent(String name){ public MappableContent(String name){
this.name = name; this.name = name;
Vars.content.handleMappableContent(this);
} }
@Override @Override
@@ -13,6 +13,7 @@ import io.anuke.mindustry.entities.Effects.*;
import io.anuke.mindustry.entities.bullet.*; import io.anuke.mindustry.entities.bullet.*;
import io.anuke.mindustry.entities.type.*; import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.game.*; import io.anuke.mindustry.game.*;
import io.anuke.mindustry.mod.Mods.*;
import io.anuke.mindustry.type.*; import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.*;
@@ -24,6 +25,10 @@ public class ContentParser{
put(BulletType.class, (type, data) -> field(Bullets.class, data)); put(BulletType.class, (type, data) -> field(Bullets.class, data));
put(Effect.class, (type, data) -> field(Fx.class, data)); put(Effect.class, (type, data) -> field(Fx.class, data));
}}; }};
/** Stores things that need to be parsed fully, e.g. reading fields of content.
* This is done to accomodate binding of content names first.*/
private Array<Runnable> reads = new Array<>();
private LoadedMod currentMod;
private Json parser = new Json(){ private Json parser = new Json(){
public <T> T readValue(Class<T> type, Class elementType, JsonValue jsonData){ public <T> T readValue(Class<T> type, Class elementType, JsonValue jsonData){
@@ -33,7 +38,11 @@ public class ContentParser{
} }
if(Content.class.isAssignableFrom(type)){ if(Content.class.isAssignableFrom(type)){
return (T)Vars.content.getByName(contentTypes.getThrow(type, () -> new IllegalArgumentException("No content type for class: " + type.getSimpleName())), jsonData.asString()); ContentType ctype = contentTypes.getThrow(type, () -> new IllegalArgumentException("No content type for class: " + type.getSimpleName()));
String prefix = currentMod != null ? currentMod.name + "-" : "";
T one = (T)Vars.content.getByName(ctype, prefix + jsonData.asString());
if(one != null) return one;
return (T)Vars.content.getByName(ctype, jsonData.asString());
} }
} }
@@ -43,21 +52,37 @@ public class ContentParser{
private ObjectMap<ContentType, TypeParser<?>> parsers = ObjectMap.of( private ObjectMap<ContentType, TypeParser<?>> parsers = ObjectMap.of(
ContentType.block, (TypeParser<Block>)(mod, name, value) -> { ContentType.block, (TypeParser<Block>)(mod, name, value) -> {
Class<Block> type = resolve(value.getString("type"), "io.anuke.mindustry.world", "io.anuke.mindustry.world.blocks", "io.anuke.mindustry.world.blocks.defense"); //TODO generate dynamically instead of doing.. this
Class<? extends Block> type = resolve(value.getString("type"),
"io.anuke.mindustry.world",
"io.anuke.mindustry.world.blocks",
"io.anuke.mindustry.world.blocks.defense",
"io.anuke.mindustry.world.blocks.defense.turrets",
"io.anuke.mindustry.world.blocks.distribution",
"io.anuke.mindustry.world.blocks.logic",
"io.anuke.mindustry.world.blocks.power",
"io.anuke.mindustry.world.blocks.production",
"io.anuke.mindustry.world.blocks.sandbox",
"io.anuke.mindustry.world.blocks.storage",
"io.anuke.mindustry.world.blocks.units"
);
Block block = type.getDeclaredConstructor(String.class).newInstance(mod + "-" + name); Block block = type.getDeclaredConstructor(String.class).newInstance(mod + "-" + name);
read(() -> {
readFields(block, value, true); readFields(block, value, true);
//make block visible //make block visible
if(block.buildRequirements != null){ if(block.requirements != null){
block.buildVisibility = () -> true; block.buildVisibility = () -> true;
} }
});
return block; return block;
}, },
ContentType.unit, (TypeParser<UnitType>)(mod, name, value) -> { ContentType.unit, (TypeParser<UnitType>)(mod, name, value) -> {
Class<BaseUnit> type = resolve(value.getString("type"), "io.anuke.mindustry.entities.type.base"); Class<BaseUnit> type = resolve(value.getString("type"), "io.anuke.mindustry.entities.type.base");
UnitType unit = new UnitType(mod + "-" + name, supply(type)); UnitType unit = new UnitType(mod + "-" + name, supply(type));
readFields(unit, value, true); read(() -> readFields(unit, value, true));
return unit; return unit;
}, },
@@ -75,11 +100,19 @@ public class ContentParser{
}else{ }else{
item = constructor.get(mod + "-" + name); item = constructor.get(mod + "-" + name);
} }
readFields(item, value); read(() -> readFields(item, value));
return item; return item;
}; };
} }
private void read(Runnable run){
LoadedMod mod = currentMod;
reads.add(() -> {
this.currentMod = mod;
run.run();
});
}
private void init(){ private void init(){
for(ContentType type : ContentType.all){ for(ContentType type : ContentType.all){
Array<Content> arr = Vars.content.getBy(type); Array<Content> arr = Vars.content.getBy(type);
@@ -95,6 +128,11 @@ public class ContentParser{
} }
} }
public void finishParsing(){
reads.each(Runnable::run);
reads.clear();
}
/** /**
* Parses content from a json file. * Parses content from a json file.
* @param name the name of the file without its extension * @param name the name of the file without its extension
@@ -102,7 +140,7 @@ public class ContentParser{
* @param type the type of content this is * @param type the type of content this is
* @return the content that was parsed * @return the content that was parsed
*/ */
public Content parse(String mod, String name, String json, ContentType type) throws Exception{ public Content parse(LoadedMod mod, String name, String json, ContentType type) throws Exception{
if(contentTypes.isEmpty()){ if(contentTypes.isEmpty()){
init(); init();
} }
@@ -112,7 +150,9 @@ public class ContentParser{
throw new SerializationException("No parsers for content type '" + type + "'"); throw new SerializationException("No parsers for content type '" + type + "'");
} }
Content c = parsers.get(type).parse(mod, name, value); currentMod = mod;
Content c = parsers.get(type).parse(mod.name, name, value);
c.mod = mod;
checkNulls(c); checkNulls(c);
return c; return c;
} }
+15 -11
View File
@@ -44,8 +44,7 @@ public class Mods implements Loadable{
} }
/** @return the loaded mod found by class, or null if not found. */ /** @return the loaded mod found by class, or null if not found. */
public @Nullable public @Nullable LoadedMod getMod(Class<? extends Mod> type){
LoadedMod getMod(Class<? extends Mod> type){
return loaded.find(l -> l.mod.getClass() == type); return loaded.find(l -> l.mod.getClass() == type);
} }
@@ -76,27 +75,30 @@ public class Mods implements Loadable{
packer = new PixmapPacker(2048, 2048, Format.RGBA8888, 2, true); packer = new PixmapPacker(2048, 2048, Format.RGBA8888, 2, true);
for(LoadedMod mod : loaded){ for(LoadedMod mod : loaded){
try{ int[] packed = {0};
int packed = 0; boolean[] failed = {false};
for(FileHandle file : mod.root.child("sprites").list()){ mod.root.child("sprites").walk(file -> {
if(failed[0]) return;
if(file.extension().equals("png")){ if(file.extension().equals("png")){
try(InputStream stream = file.read()){ try(InputStream stream = file.read()){
byte[] bytes = Streams.copyStreamToByteArray(stream, Math.max((int)file.length(), 512)); byte[] bytes = Streams.copyStreamToByteArray(stream, Math.max((int)file.length(), 512));
Pixmap pixmap = new Pixmap(bytes, 0, bytes.length); Pixmap pixmap = new Pixmap(bytes, 0, bytes.length);
packer.pack(mod.name + "-" + file.nameWithoutExtension(), pixmap); packer.pack(mod.name + "-" + file.nameWithoutExtension(), pixmap);
pixmap.dispose(); pixmap.dispose();
packed ++; packed[0] ++;
totalSprites ++; totalSprites ++;
}
}
}
Log.info("Packed {0} images for mod '{1}'.", packed, mod.meta.name);
}catch(IOException e){ }catch(IOException e){
failed[0] = true;
Core.app.post(() -> {
Log.err("Error packing images for mod: {0}", mod.meta.name); Log.err("Error packing images for mod: {0}", mod.meta.name);
e.printStackTrace(); e.printStackTrace();
if(!headless) ui.showException(e); if(!headless) ui.showException(e);
});
} }
} }
});
Log.info("Packed {0} images for mod '{1}'.", packed[0], mod.meta.name);
}
} }
@Override @Override
@@ -197,7 +199,7 @@ public class Mods implements Loadable{
for(FileHandle file : folder.list()){ for(FileHandle file : folder.list()){
if(file.extension().equals("json")){ if(file.extension().equals("json")){
try{ try{
Content loaded = parser.parse(mod.name, file.nameWithoutExtension(), file.readString(), type); Content loaded = parser.parse(mod, file.nameWithoutExtension(), file.readString(), type);
Log.info("[{0}] Loaded '{1}'.", mod.meta.name, loaded); Log.info("[{0}] Loaded '{1}'.", mod.meta.name, loaded);
}catch(Exception e){ }catch(Exception e){
throw new RuntimeException("Failed to parse content file '" + file + "' for mod '" + mod.meta.name + "'.", e); throw new RuntimeException("Failed to parse content file '" + file + "' for mod '" + mod.meta.name + "'.", e);
@@ -209,6 +211,8 @@ public class Mods implements Loadable{
} }
} }
parser.finishParsing();
each(Mod::loadContent); each(Mod::loadContent);
} }
@@ -80,7 +80,7 @@ public class PlacementFragment extends Fragment{
Block tryRecipe = tile.block(); Block tryRecipe = tile.block();
if(tryRecipe.isVisible() && unlocked(tryRecipe)){ if(tryRecipe.isVisible() && unlocked(tryRecipe)){
input.block = tryRecipe; input.block = tryRecipe;
currentCategory = input.block.buildCategory; currentCategory = input.block.category;
return true; return true;
} }
} }
@@ -92,7 +92,7 @@ public class PlacementFragment extends Fragment{
for(KeyCode key : inputCatGrid){ for(KeyCode key : inputCatGrid){
if(Core.input.keyDown(key)){ if(Core.input.keyDown(key)){
input.block = getByCategory(Category.all[i]).first(); input.block = getByCategory(Category.all[i]).first();
currentCategory = input.block.buildCategory; currentCategory = input.block.category;
} }
i++; i++;
} }
@@ -147,7 +147,7 @@ public class PlacementFragment extends Fragment{
button.update(() -> { //color unplacable things gray button.update(() -> { //color unplacable things gray
TileEntity core = player.getClosestCore(); TileEntity core = player.getClosestCore();
Color color = state.rules.infiniteResources || (core != null && (core.items.has(block.buildRequirements, state.rules.buildCostMultiplier) || state.rules.infiniteResources)) ? Color.white : Color.gray; Color color = state.rules.infiniteResources || (core != null && (core.items.has(block.requirements, state.rules.buildCostMultiplier) || state.rules.infiniteResources)) ? Color.white : Color.gray;
button.forEach(elem -> elem.setColor(color)); button.forEach(elem -> elem.setColor(color));
button.setChecked(control.input.block == block); button.setChecked(control.input.block == block);
}); });
@@ -205,7 +205,7 @@ public class PlacementFragment extends Fragment{
topTable.table(req -> { topTable.table(req -> {
req.top().left(); req.top().left();
for(ItemStack stack : lastDisplay.buildRequirements){ for(ItemStack stack : lastDisplay.requirements){
req.table(line -> { req.table(line -> {
line.left(); line.left();
line.addImage(stack.item.icon(Item.Icon.small)).size(8 * 2); line.addImage(stack.item.icon(Item.Icon.small)).size(8 * 2);
@@ -296,7 +296,7 @@ public class PlacementFragment extends Fragment{
Array<Block> getByCategory(Category cat){ Array<Block> getByCategory(Category cat){
returnArray.clear(); returnArray.clear();
for(Block block : content.blocks()){ for(Block block : content.blocks()){
if(block.buildCategory == cat && block.isVisible()){ if(block.category == cat && block.isVisible()){
returnArray.add(block); returnArray.add(block);
} }
} }
+7 -7
View File
@@ -114,9 +114,9 @@ public class Block extends BlockStorage{
public float idleSoundVolume = 0.5f; public float idleSoundVolume = 0.5f;
/** Cost of constructing this block. */ /** Cost of constructing this block. */
public ItemStack[] buildRequirements = new ItemStack[]{}; public ItemStack[] requirements = new ItemStack[]{};
/** Category in place menu. */ /** Category in place menu. */
public Category buildCategory = Category.distribution; public Category category = Category.distribution;
/** Cost of building this block; do not modify directly! */ /** Cost of building this block; do not modify directly! */
public float buildCost; public float buildCost;
/** Whether this block is visible and can currently be built. */ /** Whether this block is visible and can currently be built. */
@@ -387,7 +387,7 @@ public class Block extends BlockStorage{
} }
buildCost = 0f; buildCost = 0f;
for(ItemStack stack : buildRequirements){ for(ItemStack stack : requirements){
buildCost += stack.amount * stack.item.cost; buildCost += stack.amount * stack.item.cost;
} }
@@ -493,7 +493,7 @@ public class Block extends BlockStorage{
stats.add(BlockStat.health, health, StatUnit.none); stats.add(BlockStat.health, health, StatUnit.none);
if(isBuildable()){ if(isBuildable()){
stats.add(BlockStat.buildTime, buildCost / 60, StatUnit.seconds); stats.add(BlockStat.buildTime, buildCost / 60, StatUnit.seconds);
stats.add(BlockStat.buildCost, new ItemListValue(false, buildRequirements)); stats.add(BlockStat.buildCost, new ItemListValue(false, requirements));
} }
consumes.display(stats); consumes.display(stats);
@@ -772,11 +772,11 @@ public class Block extends BlockStorage{
/** Sets up requirements. Use only this method to set up requirements. */ /** Sets up requirements. Use only this method to set up requirements. */
protected void requirements(Category cat, BooleanProvider visible, ItemStack[] stacks){ protected void requirements(Category cat, BooleanProvider visible, ItemStack[] stacks){
this.buildCategory = cat; this.category = cat;
this.buildRequirements = stacks; this.requirements = stacks;
this.buildVisibility = visible; this.buildVisibility = visible;
Arrays.sort(buildRequirements, (a, b) -> Integer.compare(a.item.id, b.item.id)); Arrays.sort(requirements, (a, b) -> Integer.compare(a.item.id, b.item.id));
} }
public enum Icon{ public enum Icon{
@@ -196,8 +196,8 @@ public class BuildBlock extends Block{
float maxProgress = core == null ? amount : checkRequired(core.items, amount, false); float maxProgress = core == null ? amount : checkRequired(core.items, amount, false);
for(int i = 0; i < cblock.buildRequirements.length; i++){ for(int i = 0; i < cblock.requirements.length; i++){
int reqamount = Math.round(state.rules.buildCostMultiplier * cblock.buildRequirements[i].amount); int reqamount = Math.round(state.rules.buildCostMultiplier * cblock.requirements[i].amount);
accumulator[i] += Math.min(reqamount * maxProgress, reqamount - totalAccumulator[i] + 0.00001f); //add min amount progressed to the accumulator accumulator[i] += Math.min(reqamount * maxProgress, reqamount - totalAccumulator[i] + 0.00001f); //add min amount progressed to the accumulator
totalAccumulator[i] = Math.min(totalAccumulator[i] + reqamount * maxProgress, reqamount); totalAccumulator[i] = Math.min(totalAccumulator[i] + reqamount * maxProgress, reqamount);
} }
@@ -221,7 +221,7 @@ public class BuildBlock extends Block{
float deconstructMultiplier = 0.5f; float deconstructMultiplier = 0.5f;
if(cblock != null){ if(cblock != null){
ItemStack[] requirements = cblock.buildRequirements; ItemStack[] requirements = cblock.requirements;
if(requirements.length != accumulator.length || totalAccumulator.length != requirements.length){ if(requirements.length != accumulator.length || totalAccumulator.length != requirements.length){
setDeconstruct(previous); setDeconstruct(previous);
} }
@@ -258,15 +258,15 @@ public class BuildBlock extends Block{
private float checkRequired(ItemModule inventory, float amount, boolean remove){ private float checkRequired(ItemModule inventory, float amount, boolean remove){
float maxProgress = amount; float maxProgress = amount;
for(int i = 0; i < cblock.buildRequirements.length; i++){ for(int i = 0; i < cblock.requirements.length; i++){
int sclamount = Math.round(state.rules.buildCostMultiplier * cblock.buildRequirements[i].amount); int sclamount = Math.round(state.rules.buildCostMultiplier * cblock.requirements[i].amount);
int required = (int)(accumulator[i]); //calculate items that are required now int required = (int)(accumulator[i]); //calculate items that are required now
if(inventory.get(cblock.buildRequirements[i].item) == 0 && sclamount != 0){ if(inventory.get(cblock.requirements[i].item) == 0 && sclamount != 0){
maxProgress = 0f; maxProgress = 0f;
}else if(required > 0){ //if this amount is positive... }else if(required > 0){ //if this amount is positive...
//calculate how many items it can actually use //calculate how many items it can actually use
int maxUse = Math.min(required, inventory.get(cblock.buildRequirements[i].item)); int maxUse = Math.min(required, inventory.get(cblock.requirements[i].item));
//get this as a fraction //get this as a fraction
float fraction = maxUse / (float)required; float fraction = maxUse / (float)required;
@@ -277,7 +277,7 @@ public class BuildBlock extends Block{
//remove stuff that is actually used //remove stuff that is actually used
if(remove){ if(remove){
inventory.remove(cblock.buildRequirements[i].item, maxUse); inventory.remove(cblock.requirements[i].item, maxUse);
} }
} }
//else, no items are required yet, so just keep going //else, no items are required yet, so just keep going
@@ -293,8 +293,8 @@ public class BuildBlock extends Block{
public void setConstruct(Block previous, Block block){ public void setConstruct(Block previous, Block block){
this.cblock = block; this.cblock = block;
this.previous = previous; this.previous = previous;
this.accumulator = new float[block.buildRequirements.length]; this.accumulator = new float[block.requirements.length];
this.totalAccumulator = new float[block.buildRequirements.length]; this.totalAccumulator = new float[block.requirements.length];
this.buildCost = block.buildCost * state.rules.buildCostMultiplier; this.buildCost = block.buildCost * state.rules.buildCostMultiplier;
} }
@@ -303,8 +303,8 @@ public class BuildBlock extends Block{
this.progress = 1f; this.progress = 1f;
if(previous.buildCost >= 0.01f){ if(previous.buildCost >= 0.01f){
this.cblock = previous; this.cblock = previous;
this.accumulator = new float[previous.buildRequirements.length]; this.accumulator = new float[previous.requirements.length];
this.totalAccumulator = new float[previous.buildRequirements.length]; this.totalAccumulator = new float[previous.requirements.length];
this.buildCost = previous.buildCost * state.rules.buildCostMultiplier; this.buildCost = previous.buildCost * state.rules.buildCostMultiplier;
}else{ }else{
this.buildCost = 20f; //default no-requirement build cost is 20 this.buildCost = 20f; //default no-requirement build cost is 20
@@ -1,7 +1,7 @@
package io.anuke.mindustry.world.blocks; package io.anuke.mindustry.world.blocks;
import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.*;
/**An overlay ore for a specific item type.*/ /**An overlay ore for a specific item type.*/
public class OreBlock extends OverlayFloor{ public class OreBlock extends OverlayFloor{
@@ -14,9 +14,27 @@ public class OreBlock extends OverlayFloor{
this.color.set(ore.color); this.color.set(ore.color);
} }
/** For mod use only!*/
public OreBlock(String name){
super(name);
}
public void setup(Item ore){
this.localizedName = ore.localizedName();
this.itemDrop = ore;
this.variants = 3;
this.color.set(ore.color);
}
@Override @Override
public void init(){ public void init(){
super.init(); super.init();
if(itemDrop != null){
setup(itemDrop);
}else{
throw new IllegalArgumentException(name + " must have an item drop!");
}
} }
@Override @Override