start on presets gui page

This commit is contained in:
dags- 2020-06-21 22:37:56 +01:00
parent a6da0f155e
commit fad240c246
12 changed files with 449 additions and 54 deletions

View File

@ -44,7 +44,7 @@ public class SettingsHelper {
}
}
public static void applyDefaults(CompoundNBT options, TerraSettings dest) {
public static CompoundNBT applyDefaults(CompoundNBT options, TerraSettings dest) {
if (options.isEmpty()) {
try (Reader reader = new BufferedReader(new FileReader(SETTINGS_FILE))) {
JsonElement json = new JsonParser().parse(reader);
@ -54,6 +54,7 @@ public class SettingsHelper {
}
}
NBTHelper.deserialize(options, dest);
return options;
}
public static TerraSettings getSettings(WorldInfo info) {

View File

@ -0,0 +1,55 @@
package com.terraforged.chunk.settings.preset;
import com.terraforged.chunk.settings.TerraSettings;
import java.io.File;
public class Preset implements Comparable<Preset> {
private final boolean changed;
private final File file;
private final String id;
private final String name;
private final TerraSettings settings;
Preset(String name, File file, TerraSettings settings) {
this.name = name;
this.file = file;
this.changed = false;
this.settings = settings;
this.id = name.toLowerCase();
}
public Preset(String name, TerraSettings settings) {
this.name = name;
this.changed = true;
this.settings = settings;
this.id = name.toLowerCase();
this.file = new File(PresetManager.PRESETS_DIR, name + ".json");
}
public boolean changed() {
return changed;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public File getFile() {
return file;
}
public TerraSettings getSettings() {
return settings;
}
@Override
public int compareTo(Preset o) {
return id.compareTo(o.id);
}
}

View File

@ -0,0 +1,143 @@
package com.terraforged.chunk.settings.preset;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.terraforged.Log;
import com.terraforged.chunk.settings.SettingsHelper;
import com.terraforged.chunk.settings.TerraSettings;
import com.terraforged.util.nbt.NBTHelper;
import net.minecraft.nbt.CompoundNBT;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
public class PresetManager implements Iterable<Preset> {
public static final File PRESETS_DIR = new File(SettingsHelper.SETTINGS_DIR, "presets");
private final List<Preset> presets;
private final List<Preset> deleted = new ArrayList<>();
private PresetManager(List<Preset> presets) {
this.presets = presets;
}
public Optional<Preset> get(String name) {
for (Preset preset : presets) {
if (preset.getName().equalsIgnoreCase(name)) {
return Optional.of(preset);
}
}
return Optional.empty();
}
public void add(Preset preset) {
// replace a preset by the same name
for (int i = 0; i < presets.size(); i++) {
if (presets.get(i).getId().equalsIgnoreCase(preset.getId())) {
presets.set(i, preset);
return;
}
}
// otherwise add to end of list
presets.add(preset);
Collections.sort(presets);
}
public void remove(String name) {
get(name).ifPresent(preset -> {
presets.remove(preset);
deleted.add(preset);
});
}
public void saveAll() {
if (!ensureDir()) {
Log.err("Unable to save presets to disk");
return;
}
for (Preset preset : deleted) {
if (preset.getFile().exists() && preset.getFile().delete()) {
Log.debug("Deleted preset: {}", preset.getName());
} else {
Log.debug("Unable to delete file: {}", preset.getFile());
}
}
Log.info("Saving presets");
Gson gson = new GsonBuilder().disableHtmlEscaping().setPrettyPrinting().create();
for (Preset preset : presets) {
if (!preset.changed()) {
continue;
}
Log.debug("Saving preset: {}", preset.getName());
CompoundNBT nbt = NBTHelper.serializeCompact(preset.getSettings());
JsonElement json = NBTHelper.toJson(nbt);
try (Writer writer = new BufferedWriter(new FileWriter(preset.getFile()))) {
gson.toJson(json, writer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public Iterator<Preset> iterator() {
return presets.iterator();
}
private static boolean ensureDir() {
if (!PRESETS_DIR.exists() && !PRESETS_DIR.mkdirs()) {
Log.err("Unable to create presets directory: {}", PRESETS_DIR);
return false;
}
return true;
}
public static PresetManager load() {
if (!ensureDir()) {
return new PresetManager(new ArrayList<>());
}
File[] files = PRESETS_DIR.listFiles();
if (files == null || files.length == 0) {
return new PresetManager(new ArrayList<>());
}
List<Preset> presets = new ArrayList<>(files.length);
for (File file : files) {
if (!file.getName().endsWith(".json")) {
continue;
}
String name = file.getName().substring(0, file.getName().length() - 5);
try (Reader reader = new BufferedReader(new FileReader(file))) {
JsonElement data = new JsonParser().parse(reader);
CompoundNBT nbt = NBTHelper.fromJson(data);
TerraSettings settings = new TerraSettings();
NBTHelper.deserialize(nbt, settings);
presets.add(new Preset(name, file, settings));
} catch (IOException e) {
e.printStackTrace();
}
}
return new PresetManager(presets);
}
}

View File

@ -0,0 +1,20 @@
package com.terraforged.gui;
import com.terraforged.chunk.settings.TerraSettings;
import com.terraforged.util.nbt.NBTHelper;
import net.minecraft.nbt.CompoundNBT;
public class Instance {
public TerraSettings settings = new TerraSettings();
public CompoundNBT settingsData = new CompoundNBT();
public Instance(TerraSettings settings) {
sync(settings);
}
public void sync(TerraSettings settings) {
this.settings = settings;
this.settingsData = NBTHelper.serialize(settings);
}
}

View File

@ -33,8 +33,10 @@ import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.Widget;
import net.minecraft.client.gui.widget.list.AbstractOptionList;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
public class ScrollPane extends AbstractOptionList<ScrollPane.Entry> implements OverlayRenderer {
@ -42,6 +44,7 @@ public class ScrollPane extends AbstractOptionList<ScrollPane.Entry> implements
public ScrollPane(int slotHeightIn) {
super(Minecraft.getInstance(), 0, 0, 0, 0, slotHeightIn);
setRenderSelection(false);
}
public void addButton(Widget button) {
@ -82,6 +85,11 @@ public class ScrollPane extends AbstractOptionList<ScrollPane.Entry> implements
return hovered && super.mouseScrolled(x, y, direction);
}
@Override
protected boolean isSelectedItem(int index) {
return renderSelection && Objects.equals(getSelected(), children().get(index));
}
public class Entry extends AbstractOptionList.Entry<Entry> {
public final Widget option;
@ -90,6 +98,12 @@ public class ScrollPane extends AbstractOptionList<ScrollPane.Entry> implements
this.option = option;
}
@Nullable
@Override
public IGuiEventListener getFocused() {
return option;
}
@Override
public List<? extends IGuiEventListener> children() {
return Collections.singletonList(option);
@ -97,16 +111,21 @@ public class ScrollPane extends AbstractOptionList<ScrollPane.Entry> implements
@Override
public boolean mouseClicked(double x, double y, int button) {
// super.mouseClicked(x, y, button);
if (isMouseOver(x, y)) {
setSelected(this);
}
return option.mouseClicked(x, y, button);
}
@Override
public boolean mouseReleased(double x, double y, int button) {
// super.mouseReleased(x, y, button);
return option.mouseReleased(x, y, button);
}
@Override
public void render(int index, int top, int left, int width, int height, int mouseX, int mouseY, boolean wut, float partialTicks) {
public void render(int index, int top, int left, int width, int height, int mouseX, int mouseY, boolean hovered, float partialTicks) {
int optionWidth = Math.min(396, width);
int padding = (width - optionWidth) / 2;
option.x = left + padding;

View File

@ -33,8 +33,7 @@ import com.terraforged.gui.page.PresetsPage;
import com.terraforged.gui.page.SimplePage;
import com.terraforged.gui.page.SimplePreviewPage;
import com.terraforged.gui.page.WorldPage;
import com.terraforged.gui.preview2.PreviewPage;
import com.terraforged.util.nbt.NBTHelper;
import com.terraforged.gui.preview.PreviewPage;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.IGuiEventListener;
import net.minecraft.client.gui.screen.CreateWorldScreen;
@ -50,28 +49,35 @@ public class SettingsScreen extends OverlayScreen {
private final Page[] pages;
private final PreviewPage preview;
private final CreateWorldScreen parent;
private final TerraSettings settings = new TerraSettings();
private final Instance instance;
private int pageIndex = 0;
public SettingsScreen(CreateWorldScreen parent) {
TerraSettings settings = new TerraSettings();
SettingsHelper.applyDefaults(parent.chunkProviderSettingsJson, settings);
this.parent = parent;
this.preview = new PreviewPage(settings, getSeed(parent));
this.instance = new Instance(settings);
this.preview = new PreviewPage(instance.settings, getSeed(parent));
this.pages = new Page[]{
new PresetsPage(),
new WorldPage(settings, preview),
new SimplePreviewPage("Climate Settings", "climate", preview, settings, s -> s.climate),
new SimplePreviewPage("Terrain Settings", "terrain", preview, settings, s -> s.terrain),
new SimplePreviewPage("River Settings", "rivers", preview, settings, s -> s.rivers),
new SimplePreviewPage("Filter Settings", "filters", preview, settings, s -> s.filters),
new SimplePage("Structure Settings", "structures", settings, s -> s.structures),
new SimplePage("Feature Settings", "features", settings, s -> s.features)
new PresetsPage(instance, preview),
new WorldPage(instance, preview),
new SimplePreviewPage("Climate Settings", "climate", preview, instance, s -> s.climate),
new SimplePreviewPage("Terrain Settings", "terrain", preview, instance, s -> s.terrain),
new SimplePreviewPage("River Settings", "rivers", preview, instance, s -> s.rivers),
new SimplePreviewPage("Filter Settings", "filters", preview, instance, s -> s.filters),
new SimplePage("Structure Settings", "structures", instance, s -> s.structures),
new SimplePage("Feature Settings", "features", instance, s -> s.features)
};
}
private boolean isPresetsPage() {
return pages[pageIndex] instanceof PresetsPage;
}
@Override
protected void init() {
public void init() {
super.buttons.clear();
super.children.clear();
@ -98,20 +104,18 @@ public class SettingsScreen extends OverlayScreen {
}
// -52
addButton(new Button(buttonsCenter - buttonWidth - buttonPad, buttonsRow, buttonWidth, buttonHeight, "Cancel"
, b -> onClose()));
addButton(new Button(buttonsCenter - buttonWidth - buttonPad, buttonsRow, buttonWidth, buttonHeight, "Cancel", b -> onClose()));
// +2
addButton(new Button(buttonsCenter + buttonPad, buttonsRow, buttonWidth, buttonHeight, "Done", b -> {
for (Page page : pages) {
page.save();
}
parent.chunkProviderSettingsJson = NBTHelper.serializeCompact(settings);
// parent.chunkProviderSettingsJson = NBTHelper.serializeCompact(settings);
SettingsScreen.setSeed(parent, preview.getSeed());
onClose();
}));
// -106
addButton(new Button(buttonsCenter - (buttonWidth * 2 + (buttonPad * 3)), buttonsRow, buttonWidth, buttonHeight, "<<", NO_ACTION) {
@Override
@ -155,7 +159,9 @@ public class SettingsScreen extends OverlayScreen {
public void render(int mouseX, int mouseY, float partialTicks) {
super.renderBackground();
pages[pageIndex].visit(pane -> pane.render(mouseX, mouseY, partialTicks));
if (pageIndex > 0) {
preview.visit(pane -> pane.render(mouseX, mouseY, partialTicks));
}
super.render(mouseX, mouseY, partialTicks);
}
@ -163,29 +169,31 @@ public class SettingsScreen extends OverlayScreen {
public void renderOverlays(Screen screen, int mouseX, int mouseY) {
super.renderOverlays(screen, mouseX, mouseY);
pages[pageIndex].visit(pane -> pane.renderOverlays(screen, mouseX, mouseY));
if (!isPresetsPage()) {
preview.visit(pane -> pane.renderOverlays(screen, mouseX, mouseY));
}
}
@Override
public boolean mouseClicked(double x, double y, int button) {
boolean a = pages[pageIndex].action(pane -> pane.mouseClicked(x, y, button));
boolean b = preview.action(pane -> pane.mouseClicked(x, y, button));
boolean b = isPresetsPage() || preview.action(pane -> pane.mouseClicked(x, y, button));;
boolean c = super.mouseClicked(x, y, button);
return a || b || c;
return a || b || c || true;
}
@Override
public boolean mouseReleased(double x, double y, int button) {
boolean a = pages[pageIndex].action(pane -> pane.mouseReleased(x, y, button));
boolean b = preview.action(pane -> pane.mouseReleased(x, y, button));
boolean b = isPresetsPage() || preview.action(pane -> pane.mouseReleased(x, y, button));
boolean c = super.mouseReleased(x, y, button);
return a || b || c;
return a || b || c || true;
}
@Override
public boolean mouseDragged(double x, double y, int button, double dx, double dy) {
boolean a = pages[pageIndex].action(pane -> pane.mouseDragged(x, y, button, dx, dy));
boolean b = preview.action(pane -> pane.mouseDragged(x, y, button, dx, dy));
boolean b = isPresetsPage() || preview.action(pane -> pane.mouseDragged(x, y, button, dx, dy));
boolean c = super.mouseDragged(x, y, button, dx, dy);
return a || b || c;
}
@ -193,7 +201,7 @@ public class SettingsScreen extends OverlayScreen {
@Override
public boolean mouseScrolled(double x, double y, double direction) {
boolean a = pages[pageIndex].action(pane -> pane.mouseScrolled(x, y, direction));
boolean b = preview.action(pane -> pane.mouseScrolled(x, y, direction));
boolean b = isPresetsPage() || preview.action(pane -> pane.mouseScrolled(x, y, direction));
boolean c = super.mouseScrolled(x, y, direction);
return a || b || c;
}
@ -201,11 +209,19 @@ public class SettingsScreen extends OverlayScreen {
@Override
public boolean keyPressed(int i, int j, int k) {
boolean a = pages[pageIndex].action(pane -> pane.keyPressed(i, j, k));
boolean b = preview.action(pane -> pane.keyPressed(i, j, k));
boolean b = isPresetsPage() || preview.action(pane -> pane.keyPressed(i, j, k));
boolean c = super.keyPressed(i, j, k);
return a || b || c;
}
@Override
public boolean charTyped(char ch, int code) {
boolean a = pages[pageIndex].action(pane -> pane.charTyped(ch, code));
boolean b = isPresetsPage() || preview.action(pane -> pane.charTyped(ch, code));
boolean c = super.charTyped(ch, code);
return a || b || c;
}
@Override
public void onClose() {
for (Page page : pages) {

View File

@ -24,6 +24,11 @@ public class TerraTextInput extends TextFieldWidget implements Element, Consumer
this.tooltip = Element.getToolTip(name, value);
setText(value.getString(name));
setResponder(this);
setEnabled(true);
}
public String getValue() {
return value.getString(name);
}
public void setColorValidator(Predicate<String> validator) {
@ -49,6 +54,7 @@ public class TerraTextInput extends TextFieldWidget implements Element, Consumer
public void accept(String text) {
value.put(name, StringNBT.valueOf(text));
callback.accept(this);
if (validator.test(text)) {
setTextColor(14737632);
} else {

View File

@ -1,21 +1,136 @@
package com.terraforged.gui.page;
import com.terraforged.chunk.settings.TerraSettings;
import com.terraforged.chunk.settings.preset.Preset;
import com.terraforged.chunk.settings.preset.PresetManager;
import com.terraforged.gui.Instance;
import com.terraforged.gui.OverlayScreen;
import com.terraforged.gui.ScrollPane;
import com.terraforged.gui.element.TerraButton;
import com.terraforged.gui.element.TerraLabel;
import com.terraforged.gui.element.TerraTextInput;
import com.terraforged.util.nbt.NBTHelper;
import net.minecraft.nbt.CompoundNBT;
import java.util.Optional;
public class PresetsPage extends BasePage {
private final UpdatablePage preview;
private final TerraTextInput nameInput;
private final Instance instance;
private final PresetManager manager = PresetManager.load();
public PresetsPage(Instance instance, UpdatablePage preview) {
CompoundNBT value = new CompoundNBT();
value.putString("name", "");
this.preview = preview;
this.instance = instance;
this.nameInput = new TerraTextInput("name", value);
}
@Override
public String getTitle() {
return "Presets & Defaults";
}
@Override
public void close() {
manager.saveAll();
}
@Override
public void save() {
}
protected void update() {
preview.apply(settings -> NBTHelper.deserialize(instance.settingsData, settings));
}
@Override
public void init(OverlayScreen parent) {
rebuildPresetList();
Column right = getColumn(1);
right.scrollPane.addButton(nameInput);
right.scrollPane.addButton(new TerraButton("Create") {
@Override
public void onClick(double x, double y) {
super.onClick(x, y);
// create new preset with default settings
Preset preset = new Preset(nameInput.getValue(), new TerraSettings());
// register with the manager & reset the text field
manager.add(preset);
nameInput.setText("");
// update the ui
rebuildPresetList();
}
});
right.scrollPane.addButton(new TerraButton("Load") {
@Override
public void onClick(double x, double y) {
super.onClick(x, y);
getSelected().ifPresent(preset -> load(preset));
}
});
right.scrollPane.addButton(new TerraButton("Save") {
@Override
public void onClick(double x, double y) {
super.onClick(x, y);
getSelected().ifPresent(preset -> {
// create a copy of the settings
TerraSettings settings = new TerraSettings();
NBTHelper.deserialize(instance.settingsData, settings);
// replace the current preset with the updated version
manager.add(new Preset(preset.getName(), settings));
// update the ui
rebuildPresetList();
});
}
});
right.scrollPane.addButton(new TerraButton("Delete") {
@Override
public void onClick(double x, double y) {
super.onClick(x, y);
getSelected().ifPresent(preset -> {
// remove & update the ui
manager.remove(preset.getName());
rebuildPresetList();
});
}
});
}
private void load(Preset preset) {
instance.sync(preset.getSettings());
update();
}
private Optional<Preset> getSelected() {
ScrollPane.Entry entry = getColumn(0).scrollPane.getSelected();
if (entry == null) {
return Optional.empty();
}
return manager.get(entry.option.getMessage());
}
private void rebuildPresetList() {
Column left = getColumn(0);
left.scrollPane.setRenderSelection(true);
left.scrollPane.children().clear();
for (Preset preset : manager) {
left.scrollPane.addButton(new TerraLabel(preset.getName()));
}
}
}

View File

@ -1,8 +1,8 @@
package com.terraforged.gui.page;
import com.terraforged.chunk.settings.TerraSettings;
import com.terraforged.gui.Instance;
import com.terraforged.gui.OverlayScreen;
import com.terraforged.util.nbt.NBTHelper;
import net.minecraft.nbt.CompoundNBT;
import java.util.function.Function;
@ -10,15 +10,17 @@ import java.util.function.Function;
public class SimplePage extends BasePage {
private final String title;
protected final TerraSettings settings;
protected final CompoundNBT sectionSettings;
private final String sectionName;
protected final Instance instance;
protected final Function<TerraSettings, Object> section;
public SimplePage(String title, String sectionName, TerraSettings settings, Function<TerraSettings, Object> section) {
protected CompoundNBT sectionSettings = null;
public SimplePage(String title, String sectionName, Instance instance, Function<TerraSettings, Object> section) {
this.title = title;
this.section = section;
this.settings = settings;
this.sectionSettings = NBTHelper.serialize(sectionName, section.apply(settings));
this.sectionName = sectionName;
this.instance = instance;
}
@Override
@ -28,11 +30,12 @@ public class SimplePage extends BasePage {
@Override
public void save() {
NBTHelper.deserialize(sectionSettings, section);
}
@Override
public void init(OverlayScreen parent) {
sectionSettings = getSectionSettings();
Column left = getColumn(0);
addElements(left.left, left.top, left, sectionSettings, true, left.scrollPane::addButton, this::update);
}
@ -41,4 +44,8 @@ public class SimplePage extends BasePage {
protected void update() {
super.update();
}
private CompoundNBT getSectionSettings() {
return instance.settingsData.getCompound(sectionName);
}
}

View File

@ -1,6 +1,7 @@
package com.terraforged.gui.page;
import com.terraforged.chunk.settings.TerraSettings;
import com.terraforged.gui.Instance;
import com.terraforged.util.nbt.NBTHelper;
import java.util.function.Function;
@ -9,8 +10,8 @@ public class SimplePreviewPage extends SimplePage {
private final UpdatablePage preview;
public SimplePreviewPage(String title, String sectionName, UpdatablePage preview, TerraSettings settings, Function<TerraSettings, Object> section) {
super(title, sectionName, settings, section);
public SimplePreviewPage(String title, String sectionName, UpdatablePage preview, Instance instance, Function<TerraSettings, Object> section) {
super(title, sectionName, instance, section);
this.preview = preview;
}

View File

@ -26,7 +26,7 @@
package com.terraforged.gui.page;
import com.terraforged.TerraWorld;
import com.terraforged.chunk.settings.TerraSettings;
import com.terraforged.gui.Instance;
import com.terraforged.gui.OverlayScreen;
import com.terraforged.gui.element.TerraTextInput;
import com.terraforged.util.nbt.NBTHelper;
@ -40,22 +40,15 @@ import net.minecraftforge.registries.ForgeRegistries;
public class WorldPage extends BasePage {
private final TerraSettings settings;
private final UpdatablePage preview;
private final CompoundNBT worldSettings;
private final CompoundNBT dimSettings;
private final Instance instance;
public WorldPage(TerraSettings settings, UpdatablePage preview) {
this.settings = settings;
private CompoundNBT worldSettings = null;
private CompoundNBT dimSettings = null;
public WorldPage(Instance instance, UpdatablePage preview) {
this.instance = instance;
this.preview = preview;
this.worldSettings = NBTHelper.serialize("world", settings.world);
this.dimSettings = NBTHelper.serialize("dimensions", settings.dimensions);
CompoundNBT generators = dimSettings.getCompound("dimensions").getCompound("value");
for (String name : generators.keySet()) {
CompoundNBT setting = generators.getCompound(name);
setting.put("#options", getWorldTypes());
}
}
@Override
@ -65,12 +58,15 @@ public class WorldPage extends BasePage {
@Override
public void save() {
NBTHelper.deserialize(worldSettings, settings.world);
NBTHelper.deserialize(dimSettings, settings.dimensions);
}
@Override
public void init(OverlayScreen parent) {
// re-sync settings from the settings object to the data structure
worldSettings = getWorldSettings();
dimSettings = getDimSettings();
Column left = getColumn(0);
addElements(left.left, left.top, left, worldSettings, true, left.scrollPane::addButton, this::update);
addElements(left.left, left.top, left, dimSettings, true, left.scrollPane::addButton, this::update);
@ -92,6 +88,22 @@ public class WorldPage extends BasePage {
});
}
private CompoundNBT getWorldSettings() {
return instance.settingsData.getCompound("world");
}
private CompoundNBT getDimSettings() {
CompoundNBT dimSettings = instance.settingsData.getCompound("dimensions");
CompoundNBT generators = dimSettings.getCompound("dimensions").getCompound("value");
for (String name : generators.keySet()) {
CompoundNBT setting = generators.getCompound(name);
setting.put("#options", getWorldTypes());
}
return dimSettings;
}
private static ListNBT getWorldTypes() {
ListNBT options = new ListNBT();
for (WorldType type : WorldType.WORLD_TYPES) {