A huge amount of work on GUI
This commit is contained in:
@@ -1 +1,55 @@
|
|||||||
test.hello-world = Hallo Welt!
|
test.hello-world = Hallo Welt!
|
||||||
|
|
||||||
|
game.budget = Budget: %d\u20ac
|
||||||
|
game.quit = Spiel beenden
|
||||||
|
game.quests = Auftr\u00e4ge
|
||||||
|
game.quests.next = N\u00e4chster Auftrag
|
||||||
|
game.quest.reward = %d\u20ac
|
||||||
|
game.trash = M\u00fclltonne
|
||||||
|
game.trash.hover = Zerst\u00f6ren
|
||||||
|
game.storage = Lager
|
||||||
|
game.balance.history = Buchungen
|
||||||
|
game.balance.history.change = Wert in \u20ac
|
||||||
|
game.balance.history.type = Beschreibung
|
||||||
|
game.balance.history.type.abandon = Auftrag abgelehnt
|
||||||
|
game.balance.history.type.destroy = Produkt zerst\u00f6rt
|
||||||
|
game.balance.history.type.move = Produkt bewegt
|
||||||
|
game.balance.history.type.noop = NOOP
|
||||||
|
game.balance.history.type.sell = Produkt ausgelagert
|
||||||
|
game.balance.history.type.store = Produkt eingelagert
|
||||||
|
game.balance.chart = Bilanz
|
||||||
|
game.balance.chart.line = Budget
|
||||||
|
game.balance.total-income = Gesamteinahmen: %d\u20ac
|
||||||
|
game.balance.total-loss = Gesamtverluste: %d\u20ac
|
||||||
|
|
||||||
|
quests.normal = Normal
|
||||||
|
|
||||||
|
products.paper = Papier
|
||||||
|
products.paper.color = Farbe
|
||||||
|
products.paper.color.white = wei\u00df
|
||||||
|
products.paper.color.green = gr\u00fcn
|
||||||
|
products.paper.color.blue = blau
|
||||||
|
products.paper.format = Format
|
||||||
|
products.paper.format.a3 = A3
|
||||||
|
products.paper.format.a4 = A4
|
||||||
|
products.paper.format.a5 = A5
|
||||||
|
|
||||||
|
products.wood = Holz
|
||||||
|
products.wood.type = Art
|
||||||
|
products.wood.type.beech = Buche
|
||||||
|
products.wood.type.oak = Eiche
|
||||||
|
products.wood.type.pine = Fichte
|
||||||
|
products.wood.form = Form
|
||||||
|
products.wood.form.pieces = Scheite
|
||||||
|
products.wood.form.boards = Bretter
|
||||||
|
products.wood.form.beams = Balken
|
||||||
|
|
||||||
|
products.stone = Stein
|
||||||
|
products.stone.type = Art
|
||||||
|
products.stone.type.granite = Granit
|
||||||
|
products.stone.type.marble = Marmor
|
||||||
|
products.stone.type.sandstone = Sandstein
|
||||||
|
products.stone.weight = Gewicht
|
||||||
|
products.stone.weight.light = Leicht
|
||||||
|
products.stone.weight.medium = Mittel
|
||||||
|
products.stone.weight.heavy = Schwer
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ public class Start {
|
|||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
WhatAStorage was = WhatAStorage.getInstance();
|
WhatAStorage was = WhatAStorage.getInstance();
|
||||||
was.reload();
|
was.reload();
|
||||||
was.start();
|
was.setup();
|
||||||
|
|
||||||
I18n.setLang("de_de", was.getContentManager());
|
I18n.getInstance().setLang("de_de", was.getContentManager());
|
||||||
System.out.println(I18n.get("test.hello-world"));
|
System.out.println(I18n.getInstance().getString("test.hello-world"));
|
||||||
|
|
||||||
was.run();
|
was.run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,14 +5,21 @@ import de.siphalor.was.content.lang.I18n;
|
|||||||
import de.siphalor.was.content.pack.FileContentPack;
|
import de.siphalor.was.content.pack.FileContentPack;
|
||||||
import de.siphalor.was.content.pack.JarContentPack;
|
import de.siphalor.was.content.pack.JarContentPack;
|
||||||
import de.siphalor.was.content.product.ProductManager;
|
import de.siphalor.was.content.product.ProductManager;
|
||||||
|
import de.siphalor.was.content.quest.Quest;
|
||||||
|
import de.siphalor.was.content.quest.QuestGenerator;
|
||||||
import de.siphalor.was.content.quest.QuestManager;
|
import de.siphalor.was.content.quest.QuestManager;
|
||||||
import de.siphalor.was.visual.CanvasVisual;
|
import de.siphalor.was.game.Balance;
|
||||||
|
import de.siphalor.was.visual.JFXVisual;
|
||||||
import de.siphalor.was.visual.Visual;
|
import de.siphalor.was.visual.Visual;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class WhatAStorage {
|
public class WhatAStorage {
|
||||||
|
private static final int MAX_QUESTS = 3;
|
||||||
|
|
||||||
public static final String TITLE = "What a Storage";
|
public static final String TITLE = "What a Storage";
|
||||||
private static final WhatAStorage INSTANCE = new WhatAStorage();
|
private static final WhatAStorage INSTANCE = new WhatAStorage();
|
||||||
|
|
||||||
@@ -29,6 +36,10 @@ public class WhatAStorage {
|
|||||||
|
|
||||||
private boolean stopScheduled;
|
private boolean stopScheduled;
|
||||||
|
|
||||||
|
private Balance balance;
|
||||||
|
private QuestGenerator questGenerator;
|
||||||
|
private final List<Quest> quests = new ArrayList<>(MAX_QUESTS);
|
||||||
|
|
||||||
private WhatAStorage() {
|
private WhatAStorage() {
|
||||||
contentManager = new ContentManager();
|
contentManager = new ContentManager();
|
||||||
mainPack = new JarContentPack("", "content");
|
mainPack = new JarContentPack("", "content");
|
||||||
@@ -36,7 +47,7 @@ public class WhatAStorage {
|
|||||||
productManager = new ProductManager();
|
productManager = new ProductManager();
|
||||||
questManager = new QuestManager();
|
questManager = new QuestManager();
|
||||||
|
|
||||||
visual = new CanvasVisual();
|
visual = new JFXVisual();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ContentManager getContentManager() {
|
public ContentManager getContentManager() {
|
||||||
@@ -61,7 +72,7 @@ public class WhatAStorage {
|
|||||||
contentManager.addPack(new FileContentPack(dir.getName(), dir.toPath()));
|
contentManager.addPack(new FileContentPack(dir.getName(), dir.toPath()));
|
||||||
}
|
}
|
||||||
|
|
||||||
I18n.reload(contentManager);
|
I18n.getInstance().reload(contentManager);
|
||||||
|
|
||||||
productManager.clear();
|
productManager.clear();
|
||||||
questManager.clear();
|
questManager.clear();
|
||||||
@@ -71,19 +82,62 @@ public class WhatAStorage {
|
|||||||
System.out.println("Reloaded game content");
|
System.out.println("Reloaded game content");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
public void setup() {
|
||||||
visual.setup(this);
|
visual.setup(this);
|
||||||
|
loadGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
visual.run();
|
visual.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void loadGame() {
|
||||||
|
questGenerator = questManager.get("normal");
|
||||||
|
quests.clear();
|
||||||
|
balance = new Balance();
|
||||||
|
}
|
||||||
|
|
||||||
public void scheduleStop() {
|
public void scheduleStop() {
|
||||||
stopScheduled = true;
|
stopScheduled = true;
|
||||||
|
visual.onScheduleStop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStopScheduled() {
|
public boolean isStopScheduled() {
|
||||||
return stopScheduled;
|
return stopScheduled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Balance getBalance() {
|
||||||
|
return balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addTransaction(Balance.Transaction transaction, int change) {
|
||||||
|
balance.add(transaction, change);
|
||||||
|
visual.onBalanceChanged(balance.getBudget(), transaction, change, balance.getTotalIncome(), balance.getTotalLoss());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean requestQuest() {
|
||||||
|
if (quests.size() >= MAX_QUESTS) return false;
|
||||||
|
|
||||||
|
if (!questGenerator.hasMoreElements()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Quest next = questGenerator.nextElement();
|
||||||
|
quests.add(next);
|
||||||
|
|
||||||
|
visual.onQuestAdded(next, quests.size() < MAX_QUESTS);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void abandonQuest(int index) {
|
||||||
|
if (index >= quests.size()) {
|
||||||
|
System.out.println("INTERNAL ERROR: Attempted to abandon non-existent quest!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Quest quest = quests.remove(index);
|
||||||
|
addTransaction(Balance.Transaction.ABANDON, -quest.getReward());
|
||||||
|
|
||||||
|
visual.onQuestAbandoned(index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,33 +7,39 @@ import javax.imageio.ImageIO;
|
|||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
public class AssetsManager {
|
public class AssetsManager {
|
||||||
private static final Map<String, Image> imageCache = new HashMap<>();
|
private static final Map<String, Image> imageCache = new HashMap<>();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public static final Image MISSINGNO = getImage("textures/missingno.png");
|
public static final Image MISSINGNO = getImage("textures/missingno.png");
|
||||||
|
|
||||||
@Nullable
|
@NotNull
|
||||||
public static InputStream getResource(@NotNull String path) {
|
public static Optional<InputStream> getStream(@NotNull String path) {
|
||||||
return Thread.currentThread().getContextClassLoader().getResourceAsStream("assets/" + path);
|
return Optional.ofNullable(Thread.currentThread().getContextClassLoader().getResourceAsStream("assets/" + path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static Optional<URL> getURL(@NotNull String path) {
|
||||||
|
return Optional.ofNullable(Thread.currentThread().getContextClassLoader().getResource(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public static Image getImage(@NotNull String path) {
|
public static Image getImage(@NotNull String path) {
|
||||||
Image image = imageCache.get(path);
|
Image image = imageCache.get(path);
|
||||||
if (image == null) {
|
if (image == null) {
|
||||||
InputStream inputStream = getResource(path);
|
image = getStream(path).map(inputStream -> {
|
||||||
if (inputStream != null) {
|
|
||||||
try {
|
try {
|
||||||
image = ImageIO.read(inputStream);
|
return (Image) ImageIO.read(inputStream);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
image = MISSINGNO;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
image = MISSINGNO;
|
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
|
}).orElse(MISSINGNO);
|
||||||
imageCache.put(path, image);
|
imageCache.put(path, image);
|
||||||
}
|
}
|
||||||
return image;
|
return image;
|
||||||
|
|||||||
@@ -4,21 +4,30 @@ import de.siphalor.was.content.ContentManager;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public class I18n {
|
import java.util.*;
|
||||||
|
|
||||||
|
public class I18n extends ResourceBundle {
|
||||||
public static final String DEFAULT = "en_us";
|
public static final String DEFAULT = "en_us";
|
||||||
private static final Lang DEFAULT_LANG = new Lang(DEFAULT);
|
|
||||||
|
private final Lang DEFAULT_LANG = new Lang(DEFAULT);
|
||||||
|
|
||||||
|
private static final I18n INSTANCE = new I18n();
|
||||||
|
|
||||||
|
public static I18n getInstance() {
|
||||||
|
return INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static Lang lang;
|
private Lang lang;
|
||||||
|
|
||||||
public static void setLang(@NotNull String code, @NotNull ContentManager contentManager) {
|
public void setLang(@NotNull String code, @NotNull ContentManager contentManager) {
|
||||||
if (lang == null || !lang.getCode().equals(code)) {
|
if (lang == null || !lang.getCode().equals(code)) {
|
||||||
lang = new Lang(code);
|
lang = new Lang(code);
|
||||||
lang.load(contentManager);
|
lang.load(contentManager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void reload(@NotNull ContentManager contentManager) {
|
public void reload(@NotNull ContentManager contentManager) {
|
||||||
DEFAULT_LANG.load(contentManager);
|
DEFAULT_LANG.load(contentManager);
|
||||||
if (lang != null) {
|
if (lang != null) {
|
||||||
lang.load(contentManager);
|
lang.load(contentManager);
|
||||||
@@ -26,7 +35,13 @@ public class I18n {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static String get(@NotNull String key) {
|
public String format(@NotNull String key, @Nullable Object... args) {
|
||||||
|
return String.format(getString(key), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
protected Object handleGetObject(@NotNull String key) {
|
||||||
String val;
|
String val;
|
||||||
if (lang != null) {
|
if (lang != null) {
|
||||||
val = lang.get(key);
|
val = lang.get(key);
|
||||||
@@ -44,7 +59,12 @@ public class I18n {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static String format(@NotNull String key, @Nullable Object... args) {
|
@Override
|
||||||
return String.format(get(key), args);
|
public Enumeration<String> getKeys() {
|
||||||
|
if (lang == null)
|
||||||
|
return DEFAULT_LANG.getKeys();
|
||||||
|
Set<String> keys = new HashSet<>(Collections.list(lang.getKeys()));
|
||||||
|
keys.addAll(Collections.list(DEFAULT_LANG.getKeys()));
|
||||||
|
return Collections.enumeration(keys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.Enumeration;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
@@ -50,4 +51,11 @@ public class Lang {
|
|||||||
public String get(@NotNull String key) {
|
public String get(@NotNull String key) {
|
||||||
return (String) properties.get(key);
|
return (String) properties.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Enumeration<String> getKeys() {
|
||||||
|
// This is really ugly but we know™ that the keys will always be strings
|
||||||
|
//noinspection unchecked
|
||||||
|
return (Enumeration<String>)(Object) properties.keys();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,42 @@
|
|||||||
package de.siphalor.was.content.product;
|
package de.siphalor.was.content.product;
|
||||||
|
|
||||||
|
import de.siphalor.was.content.lang.I18n;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public interface Product {
|
public interface Product {
|
||||||
@NotNull
|
@NotNull
|
||||||
String getPropertySpecifier();
|
String getPropertySpecifier();
|
||||||
|
String[] getProperties();
|
||||||
|
|
||||||
int getDepth();
|
int getDepth();
|
||||||
boolean testY(int y);
|
boolean testY(int y);
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
ProductType<?> getType();
|
ProductType<?> getType();
|
||||||
|
|
||||||
|
default String getTranslationKey() {
|
||||||
|
return "products." + getType().getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
default String getName(I18n i18n) {
|
||||||
|
return i18n.getString(getTranslationKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
default String getDescription(I18n i18n) {
|
||||||
|
String[] props = getType().getProperties();
|
||||||
|
String[] values = getProperties();
|
||||||
|
|
||||||
|
String base = getTranslationKey();
|
||||||
|
|
||||||
|
StringBuilder res = new StringBuilder();
|
||||||
|
for (int i = 0; i < props.length; i++) {
|
||||||
|
res.append(i18n.getString(base + "." + props[i]));
|
||||||
|
res.append(": ");
|
||||||
|
res.append(i18n.getString(base + "." + props[i] + "." + values[i]));
|
||||||
|
res.append(", ");
|
||||||
|
}
|
||||||
|
res.delete(res.length() - 2, res.length());
|
||||||
|
|
||||||
|
return res.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ public class ProductManager implements ResourceManager<ProductType<?>> {
|
|||||||
contentManager.getResources("products", "properties").forEach(resource -> {
|
contentManager.getResources("products", "properties").forEach(resource -> {
|
||||||
InputStream inputStream = resource.getInputStream();
|
InputStream inputStream = resource.getInputStream();
|
||||||
if (inputStream != null) {
|
if (inputStream != null) {
|
||||||
productTypes.put(resource.getId(), DynamicProductType.from(inputStream));
|
productTypes.put(resource.getId(), DynamicProductType.from(resource.getId(), inputStream));
|
||||||
try {
|
try {
|
||||||
inputStream.close();
|
inputStream.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
package de.siphalor.was.content.product;
|
package de.siphalor.was.content.product;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public abstract class ProductType<T extends Product> {
|
public interface ProductType<T extends Product> {
|
||||||
|
|
||||||
public ProductType() {
|
@Nullable T getProduct(@NotNull String[] values);
|
||||||
}
|
@NotNull String getId();
|
||||||
|
@NotNull String[] getProperties();
|
||||||
@Nullable
|
|
||||||
public abstract T getProduct(String[] values);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ public class DynamicProduct implements Product {
|
|||||||
return String.join("_", properties);
|
return String.join("_", properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getProperties() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
public void setDepth(int depth) {
|
public void setDepth(int depth) {
|
||||||
this.depth = depth;
|
this.depth = depth;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,13 @@ import java.util.*;
|
|||||||
import java.util.function.IntPredicate;
|
import java.util.function.IntPredicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class DynamicProductType extends ProductType<DynamicProduct> {
|
public class DynamicProductType implements ProductType<DynamicProduct> {
|
||||||
|
private final String id;
|
||||||
private final Map<String, DynamicProduct> variations;
|
private final Map<String, DynamicProduct> variations;
|
||||||
private final String[] properties;
|
private final String[] properties;
|
||||||
|
|
||||||
public DynamicProductType(List<DynamicProduct> variations, String[] properties) {
|
public DynamicProductType(String id, List<DynamicProduct> variations, String[] properties) {
|
||||||
|
this.id = id;
|
||||||
this.variations = new HashMap<>();
|
this.variations = new HashMap<>();
|
||||||
variations.forEach(p -> {
|
variations.forEach(p -> {
|
||||||
p.setType(this);
|
p.setType(this);
|
||||||
@@ -24,7 +26,7 @@ public class DynamicProductType extends ProductType<DynamicProduct> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static DynamicProductType from(@NotNull InputStream inputStream) {
|
public static DynamicProductType from(@NotNull String id, @NotNull InputStream inputStream) {
|
||||||
Properties propertiesFile = new Properties();
|
Properties propertiesFile = new Properties();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -71,13 +73,13 @@ public class DynamicProductType extends ProductType<DynamicProduct> {
|
|||||||
return product;
|
return product;
|
||||||
}).collect(Collectors.toList());
|
}).collect(Collectors.toList());
|
||||||
|
|
||||||
return new DynamicProductType(products, propNameList.toArray(String[]::new));
|
return new DynamicProductType(id, products, propNameList.toArray(String[]::new));
|
||||||
}
|
}
|
||||||
} catch (IOException | NullPointerException e) {
|
} catch (IOException | NullPointerException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DynamicProductType(List.of(new DynamicProduct(Util.emptyArray())), Util.emptyArray());
|
return new DynamicProductType(id, List.of(new DynamicProduct(Util.emptyArray())), Util.emptyArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ProductPrototype makePrototype(Properties propertiesFile, String property, String variant) {
|
private static ProductPrototype makePrototype(Properties propertiesFile, String property, String variant) {
|
||||||
@@ -109,10 +111,20 @@ public class DynamicProductType extends ProductType<DynamicProduct> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DynamicProduct getProduct(String[] values) {
|
public DynamicProduct getProduct(@NotNull String[] values) {
|
||||||
return variations.get(String.join("_", values));
|
return variations.get(String.join("_", values));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull String[] getProperties() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
private static class ProductPrototype {
|
private static class ProductPrototype {
|
||||||
String value;
|
String value;
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public class Quest {
|
|||||||
return reward;
|
return reward;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Type {
|
public enum Type {
|
||||||
IN, OUT
|
IN, OUT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package de.siphalor.was.content.quest;
|
package de.siphalor.was.content.quest;
|
||||||
|
|
||||||
public interface QuestGenerator {
|
import java.util.Enumeration;
|
||||||
|
|
||||||
|
public interface QuestGenerator extends Enumeration<Quest> {
|
||||||
/**
|
/**
|
||||||
* Restarts this generator
|
* Restarts this generator
|
||||||
*/
|
*/
|
||||||
@@ -9,21 +11,7 @@ public interface QuestGenerator {
|
|||||||
/**
|
/**
|
||||||
* Returns the next {@link Quest} but doesn't advance
|
* Returns the next {@link Quest} but doesn't advance
|
||||||
* @return the next {@link Quest}
|
* @return the next {@link Quest}
|
||||||
* @see QuestGenerator#next()
|
* @see QuestGenerator#nextElement()
|
||||||
*/
|
*/
|
||||||
Quest peek();
|
Quest peek();
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the next {@link Quest} and advances
|
|
||||||
* @return the next {@link Quest}
|
|
||||||
* @see QuestGenerator#peek()
|
|
||||||
*/
|
|
||||||
Quest next();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether another {@link Quest} can be generated
|
|
||||||
* @return whether the generator is at its end
|
|
||||||
* @see QuestGenerator#restart()
|
|
||||||
*/
|
|
||||||
boolean hasNext();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,12 +78,12 @@ public class StaticQuestGenerator implements QuestGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Quest next() {
|
public Quest nextElement() {
|
||||||
return quests.get(index++);
|
return quests.get(index++);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasMoreElements() {
|
||||||
return index < quests.size();
|
return index < quests.size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
50
src/main/java/de/siphalor/was/game/Balance.java
Normal file
50
src/main/java/de/siphalor/was/game/Balance.java
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package de.siphalor.was.game;
|
||||||
|
|
||||||
|
import de.siphalor.was.util.Pair;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
|
||||||
|
public class Balance {
|
||||||
|
private int budget = 0;
|
||||||
|
private int totalIncome = 0;
|
||||||
|
private int totalLoss = 0;
|
||||||
|
private final Queue<Pair<Transaction, Integer>> history = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
|
public void add(Transaction transaction, int change) {
|
||||||
|
history.add(Pair.of(transaction, change));
|
||||||
|
|
||||||
|
budget += change;
|
||||||
|
|
||||||
|
if (change < 0) {
|
||||||
|
totalLoss -= change;
|
||||||
|
} else {
|
||||||
|
totalIncome += change;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Queue<Pair<Transaction, Integer>> getHistory() {
|
||||||
|
return history;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBudget() {
|
||||||
|
return budget;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotalIncome() {
|
||||||
|
return totalIncome;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotalLoss() {
|
||||||
|
return totalLoss;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Transaction {
|
||||||
|
ABANDON, DESTROY, MOVE, NOOP, SELL, STORE;
|
||||||
|
|
||||||
|
public String getTranslationKey() {
|
||||||
|
return "game.balance.history.type." + name().toLowerCase(Locale.ENGLISH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,32 @@
|
|||||||
package de.siphalor.was.game;
|
package de.siphalor.was.game;
|
||||||
|
|
||||||
public class Storage {
|
import de.siphalor.was.content.product.Product;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class Storage {
|
||||||
|
StorageSlot[][] slots;
|
||||||
|
|
||||||
|
public Storage(int width, int height, int depth) {
|
||||||
|
slots = new StorageSlot[height][width];
|
||||||
|
|
||||||
|
for (StorageSlot[] row : slots) {
|
||||||
|
for (int i = 0; i < row.length; i++) {
|
||||||
|
row[i] = new StorageSlot(depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public StorageSlot get(int x, int y) {
|
||||||
|
return slots[x][y];
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean move(int x1, int y1, int x2, int y2) {
|
||||||
|
StorageSlot slot1 = get(x1, y1);
|
||||||
|
Product product = slot1.front();
|
||||||
|
if (product != null) {
|
||||||
|
return get(x2, y2).add(product);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
73
src/main/java/de/siphalor/was/game/StorageSlot.java
Normal file
73
src/main/java/de/siphalor/was/game/StorageSlot.java
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
package de.siphalor.was.game;
|
||||||
|
|
||||||
|
import de.siphalor.was.content.product.Product;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class StorageSlot {
|
||||||
|
final int depth;
|
||||||
|
final Product[] products;
|
||||||
|
|
||||||
|
public StorageSlot(int depth) {
|
||||||
|
this.depth = depth;
|
||||||
|
this.products = new Product[depth];
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public Product[] getProducts() {
|
||||||
|
return products;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Product front() {
|
||||||
|
for (int i = products.length - 1; i >= 0; i--) {
|
||||||
|
Product product = products[i];
|
||||||
|
if (product != null) {
|
||||||
|
return product;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Product pop() {
|
||||||
|
for (int i = products.length - 1; i >= 0; i--) {
|
||||||
|
Product product = products[i];
|
||||||
|
if (product != null) {
|
||||||
|
products[i] = null;
|
||||||
|
return product;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean fits(@NotNull Product product) {
|
||||||
|
int blocked = 0;
|
||||||
|
for (Product p : products) {
|
||||||
|
if (p == null) break;
|
||||||
|
blocked += p.getDepth();
|
||||||
|
}
|
||||||
|
|
||||||
|
return product.getDepth() <= depth - blocked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean add(@NotNull Product product) {
|
||||||
|
int blocked = 0;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < products.length; i++) {
|
||||||
|
Product p = products[i];
|
||||||
|
if (p == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
blocked += p.getDepth();
|
||||||
|
if (blocked >= depth) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i < products.length && product.getDepth() <= depth - blocked) {
|
||||||
|
products[i] = product;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
package de.siphalor.was.visual;
|
package de.siphalor.was.visual;
|
||||||
|
|
||||||
import de.siphalor.was.WhatAStorage;
|
import de.siphalor.was.WhatAStorage;
|
||||||
|
import de.siphalor.was.content.quest.Quest;
|
||||||
|
import de.siphalor.was.game.Balance;
|
||||||
import de.siphalor.was.visual.canvas.layout.FixedAspectLayout;
|
import de.siphalor.was.visual.canvas.layout.FixedAspectLayout;
|
||||||
import de.siphalor.was.visual.canvas.layout.FulfillingLayout;
|
import de.siphalor.was.visual.canvas.layout.FulfillingLayout;
|
||||||
|
|
||||||
@@ -119,4 +121,24 @@ public class CanvasVisual implements Visual {
|
|||||||
frame.setVisible(false);
|
frame.setVisible(false);
|
||||||
frame.dispose();
|
frame.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onScheduleStop() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBalanceChanged(int budget, Balance.Transaction transaction, int change, int totalIncome, int totalLoss) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onQuestAdded(Quest newQuest, boolean canCreateMore) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onQuestAbandoned(int index) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,36 @@ package de.siphalor.was.visual;
|
|||||||
|
|
||||||
import de.siphalor.was.WhatAStorage;
|
import de.siphalor.was.WhatAStorage;
|
||||||
import de.siphalor.was.assets.AssetsManager;
|
import de.siphalor.was.assets.AssetsManager;
|
||||||
|
import de.siphalor.was.content.lang.I18n;
|
||||||
|
import de.siphalor.was.content.product.Product;
|
||||||
|
import de.siphalor.was.content.quest.Quest;
|
||||||
|
import de.siphalor.was.game.Balance;
|
||||||
|
import de.siphalor.was.util.Pair;
|
||||||
|
import de.siphalor.was.visual.jfx.BalanceEntry;
|
||||||
|
import de.siphalor.was.visual.jfx.MainController;
|
||||||
|
import de.siphalor.was.visual.jfx.QuestController;
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
|
import javafx.scene.Parent;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.chart.NumberAxis;
|
||||||
|
import javafx.scene.chart.XYChart;
|
||||||
|
import javafx.scene.control.TableColumn;
|
||||||
|
import javafx.scene.control.cell.PropertyValueFactory;
|
||||||
|
import javafx.scene.image.Image;
|
||||||
|
import javafx.scene.layout.Pane;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public class JFXVisual extends Application implements Visual {
|
public class JFXVisual extends Application implements Visual {
|
||||||
private Scene mainScene;
|
private static Stage primaryStage;
|
||||||
|
private static final FXMLLoader loader = new FXMLLoader();
|
||||||
|
|
||||||
|
private static Scene mainScene;
|
||||||
|
|
||||||
|
private static MainController controller;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setup(WhatAStorage whatAStorage) {
|
public void setup(WhatAStorage whatAStorage) {
|
||||||
@@ -21,9 +43,109 @@ public class JFXVisual extends Application implements Visual {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start(Stage primaryStage) throws Exception {
|
public void onScheduleStop() {
|
||||||
FXMLLoader loader = new FXMLLoader();
|
primaryStage.close();
|
||||||
|
}
|
||||||
|
|
||||||
HBox hb = loader.load(AssetsManager.getResource("jfx/main.fxml"));
|
@Override
|
||||||
|
public void onBalanceChanged(int budget, Balance.Transaction transaction, int change, int totalIncome, int totalLoss) {
|
||||||
|
I18n i18n = I18n.getInstance();
|
||||||
|
|
||||||
|
controller.budgetLabel.setText(i18n.format("game.budget", budget));
|
||||||
|
if (budget < 0) {
|
||||||
|
controller.budgetLabel.getStyleClass().add("red");
|
||||||
|
} else {
|
||||||
|
controller.budgetLabel.getStyleClass().remove("red");
|
||||||
|
}
|
||||||
|
|
||||||
|
controller.totalIncomeLabel.setText(i18n.format("game.balance.total-income", totalIncome));
|
||||||
|
controller.totalLossLabel.setText(i18n.format("game.balance.total-loss", totalLoss));
|
||||||
|
|
||||||
|
ObservableList<XYChart.Data<Integer, Integer>> data = controller.budgetChartSeries.getData();
|
||||||
|
int i = data.size();
|
||||||
|
data.add(new XYChart.Data<>(data.size(), budget));
|
||||||
|
|
||||||
|
if (transaction != Balance.Transaction.NOOP) {
|
||||||
|
controller.balanceHistoryTable.getItems().add(new BalanceEntry(i, change, i18n.getString(transaction.getTranslationKey())));
|
||||||
|
controller.balanceHistoryTable.sort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onQuestAdded(Quest newQuest, boolean canCreateMore) {
|
||||||
|
addQuest(newQuest);
|
||||||
|
|
||||||
|
controller.nextQuestButton.setDisable(!canCreateMore);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onQuestAbandoned(int index) {
|
||||||
|
controller.questBox.getChildren().remove(index);
|
||||||
|
|
||||||
|
controller.nextQuestButton.setDisable(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(Stage primaryStage) throws Exception {
|
||||||
|
JFXVisual.primaryStage = primaryStage;
|
||||||
|
primaryStage.setMinWidth(850);
|
||||||
|
primaryStage.setTitle(WhatAStorage.TITLE);
|
||||||
|
|
||||||
|
loader.setResources(I18n.getInstance());
|
||||||
|
controller = new MainController(WhatAStorage.getInstance());
|
||||||
|
loader.setController(controller);
|
||||||
|
|
||||||
|
Pane pane = loader.load(AssetsManager.getStream("jfx/main.fxml").get());
|
||||||
|
mainScene = new Scene(pane);
|
||||||
|
mainScene.getStylesheets().add("assets/jfx/main.css");
|
||||||
|
|
||||||
|
ObservableList<TableColumn<BalanceEntry, ?>> columns = controller.balanceHistoryTable.getColumns();
|
||||||
|
columns.get(0).setCellValueFactory(new PropertyValueFactory<>("index"));
|
||||||
|
columns.get(1).setCellValueFactory(new PropertyValueFactory<>("change"));
|
||||||
|
columns.get(2).setCellValueFactory(new PropertyValueFactory<>("description"));
|
||||||
|
|
||||||
|
loadMainScene();
|
||||||
|
//noinspection unchecked
|
||||||
|
controller.budgetChart.getData().add((XYChart.Series<NumberAxis, NumberAxis>)(Object) controller.budgetChartSeries);
|
||||||
|
|
||||||
|
primaryStage.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadMainScene() {
|
||||||
|
primaryStage.setScene(mainScene);
|
||||||
|
|
||||||
|
AssetsManager.getStream("textures/bin_closed.png").ifPresent(inputStream -> {
|
||||||
|
controller.trash.setImage(new Image(inputStream));
|
||||||
|
});
|
||||||
|
controller.budgetChartSeries.setName(I18n.getInstance().getString("game.balance.chart.line"));
|
||||||
|
|
||||||
|
onBalanceChanged(0, Balance.Transaction.NOOP, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addQuest(Quest quest) {
|
||||||
|
AssetsManager.getStream("jfx/quest_widget.fxml").ifPresentOrElse(is -> {
|
||||||
|
try {
|
||||||
|
FXMLLoader loader = new FXMLLoader();
|
||||||
|
QuestController questController = new QuestController(WhatAStorage.getInstance());
|
||||||
|
loader.setController(questController);
|
||||||
|
Parent parent = loader.load(is);
|
||||||
|
|
||||||
|
controller.questBox.getChildren().add(parent);
|
||||||
|
|
||||||
|
Product product = quest.getProduct();
|
||||||
|
|
||||||
|
I18n i18n = I18n.getInstance();
|
||||||
|
questController.title.setText(product.getName(i18n));
|
||||||
|
|
||||||
|
questController.description.setText(product.getDescription(i18n));
|
||||||
|
|
||||||
|
questController.reward.setText(i18n.format("game.quest.reward", quest.getReward()));
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}, () -> {
|
||||||
|
System.out.println("INTERNAL ERROR: Failed to load quest widget");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
package de.siphalor.was.visual;
|
package de.siphalor.was.visual;
|
||||||
|
|
||||||
import de.siphalor.was.WhatAStorage;
|
import de.siphalor.was.WhatAStorage;
|
||||||
|
import de.siphalor.was.content.quest.Quest;
|
||||||
|
import de.siphalor.was.game.Balance;
|
||||||
|
|
||||||
public interface Visual {
|
public interface Visual {
|
||||||
void setup(WhatAStorage whatAStorage);
|
void setup(WhatAStorage whatAStorage);
|
||||||
void run();
|
void run();
|
||||||
|
void onScheduleStop();
|
||||||
|
|
||||||
|
void onBalanceChanged(int budget, Balance.Transaction transaction, int change, int totalIncome, int totalLoss);
|
||||||
|
|
||||||
|
void onQuestAdded(Quest newQuest, boolean canCreateMore);
|
||||||
|
void onQuestAbandoned(int index);
|
||||||
}
|
}
|
||||||
|
|||||||
25
src/main/java/de/siphalor/was/visual/jfx/BalanceEntry.java
Normal file
25
src/main/java/de/siphalor/was/visual/jfx/BalanceEntry.java
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package de.siphalor.was.visual.jfx;
|
||||||
|
|
||||||
|
public class BalanceEntry {
|
||||||
|
public final int index;
|
||||||
|
public final int change;
|
||||||
|
public final String description;
|
||||||
|
|
||||||
|
public BalanceEntry(int index, int change, String description) {
|
||||||
|
this.index = index;
|
||||||
|
this.change = change;
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndex() {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getChange() {
|
||||||
|
return change;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
}
|
||||||
43
src/main/java/de/siphalor/was/visual/jfx/MainController.java
Normal file
43
src/main/java/de/siphalor/was/visual/jfx/MainController.java
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package de.siphalor.was.visual.jfx;
|
||||||
|
|
||||||
|
import de.siphalor.was.WhatAStorage;
|
||||||
|
import de.siphalor.was.util.Pair;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.scene.chart.LineChart;
|
||||||
|
import javafx.scene.chart.NumberAxis;
|
||||||
|
import javafx.scene.chart.XYChart;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.TableView;
|
||||||
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
|
|
||||||
|
public class MainController {
|
||||||
|
private final WhatAStorage was;
|
||||||
|
|
||||||
|
public Label budgetLabel;
|
||||||
|
public Label totalIncomeLabel;
|
||||||
|
public Label totalLossLabel;
|
||||||
|
public TableView<BalanceEntry> balanceHistoryTable;
|
||||||
|
public LineChart<NumberAxis, NumberAxis> budgetChart;
|
||||||
|
public XYChart.Series<Integer, Integer> budgetChartSeries = new XYChart.Series<>();
|
||||||
|
|
||||||
|
public ImageView trash;
|
||||||
|
|
||||||
|
public VBox questBox;
|
||||||
|
public Button nextQuestButton;
|
||||||
|
|
||||||
|
public MainController(WhatAStorage was) {
|
||||||
|
this.was = was;
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void scheduleStop() {
|
||||||
|
was.scheduleStop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void nextQuest() {
|
||||||
|
was.requestQuest();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package de.siphalor.was.visual.jfx;
|
||||||
|
|
||||||
|
import de.siphalor.was.WhatAStorage;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.image.ImageView;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
|
|
||||||
|
public class QuestController {
|
||||||
|
private final WhatAStorage was;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private GridPane questContainer;
|
||||||
|
|
||||||
|
public Label title;
|
||||||
|
public Label description;
|
||||||
|
public Label reward;
|
||||||
|
|
||||||
|
public ImageView image;
|
||||||
|
|
||||||
|
public QuestController(WhatAStorage was) {
|
||||||
|
this.was = was;
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void abandon() {
|
||||||
|
int index = questContainer.getParent().getChildrenUnmodifiable().indexOf(questContainer);
|
||||||
|
was.abandonQuest(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="de.siphalor.was.visual.layout.MainSwingUI">
|
|
||||||
<grid id="27dc6" binding="panel1" default-binding="true" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
|
||||||
<margin top="0" left="0" bottom="0" right="0"/>
|
|
||||||
<constraints>
|
|
||||||
<xy x="20" y="20" width="639" height="461"/>
|
|
||||||
</constraints>
|
|
||||||
<properties/>
|
|
||||||
<border type="none"/>
|
|
||||||
<children>
|
|
||||||
<splitpane id="d075b">
|
|
||||||
<constraints>
|
|
||||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
|
||||||
<preferred-size width="200" height="200"/>
|
|
||||||
</grid>
|
|
||||||
</constraints>
|
|
||||||
<properties/>
|
|
||||||
<border type="none"/>
|
|
||||||
<children>
|
|
||||||
<grid id="643da" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
|
||||||
<margin top="0" left="0" bottom="0" right="0"/>
|
|
||||||
<constraints>
|
|
||||||
<splitpane position="left"/>
|
|
||||||
</constraints>
|
|
||||||
<properties/>
|
|
||||||
<border type="none"/>
|
|
||||||
<children>
|
|
||||||
<component id="833b4" class="javax.swing.JTable" binding="table1" default-binding="true">
|
|
||||||
<constraints>
|
|
||||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
|
|
||||||
<preferred-size width="150" height="50"/>
|
|
||||||
</grid>
|
|
||||||
</constraints>
|
|
||||||
<properties/>
|
|
||||||
</component>
|
|
||||||
<component id="bfa1c" class="javax.swing.JButton" binding="destroyButton" default-binding="true">
|
|
||||||
<constraints>
|
|
||||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
|
||||||
</constraints>
|
|
||||||
<properties>
|
|
||||||
<text value="Destroy"/>
|
|
||||||
</properties>
|
|
||||||
</component>
|
|
||||||
</children>
|
|
||||||
</grid>
|
|
||||||
<grid id="f0669" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
|
||||||
<margin top="0" left="0" bottom="0" right="0"/>
|
|
||||||
<constraints>
|
|
||||||
<splitpane position="right"/>
|
|
||||||
</constraints>
|
|
||||||
<properties/>
|
|
||||||
<border type="none" title="Quests"/>
|
|
||||||
<children>
|
|
||||||
<component id="f8569" class="javax.swing.JButton" binding="nextQuestButton" default-binding="true">
|
|
||||||
<constraints>
|
|
||||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
|
|
||||||
</constraints>
|
|
||||||
<properties>
|
|
||||||
<text value="Next Quest"/>
|
|
||||||
</properties>
|
|
||||||
</component>
|
|
||||||
</children>
|
|
||||||
</grid>
|
|
||||||
</children>
|
|
||||||
</splitpane>
|
|
||||||
</children>
|
|
||||||
</grid>
|
|
||||||
</form>
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package de.siphalor.was.visual.layout;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
public class MainSwingUI {
|
|
||||||
private JPanel panel1;
|
|
||||||
private JButton nextQuestButton;
|
|
||||||
private JTable table1;
|
|
||||||
private JButton destroyButton;
|
|
||||||
}
|
|
||||||
55
src/main/resources/assets/jfx/main.css
Normal file
55
src/main/resources/assets/jfx/main.css
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
Button.green {
|
||||||
|
-fx-background-color: #56893b;
|
||||||
|
}
|
||||||
|
Button.green:pressed {
|
||||||
|
-fx-background-color: #457229;
|
||||||
|
}
|
||||||
|
Button.red {
|
||||||
|
-fx-background-color: #ff4848;
|
||||||
|
}
|
||||||
|
Button.red:pressed {
|
||||||
|
-fx-background-color: #9c2121;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScrollPane {
|
||||||
|
-fx-background-color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Label.red {
|
||||||
|
-fx-text-fill: #9c2121;
|
||||||
|
}
|
||||||
|
Label.green {
|
||||||
|
-fx-text-fill: #457229;
|
||||||
|
}
|
||||||
|
|
||||||
|
.align-right {
|
||||||
|
-fx-alignment: center-right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.side-pane {
|
||||||
|
-fx-border-width: 0 1;
|
||||||
|
-fx-border-color: #aaaaaa;
|
||||||
|
-fx-background-color: linear-gradient(to bottom, #dddddd, #aaaaaa);
|
||||||
|
}
|
||||||
|
|
||||||
|
.quest-container {
|
||||||
|
-fx-border-width: 1 0 0 0;
|
||||||
|
-fx-border-color: #aaaaaa;
|
||||||
|
-fx-background-color: #eeeeee;
|
||||||
|
}
|
||||||
|
.quest-reward {
|
||||||
|
-fx-text-fill: #457229;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-info-bar {
|
||||||
|
-fx-border-width: 0 0 1 0;
|
||||||
|
-fx-border-color: #aaaaaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-column {
|
||||||
|
-fx-padding: 0 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
-fx-background-color: #dddddd;
|
||||||
|
}
|
||||||
@@ -1,9 +1,163 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<?import javafx.scene.layout.VBox?>
|
|
||||||
<?import javafx.scene.control.Label?>
|
|
||||||
|
|
||||||
<VBox>
|
<?import javafx.geometry.Insets?>
|
||||||
|
<?import javafx.scene.chart.LineChart?>
|
||||||
|
<?import javafx.scene.chart.NumberAxis?>
|
||||||
|
<?import javafx.scene.control.Accordion?>
|
||||||
|
<?import javafx.scene.control.Button?>
|
||||||
|
<?import javafx.scene.control.Label?>
|
||||||
|
<?import javafx.scene.control.ScrollPane?>
|
||||||
|
<?import javafx.scene.control.Tab?>
|
||||||
|
<?import javafx.scene.control.TabPane?>
|
||||||
|
<?import javafx.scene.control.TableColumn?>
|
||||||
|
<?import javafx.scene.control.TableView?>
|
||||||
|
<?import javafx.scene.control.ToolBar?>
|
||||||
|
<?import javafx.scene.image.ImageView?>
|
||||||
|
<?import javafx.scene.layout.ColumnConstraints?>
|
||||||
|
<?import javafx.scene.layout.GridPane?>
|
||||||
|
<?import javafx.scene.layout.HBox?>
|
||||||
|
<?import javafx.scene.layout.RowConstraints?>
|
||||||
|
<?import javafx.scene.layout.VBox?>
|
||||||
|
<?import javafx.scene.text.Font?>
|
||||||
|
|
||||||
|
<GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="450.0" prefWidth="850.0" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308" minWidth="250.0" percentWidth="30.0" prefWidth="250.0" />
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="1.7976931348623157E308" minWidth="10.0" percentWidth="70.0" prefWidth="380.0" />
|
||||||
|
</columnConstraints>
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints fillHeight="false" vgrow="NEVER" />
|
||||||
|
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||||
|
</rowConstraints>
|
||||||
<children>
|
<children>
|
||||||
<Label text="Hello world FXML"/>
|
<GridPane styleClass="side-pane" GridPane.rowIndex="1">
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
|
||||||
|
</columnConstraints>
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints fillHeight="false" minHeight="-Infinity" vgrow="NEVER" />
|
||||||
|
<RowConstraints fillHeight="false" vgrow="NEVER" />
|
||||||
|
<RowConstraints maxHeight="1.7976931348623157E308" vgrow="SOMETIMES" />
|
||||||
|
<RowConstraints fillHeight="false" maxHeight="-Infinity" vgrow="SOMETIMES" />
|
||||||
|
</rowConstraints>
|
||||||
|
<children>
|
||||||
|
<ScrollPane id="quest-pane" fitToWidth="true" hbarPolicy="NEVER" prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="2">
|
||||||
|
<content>
|
||||||
|
<VBox fx:id="questBox" />
|
||||||
|
</content>
|
||||||
|
</ScrollPane>
|
||||||
|
<Label text="%game.trash" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="BOTTOM">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="19.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<ImageView fx:id="trash" fitHeight="80.0" pickOnBounds="true" preserveRatio="true" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="TOP">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets bottom="35.0" top="10.0" />
|
||||||
|
</GridPane.margin>
|
||||||
|
</ImageView>
|
||||||
|
<Label text="%game.quests" GridPane.rowIndex="1">
|
||||||
|
<font>
|
||||||
|
<Font size="23.0" />
|
||||||
|
</font>
|
||||||
|
<padding>
|
||||||
|
<Insets left="10.0" />
|
||||||
|
</padding>
|
||||||
|
</Label>
|
||||||
|
<Button fx:id="nextQuestButton" mnemonicParsing="false" onAction="#nextQuest" styleClass="green" text="%game.quests.next" textFill="WHITE" GridPane.halignment="RIGHT" GridPane.rowIndex="1" GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets right="5.0" />
|
||||||
|
</GridPane.margin>
|
||||||
|
</Button>
|
||||||
|
<Accordion GridPane.rowIndex="1" />
|
||||||
</children>
|
</children>
|
||||||
</VBox>
|
</GridPane>
|
||||||
|
<TabPane tabClosingPolicy="UNAVAILABLE" GridPane.columnIndex="1" GridPane.rowIndex="1">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets />
|
||||||
|
</GridPane.margin>
|
||||||
|
<tabs>
|
||||||
|
<Tab text="%game.storage">
|
||||||
|
<content>
|
||||||
|
<GridPane>
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||||
|
</columnConstraints>
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||||
|
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||||
|
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||||
|
</rowConstraints>
|
||||||
|
</GridPane>
|
||||||
|
</content>
|
||||||
|
</Tab>
|
||||||
|
<Tab text="%game.balance.history">
|
||||||
|
<content>
|
||||||
|
<TableView fx:id="balanceHistoryTable" prefHeight="200.0" prefWidth="200.0">
|
||||||
|
<columns>
|
||||||
|
<TableColumn prefWidth="50.666626400416135" styleClass="align-right" text="%game.balance.history.index" />
|
||||||
|
<TableColumn maxWidth="500.0" prefWidth="149.77776718139648" styleClass="align-right" text="%game.balance.history.change" />
|
||||||
|
<TableColumn maxWidth="1.7976931348623157E308" prefWidth="400.0" text="%game.balance.history.type" />
|
||||||
|
</columns>
|
||||||
|
</TableView>
|
||||||
|
</content>
|
||||||
|
</Tab>
|
||||||
|
<Tab text="%game.balance.chart">
|
||||||
|
<content>
|
||||||
|
<VBox>
|
||||||
|
<children>
|
||||||
|
<HBox fillHeight="false" maxWidth="1.7976931348623157E308" styleClass="tab-info-bar">
|
||||||
|
<children>
|
||||||
|
<Label fx:id="totalIncomeLabel" styleClass="green" text="Label">
|
||||||
|
<font>
|
||||||
|
<Font size="14.0" />
|
||||||
|
</font>
|
||||||
|
<HBox.margin>
|
||||||
|
<Insets right="20.0" />
|
||||||
|
</HBox.margin>
|
||||||
|
</Label>
|
||||||
|
<Label fx:id="totalLossLabel" styleClass="red" text="Label">
|
||||||
|
<font>
|
||||||
|
<Font size="14.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
</children>
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="5.0" left="20.0" right="20.0" top="5.0" />
|
||||||
|
</padding>
|
||||||
|
</HBox>
|
||||||
|
<LineChart fx:id="budgetChart" verticalGridLinesVisible="false">
|
||||||
|
<xAxis>
|
||||||
|
<NumberAxis minorTickVisible="false" side="BOTTOM" tickLabelsVisible="false" tickMarkVisible="false" />
|
||||||
|
</xAxis>
|
||||||
|
<yAxis>
|
||||||
|
<NumberAxis side="LEFT" />
|
||||||
|
</yAxis>
|
||||||
|
</LineChart>
|
||||||
|
</children>
|
||||||
|
</VBox>
|
||||||
|
</content>
|
||||||
|
</Tab>
|
||||||
|
</tabs>
|
||||||
|
</TabPane>
|
||||||
|
<ToolBar prefHeight="40.0" prefWidth="200.0" GridPane.columnSpan="2147483647">
|
||||||
|
<items>
|
||||||
|
<Label fx:id="budgetLabel" text="%game.budget">
|
||||||
|
<font>
|
||||||
|
<Font size="19.0" />
|
||||||
|
</font>
|
||||||
|
<padding>
|
||||||
|
<Insets left="5.0" />
|
||||||
|
</padding>
|
||||||
|
</Label>
|
||||||
|
</items>
|
||||||
|
</ToolBar>
|
||||||
|
<Button mnemonicParsing="false" onMouseClicked="#scheduleStop" styleClass="red" text="%game.quit" textFill="WHITE" GridPane.columnSpan="2147483647" GridPane.halignment="RIGHT" GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets right="10.0" />
|
||||||
|
</GridPane.margin>
|
||||||
|
</Button>
|
||||||
|
</children>
|
||||||
|
</GridPane>
|
||||||
|
|||||||
62
src/main/resources/assets/jfx/quest_widget.fxml
Normal file
62
src/main/resources/assets/jfx/quest_widget.fxml
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.geometry.Insets?>
|
||||||
|
<?import javafx.scene.control.Button?>
|
||||||
|
<?import javafx.scene.control.Label?>
|
||||||
|
<?import javafx.scene.image.ImageView?>
|
||||||
|
<?import javafx.scene.layout.ColumnConstraints?>
|
||||||
|
<?import javafx.scene.layout.GridPane?>
|
||||||
|
<?import javafx.scene.layout.RowConstraints?>
|
||||||
|
<?import javafx.scene.layout.VBox?>
|
||||||
|
<?import javafx.scene.text.Font?>
|
||||||
|
|
||||||
|
<GridPane fx:id="questContainer" maxHeight="-Infinity" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="250.0" prefHeight="80.0" styleClass="quest-container" xmlns="http://javafx.com/javafx/9.0.1" xmlns:fx="http://javafx.com/fxml/1">
|
||||||
|
<columnConstraints>
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="-Infinity" prefWidth="80.0" />
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" />
|
||||||
|
<ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="50.0" prefWidth="50.0" />
|
||||||
|
</columnConstraints>
|
||||||
|
<rowConstraints>
|
||||||
|
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||||
|
</rowConstraints>
|
||||||
|
<children>
|
||||||
|
<ImageView fx:id="image" fitHeight="80.0" fitWidth="100.0" pickOnBounds="true" preserveRatio="true" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets />
|
||||||
|
</GridPane.margin>
|
||||||
|
</ImageView>
|
||||||
|
<Button maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#abandon" prefHeight="0.0" prefWidth="0.0" styleClass="red" text="X" textFill="WHITE" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.valignment="CENTER">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="19.0" />
|
||||||
|
</font>
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
|
</GridPane.margin>
|
||||||
|
</Button>
|
||||||
|
<VBox prefWidth="100.0" GridPane.columnIndex="1">
|
||||||
|
<children>
|
||||||
|
<Label fx:id="title" maxWidth="1.7976931348623157E308" styleClass="quest-title" text="Label">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="21.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<Label fx:id="description" styleClass="quest-desc" text="Label">
|
||||||
|
<font>
|
||||||
|
<Font size="13.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<Label fx:id="reward" styleClass="quest-reward" text="Label">
|
||||||
|
<font>
|
||||||
|
<Font size="13.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
</children>
|
||||||
|
<padding>
|
||||||
|
<Insets left="5.0" />
|
||||||
|
</padding>
|
||||||
|
</VBox>
|
||||||
|
</children>
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
|
</padding>
|
||||||
|
</GridPane>
|
||||||
@@ -1,5 +1,28 @@
|
|||||||
test.hello-world = Hello World!
|
test.hello-world = Hello World!
|
||||||
|
|
||||||
|
game.budget = Budget: %d$
|
||||||
|
game.quit = Quit Game
|
||||||
|
game.quests = Quests
|
||||||
|
game.quests.next = Next Quest
|
||||||
|
game.quest.reward = %d$
|
||||||
|
game.trash = Recycle Bin
|
||||||
|
game.trash.hover = Destroy\n%d$
|
||||||
|
game.storage = Storage
|
||||||
|
game.balance.history = Transactions
|
||||||
|
game.balance.history.index =
|
||||||
|
game.balance.history.change = Change in $
|
||||||
|
game.balance.history.type = Description
|
||||||
|
game.balance.history.type.abandon = Quest abandoned
|
||||||
|
game.balance.history.type.destroy = Product destroy
|
||||||
|
game.balance.history.type.move = Product moved
|
||||||
|
game.balance.history.type.noop = NOOP
|
||||||
|
game.balance.history.type.sell = Product sold
|
||||||
|
game.balance.history.type.store = Product stored
|
||||||
|
game.balance.chart = Balance
|
||||||
|
game.balance.chart.line = Budget
|
||||||
|
game.balance.total-income = Total Income: %d$
|
||||||
|
game.balance.total-loss = Total Loss: %d$
|
||||||
|
|
||||||
quests.normal = Normal
|
quests.normal = Normal
|
||||||
|
|
||||||
products.paper = Paper
|
products.paper = Paper
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
properties = color, format
|
properties = color, format
|
||||||
color.variants =white, green, blue
|
color.variants = white, green, blue
|
||||||
format.variants = a3, a4, a5
|
format.variants = a3, a4, a5
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ properties = type, form
|
|||||||
type.variants = pine, beech, oak
|
type.variants = pine, beech, oak
|
||||||
form.variants = boards, pieces, beams
|
form.variants = boards, pieces, beams
|
||||||
form.beams.depth = 3
|
form.beams.depth = 3
|
||||||
|
type.oak.weight = 1
|
||||||
|
|||||||
Reference in New Issue
Block a user