7 Commits

Author SHA1 Message Date
5eae9d4a8c Updated version number to 1.2.0 2025-03-25 21:18:47 +01:00
83cc3a38e9 Added back the tablist dimension indicator 2025-03-25 21:17:12 +01:00
7d4dca66f0 Created README.md 2025-03-25 19:35:11 +01:00
f6f0fc65d7 Removed GitHub workflow. It does not work with GitTea. 2025-03-25 17:35:29 +01:00
7b247ce2cc (Temporarily) Removed dimension indication to tab list due to a lot of bugs
Some checks failed
build / build (push) Has been cancelled
2025-03-18 21:28:04 +01:00
4894b7d389 Added dimension indication to tab list
Some checks failed
build / build (push) Has been cancelled
2025-03-18 16:06:43 +01:00
0ee3031742 Updated fabric.mod.json
Some checks failed
build / build (push) Has been cancelled
2025-03-18 14:27:17 +01:00
13 changed files with 131 additions and 51 deletions

View File

@ -1,30 +0,0 @@
# Automatically build the project and run any configured tests for every push
# and submitted pull request. This can help catch issues that only occur on
# certain platforms or Java versions, and provides a first line of defence
# against bad commits.
name: build
on: [pull_request, push]
jobs:
build:
runs-on: ubuntu-24.04
steps:
- name: checkout repository
uses: actions/checkout@v4
- name: validate gradle wrapper
uses: gradle/actions/wrapper-validation@v4
- name: setup jdk
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'microsoft'
- name: make gradle wrapper executable
run: chmod +x ./gradlew
- name: build
run: ./gradlew build
- name: capture build artifacts
uses: actions/upload-artifact@v4
with:
name: Artifacts
path: build/libs/

24
README.md Normal file
View File

@ -0,0 +1,24 @@
# Survival Fabric
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 ;) )
## Current feature-set
### Features
- Custom join message
- Custom quit message
- Custom chat message
- Tablist dimension indicator
### Commands
- /spectator | Essentially server-side freecam, you get put in spectator and are able to fly around, once you use the command again you get put back to where you were.
## Features to come
### Features
- Vein miner
- Telekinesis
- Shared Enderchest
- [ ] Shared for all
- [ ] Shared per team

View File

@ -9,7 +9,7 @@ yarn_mappings=1.21.4+build.8
loader_version=0.16.10
# Mod Properties
mod_version=1.0.0
mod_version=1.2.0
maven_group=wtf.hak.survivalfabric
archives_base_name=survivalfabric

View File

@ -3,11 +3,14 @@ package wtf.hak.survivalfabric;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents;
import net.minecraft.scoreboard.Team;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import wtf.hak.survivalfabric.commands.SpectatorCommand;
public class SurvivalFabric implements ModInitializer {
public static final String MOD_ID = "survivalfabric";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
@ -15,5 +18,6 @@ public class SurvivalFabric implements ModInitializer {
@Override
public void onInitialize() {
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> SpectatorCommand.register(dispatcher, new String[] { "spectator", "s", "S", "camera", "c", "C", }));
}
}

View File

@ -8,6 +8,7 @@ import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.Text;
import net.minecraft.world.GameMode;
import wtf.hak.survivalfabric.utils.Utils;
import java.util.HashMap;
import java.util.Map;
@ -19,22 +20,23 @@ public class SpectatorCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher, String... aliases) {
for (String str : aliases)
dispatcher.register(CommandManager.literal(str) // Ensure correct method name
dispatcher.register(CommandManager.literal(str)
.executes(SpectatorCommand::execute));
}
private static int execute(CommandContext<ServerCommandSource> context) {
ServerCommandSource source = context.getSource();
if (source.getEntity() == null) { // Ensure correct method name
if (source.getEntity() == null) {
source.sendMessage(Text.literal("Console cannot go into spectator mode!"));
return 0;
}
ServerPlayerEntity player = (ServerPlayerEntity) source.getEntity(); // Ensure correct method name
ServerPlayerEntity player = (ServerPlayerEntity) source.getEntity();
if (spectating.containsKey(player)) {
LocationData data = spectating.get(player);
player.teleport(data.world, data.x, data.y, data.z, Set.of(), data.yaw, data.pitch, false);
player.changeGameMode(GameMode.SURVIVAL);
spectating.remove(player);
Utils.updateListNames(player);
} else {
spectating.put(player, new LocationData(player
@ -45,6 +47,7 @@ public class SpectatorCommand {
.getPitch(), player
.getServerWorld()));
player.changeGameMode(GameMode.SPECTATOR);
Utils.updateListNames(player);
}
return 1;
}

View File

@ -6,9 +6,7 @@ import net.minecraft.network.message.SignedMessage;
import net.minecraft.server.PlayerManager;
import net.minecraft.server.network.ConnectedClientData;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.MutableText;
import net.minecraft.text.Text;
import net.minecraft.text.TextContent;
import net.minecraft.world.GameMode;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@ -18,6 +16,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import wtf.hak.survivalfabric.commands.SpectatorCommand;
import wtf.hak.survivalfabric.utils.Messages;
import java.util.Objects;
import java.util.Set;
@Mixin(PlayerManager.class)
@ -48,7 +47,7 @@ public abstract class PlayerManagerMixin {
private void onBroadcast(SignedMessage message, ServerPlayerEntity sender, MessageType.Parameters parameters, CallbackInfo ci) {
if(sender != null) {
Text text = Text.literal(String.format(Messages.CHAT_FORMAT, sender.getName().getString(), message.getContent().getString()));
sender.getServer().getPlayerManager().broadcast(text, false);
Objects.requireNonNull(sender.getServer()).getPlayerManager().broadcast(text, false);
ci.cancel();
}
}

View File

@ -15,4 +15,5 @@ public abstract class ServerPlayNetworkHandlerMixin {
String name = text.getString().split(" ")[0];
return Text.literal(String.format(Messages.QUIT_MESSAGE, name));
}
}

View File

@ -0,0 +1,34 @@
package wtf.hak.survivalfabric.mixin;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
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.CallbackInfoReturnable;
import wtf.hak.survivalfabric.commands.SpectatorCommand;
import wtf.hak.survivalfabric.utils.Messages;
@Mixin(ServerPlayerEntity.class)
public abstract class ServerPlayerEntityMixin {
@Inject(method = "getPlayerListName", at = @At("HEAD"), cancellable = true)
private void changePlayerListName(CallbackInfoReturnable<Text> cir) {
ServerPlayerEntity p = (ServerPlayerEntity) (Object) this;
String world = p.getServerWorld().getRegistryKey().getValue().toTranslationKey();
String finalName;
if(!SpectatorCommand.spectating.containsKey(p)) {
finalName = switch (world) {
case "minecraft.overworld" -> Messages.OVERWORLD_PREFIX;
case "minecraft.the_nether" -> Messages.NETHER_PREFIX;
case "minecraft.the_end" -> Messages.END_PREFIX;
default -> Messages.UNKNOWN_PREFIX;
};
} else
finalName = Messages.SPECTATOR_PREFIX;
finalName += "§7" + p.getName().getString();
cir.setReturnValue(Text.of(finalName));
}
}

View File

@ -0,0 +1,21 @@
package wtf.hak.survivalfabric.mixin;
import net.minecraft.entity.Entity;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
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;
import wtf.hak.survivalfabric.utils.Utils;
@Mixin(ServerWorld.class)
public class ServerWorldMixin {
@Inject(method = "onDimensionChanged", at = {@At("HEAD")})
public void onDimensionChange(Entity entity, CallbackInfo ci) {
if(entity instanceof ServerPlayerEntity) {
Utils.updateListNames((ServerPlayerEntity)entity);
}
}
}

View File

@ -6,4 +6,11 @@ public class Messages {
public static final String QUIT_MESSAGE = "§8[§c-§8] §7%s";
public static final String CHAT_FORMAT = "§7%s§8:§f %s";
public static final String OVERWORLD_PREFIX = "§8[§aOverworld§8] ";
public static final String NETHER_PREFIX = "§8[§cNether§8] ";
public static final String END_PREFIX = "§8[§dEnd§8] ";
public static final String SPECTATOR_PREFIX = "§8[§eSpectator§8] ";
public static final String UNKNOWN_PREFIX = "§8[§7Unknown§8] ";
}

View File

@ -0,0 +1,15 @@
package wtf.hak.survivalfabric.utils;
import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket;
import net.minecraft.server.network.ServerPlayerEntity;
import java.util.Objects;
public class Utils {
public static void updateListNames(ServerPlayerEntity p) {
for(ServerPlayerEntity sp : Objects.requireNonNull(p.getServer()).getPlayerManager().getPlayerList()) {
sp.networkHandler.sendPacket(new PlayerListS2CPacket(PlayerListS2CPacket.Action.UPDATE_DISPLAY_NAME, p));
}
}
}

View File

@ -3,13 +3,13 @@
"id": "survivalfabric",
"version": "${version}",
"name": "SurvivalFabric",
"description": "This is an example description! Tell everyone what your mod is about!",
"description": "Adds a few QOL features to your Survival!",
"authors": [
"Me!"
"AlwaysHAK"
],
"contact": {
"homepage": "https://fabricmc.net/",
"sources": "https://github.com/FabricMC/fabric-example-mod"
"homepage": "https://hak.wtf",
"sources": "https://git.hak.wtf/hkuijlman/SurvivalFabric"
},
"license": "CC0-1.0",
"icon": "assets/survivalfabric/icon.png",
@ -32,6 +32,6 @@
"fabric-api": "*"
},
"suggests": {
"another-mod": "*"
}
}

View File

@ -1,12 +1,14 @@
{
"required": true,
"package": "wtf.hak.survivalfabric.mixin",
"compatibilityLevel": "JAVA_21",
"mixins": [
"PlayerManagerMixin",
"ServerPlayNetworkHandlerMixin"
],
"injectors": {
"defaultRequire": 1
"required": true,
"package": "wtf.hak.survivalfabric.mixin",
"compatibilityLevel": "JAVA_21",
"mixins": [
"PlayerManagerMixin",
"ServerPlayerEntityMixin",
"ServerPlayNetworkHandlerMixin",
"ServerWorldMixin"
],
"injectors": {
"defaultRequire": 1
}
}