Modding improvements
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user