multi-sleep finished

multi-sleep sit fertig.
Features:
übersetzung;
speichert 5 spawnpunkte, nach respawn wird der vanilla-spawnpunkt wieder gesetzt, die vanilla-spawnfunktion bleibt also erhalten. Stürtzt nicht ab
This commit is contained in:
Malte Reents 2024-01-22 09:46:03 +01:00
parent faedbb63ba
commit 872390ede3
15 changed files with 326 additions and 97 deletions

3
.gitignore vendored
View File

@ -37,6 +37,9 @@ build/
out/ out/
classes/ classes/
.gradlew
.gradle-wrapper.properties
# eclipse # eclipse
*.launch *.launch

View File

@ -1,15 +1,10 @@
package modchest; package modchest;
import modchest.block.entity.modBlockEntities;
import modchest.block.modBlocks;
import modchest.event.entitySleepStartSleepingEventHandler;
import modchest.item.modItemGroup;
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 org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import modchest.util.initializer;
//Main file; Hier wird alles aufgesetzt //Main file; Hier wird alles aufgesetzt
public class REServerMod implements ModInitializer { public class REServerMod implements ModInitializer {
@ -17,14 +12,11 @@ public class REServerMod implements ModInitializer {
public static final Logger LOGGER = LoggerFactory.getLogger("modchest"); // Erster Error Logger public static final Logger LOGGER = LoggerFactory.getLogger("modchest"); // Erster Error Logger
@Override @Override
public void onInitialize() { public void onInitialize() { //Der uebersicht halber sind jetzt alle initializer in Klassen in util in initializer
modItemGroup.modchest(); // Item Gruppe fürs Creative-Inventar wird erstellt; In dieser Gruppe sollen initializer.itemGroups();
// dann alle Items und Blöcke dieser Mod angezeigt werden initializer.itemsAndBlocks();
modItems.setItems(); // die Items werden erstellt initializer.events();
modBlocks.setBlocks(); // Hier werden die Blöcke erstellt initializer.networking();
modBlockEntities.registerBlockEntities(); // Die Interaktionsmenüs für die Blöcke werden erstellt
EntitySleepEvents.START_SLEEPING.register(new entitySleepStartSleepingEventHandler());
modNetworkingServer.registerS2CPackets(); //Identifier unter denen der Server zuhoert werden registriert
LOGGER.info("Modchest successfully loaded!"); LOGGER.info("Modchest successfully loaded!");
} }

View File

@ -1,21 +0,0 @@
package modchest.event;
import modchest.networking.modNetworkingServer;
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.player.PlayerEntity;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos;
public class entitySleepStartSleepingEventHandler implements EntitySleepEvents.StartSleeping {
@Override
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
entity.sendMessage(Text.of("Schlafmütze!"));
}
}
}

View File

@ -0,0 +1,36 @@
package modchest.event;
import modchest.REServerMod;
import modchest.util.setAndGetMultiButtonsSpawn;
import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.World;
public class playerAfterRespawnEvent implements ServerPlayerEvents.AfterRespawn { //Wenn die Multi-Spawn mod verwendet wurde, muss der Vanillaspawn wieder gesetzt werden
@Override
public void afterRespawn(ServerPlayerEntity oldPlayer, ServerPlayerEntity newPlayer, boolean alive) {
setAndGetMultiButtonsSpawn setAndGet = new setAndGetMultiButtonsSpawn(); //Damit die Mehtoden benutzt werden koennen, muss ein Objekt erstellt werden; ist aber egal, weil eh keine Daten in dieser Klasse gespeichert werden
NbtCompound nbt = setAndGet.getMultiSpawnVanilla(newPlayer); //holt sich den nbt-tag
if (nbt != null) {
try {
int[] location = nbt.getIntArray("location"); //holt sich den gespeicherten Ort
BlockPos blockPos = new BlockPos(location[0], location[1], location[2]);
String[] parts = nbt.getString("dimension").split(":"); //holt sich die gespeicherte Dimension; trennt den String entspreichend; damit sollte es auch funktionieren, sollte eine Mod weiter Dimensionen hinzufuegen
parts = parts[2].split("]");
RegistryKey<World> dim = RegistryKey.of(Registry.WORLD_KEY, new Identifier(parts[0]));
float angle = nbt.getFloat("angle"); //Und den blickwinkel
newPlayer.setSpawnPoint(dim, blockPos, angle, true, false);
} catch (Exception e) {
REServerMod.LOGGER.info("Following error when trying set " + newPlayer.getDisplayName() + "'s Vanilla Spawn: " + e);
}
}
}
}

View File

@ -1,5 +1,6 @@
package modchest.mixin; package modchest.mixin;
import modchest.REServerMod;
import modchest.util.ServerPlayerEntityInterface; import modchest.util.ServerPlayerEntityInterface;
import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
@ -9,40 +10,41 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Arrays;
@Mixin(ServerPlayerEntity.class) @Mixin(ServerPlayerEntity.class)
public abstract class ServerPlayerEntityMixin implements ServerPlayerEntityInterface { public abstract class ServerPlayerEntityMixin implements ServerPlayerEntityInterface {
@Unique @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 private NbtCompound dataSaver = new NbtCompound(); //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 @Override
public int[] getDataSaver() { //Um errors zu vermeiden, sorgt er dafuer, dass es immer ein persistentData gibt public NbtCompound getDataSaver() { //Um errors zu vermeiden, sorgt er dafuer, dass es immer ein persistentData gibt
if (this.dataSaver == null) { if (this.dataSaver == null) {
this.dataSaver = new int[1]; this.dataSaver = new NbtCompound();
} }
return this.dataSaver; return this.dataSaver;
} }
@Override @Override
public void setDataSaver(int[] data) { //Um errors zu vermeiden, sorgt er dafuer, dass es immer ein persistentData gibt public void setDataSaver(NbtCompound data) { //Um errors zu vermeiden, sorgt er dafuer, dass es immer ein persistentData gibt
this.dataSaver = data; this.dataSaver = data;
} }
@Inject(method = "writeCustomDataToNbt", at = @At("TAIL")) @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 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.put("REServerMod", this.dataSaver);
nbt.putIntArray("REServerMod.sleep_data", this.dataSaver); REServerMod.LOGGER.info("writeCustomDataToNbt called");
}
} }
@Inject(method = "readCustomDataFromNbt", at = @At("TAIL")) @Inject(method = "readCustomDataFromNbt", at = @At("TAIL"))
public void readCustomDataFromNbt(NbtCompound nbt, CallbackInfo ci) { //gleiches beim einlesen. Werden NBT-Daten eingelesen, tun wird das auch public void readCustomDataFromNbt(NbtCompound nbt, CallbackInfo ci) { //gleiches beim einlesen. Werden NBT-Daten eingelesen, tun wird das auch
if (dataSaver.length == 15) { dataSaver = (NbtCompound) nbt.get("REServerMod");
dataSaver = nbt.getIntArray("REServerMod.sleep_data"); REServerMod.LOGGER.info("readCustomDataFromNbt called with following Data: " + Arrays.toString(nbt.getIntArray("REServerMod.sleep_data")));
}
} }
@Inject(method = "copyFrom", at = @At("TAIL")) @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 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(); dataSaver = ((ServerPlayerEntityInterface) oldPlayer).getDataSaver();
REServerMod.LOGGER.info("copyFrom called");
} }
} }

View File

@ -0,0 +1,59 @@
package modchest.mixin;
import modchest.REServerMod;
import modchest.util.setAndGetMultiButtonsSpawn;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import net.minecraft.block.BedBlock;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Arrays;
import java.util.List;
@Mixin(BedBlock.class)
public class bedBlock {
@Inject(method = "onBreak", at = @At("HEAD"))
public void onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player, CallbackInfo ci) { //Ueberprueft, wenn ein Bett zerstoert wird, ob jemand dieses Bett als Spawnpunkt hat
if (!world.isClient) { //Stellt sicher, dass das ganze nciht auf dem CLient rechnet wird, weil der Code sonst abstuertzt
setAndGetMultiButtonsSpawn setAndGet = new setAndGetMultiButtonsSpawn(); //Damit die Mehtoden benutzt werden koennen, muss ein Objekt erstellt werden; ist aber egal, weil eh keine Daten in dieser Klasse gespeichert werden
List<? extends PlayerEntity> playerArray = null;
try { //Sollte der Code doch ausversehen auf dem Client ausgefuehrt werden, wuerde die folgende Zeile einen Error schmeissen
playerArray = world.getPlayers(); //holt sich die liste aller Spieler auf dem server
} catch (Exception e) {
REServerMod.LOGGER.info("Error when trying to get players Array after Bed was destroyed: " + e);
}
for (int i = 0; i < playerArray.size(); i++) { //geht fuer jeden Spieler durch
for (int j = 1; j <= 5; j++) { //und fuer alle Speicherslots dieser
int[] posXYZ = new int[0];
try { //Sollte der Code doch ausversehen auf dem Client ausgefuehrt werden, wuerde die folgende Zeile einen Error schmeissen
posXYZ = setAndGet.getMultiSpawn((ServerPlayerEntity) playerArray.get(i), j);
} catch (Exception e) {
REServerMod.LOGGER.info("Error casting playerArray to ServerPlayerEntity: " + e);
}
if (inRange(pos.getX(), posXYZ[0], 1) && inRange(pos.getY(), posXYZ[1], 1) && inRange(pos.getZ(), posXYZ[2], 1)) { //Gleicht ab, ob die Koordinaten uebereinstimmen; die Spawnpunkte sind nicht immer ganz sauber, daher wird in Blockrange 1 geschaut
player.sendMessage(Text.of(Text.of(pos.toShortString()) + " zu " + new BlockPos(posXYZ[0], posXYZ[1], posXYZ[2])));
try { //Sollte der Code doch ausversehen auf dem Client ausgefuehrt werden, wuerde die folgende Zeile einen Error schmeissen
setAndGet.setMultiSpawnBlank((ServerPlayerEntity) playerArray.get(i), j); //Wird ein bett zerstoert, wird der Spawnpunkt geblanked
} catch (Exception e) {
REServerMod.LOGGER.info("Error when trying to get players Array after Bed was destroyed: " + e);
}
}
}
}
}
}
private boolean inRange(int one, int two, int range) {
one = (one - two);
return (-range) <= one && one <= range;
}
}

View File

@ -12,9 +12,9 @@ import net.minecraft.server.network.ServerPlayNetworkHandler;
import net.minecraft.server.network.ServerPlayerEntity; 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;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.World; import net.minecraft.world.World;
import java.awt.*;
import java.util.Arrays; import java.util.Arrays;
public class deathScreenMultiButtonsC2SPacket { public class deathScreenMultiButtonsC2SPacket {
@ -28,9 +28,8 @@ public class deathScreenMultiButtonsC2SPacket {
REServerMod.LOGGER.info("Following Error when trying to get the number of pressed Button: " + e + "continuing bwith Button 1"); REServerMod.LOGGER.info("Following Error when trying to get the number of pressed Button: " + e + "continuing bwith Button 1");
num = 1; num = 1;
} }
BlockPos posAlt = player.getSpawnPointPosition(); //Spawnpunkt der Vanilla-respawn-funktion wird gespeichert setAndGet.setMultiSpawnVanilla(player);
RegistryKey<World> dimAlt = player.getSpawnPointDimension();//Dimension "
float angleAlt = player.getSpawnAngle(); //Blickrichtung "
int[] posXYZ = setAndGet.getMultiSpawn(player, num); //neue Koordinaten werden vom Server geholt 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 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
@ -38,14 +37,19 @@ public class deathScreenMultiButtonsC2SPacket {
REServerMod.LOGGER.info("try Respawning from Multi-Sapwn"); 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 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 ServerPlayNetworking.send(player, modNetworkingServer.request_respawn, PacketByteBufs.create()); //Anfrage an den Client zum respawnen wird gesendet
player.sendMessage(Text.of("Respawn bei #" + num + "! ")); player.sendMessage((Text.translatable("chat.modchest.multispawn.respawned", num)));
REServerMod.LOGGER.info("Respawned Player: " + player.getDisplayName() + "at " + Arrays.toString(setAndGet.getMultiSpawn(player, num))); REServerMod.LOGGER.info("Respawned Player: " + player.getDisplayName() + "at " + Arrays.toString(setAndGet.getMultiSpawn(player, num)));
setAndGet.setMultiSpawn(player, 6);
} catch (Exception e) { } catch (Exception e) {
REServerMod.LOGGER.info("Sorry! Following error, trying to respawn player " + player.getDisplayName() + ": " + e); REServerMod.LOGGER.info("Sorry! Following error, trying to respawn player " + player.getDisplayName() + ": " + e);
} }
} else { } else {
player.sendMessage(Text.of("Oh! Scheint so als wäre der Spawnpunkt nicht gesetzt!")); if (posXYZ[0] == 77889944) { //Dieser Errorcode bedeutet, dass das Bett zerstoert wurde
player.sendMessage(Text.translatable("chat.modchest.multispawn.beddestroyed"));
} else {
player.sendMessage(Text.translatable("chat.modchest.multispawn.spawnnotset"));
}
} }
//player.setSpawnPoint(dimAlt, posAlt, angleAlt, true, false); //TODDO: wenn unkommentiert, setzt er schneller den neuen spawn, als der Spieler respawnt
} }
} }

View File

@ -19,27 +19,27 @@ public class setNewRespawnsC2SPacket {
switch (buf.readInt()) { //Wird nur einmal angefragt, daher muss buf.readInt() nicht als variable gesetzt werden switch (buf.readInt()) { //Wird nur einmal angefragt, daher muss buf.readInt() nicht als variable gesetzt werden
case 1: case 1:
setAndGet.setMultiSpawn(player, 1); //Spawnpunkt wird gespeichert setAndGet.setMultiSpawn(player, 1); //Spawnpunkt wird gespeichert
player.sendMessage(Text.of("Respawn #1 gesetzt! " + Arrays.toString(setAndGet.getMultiSpawn(player, 1)))); player.sendMessage(Text.translatable("chat.modchest.multispawn.setspawn", "1"));
break; break;
case 2: case 2:
setAndGet.setMultiSpawn(player, 2); setAndGet.setMultiSpawn(player, 2);
player.sendMessage(Text.of("Respawn #2 gesetzt! " + Arrays.toString(setAndGet.getMultiSpawn(player, 2)))); player.sendMessage(Text.translatable("chat.modchest.multispawn.setspawn", "2"));
break; break;
case 3: case 3:
setAndGet.setMultiSpawn(player, 3); setAndGet.setMultiSpawn(player, 3);
player.sendMessage(Text.of("Respawn #3 gesetzt! " + Arrays.toString(setAndGet.getMultiSpawn(player, 3)))); player.sendMessage(Text.translatable("chat.modchest.multispawn.setspawn", "3"));
break; break;
case 4: case 4:
setAndGet.setMultiSpawn(player, 4); setAndGet.setMultiSpawn(player, 4);
player.sendMessage(Text.of("Respawn #4 gesetzt! " + Arrays.toString(setAndGet.getMultiSpawn(player, 4)))); player.sendMessage(Text.translatable("chat.modchest.multispawn.setspawn", "4"));
break; break;
case 5: case 5:
setAndGet.setMultiSpawn(player, 5); setAndGet.setMultiSpawn(player, 5);
player.sendMessage(Text.of("Respawn #5 gesetzt! " + Arrays.toString(setAndGet.getMultiSpawn(player, 5)))); player.sendMessage(Text.translatable("chat.modchest.multispawn.setspawn", "5"));
break; break;
} }
} catch (Exception e) { } catch (Exception e) {
player.sendMessage(Text.of("Uff! Error beim Speichern! Schaue in die Logs fuer mehr details")); player.sendMessage(Text.translatable("chat.modchest.multispawn.setspawnerror"));
REServerMod.LOGGER.info("Following Error, when trying to save " + player.getDisplayName() + "'s Spawnpoint: " + e); REServerMod.LOGGER.info("Following Error, when trying to save " + player.getDisplayName() + "'s Spawnpoint: " + e);
} }
} }

View File

@ -5,6 +5,6 @@ import net.minecraft.server.network.ServerPlayerEntity;
import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.Unique;
public interface ServerPlayerEntityInterface { public interface ServerPlayerEntityInterface {
int[] getDataSaver(); NbtCompound getDataSaver();
void setDataSaver(int[] data); void setDataSaver(NbtCompound data);
} }

View File

@ -0,0 +1,30 @@
package modchest.util;
import modchest.block.entity.modBlockEntities;
import modchest.block.modBlocks;
import modchest.event.playerAfterRespawnEvent;
import modchest.item.modItemGroup;
import modchest.item.modItems;
import modchest.networking.modNetworkingServer;
import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents;
public class initializer {
public static void itemGroups() {
modItemGroup.modchest(); // Item Gruppe fürs Creative-Inventar wird erstellt; In dieser Gruppe sollen
// dann alle Items und Blöcke dieser Mod angezeigt werden
}
public static void itemsAndBlocks() {
modItems.setItems(); // die Items werden erstellt
modBlocks.setBlocks(); // Hier werden die Blöcke erstellt
modBlockEntities.registerBlockEntities(); // Die Interaktionsmenüs für die Blöcke werden erstellt
}
public static void events() { //Events, bei denen custom Code ausgefuehrt wird, werden eingefuehrt
ServerPlayerEvents.AFTER_RESPAWN.register(new playerAfterRespawnEvent());
}
public static void networking() { //Identifier unter denen der Server zuhoert werden registriert
modNetworkingServer.registerS2CPackets();
}
}

View File

@ -1,63 +1,162 @@
package modchest.util; package modchest.util;
import modchest.REServerMod; import modchest.REServerMod;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.server.network.ServerPlayerEntity; 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.registry.RegistryKey;
import net.minecraft.world.World;
public class setAndGetMultiButtonsSpawn { public class setAndGetMultiButtonsSpawn {
public synchronized void setMultiSpawn(ServerPlayerEntity player, int spawn) { public synchronized void setMultiSpawn(ServerPlayerEntity player, int spawn) {
ServerPlayerEntityInterface castedPlayer = (ServerPlayerEntityInterface) player; ServerPlayerEntityInterface castedPlayer = (ServerPlayerEntityInterface) player;
int[] fullArray = castedPlayer.getDataSaver(); //holt sich den ganzen Array, mit allen gespeicherten Spawnpunkten; struktur wird etwas weiter unten erklaert NbtCompound topNbt = ((ServerPlayerEntityInterface) player).getDataSaver(); //alle daten der mod werden in diesem NBT Gespeichert
spawn--; //weil der Array mit Slot 0 beginnt, rutscht alles eins auf if (topNbt.get("multi_sleep") == null) { //die daten fuer multi-sleep werden in dem nbt-tag "multi_sleep" gespeichert, der wiederum um anderen nbt gespeichert wird
if (fullArray.length != 15) { //Wenn der array unbeschrieben ist (Laenge ungleich 15), wird ein neuer erstellt topNbt.put("multi_sleep", new NbtCompound()); //sollte dieser nbt-tag nicht existieren, 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(); NbtCompound subNbt = (NbtCompound) topNbt.get("multi_sleep"); //nbt tag mit allen daten fuer multi-sleep wird geladen
fullArray[spawn * 3 + 1] = (int) player.getY(); spawn--; //weil der Array mit Slot 0 beginnt, rutscht alles eins auf
fullArray[spawn * 3 + 2] = (int) player.getZ(); int[] fullArray = new int[3]; //ein kleiner zwischenspeicher
fullArray[0] = (int) player.getX();
fullArray[1] = (int) player.getY();
fullArray[2] = (int) player.getZ();
try { try {
castedPlayer.setDataSaver(fullArray); assert subNbt != null;
} catch (Exception e) { subNbt.putIntArray(String.valueOf(spawn), fullArray); //speichert unseren array an der entsprechenden nummer ab
topNbt.put("multi_sleep", subNbt); //speichert den tag unter multi_sleep im top-tag ab
castedPlayer.setDataSaver(topNbt); //speichert den top-tag wieder im spieler ab
} catch (Exception e) {
REServerMod.LOGGER.info("Sorry! Error when saving Spawnpoint! Exception: " + e); REServerMod.LOGGER.info("Sorry! Error when saving Spawnpoint! Exception: " + e);
player.sendMessage(Text.of("Tut mir leid! Das hat nicht geklappt!" + e)); player.sendMessage(Text.translatable("chat.modchest.multispawn.spawnnotsaved"));
} }
} }
public synchronized int[] getMultiSpawn(ServerPlayerEntity player, int spawn) { public synchronized int[] getMultiSpawn(ServerPlayerEntity player, int spawn) {
ServerPlayerEntityInterface castedPlayer = (ServerPlayerEntityInterface) player; ServerPlayerEntityInterface castedPlayer = (ServerPlayerEntityInterface) player;
int[] fullArray = castedPlayer.getDataSaver(); NbtCompound topNbt = ((ServerPlayerEntityInterface) player).getDataSaver();
if (fullArray.length != 15) { if (topNbt.get("multi_sleep") == null) {
int[] tempArray = new int[15]; topNbt.put("multi_sleep", new NbtCompound());
for (int i = 0; i < 15; i++) { }
NbtCompound subNbt = (NbtCompound) topNbt.get("multi_sleep"); //wie bei setMultiSpawn()
spawn--; //weil der Array mit Slot 0 beginnt, rutscht alles eins auf
int[] fullArray = new int[0];
if (subNbt != null) {
fullArray = subNbt.getIntArray(String.valueOf(spawn)); //holt sich den ganzen Array, mit allen gespeicherten Spawnpunkten; struktur wird etwas weiter unten erklaert
}
if (fullArray.length != 3) { //sollte der Array leer oder anderweitig ungueltig sein wird er neu erstellt
int[] tempArray = new int[3];
for (int i = 0; i < 3; i++) {
tempArray[i] = 77889922; //Lueckenfueller; wird in deathScreenMultiButtonsC2SPacket uebrprueft und rausgefiltert tempArray[i] = 77889922; //Lueckenfueller; wird in deathScreenMultiButtonsC2SPacket uebrprueft und rausgefiltert
} }
try { try { //wenn wir gerade den Array erstellt haben, weil er ungueltig war, wird er hier in den nbt-tag abgespseichert
castedPlayer.setDataSaver(fullArray); subNbt.putIntArray(String.valueOf(spawn), fullArray);
} catch (Exception e) { topNbt.put("multi_sleep", subNbt);
castedPlayer.setDataSaver(topNbt);
} catch (Exception e) {
REServerMod.LOGGER.info("Sorry! Error when loading Spawnpoint! Exception: " + e); REServerMod.LOGGER.info("Sorry! Error when loading Spawnpoint! Exception: " + e);
player.sendMessage(Text.of("Tut mir leid! Das hat nicht geklappt!" + e)); player.sendMessage(Text.translatable("chat.modchest.multispawn.getable"));
} }
} }
fullArray = castedPlayer.getDataSaver(); fullArray = subNbt.getIntArray(String.valueOf(spawn)); //wir laden ihn uns wieder, nur um sicher zu gehen
spawn--; int[] posXYZ = new int[3]; //zwischenspeicher
int[] posXYZ = new int[3]; try { //schaut, ob wir die daten laden koennen
try { posXYZ[0] = fullArray[0];
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[1];
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[2];
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 } catch (Exception e) { //sonst geben wir folgenden Errorcode zurueck
//Diese Art macht es beim Abspeichern etwas einfacher
} catch (Exception e) {
posXYZ[0] = 77889933; posXYZ[0] = 77889933;
posXYZ[1] = 77889933; posXYZ[1] = 77889933;
posXYZ[2] = 77889933; posXYZ[2] = 77889933;
} }
return posXYZ; return posXYZ;
} }
public synchronized void setMultiSpawnVanilla(ServerPlayerEntity player) { //bevor der Spieler respawnt, speichern wir einmal seinen Vanillaspawn ab, um ihn spaeter wieder darauf zu setzen
BlockPos posAlt = player.getSpawnPointPosition(); //Spawnpunkt der Vanilla-respawn-funktion wird gespeichert
RegistryKey<World> dimAlt = player.getSpawnPointDimension();//Dimension "
float angleAlt = player.getSpawnAngle(); //Blickrichtung "
ServerPlayerEntityInterface castedPlayer = (ServerPlayerEntityInterface) player;
NbtCompound topNbt = ((ServerPlayerEntityInterface) player).getDataSaver();
if (topNbt.get("multi_sleep") == null) {
topNbt.put("multi_sleep", new NbtCompound());
}
NbtCompound subNbt = (NbtCompound) topNbt.get("multi_sleep"); //alles in der set-Methode ganz oben erklaert
try { //sicheerheit, weil hier mal wieder viel zwischen datentypen gewechselt wird
NbtCompound vanillaSpawnData = new NbtCompound();
int[] location = new int[3]; //spawnpunkt wird in einen Array komprimiert
location[0] = posAlt.getX();
location[1] = posAlt.getY();
location[2] = posAlt.getZ();
vanillaSpawnData.putIntArray("location", location); //und abgespeichert
vanillaSpawnData.putString("dimension", dimAlt.toString()); //dimension wird abgespeichert
vanillaSpawnData.putFloat("angle", angleAlt); //auch die Blickrichtung
vanillaSpawnData.putBoolean("used", false); //wird auf true gesetzt, sobald der Spawnpunkt wieder zurueck gesetzt wurde
subNbt.put("vanillaSpawnData", vanillaSpawnData); //spawnpunkt wird im sub-nbt gespeichert
topNbt.put("multi_sleep", subNbt); //und im top-nbt
castedPlayer.setDataSaver(topNbt); //um dann im player gespeichert zu werden
} catch (Exception e) {
REServerMod.LOGGER.info("Sorry! Error when saving Spawnpoint! Exception: " + e);
}
}
public synchronized NbtCompound getMultiSpawnVanilla(ServerPlayerEntity player) {
ServerPlayerEntityInterface castedPlayer = (ServerPlayerEntityInterface) player;
NbtCompound topNbt = ((ServerPlayerEntityInterface) player).getDataSaver();
if (topNbt.get("multi_sleep") == null) {
topNbt.put("multi_sleep", new NbtCompound());
}
NbtCompound subNbt = (NbtCompound) topNbt.get("multi_sleep"); //steht alles wieder in der ersten methode
if (subNbt != null) {
NbtCompound nbt = (NbtCompound) subNbt.get("vanillaSpawnData"); //hollt sich die daten
assert nbt != null;
if (!nbt.getBoolean("used")) {
nbt.putBoolean("used", true); //setzt den verwendet boolean auf true; nicht ganz perfekt, sollte ein fehler beim speichern auftreten wird es nicht nochmal versucht, speichert aber massiv an coding und leistung
subNbt.put("vanillaSpawnData", nbt);
topNbt.put("multi_sleep", subNbt); //muss den bearbeiteten nbt wieder abgespeichert (nur der boolean wurde ueberschrieben)
castedPlayer.setDataSaver(topNbt);
return nbt; //gibt den nbt-tag an die aufrufende Methode
} else {
return null;
}
} else {
return null;
}
}
public synchronized void setMultiSpawnBlank(ServerPlayerEntity player, int spawn) { //wird aufgerufen wenn das Bett dieses Spielers zerstoert wurde
ServerPlayerEntityInterface castedPlayer = (ServerPlayerEntityInterface) player;
NbtCompound topNbt = ((ServerPlayerEntityInterface) player).getDataSaver();
if (topNbt.get("multi_sleep") == null) {
topNbt.put("multi_sleep", new NbtCompound());
}
NbtCompound subNbt = (NbtCompound) topNbt.get("multi_sleep"); //alles wieder wie in der ersten Methode;
spawn--; //weil der Array mit Slot 0 beginnt, rutscht alles eins auf
int[] fullArray = new int[0];
if (subNbt != null) {
fullArray = subNbt.getIntArray(String.valueOf(spawn)); //holt sich den ganzen Array, mit allen gespeicherten Spawnpunkten; struktur wird etwas weiter unten erklaert
}
fullArray[0] = 77889944; //Errorcode der in deathScreenMultiButtonsC2SPacket als zerstoertes Bett rausgefiltert wird
fullArray[1] = 77889944;
fullArray[2] = 77889944;
try {
subNbt.putIntArray(String.valueOf(spawn), fullArray); //wird abgespeichert
topNbt.put("multi_sleep", subNbt);
castedPlayer.setDataSaver(topNbt);
} catch (Exception e) {
REServerMod.LOGGER.info("Sorry! Error when saving Spawnpoint! Exception: " + e);
}
}
} }

View File

@ -2,5 +2,13 @@
"item.modchest.shipblock": "Schiffsblock", "item.modchest.shipblock": "Schiffsblock",
"item.modchest.pirates_coin": "OP Piraten ding zum Testen", "item.modchest.pirates_coin": "OP Piraten ding zum Testen",
"block.modchest.steering_wheel": "Lenkrad", "block.modchest.steering_wheel": "Lenkrad",
"itemGroup.modchest.itemlist1": "Malte's Mod" "itemGroup.modchest.itemlist1": "Malte's Mod",
"chat.modchest.multispawn.beddestroyed": "Scheint so, als wäre das Bett zerstört worden!",
"chat.modchest.multispawn.respawned": "Respawne bei #%s",
"chat.modchest.multispawn.setspawn": "Nutze spawn #%s",
"chat.modchest.multispawn.setspawnerror": "Fehler beim speichern!",
"chat.modchest.multispawn.spawnnotset": "Es scheint so, als wäre dieser Spawn nicht gesetzt!",
"chat.modchest.multispawn.spawnnotsaved": "Fehler beim Versuch, diesen Spawn zu speichern!",
"chat.modchest.multispawn.getable": "Diese spawn location konnte nicht geladen werden!"
} }

View File

@ -2,5 +2,13 @@
"item.modchest.shipblock": "Hanno, änder die Sprache!", "item.modchest.shipblock": "Hanno, änder die Sprache!",
"item.modchest.pirates_coin": "Ya coin for tha pirrrrrates!", "item.modchest.pirates_coin": "Ya coin for tha pirrrrrates!",
"block.modchest.steering_wheel": "Ne, du kriegst keine hilfreichen Angaben mit der Sprache!", "block.modchest.steering_wheel": "Ne, du kriegst keine hilfreichen Angaben mit der Sprache!",
"itemGroup.modchest.itemlist1": "Änder doch endlich die Sprache..." "itemGroup.modchest.itemlist1": "Änder doch endlich die Sprache...",
"chat.modchest.multispawn.beddestroyed": "Sorry, mate! Looks like that cap'n doesn't like you",
"chat.modchest.multispawn.respawned": "Prepare to board some ship, lads!",
"chat.modchest.multispawn.setspawn": "Boarded random ship!",
"chat.modchest.multispawn.setspawnerror": "oh, that hammock is full!",
"chat.modchest.multispawn.spawnnotset": "No hammocks a'board!",
"chat.modchest.multispawn.spawnnotsaved": "Couldn't remember that ship...",
"chat.modchest.multispawn.getable": "Na ship could be found!"
} }

View File

@ -2,5 +2,13 @@
"item.modchest.shipblock": "Shipblock", "item.modchest.shipblock": "Shipblock",
"item.modchest.pirates_coin": "Pirate's Coin", "item.modchest.pirates_coin": "Pirate's Coin",
"block.modchest.steering_wheel": "Steering Wheel", "block.modchest.steering_wheel": "Steering Wheel",
"itemGroup.modchest.itemlist1": "Theo macht unfug" "itemGroup.modchest.itemlist1": "new blocks",
"chat.modchest.multispawn.beddestroyed": "Oh shit! Looks like that bed got destroyed!",
"chat.modchest.multispawn.respawned": "Respawn #%s used",
"chat.modchest.multispawn.setspawn": "Set spawn #%s",
"chat.modchest.multispawn.setspawnerror": "Sorry! Error when setting that spawn!",
"chat.modchest.multispawn.spawnnotset": "Sorry! Looks like that Spawnpoint isn't set yet!",
"chat.modchest.multispawn.spawnnotsaved": "Sorry! Error when trying to save your spawn!",
"chat.modchest.multispawn.getable": "Sorry! Couldn't get your spawnlocation!"
} }

View File

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