Skip to content

Commit

Permalink
Implement serverside ticking for scoreboard components
Browse files Browse the repository at this point in the history
  • Loading branch information
Pyrofab committed Oct 16, 2020
1 parent 0a557c1 commit b49ea8b
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 2 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,10 @@ public interface LevelComponentFactoryRegistry {
*/
<C extends Component> void register(ComponentKey<C> type, LevelComponentFactory<C> factory);

/**
* Registers a {@link LevelComponentFactory}.
*
* @param factory the factory to use to create components of the given type
*/
<C extends Component> void register(ComponentKey<? super C> type, Class<C> impl, LevelComponentFactory<C> factory);
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,10 @@ public <C extends Component> void register(ComponentKey<C> 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 <C extends Component> void register(ComponentKey<? super C> type, Class<C> impl, LevelComponentFactory<C> 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()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,24 @@ public interface ScoreboardComponentFactoryRegistry {
*/
<C extends Component> void register(ComponentKey<C> type, TeamComponentFactory<? extends C> factory);

/**
* Registers a {@link TeamComponentFactory}.
*
* @param factory the factory to use to create components of the given type
*/
<C extends Component> void registerForTeams(ComponentKey<? super C> type, Class<C> impl, TeamComponentFactory<? extends C> factory);

/**
* Registers a {@link ScoreboardComponentFactory}.
*
* @param factory the factory to use to create components of the given type
*/
<C extends Component> void register(ComponentKey<C> type, ScoreboardComponentFactory<? extends C> factory);

/**
* Registers a {@link ScoreboardComponentFactory}.
*
* @param factory the factory to use to create components of the given type
*/
<C extends Component> void registerForScoreboards(ComponentKey<? super C> type, Class<C> impl, ScoreboardComponentFactory<? extends C> factory);
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,19 @@ public <C extends Component> void register(ComponentKey<C> 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 <C extends Component> void registerForScoreboards(ComponentKey<? super C> type, Class<C> impl, ScoreboardComponentFactory<? extends C> 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 <C extends Component> void register(ComponentKey<C> type, TeamComponentFactory<? extends C> factory) {
StaticTeamComponentPlugin.INSTANCE.register(type, factory);
}

@Override
public <C extends Component> void registerForTeams(ComponentKey<? super C> type, Class<C> impl, TeamComponentFactory<? extends C> factory) {
StaticTeamComponentPlugin.INSTANCE.register(type, impl, factory);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,8 @@ public Class<? extends DynamicContainerFactory<Team>> getContainerFactoryClass()
public <C extends Component> void register(ComponentKey<C> type, TeamComponentFactory<? extends C> factory) {
super.register(type, (team) -> Objects.requireNonNull(((TeamComponentFactory<?>) factory).createForTeam(team), "Component factory "+ factory + " for " + type.getId() + " returned null on " + team.getClass().getSimpleName()));
}

public <C extends Component> void register(ComponentKey<? super C> type, Class<C> impl, TeamComponentFactory<? extends C> factory) {
super.register(type, impl, (team) -> Objects.requireNonNull(((TeamComponentFactory<?>) factory).createForTeam(team), "Component factory "+ factory + " for " + type.getId() + " returned null on " + team.getClass().getSimpleName()));
}
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"compatibilityLevel": "JAVA_8",
"package": "dev.onyxstudios.cca.mixin.scoreboard",
"mixins": [
"MixinMinecraftServer",
"MixinPlayerManager",
"MixinScoreboard",
"MixinScoreboardState",
Expand Down
3 changes: 2 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit b49ea8b

Please sign in to comment.