From b49ea8b4aad13f087d5bb121a35b2a832aab6e89 Mon Sep 17 00:00:00 2001 From: Pyrofab Date: Sat, 17 Oct 2020 00:37:24 +0200 Subject: [PATCH] Implement serverside ticking for scoreboard components --- README.md | 3 +- .../level/LevelComponentFactoryRegistry.java | 6 +++ .../level/StaticLevelComponentPlugin.java | 6 +++ .../ScoreboardComponentFactoryRegistry.java | 14 +++++ .../StaticScoreboardComponentPlugin.java | 11 ++++ .../scoreboard/StaticTeamComponentPlugin.java | 4 ++ .../scoreboard/MixinMinecraftServer.java | 51 +++++++++++++++++++ ...mixins.cardinal_components_scoreboard.json | 1 + changelog.md | 3 +- 9 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/mixin/scoreboard/MixinMinecraftServer.java diff --git a/README.md b/README.md index 512380d8..b03f6e60 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,8 @@ If you want your component to be **automatically synchronized with watching clie If you want your component to **tick alongside its provider**, you can add the [`ServerTickingComponent`](https://github.com/OnyxStudios/Cardinal-Components-API/blob/master/cardinal-components-base/src/main/java/dev/onyxstudios/cca/api/v3/component/ServerTickingComponent.java) or [`ClientTickingComponent`](https://github.com/OnyxStudios/Cardinal-Components-API/blob/master/cardinal-components-base/src/main/java/dev/onyxstudios/cca/api/v3/component/ClientTickingComponent.java) (or both) to your *component interface* (here, `IntComponent`). If you'd rather add the ticking interface to a single component subclass, you can use one of the specific methods provided in the individual modules. -*This feature is still experimental, and only implemented for entities, block entities, chunks, and worlds.* +*This feature is still experimental. Serverside ticking is implemented for all providers except item stacks. + Clientside ticking is only implemented for entities, block entities, and worlds.* The next step is to choose an identifier for your component, and to declare it in your `fabric.mod.json`'s custom properties: ```json diff --git a/cardinal-components-level/src/main/java/dev/onyxstudios/cca/api/v3/level/LevelComponentFactoryRegistry.java b/cardinal-components-level/src/main/java/dev/onyxstudios/cca/api/v3/level/LevelComponentFactoryRegistry.java index ae4f5544..52259b61 100644 --- a/cardinal-components-level/src/main/java/dev/onyxstudios/cca/api/v3/level/LevelComponentFactoryRegistry.java +++ b/cardinal-components-level/src/main/java/dev/onyxstudios/cca/api/v3/level/LevelComponentFactoryRegistry.java @@ -38,4 +38,10 @@ public interface LevelComponentFactoryRegistry { */ void register(ComponentKey type, LevelComponentFactory factory); + /** + * Registers a {@link LevelComponentFactory}. + * + * @param factory the factory to use to create components of the given type + */ + void register(ComponentKey type, Class impl, LevelComponentFactory factory); } diff --git a/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/StaticLevelComponentPlugin.java b/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/StaticLevelComponentPlugin.java index fa37d58b..d93c0568 100644 --- a/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/StaticLevelComponentPlugin.java +++ b/cardinal-components-level/src/main/java/dev/onyxstudios/cca/internal/level/StaticLevelComponentPlugin.java @@ -65,4 +65,10 @@ public void register(ComponentKey type, LevelComponentF this.checkLoading(LevelComponentFactoryRegistry.class, "register"); super.register(type, (props) -> Objects.requireNonNull(((LevelComponentFactory) factory).createForSave(props), "Component factory "+ factory + " for " + type.getId() + " returned null on " + props)); } + + @Override + public void register(ComponentKey type, Class impl, LevelComponentFactory factory) { + this.checkLoading(LevelComponentFactoryRegistry.class, "register"); + super.register(type, impl, (world) -> Objects.requireNonNull(((LevelComponentFactory) factory).createForSave(world), "Component factory "+ factory + " for " + type.getId() + " returned null on " + world.getClass().getSimpleName())); + } } diff --git a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/api/v3/scoreboard/ScoreboardComponentFactoryRegistry.java b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/api/v3/scoreboard/ScoreboardComponentFactoryRegistry.java index 2e67dc0d..27796482 100644 --- a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/api/v3/scoreboard/ScoreboardComponentFactoryRegistry.java +++ b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/api/v3/scoreboard/ScoreboardComponentFactoryRegistry.java @@ -38,10 +38,24 @@ public interface ScoreboardComponentFactoryRegistry { */ void register(ComponentKey type, TeamComponentFactory factory); + /** + * Registers a {@link TeamComponentFactory}. + * + * @param factory the factory to use to create components of the given type + */ + void registerForTeams(ComponentKey type, Class impl, TeamComponentFactory factory); + /** * Registers a {@link ScoreboardComponentFactory}. * * @param factory the factory to use to create components of the given type */ void register(ComponentKey type, ScoreboardComponentFactory factory); + + /** + * Registers a {@link ScoreboardComponentFactory}. + * + * @param factory the factory to use to create components of the given type + */ + void registerForScoreboards(ComponentKey type, Class impl, ScoreboardComponentFactory factory); } diff --git a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/StaticScoreboardComponentPlugin.java b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/StaticScoreboardComponentPlugin.java index 5378e249..c872e0c3 100644 --- a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/StaticScoreboardComponentPlugin.java +++ b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/StaticScoreboardComponentPlugin.java @@ -74,8 +74,19 @@ public void register(ComponentKey type, ScoreboardCompo super.register(type, (team) -> Objects.requireNonNull(((ScoreboardComponentFactory) factory).createForScoreboard(team), "Component factory "+ factory + " for " + type.getId() + " returned null on " + team.getClass().getSimpleName())); } + @Override + public void registerForScoreboards(ComponentKey type, Class impl, ScoreboardComponentFactory factory) { + this.checkLoading(ScoreboardComponentFactoryRegistry.class, "registerForScoreboards"); + super.register(type, impl, (team) -> Objects.requireNonNull(((ScoreboardComponentFactory) factory).createForScoreboard(team), "Component factory "+ factory + " for " + type.getId() + " returned null on " + team.getClass().getSimpleName())); + } + @Override public void register(ComponentKey type, TeamComponentFactory factory) { StaticTeamComponentPlugin.INSTANCE.register(type, factory); } + + @Override + public void registerForTeams(ComponentKey type, Class impl, TeamComponentFactory factory) { + StaticTeamComponentPlugin.INSTANCE.register(type, impl, factory); + } } diff --git a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/StaticTeamComponentPlugin.java b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/StaticTeamComponentPlugin.java index c0f15998..57459864 100644 --- a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/StaticTeamComponentPlugin.java +++ b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/internal/scoreboard/StaticTeamComponentPlugin.java @@ -68,4 +68,8 @@ public Class> getContainerFactoryClass() public void register(ComponentKey type, TeamComponentFactory factory) { super.register(type, (team) -> Objects.requireNonNull(((TeamComponentFactory) factory).createForTeam(team), "Component factory "+ factory + " for " + type.getId() + " returned null on " + team.getClass().getSimpleName())); } + + public void register(ComponentKey type, Class impl, TeamComponentFactory factory) { + super.register(type, impl, (team) -> Objects.requireNonNull(((TeamComponentFactory) factory).createForTeam(team), "Component factory "+ factory + " for " + type.getId() + " returned null on " + team.getClass().getSimpleName())); + } } diff --git a/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/mixin/scoreboard/MixinMinecraftServer.java b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/mixin/scoreboard/MixinMinecraftServer.java new file mode 100644 index 00000000..04c8e5fc --- /dev/null +++ b/cardinal-components-scoreboard/src/main/java/dev/onyxstudios/cca/mixin/scoreboard/MixinMinecraftServer.java @@ -0,0 +1,51 @@ +/* + * Cardinal-Components-API + * Copyright (C) 2019-2020 OnyxStudios + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE + * OR OTHER DEALINGS IN THE SOFTWARE. + */ +package dev.onyxstudios.cca.mixin.scoreboard; + +import dev.onyxstudios.cca.api.v3.component.ComponentProvider; +import dev.onyxstudios.cca.internal.base.InternalComponentProvider; +import net.minecraft.scoreboard.ServerScoreboard; +import net.minecraft.scoreboard.Team; +import net.minecraft.server.MinecraftServer; +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.CallbackInfo; + +import java.util.function.BooleanSupplier; + +@Mixin(MinecraftServer.class) +public abstract class MixinMinecraftServer { + @Shadow public abstract ServerScoreboard getScoreboard(); + + @Inject(at = @At("TAIL"), method = "tick") + private void onEndTick(BooleanSupplier shouldKeepTicking, CallbackInfo info) { + ServerScoreboard scoreboard = this.getScoreboard(); + ((InternalComponentProvider) ComponentProvider.fromScoreboard(scoreboard)).getComponentContainer().tickServerComponents(); + + for (Team team : scoreboard.getTeams()) { + ((InternalComponentProvider) ComponentProvider.fromTeam(team)).getComponentContainer().tickServerComponents(); + } + } +} diff --git a/cardinal-components-scoreboard/src/main/resources/mixins.cardinal_components_scoreboard.json b/cardinal-components-scoreboard/src/main/resources/mixins.cardinal_components_scoreboard.json index 5b2bbcdd..d0d200fd 100644 --- a/cardinal-components-scoreboard/src/main/resources/mixins.cardinal_components_scoreboard.json +++ b/cardinal-components-scoreboard/src/main/resources/mixins.cardinal_components_scoreboard.json @@ -4,6 +4,7 @@ "compatibilityLevel": "JAVA_8", "package": "dev.onyxstudios.cca.mixin.scoreboard", "mixins": [ + "MixinMinecraftServer", "MixinPlayerManager", "MixinScoreboard", "MixinScoreboardState", diff --git a/changelog.md b/changelog.md index bd717d8b..b164951f 100644 --- a/changelog.md +++ b/changelog.md @@ -5,8 +5,9 @@ Version 2.7.0 Those classes will be **removed** during the MC 1.17 update. Additions -- Implemented the new synchronization and (serverside) ticking APIs in `cardinal-components-level` +- Implemented the new synchronization in `cardinal-components-level` - Added `LevelComponents#sync`, replacing `ComponentKey#sync` for components attached to `WorldProperties` +- Implemented the new (serverside) ticking API in `cardinal-components-level` and `cardinal-components-scoreboard` - Added a `CommonTickingComponent` interface, implementing both Client and Server variants Changes