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:
Malte Reents 2024-01-21 10:09:48 +01:00
parent f58ffa9b65
commit faedbb63ba
18 changed files with 454 additions and 55 deletions

View File

@ -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

View File

@ -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 {
public static final Logger LOGGER = LoggerFactory.getLogger("modchest"); // Erster Error Logger
@Override @Override
public void onInitializeClient() { public void onInitializeClient() {
// This entrypoint is suitable for setting up client-specific logic, such as rendering. // This entrypoint is suitable for setting up client-specific logic, such as rendering.
//EntitySleepEvents.START_SLEEPING.register(new entitySleepStartSleepingEventHandler());
}
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));
} }
} }

View File

@ -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) {}
}
}

View File

@ -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
}
}

View File

@ -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) {}
}
}

View File

@ -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
}
}

View File

@ -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();
}
}

View File

@ -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": [
]
} }

View File

@ -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!");
} }
} }

View File

@ -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

View File

@ -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
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -3,7 +3,7 @@
"package": "modchest.mixin", "package": "modchest.mixin",
"compatibilityLevel": "JAVA_17", "compatibilityLevel": "JAVA_17",
"mixins": [ "mixins": [
"ExampleMixin" "ServerPlayerEntityMixin"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1