basic stuff exist
TODO: wenn man das spiel leaved werden die Spawnpunkte gelöscht und wenn man einen spawnpunkt benutzt überschreibt das die vanilla Spawnfunktion
This commit is contained in:
parent
f58ffa9b65
commit
faedbb63ba
|
@ -1,6 +1,6 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
package modchest;
|
package modchest;
|
||||||
|
|
||||||
|
import modchest.networking.modNetworkingClient;
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import org.slf4j.Logger;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import org.slf4j.LoggerFactory;
|
||||||
import net.minecraft.text.Text;
|
|
||||||
|
|
||||||
public class REServerModClient implements ClientModInitializer {
|
public class REServerModClient implements ClientModInitializer {
|
||||||
@Override
|
public static final Logger LOGGER = LoggerFactory.getLogger("modchest"); // Erster Error Logger
|
||||||
public void onInitializeClient() {
|
@Override
|
||||||
// This entrypoint is suitable for setting up client-specific logic, such as rendering.
|
public void onInitializeClient() {
|
||||||
//EntitySleepEvents.START_SLEEPING.register(new entitySleepStartSleepingEventHandler());
|
// This entrypoint is suitable for setting up client-specific logic, such as rendering.
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeMessage(String text) { //holt den Spieler dieses Clients und sendet ihm eine Nachricht
|
modNetworkingClient.registerC2SPackets(); //Identifier unter denen der Client zuhoert werden registriert
|
||||||
PlayerEntity thisPlayer = MinecraftClient.getInstance().player;
|
|
||||||
assert thisPlayer != null;
|
LOGGER.info("Modchest successfully loaded!");
|
||||||
thisPlayer.sendMessage(Text.literal(text));
|
}
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package modchest.mixin.client;
|
||||||
|
|
||||||
|
import modchest.REServerModClient;
|
||||||
|
import modchest.networking.modNetworkingClient;
|
||||||
|
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(net.minecraft.client.gui.screen.DeathScreen.class)
|
||||||
|
public class DeathScreen extends Screen {
|
||||||
|
protected DeathScreen(Text title) {
|
||||||
|
super(Text.of("useless"));
|
||||||
|
} //Da wir einen bereits bestehenden Screen erweitern, wird dieser Text nie angezeigt
|
||||||
|
|
||||||
|
@Inject(method = "init", at = @At("TAIL")) //Dieser Code wird in den eigentlich bereits bestehenden Code der Klasse DeathScreen hinzugefügt
|
||||||
|
private void addMultiSleepButtons(CallbackInfo info) {;
|
||||||
|
int widthButton = 40; //Die generelle Breite der knoepfe wird definiert
|
||||||
|
int heightButton = 20; // " hoehe "
|
||||||
|
int yOffset = 5; //Wie gross der Abstand zwischen der oberen Kante un dem knop sein soll (der Nullpunkt (0|0) ist soswohl im Fenster als auch beim Knopf oben links die Ecke)
|
||||||
|
int xOffset = this.width / 2 - widthButton / 2; //Die Mitte wird ausgerechnet (Mitte vom fenster minus halbe Breite des knopfes um tatsächlich die Mitte zu haben, weil koordinaten und so
|
||||||
|
this.addDrawableChild(
|
||||||
|
new ButtonWidget(xOffset - 2 * (widthButton + 5), yOffset, widthButton, heightButton, Text.translatable("#1"), button -> { //Knopf wird erzeugt
|
||||||
|
REServerModClient.LOGGER.info("First Button for using spawn pressed!");
|
||||||
|
PacketByteBuf buffer = PacketByteBufs.create(); //Neuer Buffer wird erstellt
|
||||||
|
buffer.writeInt(1); //Beschrieben, damit der Server weiss, welcher knopf gedrueckt wurde
|
||||||
|
sendPacket(buffer); //Und an den Server gesendet zum Speichern; Die gesamte logik passiert auf dem server, damit man keien fake koordinaten oder so eingeben kann
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this.addDrawableChild(
|
||||||
|
new ButtonWidget(xOffset - (widthButton + 5), yOffset, widthButton, heightButton, Text.translatable("#2"), button -> { //Kommentare siehe knopf #1
|
||||||
|
REServerModClient.LOGGER.info("Second Button for using spawn pressed!");
|
||||||
|
PacketByteBuf buffer = PacketByteBufs.create();
|
||||||
|
buffer.writeInt(2);
|
||||||
|
sendPacket(buffer);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this.addDrawableChild(
|
||||||
|
new ButtonWidget(xOffset, yOffset, widthButton, heightButton, Text.translatable("#3"), button -> { //Kommentare siehe knopf #1
|
||||||
|
REServerModClient.LOGGER.info("Third Button for using spawn pressed!");
|
||||||
|
PacketByteBuf buffer = PacketByteBufs.create();
|
||||||
|
buffer.writeInt(3);
|
||||||
|
sendPacket(buffer);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this.addDrawableChild(
|
||||||
|
new ButtonWidget(xOffset + (widthButton + 5), yOffset, widthButton, heightButton, Text.translatable("#4"), button -> { //Kommentare siehe knopf #1
|
||||||
|
REServerModClient.LOGGER.info("Fourth Button for using spawn pressed!");
|
||||||
|
PacketByteBuf buffer = PacketByteBufs.create();
|
||||||
|
buffer.writeInt(4);
|
||||||
|
sendPacket(buffer);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this.addDrawableChild(
|
||||||
|
new ButtonWidget(xOffset + 2 * (widthButton + 5), yOffset, widthButton, heightButton, Text.translatable("#5"), button -> { //Kommentare siehe knopf #1
|
||||||
|
REServerModClient.LOGGER.info("Fifth Button for using spawn pressed!");
|
||||||
|
PacketByteBuf buffer = PacketByteBufs.create();
|
||||||
|
buffer.writeInt(5);
|
||||||
|
sendPacket(buffer);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private synchronized void sendPacket(PacketByteBuf buffer) {
|
||||||
|
try {
|
||||||
|
ClientPlayNetworking.send(modNetworkingClient.death_multi_respawn_buttons, buffer);
|
||||||
|
} catch (Exception e) {}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +0,0 @@
|
||||||
package modchest.mixin.client;
|
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
@Mixin(MinecraftClient.class)
|
|
||||||
public class ExampleClientMixin {
|
|
||||||
@Inject(at = @At("HEAD"), method = "run")
|
|
||||||
private void run(CallbackInfo info) {
|
|
||||||
// This code is injected into the start of MinecraftClient.run()V
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
package modchest.mixin.client;
|
||||||
|
|
||||||
|
import modchest.REServerModClient;
|
||||||
|
import modchest.networking.modNetworkingClient;
|
||||||
|
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(net.minecraft.client.gui.screen.SleepingChatScreen.class)
|
||||||
|
public class SleepingChatScreen extends Screen { //Sehr identisch zu Death Screen, siehe dort fuer Kommentare!!
|
||||||
|
protected SleepingChatScreen(Text title) {
|
||||||
|
super(Text.of("useless"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "init", at = @At("TAIL"))
|
||||||
|
private void addMultiSleepButtons(CallbackInfo info) {
|
||||||
|
int widthButton = 40;
|
||||||
|
int heightButton = 20;
|
||||||
|
int yOffset = 5;
|
||||||
|
int xOffset = this.width / 2 - widthButton / 2;
|
||||||
|
this.addDrawableChild(
|
||||||
|
new ButtonWidget(xOffset - 2 * (widthButton + 5), yOffset, widthButton, heightButton, Text.translatable("#1"), button -> {
|
||||||
|
REServerModClient.LOGGER.info("First Button for saving spawn pressed!");
|
||||||
|
PacketByteBuf buffer = PacketByteBufs.create();
|
||||||
|
buffer.writeInt(1);
|
||||||
|
sendPacket(buffer);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this.addDrawableChild(
|
||||||
|
new ButtonWidget(xOffset - (widthButton + 5), yOffset, widthButton, heightButton, Text.translatable("#2"), button -> {
|
||||||
|
REServerModClient.LOGGER.info("Second Button for saving spawn pressed!");
|
||||||
|
PacketByteBuf buffer = PacketByteBufs.create();
|
||||||
|
buffer.writeInt(2);
|
||||||
|
sendPacket(buffer);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this.addDrawableChild(
|
||||||
|
new ButtonWidget(xOffset, yOffset, widthButton, heightButton, Text.translatable("#3"), button -> {
|
||||||
|
REServerModClient.LOGGER.info("Third Button for saving spawn pressed!");
|
||||||
|
PacketByteBuf buffer = PacketByteBufs.create();
|
||||||
|
buffer.writeInt(3);
|
||||||
|
sendPacket(buffer);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this.addDrawableChild(
|
||||||
|
new ButtonWidget(xOffset + (widthButton + 5), yOffset, widthButton, heightButton, Text.translatable("#4"), button -> {
|
||||||
|
REServerModClient.LOGGER.info("Fourth Button for saving spawn pressed!");
|
||||||
|
PacketByteBuf buffer = PacketByteBufs.create();
|
||||||
|
buffer.writeInt(4);
|
||||||
|
sendPacket(buffer);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
this.addDrawableChild(
|
||||||
|
new ButtonWidget(xOffset + 2 * (widthButton + 5), yOffset, widthButton, heightButton, Text.translatable("#5"), button -> {
|
||||||
|
REServerModClient.LOGGER.info("Fifth Button for saving spawn pressed!");
|
||||||
|
PacketByteBuf buffer = PacketByteBufs.create();
|
||||||
|
buffer.writeInt(5);
|
||||||
|
sendPacket(buffer);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unique
|
||||||
|
private synchronized void sendPacket(PacketByteBuf buffer) {
|
||||||
|
try {
|
||||||
|
ClientPlayNetworking.send(modNetworkingClient.start_sleeping_call_buttons, buffer);
|
||||||
|
} catch (Exception e) {}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package modchest.networking;
|
||||||
|
|
||||||
|
import modchest.REServerMod;
|
||||||
|
import modchest.networking.packet.respawnRequestS2CPacket;
|
||||||
|
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
public class modNetworkingClient { //Identifier werden eingeführt
|
||||||
|
public static final Identifier request_respawn = new Identifier(REServerMod.MOD_ID, "request_respawn"); //alle Identifier muessen leider IMMER auf Client und Server (doppelt) eingefuehrt werden
|
||||||
|
public static final Identifier start_sleeping_call_buttons = new Identifier(REServerMod.MOD_ID, "start_sleeping_call_buttons");
|
||||||
|
public static final Identifier death_multi_respawn_buttons = new Identifier(REServerMod.MOD_ID, "death_call_respawn_buttons");
|
||||||
|
public static void registerC2SPackets() { //Identifier fuer packets werden registriert (Identifier die der Server aufruft um beim CLient was auszufuehren)
|
||||||
|
ClientPlayNetworking.registerGlobalReceiver(request_respawn, respawnRequestS2CPacket::receive); //was der Client dann machen soll steht in der receive Methode
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package modchest.networking.packet;
|
||||||
|
|
||||||
|
import modchest.REServerModClient;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
|
||||||
|
public class respawnRequestS2CPacket {
|
||||||
|
|
||||||
|
public static void receive(MinecraftClient minecraftClient, ClientPlayNetworkHandler clientPlayNetworkHandler, PacketByteBuf packetByteBuf, PacketSender packetSender) {
|
||||||
|
REServerModClient.LOGGER.info("Server asked for respawn after pressing a saved respawn button!");
|
||||||
|
minecraftClient.player.requestRespawn();
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,9 +3,12 @@
|
||||||
"package": "modchest.mixin.client",
|
"package": "modchest.mixin.client",
|
||||||
"compatibilityLevel": "JAVA_17",
|
"compatibilityLevel": "JAVA_17",
|
||||||
"client": [
|
"client": [
|
||||||
"ExampleClientMixin"
|
"DeathScreen",
|
||||||
|
"SleepingChatScreen"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
}
|
},
|
||||||
|
"mixins": [
|
||||||
|
]
|
||||||
}
|
}
|
|
@ -5,6 +5,7 @@ import modchest.block.modBlocks;
|
||||||
import modchest.event.entitySleepStartSleepingEventHandler;
|
import modchest.event.entitySleepStartSleepingEventHandler;
|
||||||
import modchest.item.modItemGroup;
|
import modchest.item.modItemGroup;
|
||||||
import modchest.item.modItems;
|
import modchest.item.modItems;
|
||||||
|
import modchest.networking.modNetworkingServer;
|
||||||
import net.fabricmc.api.ModInitializer;
|
import net.fabricmc.api.ModInitializer;
|
||||||
import net.fabricmc.fabric.api.entity.event.v1.EntitySleepEvents;
|
import net.fabricmc.fabric.api.entity.event.v1.EntitySleepEvents;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -23,7 +24,8 @@ public class REServerMod implements ModInitializer {
|
||||||
modBlocks.setBlocks(); // Hier werden die Blöcke erstellt
|
modBlocks.setBlocks(); // Hier werden die Blöcke erstellt
|
||||||
modBlockEntities.registerBlockEntities(); // Die Interaktionsmenüs für die Blöcke werden erstellt
|
modBlockEntities.registerBlockEntities(); // Die Interaktionsmenüs für die Blöcke werden erstellt
|
||||||
EntitySleepEvents.START_SLEEPING.register(new entitySleepStartSleepingEventHandler());
|
EntitySleepEvents.START_SLEEPING.register(new entitySleepStartSleepingEventHandler());
|
||||||
|
modNetworkingServer.registerS2CPackets(); //Identifier unter denen der Server zuhoert werden registriert
|
||||||
|
|
||||||
LOGGER.info("Modchest erfolgreich geladen!");
|
LOGGER.info("Modchest successfully loaded!");
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,17 @@
|
||||||
package modchest.event;
|
package modchest.event;
|
||||||
|
|
||||||
|
import modchest.networking.modNetworkingServer;
|
||||||
import net.fabricmc.fabric.api.entity.event.v1.EntitySleepEvents;
|
import net.fabricmc.fabric.api.entity.event.v1.EntitySleepEvents;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
|
||||||
public class entitySleepStartSleepingEventHandler implements EntitySleepEvents.StartSleeping {
|
public class entitySleepStartSleepingEventHandler implements EntitySleepEvents.StartSleeping {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStartSleeping(LivingEntity entity, BlockPos sleepingPos) { //Methode die aufgerufen wird, wenn sich ein entity Hinlegt
|
public void onStartSleeping(LivingEntity entity, BlockPos sleepingPos) { //Methode die aufgerufen wird, wenn sich ein entity Hinlegt
|
||||||
if (entity instanceof PlayerEntity) { //ueberprueft ob das Entity ein Spieler ist
|
if (entity instanceof PlayerEntity) { //ueberprueft ob das Entity ein Spieler ist
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
package modchest.mixin;
|
|
||||||
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
@Mixin(MinecraftServer.class)
|
|
||||||
public class ExampleMixin {
|
|
||||||
@Inject(at = @At("HEAD"), method = "loadWorld")
|
|
||||||
private void init(CallbackInfo info) {
|
|
||||||
// This code is injected into the start of MinecraftServer.loadWorld()V
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
package modchest.mixin;
|
||||||
|
|
||||||
|
import modchest.util.ServerPlayerEntityInterface;
|
||||||
|
import net.minecraft.nbt.NbtCompound;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(ServerPlayerEntity.class)
|
||||||
|
public abstract class ServerPlayerEntityMixin implements ServerPlayerEntityInterface {
|
||||||
|
@Unique
|
||||||
|
private int[] dataSaver = new int [1]; //Weil die nbt daten beim tod geloescht werden, muessen sie rueber kopiert werden; der neue nbtTag existiert aber noch nciht, daher muessen sie hier zwischengespeichert werden
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getDataSaver() { //Um errors zu vermeiden, sorgt er dafuer, dass es immer ein persistentData gibt
|
||||||
|
if (this.dataSaver == null) {
|
||||||
|
this.dataSaver = new int[1];
|
||||||
|
}
|
||||||
|
return this.dataSaver;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDataSaver(int[] data) { //Um errors zu vermeiden, sorgt er dafuer, dass es immer ein persistentData gibt
|
||||||
|
this.dataSaver = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "writeCustomDataToNbt", at = @At("TAIL"))
|
||||||
|
public void writeCustomDataToNbt(NbtCompound nbt, CallbackInfo ci) { //Immer wenn eine andere Methode aufruft, dass Daten abgespeichert werden sollen, tun wir das jetzt auch
|
||||||
|
if (this.dataSaver.length == 15) {
|
||||||
|
nbt.putIntArray("REServerMod.sleep_data", this.dataSaver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "readCustomDataFromNbt", at = @At("TAIL"))
|
||||||
|
public void readCustomDataFromNbt(NbtCompound nbt, CallbackInfo ci) { //gleiches beim einlesen. Werden NBT-Daten eingelesen, tun wird das auch
|
||||||
|
if (dataSaver.length == 15) {
|
||||||
|
dataSaver = nbt.getIntArray("REServerMod.sleep_data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "copyFrom", at = @At("TAIL"))
|
||||||
|
public void copyFrom(ServerPlayerEntity oldPlayer, boolean alive, CallbackInfo ci) { //Beim Tod des Spielers werden die NBT-Daten kopiert, damit die Spawnpunkte nicht verloren gehen, kopieren wir sie auch mit rueber
|
||||||
|
dataSaver = ((ServerPlayerEntityInterface) oldPlayer).getDataSaver();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package modchest.networking;
|
||||||
|
|
||||||
|
import modchest.REServerMod;
|
||||||
|
import modchest.networking.packet.deathScreenMultiButtonsC2SPacket;
|
||||||
|
import modchest.networking.packet.setNewRespawnsC2SPacket;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
public class modNetworkingServer { //Identifier werden eingeführt
|
||||||
|
public static final Identifier request_respawn = new Identifier(REServerMod.MOD_ID, "request_respawn"); //alle Identifier muessen leider IMMER auf Client und Server (doppelt) eingefuehrt werden
|
||||||
|
public static final Identifier start_sleeping_call_buttons = new Identifier(REServerMod.MOD_ID, "start_sleeping_call_buttons");
|
||||||
|
public static final Identifier death_multi_respawn_buttons = new Identifier(REServerMod.MOD_ID, "death_call_respawn_buttons");
|
||||||
|
|
||||||
|
public static void registerS2CPackets() { //Identifier fuer packets werden registriert (Identifier die der Client aufruft um beim Server was auszufuehren)
|
||||||
|
ServerPlayNetworking.registerGlobalReceiver(start_sleeping_call_buttons, setNewRespawnsC2SPacket::receive); //was der Server dann machen soll steht in der receive Methode
|
||||||
|
|
||||||
|
ServerPlayNetworking.registerGlobalReceiver(death_multi_respawn_buttons, deathScreenMultiButtonsC2SPacket::receive);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package modchest.networking.packet;
|
||||||
|
|
||||||
|
import modchest.REServerMod;
|
||||||
|
import modchest.networking.modNetworkingServer;
|
||||||
|
import modchest.util.setAndGetMultiButtonsSpawn;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.registry.RegistryKey;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class deathScreenMultiButtonsC2SPacket {
|
||||||
|
public static void receive(MinecraftServer server, ServerPlayerEntity player, //Passiert auf dem Server!!!
|
||||||
|
ServerPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) {
|
||||||
|
setAndGetMultiButtonsSpawn setAndGet = new setAndGetMultiButtonsSpawn(); //um die nicht-statischen Methoden aufzurufen, erzeugen wir ein Objekt. Wir speichern aber keine Daten in der Klasse, daher ist das OK
|
||||||
|
int num; //num steht fuer Number, und sagt, welcher der 5 Knoepfe gedrueckt wurde, da das Spiel abstuertzt wenn man buf.readInt() mehr als einmal ausfuehrt
|
||||||
|
try {
|
||||||
|
num = buf.readInt(); //Um Spielabstuertze definitiv zu verhindern in einem try block, hat aber nie Probleme gemacht, also eine reine absicherung
|
||||||
|
} catch (Exception e) {
|
||||||
|
REServerMod.LOGGER.info("Following Error when trying to get the number of pressed Button: " + e + "continuing bwith Button 1");
|
||||||
|
num = 1;
|
||||||
|
}
|
||||||
|
BlockPos posAlt = player.getSpawnPointPosition(); //Spawnpunkt der Vanilla-respawn-funktion wird gespeichert
|
||||||
|
RegistryKey<World> dimAlt = player.getSpawnPointDimension();//Dimension "
|
||||||
|
float angleAlt = player.getSpawnAngle(); //Blickrichtung "
|
||||||
|
int[] posXYZ = setAndGet.getMultiSpawn(player, num); //neue Koordinaten werden vom Server geholt
|
||||||
|
|
||||||
|
if (posXYZ.length == 3 && posXYZ[0] < 77889900) { //Stellt sicher, dass die 3 spawnkoordinaten nicht null sind; Koordinaten 77889900 sind ausserhalb der Welt und werden daher von mir in setAndGetMultiSpawnButtonsSpawn als Errorcodes verwendet
|
||||||
|
try {
|
||||||
|
REServerMod.LOGGER.info("try Respawning from Multi-Sapwn");
|
||||||
|
player.setSpawnPoint(World.OVERWORLD, new BlockPos(posXYZ[0], posXYZ[1], posXYZ[2]), 0, true, true); //neuer Spawn wird gesetzt
|
||||||
|
ServerPlayNetworking.send(player, modNetworkingServer.request_respawn, PacketByteBufs.create()); //Anfrage an den Client zum respawnen wird gesendet
|
||||||
|
player.sendMessage(Text.of("Respawn bei #" + num + "! "));
|
||||||
|
REServerMod.LOGGER.info("Respawned Player: " + player.getDisplayName() + "at " + Arrays.toString(setAndGet.getMultiSpawn(player, num)));
|
||||||
|
} catch (Exception e) {
|
||||||
|
REServerMod.LOGGER.info("Sorry! Following error, trying to respawn player " + player.getDisplayName() + ": " + e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
player.sendMessage(Text.of("Oh! Scheint so als wäre der Spawnpunkt nicht gesetzt!"));
|
||||||
|
}
|
||||||
|
//player.setSpawnPoint(dimAlt, posAlt, angleAlt, true, false); //TODDO: wenn unkommentiert, setzt er schneller den neuen spawn, als der Spieler respawnt
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package modchest.networking.packet;
|
||||||
|
|
||||||
|
import modchest.REServerMod;
|
||||||
|
import modchest.util.setAndGetMultiButtonsSpawn;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.PacketSender;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class setNewRespawnsC2SPacket {
|
||||||
|
public static void receive(MinecraftServer server, ServerPlayerEntity player, //Passiert auf dem Server!!!
|
||||||
|
ServerPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) {
|
||||||
|
setAndGetMultiButtonsSpawn setAndGet = new setAndGetMultiButtonsSpawn();
|
||||||
|
try {
|
||||||
|
switch (buf.readInt()) { //Wird nur einmal angefragt, daher muss buf.readInt() nicht als variable gesetzt werden
|
||||||
|
case 1:
|
||||||
|
setAndGet.setMultiSpawn(player, 1); //Spawnpunkt wird gespeichert
|
||||||
|
player.sendMessage(Text.of("Respawn #1 gesetzt! " + Arrays.toString(setAndGet.getMultiSpawn(player, 1))));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
setAndGet.setMultiSpawn(player, 2);
|
||||||
|
player.sendMessage(Text.of("Respawn #2 gesetzt! " + Arrays.toString(setAndGet.getMultiSpawn(player, 2))));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
setAndGet.setMultiSpawn(player, 3);
|
||||||
|
player.sendMessage(Text.of("Respawn #3 gesetzt! " + Arrays.toString(setAndGet.getMultiSpawn(player, 3))));
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
setAndGet.setMultiSpawn(player, 4);
|
||||||
|
player.sendMessage(Text.of("Respawn #4 gesetzt! " + Arrays.toString(setAndGet.getMultiSpawn(player, 4))));
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
setAndGet.setMultiSpawn(player, 5);
|
||||||
|
player.sendMessage(Text.of("Respawn #5 gesetzt! " + Arrays.toString(setAndGet.getMultiSpawn(player, 5))));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
player.sendMessage(Text.of("Uff! Error beim Speichern! Schaue in die Logs fuer mehr details"));
|
||||||
|
REServerMod.LOGGER.info("Following Error, when trying to save " + player.getDisplayName() + "'s Spawnpoint: " + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package modchest.util;
|
||||||
|
|
||||||
|
import net.minecraft.nbt.NbtCompound;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
|
||||||
|
public interface ServerPlayerEntityInterface {
|
||||||
|
int[] getDataSaver();
|
||||||
|
void setDataSaver(int[] data);
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package modchest.util;
|
||||||
|
|
||||||
|
import modchest.REServerMod;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
public class setAndGetMultiButtonsSpawn {
|
||||||
|
|
||||||
|
public synchronized void setMultiSpawn(ServerPlayerEntity player, int spawn) {
|
||||||
|
ServerPlayerEntityInterface castedPlayer = (ServerPlayerEntityInterface) player;
|
||||||
|
int[] fullArray = castedPlayer.getDataSaver(); //holt sich den ganzen Array, mit allen gespeicherten Spawnpunkten; struktur wird etwas weiter unten erklaert
|
||||||
|
spawn--; //weil der Array mit Slot 0 beginnt, rutscht alles eins auf
|
||||||
|
if (fullArray.length != 15) { //Wenn der array unbeschrieben ist (Laenge ungleich 15), wird ein neuer erstellt
|
||||||
|
fullArray = new int[15];
|
||||||
|
for (int i = 0; i < 15; i++) {
|
||||||
|
fullArray[i] = 77889911; //Lueckenfueller; wird in deathScreenMultiButtonsC2SPacket uebrprueft und rausgefiltert
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fullArray[spawn * 3 + 0] = (int) player.getX();
|
||||||
|
fullArray[spawn * 3 + 1] = (int) player.getY();
|
||||||
|
fullArray[spawn * 3 + 2] = (int) player.getZ();
|
||||||
|
|
||||||
|
try {
|
||||||
|
castedPlayer.setDataSaver(fullArray);
|
||||||
|
} catch (Exception e) {
|
||||||
|
REServerMod.LOGGER.info("Sorry! Error when saving Spawnpoint! Exception: " + e);
|
||||||
|
player.sendMessage(Text.of("Tut mir leid! Das hat nicht geklappt!" + e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized int[] getMultiSpawn(ServerPlayerEntity player, int spawn) {
|
||||||
|
ServerPlayerEntityInterface castedPlayer = (ServerPlayerEntityInterface) player;
|
||||||
|
int[] fullArray = castedPlayer.getDataSaver();
|
||||||
|
if (fullArray.length != 15) {
|
||||||
|
int[] tempArray = new int[15];
|
||||||
|
for (int i = 0; i < 15; i++) {
|
||||||
|
tempArray[i] = 77889922; //Lueckenfueller; wird in deathScreenMultiButtonsC2SPacket uebrprueft und rausgefiltert
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
castedPlayer.setDataSaver(fullArray);
|
||||||
|
} catch (Exception e) {
|
||||||
|
REServerMod.LOGGER.info("Sorry! Error when loading Spawnpoint! Exception: " + e);
|
||||||
|
player.sendMessage(Text.of("Tut mir leid! Das hat nicht geklappt!" + e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fullArray = castedPlayer.getDataSaver();
|
||||||
|
spawn--;
|
||||||
|
int[] posXYZ = new int[3];
|
||||||
|
try {
|
||||||
|
posXYZ[0] = fullArray[spawn * 3 + 0]; //der array ist 15 slots lang, davon gehoeren immer 3 zusammen; wir rutschen also um die anzahl an Spawns weiter und holen uns dann den nullten, ersten un zweiten
|
||||||
|
posXYZ[1] = fullArray[spawn * 3 + 1]; //Bsp.: angenommen wir wollen den 2. spawn, ueberspringen wir FullArray[0] (x-Koordinate fuer slot 1), FullArray[1] (y-Koordinate fuer slot 1), FullArray[03] (z-Koordinate fuer slot 1),
|
||||||
|
posXYZ[2] = fullArray[spawn * 3 + 2]; //dann holen wir uns also fullArray[3] = x-Koordinate slot 2, fullArray[4] = y-Koordinate slot 2 und fullArray[5] = z-Koordinate slot 2
|
||||||
|
//Diese Art macht es beim Abspeichern etwas einfacher
|
||||||
|
} catch (Exception e) {
|
||||||
|
posXYZ[0] = 77889933;
|
||||||
|
posXYZ[1] = 77889933;
|
||||||
|
posXYZ[2] = 77889933;
|
||||||
|
}
|
||||||
|
return posXYZ;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"required": true,
|
"required": true,
|
||||||
"package": "modchest.mixin",
|
"package": "modchest.mixin",
|
||||||
"compatibilityLevel": "JAVA_17",
|
"compatibilityLevel": "JAVA_17",
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"ExampleMixin"
|
"ServerPlayerEntityMixin"
|
||||||
],
|
],
|
||||||
"injectors": {
|
"injectors": {
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue