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 @@ -20,7 +20,6 @@
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;

public final class PackManager {
Expand All @@ -30,7 +29,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 @@ -64,6 +63,10 @@ public void runOrElse(Consumer<BedrockPack> 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.name()));
}
Expand Down
119 changes: 119 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,119 @@
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 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?

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

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

manager.run(pack -> {
ItemStack heldItem = minecraft.player.getMainHandItem();
switch (pack.map(heldItem)) {
case NONE_MAPPED -> minecraft.player.displayClientMessage(Component.translatable("feedback.rainbow.no_item_mapped").withStyle(ChatFormatting.RED), false);
case PROBLEMS_OCCURRED -> minecraft.player.displayClientMessage(Component.translatable("feedback.rainbow.mapped_item_problems").withStyle(ChatFormatting.YELLOW), false);
case MAPPED_SUCCESSFULLY -> minecraft.player.displayClientMessage(Component.translatable("feedback.rainbow.mapped_item").withStyle(ChatFormatting.GREEN), false);
}
});

return true;
}

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

manager.run(pack -> {
int mapped = 0;
boolean errors = false;

List<ItemStack> items;

if (minecraft.screen instanceof AbstractContainerScreen<?> abstractContainerScreen) {
items = abstractContainerScreen.getMenu().getItems();
} else {
items = new ArrayList<>(minecraft.player.getInventory().getNonEquipmentItems());
items.add(minecraft.player.getInventory().getItem(36)); // Boots
items.add(minecraft.player.getInventory().getItem(37)); // Leggings
items.add(minecraft.player.getInventory().getItem(38)); // Chestplate
items.add(minecraft.player.getInventory().getItem(39)); // Helmet
items.add(minecraft.player.getInventory().getItem(40)); // Offhand
}
Comment on lines +67 to +78
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.

Suggested change
List<ItemStack> items;
if (minecraft.screen instanceof AbstractContainerScreen<?> abstractContainerScreen) {
items = abstractContainerScreen.getMenu().getItems();
} else {
items = new ArrayList<>(minecraft.player.getInventory().getNonEquipmentItems());
items.add(minecraft.player.getInventory().getItem(36)); // Boots
items.add(minecraft.player.getInventory().getItem(37)); // Leggings
items.add(minecraft.player.getInventory().getItem(38)); // Chestplate
items.add(minecraft.player.getInventory().getItem(39)); // Helmet
items.add(minecraft.player.getInventory().getItem(40)); // Offhand
}
List<ItemStack> items = new ArrayList<>(minecraft.player.inventoryMenu.getItems());
if (minecraft.player.hasContainerOpen()) {
items.addAll(minecraft.player.containerMenu.getItems())
}


for (ItemStack stack : items) {
BedrockPack.MappingResult result = pack.map(stack);
if (result != BedrockPack.MappingResult.NONE_MAPPED) {
mapped++;
if (result == BedrockPack.MappingResult.PROBLEMS_OCCURRED) {
errors = true;
}
}
}

if (mapped > 0) {
minecraft.player.displayClientMessage(Component.translatable("feedback.rainbow.mapped_items", mapped).withStyle(ChatFormatting.GREEN), false);
if (errors) {
minecraft.player.displayClientMessage(Component.translatable("feedback.rainbow.mapped_items_problems").withStyle(ChatFormatting.YELLOW), false);
}
} else {
minecraft.player.displayClientMessage(Component.translatable("feedback.rainbow.no_items_mapped").withStyle(ChatFormatting.RED), false);
}
});

return true;
}

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

Optional<Path> exportPath = manager.getExportPath();
// Ignore the result of the method, we check above
manager.finish(() -> minecraft.player.displayClientMessage(
Component.translatable("feedback.rainbow.pack_finished_success")
.withStyle(style -> style
.withColor(ChatFormatting.GREEN)
.withClickEvent(new ClickEvent.OpenFile(exportPath.orElseThrow()))
),
false
));

return true;
}
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,55 @@
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.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"));

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, buildContext) -> 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.getModdedLocation("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,74 +8,41 @@
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 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;
import org.geysermc.rainbow.pack.BedrockPack;

import java.nio.file.Path;
import java.util.Optional;
import java.util.function.BiConsumer;

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(ClientCommandManager.literal("rainbow")
.then(ClientCommandManager.literal("create")
.then(ClientCommandManager.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(ClientCommandManager.literal("map")
.executes(runWithPack(packManager, (source, pack) -> {
ItemStack heldItem = source.getPlayer().getMainHandItem();
switch (pack.map(heldItem)) {
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(ClientCommandManager.literal("mapinventory")
.executes(runWithPack(packManager, (source, pack) -> {
int mapped = 0;
boolean errors = false;
Inventory inventory = source.getPlayer().getInventory();

for (ItemStack stack : inventory) {
BedrockPack.MappingResult result = pack.map(stack);
if (result != BedrockPack.MappingResult.NONE_MAPPED) {
mapped++;
if (result == BedrockPack.MappingResult.PROBLEMS_OCCURRED) {
errors = true;
}
}
}

if (mapped > 0) {
source.sendFeedback(Component.translatable("commands.rainbow.mapped_items_from_inventory", mapped));
if (errors) {
source.sendFeedback(Component.translatable("commands.rainbow.mapped_items_problems"));
}
} else {
source.sendError(Component.translatable("commands.rainbow.no_items_mapped"));
}
PackManagerUtils.mapItemsInInventory(packManager, source.getClient());
}))
)
.then(ClientCommandManager.literal("auto")
Expand All @@ -100,24 +67,25 @@ public static void register(CommandDispatcher<FabricClientCommandSource> dispatc
.then(ClientCommandManager.literal("inventory")
.executes(runWithPack(packManager, (source, pack) -> {
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(ClientCommandManager.literal("stop")
.executes(runWithPack(packManager, (source, pack) -> {
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(ClientCommandManager.literal("finish")
.executes(context -> {
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.ItemStack;

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

boolean isDone();

Component name();
}
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.ItemStack;

import java.util.stream.Stream;
Expand All @@ -20,4 +21,9 @@ public Stream<ItemStack> nextItems(LocalPlayer player, ClientPacketListener conn
public boolean isDone() {
return false;
}

@Override
public Component name() {
return Component.translatable("menu.rainbow.manage_pack.auto_mapping.inventory");
}
}
Loading