9 Commits

Author SHA1 Message Date
9325e24c5c Removed unnecessary comment
All checks were successful
build / build (push) Successful in 1m16s
2025-04-12 15:21:21 +02:00
02d2f624cf Code cleanup 2025-04-11 17:30:08 +02:00
9041bacf48 Updated README.md 2025-04-11 17:21:59 +02:00
23aefb2f8d Code cleanup 2025-04-11 17:21:51 +02:00
0941d3929e Renamed Utils.java to PacketUtils.java 2025-04-11 14:18:38 +02:00
c7722115ed Fixed bug where EC closes if another player is still inside 2025-04-11 14:17:14 +02:00
168f916baa Moved features to "features" package 2025-04-11 14:07:19 +02:00
f28159b442 Open/close EC block while opening/closing SEC + Play open & close sounds 2025-04-11 14:06:21 +02:00
c3a13c8063 Optimized fog removal ever so slightly 2025-04-11 13:21:46 +02:00
30 changed files with 290 additions and 265 deletions

View File

@ -3,7 +3,7 @@
# ![Logo](https://i.imgur.com/ktkHND1.png) # ![Logo](https://i.imgur.com/ktkHND1.png)
This mod is FAR FROM FINISHED, and initially just created for our private Survival Server. This mod is FAR FROM FINISHED, and initially just created for our private Survival Server.
As a challenge I'm trying to make it as user-friendly as possible. (It ain't there yet tho ;) ) As a challenge I'm trying to make it as user-friendly as possible.
# Current feature-set # Current feature-set
## Server Side ## Server Side
@ -38,7 +38,10 @@ As a challenge I'm trying to make it as user-friendly as possible. (It ain't the
## Server Side ## Server Side
- [x] Chat Calculator - [x] Chat Calculator
## Client Side ## Client Side
### New Features
- [x] Teleportation Angle Viewer for [this machine](https://www.youtube.com/watch?v=FnUE-ZaALLw) - [x] Teleportation Angle Viewer for [this machine](https://www.youtube.com/watch?v=FnUE-ZaALLw)
![Teleportation Keybindings](https://i.imgur.com/gjO1H3d.png) ![Teleportation Keybindings](https://i.imgur.com/gjO1H3d.png)
- [x] Removed game fog (lava, water, etc.) - [x] Removed game fog (lava, water, etc.)
@ -48,8 +51,18 @@ As a challenge I'm trying to make it as user-friendly as possible. (It ain't the
- [x] Removed darkness effect - [x] Removed darkness effect
- [x] Toggleable - [x] Toggleable
### Changes
- Shared Ender Chest
- [x] Open/close EC block while opening/closing SEC
- [x] Play open & close sounds
# Features to come # Features to come
## General
- Rework config system
- Store server settings in world folder for better singleplayer use
- Rework Mod Menu integration to be more flexible
## Server Side ## Server Side
- Telekinesis - Telekinesis

View File

@ -7,10 +7,10 @@ import wtf.hak.survivalfabric.features.RemoveDarknessEffect;
public class SurvivalFabricClient implements ClientModInitializer { public class SurvivalFabricClient implements ClientModInitializer {
@Override @Override
public void onInitializeClient() { public void onInitializeClient() {
ClientConfigManager.getConfig(); ClientConfigManager.getConfig();
AngleViewer.register(); AngleViewer.register();
RemoveDarknessEffect.register(); RemoveDarknessEffect.register();
} }
} }

View File

@ -4,8 +4,8 @@ import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint;
import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator; import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator;
public class SurvivalFabricDataGenerator implements DataGeneratorEntrypoint { public class SurvivalFabricDataGenerator implements DataGeneratorEntrypoint {
@Override @Override
public void onInitializeDataGenerator(FabricDataGenerator fabricDataGenerator) { public void onInitializeDataGenerator(FabricDataGenerator fabricDataGenerator) {
} }
} }

View File

@ -25,7 +25,7 @@ public class ClientConfigManager {
} }
public static ClientConfig load() { public static ClientConfig load() {
try(FileReader reader = new FileReader(CONFIG_FILE)) { try (FileReader reader = new FileReader(CONFIG_FILE)) {
INSTANCE = GSON.fromJson(reader, ClientConfig.class); INSTANCE = GSON.fromJson(reader, ClientConfig.class);
if (INSTANCE.configVersion.equalsIgnoreCase(new Config().configVersion)) { if (INSTANCE.configVersion.equalsIgnoreCase(new Config().configVersion)) {
return INSTANCE; return INSTANCE;
@ -41,12 +41,12 @@ public class ClientConfigManager {
} }
} }
public static void save(){ public static void save() {
save(INSTANCE); save(INSTANCE);
} }
public static void save(ClientConfig config) { public static void save(ClientConfig config) {
try(FileWriter writer = new FileWriter(CONFIG_FILE)) { try (FileWriter writer = new FileWriter(CONFIG_FILE)) {
GSON.toJson(config, writer); GSON.toJson(config, writer);
} catch (IOException e) { } catch (IOException e) {
System.out.println("Error saving config: " + e.getMessage()); System.out.println("Error saving config: " + e.getMessage());

View File

@ -17,7 +17,7 @@ public class AngleViewer {
public static boolean PREVENT_HEAD_MOVEMENT = false; public static boolean PREVENT_HEAD_MOVEMENT = false;
public static void register() { public static void register() {
for(Angle angle : Angle.values()) { for (Angle angle : Angle.values()) {
KeyBinding keyBinding = KeyBindingHelper.registerKeyBinding(new KeyBinding( KeyBinding keyBinding = KeyBindingHelper.registerKeyBinding(new KeyBinding(
"key.survivalfabric." + angle.name().toLowerCase(), "key.survivalfabric." + angle.name().toLowerCase(),
InputUtil.Type.KEYSYM, InputUtil.Type.KEYSYM,
@ -28,14 +28,14 @@ public class AngleViewer {
ClientTickEvents.END_CLIENT_TICK.register(mc -> { ClientTickEvents.END_CLIENT_TICK.register(mc -> {
while (keyBinding.wasPressed()) { while (keyBinding.wasPressed()) {
ClientPlayerEntity player = mc.player; ClientPlayerEntity player = mc.player;
if(player == null) return; if (player == null) return;
player.setYaw(angle.yaw); player.setYaw(angle.yaw);
player.setPitch(angle.pitch); player.setPitch(angle.pitch);
PREVENT_HEAD_MOVEMENT = true; PREVENT_HEAD_MOVEMENT = true;
scheduler.schedule(() -> { scheduler.schedule(() -> {
if(player == null) return; if (player == null) return;
PREVENT_HEAD_MOVEMENT = false; PREVENT_HEAD_MOVEMENT = false;
player.setPitch(-90); player.setPitch(-90);
PREVENT_HEAD_MOVEMENT = true; PREVENT_HEAD_MOVEMENT = true;

View File

@ -9,9 +9,9 @@ public class RemoveDarknessEffect {
public static void register() { public static void register() {
ClientTickEvents.END_CLIENT_TICK.register(client -> { ClientTickEvents.END_CLIENT_TICK.register(client -> {
if(client.player != null && ClientConfigManager.getConfig().removeDarknessEffect){ if (client.player != null && ClientConfigManager.getConfig().removeDarknessEffect) {
StatusEffectInstance darknessEffect = client.player.getStatusEffect(StatusEffects.DARKNESS); StatusEffectInstance darknessEffect = client.player.getStatusEffect(StatusEffects.DARKNESS);
if(darknessEffect != null) if (darknessEffect != null)
client.player.removeStatusEffect(darknessEffect.getEffectType()); client.player.removeStatusEffect(darknessEffect.getEffectType());
} }
}); });

View File

@ -8,6 +8,7 @@ import net.minecraft.client.render.FogShape;
import net.minecraft.world.World; import net.minecraft.world.World;
import org.joml.Vector4f; import org.joml.Vector4f;
import org.spongepowered.asm.mixin.Mixin; 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.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@ -17,26 +18,29 @@ import static wtf.hak.survivalfabric.config.client.ClientConfigManager.getConfig
@Mixin(value = BackgroundRenderer.class, priority = 910) @Mixin(value = BackgroundRenderer.class, priority = 910)
public abstract class BackgroundRendererMixin { public abstract class BackgroundRendererMixin {
@Unique
private static final Fog EMPTY_FOG = new Fog(-8.0f, 1_000_000.0F, FogShape.CYLINDER, 0, 0, 0, 0);
@Inject(method = "applyFog", at = @At("RETURN"), cancellable = true) @Inject(method = "applyFog", at = @At("RETURN"), cancellable = true)
private static void applyFog(Camera camera, BackgroundRenderer.FogType fogType, Vector4f color, float viewDistance, boolean thickenFog, float tickProgress, CallbackInfoReturnable<Fog> cir) { private static void applyFog(Camera camera, BackgroundRenderer.FogType fogType, Vector4f color, float viewDistance, boolean thickenFog, float tickProgress, CallbackInfoReturnable<Fog> cir) {
boolean renderFog = true; boolean renderFog = true;
CameraSubmersionType subType = camera.getSubmersionType(); CameraSubmersionType subType = camera.getSubmersionType();
if(subType == CameraSubmersionType.NONE) { if (subType == CameraSubmersionType.NONE) {
World world = camera.getFocusedEntity().getWorld(); World world = camera.getFocusedEntity().getWorld();
if(world.getRegistryKey() == World.OVERWORLD && !getConfig().renderOverworldFog) if (world.getRegistryKey() == World.OVERWORLD && !getConfig().renderOverworldFog)
renderFog = false; renderFog = false;
else if(world.getRegistryKey() == World.NETHER && !getConfig().renderNetherFog) else if (world.getRegistryKey() == World.NETHER && !getConfig().renderNetherFog)
renderFog = false; renderFog = false;
else if(world.getRegistryKey() == World.END && !getConfig().renderEndFog) else if (world.getRegistryKey() == World.END && !getConfig().renderEndFog)
renderFog = false; renderFog = false;
} else if(subType == CameraSubmersionType.WATER && !getConfig().renderWaterFog) } else if (subType == CameraSubmersionType.WATER && !getConfig().renderWaterFog)
renderFog = false; renderFog = false;
else if(subType == CameraSubmersionType.LAVA && !getConfig().renderLavaFog) else if (subType == CameraSubmersionType.LAVA && !getConfig().renderLavaFog)
renderFog = false; renderFog = false;
else if(subType == CameraSubmersionType.POWDER_SNOW && !getConfig().renderSnowFog) else if (subType == CameraSubmersionType.POWDER_SNOW && !getConfig().renderSnowFog)
renderFog = false; renderFog = false;
if(!renderFog) if (!renderFog)
cir.setReturnValue(new Fog(-8.0f, 1_000_000.0F, FogShape.CYLINDER, 0,0,0,0)); cir.setReturnValue(EMPTY_FOG);
} }
} }

View File

@ -13,8 +13,8 @@ public abstract class EntityMixin {
@Inject(method = "setYaw", at = @At("HEAD"), cancellable = true) @Inject(method = "setYaw", at = @At("HEAD"), cancellable = true)
private void preventYawChange(float yaw, CallbackInfo ci) { private void preventYawChange(float yaw, CallbackInfo ci) {
if((Object) this instanceof ClientPlayerEntity player) { if ((Object) this instanceof ClientPlayerEntity player) {
if(player.isMainPlayer() && AngleViewer.PREVENT_HEAD_MOVEMENT) { if (player.isMainPlayer() && AngleViewer.PREVENT_HEAD_MOVEMENT) {
ci.cancel(); ci.cancel();
} }
} }
@ -22,8 +22,8 @@ public abstract class EntityMixin {
@Inject(method = "setPitch", at = @At("HEAD"), cancellable = true) @Inject(method = "setPitch", at = @At("HEAD"), cancellable = true)
private void preventPitchChange(float pitch, CallbackInfo ci) { private void preventPitchChange(float pitch, CallbackInfo ci) {
if((Object) this instanceof ClientPlayerEntity player) { if ((Object) this instanceof ClientPlayerEntity player) {
if(player.isMainPlayer() && AngleViewer.PREVENT_HEAD_MOVEMENT) { if (player.isMainPlayer() && AngleViewer.PREVENT_HEAD_MOVEMENT) {
ci.cancel(); ci.cancel();
} }
} }

View File

@ -55,7 +55,6 @@ public class ConfigScreen extends Screen {
} }
} }
// Done button
this.addDrawableChild(ButtonWidget.builder( this.addDrawableChild(ButtonWidget.builder(
Text.translatable("gui.done"), Text.translatable("gui.done"),
button -> this.client.setScreen(parent) button -> this.client.setScreen(parent)

View File

@ -8,5 +8,5 @@
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1
} }
} }

View File

@ -1,7 +1,6 @@
package wtf.hak.survivalfabric; package wtf.hak.survivalfabric;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents;
import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents; import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
@ -11,37 +10,36 @@ import org.slf4j.LoggerFactory;
import wtf.hak.survivalfabric.commands.ReloadConfigCommand; import wtf.hak.survivalfabric.commands.ReloadConfigCommand;
import wtf.hak.survivalfabric.commands.SlimeChunkCommand; import wtf.hak.survivalfabric.commands.SlimeChunkCommand;
import wtf.hak.survivalfabric.commands.SpectatorCommand; import wtf.hak.survivalfabric.commands.SpectatorCommand;
import wtf.hak.survivalfabric.sharedenderchest.SharedEnderChest; import wtf.hak.survivalfabric.features.sharedenderchest.SharedEnderChest;
import wtf.hak.survivalfabric.veinminer.VeinMinerEvents; import wtf.hak.survivalfabric.features.veinminer.VeinMinerEvents;
import static wtf.hak.survivalfabric.config.ConfigManager.getConfig; import static wtf.hak.survivalfabric.config.ConfigManager.getConfig;
public class SurvivalFabric implements ModInitializer { public class SurvivalFabric implements ModInitializer {
public static final String MOD_ID = "survivalfabric"; public static final String MOD_ID = "survivalfabric";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID); public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
@Override @Override
public void onInitialize() { public void onInitialize() {
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> SpectatorCommand.register(dispatcher, new String[] { "spectator", "s", "S", "camera", "c", "C", })); CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> SpectatorCommand.register(dispatcher, "spectator", "s", "S", "camera", "c", "C"));
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> ReloadConfigCommand.register(dispatcher, new String[] { "reloadsurvivalconfig" })); CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> ReloadConfigCommand.register(dispatcher, "reloadsurvivalconfig"));
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> SlimeChunkCommand.register(dispatcher, new String[] { "slimechunk", "sc" })); CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> SlimeChunkCommand.register(dispatcher, "slimechunk", "sc"));
if(getConfig().sharedEnderChestEnabled) if (getConfig().sharedEnderChestEnabled)
new SharedEnderChest().onInitialize(); new SharedEnderChest().onInitialize();
if(getConfig().veinMinerEnabled) { if (getConfig().veinMinerEnabled) {
PlayerBlockBreakEvents.BEFORE.register((world, player, pos, state, blockEntity) -> { PlayerBlockBreakEvents.BEFORE.register((world, player, pos, state, blockEntity) -> {
if (player instanceof ServerPlayerEntity serverPlayer) { if (player instanceof ServerPlayerEntity serverPlayer) {
return VeinMinerEvents.beforeBlockBreak(world, serverPlayer, pos, state); return VeinMinerEvents.beforeBlockBreak(world, serverPlayer, pos, state);
} } else {
else { return true;
return true; }
} });
});
ServerEntityEvents.ENTITY_LOAD.register(VeinMinerEvents::onEntityLoad); ServerEntityEvents.ENTITY_LOAD.register(VeinMinerEvents::onEntityLoad);
} }
} }
} }

View File

@ -6,11 +6,9 @@ import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.command.ServerCommandSource;
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.random.CheckedRandom;
import net.minecraft.util.math.random.ChunkRandom; import net.minecraft.util.math.random.ChunkRandom;
import net.minecraft.util.math.random.Random; import net.minecraft.util.math.random.Random;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import wtf.hak.survivalfabric.config.ConfigManager;
import static wtf.hak.survivalfabric.config.ConfigManager.getConfig; import static wtf.hak.survivalfabric.config.ConfigManager.getConfig;
@ -31,7 +29,7 @@ public class SlimeChunkCommand {
ServerPlayerEntity p = (ServerPlayerEntity) source.getEntity(); ServerPlayerEntity p = (ServerPlayerEntity) source.getEntity();
Chunk chunk = p.getServerWorld().getChunk(p.getBlockPos()); Chunk chunk = p.getServerWorld().getChunk(p.getBlockPos());
Random slimeRandom = ChunkRandom.getSlimeRandom(chunk.getPos().x, chunk.getPos().z, p.getServerWorld().getSeed(), 987234911L); Random slimeRandom = ChunkRandom.getSlimeRandom(chunk.getPos().x, chunk.getPos().z, p.getServerWorld().getSeed(), 987234911L);
if(slimeRandom.nextInt(10) == 0) { if (slimeRandom.nextInt(10) == 0) {
p.sendMessage(Text.literal(getConfig().inSlimeChunkMessage)); p.sendMessage(Text.literal(getConfig().inSlimeChunkMessage));
} else } else
p.sendMessage(Text.literal(getConfig().notInSlimeChunkMessage)); p.sendMessage(Text.literal(getConfig().notInSlimeChunkMessage));

View File

@ -8,7 +8,7 @@ import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.world.GameMode; import net.minecraft.world.GameMode;
import wtf.hak.survivalfabric.utils.Utils; import wtf.hak.survivalfabric.utils.PacketUtils;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -36,7 +36,7 @@ public class SpectatorCommand {
player.teleport(data.world, data.x, data.y, data.z, Set.of(), data.yaw, data.pitch, false); player.teleport(data.world, data.x, data.y, data.z, Set.of(), data.yaw, data.pitch, false);
player.changeGameMode(GameMode.SURVIVAL); player.changeGameMode(GameMode.SURVIVAL);
spectating.remove(player); spectating.remove(player);
Utils.updateListNames(player); PacketUtils.updateListNames(player);
} else { } else {
spectating.put(player, new LocationData(player spectating.put(player, new LocationData(player
@ -47,7 +47,7 @@ public class SpectatorCommand {
.getPitch(), player .getPitch(), player
.getServerWorld())); .getServerWorld()));
player.changeGameMode(GameMode.SPECTATOR); player.changeGameMode(GameMode.SPECTATOR);
Utils.updateListNames(player); PacketUtils.updateListNames(player);
} }
return 1; return 1;
} }

View File

@ -24,7 +24,7 @@ public class ConfigManager {
} }
public static Config load() { public static Config load() {
try(FileReader reader = new FileReader(CONFIG_FILE)) { try (FileReader reader = new FileReader(CONFIG_FILE)) {
INSTANCE = GSON.fromJson(reader, Config.class); INSTANCE = GSON.fromJson(reader, Config.class);
if (INSTANCE.configVersion.equalsIgnoreCase(new Config().configVersion)) { if (INSTANCE.configVersion.equalsIgnoreCase(new Config().configVersion)) {
return INSTANCE; return INSTANCE;
@ -41,7 +41,7 @@ public class ConfigManager {
} }
public static void save(Config config) { public static void save(Config config) {
try(FileWriter writer = new FileWriter(CONFIG_FILE)) { try (FileWriter writer = new FileWriter(CONFIG_FILE)) {
GSON.toJson(config, writer); GSON.toJson(config, writer);
} catch (IOException e) { } catch (IOException e) {
System.out.println("Error saving config: " + e.getMessage()); System.out.println("Error saving config: " + e.getMessage());

View File

@ -1,15 +1,9 @@
package wtf.hak.survivalfabric.sharedenderchest; package wtf.hak.survivalfabric.features.sharedenderchest;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.minecraft.block.Blocks;
import net.minecraft.block.EnderChestBlock; import net.minecraft.block.EnderChestBlock;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventories; import net.minecraft.inventory.Inventories;
@ -23,11 +17,14 @@ import net.minecraft.server.MinecraftServer;
import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents; import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.*; import net.minecraft.util.ActionResult;
import net.minecraft.util.WorldSavePath;
import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import java.io.*;
import static wtf.hak.survivalfabric.SurvivalFabric.LOGGER; import static wtf.hak.survivalfabric.SurvivalFabric.LOGGER;
import static wtf.hak.survivalfabric.config.ConfigManager.getConfig; import static wtf.hak.survivalfabric.config.ConfigManager.getConfig;
@ -37,6 +34,51 @@ public class SharedEnderChest implements ServerLifecycleEvents.ServerStopping, S
private long ticksUntilSave = -20; private long ticksUntilSave = -20;
public static void saveInventory(MinecraftServer server) {
File inventoryFile = getFile(server);
NbtCompound nbt = new NbtCompound();
DefaultedList<ItemStack> inventoryItemStacks = DefaultedList.ofSize(getConfig().sharedEnderChestRows * 9, ItemStack.EMPTY);
Inventories.writeNbt(nbt, sharedInventory.getList(inventoryItemStacks), server.getRegistryManager());
try (FileOutputStream inventoryFileOutputStream = new FileOutputStream(inventoryFile);
DataOutputStream inventoryFileDataOutput = new DataOutputStream(inventoryFileOutputStream)) {
inventoryFile.createNewFile();
NbtIo.writeCompressed(nbt, inventoryFileDataOutput);
} catch (Exception e) {
LOGGER.error("Error while saving Shared Ender Chest: " + e);
}
}
public static void openSharedEnderChest(PlayerEntity player, World world, BlockPos pos) {
fakeEnderChestOpen(world, pos, true);
sharedInventory.openedEnderChests.put(player, pos);
player.openHandledScreen(new SimpleNamedScreenHandlerFactory((int_1, playerInventory, playerEntity) ->
new GenericContainerScreenHandler(getConfig().screenHandlerType(), int_1, playerInventory, sharedInventory, getConfig().sharedEnderChestRows), Text.of(getConfig().sharedEnderChestName)));
}
public static void playEnderChestOpenSound(World world, BlockPos pos) {
world.playSound(null, pos, SoundEvents.BLOCK_ENDER_CHEST_OPEN, SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F);
}
public static void playEnderChestCloseSound(World world, BlockPos pos) {
world.playSound(null, pos, SoundEvents.BLOCK_ENDER_CHEST_CLOSE, SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F);
}
public static void fakeEnderChestOpen(World world, BlockPos pos, boolean open) {
if (!(world.getBlockState(pos).getBlock() instanceof EnderChestBlock)) {
return;
}
if (open)
playEnderChestOpenSound(world, pos);
else
playEnderChestCloseSound(world, pos);
world.addSyncedBlockEvent(pos, Blocks.ENDER_CHEST, 1, open ? 1 : 0);
}
private static File getFile(MinecraftServer server) {
return server.getSavePath(WorldSavePath.ROOT).resolve("sharedenderchest.sav").toFile();
}
public void onServerStarted(MinecraftServer server) { public void onServerStarted(MinecraftServer server) {
File inventoryFile = getFile(server); File inventoryFile = getFile(server);
if (inventoryFile.exists()) { if (inventoryFile.exists()) {
@ -55,19 +97,6 @@ public class SharedEnderChest implements ServerLifecycleEvents.ServerStopping, S
} }
} }
public static void saveInventory(MinecraftServer server) {
File inventoryFile = getFile(server);
NbtCompound nbt = new NbtCompound();
DefaultedList<ItemStack> inventoryItemStacks = DefaultedList.ofSize(getConfig().sharedEnderChestRows * 9, ItemStack.EMPTY);
Inventories.writeNbt(nbt, sharedInventory.getList(inventoryItemStacks), server.getRegistryManager());
try (FileOutputStream inventoryFileOutputStream = new FileOutputStream(inventoryFile);
DataOutputStream inventoryFileDataOutput = new DataOutputStream(inventoryFileOutputStream)) {
inventoryFile.createNewFile();
NbtIo.writeCompressed(nbt, inventoryFileDataOutput);
} catch (Exception e) {
LOGGER.error("Error while saving Shared Ender Chest: " + e);
}
}
public void onServerStopping(MinecraftServer server) { public void onServerStopping(MinecraftServer server) {
saveInventory(server); saveInventory(server);
} }
@ -86,17 +115,15 @@ public class SharedEnderChest implements ServerLifecycleEvents.ServerStopping, S
if (world.getBlockState(hitResult.getBlockPos()).getBlock() instanceof EnderChestBlock) { if (world.getBlockState(hitResult.getBlockPos()).getBlock() instanceof EnderChestBlock) {
if (!player.isSpectator()) { if (!player.isSpectator()) {
if(!getConfig().sharedEnderChestLimitedAccess) { if (!getConfig().sharedEnderChestLimitedAccess) {
if (world.isClient()) return ActionResult.SUCCESS; if (world.isClient()) return ActionResult.SUCCESS;
playEnderChestOpenSound(world, hitResult.getBlockPos()); openSharedEnderChest(player, world, hitResult.getBlockPos());
openSharedEnderChest(player);
return ActionResult.SUCCESS; return ActionResult.SUCCESS;
} else { } else {
for(String name : getConfig().sharedEnderChestNames) { for (String name : getConfig().sharedEnderChestNames) {
if(name.toLowerCase().strip().equalsIgnoreCase(player.getNameForScoreboard().toLowerCase())) { if (name.toLowerCase().strip().equalsIgnoreCase(player.getNameForScoreboard().toLowerCase())) {
if (world.isClient()) return ActionResult.SUCCESS; if (world.isClient()) return ActionResult.SUCCESS;
playEnderChestOpenSound(world, hitResult.getBlockPos()); openSharedEnderChest(player, world, hitResult.getBlockPos());
openSharedEnderChest(player);
return ActionResult.SUCCESS; return ActionResult.SUCCESS;
} }
} }
@ -113,17 +140,4 @@ public class SharedEnderChest implements ServerLifecycleEvents.ServerStopping, S
} }
public static void openSharedEnderChest(PlayerEntity player) {
player.openHandledScreen(new SimpleNamedScreenHandlerFactory((int_1, playerInventory, playerEntity) ->
new GenericContainerScreenHandler(getConfig().screenHandlerType(), int_1, playerInventory, sharedInventory, getConfig().sharedEnderChestRows), Text.of(getConfig().sharedEnderChestName)));
}
public static void playEnderChestOpenSound(World world, BlockPos pos) {
world.playSound(null, pos, SoundEvents.BLOCK_ENDER_CHEST_OPEN, SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.1F + 0.9F);
}
private static File getFile(MinecraftServer server) {
return server.getSavePath(WorldSavePath.ROOT).resolve("sharedenderchest.sav").toFile();
}
} }

View File

@ -1,13 +1,18 @@
package wtf.hak.survivalfabric.sharedenderchest; package wtf.hak.survivalfabric.features.sharedenderchest;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventories; import net.minecraft.inventory.Inventories;
import net.minecraft.inventory.Inventory; import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.math.BlockPos;
import java.util.HashMap;
import java.util.Map;
public class SharedInventory implements Inventory { public class SharedInventory implements Inventory {
public final Map<PlayerEntity, BlockPos> openedEnderChests = new HashMap<>();
private final DefaultedList<ItemStack> stacks; private final DefaultedList<ItemStack> stacks;
public SharedInventory(int inventoryRows) { public SharedInventory(int inventoryRows) {
@ -40,7 +45,7 @@ public class SharedInventory implements Inventory {
} }
itemStack_1 = var1.next(); itemStack_1 = var1.next();
} while(itemStack_1.isEmpty()); } while (itemStack_1.isEmpty());
return false; return false;
} }
@ -52,8 +57,7 @@ public class SharedInventory implements Inventory {
@Override @Override
public ItemStack removeStack(int int_1, int int_2) { public ItemStack removeStack(int int_1, int int_2) {
ItemStack itemStack_1 = Inventories.splitStack(this.stacks, int_1, int_2); return Inventories.splitStack(this.stacks, int_1, int_2);
return itemStack_1;
} }
@Override @Override
@ -80,4 +84,12 @@ public class SharedInventory implements Inventory {
public void clear() { public void clear() {
stacks.clear(); stacks.clear();
} }
@Override
public void onClose(PlayerEntity player) {
BlockPos pos = openedEnderChests.remove(player);
if (openedEnderChests.containsValue(pos))
return;
SharedEnderChest.fakeEnderChestOpen(player.getWorld(), pos, false);
}
} }

View File

@ -1,10 +1,12 @@
package wtf.hak.survivalfabric.veinminer; package wtf.hak.survivalfabric.features.veinminer;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
public interface Drill { public interface Drill {
boolean canHandle(BlockState blockState); boolean canHandle(BlockState blockState);
boolean isRightTool(BlockPos pos); boolean isRightTool(BlockPos pos);
boolean drill(BlockPos blockPos); boolean drill(BlockPos blockPos);
} }

View File

@ -1,15 +1,14 @@
package wtf.hak.survivalfabric.veinminer; package wtf.hak.survivalfabric.features.veinminer;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.registry.Registries;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import wtf.hak.survivalfabric.veinminer.drills.LeavesDrill; import wtf.hak.survivalfabric.features.veinminer.drills.LeavesDrill;
import wtf.hak.survivalfabric.veinminer.drills.OreDrill; import wtf.hak.survivalfabric.features.veinminer.drills.OreDrill;
import wtf.hak.survivalfabric.veinminer.drills.WoodDrill; import wtf.hak.survivalfabric.features.veinminer.drills.WoodDrill;
public class VeinMinerEvents { public class VeinMinerEvents {
@ -21,26 +20,25 @@ public class VeinMinerEvents {
boolean isVeinMining = VeinMinerSession.sessionForPlayer(player) != null; boolean isVeinMining = VeinMinerSession.sessionForPlayer(player) != null;
boolean canVeinMine = player.isInSneakingPose(); boolean canVeinMine = player.isInSneakingPose();
if (canVeinMine && !isVeinMining) { if (canVeinMine && !isVeinMining) {
VeinMinerSession session = VeinMinerSession.start(player, (ServerWorld)world, pos); VeinMinerSession session = VeinMinerSession.start(player, (ServerWorld) world, pos);
boolean shouldContinue = !mine(session); boolean shouldContinue = !mine(session);
session.finish(); session.finish();
return shouldContinue; return shouldContinue;
} } else {
else {
return true; return true;
} }
} }
public static void onEntityLoad(Entity entity, ServerWorld world) { public static void onEntityLoad(Entity entity, ServerWorld world) {
BlockPos pos = entity.getBlockPos(); BlockPos pos = entity.getBlockPos();
VeinMinerSession session = VeinMinerSession.sessionForPosition(pos); VeinMinerSession session = VeinMinerSession.sessionForPosition(pos);
if (session != null) { if (session != null) {
entity.setPos(session.initialPos.getX(), session.initialPos.getY(), session.initialPos.getZ()); entity.setPos(session.initialPos.getX(), session.initialPos.getY(), session.initialPos.getZ());
} }
} }
private static boolean mine(VeinMinerSession session) { private static boolean mine(VeinMinerSession session) {
Drill[] drills = new Drill[] { Drill[] drills = new Drill[]{
new OreDrill(session), new OreDrill(session),
new WoodDrill(session), new WoodDrill(session),
new LeavesDrill(session) new LeavesDrill(session)

View File

@ -1,23 +1,31 @@
package wtf.hak.survivalfabric.veinminer; package wtf.hak.survivalfabric.features.veinminer;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
public class VeinMinerSession { public class VeinMinerSession {
private static ArrayList<VeinMinerSession> sessions = new ArrayList<>(); private static final ArrayList<VeinMinerSession> sessions = new ArrayList<>();
public ServerPlayerEntity player; public ServerPlayerEntity player;
public ServerWorld world; public ServerWorld world;
public Set<BlockPos> positions; public Set<BlockPos> positions;
public BlockPos initialPos; public BlockPos initialPos;
private VeinMinerSession(ServerPlayerEntity player, ServerWorld world, BlockPos initialPos) {
this.player = player;
this.world = world;
this.initialPos = initialPos;
this.positions = new HashSet<>();
positions.add(initialPos);
}
public static VeinMinerSession sessionForPlayer(ServerPlayerEntity player) { public static VeinMinerSession sessionForPlayer(ServerPlayerEntity player) {
for (var session: sessions) { for (var session : sessions) {
if (session.player == player) { if (session.player == player) {
return session; return session;
} }
@ -26,7 +34,7 @@ public class VeinMinerSession {
} }
public static VeinMinerSession sessionForPosition(BlockPos position) { public static VeinMinerSession sessionForPosition(BlockPos position) {
for (var session: sessions) { for (var session : sessions) {
if (session.positions.contains(position)) { if (session.positions.contains(position)) {
return session; return session;
} }
@ -44,14 +52,6 @@ public class VeinMinerSession {
sessions.remove(session); sessions.remove(session);
} }
private VeinMinerSession(ServerPlayerEntity player, ServerWorld world, BlockPos initialPos) {
this.player = player;
this.world = world;
this.initialPos = initialPos;
this.positions = new HashSet<>();
positions.add(initialPos);
}
public void addPosition(BlockPos pos) { public void addPosition(BlockPos pos) {
positions.add(pos); positions.add(pos);
} }

View File

@ -1,15 +1,15 @@
package wtf.hak.survivalfabric.veinminer.drills; package wtf.hak.survivalfabric.features.veinminer.drills;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import java.util.ArrayList;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.MutableText; import net.minecraft.text.MutableText;
import net.minecraft.text.PlainTextContent; import net.minecraft.text.PlainTextContent;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import wtf.hak.survivalfabric.veinminer.Drill; import wtf.hak.survivalfabric.features.veinminer.Drill;
import wtf.hak.survivalfabric.veinminer.VeinMinerSession; import wtf.hak.survivalfabric.features.veinminer.VeinMinerSession;
import java.util.ArrayList;
import static wtf.hak.survivalfabric.SurvivalFabric.LOGGER; import static wtf.hak.survivalfabric.SurvivalFabric.LOGGER;
@ -37,14 +37,6 @@ public class DrillBase implements Drill {
return session.player.getMainHandStack().isSuitableFor(blockState); return session.player.getMainHandStack().isSuitableFor(blockState);
} }
protected interface ForXYZHandler {
public void handle(BlockPos pos);
}
protected interface ForXYZCounter {
public int handle(BlockPos pos);
}
protected void forXYZ(BlockPos pos, int max, ForXYZHandler handler) { protected void forXYZ(BlockPos pos, int max, ForXYZHandler handler) {
forXYZ(pos, max, handlerPos -> { forXYZ(pos, max, handlerPos -> {
handler.handle(handlerPos); handler.handle(handlerPos);
@ -72,33 +64,30 @@ public class DrillBase implements Drill {
} }
} }
String[] order = new String[] { "x", "y", "z" }; String[] order = new String[]{"x", "y", "z"};
if (forceVertical) { if (forceVertical) {
order = new String[] { "y", "x", "z" }; order = new String[]{"y", "x", "z"};
} } else {
else {
ServerPlayerEntity player = session.player; ServerPlayerEntity player = session.player;
boolean majorPitchChange = player.getPitch() < -45.0 || player.getPitch() > 45.0; boolean majorPitchChange = player.getPitch() < -45.0 || player.getPitch() > 45.0;
boolean majorYawChange = (player.getYaw() > 45.0 && player.getYaw() < 135.0) || (player.getYaw() < -45.0 && player.getYaw() > -135.0); boolean majorYawChange = (player.getYaw() > 45.0 && player.getYaw() < 135.0) || (player.getYaw() < -45.0 && player.getYaw() > -135.0);
if (majorPitchChange) { if (majorPitchChange) {
if (majorYawChange) { if (majorYawChange) {
order = new String[] { "y", "z", "x" }; order = new String[]{"y", "z", "x"};
} else {
order = new String[]{"y", "x", "z"};
} }
else { } else {
order = new String[] { "y", "x", "z" };
}
}
else {
if (majorYawChange) { if (majorYawChange) {
order = new String[] { "z", "y", "x" }; order = new String[]{"z", "y", "x"};
} }
} }
} }
int counter = 0; int counter = 0;
for (int i1: offsets) { for (int i1 : offsets) {
for (int i2: offsets) { for (int i2 : offsets) {
for (int i3: offsets) { for (int i3 : offsets) {
int ix = order[0] == "x" ? i1 : order[1] == "x" ? i2 : i3; int ix = order[0] == "x" ? i1 : order[1] == "x" ? i2 : i3;
int iy = order[0] == "y" ? i1 : order[1] == "y" ? i2 : i3; int iy = order[0] == "y" ? i1 : order[1] == "y" ? i2 : i3;
int iz = order[0] == "z" ? i1 : order[1] == "z" ? i2 : i3; int iz = order[0] == "z" ? i1 : order[1] == "z" ? i2 : i3;
@ -130,4 +119,12 @@ public class DrillBase implements Drill {
session.player.sendMessage(text); session.player.sendMessage(text);
LOGGER.info(message); LOGGER.info(message);
} }
protected interface ForXYZHandler {
void handle(BlockPos pos);
}
protected interface ForXYZCounter {
int handle(BlockPos pos);
}
} }

View File

@ -1,4 +1,4 @@
package wtf.hak.survivalfabric.veinminer.drills; package wtf.hak.survivalfabric.features.veinminer.drills;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -7,7 +7,7 @@ import net.minecraft.registry.tag.TagKey;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import wtf.hak.survivalfabric.veinminer.VeinMinerSession; import wtf.hak.survivalfabric.features.veinminer.VeinMinerSession;
import java.util.ArrayDeque; import java.util.ArrayDeque;
@ -15,12 +15,12 @@ import static wtf.hak.survivalfabric.config.ConfigManager.getConfig;
public class LeavesDrill extends DrillBase { public class LeavesDrill extends DrillBase {
public static final TagKey<Block> leavesTag = TagKey.of(RegistryKeys.BLOCK, Identifier.of("survivalfabric", "leaves"));
public LeavesDrill(VeinMinerSession session) { public LeavesDrill(VeinMinerSession session) {
super(session); super(session);
} }
public static final TagKey<Block> leavesTag = TagKey.of(RegistryKeys.BLOCK, Identifier.of("survivalfabric", "leaves"));
@Override @Override
public boolean canHandle(BlockState blockState) { public boolean canHandle(BlockState blockState) {
return blockState.isIn(leavesTag); return blockState.isIn(leavesTag);

View File

@ -1,4 +1,4 @@
package wtf.hak.survivalfabric.veinminer.drills; package wtf.hak.survivalfabric.features.veinminer.drills;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -6,23 +6,21 @@ import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.tag.TagKey; import net.minecraft.registry.tag.TagKey;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import wtf.hak.survivalfabric.features.veinminer.VeinMinerSession;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import net.minecraft.registry.Registries;
import net.minecraft.util.math.BlockPos;
import wtf.hak.survivalfabric.veinminer.VeinMinerSession;
import static wtf.hak.survivalfabric.config.ConfigManager.getConfig; import static wtf.hak.survivalfabric.config.ConfigManager.getConfig;
public class OreDrill extends DrillBase { public class OreDrill extends DrillBase {
public static final TagKey<Block> oreTag = TagKey.of(RegistryKeys.BLOCK, Identifier.of("survivalfabric", "ore"));
public OreDrill(VeinMinerSession session) { public OreDrill(VeinMinerSession session) {
super(session); super(session);
} }
public static final TagKey<Block> oreTag = TagKey.of(RegistryKeys.BLOCK, Identifier.of("survivalfabric", "ore"));
@Override @Override
public boolean canHandle(BlockState blockState) { public boolean canHandle(BlockState blockState) {
return blockState.isIn(oreTag); return blockState.isIn(oreTag);

View File

@ -1,29 +1,27 @@
package wtf.hak.survivalfabric.veinminer.drills; package wtf.hak.survivalfabric.features.veinminer.drills;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.registry.Registries;
import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.tag.TagKey; import net.minecraft.registry.tag.TagKey;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import wtf.hak.survivalfabric.features.veinminer.VeinMinerSession;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import net.minecraft.block.Block;
import net.minecraft.registry.Registries;
import net.minecraft.util.math.BlockPos;
import wtf.hak.survivalfabric.veinminer.VeinMinerSession;
import static wtf.hak.survivalfabric.config.ConfigManager.getConfig; import static wtf.hak.survivalfabric.config.ConfigManager.getConfig;
public class WoodDrill extends DrillBase { public class WoodDrill extends DrillBase {
public static final TagKey<Block> woodTag = TagKey.of(RegistryKeys.BLOCK, Identifier.of("survivalfabric", "wood"));
public WoodDrill(VeinMinerSession session) { public WoodDrill(VeinMinerSession session) {
super(session); super(session);
} }
public static final TagKey<Block> woodTag = TagKey.of(RegistryKeys.BLOCK, Identifier.of("survivalfabric", "wood"));
@Override @Override
public boolean canHandle(BlockState blockState) { public boolean canHandle(BlockState blockState) {
return blockState.isIn(woodTag); return blockState.isIn(woodTag);
@ -33,8 +31,8 @@ public class WoodDrill extends DrillBase {
public boolean drill(BlockPos startPos) { public boolean drill(BlockPos startPos) {
ServerWorld world = session.world; ServerWorld world = session.world;
int broken = 0; int broken = 0;
ArrayDeque<BlockPos> pendingLogs = new ArrayDeque<BlockPos>(); ArrayDeque<BlockPos> pendingLogs = new ArrayDeque<>();
ArrayDeque<BlockPos> logBlocks = new ArrayDeque<BlockPos>(); ArrayDeque<BlockPos> logBlocks = new ArrayDeque<>();
pendingLogs.add(startPos); pendingLogs.add(startPos);
String leavesBlockId = Registries.BLOCK.getId(world.getBlockState(startPos).getBlock()).toString().replace("_log", "_leaves"); String leavesBlockId = Registries.BLOCK.getId(world.getBlockState(startPos).getBlock()).toString().replace("_log", "_leaves");
@ -57,11 +55,8 @@ public class WoodDrill extends DrillBase {
} }
} }
// second round, leaves
// The pending blocks are all air now,
ArrayDeque<BlockPos> pendingLeaves = logBlocks; ArrayDeque<BlockPos> pendingLeaves = logBlocks;
while (!pendingLeaves.isEmpty() && broken < getConfig().maxVeinSize) { while (!pendingLeaves.isEmpty() && broken < getConfig().maxVeinSize) {
// remove the immediately surrounding leaves around the log blocks
broken += forXYZ(pendingLeaves.remove(), 1, newPos -> { broken += forXYZ(pendingLeaves.remove(), 1, newPos -> {
int brokenLeaves = 0; int brokenLeaves = 0;
Block newBlock = world.getBlockState(newPos).getBlock(); Block newBlock = world.getBlockState(newPos).getBlock();

View File

@ -1,10 +1,8 @@
package wtf.hak.survivalfabric.mixin; package wtf.hak.survivalfabric.mixin;
import com.mojang.authlib.minecraft.client.MinecraftClient;
import net.minecraft.network.ClientConnection; import net.minecraft.network.ClientConnection;
import net.minecraft.network.message.MessageType; import net.minecraft.network.message.MessageType;
import net.minecraft.network.message.SignedMessage; import net.minecraft.network.message.SignedMessage;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.PlayerManager; import net.minecraft.server.PlayerManager;
import net.minecraft.server.network.ConnectedClientData; import net.minecraft.server.network.ConnectedClientData;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
@ -18,9 +16,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import wtf.hak.survivalfabric.commands.SpectatorCommand; import wtf.hak.survivalfabric.commands.SpectatorCommand;
import wtf.hak.survivalfabric.config.ConfigManager; import wtf.hak.survivalfabric.config.ConfigManager;
import java.awt.*;
import java.beans.Expression;
import java.util.Objects;
import java.util.Set; import java.util.Set;
@Mixin(PlayerManager.class) @Mixin(PlayerManager.class)
@ -28,7 +23,7 @@ public abstract class PlayerManagerMixin {
@Inject(method = {"onPlayerConnect"}, at = {@At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V")}) @Inject(method = {"onPlayerConnect"}, at = {@At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V")})
public void onPlayerConnect(ClientConnection connection, ServerPlayerEntity player, ConnectedClientData clientData, CallbackInfo ci) { public void onPlayerConnect(ClientConnection connection, ServerPlayerEntity player, ConnectedClientData clientData, CallbackInfo ci) {
if(ConfigManager.getConfig().joinMessageEnabled && !player.getServer().isSingleplayer()) { if (ConfigManager.getConfig().joinMessageEnabled && !player.getServer().isSingleplayer()) {
Text text = Text.literal(String.format(ConfigManager.getConfig().joinMessage, player.getName().getString())); Text text = Text.literal(String.format(ConfigManager.getConfig().joinMessage, player.getName().getString()));
player.sendMessage(text, false); player.sendMessage(text, false);
} }
@ -36,7 +31,7 @@ public abstract class PlayerManagerMixin {
@ModifyArg(method = {"onPlayerConnect"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V")) @ModifyArg(method = {"onPlayerConnect"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V"))
private Text onPlayerConnect(Text text) { private Text onPlayerConnect(Text text) {
if(ConfigManager.getConfig().joinMessageEnabled) { if (ConfigManager.getConfig().joinMessageEnabled) {
String name = text.getString().split(" ")[0]; String name = text.getString().split(" ")[0];
return Text.literal(String.format(ConfigManager.getConfig().joinMessage, name)); return Text.literal(String.format(ConfigManager.getConfig().joinMessage, name));
} else } else
@ -45,24 +40,25 @@ public abstract class PlayerManagerMixin {
@Inject(method = {"remove"}, at = {@At("HEAD")}) @Inject(method = {"remove"}, at = {@At("HEAD")})
public void onPlayerLeave(ServerPlayerEntity player, CallbackInfo ci) { public void onPlayerLeave(ServerPlayerEntity player, CallbackInfo ci) {
if(SpectatorCommand.spectating.containsKey(player)) { if (SpectatorCommand.spectating.containsKey(player)) {
SpectatorCommand.LocationData loc = SpectatorCommand.spectating.remove(player); SpectatorCommand.LocationData loc = SpectatorCommand.spectating.remove(player);
player.teleport(loc.world, loc.x,loc.y,loc.z, Set.of(), loc.yaw, loc.pitch, false); player.teleport(loc.world, loc.x, loc.y, loc.z, Set.of(), loc.yaw, loc.pitch, false);
player.changeGameMode(GameMode.SURVIVAL); player.changeGameMode(GameMode.SURVIVAL);
} }
} }
@Inject(method = {"broadcast(Lnet/minecraft/network/message/SignedMessage;Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/network/message/MessageType$Parameters;)V"}, at = {@At("HEAD")}, cancellable = true) @Inject(method = {"broadcast(Lnet/minecraft/network/message/SignedMessage;Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/network/message/MessageType$Parameters;)V"}, at = {@At("HEAD")}, cancellable = true)
private void onBroadcast(SignedMessage message, ServerPlayerEntity sender, MessageType.Parameters parameters, CallbackInfo ci) { private void onBroadcast(SignedMessage message, ServerPlayerEntity sender, MessageType.Parameters parameters, CallbackInfo ci) {
if(sender != null && ConfigManager.getConfig().chatMessageEnabled) { if (sender != null && ConfigManager.getConfig().chatMessageEnabled) {
String rawMessage = message.getContent().getString().trim(); String rawMessage = message.getContent().getString().trim();
if(sender != null && ConfigManager.getConfig().chatCalcEnabled && rawMessage.endsWith("=")) { if (sender != null && ConfigManager.getConfig().chatCalcEnabled && rawMessage.endsWith("=")) {
String expression = rawMessage.substring(0, rawMessage.length() - 1).trim(); String expression = rawMessage.substring(0, rawMessage.length() - 1).trim();
try { try {
String result = String.valueOf(evaluateExpression(expression)); String result = String.valueOf(evaluateExpression(expression));
if(rawMessage.contains(" ")) rawMessage += " "; if (rawMessage.contains(" ")) rawMessage += " ";
rawMessage += (result.endsWith(".0")) ? result.substring(0, result.length() - 2) : result; rawMessage += (result.endsWith(".0")) ? result.substring(0, result.length() - 2) : result;
} catch (Exception e) {} } catch (Exception e) {
}
} }
Text text = Text.literal(String.format(ConfigManager.getConfig().chatMessage, sender.getName().getString(), rawMessage)); Text text = Text.literal(String.format(ConfigManager.getConfig().chatMessage, sender.getName().getString(), rawMessage));
sender.getServer().getPlayerManager().broadcast(text, false); sender.getServer().getPlayerManager().broadcast(text, false);
@ -73,12 +69,13 @@ public abstract class PlayerManagerMixin {
String expression = rawMessage.substring(0, rawMessage.length() - 1).trim(); String expression = rawMessage.substring(0, rawMessage.length() - 1).trim();
try { try {
String result = String.valueOf(evaluateExpression(expression)); String result = String.valueOf(evaluateExpression(expression));
if(rawMessage.contains(" ")) rawMessage += " "; if (rawMessage.contains(" ")) rawMessage += " ";
rawMessage += (result.endsWith(".0")) ? result.substring(0, result.length() - 2) : result; rawMessage += (result.endsWith(".0")) ? result.substring(0, result.length() - 2) : result;
Text formattedMessage = Text.literal("<" + sender.getName().getString() + "> " + rawMessage); Text formattedMessage = Text.literal("<" + sender.getName().getString() + "> " + rawMessage);
sender.getServer().getPlayerManager().broadcast(formattedMessage, false); sender.getServer().getPlayerManager().broadcast(formattedMessage, false);
ci.cancel(); ci.cancel();
} catch (Exception e) {} } catch (Exception e) {
}
} }
} }
} }

View File

@ -12,7 +12,7 @@ public abstract class ServerPlayNetworkHandlerMixin {
@ModifyArg(method = {"cleanUp"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V")) @ModifyArg(method = {"cleanUp"}, at = @At(value = "INVOKE", target = "Lnet/minecraft/server/PlayerManager;broadcast(Lnet/minecraft/text/Text;Z)V"))
private Text quitMessage(Text text) { private Text quitMessage(Text text) {
if(ConfigManager.getConfig().quitMessageEnabled) { if (ConfigManager.getConfig().quitMessageEnabled) {
String name = text.getString().split(" ")[0]; String name = text.getString().split(" ")[0];
return Text.literal(String.format(ConfigManager.getConfig().quitMessage, name)); return Text.literal(String.format(ConfigManager.getConfig().quitMessage, name));
} }

View File

@ -14,7 +14,7 @@ public abstract class ServerPlayerEntityMixin {
@Inject(method = "getPlayerListName", at = @At("HEAD"), cancellable = true) @Inject(method = "getPlayerListName", at = @At("HEAD"), cancellable = true)
private void changePlayerListName(CallbackInfoReturnable<Text> cir) { private void changePlayerListName(CallbackInfoReturnable<Text> cir) {
if(ConfigManager.getConfig().dimensionIndicatorEnabled) { if (ConfigManager.getConfig().dimensionIndicatorEnabled) {
ServerPlayerEntity p = (ServerPlayerEntity) (Object) this; ServerPlayerEntity p = (ServerPlayerEntity) (Object) this;
String world = p.getServerWorld().getRegistryKey().getValue().toTranslationKey(); String world = p.getServerWorld().getRegistryKey().getValue().toTranslationKey();
String finalName; String finalName;

View File

@ -7,15 +7,15 @@ import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; 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 wtf.hak.survivalfabric.utils.Utils; import wtf.hak.survivalfabric.utils.PacketUtils;
@Mixin(ServerWorld.class) @Mixin(ServerWorld.class)
public class ServerWorldMixin { public class ServerWorldMixin {
@Inject(method = "onDimensionChanged", at = {@At("HEAD")}) @Inject(method = "onDimensionChanged", at = {@At("HEAD")})
public void onDimensionChange(Entity entity, CallbackInfo ci) { public void onDimensionChange(Entity entity, CallbackInfo ci) {
if(entity instanceof ServerPlayerEntity) { if (entity instanceof ServerPlayerEntity) {
Utils.updateListNames((ServerPlayerEntity)entity); PacketUtils.updateListNames((ServerPlayerEntity) entity);
} }
} }
} }

View File

@ -5,10 +5,10 @@ import net.minecraft.server.network.ServerPlayerEntity;
import java.util.Objects; import java.util.Objects;
public class Utils { public class PacketUtils {
public static void updateListNames(ServerPlayerEntity p) { public static void updateListNames(ServerPlayerEntity p) {
for(ServerPlayerEntity sp : Objects.requireNonNull(p.getServer()).getPlayerManager().getPlayerList()) { for (ServerPlayerEntity sp : Objects.requireNonNull(p.getServer()).getPlayerManager().getPlayerList()) {
sp.networkHandler.sendPacket(new PlayerListS2CPacket(PlayerListS2CPacket.Action.UPDATE_DISPLAY_NAME, p)); sp.networkHandler.sendPacket(new PlayerListS2CPacket(PlayerListS2CPacket.Action.UPDATE_DISPLAY_NAME, p));
} }
} }

View File

@ -1,48 +1,48 @@
{ {
"schemaVersion": 1, "schemaVersion": 1,
"id": "survivalfabric", "id": "survivalfabric",
"version": "${version}", "version": "${version}",
"name": "SurvivalFabric", "name": "SurvivalFabric",
"description": "Adds a few QOL features to your Survival!", "description": "Adds a few QOL features to your Survival!",
"authors": [ "authors": [
"AlwaysHAK" "AlwaysHAK"
], ],
"contact": { "contact": {
"homepage": "https://hak.wtf", "homepage": "https://hak.wtf",
"sources": "https://git.hak.wtf/hkuijlman/SurvivalFabric", "sources": "https://git.hak.wtf/hkuijlman/SurvivalFabric",
"issues": "https://git.hak.wtf/hkuijlman/SurvivalFabric/issues" "issues": "https://git.hak.wtf/hkuijlman/SurvivalFabric/issues"
}, },
"license": "CC0-1.0", "license": "CC0-1.0",
"icon": "assets/survivalfabric/icon.png", "icon": "assets/survivalfabric/icon.png",
"environment": "*", "environment": "*",
"entrypoints": { "entrypoints": {
"main": [ "main": [
"wtf.hak.survivalfabric.SurvivalFabric" "wtf.hak.survivalfabric.SurvivalFabric"
], ],
"client": [ "client": [
"wtf.hak.survivalfabric.SurvivalFabricClient" "wtf.hak.survivalfabric.SurvivalFabricClient"
], ],
"fabric-datagen": [ "fabric-datagen": [
"wtf.hak.survivalfabric.SurvivalFabricDataGenerator" "wtf.hak.survivalfabric.SurvivalFabricDataGenerator"
], ],
"modmenu": [ "modmenu": [
"wtf.hak.survivalfabric.modmenu.ModMenuIntegration" "wtf.hak.survivalfabric.modmenu.ModMenuIntegration"
] ]
}, },
"mixins": [ "mixins": [
"survivalfabric.mixins.json", "survivalfabric.mixins.json",
{ {
"config": "survivalfabric.client.mixins.json", "config": "survivalfabric.client.mixins.json",
"environment": "client" "environment": "client"
} }
], ],
"depends": { "depends": {
"fabricloader": ">=0.16.10", "fabricloader": ">=0.16.10",
"minecraft": "~1.21.5", "minecraft": "~1.21.5",
"java": ">=21", "java": ">=21",
"fabric-api": "*" "fabric-api": "*"
}, },
"optional": { "optional": {
"modmenu": "*" "modmenu": "*"
} }
} }

View File

@ -10,5 +10,5 @@
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1
} }
} }