load cloud images

This commit is contained in:
Halbear
2026-08-05 19:28:01 +01:00
parent 2b706b0687
commit 157960f663
4 changed files with 184 additions and 53 deletions
+23 -31
View File
@@ -255,24 +255,30 @@ public class Config {
} }
} }
public List<Identifier> GetAndLoadAllCloudFiles(){ public List<Identifier> GetAndLoadAllCloudFiles() {
Path ResourcesDir = FMLPaths.GAMEDIR.get().resolve(ResourceFolderName); Path ResourcesDir = FMLPaths.GAMEDIR.get().resolve(ResourceFolderName);
Path Clouds = ResourcesDir.resolve(CloudsFolderName); Path Clouds = ResourcesDir.resolve(CloudsFolderName);
List<Identifier> CloudFiles = new ArrayList<>(); List<Identifier> CloudFiles = new ArrayList<>();
try (Stream<Path> stream = Files.walk(Clouds)) { try (Stream<Path> stream = Files.walk(Clouds)) {
List<Path> files = stream List<Path> files = stream
.filter(Files::isRegularFile) .filter(Files::isRegularFile)
.collect(Collectors.toList()); .toList();
files.forEach(cloudfile->{ files.forEach(cloudfile -> {
if(cloudfile.endsWith(".png")) { SkyboxMod.LOGGER.debug("FILE: " + cloudfile.toString());
File texture = cloudfile.toFile(); File texture = cloudfile.toFile();
Identifier loadedTexture = registerExternalTexture(texture); Identifier loadedTexture = registerExternalTexture(texture);
CloudFiles.add(loadedTexture); CloudFiles.add(loadedTexture);
}
}); });
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); SkyboxMod.LOGGER.error("failed to open cloud path: ", e);
}
if (RESOURCE_LOCATION.get() == ResourceLocations.IDENTIFIERS){
List<? extends String> paths = CLOUD_PATHS.get();
paths.forEach(path->{
if(!Identifier.isValidPath(path)) CloudFiles.add(Identifier.fromNamespaceAndPath(SkyboxMod.MODID, "textures/correct_regex.png"));
else CloudFiles.add(Identifier.parse(path));
});
} }
return CloudFiles; return CloudFiles;
} }
@@ -290,7 +296,8 @@ public class Config {
}); });
} else{ } else{
paths.forEach(path->{ paths.forEach(path->{
loadedAssets.add(Identifier.parse(path)); if(!Identifier.isValidPath(path)) loadedAssets.add(Identifier.fromNamespaceAndPath(SkyboxMod.MODID, "textures/correct_regex.png"));
else loadedAssets.add(Identifier.parse(path));
}); });
} }
return loadedAssets; return loadedAssets;
@@ -301,7 +308,11 @@ public class Config {
public static Identifier registerExternalTexture(File imageFile) { public static Identifier registerExternalTexture(File imageFile) {
if(LoadedTextureMap.containsKey( imageFile)) return LoadedTextureMap.get(imageFile); if(LoadedTextureMap.containsKey( imageFile)) return LoadedTextureMap.get(imageFile);
Identifier location = Identifier.fromNamespaceAndPath(SkyboxMod.MODID, "external_textures/loaded_texture_" + loadedTexture); String path = "external_textures/"+loadedTexture+"loaded_texture_" + imageFile.getPath().split(CloudsFolderName)[1].substring(1).toLowerCase().replace(' ','-');
if(!Identifier.isValidPath(path)) {
return Identifier.fromNamespaceAndPath(SkyboxMod.MODID, "textures/correct_regex.png");
}
Identifier location = Identifier.fromNamespaceAndPath(SkyboxMod.MODID,path );
try (InputStream stream = new FileInputStream(imageFile)) { try (InputStream stream = new FileInputStream(imageFile)) {
NativeImage nativeImage = NativeImage.read(stream); NativeImage nativeImage = NativeImage.read(stream);
@@ -317,19 +328,6 @@ public class Config {
} }
} }
public File getAssetAsFile(Identifier location) throws IOException {
var resourceManager = Minecraft.getInstance().getResourceManager();
var resource = resourceManager.getResource(location)
.orElseThrow(() -> new FileNotFoundException("Asset not found: " + location));
try (InputStream stream = resource.open()) {
File tempFile = File.createTempFile("asset_", "_" + location.getPath().replace("/", "_"));
tempFile.deleteOnExit();
Files.copy(stream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
return tempFile;
}
}
private static final ModConfigSpec.Builder BUILDER = new ModConfigSpec.Builder(); private static final ModConfigSpec.Builder BUILDER = new ModConfigSpec.Builder();
@@ -411,13 +409,7 @@ public class Config {
static final ModConfigSpec SPEC = BUILDER.build(); static final ModConfigSpec SPEC = BUILDER.build();
private static boolean ValidateCloudPath(final Object obj) { private static boolean ValidateCloudPath(final Object obj) {
return obj instanceof String itemName && Identifier.isValidPath(itemName); return obj instanceof String itemName;
} }
public static final ModConfigSpec.ConfigValue<List<? extends String>> ITEM_STRINGS = BUILDER
.comment("A list of items to log on common setup.")
.defineListAllowEmpty("items", List.of("minecraft:iron_ingot"), () -> "", Config::validateItemName);
private static boolean validateItemName(final Object obj) {
return obj instanceof String itemName && BuiltInRegistries.ITEM.containsKey(Identifier.parse(itemName));
}
} }
@@ -42,7 +42,6 @@ public class ConfigScreen extends OptionsSubScreen {
this.list.addBig(Config.Instance.CloudCount()); this.list.addBig(Config.Instance.CloudCount());
this.list.addSmall(CloudOptions(this.options)); this.list.addSmall(CloudOptions(this.options));
this.list.addBig(Config.Instance.OpenCloudSprites()); this.list.addBig(Config.Instance.OpenCloudSprites());
this.list.addBig(Config.Instance.OpenCloudImageButton());
} }
@@ -1,11 +1,14 @@
package net.halbear.skyboxmod.rendering.screen; package net.halbear.skyboxmod.rendering.screen;
import net.halbear.skyboxmod.Config;
import net.halbear.skyboxmod.SkyboxMod; import net.halbear.skyboxmod.SkyboxMod;
import net.halbear.skyboxmod.rendering.skybox.DistantSkyObject;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphicsExtractor; import net.minecraft.client.gui.GuiGraphicsExtractor;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.ObjectSelectionList; import net.minecraft.client.gui.components.ObjectSelectionList;
import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.components.toasts.SystemToast;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.packs.TransferableSelectionList; import net.minecraft.client.gui.screens.packs.TransferableSelectionList;
import net.minecraft.client.input.MouseButtonEvent; import net.minecraft.client.input.MouseButtonEvent;
@@ -14,23 +17,31 @@ import net.minecraft.resources.Identifier;
import net.minecraft.util.Util; import net.minecraft.util.Util;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
import net.neoforged.fml.loading.FMLPaths;
import net.neoforged.neoforge.client.event.ContainerScreenEvent; import net.neoforged.neoforge.client.event.ContainerScreenEvent;
import net.neoforged.neoforge.client.event.ScreenEvent; import net.neoforged.neoforge.client.event.ScreenEvent;
import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.common.NeoForge;
import org.jspecify.annotations.NonNull; import org.jspecify.annotations.NonNull;
import java.io.File; import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import static net.halbear.skyboxmod.Config.CloudsFolderName;
import static net.halbear.skyboxmod.Config.ResourceFolderName;
public class SelectionScreen extends Screen { public class SelectionScreen extends Screen {
private final Screen lastScreen; private final Screen lastScreen;
private final File targetDirectory; private final File targetDirectory;
private final List<String> availableItems = new ArrayList<>(List.of("Test1", "Test2", "Test3", "Test4")); private final LinkedHashSet<Identifier> AllItemsLoaded = new LinkedHashSet<>();
private final List<String> selectedItems = new ArrayList<>(List.of("Test5")); private final LinkedHashSet<Identifier> availableItems = new LinkedHashSet<>();
private final LinkedHashSet<Identifier> selectedItems = new LinkedHashSet<>();
private final ConcurrentLinkedQueue<Button> transferButtons = new ConcurrentLinkedQueue<Button>(); private final ConcurrentLinkedQueue<Button> transferButtons = new ConcurrentLinkedQueue<Button>();
@@ -39,9 +50,33 @@ public class SelectionScreen extends Screen {
public SelectionScreen(Screen lastScreen, File targetDirectory) { public SelectionScreen(Screen lastScreen, File targetDirectory) {
super(Component.literal("Select Custom Options")); super(Component.literal("Cloud Asset Manager"));
this.lastScreen = lastScreen; this.lastScreen = lastScreen;
this.targetDirectory = targetDirectory; this.targetDirectory = targetDirectory;
}
@Override
public void onFilesDrop(java.util.List<java.nio.file.Path> files) {
for (java.nio.file.Path file : files) {
try {
java.nio.file.Files.copy(
file,
this.targetDirectory.toPath().resolve(file.getFileName().toString().toLowerCase().replace(' ','-')),
java.nio.file.StandardCopyOption.REPLACE_EXISTING
);
} catch (Exception e) {
this.minecraft.getToastManager().addToast(SystemToast.multiline(
this.minecraft,
SystemToast.SystemToastId.PACK_COPY_FAILURE,
Component.literal("Error processing choice file"),
Component.literal(e.getMessage())
));
}
}
this.refreshLoadedContent();
this.refreshListData();
this.rebuildWidgets();
} }
@Override @Override
@@ -50,13 +85,25 @@ public class SelectionScreen extends Screen {
int listWidth = 170; int listWidth = 170;
int listHeight = this.height - 80; int listHeight = this.height - 80;
this.leftList = new SelectionPanelList(this.minecraft, listWidth, listHeight,40,24 ); this.leftList = new SelectionPanelList(this.minecraft, listWidth, listHeight,48,64,this );
this.leftList.setX(this.width / 2 - 180); this.leftList.setX(this.width / 2 - 180);
this.rightList = new SelectionPanelList(this.minecraft, listWidth, listHeight,40,24); this.rightList = new SelectionPanelList(this.minecraft, listWidth, listHeight,48,64,this);
this.rightList.setX(this.width / 2 + 10); this.rightList.setX(this.width / 2 + 10);
AllItemsLoaded.clear();
selectedItems.clear();
availableItems.clear();
AllItemsLoaded.addAll(Config.Instance.GetAndLoadAllCloudFiles());
selectedItems.addAll(Config.Instance.GetAllClouds());
AllItemsLoaded.forEach(item->{
SkyboxMod.LOGGER.debug(item.getPath());
if(!selectedItems.contains(item)){
availableItems.add(item);
}
});
refreshListData(); refreshListData();
this.addRenderableWidget(this.leftList); this.addRenderableWidget(this.leftList);
@@ -65,7 +112,37 @@ public class SelectionScreen extends Screen {
this.addRenderableWidget(Button.builder( this.addRenderableWidget(Button.builder(
Component.literal("Done"), Component.literal("Done"),
button -> this.onClose() button -> this.onClose()
).bounds(this.width / 2 - 75, this.height - 32, 150, 20).build()); ).bounds(this.rightList.getX(), rightList.getY() + rightList.getHeight() + 4, this.rightList.getWidth(), 20 ).build());
this.addRenderableWidget(Button.builder(Component.literal("Open Folder"),
button -> {
Path ResourcesDir = FMLPaths.GAMEDIR.get().resolve(ResourceFolderName);
Path Clouds = ResourcesDir.resolve(CloudsFolderName);
if(!Files.isDirectory(Clouds)) {
try {
Files.createDirectories(Clouds);
} catch (Exception e) {
SkyboxMod.LOGGER.error("Failed to create Clouds directory", e);
return;
}
}
Util.getPlatform().openFile(Clouds.toFile());
}).bounds(this.leftList.getX(), leftList.getY() + leftList.getHeight() + 4, this.leftList.getWidth(), 20 ).build());
}
private void refreshLoadedContent(){
AllItemsLoaded.clear();
selectedItems.clear();
availableItems.clear();
AllItemsLoaded.addAll(Config.Instance.GetAndLoadAllCloudFiles());
selectedItems.addAll(Config.Instance.GetAllClouds());
AllItemsLoaded.forEach(item->{
SkyboxMod.LOGGER.debug(item.getPath());
if(!selectedItems.contains(item)){
availableItems.add(item);
}
});
} }
private void refreshListData() { private void refreshListData() {
@@ -78,10 +155,10 @@ public class SelectionScreen extends Screen {
this.leftList.clearEntries(); this.leftList.clearEntries();
this.rightList.clearEntries(); this.rightList.clearEntries();
for (String item : availableItems) { for (Identifier item : availableItems) {
this.leftList.AddEntry(new TextRowEntry(item, true,this)); this.leftList.AddEntry(new TextRowEntry(item, true,this));
} }
for (String item : selectedItems) { for (Identifier item : selectedItems) {
this.rightList.AddEntry(new TextRowEntry(item, false,this)); this.rightList.AddEntry(new TextRowEntry(item, false,this));
} }
} }
@@ -92,11 +169,9 @@ public class SelectionScreen extends Screen {
guiGraphics.pose().pushMatrix(); guiGraphics.pose().pushMatrix();
guiGraphics.text(this.font, this.title, this.width / 2 - this.font.width(this.title)/2, 8, 0xFFFFFFFF,true); guiGraphics.text(this.font, this.title, this.width / 2 - this.font.width(this.title)/2, 8, 0xFFFFFFFF,true);
guiGraphics.text(this.font, "Drag and drop sprites inside...", this.width / 2 - this.font.width("Drag and drop sprites inside...")/2, 20, 0xFFFFFFFF,true); guiGraphics.text(this.font, "Drag and drop sprites inside...", this.width / 2 - this.font.width("Drag and drop sprites inside...")/2, 20, 0xFFFFFFFF,true);
guiGraphics.text(this.font, "All loaded clouds", leftList.getX(), 32, 0xFFFFFFFF,true);
guiGraphics.text(this.font, "Selected clouds", rightList.getX(), 32, 0xFFFFFFFF,true);
guiGraphics.pose().popMatrix(); guiGraphics.pose().popMatrix();
// NeoForge.EVENT_BUS.post(new ScreenEvent.Render.Post(this,guiGraphicsExtractor, mouseX, mouseY,partialTick));
//SkyboxMod.LOGGER.debug("\n this font: " + this.font + "\n this width:" + this.width + "\n this Title: " + this.title + "\n this title width: " + this.font.width(this.title));
} }
@Override @Override
@@ -107,18 +182,54 @@ public class SelectionScreen extends Screen {
@Override @Override
public void onClose() { public void onClose() {
List<String> IdentifierToStrings = new ArrayList<>();
selectedItems.forEach(item->{
String name = item.getPath();
if(name.contains("loaded_texture_")){
name = name.split("loaded_texture_")[1];
Path ResourcesDir = FMLPaths.GAMEDIR.get().resolve(ResourceFolderName);
Path Clouds = ResourcesDir.resolve(CloudsFolderName);
name = Clouds.resolve(name).toString();
}
SkyboxMod.LOGGER.debug("Loaded Identifier: " + name);
IdentifierToStrings.add(name);
});
Config.CLOUD_PATHS.get().clear();
Config.CLOUD_PATHS.set(IdentifierToStrings);
Config.CLOUD_PATHS.save();
DistantSkyObject.RegenerateClouds();
this.minecraft.setScreen(this.lastScreen); this.minecraft.setScreen(this.lastScreen);
} }
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY) {
boolean scroll = false;
if (leftList != null && leftList.mouseScrolled(mouseX, mouseY, scrollX, scrollY)) {
scroll = true;
}
if (rightList != null && rightList.mouseScrolled(mouseX, mouseY, scrollX, scrollY)) {
scroll = true;
}
if(scroll) return true;
return super.mouseScrolled(mouseX, mouseY, scrollX, scrollY);
}
private class SelectionPanelList extends ObjectSelectionList<TextRowEntry> { private class SelectionPanelList extends ObjectSelectionList<TextRowEntry> {
public SelectionPanelList(Minecraft minecraft, int width, int height, int y, int itemHeight) { private final SelectionScreen parent;
public SelectionPanelList(Minecraft minecraft, int width, int height, int y, int itemHeight, SelectionScreen parent) {
super(minecraft, width, height, y, itemHeight); super(minecraft, width, height, y, itemHeight);
this.parent = parent;
} }
public void AddEntry(TextRowEntry entry){ public void AddEntry(TextRowEntry entry){
this.addEntry(entry); this.addEntry(entry);
} }
public void RemoveEntry(TextRowEntry entry){
this.removeEntry(entry);
}
@Override @Override
public int getRowWidth() { public int getRowWidth() {
return getWidth() - this.scrollbarWidth(); return getWidth() - this.scrollbarWidth();
@@ -127,30 +238,51 @@ public class SelectionScreen extends Screen {
public void ClearChildren(){ public void ClearChildren(){
this.clearEntries(); this.clearEntries();
} }
@Override
protected int scrollBarX() {
return this.getX() + this.getRowWidth();
}
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY)
{
if (!this.visible || !this.isHovered) {
return false;
} else {
this.setScrollAmount(this.scrollAmount() - scrollY * this.scrollRate());
return true;
}
}
} }
private class TextRowEntry extends ObjectSelectionList.Entry<TextRowEntry> { private class TextRowEntry extends ObjectSelectionList.Entry<TextRowEntry> {
private final String textValue; private final Identifier textValue;
private final Button transferButton; private final Button transferButton;
private final SelectionScreen Parent; private final SelectionScreen Parent;
public TextRowEntry(String value, boolean isAvailableSide, SelectionScreen Parent) { public TextRowEntry(Identifier value, boolean isAvailableSide, SelectionScreen Parent) {
this.Parent = Parent; this.Parent = Parent;
this.textValue = value; this.textValue = value;
String buttonSymbol = isAvailableSide ? "" : ""; String buttonSymbol = isAvailableSide ? "" : "";
TextRowEntry currentEntry = this;
this.transferButton = Button.builder(Component.literal(buttonSymbol), button -> { this.transferButton = Button.builder(Component.literal(buttonSymbol), button -> {
if (isAvailableSide) { if (isAvailableSide) {
availableItems.remove(textValue); availableItems.remove(textValue);
selectedItems.add(textValue); selectedItems.add(textValue);
Parent.leftList.RemoveEntry(currentEntry);
} else { } else {
selectedItems.remove(textValue); selectedItems.remove(textValue);
availableItems.add(textValue); availableItems.add(textValue);
Parent.rightList.RemoveEntry(currentEntry);
} }
SkyboxMod.LOGGER.debug("BUTTON CLICKED!!!! " + isAvailableSide);
refreshListData(); refreshListData();
}).bounds(0, 0, 20, 20).build(); }).bounds(0, 0, 20, 20).build();
transferButtons.add(this.transferButton); transferButtons.add(this.transferButton);
Parent.addRenderableWidget(this.transferButton);
} }
@Override @Override
@@ -159,14 +291,18 @@ public class SelectionScreen extends Screen {
int top = this.getY(); int top = this.getY();
int rowWidth = this.getWidth(); int rowWidth = this.getWidth();
int rowHeight = this.getHeight(); int rowHeight = this.getHeight();
graphics.pose().pushMatrix();
this.transferButton.setX(left + rowWidth - (transferButton.getWidth() + 2)); this.transferButton.setX(left + rowWidth - (transferButton.getWidth() + 2));
this.transferButton.setY(top + rowHeight/2 - transferButton.getWidth()/2); this.transferButton.setY(top + rowHeight/2 - transferButton.getWidth()/2);
this.transferButton.extractRenderState(graphics, mouseX, mouseY, partialTick);
graphics.pose().pushMatrix();
graphics.pose().translate((float)left, (float)top); graphics.pose().translate((float)left, (float)top);
// SkyboxMod.LOGGER.debug("\n this font: " + Parent.getFont() + "\n this rowWidth:" + rowWidth + "\n this Text: " + this.textValue + "\n this Position: " + left +"_"+top); // SkyboxMod.LOGGER.debug("\n this font: " + Parent.getFont() + "\n this rowWidth:" + rowWidth + "\n this Text: " + this.textValue + "\n this Position: " + left +"_"+top);
graphics.blit( Identifier.fromNamespaceAndPath(SkyboxMod.MODID, "textures/no_texture.png"),0, 0, 20, 20,0,1,0,1); String name = this.textValue.getPath();
graphics.text(Parent.getFont(), this.textValue, 24, 6, 0xFFFFFFFF, true); if(name.contains("loaded_texture_")){
this.transferButton.extractRenderState(graphics, mouseX, mouseY, partialTick); name = name.split("loaded_texture_")[1];
}
graphics.blit( this.textValue,0, 0, 48, 48,0,1,0,1);
graphics.text(Parent.getFont(), name, 4, 52, 0xFFFFFFFF, true);
graphics.pose().popMatrix(); graphics.pose().popMatrix();
} }
@@ -180,7 +316,11 @@ public class SelectionScreen extends Screen {
@Override @Override
public Component getNarration() { public Component getNarration() {
return Component.literal(this.textValue); String name = this.textValue.getPath();
if(name.contains("loaded_texture_")){
name = name.split("loaded_texture_")[1];
}
return Component.literal(name);
} }
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB