Skip to content

Commit

Permalink
make 'get-lavender-book' command client-side and expand to appropriat…
Browse files Browse the repository at this point in the history
…e /give invocation when executed
  • Loading branch information
gliscowo committed Aug 18, 2024
1 parent 11d94c9 commit 38aa191
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 39 deletions.
5 changes: 0 additions & 5 deletions src/main/java/io/wispforest/lavender/Lavender.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import io.wispforest.lavender.book.LavenderBookItem;
import io.wispforest.owo.serialization.CodecUtils;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.minecraft.datafixer.DataFixTypes;
Expand All @@ -30,15 +29,11 @@ public class Lavender implements ModInitializer {
public static final String MOD_ID = "lavender";
public static final SoundEvent ITEM_BOOK_OPEN = SoundEvent.of(id("item.book.open"));

public static final Identifier WORLD_ID_CHANNEL = Lavender.id("world_id_channel");

@Override
public void onInitialize() {
Registry.register(Registries.ITEM, id("dynamic_book"), LavenderBookItem.DYNAMIC_BOOK);
Registry.register(Registries.SOUND_EVENT, ITEM_BOOK_OPEN.getId(), ITEM_BOOK_OPEN);

CommandRegistrationCallback.EVENT.register(LavenderCommands::register);

PayloadTypeRegistry.playS2C().register(WorldUUIDPayload.ID, CodecUtils.toPacketCodec(WorldUUIDPayload.ENDEC));

ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> {
Expand Down
99 changes: 65 additions & 34 deletions src/main/java/io/wispforest/lavender/LavenderCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,72 +7,103 @@
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import io.wispforest.lavender.book.Book;
import io.wispforest.lavender.book.LavenderBookItem;
import io.wispforest.lavender.book.BookLoader;
import io.wispforest.lavender.book.LavenderBookItem;
import io.wispforest.lavender.client.StructureOverlayRenderer;
import io.wispforest.lavender.structure.LavenderStructures;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.client.gui.screen.ChatScreen;
import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.command.CommandSource;
import net.minecraft.command.argument.IdentifierArgumentType;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.component.Component;
import net.minecraft.nbt.NbtOps;
import net.minecraft.registry.Registries;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;

import static net.minecraft.server.command.CommandManager.argument;
import static net.minecraft.server.command.CommandManager.literal;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument;
import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;

public class LavenderCommands {

private static final SimpleCommandExceptionType NO_SUCH_BOOK = new SimpleCommandExceptionType(Text.literal("No such book is loaded"));

private static final SuggestionProvider<ServerCommandSource> LOADED_BOOKS = (context, builder) -> {
private static final SuggestionProvider<FabricClientCommandSource> LOADED_BOOKS = (context, builder) -> {
return CommandSource.suggestIdentifiers(BookLoader.loadedBooks().stream().map(Book::id), builder);
};

public static void register(CommandDispatcher<ServerCommandSource> dispatcher, CommandRegistryAccess access, CommandManager.RegistrationEnvironment environment) {
dispatcher.register(literal("get-lavender-book")
.then(argument("book_id", IdentifierArgumentType.identifier()).suggests(LOADED_BOOKS)
.executes(context -> executeGetLavenderBook(context, false))
.then(argument("force_dynamic_book", BoolArgumentType.bool())
.executes(context -> executeGetLavenderBook(context, BoolArgumentType.getBool(context, "force_dynamic_book"))))));

}

private static int executeGetLavenderBook(CommandContext<ServerCommandSource> context, boolean forceDynamicBook) throws CommandSyntaxException {
var book = BookLoader.get(IdentifierArgumentType.getIdentifier(context, "book_id"));
if (book == null) {
throw NO_SUCH_BOOK.create();
}

context.getSource().getPlayer().getInventory().offerOrDrop(forceDynamicBook
? LavenderBookItem.createDynamic(book)
: LavenderBookItem.itemOf(book)
);

return 0;
}

@Environment(EnvType.CLIENT)
public static class Client {

private static final SimpleCommandExceptionType NO_SUCH_STRUCTURE = new SimpleCommandExceptionType(Text.literal("No such structure is loaded"));
private static final SuggestionProvider<FabricClientCommandSource> STRUCTURE_INFO = (context, builder) ->
CommandSource.suggestMatching(LavenderStructures.loadedStructures().stream().map(Identifier::toString), builder);

private static int executeGetLavenderBook(CommandContext<FabricClientCommandSource> context, boolean forceDynamicBook) throws CommandSyntaxException {
var book = BookLoader.get(context.getArgument("book_id", Identifier.class));
if (book == null) {
throw NO_SUCH_BOOK.create();
}

var stack = forceDynamicBook
? LavenderBookItem.createDynamic(book)
: LavenderBookItem.itemOf(book);

var command = "/give @s " + Registries.ITEM.getId(stack.getItem());

var ops = context.getSource().getWorld().getRegistryManager().getOps(NbtOps.INSTANCE);
var components = stack.getComponentChanges().entrySet().stream().flatMap(entry -> {
var componentType = entry.getKey();
var typeId = Registries.DATA_COMPONENT_TYPE.getId(componentType);
if (typeId == null) return Stream.empty();

var componentOptional = entry.getValue();
if (componentOptional.isPresent()) {
Component<?> component = Component.of(componentType, componentOptional.get());
return component.encode(ops).result().stream().map(value -> typeId + "=" + value);
} else {
return Stream.of("!" + typeId);
}
}).collect(Collectors.joining(String.valueOf(',')));

if (!components.isEmpty()) {
command += "[" + components + "]";
}

if (stack.getCount() > 1) {
command += " " + stack.getCount();
}

var jAvAsE = command;
context.getSource().getClient().send(() -> {
context.getSource().getClient().setScreen(new ChatScreen(jAvAsE));
});

return 0;
}

public static void register(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess access) {
dispatcher.register(ClientCommandManager.literal("structure-overlay")
.then(ClientCommandManager.literal("clear-all").executes(context -> {
dispatcher.register(literal("get-lavender-book").requires(source -> source.hasPermissionLevel(2))
.then(argument("book_id", IdentifierArgumentType.identifier()).suggests(LOADED_BOOKS)
.executes(context -> executeGetLavenderBook(context, false))
.then(argument("force_dynamic_book", BoolArgumentType.bool())
.executes(context -> executeGetLavenderBook(context, BoolArgumentType.getBool(context, "force_dynamic_book"))))));


dispatcher.register(literal("structure-overlay")
.then(literal("clear-all").executes(context -> {
StructureOverlayRenderer.clearOverlays();
return 0;
}))

.then(ClientCommandManager.literal("add")
.then(ClientCommandManager.argument("structure", IdentifierArgumentType.identifier()).suggests(STRUCTURE_INFO).executes(context -> {
.then(literal("add")
.then(argument("structure", IdentifierArgumentType.identifier()).suggests(STRUCTURE_INFO).executes(context -> {
var structureId = context.getArgument("structure", Identifier.class);
if (LavenderStructures.get(structureId) == null) throw NO_SUCH_STRUCTURE.create();

Expand Down

0 comments on commit 38aa191

Please sign in to comment.