mirror of
https://github.com/GeyserMC/Rainbow.git
synced 2025-12-19 14:59:16 +00:00
Refactor item suggestion mapper into custom item provider, only map items if their model hasn't been mapped before, don't export textures more than once
This commit is contained in:
@@ -9,7 +9,7 @@ import net.minecraft.commands.synchronization.SingletonArgumentInfo;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.geysermc.packgenerator.command.CommandSuggestionsArgumentType;
|
||||
import org.geysermc.packgenerator.command.PackGeneratorCommand;
|
||||
import org.geysermc.packgenerator.mapper.PackMappers;
|
||||
import org.geysermc.packgenerator.mapper.PackMapper;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public class GeyserMappingsGenerator implements ClientModInitializer {
|
||||
@@ -19,12 +19,12 @@ public class GeyserMappingsGenerator implements ClientModInitializer {
|
||||
public static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
private final PackManager packManager = new PackManager();
|
||||
private final PackMappers packMappers = new PackMappers(packManager);
|
||||
private final PackMapper packMapper = new PackMapper();
|
||||
|
||||
@Override
|
||||
public void onInitializeClient() {
|
||||
ClientCommandRegistrationCallback.EVENT.register((dispatcher, buildContext) -> PackGeneratorCommand.register(dispatcher, packManager, packMappers));
|
||||
ClientTickEvents.START_CLIENT_TICK.register(packMappers::tick);
|
||||
ClientCommandRegistrationCallback.EVENT.register((dispatcher, buildContext) -> PackGeneratorCommand.register(dispatcher, packManager, packMapper));
|
||||
ClientTickEvents.START_CLIENT_TICK.register(minecraft -> packMapper.tick(packManager, minecraft));
|
||||
|
||||
ArgumentTypeRegistry.registerArgumentType(getModdedLocation("command_suggestions"),
|
||||
CommandSuggestionsArgumentType.class, SingletonArgumentInfo.contextFree(CommandSuggestionsArgumentType::new));
|
||||
|
||||
@@ -1,39 +1,36 @@
|
||||
package org.geysermc.packgenerator;
|
||||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
|
||||
import org.geysermc.packgenerator.pack.BedrockPack;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
public final class PackManager {
|
||||
|
||||
private BedrockPack currentPack;
|
||||
private Optional<BedrockPack> currentPack = Optional.empty();
|
||||
|
||||
public void startPack(String name) throws IOException {
|
||||
if (currentPack != null) {
|
||||
throw new IllegalStateException("Already started a pack (" + currentPack.name() + ")");
|
||||
if (currentPack.isPresent()) {
|
||||
throw new IllegalStateException("Already started a pack (" + currentPack.get().name() + ")");
|
||||
}
|
||||
|
||||
currentPack = new BedrockPack(name);
|
||||
currentPack = Optional.of(new BedrockPack(name));
|
||||
}
|
||||
|
||||
public Optional<Boolean> map(ItemStack stack) {
|
||||
ensurePackIsCreated();
|
||||
|
||||
return currentPack.map(stack);
|
||||
public void run(Consumer<BedrockPack> consumer) {
|
||||
currentPack.ifPresent(consumer);
|
||||
}
|
||||
|
||||
public boolean finish() {
|
||||
ensurePackIsCreated();
|
||||
boolean success = currentPack.save();
|
||||
currentPack = null;
|
||||
public <T> Optional<T> run(Function<BedrockPack, T> function) {
|
||||
return currentPack.map(function);
|
||||
}
|
||||
|
||||
public Optional<Boolean> finish() {
|
||||
Optional<Boolean> success = currentPack.map(BedrockPack::save);
|
||||
currentPack = Optional.empty();
|
||||
return success;
|
||||
}
|
||||
|
||||
public void ensurePackIsCreated() {
|
||||
if (currentPack == null) {
|
||||
throw new IllegalStateException("Create a new pack first!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@ import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.geysermc.packgenerator.GeyserMappingsGenerator;
|
||||
import org.geysermc.packgenerator.PackManager;
|
||||
import org.geysermc.packgenerator.mapper.PackMappers;
|
||||
import org.geysermc.packgenerator.mapper.ItemSuggestionProvider;
|
||||
import org.geysermc.packgenerator.mapper.PackMapper;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -20,7 +20,7 @@ import java.util.function.Consumer;
|
||||
|
||||
public class PackGeneratorCommand {
|
||||
|
||||
public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher, PackManager packManager, PackMappers mappers) {
|
||||
public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher, PackManager packManager, PackMapper packMapper) {
|
||||
dispatcher.register(ClientCommandManager.literal("packgenerator")
|
||||
.then(ClientCommandManager.literal("create")
|
||||
.then(ClientCommandManager.argument("name", StringArgumentType.word())
|
||||
@@ -39,14 +39,16 @@ public class PackGeneratorCommand {
|
||||
)
|
||||
.then(ClientCommandManager.literal("map")
|
||||
.executes(context -> {
|
||||
packManager.run(pack -> {
|
||||
ItemStack heldItem = context.getSource().getPlayer().getMainHandItem();
|
||||
Optional<Boolean> problems = packManager.map(heldItem);
|
||||
Optional<Boolean> problems = pack.map(heldItem);
|
||||
if (problems.isEmpty()) {
|
||||
context.getSource().sendError(Component.literal("No item found to map!"));
|
||||
} else if (problems.get()) {
|
||||
context.getSource().sendError(Component.literal("Problems occurred whilst mapping the item!"));
|
||||
}
|
||||
context.getSource().sendFeedback(Component.literal("Added held item to Geyser mappings"));
|
||||
});
|
||||
return 0;
|
||||
})
|
||||
)
|
||||
@@ -55,24 +57,27 @@ public class PackGeneratorCommand {
|
||||
)
|
||||
.then(ClientCommandManager.literal("finish")
|
||||
.executes(context -> {
|
||||
if (!packManager.finish()) {
|
||||
packManager.finish().ifPresent(success -> {
|
||||
if (!success) {
|
||||
context.getSource().sendError(Component.literal("Errors occurred whilst trying to write the pack to disk!"));
|
||||
}
|
||||
} else {
|
||||
context.getSource().sendFeedback(Component.literal("Wrote pack to disk"));
|
||||
}
|
||||
});
|
||||
return 0;
|
||||
})
|
||||
)
|
||||
.then(ClientCommandManager.literal("auto")
|
||||
.then(ClientCommandManager.argument("suggestions", CommandSuggestionsArgumentType.TYPE)
|
||||
.executes(context -> {
|
||||
packManager.ensurePackIsCreated();
|
||||
Pair<String, CompletableFuture<Suggestions>> suggestions = CommandSuggestionsArgumentType.getSuggestions(context, "suggestions");
|
||||
String baseCommand = suggestions.getFirst();
|
||||
suggestions.getSecond().thenAccept(completed -> {
|
||||
mappers.getSuggestionMapper().start(completed.getList().stream()
|
||||
ItemSuggestionProvider provider = new ItemSuggestionProvider(completed.getList().stream()
|
||||
.map(suggestion -> baseCommand.substring(0, suggestion.getRange().getStart()) + suggestion.getText())
|
||||
.toList());
|
||||
context.getSource().sendFeedback(Component.literal("Running " + mappers.getSuggestionMapper().queueSize() + " commands to obtain custom items to map"));
|
||||
packMapper.setItemProvider(provider);
|
||||
context.getSource().sendFeedback(Component.literal("Running " + provider.queueSize() + " commands to obtain custom items to map"));
|
||||
});
|
||||
return 0;
|
||||
})
|
||||
@@ -82,10 +87,11 @@ public class PackGeneratorCommand {
|
||||
}
|
||||
|
||||
public static int mapInventory(PackManager manager, Inventory inventory, Consumer<Component> feedback, boolean feedbackOnEmpty) {
|
||||
return manager.run(pack -> {
|
||||
int mapped = 0;
|
||||
boolean errors = false;
|
||||
for (ItemStack stack : inventory) {
|
||||
Optional<Boolean> problems = manager.map(stack);
|
||||
Optional<Boolean> problems = pack.map(stack);
|
||||
if (problems.isPresent()) {
|
||||
mapped++;
|
||||
errors |= problems.get();
|
||||
@@ -99,6 +105,8 @@ public class PackGeneratorCommand {
|
||||
} else if (feedbackOnEmpty) {
|
||||
feedback.accept(Component.literal("No items were mapped"));
|
||||
}
|
||||
|
||||
return mapped;
|
||||
}).orElse(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.geysermc.packgenerator.mapper;
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface CustomItemProvider {
|
||||
|
||||
Stream<ItemStack> nextItems(LocalPlayer player, ClientPacketListener connection);
|
||||
|
||||
boolean isDone();
|
||||
}
|
||||
@@ -1,11 +1,23 @@
|
||||
package org.geysermc.packgenerator.mapper;
|
||||
|
||||
import org.geysermc.packgenerator.PackManager;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class InventoryMapper {
|
||||
private final PackManager packManager;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public InventoryMapper(PackManager packManager) {
|
||||
this.packManager = packManager;
|
||||
public class InventoryMapper implements CustomItemProvider {
|
||||
|
||||
public InventoryMapper() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<ItemStack> nextItems(LocalPlayer player, ClientPacketListener connection) {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
package org.geysermc.packgenerator.mapper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.game.ServerboundChatCommandPacket;
|
||||
import org.geysermc.packgenerator.PackManager;
|
||||
import org.geysermc.packgenerator.command.PackGeneratorCommand;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
// TODO safety
|
||||
public final class ItemSuggestionMapper {
|
||||
private final PackManager packManager;
|
||||
private final List<String> remainingCommands = new ArrayList<>();
|
||||
private boolean waitingOnItem = false;
|
||||
private boolean waitingOnClear = false;
|
||||
private int mapped = 0;
|
||||
|
||||
public ItemSuggestionMapper(PackManager packManager) {
|
||||
this.packManager = packManager;
|
||||
}
|
||||
|
||||
// TODO
|
||||
public boolean start(List<String> commands) {
|
||||
if (remainingCommands.isEmpty()) {
|
||||
remainingCommands.addAll(commands);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void tick(Minecraft minecraft) {
|
||||
if (minecraft.player == null || minecraft.getConnection() == null) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!remainingCommands.isEmpty() || waitingOnItem) {
|
||||
if (waitingOnClear && minecraft.player.getInventory().isEmpty()) {
|
||||
waitingOnClear = false;
|
||||
} else if (!waitingOnItem) {
|
||||
minecraft.getConnection().send(new ServerboundChatCommandPacket(remainingCommands.removeFirst()));
|
||||
waitingOnItem = true;
|
||||
} else {
|
||||
if (!minecraft.player.getInventory().isEmpty()) {
|
||||
mapped += PackGeneratorCommand.mapInventory(packManager, minecraft.player.getInventory(),
|
||||
component -> minecraft.player.displayClientMessage(component, false), false);
|
||||
|
||||
minecraft.getConnection().send(new ServerboundChatCommandPacket("clear"));
|
||||
|
||||
waitingOnItem = false;
|
||||
if (remainingCommands.isEmpty()) {
|
||||
minecraft.player.displayClientMessage(Component.literal("Done, " + mapped + " items have been mapped"), false);
|
||||
} else {
|
||||
waitingOnClear = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int queueSize() {
|
||||
return remainingCommands.size();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
remainingCommands.clear();
|
||||
waitingOnItem = false;
|
||||
waitingOnClear = false;
|
||||
mapped = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.geysermc.packgenerator.mapper;
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.network.protocol.game.ServerboundChatCommandPacket;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
// TODO safety
|
||||
public class ItemSuggestionProvider implements CustomItemProvider {
|
||||
private final List<String> remainingCommands;
|
||||
private boolean waitingOnItem = false;
|
||||
private boolean waitingOnClear = false;
|
||||
|
||||
public ItemSuggestionProvider(List<String> commands) {
|
||||
remainingCommands = commands;
|
||||
}
|
||||
|
||||
public Stream<ItemStack> nextItems(LocalPlayer player, ClientPacketListener connection) {
|
||||
if (!remainingCommands.isEmpty() || waitingOnItem) {
|
||||
if (waitingOnClear && player.getInventory().isEmpty()) {
|
||||
waitingOnClear = false;
|
||||
} else if (!waitingOnItem) {
|
||||
connection.send(new ServerboundChatCommandPacket(remainingCommands.removeFirst()));
|
||||
waitingOnItem = true;
|
||||
} else {
|
||||
if (!player.getInventory().isEmpty()) {
|
||||
Stream<ItemStack> items = player.getInventory().getNonEquipmentItems().stream();
|
||||
connection.send(new ServerboundChatCommandPacket("clear"));
|
||||
|
||||
waitingOnItem = false;
|
||||
if (!remainingCommands.isEmpty()) {
|
||||
waitingOnClear = true;
|
||||
}
|
||||
return items;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
public int queueSize() {
|
||||
return remainingCommands.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return remainingCommands.isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.geysermc.packgenerator.mapper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import org.geysermc.packgenerator.PackManager;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public class PackMapper {
|
||||
private CustomItemProvider itemProvider;
|
||||
|
||||
public void setItemProvider(CustomItemProvider itemProvider) {
|
||||
this.itemProvider = itemProvider;
|
||||
}
|
||||
|
||||
public void tick(PackManager packManager, Minecraft minecraft) {
|
||||
if (itemProvider != null) {
|
||||
LocalPlayer player = Objects.requireNonNull(minecraft.player);
|
||||
ClientPacketListener connection = Objects.requireNonNull(minecraft.getConnection());
|
||||
|
||||
packManager.run(pack -> {
|
||||
// TODO maybe report problems here... probably better to do so in pack class though
|
||||
long mapped = itemProvider.nextItems(player, connection)
|
||||
.map(pack::map)
|
||||
.filter(Optional::isPresent)
|
||||
.count();
|
||||
player.displayClientMessage(Component.literal("Mapped " + mapped + " items"), false);
|
||||
if (itemProvider.isDone()) {
|
||||
player.displayClientMessage(Component.literal("Finished mapping items from provider"), false);
|
||||
itemProvider = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package org.geysermc.packgenerator.mapper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import org.geysermc.packgenerator.PackManager;
|
||||
|
||||
public class PackMappers {
|
||||
private final ItemSuggestionMapper suggestionMapper;
|
||||
private final InventoryMapper inventoryMapper;
|
||||
|
||||
public PackMappers(PackManager packManager) {
|
||||
this.suggestionMapper = new ItemSuggestionMapper(packManager);
|
||||
this.inventoryMapper = new InventoryMapper(packManager);
|
||||
}
|
||||
|
||||
public ItemSuggestionMapper getSuggestionMapper() {
|
||||
return suggestionMapper;
|
||||
}
|
||||
|
||||
public InventoryMapper getInventoryMapper() {
|
||||
return inventoryMapper;
|
||||
}
|
||||
|
||||
public void tick(Minecraft minecraft) {
|
||||
suggestionMapper.tick(minecraft);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package org.geysermc.packgenerator.pack;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.components.SplashRenderer;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.ProblemReporter;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
@@ -22,8 +23,10 @@ import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@@ -45,7 +48,9 @@ public class BedrockPack {
|
||||
private final GeyserMappings mappings;
|
||||
private final BedrockTextures.Builder itemTextures;
|
||||
private final List<BedrockAttachable> attachables = new ArrayList<>();
|
||||
private final List<ResourceLocation> texturesToExport = new ArrayList<>();
|
||||
private final Set<ResourceLocation> texturesToExport = new HashSet<>();
|
||||
|
||||
private final Set<ResourceLocation> modelsMapped = new HashSet<>();
|
||||
|
||||
private final ProblemReporter.Collector reporter;
|
||||
|
||||
@@ -67,7 +72,7 @@ public class BedrockPack {
|
||||
}
|
||||
|
||||
public Optional<Boolean> map(ItemStack stack) {
|
||||
if (stack.isEmpty()) {
|
||||
if (stack.isEmpty() || !modelsMapped.add(stack.get(DataComponents.ITEM_MODEL))) {
|
||||
return Optional.empty();
|
||||
}
|
||||
AtomicBoolean problems = new AtomicBoolean();
|
||||
|
||||
Reference in New Issue
Block a user