-
Notifications
You must be signed in to change notification settings - Fork 302
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1652 from SamB440/feat/tag-sync
Synchronise server tags
- Loading branch information
Showing
8 changed files
with
181 additions
and
14 deletions.
There are no files selected for viewing
28 changes: 28 additions & 0 deletions
28
src/main/java/ac/grim/grimac/events/packets/PacketServerTags.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package ac.grim.grimac.events.packets; | ||
|
||
import ac.grim.grimac.GrimAPI; | ||
import ac.grim.grimac.player.GrimPlayer; | ||
import com.github.retrooper.packetevents.event.PacketListenerAbstract; | ||
import com.github.retrooper.packetevents.event.PacketSendEvent; | ||
import com.github.retrooper.packetevents.protocol.packettype.PacketType; | ||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerTags; | ||
|
||
public class PacketServerTags extends PacketListenerAbstract { | ||
|
||
@Override | ||
public void onPacketSend(PacketSendEvent event) { | ||
if (event.getPacketType() == PacketType.Play.Server.TAGS || event.getPacketType() == PacketType.Configuration.Server.UPDATE_TAGS) { | ||
GrimPlayer player = GrimAPI.INSTANCE.getPlayerDataManager().getPlayer(event.getUser()); | ||
if (player == null) return; | ||
|
||
WrapperPlayServerTags tags = new WrapperPlayServerTags(event); | ||
final boolean isPlay = event.getPacketType() == PacketType.Play.Server.TAGS; | ||
if (isPlay) { | ||
player.latencyUtils.addRealTimeTask(player.lastTransactionSent.get(), () -> player.tagManager.handleTagSync(tags)); | ||
} else { | ||
// This is during configuration stage, player isn't even in the game yet so no need to lag compensate. | ||
player.tagManager.handleTagSync(tags); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
src/main/java/ac/grim/grimac/utils/data/tags/SyncedTag.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package ac.grim.grimac.utils.data.tags; | ||
|
||
import com.github.retrooper.packetevents.resources.ResourceLocation; | ||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerTags; | ||
|
||
import java.util.HashSet; | ||
import java.util.Set; | ||
import java.util.function.Function; | ||
|
||
public final class SyncedTag<T> { | ||
|
||
private final ResourceLocation location; | ||
private final Set<T> values; | ||
private final Function<Integer, T> remapper; | ||
|
||
private SyncedTag(ResourceLocation location, Function<Integer, T> remapper, Set<T> defaultValues) { | ||
this.location = location; | ||
this.values = new HashSet<>(); | ||
this.remapper = remapper; | ||
this.values.addAll(defaultValues); | ||
} | ||
|
||
public static <T> Builder<T> builder(ResourceLocation location) { | ||
return new Builder<>(location); | ||
} | ||
|
||
public ResourceLocation location() { | ||
return location; | ||
} | ||
|
||
public boolean contains(T value) { | ||
return values.contains(value); | ||
} | ||
|
||
public void readTagValues(WrapperPlayServerTags.Tag tag) { | ||
// Server is sending tag replacement, clear default values. | ||
values.clear(); | ||
for (int id : tag.getValues()) { | ||
values.add(remapper.apply(id)); | ||
} | ||
} | ||
|
||
public static final class Builder<T> { | ||
private final ResourceLocation location; | ||
private Function<Integer, T> remapper; | ||
private Set<T> defaultValues; | ||
|
||
private Builder(ResourceLocation location) { | ||
this.location = location; | ||
} | ||
|
||
public Builder<T> remapper(Function<Integer, T> remapper) { | ||
this.remapper = remapper; | ||
return this; | ||
} | ||
|
||
public Builder<T> defaults(Set<T> defaultValues) { | ||
this.defaultValues = defaultValues; | ||
return this; | ||
} | ||
|
||
public SyncedTag<T> build() { | ||
return new SyncedTag<>(location, remapper, defaultValues); | ||
} | ||
} | ||
} |
65 changes: 65 additions & 0 deletions
65
src/main/java/ac/grim/grimac/utils/data/tags/SyncedTags.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package ac.grim.grimac.utils.data.tags; | ||
|
||
import ac.grim.grimac.player.GrimPlayer; | ||
import com.github.retrooper.packetevents.PacketEvents; | ||
import com.github.retrooper.packetevents.manager.server.ServerVersion; | ||
import com.github.retrooper.packetevents.protocol.player.ClientVersion; | ||
import com.github.retrooper.packetevents.protocol.world.states.defaulttags.BlockTags; | ||
import com.github.retrooper.packetevents.protocol.world.states.type.StateType; | ||
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes; | ||
import com.github.retrooper.packetevents.resources.ResourceLocation; | ||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerTags; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.function.Function; | ||
|
||
/** | ||
* This class stores tags that the client is aware of. | ||
*/ | ||
public final class SyncedTags { | ||
|
||
private static final ServerVersion VERSION = PacketEvents.getAPI().getServerManager().getVersion(); | ||
|
||
private static final ResourceLocation BLOCK = VERSION.isNewerThanOrEquals(ServerVersion.V_1_21) ? ResourceLocation.minecraft("block") : ResourceLocation.minecraft("blocks"); | ||
|
||
public static final ResourceLocation CLIMBABLE = ResourceLocation.minecraft("climbable"); | ||
|
||
private final GrimPlayer player; | ||
private final Map<ResourceLocation, Map<ResourceLocation, SyncedTag<?>>> synced; | ||
|
||
public SyncedTags(GrimPlayer player) { | ||
this.player = player; | ||
this.synced = new HashMap<>(); | ||
trackTags(BLOCK, id -> StateTypes.getById(player.getClientVersion(), id), | ||
SyncedTag.<StateType>builder(CLIMBABLE).defaults(BlockTags.CLIMBABLE.getStates())); | ||
} | ||
|
||
@SafeVarargs | ||
private final <T> void trackTags(ResourceLocation location, Function<Integer, T> remapper, SyncedTag.Builder<T>... syncedTags) { | ||
final Map<ResourceLocation, SyncedTag<?>> tags = new HashMap<>(syncedTags.length); | ||
for (SyncedTag.Builder<T> syncedTag : syncedTags) { | ||
syncedTag.remapper(remapper); | ||
final SyncedTag<T> built = syncedTag.build(); | ||
tags.put(built.location(), built); | ||
} | ||
synced.put(location, tags); | ||
} | ||
|
||
public SyncedTag<StateType> block(ResourceLocation tag) { | ||
final Map<ResourceLocation, SyncedTag<?>> blockTags = synced.get(BLOCK); | ||
return (SyncedTag<StateType>) blockTags.get(tag); | ||
} | ||
|
||
public void handleTagSync(WrapperPlayServerTags tags) { | ||
if (player.getClientVersion().isOlderThan(ClientVersion.V_1_13)) return; | ||
tags.getTagMap().forEach((location, tagList) -> { | ||
if (!synced.containsKey(location)) return; | ||
final Map<ResourceLocation, SyncedTag<?>> syncedTags = synced.get(location); | ||
tagList.forEach(tag -> { | ||
if (!syncedTags.containsKey(tag.getKey())) return; | ||
syncedTags.get(tag.getKey()).readTagValues(tag); | ||
}); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters