Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public final class PackManager {
"you are now blinking manually", "you're eligible for a free hug token! <3", "don't mind me!", "hissss", "Gayser and Floodgayte, my favourite plugins.",
"meow", "we'll be done here soon™", "got anything else to say?", "we're done now!", "this will be fixed by v6053", "expect it to be done within 180 business days!",
"any colour you like", "someone tell Mojang about this", "you can't unbake baked models, so we'll store the unbaked models", "soon fully datagen ready",
"packconverter when", "codecs ftw");
"packconverter when", "codecs ftw", "we <3 barrels.", "Nothing beats a Jet2 Holiday!");
private static final RandomSource RANDOM = RandomSource.create();

private static final Path EXPORT_DIRECTORY = FabricLoader.getInstance().getGameDir().resolve(Rainbow.MOD_ID);
Expand Down Expand Up @@ -71,6 +71,10 @@ public void runOrElse(Consumer<RainbowPack> consumer, Runnable runnable) {
currentPack.ifPresentOrElse(consumer, runnable);
}

public boolean isInProgress() {
return currentPack.isPresent();
}

public Optional<Path> getExportPath() {
return currentPack.map(pack -> EXPORT_DIRECTORY.resolve(pack.resources.name()));
}
Expand Down
115 changes: 115 additions & 0 deletions client/src/main/java/org/geysermc/rainbow/client/PackManagerUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package org.geysermc.rainbow.client;

import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.network.chat.ClickEvent;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.ItemStackTemplate;
import org.geysermc.rainbow.client.mapper.PackMapper;
import org.geysermc.rainbow.pack.BedrockPack;

import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

// These methods are only ever called if player isn't null, so please stop warning me IntelliJ qwq
@SuppressWarnings("DataFlowIssue")
public class PackManagerUtils {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason the methods in this class can't be in PackManager itself?

private static final Component NO_PACK_CREATED = Component.translatable("feedback.rainbow.no_pack", Component.literal("/rainbow create <name>")
.withStyle(style -> style.withColor(ChatFormatting.BLUE).withUnderlined(true)
.withClickEvent(new ClickEvent.SuggestCommand("/rainbow create ")))).withStyle(ChatFormatting.RED);

public static boolean startPack(String name, PackManager manager, Minecraft minecraft) {
try {
manager.startPack(name);
minecraft.player.sendSystemMessage(
Component.translatable("feedback.rainbow.pack_create_success", name)
.withStyle(style -> style
.withColor(ChatFormatting.GREEN)
)
);
return true;
} catch (IOException e) {
RainbowClient.LOGGER.error("IOException when creating pack.", e);
minecraft.player.sendSystemMessage(
Component.translatable("feedback.rainbow.pack_create_error")
.withStyle(style -> style
.withColor(ChatFormatting.RED)
.withClickEvent(RainbowClient.LOG_CLICK_EVENT)
)
);
return false;
}
}

public static boolean mapItemInHand(PackManager manager, Minecraft minecraft) {
if (!manager.isInProgress()) return false;

manager.run(pack -> {
ItemStack heldItem = minecraft.player.getMainHandItem();
if (heldItem.isEmpty()) {
minecraft.player.sendSystemMessage(Component.literal("Must hold an item to map").withStyle(ChatFormatting.RED));
} else {
switch (RainbowClient.getPackMapper().mapItems(pack, List.of(ItemStackTemplate.fromNonEmptyStack(heldItem))).toSingleResult()) {
case NONE_MAPPED -> minecraft.player.sendSystemMessage(Component.translatable("commands.rainbow.no_item_mapped").withStyle(ChatFormatting.RED));
case PROBLEMS_OCCURRED -> minecraft.player.sendSystemMessage(Component.translatable("commands.rainbow.mapped_held_item_problems"));
case MAPPED_SUCCESSFULLY -> minecraft.player.sendSystemMessage(Component.translatable("commands.rainbow.mapped_held_item"));
}
}
});

return true;
}

public static boolean mapItemsInInventory(PackManager manager, Minecraft minecraft) {
if (!manager.isInProgress()) return false;

manager.run(pack -> {
List<ItemStackTemplate> inventoryStacks = new ArrayList<>(minecraft.player.inventoryMenu.getItems().stream()
.filter(stack -> !stack.isEmpty())
.map(ItemStackTemplate::fromNonEmptyStack)
.toList());
if (minecraft.player.hasContainerOpen()) {
inventoryStacks.addAll(minecraft.player.containerMenu.getItems().stream()
.filter(stack -> !stack.isEmpty())
.map(ItemStackTemplate::fromNonEmptyStack)
.toList());
}
PackMapper.MappingResults results = RainbowClient.getPackMapper().mapItems(pack, inventoryStacks);

if (results.itemsMapped() > 0 || results.skullsMapped() > 0) {
if (results.itemsMapped() > 0) {
minecraft.player.sendSystemMessage(Component.translatable("commands.rainbow.mapped_items_from_inventory", results.itemsMapped()).withStyle(ChatFormatting.GREEN));
if (results.problems() > 0) {
minecraft.player.sendSystemMessage(Component.translatable("commands.rainbow.mapped_items_problems").withStyle(ChatFormatting.YELLOW));
}
}
if (results.skullsMapped() > 0) {
minecraft.player.sendSystemMessage(Component.translatable("commands.rainbow.mapped_skulls_from_inventory", results.skullsMapped()).withStyle(ChatFormatting.GREEN));
}
} else {
minecraft.player.sendSystemMessage(Component.translatable("commands.rainbow.no_items_mapped").withStyle(ChatFormatting.RED));
}
});

return true;
}

public static boolean finishPack(PackManager manager, Minecraft minecraft) {
if (!manager.isInProgress()) return false;

minecraft.player.sendSystemMessage(Component.translatable("commands.rainbow.pack_finishing"));
Optional<Path> exportPath = manager.getExportPath();
Runnable onFinish = () -> minecraft.player.sendSystemMessage(Component.translatable("commands.rainbow.pack_finished_successfully").withStyle(style
-> style.withUnderlined(true).withClickEvent(new ClickEvent.OpenFile(exportPath.orElseThrow()))));
if (!manager.finish(onFinish)) {
minecraft.player.sendSystemMessage(NO_PACK_CREATED);
}

return true;
}
}
Original file line number Diff line number Diff line change
@@ -1,29 +1,58 @@
package org.geysermc.rainbow.client;

import com.mojang.blaze3d.platform.InputConstants;
import com.mojang.logging.LogUtils;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.fabricmc.fabric.api.command.v2.ArgumentTypeRegistry;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.Minecraft;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.commands.synchronization.SingletonArgumentInfo;
import net.minecraft.network.chat.ClickEvent;
import org.geysermc.rainbow.Rainbow;
import org.geysermc.rainbow.RainbowIO;
import org.geysermc.rainbow.client.command.CommandSuggestionsArgumentType;
import org.geysermc.rainbow.client.command.PackGeneratorCommand;
import org.geysermc.rainbow.client.mapper.PackMapper;
import org.geysermc.rainbow.client.screen.CreatePackScreen;
import org.geysermc.rainbow.client.screen.ManagePackScreen;
import org.slf4j.Logger;

public class RainbowClient implements ClientModInitializer {
public static final Logger LOGGER = LogUtils.getLogger();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can replace this with Rainbow.LOGGER.

public static final ClickEvent LOG_CLICK_EVENT = new ClickEvent.OpenFile(Minecraft.getInstance().gameDirectory.toPath().resolve("logs/latest.log"));

public static final String MOD_ID = Rainbow.MOD_ID + "-client";

private final PackManager packManager = new PackManager();
private final PackMapper packMapper = new PackMapper(packManager);
private static final PackManager packManager = new PackManager();
private static final PackMapper packMapper = new PackMapper(packManager);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are constants, so PACK_MANAGER and PACK_MAPPER.


public static PackManager getPackManager() {
return packManager;
}
public static PackMapper getPackMapper() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a newline before this method.

return packMapper;
}

// TODO export language overrides
@Override
public void onInitializeClient() {
KeyMapping openPackScreenKeyBind = KeyBindingHelper.registerKeyBinding(new KeyMapping("key.rainbow.open_pack_screen", InputConstants.KEY_O, KeyMapping.Category.MISC));

ClientCommandRegistrationCallback.EVENT.register((dispatcher, _) -> PackGeneratorCommand.register(dispatcher, packManager, packMapper));
ClientTickEvents.START_CLIENT_TICK.register(packMapper::tick);
ClientTickEvents.END_CLIENT_TICK.register(minecraft -> {
if (minecraft.player == null) return;
if (minecraft.screen != null) return;

if (openPackScreenKeyBind.consumeClick()) {
if (packManager.isInProgress()) minecraft.setScreen(new ManagePackScreen(packManager, packMapper));
else minecraft.setScreen(new CreatePackScreen(packManager, packMapper));
}
});

ArgumentTypeRegistry.registerArgumentType(Rainbow.getModdedIdentifier("command_suggestions"),
CommandSuggestionsArgumentType.class, SingletonArgumentInfo.contextFree(CommandSuggestionsArgumentType::new));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
package org.geysermc.rainbow.client;

import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.toasts.SystemToast;
import net.minecraft.network.chat.Component;
import org.geysermc.rainbow.RainbowIO;

import java.io.IOException;

public class RainbowClientIOHandler implements RainbowIO.IOExceptionListener {
private static final SystemToast.SystemToastId TOAST_ID = new SystemToast.SystemToastId();

@Override
public void error(IOException exception) {
Minecraft.getInstance().getToastManager().addToast(new SystemToast(TOAST_ID,
Component.translatable("toast.rainbow.io_exception.title"), Component.translatable("toast.rainbow.io_exception.description")));
Minecraft.getInstance().player.displayClientMessage(
Component.translatable("feedback.rainbow.io_exception")
.withStyle(style -> style
.withColor(ChatFormatting.RED)
.withClickEvent(RainbowClient.LOG_CLICK_EVENT)
),
false
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.ClickEvent;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.ItemStackTemplate;
import org.geysermc.rainbow.client.PackManager;
import org.geysermc.rainbow.client.PackManagerUtils;
import org.geysermc.rainbow.client.mapper.InventoryMapper;
import org.geysermc.rainbow.client.mapper.PackMapper;

Expand All @@ -22,64 +24,31 @@

public class PackGeneratorCommand {

private static final Component NO_PACK_CREATED = Component.translatable("commands.rainbow.no_pack", Component.literal("/rainbow create <name>")
private static final Component NO_PACK_CREATED = Component.translatable("feedback.rainbow.no_pack", Component.literal("/rainbow create <name>")
.withStyle(style -> style.withColor(ChatFormatting.BLUE).withUnderlined(true)
.withClickEvent(new ClickEvent.SuggestCommand("/rainbow create "))));
.withClickEvent(new ClickEvent.SuggestCommand("/rainbow create ")))).withStyle(ChatFormatting.RED);

public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher, PackManager packManager, PackMapper packMapper) {
dispatcher.register(ClientCommands.literal("rainbow")
.then(ClientCommands.literal("create")
.then(ClientCommands.argument("name", StringArgumentType.word())
.executes(context -> {
String name = StringArgumentType.getString(context, "name");
try {
packManager.startPack(name);
} catch (Exception exception) {
context.getSource().sendError(Component.translatable("commands.rainbow.create_pack_failed"));
throw new RuntimeException(exception);
}
context.getSource().sendFeedback(Component.translatable("commands.rainbow.pack_created", name));

PackManagerUtils.startPack(name, packManager, context.getSource().getClient());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary whitespace.

return 0;
})
)
)
.then(ClientCommands.literal("map")
.executes(runWithPack(packManager, (source, pack) -> {
ItemStack heldItem = source.getPlayer().getMainHandItem();
if (heldItem.isEmpty()) {
source.sendError(Component.literal("Must hold an item to map"));
} else {
switch (packMapper.mapItems(pack, List.of(ItemStackTemplate.fromNonEmptyStack(heldItem))).toSingleResult()) {
case NONE_MAPPED -> source.sendError(Component.translatable("commands.rainbow.no_item_mapped"));
case PROBLEMS_OCCURRED -> source.sendFeedback(Component.translatable("commands.rainbow.mapped_held_item_problems"));
case MAPPED_SUCCESSFULLY -> source.sendFeedback(Component.translatable("commands.rainbow.mapped_held_item"));
}
}
PackManagerUtils.mapItemInHand(packManager, source.getClient());
}))
)
.then(ClientCommands.literal("mapinventory")
.executes(runWithPack(packManager, (source, pack) -> {
List<ItemStackTemplate> inventoryStacks = new ArrayList<>();
source.getPlayer().getInventory().forEach(stack -> {
if (!stack.isEmpty()) {
inventoryStacks.add(ItemStackTemplate.fromNonEmptyStack(stack));
}
});
PackMapper.MappingResults results = packMapper.mapItems(pack, inventoryStacks);

if (results.itemsMapped() > 0 || results.skullsMapped() > 0) {
if (results.itemsMapped() > 0) {
source.sendFeedback(Component.translatable("commands.rainbow.mapped_items_from_inventory", results.itemsMapped()));
if (results.problems() > 0) {
source.sendFeedback(Component.translatable("commands.rainbow.mapped_items_problems"));
}
}
if (results.skullsMapped() > 0) {
source.sendFeedback(Component.translatable("commands.rainbow.mapped_skulls_from_inventory", results.skullsMapped()));
}
} else {
source.sendError(Component.translatable("commands.rainbow.no_items_mapped"));
}
PackManagerUtils.mapItemsInInventory(packManager, source.getClient());
}))
)
.then(ClientCommands.literal("auto")
Expand All @@ -104,25 +73,25 @@ public static void register(CommandDispatcher<FabricClientCommandSource> dispatc
.then(ClientCommands.literal("inventory")
.executes(runWithPack(packManager, (source, _) -> {
packMapper.setItemProvider(InventoryMapper.INSTANCE);
source.sendFeedback(Component.translatable("commands.rainbow.automatic_inventory_mapping"));
source.sendFeedback(
Component.translatable("feedback.rainbow.automatic_mapping_inventory")
.withStyle(ChatFormatting.GREEN)
);
}))
)
.then(ClientCommands.literal("stop")
.executes(runWithPack(packManager, (source, _) -> {
packMapper.setItemProvider(null);
source.sendFeedback(Component.translatable("commands.rainbow.stopped_automatic_mapping"));
source.sendFeedback(
Component.translatable("feedback.rainbow.automatic_mapping_none")
.withStyle(ChatFormatting.GREEN)
);
}))
)
)
.then(ClientCommands.literal("finish")
.executes(context -> {
context.getSource().sendFeedback(Component.translatable("commands.rainbow.pack_finishing"));
Optional<Path> exportPath = packManager.getExportPath();
Runnable onFinish = () -> context.getSource().sendFeedback(Component.translatable("commands.rainbow.pack_finished_successfully").withStyle(style
-> style.withUnderlined(true).withClickEvent(new ClickEvent.OpenFile(exportPath.orElseThrow()))));
if (!packManager.finish(onFinish)) {
context.getSource().sendError(NO_PACK_CREATED);
}
PackManagerUtils.finishPack(packManager, context.getSource().getClient());
return 0;
})
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStackTemplate;

import java.util.Collection;
Expand All @@ -11,4 +12,6 @@ public interface CustomItemProvider {
Collection<ItemStackTemplate> nextItems(LocalPlayer player, ClientPacketListener connection);

boolean isDone();

Component name();
}
Loading
Loading