mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-25 21:40:05 +00:00
List where you are in the palette explorer instead of following you
Biomes are 3D, so the biome at a player's position underground isn't the surface biome above it. The Here tab now lists the region, the surface biome and, when different, the biome at the player's position, each with its layers, followed by the region's other biomes. It updates as the player moves but no longer changes the selection, and biomes without a key no longer crash it. Model used: Claude Opus 5.5
This commit is contained in:
1 parent
252facf41e
commit
76860e94fa
3 files changed
+54
-46
No files matched your search
@@ -54,7 +54,7 @@ record PaletteCatalog(List<RegionEntry> regions, List<String> biomesOutsideRegio
|
|||||||
}
|
}
|
||||||
|
|
||||||
BiomeEntry biome(String key) {
|
BiomeEntry biome(String key) {
|
||||||
return biomes.get(key);
|
return key == null ? null : biomes.get(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
RegionEntry region(String key) {
|
RegionEntry region(String key) {
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import javax.swing.BorderFactory;
|
|||||||
import javax.swing.ButtonGroup;
|
import javax.swing.ButtonGroup;
|
||||||
import javax.swing.DefaultListCellRenderer;
|
import javax.swing.DefaultListCellRenderer;
|
||||||
import javax.swing.DefaultListModel;
|
import javax.swing.DefaultListModel;
|
||||||
import javax.swing.JCheckBox;
|
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
@@ -72,12 +71,11 @@ final class PaletteNavigator extends JPanel {
|
|||||||
private static final String DETAIL_COLOR = "#8890A0";
|
private static final String DETAIL_COLOR = "#8890A0";
|
||||||
|
|
||||||
private final Listener listener;
|
private final Listener listener;
|
||||||
private final boolean followsPlayer;
|
private final boolean showsPlayerLocation;
|
||||||
private final CardLayout cards = new CardLayout();
|
private final CardLayout cards = new CardLayout();
|
||||||
private final JPanel cardPanel = new JPanel(cards);
|
private final JPanel cardPanel = new JPanel(cards);
|
||||||
private final JLabel regionLabel = new JLabel();
|
private final JLabel regionLabel = new JLabel();
|
||||||
private final JLabel biomeLabel = new JLabel();
|
private final JLabel positionLabel = new JLabel();
|
||||||
private final JCheckBox followCheckBox = new JCheckBox("Follow me", true);
|
|
||||||
private final DefaultListModel<HereRow> hereRows = new DefaultListModel<>();
|
private final DefaultListModel<HereRow> hereRows = new DefaultListModel<>();
|
||||||
private final JList<HereRow> hereList = new JList<>(hereRows);
|
private final JList<HereRow> hereList = new JList<>(hereRows);
|
||||||
private final JTextField searchField = new JTextField();
|
private final JTextField searchField = new JTextField();
|
||||||
@@ -90,9 +88,9 @@ final class PaletteNavigator extends JPanel {
|
|||||||
private int selectedLayer;
|
private int selectedLayer;
|
||||||
private boolean updatingSelection;
|
private boolean updatingSelection;
|
||||||
|
|
||||||
PaletteNavigator(boolean followsPlayer, Listener listener) {
|
PaletteNavigator(boolean showsPlayerLocation, Listener listener) {
|
||||||
super(new BorderLayout());
|
super(new BorderLayout());
|
||||||
this.followsPlayer = followsPlayer;
|
this.showsPlayerLocation = showsPlayerLocation;
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
setBackground(SIDEBAR_BACKGROUND);
|
setBackground(SIDEBAR_BACKGROUND);
|
||||||
cardPanel.add(buildHereCard(), HERE_CARD);
|
cardPanel.add(buildHereCard(), HERE_CARD);
|
||||||
@@ -109,13 +107,8 @@ final class PaletteNavigator extends JPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void showLocation(PlayerLocation nextLocation) {
|
void showLocation(PlayerLocation nextLocation) {
|
||||||
String previousBiome = location == null ? null : location.biomeKey();
|
|
||||||
location = nextLocation;
|
location = nextLocation;
|
||||||
refreshHere();
|
refreshHere();
|
||||||
boolean enteredNewBiome = nextLocation.biomeKey() != null && !nextLocation.biomeKey().equals(previousBiome);
|
|
||||||
if (enteredNewBiome && followCheckBox.isSelected()) {
|
|
||||||
chooseBiome(nextLocation.biomeKey(), selectedLayer);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void markSelected(String biomeKey, int layer) {
|
void markSelected(String biomeKey, int layer) {
|
||||||
@@ -139,7 +132,7 @@ final class PaletteNavigator extends JPanel {
|
|||||||
JToggleButton overview = createTab("Overview", OVERVIEW_CARD, group);
|
JToggleButton overview = createTab("Overview", OVERVIEW_CARD, group);
|
||||||
bar.add(here);
|
bar.add(here);
|
||||||
bar.add(overview);
|
bar.add(overview);
|
||||||
(followsPlayer ? here : overview).doClick();
|
(showsPlayerLocation ? here : overview).doClick();
|
||||||
return bar;
|
return bar;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,17 +167,11 @@ final class PaletteNavigator extends JPanel {
|
|||||||
BorderFactory.createMatteBorder(1, 0, 1, 0, BORDER),
|
BorderFactory.createMatteBorder(1, 0, 1, 0, BORDER),
|
||||||
BorderFactory.createEmptyBorder(9, 12, 9, 12)
|
BorderFactory.createEmptyBorder(9, 12, 9, 12)
|
||||||
));
|
));
|
||||||
for (JLabel label : List.of(regionLabel, biomeLabel)) {
|
for (JLabel label : List.of(regionLabel, positionLabel)) {
|
||||||
label.setForeground(PRIMARY_TEXT);
|
label.setForeground(PRIMARY_TEXT);
|
||||||
label.setFont(ITEM_FONT);
|
label.setFont(ITEM_FONT);
|
||||||
location.add(label);
|
location.add(label);
|
||||||
}
|
}
|
||||||
followCheckBox.setOpaque(false);
|
|
||||||
followCheckBox.setForeground(SECONDARY_TEXT);
|
|
||||||
followCheckBox.setFont(ITEM_FONT);
|
|
||||||
followCheckBox.setToolTipText("Open the biome you walk into");
|
|
||||||
followCheckBox.setVisible(followsPlayer);
|
|
||||||
location.add(followCheckBox);
|
|
||||||
|
|
||||||
hereList.setBackground(SIDEBAR_BACKGROUND);
|
hereList.setBackground(SIDEBAR_BACKGROUND);
|
||||||
hereList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
hereList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||||
@@ -267,7 +254,7 @@ final class PaletteNavigator extends JPanel {
|
|||||||
updatingSelection = true;
|
updatingSelection = true;
|
||||||
try {
|
try {
|
||||||
hereRows.clear();
|
hereRows.clear();
|
||||||
if (!followsPlayer) {
|
if (!showsPlayerLocation) {
|
||||||
showHereMessage("Run /iris std pal in-game", "to see where you are standing.");
|
showHereMessage("Run /iris std pal in-game", "to see where you are standing.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -278,7 +265,7 @@ final class PaletteNavigator extends JPanel {
|
|||||||
switch (location.status()) {
|
switch (location.status()) {
|
||||||
case OFFLINE -> showHereMessage("You are offline.", " ");
|
case OFFLINE -> showHereMessage("You are offline.", " ");
|
||||||
case OUTSIDE_IRIS_WORLD -> showHereMessage("You are not in an Iris world.", " ");
|
case OUTSIDE_IRIS_WORLD -> showHereMessage("You are not in an Iris world.", " ");
|
||||||
case IN_BIOME -> showHereRows(location.regionKey(), location.biomeKey());
|
case IN_REGION -> showHereRows(location);
|
||||||
}
|
}
|
||||||
selectInHereList();
|
selectInHereList();
|
||||||
} finally {
|
} finally {
|
||||||
@@ -288,22 +275,16 @@ final class PaletteNavigator extends JPanel {
|
|||||||
|
|
||||||
private void showHereMessage(String firstLine, String secondLine) {
|
private void showHereMessage(String firstLine, String secondLine) {
|
||||||
regionLabel.setText(firstLine);
|
regionLabel.setText(firstLine);
|
||||||
biomeLabel.setText(secondLine);
|
positionLabel.setText(secondLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showHereRows(String regionKey, String biomeKey) {
|
private void showHereRows(PlayerLocation here) {
|
||||||
RegionEntry region = catalog.region(regionKey);
|
RegionEntry region = catalog.region(here.regionKey());
|
||||||
BiomeEntry biome = catalog.biome(biomeKey);
|
regionLabel.setText(labeled("Region", region == null ? here.regionKey() : region.name(), here.regionKey()));
|
||||||
regionLabel.setText(labeled("Region", region == null ? regionKey : region.name(), regionKey));
|
positionLabel.setText(here.isBelowSurfaceBiome() ? "Underground, below the surface biome" : "On the surface");
|
||||||
biomeLabel.setText(labeled("Biome", biome == null ? biomeKey : biome.name(), biomeKey));
|
addBiomeLayers("Surface biome", here.surfaceBiomeKey());
|
||||||
if (biome != null) {
|
if (here.isBelowSurfaceBiome()) {
|
||||||
hereRows.addElement(HereRow.header("Layers here"));
|
addBiomeLayers("Biome at your position", here.biomeAtPositionKey());
|
||||||
for (int layer = 0; layer < biome.layerSummaries().size(); layer++) {
|
|
||||||
hereRows.addElement(new HereRow(layerText(layer, biome), biomeKey, layer, false));
|
|
||||||
}
|
|
||||||
if (biome.layerSummaries().isEmpty()) {
|
|
||||||
hereRows.addElement(HereRow.header("This biome has no palette layers"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (region == null) {
|
if (region == null) {
|
||||||
return;
|
return;
|
||||||
@@ -311,12 +292,25 @@ final class PaletteNavigator extends JPanel {
|
|||||||
hereRows.addElement(HereRow.header("Other biomes in this region"));
|
hereRows.addElement(HereRow.header("Other biomes in this region"));
|
||||||
for (String otherKey : region.allBiomeKeys()) {
|
for (String otherKey : region.allBiomeKeys()) {
|
||||||
BiomeEntry other = catalog.biome(otherKey);
|
BiomeEntry other = catalog.biome(otherKey);
|
||||||
if (!otherKey.equals(biomeKey) && other != null) {
|
boolean shownAbove = otherKey.equals(here.surfaceBiomeKey()) || otherKey.equals(here.biomeAtPositionKey());
|
||||||
|
if (!shownAbove && other != null) {
|
||||||
hereRows.addElement(new HereRow(biomeText(other), otherKey, -1, false));
|
hereRows.addElement(new HereRow(biomeText(other), otherKey, -1, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void addBiomeLayers(String title, String biomeKey) {
|
||||||
|
BiomeEntry biome = catalog.biome(biomeKey);
|
||||||
|
if (biome == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hereRows.addElement(HereRow.header(title));
|
||||||
|
hereRows.addElement(new HereRow(biomeText(biome), biomeKey, -1, false));
|
||||||
|
for (int layer = 0; layer < biome.layerSummaries().size(); layer++) {
|
||||||
|
hereRows.addElement(new HereRow(layerText(layer, biome), biomeKey, layer, false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void rebuildOverview() {
|
private void rebuildOverview() {
|
||||||
if (catalog == null) {
|
if (catalog == null) {
|
||||||
return;
|
return;
|
||||||
@@ -470,6 +464,9 @@ final class PaletteNavigator extends JPanel {
|
|||||||
|
|
||||||
private static final class HereRowRenderer extends DefaultListCellRenderer {
|
private static final class HereRowRenderer extends DefaultListCellRenderer {
|
||||||
private static final long serialVersionUID = 2785341117408251320L;
|
private static final long serialVersionUID = 2785341117408251320L;
|
||||||
|
private static final int HEADER_INDENT = 11;
|
||||||
|
private static final int BIOME_INDENT = 20;
|
||||||
|
private static final int LAYER_INDENT = 34;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean selected, boolean focus) {
|
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean selected, boolean focus) {
|
||||||
@@ -480,7 +477,7 @@ final class PaletteNavigator extends JPanel {
|
|||||||
setFont(row.header() ? HEADER_FONT : ITEM_FONT);
|
setFont(row.header() ? HEADER_FONT : ITEM_FONT);
|
||||||
setForeground(row.header() ? ACCENT : selected ? PRIMARY_TEXT : SECONDARY_TEXT);
|
setForeground(row.header() ? ACCENT : selected ? PRIMARY_TEXT : SECONDARY_TEXT);
|
||||||
setBackground(selected && selectable ? FIELD_BACKGROUND.brighter() : SIDEBAR_BACKGROUND);
|
setBackground(selected && selectable ? FIELD_BACKGROUND.brighter() : SIDEBAR_BACKGROUND);
|
||||||
int indent = row.header() ? 11 : 20;
|
int indent = row.header() ? HEADER_INDENT : row.layer() >= 0 ? LAYER_INDENT : BIOME_INDENT;
|
||||||
setBorder(BorderFactory.createEmptyBorder(row.header() ? 11 : 4, indent, 4, 10));
|
setBorder(BorderFactory.createEmptyBorder(row.header() ? 11 : 4, indent, 4, 10));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,12 +75,18 @@ final class PlayerLocationTracker {
|
|||||||
if (engine == null) {
|
if (engine == null) {
|
||||||
return PlayerLocation.OUTSIDE_IRIS_WORLD;
|
return PlayerLocation.OUTSIDE_IRIS_WORLD;
|
||||||
}
|
}
|
||||||
IrisRegion region = engine.getRegion(player.getLocation());
|
Location position = player.getLocation();
|
||||||
IrisBiome biome = engine.getBiomeOrMantle(player.getLocation());
|
IrisRegion region = engine.getRegion(position);
|
||||||
if (region == null || biome == null) {
|
String surfaceBiome = keyOf(engine.getSurfaceBiome(position.getBlockX(), position.getBlockZ()));
|
||||||
|
String biomeAtPosition = keyOf(engine.getBiomeOrMantle(position));
|
||||||
|
if (region == null || region.getLoadKey() == null || surfaceBiome == null) {
|
||||||
return PlayerLocation.OUTSIDE_IRIS_WORLD;
|
return PlayerLocation.OUTSIDE_IRIS_WORLD;
|
||||||
}
|
}
|
||||||
return new PlayerLocation(Status.IN_BIOME, region.getLoadKey(), biome.getLoadKey());
|
return new PlayerLocation(Status.IN_REGION, region.getLoadKey(), surfaceBiome, biomeAtPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String keyOf(IrisBiome biome) {
|
||||||
|
return biome == null ? null : biome.getLoadKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Engine engineAt(Location location) {
|
private static Engine engineAt(Location location) {
|
||||||
@@ -94,12 +100,17 @@ final class PlayerLocationTracker {
|
|||||||
enum Status {
|
enum Status {
|
||||||
OFFLINE,
|
OFFLINE,
|
||||||
OUTSIDE_IRIS_WORLD,
|
OUTSIDE_IRIS_WORLD,
|
||||||
IN_BIOME
|
IN_REGION
|
||||||
}
|
}
|
||||||
|
|
||||||
record PlayerLocation(Status status, String regionKey, String biomeKey) {
|
// Biomes are 3D: underground, the biome at the player's position can differ from the surface biome above it.
|
||||||
static final PlayerLocation OFFLINE = new PlayerLocation(Status.OFFLINE, null, null);
|
record PlayerLocation(Status status, String regionKey, String surfaceBiomeKey, String biomeAtPositionKey) {
|
||||||
static final PlayerLocation OUTSIDE_IRIS_WORLD = new PlayerLocation(Status.OUTSIDE_IRIS_WORLD, null, null);
|
static final PlayerLocation OFFLINE = new PlayerLocation(Status.OFFLINE, null, null, null);
|
||||||
|
static final PlayerLocation OUTSIDE_IRIS_WORLD = new PlayerLocation(Status.OUTSIDE_IRIS_WORLD, null, null, null);
|
||||||
|
|
||||||
|
boolean isBelowSurfaceBiome() {
|
||||||
|
return biomeAtPositionKey != null && !biomeAtPositionKey.equals(surfaceBiomeKey);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Listener {
|
interface Listener {
|
||||||
|
|||||||
Reference in new issue
Block a user