1
0
Fork 0

Compare commits

...

17 Commits

Author SHA1 Message Date
Ryan Fox fa28c8bed1
Add /tpa and /tpaccept 2023-06-13 16:24:46 -07:00
Ryan Fox 9358086717
Bump to 1.20 2023-06-11 14:48:04 -07:00
Ryan Fox b617dd4d54
Disable name / skin overrides by default 2023-06-09 20:01:43 -07:00
Ryan Fox e5a9c1b04d
Ignore Mojang's names & skins
Being able to control people's names and skins is loads of fun!
2023-05-31 20:45:46 -07:00
Ryan Fox ca09970fda
Bump to 1.19.4 2023-05-30 17:22:34 -07:00
Ryan Fox de8df562de
Bump to 1.19 2022-06-11 21:00:41 -07:00
Ryan Fox 94b26089a8
Bump to 1.18.2 2022-03-12 15:37:37 -08:00
Ryan Fox ff5774f3cb
Disable creeper explosions 2022-02-08 10:43:58 -08:00
Ryan Fox d7c1f5297a
Bring back /fly command
The persistentFlight option just kicks in flight whenever a player joins
the server mid-air. Servers with this will have the /fly command enabled
anyway, so it doesn't hurt.
2022-01-29 19:06:54 -08:00
Ryan Fox 8c51919e4e
Partial upgrade to 1.18.1 2022-01-29 17:18:37 -08:00
Ryan Fox 326e9cc4fc
Nuke README 2022-01-29 14:48:16 -08:00
Ryan Fox 5e3a9793e6
Add disableFlyCommand config option 2020-12-01 03:27:23 +00:00
Ryan Fox 95412f6cf8
Add more information to README.txt 2020-10-28 01:30:10 +00:00
Ryan Fox cbea81f9ce
Add persistent flight
When a player disconnects while flying in survival mode, they will
plummet to their deaths while reconnecting. These changes prevent that.
If a player is currently flying, their flight will not be disabled
unless the setGameMode method is called in the ServerPlayerEntity, which
is how the GameMode is usually set. Since the GameMode is initially set
using the interaction manager instead, players should be safe. :-)
2020-10-28 00:24:51 +00:00
Ryan Fox 037342e553
Add config value for persistent flight 2020-10-27 23:48:38 +00:00
Ryan Fox 6ff2142538
Add ASN field to players table
Ban evaders will often use the accounts of whitelisted users. This will
allow me to lock specific users into their ASN to prevent ban evaders
from connecting via VPNs or other residential connections (unless
they're from the same ISP).
2020-10-27 17:59:25 +00:00
Ryan Fox 320199d2a6
Add area-related tables to SQLite database
I am adding area protection to this mod since I have yet to find one for
Fabric, and people have been complaining about it for as long as I can
remember. (Honestly, I'd like it too.)
2020-10-27 06:45:26 +00:00
25 changed files with 522 additions and 94 deletions

View File

@ -1,6 +1,5 @@
minecraft-tweaks-2a03
This repository contains simple modifications for the 2a03.party Minecraft
server. I have replaced the patches with a Fabric mod.
Send questions, issues, and patches to flewkey@2a03.party.
minecraft-tweaks-2a03
Simple modifications for mc.2a03.party.
Send questions, issues, and patches to flewkey@2a03.party.

View File

@ -1,5 +1,5 @@
plugins {
id 'fabric-loom' version '0.4-SNAPSHOT'
id 'fabric-loom' version '1.2-SNAPSHOT'
}
repositories {
@ -9,13 +9,14 @@ repositories {
dependencies {
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modCompile "net.fabricmc:fabric-loader:${project.loader_version}"
modCompile "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
modCompile "org.json:json:20200518"
modCompile "org.xerial:sqlite-jdbc:3.32.3.2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
modImplementation "org.json:json:20211205"
modImplementation "org.xerial:sqlite-jdbc:3.36.0.3"
modImplementation "com.google.code.findbugs:jsr305:3.0.2"
include "org.json:json:20200518"
include "org.xerial:sqlite-jdbc:3.32.3.2"
include "org.json:json:20211205"
include "org.xerial:sqlite-jdbc:3.36.0.3"
}
jar {

View File

@ -1,8 +1,9 @@
org.gradle.jvmargs=-Xmx1G
minecraft_version=1.16.3
yarn_mappings=1.16.3+build.47
loader_version=0.10.3+build.211
org.gradle.parallel=true
minecraft_version=1.20
yarn_mappings=1.20+build.1
loader_version=0.14.21
mod_version=1.2.0
maven_group=party.2a03.mc
maven_group=party._2a03.mc
archives_base_name=minecraft-tweaks-2a03
fabric_version=0.24.1+build.412-1.16
fabric_version=0.83.0+1.20

View File

@ -1,8 +1,8 @@
package party._2a03.mc;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.registry.CommandRegistry;
import net.fabricmc.loader.api.FabricLoader;
import java.io.File;
import java.nio.file.Files;
@ -14,7 +14,10 @@ import party._2a03.mc.command.FlyCommand;
import party._2a03.mc.command.HatCommand;
import party._2a03.mc.command.HeadCommand;
import party._2a03.mc.command.HomeCommand;
import party._2a03.mc.command.NameCommand;
import party._2a03.mc.command.SkinCommand;
import party._2a03.mc.command.SpawnCommand;
import party._2a03.mc.command.TpaCommand;
import party._2a03.mc.util.Config;
import party._2a03.mc.util.Database;
@ -49,13 +52,18 @@ public class MinecraftTweaks2a03 implements ModInitializer {
Database.close();
});
LOGGER.info("Registering 2a03.party commands");
CommandRegistry.INSTANCE.register(false, dispatcher -> {
ConfigCommand.register(dispatcher);
FlyCommand.register(dispatcher);
HatCommand.register(dispatcher);
HeadCommand.register(dispatcher);
HomeCommand.register(dispatcher);
SpawnCommand.register(dispatcher);
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
if (environment.dedicated) {
ConfigCommand.register(dispatcher);
FlyCommand.register(dispatcher);
HatCommand.register(dispatcher);
HeadCommand.register(dispatcher);
HomeCommand.register(dispatcher);
NameCommand.register(dispatcher);
SkinCommand.register(dispatcher);
SpawnCommand.register(dispatcher);
TpaCommand.register(dispatcher);
}
});
}
}

View File

@ -4,7 +4,7 @@ import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import party._2a03.mc.util.Config;
public class ConfigCommand {
@ -17,9 +17,9 @@ public class ConfigCommand {
ServerCommandSource source = ctx.getSource();
try {
Config.loadConfig();
source.sendFeedback(new LiteralText("Reloaded the configuration"), true);
source.sendFeedback(() -> Text.of("Reloaded the configuration"), true);
} catch(Exception e) {
source.sendFeedback(new LiteralText("Failed to reload the configuration"), true);
source.sendFeedback(() -> Text.of("Failed to reload the configuration"), true);
}
return 1;
}));

View File

@ -1,23 +1,30 @@
package party._2a03.mc.command;
import com.mojang.brigadier.CommandDispatcher;
import net.minecraft.entity.player.PlayerAbilities;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import party._2a03.mc.util.Config;
public class FlyCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
dispatcher.register(CommandManager.literal("fly").executes(ctx -> {
ServerCommandSource source = ctx.getSource();
if (Config.getBool("disableFlyCommand")) {
source.sendFeedback(() -> Text.of("The /fly command is disabled"), true);
return 0;
}
ServerPlayerEntity sender = source.getPlayer();
boolean flight = sender.abilities.allowFlying;
sender.abilities.allowFlying = !flight;
PlayerAbilities abilities = sender.getAbilities();
boolean flight = abilities.allowFlying;
abilities.allowFlying = !flight;
if (!flight)
source.sendFeedback(new LiteralText("I wanna fly like an eagle... to the sea!"), true);
source.sendFeedback(() -> Text.of("I wanna fly like an eagle... to the sea!"), true);
else {
source.sendFeedback(new LiteralText("Flight disabled"), true);
sender.abilities.flying = false;
source.sendFeedback(() -> Text.of("Flight disabled"), true);
abilities.flying = false;
}
sender.sendAbilitiesUpdate();
return 1;

View File

@ -6,7 +6,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
public class HatCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
@ -17,7 +17,7 @@ public class HatCommand {
ItemStack head = sender.getEquippedStack(EquipmentSlot.HEAD);
sender.equipStack(EquipmentSlot.MAINHAND, head);
sender.equipStack(EquipmentSlot.HEAD, mainhand);
source.sendFeedback(new LiteralText("Swapped items between main hand and head"), false);
source.sendFeedback(() -> Text.of("Swapped items between main hand and head"), false);
return 1;
}));
}

View File

@ -6,11 +6,11 @@ import net.minecraft.block.Blocks;
import net.minecraft.entity.ItemEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
public class HeadCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
@ -23,13 +23,13 @@ public class HeadCommand {
private static int giveHead(ServerCommandSource source, ServerPlayerEntity sender, String skullowner) {
ItemStack itemstack = new ItemStack(Blocks.PLAYER_HEAD.asItem());
CompoundTag compoundtag = new CompoundTag();
compoundtag.putString("SkullOwner", skullowner);
itemstack.setTag(compoundtag);
NbtCompound nbt = new NbtCompound();
nbt.putString("SkullOwner", skullowner);
itemstack.setNbt(nbt);
ItemEntity itementity = sender.dropItem(itemstack, false);
itementity.resetPickupDelay();
itementity.setOwner(sender.getUuid());
source.sendFeedback(new LiteralText("Player head has been given"), false);
source.sendFeedback(() -> Text.of("Player head has been given"), false);
return 1;
}
}

View File

@ -3,15 +3,17 @@ package party._2a03.mc.command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.registry.RegistryKey;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.LiteralText;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.text.Text;
import party._2a03.mc.util.Database;
import party._2a03.mc.util.PlayerData;
import party._2a03.mc.util.PlayerPosition;
import java.util.UUID;
public class HomeCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
LiteralArgumentBuilder<ServerCommandSource> literalargumentbuilder = CommandManager.literal("home").executes(ctx -> {
@ -19,11 +21,11 @@ public class HomeCommand {
ServerPlayerEntity sender = source.getPlayer();
PlayerPosition position = Database.getPlayer(sender.getUuid().toString()).getHome();
if (position.registrykey == null) {
source.sendFeedback(new LiteralText("Home not found, do /home set"), false);
source.sendFeedback(() -> Text.of("Home not found, do /home set"), false);
return -1;
}
sender.teleport(sender.getServer().getWorld(position.registrykey), position.x, position.y, position.z, position.yaw, position.pitch);
source.sendFeedback(new LiteralText("Teleported to home"), true);
source.sendFeedback(() -> Text.of("Teleported to home"), true);
return 1;
});
@ -34,30 +36,31 @@ public class HomeCommand {
double x = sender.getX();
double y = sender.getY();
double z = sender.getZ();
float yaw = sender.yaw;
float pitch = sender.pitch;
RegistryKey registrykey = sender.getServerWorld().getRegistryKey();
float yaw = sender.getYaw();
float pitch = sender.getPitch();
RegistryKey registrykey = sender.getWorld().getRegistryKey();
PlayerPosition location = new PlayerPosition(x, y, z, yaw, pitch, registrykey);
playerdata.setHome(location);
source.sendFeedback(new LiteralText("Your home has been updated"), true);
source.sendFeedback(() -> Text.of("Your home has been updated"), true);
return 1;
}));
literalargumentbuilder.then(CommandManager.literal("sudoset").requires(ctx -> {
literalargumentbuilder.then(CommandManager.literal("assign").requires(ctx -> {
return ctx.hasPermissionLevel(2);
}).then(CommandManager.argument("UUID", StringArgumentType.word()).executes(ctx -> {
UUID uuid = UUID.fromString(StringArgumentType.getString(ctx, "UUID"));
ServerCommandSource source = ctx.getSource();
ServerPlayerEntity sender = source.getPlayer();
PlayerData playerdata = Database.getPlayer(StringArgumentType.getString(ctx, "UUID"));
PlayerData playerdata = Database.getPlayer(uuid);
double x = sender.getX();
double y = sender.getY();
double z = sender.getZ();
float yaw = sender.yaw;
float pitch = sender.pitch;
RegistryKey registrykey = sender.getServerWorld().getRegistryKey();
float yaw = sender.getYaw();
float pitch = sender.getPitch();
RegistryKey registrykey = sender.getWorld().getRegistryKey();
PlayerPosition location = new PlayerPosition(x, y, z, yaw, pitch, registrykey);
playerdata.setHome(location);
source.sendFeedback(new LiteralText("User's home has been updated (" + StringArgumentType.getString(ctx, "UUID") + ")"), true);
source.sendFeedback(() -> Text.of("User's home has been updated (" + uuid.toString() + ")"), true);
return 1;
})));

View File

@ -0,0 +1,32 @@
package party._2a03.mc.command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import party._2a03.mc.util.Database;
import party._2a03.mc.util.PlayerData;
import java.util.UUID;
public class NameCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
dispatcher.register(CommandManager.literal("name")
.then(CommandManager.literal("assign")
.requires(ctx -> { return ctx.hasPermissionLevel(2); })
.then(CommandManager.argument("UUID", StringArgumentType.word())
.then(CommandManager.argument("name", StringArgumentType.word())
.executes(ctx -> {
UUID uuid = UUID.fromString(StringArgumentType.getString(ctx, "UUID"));
ServerCommandSource source = ctx.getSource();
ServerPlayerEntity sender = source.getPlayer();
PlayerData playerdata = Database.getPlayer(uuid);
playerdata.setName(StringArgumentType.getString(ctx, "name"));
source.sendFeedback(() -> Text.of("User's name has been updated (" + uuid.toString() + ")"), true);
return 1;
})))));
}
}

View File

@ -0,0 +1,52 @@
package party._2a03.mc.command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import party._2a03.mc.util.Database;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.net.URL;
import java.util.UUID;
public class SkinCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
LiteralArgumentBuilder literalargumentbuilder = CommandManager.literal("skin");
literalargumentbuilder.then(CommandManager.literal("assign")
.requires(ctx -> { return ctx.hasPermissionLevel(2); })
.then(CommandManager.argument("UUID", StringArgumentType.word())
.then(CommandManager.argument("url", StringArgumentType.greedyString())
.executes(ctx -> {
ServerCommandSource source = ctx.getSource();
String magic, skinval, skinsig;
try {
URL url = new URL(StringArgumentType.getString(ctx, "url"));
BufferedReader read = new BufferedReader(new InputStreamReader(url.openStream()));
magic = read.readLine();
skinval = read.readLine();
skinsig = read.readLine();
read.close();
} catch (IOException e) {
source.sendFeedback(() -> Text.of("Failed to access skin"), false);
return 1;
}
if (!magic.equals("SKIN:1") || skinval == null || skinsig == null) {
source.sendFeedback(() -> Text.of("Invalid skin"), false);
return 1;
}
UUID uuid = UUID.fromString(StringArgumentType.getString(ctx, "UUID"));
Database.getPlayer(uuid).setTextures(skinval, skinsig);
source.sendFeedback(() -> Text.of("User's skin has been updated (" + uuid.toString() + ")"), true);
return 1;
}))));
dispatcher.register(literalargumentbuilder);
}
}

View File

@ -2,11 +2,11 @@ package party._2a03.mc.command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.registry.RegistryKey;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.LiteralText;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.text.Text;
import party._2a03.mc.util.Config;
import party._2a03.mc.util.PlayerPosition;
@ -18,14 +18,14 @@ public class SpawnCommand {
PlayerPosition position = new PlayerPosition(Config.getData("spawn"));
if (position.registrykey == null) {
if (source.hasPermissionLevel(2)) {
source.sendFeedback(new LiteralText("Spawn not found, do /spawn set"), false);
source.sendFeedback(() -> Text.of("Spawn not found, do /spawn set"), false);
} else {
source.sendFeedback(new LiteralText("Spawn not found, ask an admin to set it"), false);
source.sendFeedback(() -> Text.of("Spawn not found, ask an admin to set it"), false);
}
return -1;
}
sender.teleport(sender.getServer().getWorld(position.registrykey), position.x, position.y, position.z, position.yaw, position.pitch);
source.sendFeedback(new LiteralText("Teleported to the spawn point"), true);
source.sendFeedback(() -> Text.of("Teleported to the spawn point"), true);
return 1;
});
@ -37,12 +37,12 @@ public class SpawnCommand {
double x = sender.getX();
double y = sender.getY();
double z = sender.getZ();
float yaw = sender.yaw;
float pitch = sender.pitch;
RegistryKey registrykey = sender.getServerWorld().getRegistryKey();
float yaw = sender.getYaw();
float pitch = sender.getPitch();
RegistryKey registrykey = sender.getWorld().getRegistryKey();
PlayerPosition location = new PlayerPosition(x, y, z, yaw, pitch, registrykey);
Config.setData("spawn", location.getJSON());
source.sendFeedback(new LiteralText("Spawn has been set"), true);
source.sendFeedback(() -> Text.of("Spawn has been set"), true);
return 1;
}));

View File

@ -0,0 +1,102 @@
package party._2a03.mc.command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.command.argument.EntityArgumentType;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import java.util.Hashtable;
import java.util.UUID;
public class TpaCommand {
private static class TpaRequest {
private UUID requester;
private UUID accepter;
public TpaRequest(UUID requester, UUID accepter) {
this.requester = requester;
this.accepter = accepter;
}
@Override
public String toString() {
return requester.toString()+"->"+accepter.toString();
}
@Override
public int hashCode() {
return (requester.hashCode() << 1) ^ (accepter.hashCode() >> 1);
}
}
private static Hashtable<Integer, Long> requests = new Hashtable<>();
public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
dispatcher.register(CommandManager.literal("tpa")
.then(CommandManager.argument("target", EntityArgumentType.player())
.executes(TpaCommand::executeRequest)
)
);
dispatcher.register(CommandManager.literal("tpaccept")
.then(CommandManager.argument("target", EntityArgumentType.player())
.executes(TpaCommand::executeAccept)
)
);
}
private static int executeRequest(CommandContext<ServerCommandSource> ctx) throws CommandSyntaxException {
ServerCommandSource source = ctx.getSource();
ServerPlayerEntity source_player = source.getPlayer();
ServerPlayerEntity target_player = EntityArgumentType.getPlayer(ctx, "target");
final String source_name = source_player.getEntityName();
final String target_name = target_player.getEntityName();
if (source_player.getUuid() == target_player.getUuid()) {
source.sendFeedback(() -> Text.of("Teleported "+source_name+" to "+target_name), false);
return 0;
}
TpaRequest req = new TpaRequest(source_player.getUuid(), target_player.getUuid());
requests.put(req.hashCode(), System.currentTimeMillis());
source.sendFeedback(() -> Text.of("Requested to teleport to "+target_name), false);
target_player.sendMessage(Text.of(source_name+" requested to teleport to you"));
target_player.sendMessage(Text.of("Type /tpaccept "+source_name+" within 30 seconds to accept it"));
return 1;
}
private static int executeAccept(CommandContext<ServerCommandSource> ctx) throws CommandSyntaxException {
ServerCommandSource source = ctx.getSource();
ServerPlayerEntity source_player = source.getPlayer();
ServerPlayerEntity target_player = EntityArgumentType.getPlayer(ctx, "target");
final String source_name = source_player.getEntityName();
final String target_name = target_player.getEntityName();
TpaRequest req = new TpaRequest(target_player.getUuid(), source_player.getUuid());
Long req_time = requests.get(req.hashCode());
if (req_time == null) {
source.sendFeedback(() -> Text.of(target_name+" has not requested to teleport to you"), false);
return 0;
}
if (System.currentTimeMillis() - req_time.longValue() > 30e3) {
requests.remove(req.hashCode());
source.sendFeedback(() -> Text.of(target_name+"'s teleport request has expired"), false);
return 0;
}
if (source_player.getAbilities().flying && !target_player.getAbilities().flying) {
source.sendFeedback(() -> Text.of("Stop flying, dumbass! You'll kill them!"), false);
return 0;
}
requests.remove(req.hashCode());
target_player.teleport(source_player.getServerWorld(), source_player.getX(), source_player.getY(), source_player.getZ(), source_player.getYaw(), source_player.getPitch());
source.sendFeedback(() -> Text.of("Teleported "+target_name+" to "+source_name), false);
target_player.sendMessage(Text.of(target_name+" has accepted your teleport request"));
return 1;
}
}

View File

@ -0,0 +1,29 @@
package party._2a03.mc.mixin;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.Entity;
import net.minecraft.entity.mob.CreeperEntity;
import net.minecraft.entity.mob.HostileEntity;
import net.minecraft.world.World;
import net.minecraft.world.explosion.Explosion;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.Mixin;
import party._2a03.mc.util.Config;
@Mixin(CreeperEntity.class)
public abstract class MixinCreeperEntity extends HostileEntity {
public MixinCreeperEntity(EntityType<? extends CreeperEntity> entityType, World world) {
super((EntityType<? extends HostileEntity>)entityType, world);
}
@Redirect(method = "explode()V", at = @At(value = "INVOKE",
target = "Lnet/minecraft/world/World;createExplosion(Lnet/minecraft/entity/Entity;DDDFLnet/minecraft/world/World$ExplosionSourceType;)Lnet/minecraft/world/explosion/Explosion;"))
private Explosion OnCreeperExplode(World self, Entity entity,
double x, double y, double z, float r,
World.ExplosionSourceType explosionSourceType) {
if (Config.getBool("disableCreeperExplosions"))
explosionSourceType = World.ExplosionSourceType.NONE;
return self.createExplosion(entity, x, y, z, r, explosionSourceType);
}
}

View File

@ -1,21 +1,23 @@
package party._2a03.mc.mixin;
import java.util.Collection;
import com.mojang.brigadier.context.CommandContext;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.command.GameModeCommand;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.world.GameMode;
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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(GameModeCommand.class)
public class MixinGameModeCommand {
@Inject(method = "setGameMode", at = @At("HEAD"))
private static void OnSetGameMode(ServerCommandSource source, ServerPlayerEntity player, GameMode gameMode, CallbackInfo ci) {
@Inject(method = "execute", at = @At("HEAD"))
private static void OnExecute(CommandContext<ServerCommandSource> context, Collection<ServerPlayerEntity> targets, GameMode gameMode, CallbackInfoReturnable cir) {
if (gameMode == GameMode.CREATIVE) {
source.sendFeedback(new LiteralText("<Server> Creative mode? What are you, a cheater?"), false);
context.getSource().sendFeedback(() -> Text.of("<Server> Creative mode? What are you, a cheater?"), false);
}
return;
}

View File

@ -0,0 +1,36 @@
package party._2a03.mc.mixin;
import com.mojang.authlib.GameProfile;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import party._2a03.mc.util.Config;
import party._2a03.mc.util.Database;
import party._2a03.mc.util.PlayerData;
import java.util.UUID;
@Mixin(value = GameProfile.class, remap = false)
public class MixinGameProfile {
int ready = 0;
String server_name = "";
@Inject(method = "getName", at = @At("RETURN"), cancellable = true)
public void replaceName(CallbackInfoReturnable<String> ci) {
if (ready++ < 2) // wait until authenticated
return;
UUID uuid = ((GameProfile)(Object)this).getId();
if (uuid == null) // wait until UUID is set
return;
if (!Config.getBool("overrideNames"))
return;
if (this.server_name == "") {
PlayerData playerdata = Database.getPlayer(uuid.toString());
this.server_name = playerdata.getName();
}
ci.setReturnValue(this.server_name);
}
}

View File

@ -0,0 +1,45 @@
package party._2a03.mc.mixin;
import com.mojang.authlib.properties.PropertyMap;
import net.minecraft.entity.player.PlayerAbilities;
import net.minecraft.server.PlayerManager;
import net.minecraft.network.ClientConnection;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.world.GameMode;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import party._2a03.mc.util.Config;
import party._2a03.mc.util.Database;
import party._2a03.mc.util.PlayerData;
@Mixin(PlayerManager.class)
public abstract class MixinPlayerManager {
@Inject(method = "onPlayerConnect", at = @At(value = "HEAD"))
void onConnect(ClientConnection connection, ServerPlayerEntity player, CallbackInfo ci) {
if (!Config.getBool("overrideSkins"))
return;
PlayerData playerdata = Database.getPlayer(player.getGameProfile().getId());
PropertyMap map = player.getGameProfile().getProperties();
map.removeAll("textures");
map.put("textures", playerdata.getTextures());
}
@Inject(method = "onPlayerConnect", at = @At(value = "INVOKE",
target = "Lnet/minecraft/server/network/ServerPlayerEntity;getAbilities()Lnet/minecraft/entity/player/PlayerAbilities;"))
public void persistFlight(ClientConnection connection, ServerPlayerEntity player, CallbackInfo ci) {
if (!Config.getBool("persistentFlight"))
return;
if (player.isOnGround())
return;
GameMode gameMode = player.interactionManager.getGameMode();
if (gameMode == GameMode.CREATIVE || gameMode == GameMode.SPECTATOR)
return;
PlayerAbilities abilities = player.getAbilities();
abilities.allowFlying = true;
abilities.flying = true;
}
}

View File

@ -1,12 +1,14 @@
package party._2a03.mc.mixin;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.registry.RegistryKey;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.text.Text;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import party._2a03.mc.util.Config;

View File

@ -13,13 +13,9 @@ import party._2a03.mc.util.Config;
@Mixin(TntEntity.class)
public abstract class MixinTntEntity extends Entity {
@Shadow
private int fuseTimer;
public MixinTntEntity(EntityType<? extends TntEntity> entityType, World world) {
super(entityType, world);
this.fuseTimer = 80;
this.inanimate = true;
this.intersectionChecked = true;
}
@Inject(method = "explode", at = @At("HEAD"), cancellable = true)

View File

@ -35,7 +35,12 @@ public class Config {
json = new JSONObject();
}
setDefault("overrideNames", false);
setDefault("overrideSkins", false);
setDefault("persistentFlight", false);
setDefault("disableFlyCommand", true);
setDefault("disableTntExplosions", false);
setDefault("disableCreeperExplosions", false);
setDefault("disableRespawnAnchorExplosions", false);
setDefault("iphubApiKey", "");
setDefault("spawn", (new PlayerPosition()).getJSON());

View File

@ -13,6 +13,8 @@ import org.json.JSONArray;
import party._2a03.mc.util.PlayerData;
import party._2a03.mc.util.PlayerPosition;
import java.util.UUID;
public class Database {
private static final Logger LOGGER = LogManager.getLogger();
private static Connection conn = null;
@ -32,10 +34,32 @@ public class Database {
stmt = conn.createStatement();
stmt.executeUpdate(
"CREATE TABLE IF NOT EXISTS players (" +
"uuid TEXT NOT NULL UNIQUE," +
"home TEXT," +
"uuid TEXT NOT NULL UNIQUE," +
"name TEXT," +
"skinval TEXT," +
"skinsig TEXT," +
"home TEXT," +
"asn INTEGER," +
"PRIMARY KEY(uuid)" +
");");
stmt.executeUpdate(
"CREATE TABLE IF NOT EXISTS claims (" +
"id TEXT NOT NULL UNIQUE," +
"owner TEXT NOT NULL," +
"members TEXT NOT NULL," +
"rules TEXT NOT NULL," +
"PRIMARY KEY(id)" +
");");
stmt.executeUpdate(
"CREATE TABLE IF NOT EXISTS areas (" +
"chunk_x INTEGER NOT NULL," +
"chunk_z INTEGER NOT NULL," +
"min_x INTEGER NOT NULL," +
"min_z INTEGER NOT NULL," +
"max_x INTEGER NOT NULL," +
"max_z INTEGER NOT NULL," +
"claim TEXT NOT NULL" +
");");
stmt.close();
} catch (SQLException e) {
LOGGER.error(e.getMessage(), e);
@ -53,16 +77,26 @@ public class Database {
}
}
public static PlayerData getPlayer(UUID uuid) {
return getPlayer(uuid.toString());
}
public static PlayerData getPlayer(String uuid) {
try {
PreparedStatement pstmt;
pstmt = conn.prepareStatement(
"SELECT home FROM players WHERE uuid = ?;");
"SELECT home, name, skinval, skinsig FROM players WHERE uuid = ?;");
pstmt.setString(1, uuid);
ResultSet res = pstmt.executeQuery();
if (res.next()) {
PlayerPosition home = new PlayerPosition(new JSONArray(res.getString("home")));
return new PlayerData(uuid, home);
String homeData = res.getString("home");
PlayerPosition home = new PlayerPosition();
if (homeData != "" && homeData != null)
home = new PlayerPosition(new JSONArray(homeData));
String name = res.getString("name");
String skinval = res.getString("skinval");
String skinsig = res.getString("skinsig");
return new PlayerData(uuid, home, name, skinval, skinsig);
}
pstmt.close();
} catch (SQLException e) {
@ -71,6 +105,44 @@ public class Database {
return new PlayerData(uuid);
}
public static void setPlayerTextures(String uuid, String skinval, String skinsig) {
try {
PreparedStatement pstmt;
pstmt = conn.prepareStatement(
"INSERT INTO players (uuid, skinval, skinsig) " +
"VALUES(?, ?, ?) " +
"ON CONFLICT(uuid) " +
"DO UPDATE SET skinval=?, skinsig=?;");
pstmt.setString(1, uuid);
pstmt.setString(2, skinval);
pstmt.setString(3, skinsig);
pstmt.setString(4, skinval);
pstmt.setString(5, skinsig);
pstmt.executeUpdate();
pstmt.close();
} catch (SQLException e) {
LOGGER.error(e.getMessage(), e);
}
}
public static void setPlayerName(String uuid, String name) {
try {
PreparedStatement pstmt;
pstmt = conn.prepareStatement(
"INSERT INTO players (uuid, name) " +
"VALUES(?, ?) " +
"ON CONFLICT(uuid) " +
"DO UPDATE SET name=?;");
pstmt.setString(1, uuid);
pstmt.setString(2, name);
pstmt.setString(3, name);
pstmt.executeUpdate();
pstmt.close();
} catch (SQLException e) {
LOGGER.error(e.getMessage(), e);
}
}
public static void setPlayerHome(String uuid, PlayerPosition home) {
try {
PreparedStatement pstmt;

View File

@ -1,5 +1,6 @@
package party._2a03.mc.util;
import com.mojang.authlib.properties.Property;
import org.json.JSONArray;
import org.json.JSONObject;
import party._2a03.mc.util.Database;
@ -8,15 +9,33 @@ import party._2a03.mc.util.PlayerPosition;
public class PlayerData {
private String uuid;
private PlayerPosition home;
private String name;
private String skinval;
private String skinsig;
public PlayerData(String p_uuid) {
this.uuid = p_uuid;
this.home = new PlayerPosition();
}
public PlayerData(String p_uuid, PlayerPosition p_home) {
public PlayerData(String p_uuid, PlayerPosition p_home, String p_name, String p_skinval, String p_skinsig) {
this.uuid = p_uuid;
this.home = p_home;
this.name = p_name;
this.skinval = p_skinval;
this.skinsig = p_skinsig;
}
public Property getTextures() {
// Return a Steve texture if unset
if (this.skinval == null || this.skinsig == null || this.skinval.length() == 0 || this.skinsig.length() == 0)
return new Property("textures", "ewogICJ0aW1lc3RhbXAiIDogMTY2NjMwMjkxNzkzOCwKICAicHJvZmlsZUlkIiA6ICJjOWRlZTM4MDUzYjg0YzI5YjZlZjA5YjJlMDM5OTc0ZiIsCiAgInByb2ZpbGVOYW1lIiA6ICJTQVJfRGVjZW1iZXI1IiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzMxZjQ3N2ViMWE3YmVlZTYzMWMyY2E2NGQwNmY4ZjY4ZmE5M2EzMzg2ZDA0NDUyYWIyN2Y0M2FjZGYxYjYwY2IiCiAgICB9CiAgfQp9", "tTCtASRIyuzlNUgSoXgUr6arxABhCR4EQ9+eHaUoO8bADljmUFoQfb6oba8zqe2gIa2mnu5KQaOPQCxcTDjgNv9aIL2smINKxy/60VE4Mgnrh5ntH+mGuDi00V3Bk2CsObFZXz1vgk2UxdQUQ41eVQYm2xBrXFEbXMSoTafWGv0FMTPFpGxGRdduTe3QTEie3GcfAMHCn/9xMMmUxZZ6UVZ+mDe8ARt9/cmK+GmqT8m3kmrz/vq+i29KV4tWvJqsKIVAXm97jVPH9XxVR3tYlheimQSFNrCU8SzNPum/ZhxNAf5Uw90+/K0eaJE59y8tS7KDV5DHrRrHHXb/ywGGklSri1YjFm9AEBk6BeH8Y3Ot/e+zfQbF3rOny2DkBAm/v28FooYd25gXB4MjUFNPj3KdveQh7DpRAvnkmBZMqJCO+Z9fdY4Dw+jmqjII88r6mukWAODvXed/x8bvv55zzNOAxtqtwBTWHIdqWFr/7pMZF26RY1Tluw+pAWGWaKMHtqlGzyOLGMxMKwXqtLNEpIYw52ETwGKaWh8h34cOoI8dhpjfjym4UOihMmazK9LC0EUEHuBlgy5b/Ae71+6UsLNIX8bJwIvN16sP6wpSTNbV6htWoS7/ehvoxdKhI6XEUqWgEoAwmquClPfWiveCV057reoKeVHB9RdTl0sW+HM=");
// Otherwise...
return new Property("textures", this.skinval, this.skinsig);
}
public String getName() {
return (this.name == null || this.name.length() == 0) ? "Unknown" : this.name;
}
public PlayerPosition getHome() {
@ -27,6 +46,17 @@ public class PlayerData {
return this.uuid;
}
public void setTextures(String skinval, String skinsig) {
this.skinval = skinval;
this.skinsig = skinsig;
Database.setPlayerTextures(this.uuid, this.skinval, this.skinsig);
}
public void setName(String name) {
this.name = name;
Database.setPlayerName(this.uuid, this.name);
}
public void setHome(PlayerPosition location) {
this.home = location;
Database.setPlayerHome(this.uuid, this.home);
@ -36,6 +66,7 @@ public class PlayerData {
JSONObject json = new JSONObject();
json.put("uuid", uuid);
json.put("home", home.getJSON());
json.put("name", name);
return json;
}
}

View File

@ -1,9 +1,10 @@
package party._2a03.mc.util;
import org.json.JSONArray;
import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryKey;
public class PlayerPosition {
public double x;
@ -24,7 +25,7 @@ public class PlayerPosition {
this.z = data.getDouble(2);
this.yaw = data.getNumber(3).floatValue();
this.pitch = data.getNumber(4).floatValue();
this.registrykey = RegistryKey.of(Registry.DIMENSION, new Identifier(registry_string));
this.registrykey = RegistryKey.of(RegistryKeys.DIMENSION, new Identifier(registry_string));
}
}

View File

@ -2,17 +2,17 @@
"schemaVersion": 1,
"id": "minecraft-tweaks-2a03",
"version": "1.2.0",
"name": "2a03.party Tweaks",
"description": "Simple modifications for the 2a03.party Minecraft server.",
"name": "minecraft-tweaks-2a03",
"description": "Simple modifications for mc.2a03.party.",
"authors": [
"flewkey"
],
"contact": {
"homepage": "https://flewkey.com/",
"sources": "https://github.com/flewkey/minecraft-tweaks-2a03"
"sources": "https://git.sdf.org/flewkey/minecraft-tweaks-2a03"
},
"license": "MIT",
"icon": "assets/2a03-minecraft-tweaks/icon.png",
"icon": "assets/minecraft-tweaks-2a03/icon.png",
"environment": "*",
"entrypoints": {
"main": [
@ -23,8 +23,9 @@
"minecraft-tweaks-2a03.mixins.json"
],
"depends": {
"fabricloader": ">=0.8.2",
"fabric": "*",
"minecraft": "1.16.x"
"fabricloader": ">=0.14.21",
"fabric-api": "*",
"minecraft": "~1.20",
"java": ">=17"
}
}

View File

@ -1,9 +1,12 @@
{
"required": true,
"package": "party._2a03.mc.mixin",
"compatibilityLevel": "JAVA_8",
"compatibilityLevel": "JAVA_17",
"server": [
"MixinCreeperEntity",
"MixinGameModeCommand",
"MixinGameProfile",
"MixinPlayerManager",
"MixinRespawnAnchorBlock",
"MixinServerPlayerEntity",
"MixinTntBlock",