9
0
mirror of https://github.com/WiIIiam278/HuskSync.git synced 2025-12-24 17:19:19 +00:00

Compare commits

..

15 Commits
3.5.1 ... 3.5.3

Author SHA1 Message Date
William
c4adec3082 refactor: make more resilient against invalid effect types
Spigot has a potion effect API lookup mismatch bug (SPIGOT-7674) due to the deprecated methods we use to support 1.17
2024-05-29 00:08:40 +01:00
William
107238360c build: bump to 3.5.3 2024-05-28 21:57:56 +01:00
William
6141adbdb9 fix: attribute base values not being applied
modifiers were being applied, but in cases where the base value was edited, this was not
2024-05-28 21:57:26 +01:00
dependabot[bot]
eaa2ed74a6 deps: bump com.github.retrooper.packetevents:spigot from 2.2.1 to 2.3.0 (#305)
Bumps com.github.retrooper.packetevents:spigot from 2.2.1 to 2.3.0.

---
updated-dependencies:
- dependency-name: com.github.retrooper.packetevents:spigot
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-27 17:04:08 +01:00
William
44c652c452 Merge remote-tracking branch 'origin/master' 2024-05-27 01:52:24 +01:00
William
78cf6bff63 docs: add PacketEvents docs to config 2024-05-27 01:52:18 +01:00
William
8ad4158ec0 docs: document PacketEvents support 2024-05-27 01:52:08 +01:00
William
405e6d7162 deps: bump runtime dependencies 2024-05-27 01:50:27 +01:00
AlexDev_
cff1c8f982 feat: added PacketEvents support as ProtocolLib alternative (#296) 2024-05-27 01:46:44 +01:00
William
f43ca2f043 refactor: adjust BukkitKeyedAdapter logic, close #304 2024-05-27 01:43:47 +01:00
dependabot[bot]
3114ab1a62 deps: bump com.google.code.gson:gson from 2.10.1 to 2.11.0 (#302)
Bumps [com.google.code.gson:gson](https://github.com/google/gson) from 2.10.1 to 2.11.0.
- [Release notes](https://github.com/google/gson/releases)
- [Changelog](https://github.com/google/gson/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/gson/compare/gson-parent-2.10.1...gson-parent-2.11.0)

---
updated-dependencies:
- dependency-name: com.google.code.gson:gson
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-27 01:11:02 +01:00
dependabot[bot]
2da9749b0c deps: bump net.kyori:adventure-api from 4.16.0 to 4.17.0 (#300)
Bumps [net.kyori:adventure-api](https://github.com/KyoriPowered/adventure) from 4.16.0 to 4.17.0.
- [Release notes](https://github.com/KyoriPowered/adventure/releases)
- [Commits](https://github.com/KyoriPowered/adventure/compare/v4.16.0...v4.17.0)

---
updated-dependencies:
- dependency-name: net.kyori:adventure-api
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-27 01:10:54 +01:00
dependabot[bot]
d4d510e100 --- (#303)
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-27 01:10:29 +01:00
Preva1l
550ea26097 fix: MongoDB duplicate user table entries & not updating cached username (#301) 2024-05-13 10:50:58 +01:00
Preva1l
2b1e72a42e fix: wrong type in PostgreSQL schema (#299)
* Started impl for mongo

* fix silly mistake with postgresql

* fix silly mistake with postgresql
2024-05-10 19:06:34 +01:00
20 changed files with 214 additions and 58 deletions

View File

@@ -13,6 +13,7 @@ dependencies {
implementation 'de.tr7zw:item-nbt-api:2.12.4'
compileOnly 'org.spigotmc:spigot-api:1.17.1-R0.1-SNAPSHOT'
compileOnly 'com.github.retrooper.packetevents:spigot:2.3.0'
compileOnly 'com.comphenix.protocol:ProtocolLib:5.1.0'
compileOnly 'org.projectlombok:lombok:1.18.32'
compileOnly 'commons-io:commons-io:2.16.1'

View File

@@ -46,7 +46,6 @@ import net.william278.husksync.database.PostgresDatabase;
import net.william278.husksync.event.BukkitEventDispatcher;
import net.william278.husksync.hook.PlanHook;
import net.william278.husksync.listener.BukkitEventListener;
import net.william278.husksync.listener.EventListener;
import net.william278.husksync.migrator.LegacyMigrator;
import net.william278.husksync.migrator.Migrator;
import net.william278.husksync.migrator.MpdbMigrator;
@@ -98,7 +97,7 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync, BukkitTask.S
private MorePaperLib paperLib;
private Database database;
private RedisManager redisManager;
private EventListener eventListener;
private BukkitEventListener eventListener;
private DataAdapter dataAdapter;
private DataSyncer dataSyncer;
private LegacyConverter legacyConverter;
@@ -113,11 +112,10 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync, BukkitTask.S
private Server serverName;
@Override
public void onEnable() {
public void onLoad() {
// Initial plugin setup
this.disabling = false;
this.gson = createGson();
this.audiences = BukkitAudiences.create(this);
this.paperLib = new MorePaperLib(this);
// Load settings and locales
@@ -127,6 +125,13 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync, BukkitTask.S
loadServer();
});
this.eventListener = createEventListener();
eventListener.onLoad();
}
@Override
public void onEnable() {
this.audiences = BukkitAudiences.create(this);
// Prepare data adapter
initialize("data adapter", (plugin) -> {
if (settings.getSynchronization().isCompressData()) {
@@ -185,7 +190,7 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync, BukkitTask.S
});
// Register events
initialize("events", (plugin) -> this.eventListener = createEventListener());
initialize("events", (plugin) -> eventListener.onEnable());
// Register commands
initialize("commands", (plugin) -> BukkitCommand.Type.registerCommands(this));

View File

@@ -237,21 +237,20 @@ public abstract class BukkitData implements Data {
@NotNull
public static BukkitData.PotionEffects adapt(@NotNull Collection<Effect> effects) {
return from(
effects.stream()
.map(effect -> new PotionEffect(
Objects.requireNonNull(
PotionEffectType.getByName(effect.type()),
"Invalid potion effect type"
),
effect.duration(),
effect.amplifier(),
effect.isAmbient(),
effect.showParticles(),
effect.hasIcon()
))
.toList()
);
return from(effects.stream()
.map(effect -> {
final PotionEffectType type = matchEffectType(effect.type());
return type != null ? new PotionEffect(
type,
effect.duration(),
effect.amplifier(),
effect.isAmbient(),
effect.showParticles(),
effect.hasIcon()
) : null;
})
.filter(Objects::nonNull)
.toList());
}
@NotNull
@@ -616,7 +615,7 @@ public abstract class BukkitData implements Data {
if (instance == null) {
return;
}
instance.setBaseValue(attribute == null ? instance.getDefaultValue() : instance.getBaseValue());
instance.setBaseValue(attribute == null ? instance.getDefaultValue() : attribute.baseValue());
instance.getModifiers().forEach(instance::removeModifier);
if (attribute != null) {
attribute.modifiers().forEach(modifier -> instance.addModifier(new AttributeModifier(

View File

@@ -20,7 +20,6 @@
package net.william278.husksync.listener;
import net.william278.husksync.BukkitHuskSync;
import net.william278.husksync.HuskSync;
import net.william278.husksync.data.BukkitData;
import net.william278.husksync.user.BukkitUser;
import net.william278.husksync.user.OnlineUser;
@@ -40,21 +39,38 @@ import java.util.stream.Collectors;
public class BukkitEventListener extends EventListener implements BukkitJoinEventListener, BukkitQuitEventListener,
BukkitDeathEventListener, Listener {
protected final LockedHandler lockedHandler;
protected LockedHandler lockedHandler;
public BukkitEventListener(@NotNull BukkitHuskSync plugin) {
super(plugin);
plugin.getServer().getPluginManager().registerEvents(this, plugin);
this.lockedHandler = createLockedHandler(plugin);
}
public void onLoad() {
this.lockedHandler = createLockedHandler((BukkitHuskSync) plugin);
}
public void onEnable() {
getPlugin().getServer().getPluginManager().registerEvents(this, getPlugin());
lockedHandler.onEnable();
}
public void handlePluginDisable() {
super.handlePluginDisable();
lockedHandler.onDisable();
}
@NotNull
private LockedHandler createLockedHandler(@NotNull BukkitHuskSync plugin) {
if (getPlugin().isDependencyLoaded("ProtocolLib") && getPlugin().getSettings().isCancelPackets()) {
return new BukkitLockedPacketListener(plugin);
} else {
if (!getPlugin().getSettings().isCancelPackets()) {
return new BukkitLockedEventListener(plugin);
}
if (getPlugin().isDependencyLoaded("PacketEvents")) {
return new BukkitPacketEventsLockedPacketListener(plugin);
} else if (getPlugin().isDependencyLoaded("ProtocolLib")) {
return new BukkitProtocolLibLockedPacketListener(plugin);
}
return new BukkitLockedEventListener(plugin);
}
@Override
@@ -134,8 +150,8 @@ public class BukkitEventListener extends EventListener implements BukkitJoinEven
@NotNull
@Override
public HuskSync getPlugin() {
return plugin;
public BukkitHuskSync getPlugin() {
return (BukkitHuskSync) plugin;
}
}

View File

@@ -50,6 +50,10 @@ public class BukkitLockedEventListener implements LockedHandler, Listener {
protected BukkitLockedEventListener(@NotNull BukkitHuskSync plugin) {
this.plugin = plugin;
}
@Override
public void onEnable() {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}

View File

@@ -0,0 +1,103 @@
/*
* This file is part of HuskSync, licensed under the Apache License 2.0.
*
* Copyright (c) William278 <will27528@gmail.com>
* Copyright (c) contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.william278.husksync.listener;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.event.PacketListenerAbstract;
import com.github.retrooper.packetevents.event.PacketListenerPriority;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.google.common.collect.Sets;
import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder;
import net.william278.husksync.BukkitHuskSync;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
import java.util.logging.Level;
public class BukkitPacketEventsLockedPacketListener extends BukkitLockedEventListener implements LockedHandler {
protected BukkitPacketEventsLockedPacketListener(@NotNull BukkitHuskSync plugin) {
super(plugin);
}
@Override
public void onLoad() {
super.onLoad();
PacketEvents.setAPI(SpigotPacketEventsBuilder.build(getPlugin()));
PacketEvents.getAPI().getSettings().reEncodeByDefault(false)
.checkForUpdates(false)
.bStats(true);
PacketEvents.getAPI().load();
}
@Override
public void onEnable() {
super.onEnable();
PacketEvents.getAPI().getEventManager().registerListener(new PlayerPacketAdapter(this));
PacketEvents.getAPI().init();
plugin.log(Level.INFO, "Using PacketEvents to cancel packets for locked players");
}
private static class PlayerPacketAdapter extends PacketListenerAbstract {
private static final Set<PacketType.Play.Client> ALLOWED_PACKETS = Set.of(
PacketType.Play.Client.KEEP_ALIVE, PacketType.Play.Client.PONG, PacketType.Play.Client.PLUGIN_MESSAGE, // Connection packets
PacketType.Play.Client.CHAT_MESSAGE, PacketType.Play.Client.CHAT_COMMAND, PacketType.Play.Client.CHAT_SESSION_UPDATE, // Chat / command packets
PacketType.Play.Client.PLAYER_POSITION, PacketType.Play.Client.PLAYER_POSITION_AND_ROTATION, PacketType.Play.Client.PLAYER_ROTATION, // Movement packets
PacketType.Play.Client.HELD_ITEM_CHANGE, PacketType.Play.Client.ANIMATION, PacketType.Play.Client.TELEPORT_CONFIRM, // Animation packets
PacketType.Play.Client.CLIENT_SETTINGS // Video setting packets
);
private static final Set<PacketType.Play.Client> CANCEL_PACKETS = getPacketsToListenFor();
private final BukkitPacketEventsLockedPacketListener listener;
public PlayerPacketAdapter(@NotNull BukkitPacketEventsLockedPacketListener listener) {
super(PacketListenerPriority.HIGH);
this.listener = listener;
}
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if(!(event.getPacketType() instanceof PacketType.Play.Client client)) {
return;
}
if (!CANCEL_PACKETS.contains(client)) {
return;
}
if (listener.cancelPlayerEvent(event.getUser().getUUID())) {
event.setCancelled(true);
}
}
// Returns the set of ALL Server packets, excluding the set of allowed packets
@NotNull
private static Set<PacketType.Play.Client> getPacketsToListenFor() {
return Sets.difference(
Sets.newHashSet(PacketType.Play.Client.values()),
ALLOWED_PACKETS
);
}
}
}

View File

@@ -34,10 +34,15 @@ import java.util.stream.Collectors;
import static com.comphenix.protocol.PacketType.Play.Client;
public class BukkitLockedPacketListener extends BukkitLockedEventListener implements LockedHandler {
public class BukkitProtocolLibLockedPacketListener extends BukkitLockedEventListener implements LockedHandler {
protected BukkitLockedPacketListener(@NotNull BukkitHuskSync plugin) {
protected BukkitProtocolLibLockedPacketListener(@NotNull BukkitHuskSync plugin) {
super(plugin);
}
@Override
public void onEnable() {
super.onEnable();
ProtocolLibrary.getProtocolManager().addPacketListener(new PlayerPacketAdapter(this));
plugin.log(Level.INFO, "Using ProtocolLib to cancel packets for locked players");
}
@@ -53,9 +58,9 @@ public class BukkitLockedPacketListener extends BukkitLockedEventListener implem
Client.SETTINGS // Video setting packets
);
private final BukkitLockedPacketListener listener;
private final BukkitProtocolLibLockedPacketListener listener;
public PlayerPacketAdapter(@NotNull BukkitLockedPacketListener listener) {
public PlayerPacketAdapter(@NotNull BukkitProtocolLibLockedPacketListener listener) {
super(listener.getPlugin(), ListenerPriority.HIGHEST, getPacketsToListenFor());
this.listener = listener;
}

View File

@@ -19,38 +19,44 @@
package net.william278.husksync.util;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.Statistic;
import org.bukkit.*;
import org.bukkit.attribute.Attribute;
import org.bukkit.entity.EntityType;
import org.bukkit.potion.PotionEffectType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
// Utility class for adapting "Keyed" Bukkit objects
public final class BukkitKeyedAdapter {
@Nullable
public static Statistic matchStatistic(@NotNull String key) {
return Registry.STATISTIC.get(Objects.requireNonNull(NamespacedKey.fromString(key), "Null key"));
return getRegistryValue(Registry.STATISTIC, key);
}
@Nullable
public static EntityType matchEntityType(@NotNull String key) {
return Registry.ENTITY_TYPE.get(Objects.requireNonNull(NamespacedKey.fromString(key), "Null key"));
return getRegistryValue(Registry.ENTITY_TYPE, key);
}
@Nullable
public static Material matchMaterial(@NotNull String key) {
return Registry.MATERIAL.get(Objects.requireNonNull(NamespacedKey.fromString(key), "Null key"));
return getRegistryValue(Registry.MATERIAL, key);
}
@Nullable
public static Attribute matchAttribute(@NotNull String key) {
return Registry.ATTRIBUTE.get(Objects.requireNonNull(NamespacedKey.fromString(key), "Null key"));
return getRegistryValue(Registry.ATTRIBUTE, key);
}
@Nullable
public static PotionEffectType matchEffectType(@NotNull String key) {
return PotionEffectType.getByName(key); // No registry for this in 1.17 API
}
private static <T extends Keyed> T getRegistryValue(@NotNull Registry<T> registry, @NotNull String keyString) {
final NamespacedKey key = NamespacedKey.fromString(keyString);
return key != null ? registry.get(key) : null;
}
}

View File

@@ -7,6 +7,7 @@ description: '${description}'
website: 'https://william278.net'
folia-supported: true
softdepend:
- 'packetevents'
- 'ProtocolLib'
- 'MysqlPlayerDataBridge'
- 'Plan'

View File

@@ -7,7 +7,7 @@ dependencies {
api 'org.apache.commons:commons-text:1.12.0'
api 'net.william278:minedown:1.8.2'
api 'org.json:json:20240303'
api 'com.google.code.gson:gson:2.10.1'
api 'com.google.code.gson:gson:2.11.0'
api 'com.fatboyindustrial.gson-javatime-serialisers:gson-javatime-serialisers:1.1.2'
api 'de.exlll:configlib-yaml:4.5.0'
api 'net.william278:paginedown:1.1.2'
@@ -18,7 +18,7 @@ dependencies {
compileOnly 'org.projectlombok:lombok:1.18.32'
compileOnly 'org.jetbrains:annotations:24.1.0'
compileOnly 'net.kyori:adventure-api:4.16.0'
compileOnly 'net.kyori:adventure-api:4.17.0'
compileOnly 'net.kyori:adventure-platform-api:4.3.2'
compileOnly 'com.google.guava:guava:33.2.0-jre'
compileOnly 'com.github.plan-player-analytics:Plan:5.5.2272'

View File

@@ -75,7 +75,7 @@ public class Settings {
@Comment({"Whether to enable the Player Analytics hook.", "Docs: https://william278.net/docs/husksync/plan-hook"})
private boolean enablePlanHook = true;
@Comment("Whether to cancel game event packets directly when handling locked players if ProtocolLib is installed")
@Comment("Whether to cancel game event packets directly when handling locked players if ProtocolLib or PacketEvents is installed")
private boolean cancelPackets = true;

View File

@@ -113,7 +113,7 @@ public class MongoDbDatabase extends Database {
throw new MongoException("User document returned null!");
}
Bson updates = Updates.set("uuid", user.getUuid().toString());
Bson updates = Updates.set("username", user.getUsername());
mongoCollectionHelper.updateDocument(usersTable, doc, updates);
} catch (MongoException e) {
plugin.log(Level.SEVERE, "Failed to insert a user into the database", e);

View File

@@ -107,7 +107,7 @@ public abstract class EventListener {
/**
* Handle the plugin disabling
*/
public final void handlePluginDisable() {
public void handlePluginDisable() {
// Save for all online players
plugin.getOnlineUsers().stream()
.filter(user -> !plugin.isLocked(user.getUuid()) && !user.isNpc())

View File

@@ -54,4 +54,16 @@ public interface LockedHandler {
@ApiStatus.Internal
HuskSync getPlugin();
default void onLoad() {
}
default void onEnable() {
}
default void onDisable() {
}
}

View File

@@ -15,7 +15,7 @@ CREATE TABLE IF NOT EXISTS "%user_data_table%"
timestamp timestamp NOT NULL,
save_cause varchar(32) NOT NULL,
pinned boolean NOT NULL DEFAULT FALSE,
data longblob NOT NULL,
data bytea NOT NULL,
PRIMARY KEY (version_uuid, player_uuid),
FOREIGN KEY (player_uuid) REFERENCES "%users_table%" (uuid) ON DELETE CASCADE

View File

@@ -33,7 +33,7 @@ brigadier_tab_completion: false
# Whether to enable the Player Analytics hook.
# Docs: https://william278.net/docs/husksync/plan-hook
enable_plan_hook: true
# Whether to cancel game event packets directly when handling locked players if ProtocolLib is installed
# Whether to cancel game event packets directly when handling locked players if ProtocolLib or PacketEvents is installed
cancel_packets: true
# Database settings
database:

View File

@@ -11,7 +11,7 @@ This will walk you through installing HuskSync on your network of Spigot servers
### 1. Install the jar
- Place the plugin jar file in the `/plugins/` directory of each Spigot server.
- You do not need to install HuskSync as a proxy plugin.
- You can additionally install [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/) for better locked user handling, and [Plan](https://www.spigotmc.org/resources/plan-player-analytics.32536/) for analytics.
- You can additionally install [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997/) or [PacketEvents](https://www.spigotmc.org/resources/packetevents-api.80279/) for better locked user handling, and [Plan](https://www.spigotmc.org/resources/plan-player-analytics.32536/) for analytics.
### 2. Restart servers
- Start, then stop every server to let HuskSync generate the [[config file]].

View File

@@ -3,13 +3,13 @@ org.gradle.jvmargs='-Dfile.encoding=UTF-8'
org.gradle.daemon=true
javaVersion=17
plugin_version=3.5.1
plugin_version=3.5.3
plugin_archive=husksync
plugin_description=A modern, cross-server player data synchronization system
jedis_version=5.1.2
mysql_driver_version=8.3.0
mariadb_driver_version=3.3.3
jedis_version=5.1.3
mysql_driver_version=8.4.0
mariadb_driver_version=3.4.0
postgres_driver_version=42.7.3
mongodb_driver_version=5.0.1
mongodb_driver_version=5.1.0
snappy_version=1.1.10.5

View File

@@ -9,6 +9,10 @@ api-version: '1.19'
folia-supported: true
dependencies:
server:
packetevents:
required: false
load: BEFORE
join-classpath: true
ProtocolLib:
required: false
load: BEFORE

View File

@@ -2,6 +2,6 @@ certifi==2023.7.22
charset-normalizer==3.2.0
colorama==0.4.6
idna==3.7
requests==2.31.0
requests==2.32.0
tqdm==4.66.3
urllib3==2.0.7