Close #18 Currently testing item / block addition, keybinds and creative tabs.

This commit is contained in:
shedaniel
2021-01-20 20:28:15 +08:00
parent 5df13d4179
commit 9c6101835d
30 changed files with 431 additions and 41 deletions

View File

@@ -0,0 +1,42 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.test;
import me.shedaniel.architectury.platform.Platform;
import me.shedaniel.architectury.test.debug.ConsoleMessageSink;
import me.shedaniel.architectury.test.debug.DebugEvents;
import me.shedaniel.architectury.test.debug.MessageSink;
import me.shedaniel.architectury.test.debug.client.ClientOverlayMessageSink;
import me.shedaniel.architectury.test.registry.TestRegistries;
import me.shedaniel.architectury.test.registry.client.TestKeybinds;
import me.shedaniel.architectury.utils.Env;
import me.shedaniel.architectury.utils.EnvExecutor;
public class TestMod {
public static final MessageSink SINK = EnvExecutor.getEnvSpecific(() -> ClientOverlayMessageSink::new, () -> ConsoleMessageSink::new);
public static final String MOD_ID = "architectury-test";
public static void initialize() {
DebugEvents.initialize();
TestRegistries.initialize();
if (Platform.getEnvironment() == Env.CLIENT)
TestKeybinds.initialize();
}
}

View File

@@ -0,0 +1,32 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.test.debug;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class ConsoleMessageSink implements MessageSink {
protected final Logger logger = LogManager.getLogger("Architectury Test");
@Override
public void accept(String message) {
logger.info(message);
}
}

View File

@@ -0,0 +1,264 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.test.debug;
import com.mojang.blaze3d.platform.InputConstants;
import me.shedaniel.architectury.event.events.*;
import me.shedaniel.architectury.event.events.client.ClientChatEvent;
import me.shedaniel.architectury.event.events.client.ClientScreenInputEvent;
import me.shedaniel.architectury.event.events.client.ClientLifecycleEvent;
import me.shedaniel.architectury.event.events.client.ClientPlayerEvent;
import me.shedaniel.architectury.hooks.ExplosionHooks;
import me.shedaniel.architectury.platform.Platform;
import me.shedaniel.architectury.test.debug.client.ClientOverlayMessageSink;
import me.shedaniel.architectury.test.debug.ConsoleMessageSink;
import me.shedaniel.architectury.test.debug.MessageSink;
import me.shedaniel.architectury.utils.Env;
import me.shedaniel.architectury.utils.EnvExecutor;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.core.Position;
import net.minecraft.core.Vec3i;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import java.util.Optional;
import static me.shedaniel.architectury.test.TestMod.SINK;
public class DebugEvents {
public static void initialize() {
debugEvents();
if (Platform.getEnvironment() == Env.CLIENT)
debugEventsClient();
}
public static void debugEvents() {
ChatEvent.SERVER.register((player, message, component) -> {
SINK.accept("Server chat received: " + message);
return InteractionResultHolder.pass(component);
});
CommandPerformEvent.EVENT.register(event -> {
SINK.accept("Server command performed: " + event.getResults().getReader().getString());
return InteractionResult.PASS;
});
CommandRegistrationEvent.EVENT.register((dispatcher, selection) -> {
SINK.accept("Server commands registers");
});
EntityEvent.LIVING_DEATH.register((entity, source) -> {
if (entity instanceof Player) {
SINK.accept(entity.getScoreboardName() + " died to " + source.getMsgId() + logSide(entity.level));
}
return InteractionResult.PASS;
});
EntityEvent.LIVING_ATTACK.register((entity, source, amount) -> {
if (source.getDirectEntity() instanceof Player) {
SINK.accept(source.getDirectEntity().getScoreboardName() + " deals %.2f damage" + logSide(entity.level), amount);
}
return InteractionResult.PASS;
});
EntityEvent.ADD.register((entity, level) -> {
if (entity instanceof Player) {
SINK.accept(entity.getScoreboardName() + " was added to " + level.dimension().location().toString() + logSide(level));
}
return InteractionResult.PASS;
});
EntityEvent.PLACE_BLOCK.register((world, pos, state, placer) -> {
SINK.accept(Optional.ofNullable(placer).map(Entity::getScoreboardName).orElse("null") + " places block at " + toShortString(pos) + logSide(world));
return InteractionResult.PASS;
});
ExplosionEvent.DETONATE.register((world, explosion, affectedEntities) -> {
SINK.accept(world.dimension().location() + " explodes at " + toShortString(ExplosionHooks.getPosition(explosion)) + logSide(world));
});
InteractionEvent.LEFT_CLICK_BLOCK.register((player, hand, pos, face) -> {
SINK.accept(player.getScoreboardName() + " left clicks " + toShortString(pos) + logSide(player.level));
return InteractionResult.PASS;
});
InteractionEvent.RIGHT_CLICK_BLOCK.register((player, hand, pos, face) -> {
SINK.accept(player.getScoreboardName() + " right clicks " + toShortString(pos) + logSide(player.level));
return InteractionResult.PASS;
});
InteractionEvent.RIGHT_CLICK_ITEM.register((player, hand) -> {
SINK.accept(player.getScoreboardName() + " uses " + (hand == InteractionHand.MAIN_HAND ? "main hand" : "off hand") + logSide(player.level));
return InteractionResultHolder.pass(player.getItemInHand(hand));
});
InteractionEvent.INTERACT_ENTITY.register((player, entity, hand) -> {
SINK.accept(player.getScoreboardName() + " interacts with " + entity.getScoreboardName() + " using " + (hand == InteractionHand.MAIN_HAND ? "main hand" : "off hand") + logSide(player.level));
return InteractionResult.PASS;
});
LifecycleEvent.SERVER_BEFORE_START.register(instance -> {
SINK.accept("Server ready to start");
});
LifecycleEvent.SERVER_STARTING.register(instance -> {
SINK.accept("Server starting");
});
LifecycleEvent.SERVER_STARTED.register(instance -> {
SINK.accept("Server started");
});
LifecycleEvent.SERVER_STOPPING.register(instance -> {
SINK.accept("Server stopping");
});
LifecycleEvent.SERVER_STOPPED.register(instance -> {
SINK.accept("Server stopped");
});
LifecycleEvent.SERVER_WORLD_LOAD.register(instance -> {
SINK.accept("Server world loaded: " + instance.dimension().location());
});
LifecycleEvent.SERVER_WORLD_UNLOAD.register(instance -> {
SINK.accept("Server world unloaded: " + instance.dimension().location());
});
LifecycleEvent.SERVER_WORLD_SAVE.register(instance -> {
SINK.accept("Server world saved: " + instance.dimension().location());
});
PlayerEvent.PLAYER_JOIN.register(player -> {
SINK.accept(player.getScoreboardName() + " joined" + logSide(player.level));
});
PlayerEvent.PLAYER_QUIT.register(player -> {
SINK.accept(player.getScoreboardName() + " quit" + logSide(player.level));
});
PlayerEvent.PLAYER_RESPAWN.register((player, conqueredEnd) -> {
if (!conqueredEnd) {
SINK.accept(player.getScoreboardName() + " respawns " + logSide(player.level));
}
});
PlayerEvent.PLAYER_CLONE.register((oldPlayer, newPlayer, wonGame) -> {
SINK.accept("Player cloned: " + newPlayer.getScoreboardName() + logSide(newPlayer.level));
});
PlayerEvent.PLAYER_ADVANCEMENT.register((player, advancement) -> {
SINK.accept(player.getScoreboardName() + " was awarded with %s" + logSide(player.level), advancement.getChatComponent().getString());
});
PlayerEvent.CRAFT_ITEM.register((player, constructed, inventory) -> {
SINK.accept(player.getScoreboardName() + " crafts " + new TranslatableComponent(constructed.getDescriptionId()).getString() + logSide(player.level));
});
PlayerEvent.SMELT_ITEM.register((player, smelted) -> {
SINK.accept(player.getScoreboardName() + " smelts " + new TranslatableComponent(smelted.getDescriptionId()).getString() + logSide(player.level));
});
PlayerEvent.PICKUP_ITEM_POST.register((player, entity, stack) -> {
SINK.accept(player.getScoreboardName() + " picks up " + new TranslatableComponent(stack.getDescriptionId()).getString() + logSide(player.level));
});
PlayerEvent.DROP_ITEM.register((player, entity) -> {
SINK.accept(player.getScoreboardName() + " drops " + new TranslatableComponent(entity.getItem().getDescriptionId()).getString() + logSide(player.level));
return InteractionResult.PASS;
});
PlayerEvent.BREAK_BLOCK.register((world, pos, state, player, xp) -> {
SINK.accept(player.getScoreboardName() + " breaks " + toShortString(pos) + logSide(player.level));
return InteractionResult.PASS;
});
PlayerEvent.OPEN_MENU.register((player, menu) -> {
SINK.accept(player.getScoreboardName() + " opens " + toSimpleName(menu) + logSide(player.level));
});
PlayerEvent.CLOSE_MENU.register((player, menu) -> {
SINK.accept(player.getScoreboardName() + " closes " + toSimpleName(menu) + logSide(player.level));
});
}
public static String toShortString(Vec3i pos) {
return pos.getX() + ", " + pos.getY() + ", " + pos.getZ();
}
public static String toShortString(Position pos) {
return pos.x() + ", " + pos.y() + ", " + pos.z();
}
public static String logSide(Level level) {
if (level.isClientSide())
return " (client)";
return " (server)";
}
@Environment(EnvType.CLIENT)
public static void debugEventsClient() {
ClientChatEvent.CLIENT.register(message -> {
SINK.accept("Client chat sent: " + message);
return InteractionResultHolder.pass(message);
});
ClientChatEvent.CLIENT_RECEIVED.register((type, message, sender) -> {
SINK.accept("Client chat received: " + message.getString());
return InteractionResultHolder.pass(message);
});
ClientLifecycleEvent.CLIENT_WORLD_LOAD.register(world -> {
SINK.accept("Client world loaded: " + world.dimension().location().toString());
});
ClientPlayerEvent.CLIENT_PLAYER_JOIN.register(player -> {
SINK.accept(player.getScoreboardName() + " joined (client)");
});
ClientPlayerEvent.CLIENT_PLAYER_QUIT.register(player -> {
if (player != null) {
SINK.accept(player.getScoreboardName() + " quit (client)");
}
});
ClientPlayerEvent.CLIENT_PLAYER_RESPAWN.register((oldPlayer, newPlayer) -> {
SINK.accept(newPlayer.getScoreboardName() + " respawned (client)");
});
GuiEvent.INIT_PRE.register((screen, widgets, children) -> {
SINK.accept(toSimpleName(screen) + " initializes");
return InteractionResult.PASS;
});
InteractionEvent.CLIENT_LEFT_CLICK_AIR.register((player, hand) -> {
SINK.accept(player.getScoreboardName() + " left clicks air" + logSide(player.level));
});
InteractionEvent.CLIENT_RIGHT_CLICK_AIR.register((player, hand) -> {
SINK.accept(player.getScoreboardName() + " right clicks air" + logSide(player.level));
});
RecipeUpdateEvent.EVENT.register(recipeManager -> {
SINK.accept("Client recipes received");
});
TextureStitchEvent.POST.register(atlas -> {
SINK.accept("Client texture stitched: " + atlas.location());
});
ClientScreenInputEvent.MOUSE_SCROLLED_PRE.register((client, screen, mouseX, mouseY, amount) -> {
SINK.accept("Screen Mouse amount: %.2f distance", amount);
return InteractionResult.PASS;
});
ClientScreenInputEvent.MOUSE_CLICKED_PRE.register((client, screen, mouseX, mouseY, button) -> {
SINK.accept("Screen Mouse clicked: " + button);
return InteractionResult.PASS;
});
ClientScreenInputEvent.MOUSE_RELEASED_PRE.register((client, screen, mouseX, mouseY, button) -> {
SINK.accept("Screen Mouse released: " + button);
return InteractionResult.PASS;
});
ClientScreenInputEvent.MOUSE_DRAGGED_PRE.register((client, screen, mouseX1, mouseY1, button, mouseX2, mouseY2) -> {
SINK.accept("Screen Mouse dragged: %d (%d,%d) by (%d,%d)", button, (int) mouseX1, (int) mouseY1, (int) mouseX2, (int) mouseY2);
return InteractionResult.PASS;
});
ClientScreenInputEvent.CHAR_TYPED_PRE.register((client, screen, character, keyCode) -> {
SINK.accept("Screen Char typed: " + character);
return InteractionResult.PASS;
});
ClientScreenInputEvent.KEY_PRESSED_PRE.register((client, screen, keyCode, scanCode, modifiers) -> {
SINK.accept("Screen Key pressed: " + InputConstants.getKey(keyCode, scanCode).getDisplayName().getString());
return InteractionResult.PASS;
});
ClientScreenInputEvent.KEY_RELEASED_PRE.register((client, screen, keyCode, scanCode, modifiers) -> {
SINK.accept("Screen Key released: " + InputConstants.getKey(keyCode, scanCode).getDisplayName().getString());
return InteractionResult.PASS;
});
}
private static String toSimpleName(Object o) {
return o.getClass().getSimpleName() + "@" + Integer.toHexString(o.hashCode());
}
}

View File

@@ -0,0 +1,28 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.test.debug;
public interface MessageSink {
void accept(String message);
default void accept(String message, Object... args) {
accept(String.format(message, args));
}
}

View File

@@ -0,0 +1,104 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.test.debug.client;
import com.google.common.collect.Lists;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import me.shedaniel.architectury.event.events.GuiEvent;
import me.shedaniel.architectury.test.debug.ConsoleMessageSink;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.util.Mth;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@Environment(EnvType.CLIENT)
public class ClientOverlayMessageSink extends ConsoleMessageSink {
private final List<Message> messages = Collections.synchronizedList(Lists.newArrayList());
public ClientOverlayMessageSink() {
GuiEvent.RENDER_POST.register((screen, matrices, mouseX, mouseY, delta) -> render(matrices, delta));
GuiEvent.RENDER_HUD.register((matrices, tickDelta) -> {
if (Minecraft.getInstance().screen == null && !Minecraft.getInstance().options.renderDebug) {
render(matrices, tickDelta);
}
});
}
@Override
public void accept(String message) {
super.accept(message);
messages.add(0, new Message(new TextComponent(message), Util.getMillis()));
}
public void render(PoseStack matrices, float delta) {
matrices.pushPose();
matrices.scale(0.5f, 0.5f, 1f);
Minecraft minecraft = Minecraft.getInstance();
long currentMills = Util.getMillis();
int lineHeight = minecraft.font.lineHeight;
synchronized (messages) {
Iterator<Message> messageIterator = messages.iterator();
int y = 1;
RenderSystem.enableBlend();
while (messageIterator.hasNext()) {
Message message = messageIterator.next();
int timeExisted = (int) (currentMills - message.created);
if (timeExisted >= 5000) {
messageIterator.remove();
} else {
if (y - 1 < minecraft.getWindow().getGuiScaledHeight()) {
int textWidth = minecraft.font.width(message.text);
int alpha = (int) Mth.clamp((5000 - timeExisted) / 5000f * 400f + 8, 0, 255);
GuiComponent.fill(matrices, 0, y - 1, 2 + textWidth + 1, y + lineHeight - 1, 0x505050 + ((alpha * 144 / 255) << 24));
minecraft.font.draw(matrices, message.text, 1, y, 0xE0E0E0 + (alpha << 24));
}
y += lineHeight;
}
}
}
RenderSystem.disableAlphaTest();
RenderSystem.disableBlend();
matrices.popPose();
}
private static class Message {
private final Component text;
private final long created;
public Message(Component text, long created) {
this.text = text;
this.created = created;
}
}
}

View File

@@ -0,0 +1,49 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.test.registry;
import me.shedaniel.architectury.registry.BlockProperties;
import me.shedaniel.architectury.registry.DeferredRegister;
import me.shedaniel.architectury.registry.RegistrySupplier;
import me.shedaniel.architectury.test.TestMod;
import me.shedaniel.architectury.test.tab.TestCreativeTabs;
import net.minecraft.core.Registry;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
public class TestRegistries {
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(TestMod.MOD_ID, Registry.ITEM_REGISTRY);
public static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(TestMod.MOD_ID, Registry.BLOCK_REGISTRY);
public static final RegistrySupplier<Item> TEST_ITEM = ITEMS.register("test_item", () ->
new Item(new Item.Properties().tab(TestCreativeTabs.TEST_TAB)));
public static final RegistrySupplier<Block> TEST_BLOCK = BLOCKS.register("test_block", () ->
new Block(BlockProperties.copy(Blocks.STONE)));
public static final RegistrySupplier<Item> TEST_BLOCK_ITEM = ITEMS.register("test_block", () ->
new BlockItem(TEST_BLOCK.get(), new Item.Properties().tab(TestCreativeTabs.TEST_TAB)));
public static void initialize() {
BLOCKS.register();
ITEMS.register();
}
}

View File

@@ -0,0 +1,43 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.test.registry.client;
import com.mojang.blaze3d.platform.InputConstants;
import me.shedaniel.architectury.event.events.client.ClientTickEvent;
import me.shedaniel.architectury.registry.KeyBindings;
import me.shedaniel.architectury.test.TestMod;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.resources.language.I18n;
import org.lwjgl.glfw.GLFW;
public class TestKeybinds {
@Environment(EnvType.CLIENT)
public static void initialize() {
KeyMapping mapping = new KeyMapping("key.architectury-test.test", InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_O, "category.architectury-test");
KeyBindings.registerKeyBinding(mapping);
ClientTickEvent.CLIENT_POST.register(instance -> {
while (mapping.consumeClick()) {
TestMod.SINK.accept("Key \"%s\" pressed!", I18n.get("key.architectury-test.test"));
}
});
}
}

View File

@@ -0,0 +1,32 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021 shedaniel
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package me.shedaniel.architectury.test.tab;
import me.shedaniel.architectury.registry.CreativeTabs;
import me.shedaniel.architectury.test.TestMod;
import me.shedaniel.architectury.test.registry.TestRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
public class TestCreativeTabs {
public static final CreativeModeTab TEST_TAB = CreativeTabs.create(new ResourceLocation(TestMod.MOD_ID, "test_tab"),
() -> new ItemStack(TestRegistries.TEST_ITEM.get()));
}

View File

@@ -0,0 +1,4 @@
{
"category.architectury-test": "Architectury Test",
"key.architectury-test.test": "Test Keybind"
}