Skip to content

Commit

Permalink
完成跨服菜单
Browse files Browse the repository at this point in the history
  • Loading branch information
Sunshine-wzy committed Dec 1, 2023
1 parent 4bd0f3c commit bc7be1a
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 17 deletions.
8 changes: 3 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ repositories {
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories.

maven { url 'https://maven.nucleoid.xyz' }
}

loom {
Expand All @@ -27,7 +29,6 @@ loom {
sourceSet sourceSets.client
}
}

}

dependencies {
Expand All @@ -38,11 +39,8 @@ dependencies {

// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"

// Uncomment the following line to enable the deprecated Fabric API modules.
// These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time.

// modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}"
modImplementation include("eu.pb4:sgui:1.2.2+1.20")
}

processResources {
Expand Down
4 changes: 1 addition & 3 deletions src/client/resources/modid.client.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
"required": true,
"package": "io.github.sunshinewzy.serverconductor.fabric.mixin.client",
"compatibilityLevel": "JAVA_17",
"client": [
"ExampleClientMixin"
],
"client": [],
"injectors": {
"defaultRequire": 1
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package io.github.sunshinewzy.serverconductor.fabric;

import eu.pb4.sgui.api.elements.GuiElementBuilder;
import eu.pb4.sgui.api.gui.SimpleGui;
import net.minecraft.item.Items;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;

import java.util.List;

public class ConductorGameMenu extends SimpleGui {

private static final GuiElementBuilder EDGE = new GuiElementBuilder(Items.GRAY_STAINED_GLASS_PANE).setName(Text.of(" "));
private static final GuiElementBuilder itemGameBingo = new GuiElementBuilder(Items.MAP)
.setName(Text.literal("宾果小游戏 - Bingo").formatted(Formatting.GREEN))
.setLore(List.of(Text.empty(), Text.of("一种原版生存竞赛小游戏"), Text.of("玩家需要通过探索,采掘,搏斗"), Text.of("与合成来收集Bingo卡片上的物品")))
.setCallback((index, clickType, action, gui) -> ConductorMenu.switchServer(gui.getPlayer(), "bingo"));
private static final GuiElementBuilder itemGameSkywar = new GuiElementBuilder(Items.ENDER_EYE)
.setName(Text.literal("空岛战争 - Skywar").formatted(Formatting.YELLOW))
.setLore(List.of(Text.empty(), Text.of("一种多人PvP小游戏"), Text.of("玩家在各自的空岛上开始游戏"), Text.of("收集资源,并彼此交战"), Text.of("努力活到最后吧!")))
.setCallback((index, clickType, action, gui) -> ConductorMenu.switchServer(gui.getPlayer(), "skywar"));


/**
* Constructs a conductor game menu for the supplied player.
*
* @param player the player to server this gui to
*/
public ConductorGameMenu(ServerPlayerEntity player) {
super(ScreenHandlerType.GENERIC_9X3, player, false);
setTitle(Text.of("选择小游戏服"));

for (int i = 0; i <= 9; i++)
setSlot(i, EDGE);
for (int i = 17; i <= 26; i++)
setSlot(i, EDGE);

setSlot(12, itemGameBingo);
setSlot(14, itemGameSkywar);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package io.github.sunshinewzy.serverconductor.fabric;

import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import eu.pb4.sgui.api.elements.GuiElementBuilder;
import eu.pb4.sgui.api.gui.SimpleGui;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.item.Items;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
import org.jetbrains.annotations.NotNull;

import java.util.List;

public class ConductorMenu extends SimpleGui {

private static final GuiElementBuilder EDGE = new GuiElementBuilder(Items.GRAY_STAINED_GLASS_PANE).setName(Text.of(" "));
private static final GuiElementBuilder itemSurvival = new GuiElementBuilder(Items.STONE_PICKAXE)
.setName(Text.literal("生存服 - Survival").formatted(Formatting.GREEN))
.setLore(List.of(Text.empty(), Text.of("1.20.1 普通生存服"), Text.of("(首次进服默认进入生存服)")))
.setCallback((index, clickType, action, gui) -> switchServer(gui.getPlayer(), "s"));
private static final GuiElementBuilder itemMirror = new GuiElementBuilder(Items.GLASS)
.setName(Text.literal("镜像服 - Mirror").formatted(Formatting.AQUA))
.setLore(List.of(Text.empty(), Text.of("1.20.1 生存服的镜像"), Text.of("创造模式!想干什么就干什么")))
.setCallback((index, clickType, action, gui) -> switchServer(gui.getPlayer(), "m"));
private static final GuiElementBuilder itemCreative = new GuiElementBuilder(Items.CRAFTING_TABLE)
.setName(Text.literal("创造服 - Creative").formatted(Formatting.YELLOW))
.setLore(List.of(Text.empty(), Text.of("1.20.1 超平坦"), Text.of("创造模式!建筑基地与红石实验室!")))
.setCallback((index, clickType, action, gui) -> switchServer(gui.getPlayer(), "c"));
private static final GuiElementBuilder itemIsland = new GuiElementBuilder(Items.OAK_SAPLING)
.setName(Text.literal("空岛服 - Island").formatted(Formatting.GREEN))
.setLore(List.of(Text.empty(), Text.of("1.17.1 空岛"), Text.of("有丰富的成就系统,推荐给萌新~")))
.setCallback((index, clickType, action, gui) -> switchServer(gui.getPlayer(), "i"));
private static final GuiElementBuilder itemArchitecture = new GuiElementBuilder(Items.STONE_BRICKS)
.setName(Text.literal("建筑服 - Architecture").formatted(Formatting.GOLD))
.setLore(List.of(Text.empty(), Text.of("1.20.1 地皮世界"), Text.of("创造!可以领取一块自己的领地!")))
.setCallback((index, clickType, action, gui) -> switchServer(gui.getPlayer(), "ar"));
private static final GuiElementBuilder itemForbiddenCity = new GuiElementBuilder(Items.BRICKS)
.setName(Text.literal("故宫服 - Forbidden City").formatted(Formatting.LIGHT_PURPLE))
.setLore(List.of(Text.empty(), Text.of("1.20.1 故宫"), Text.of("重檐翠瓦缀天绫,砌玉楼栏嵌彩龙!")))
.setCallback((index, clickType, action, gui) -> switchServer(gui.getPlayer(), "fc"));
private static final GuiElementBuilder itemTest = new GuiElementBuilder(Items.STICK)
.setName(Text.literal("测试服 - Test").formatted(Formatting.RED))
.setLore(List.of(Text.empty(), Text.of("1.20.1 进行功能测试"), Text.of("用来整活的")))
.setCallback((index, clickType, action, gui) -> switchServer(gui.getPlayer(), "t"));
private static final GuiElementBuilder itemGame = new GuiElementBuilder(Items.SLIME_BALL)
.setName(Text.literal("小游戏服 - Game").formatted(Formatting.GREEN))
.setLore(List.of(Text.empty(), Text.of("1.20.1 小游戏"), Text.of("含有bingo和skywar等小游戏")))
.setCallback((index, clickType, action, gui) -> new ConductorGameMenu(gui.getPlayer()).open());


/**
* Constructs a conductor menu for the supplied player.
*
* @param player the player to server this gui to
*/
public ConductorMenu(ServerPlayerEntity player) {
super(ScreenHandlerType.GENERIC_9X5, player, false);
setTitle(Text.of("选择子服"));

for (int i = 0; i <= 8; i++)
setSlot(i, EDGE);
for (int i = 36; i <= 44; i++)
setSlot(i, EDGE);
int[] otherEdges = new int[]{9, 17, 18, 26, 27, 35};
for (int i : otherEdges)
setSlot(i, EDGE);

setSlot(11, itemSurvival);
setSlot(13, itemMirror);
setSlot(15, itemCreative);
setSlot(20, itemIsland);
setSlot(22, itemArchitecture);
setSlot(24, itemForbiddenCity);
setSlot(30, itemTest);
setSlot(32, itemGame);
}

@SuppressWarnings("UnstableApiUsage")
public static void switchServer(@NotNull ServerPlayerEntity player, @NotNull String server) {
PacketByteBuf packetBuf = PacketByteBufs.create();
ByteArrayDataOutput output = ByteStreams.newDataOutput();
output.writeUTF(server);
packetBuf.writeBytes(output.toByteArray());
ServerPlayNetworking.send(player, new Identifier("server_conductor:switch"), packetBuf);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.github.sunshinewzy.serverconductor.fabric;

import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtList;
import net.minecraft.nbt.NbtString;
import net.minecraft.text.Text;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class ItemUtils {

@NotNull
public static NbtCompound getOrCreateDisplay(@NotNull ItemStack item) {
return item.getOrCreateSubNbt(ItemStack.DISPLAY_KEY);
}

public static void setItemName(@NotNull ItemStack item, @NotNull Text name) {
if (name.getString().isEmpty()) getOrCreateDisplay(item).remove(ItemStack.NAME_KEY);
else getOrCreateDisplay(item).putString(ItemStack.NAME_KEY, Text.Serializer.toJson(name));
}

public static void setItemLore(@NotNull ItemStack item, @Nullable Text[] lore) {
if (lore == null || lore.length == 0) {
getOrCreateDisplay(item).remove(ItemStack.LORE_KEY);
return;
}

NbtList list = new NbtList();
for (Text text : lore) {
list.add(NbtString.of(Text.Serializer.toJson(text)));
}
getOrCreateDisplay(item).put(ItemStack.LORE_KEY, list);
}

}
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package io.github.sunshinewzy.serverconductor.fabric;

import net.fabricmc.api.ModInitializer;

import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.minecraft.server.network.ServerPlayerEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static net.minecraft.server.command.CommandManager.literal;


public class ServerConductor implements ModInitializer {
// This logger is used to write text to the console and the log file.
// It is considered best practice to use your mod id as the logger's name.
Expand All @@ -16,7 +20,14 @@ public void onInitialize() {
// This code runs as soon as Minecraft is in a mod-load-ready state.
// However, some things (like resources) may still be uninitialized.
// Proceed with mild caution.
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(literal("ser")
.executes(context -> {
ServerPlayerEntity player = context.getSource().getPlayer();
if (player == null) return 0;
new ConductorMenu(player).open();
return 1;
})));

LOGGER.info("Hello Fabric world!");
LOGGER.info("Successfully running ServerConductorFabric!");
}
}
5 changes: 1 addition & 4 deletions src/main/resources/fabric.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@
"entrypoints": {
"main": [
"io.github.sunshinewzy.serverconductor.fabric.ServerConductor"
],
"client": [
"io.github.sunshinewzy.serverconductor.fabric.ServerConductorClient"
]
},
"mixins": [
Expand All @@ -30,7 +27,7 @@
}
],
"depends": {
"fabricloader": ">=0.14.25",
"fabricloader": ">=0.14.21",
"minecraft": "~1.20.1",
"java": ">=17",
"fabric-api": "*"
Expand Down
4 changes: 1 addition & 3 deletions src/main/resources/modid.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
"required": true,
"package": "io.github.sunshinewzy.serverconductor.fabric.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"ExampleMixin"
],
"mixins": [],
"injectors": {
"defaultRequire": 1
}
Expand Down

0 comments on commit bc7be1a

Please sign in to comment.