Skip to content

Commit

Permalink
Make PAL serverside only
Browse files Browse the repository at this point in the history
At least for now, the library isn't made for clientside use
  • Loading branch information
Pyrofab committed Mar 2, 2020
1 parent 4bc9fb7 commit ab15490
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 124 deletions.
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

[![Curseforge](https://curse.nikky.moe/api/img/359522?logo)](https://www.curseforge.com/projects/359522) [![](https://jitpack.io/v/Ladysnake/PlayerAbilityLib.svg)](https://jitpack.io/#Ladysnake/PlayerAbilityLib)

A lightweight library to provide compatibility between mods that make use of player abilities.
A lightweight serverside library to provide compatibility between mods that make use of player abilities.

*credits to Chloe Dawn for some of the API design*
Conflicts arise often when several mods update the same field in `PlayerAbilities`. This library exists so that
all modifications can be made from a single place, keeping track of what mod enabled what ability.

*credits to ~~InsomniaPrincess~~ Chloe Dawn for some of the API design*

## Adding PAL to your project

Expand Down Expand Up @@ -37,7 +40,10 @@ You can find the current version of PAL in the [releases](https://github.com/Lad

You can find a couple examples in the [Test Mod](https://github.com/Ladysnake/PlayerAbilityLib/tree/master/src/testmod/java/io/github/ladysnake/paltest).

Note that player abilities can only accessed serverside. If you want to store more complex data, or to synchronize it between server and client,
**Note that PAL interfaces can only be accessed serverside, as no synchronization is done on the ability sources.**
Read accesses can still be done directly on the `PlayerAbilities` instance, both serverside and clientside.

If you want to store more complex data, or to synchronize it between server and client,
you should take a look at [Cardinal Components API](https://github.com/OnyxStudios/Cardinal-Components-API).

[Item that toggles an ability](https://github.com/Ladysnake/PlayerAbilityLib/blob/master/src/testmod/java/io/github/ladysnake/paltest/AbilityToggleItem.java) :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ public interface PlayerAbilityView {
* @return a view for the player's abilities
*/
static PlayerAbilityView of(PlayerEntity player) {
if (player.world.isClient) {
throw new IllegalStateException("Player abilities must be accessed from the logical server !");
}
return (PlayerAbilityView) player;
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,69 @@
*/
package io.github.ladysnake.pal.impl.mixin;

import com.mojang.authlib.GameProfile;
import io.github.ladysnake.pal.AbilityTracker;
import io.github.ladysnake.pal.PlayerAbility;
import io.github.ladysnake.pal.VanillaAbilities;
import io.github.ladysnake.pal.impl.PalInternals;
import io.github.ladysnake.pal.impl.PlayerAbilityView;
import io.github.ladysnake.pal.impl.VanillaAbilityTracker;
import net.fabricmc.fabric.api.util.NbtType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.Tag;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.network.ServerPlayerInteractionManager;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
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.LinkedHashMap;
import java.util.Map;

@Mixin(ServerPlayerEntity.class)
public abstract class ServerPlayerEntityMixin implements PlayerAbilityView {
@Shadow
public abstract void sendAbilitiesUpdate();
public abstract class ServerPlayerEntityMixin extends PlayerEntity implements PlayerAbilityView {

@Unique
private final Map<PlayerAbility, AbilityTracker> palAbilities = new LinkedHashMap<>();

public ServerPlayerEntityMixin(World world, GameProfile profile) {
super(world, profile);
}

@Inject(method = "<init>", at = @At("RETURN"))
private void init(MinecraftServer server, ServerWorld world, GameProfile profile, ServerPlayerInteractionManager interactionManager, CallbackInfo ci) {
PalInternals.populate(this, this.palAbilities);
}

@Override
public Iterable<PlayerAbility> listPalAbilities() {
return this.palAbilities.keySet();
}

@Override
public AbilityTracker get(PlayerAbility abilityId) {
return this.palAbilities.get(abilityId);
}

@Override
public void refreshAllPalAbilities(boolean syncVanilla) {
for (PlayerAbility ability : this.listPalAbilities()) {
if (ability != VanillaAbilities.FLYING) {
this.get(ability).refresh(false);
}
}
if (syncVanilla) {
this.sendAbilitiesUpdate(); // batch vanilla abilities updates
}
}

@Inject(method = "sendAbilitiesUpdate", at = @At(value = "NEW", target = "net/minecraft/client/network/packet/PlayerAbilitiesS2CPacket"))
private void checkAbilityConsistency(CallbackInfo ci) {
Expand All @@ -44,4 +91,31 @@ private void checkAbilityConsistency(CallbackInfo ci) {
}
}

@Inject(method = "writeCustomDataToTag", at = @At("RETURN"))
private void writeAbilitiesToTag(CompoundTag tag, CallbackInfo ci) {
ListTag list = new ListTag();
for (Map.Entry<PlayerAbility, AbilityTracker> entry : this.palAbilities.entrySet()) {
CompoundTag abilityTag = new CompoundTag();
abilityTag.putString("ability_id", entry.getKey().toString());
entry.getValue().save(abilityTag);
list.add(abilityTag);
}
tag.put("playerabilitylib:abilities", list);
}

@Inject(method = "readCustomDataFromTag", at = @At("RETURN"))
private void readAbilitiesFromTag(CompoundTag tag, CallbackInfo ci) {
for (Tag t : tag.getList("playerabilitylib:abilities", NbtType.COMPOUND)) {
CompoundTag abilityTag = ((CompoundTag) t);
if (abilityTag.contains("ability_id")) {
Identifier abilityId = Identifier.tryParse(abilityTag.getString("ability_id"));
if (abilityId != null) {
AbilityTracker ability = this.palAbilities.get(PalInternals.getAbility(abilityId));
if (ability != null) {
ability.load(abilityTag);
}
}
}
}
}
}
1 change: 0 additions & 1 deletion src/main/resources/mixins.playerabilitylib.common.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
"compatibilityLevel": "JAVA_8",
"minVersion": "0.7.11-SNAPSHOT",
"mixins": [
"PlayerEntityMixin",
"ServerPlayerEntityMixin",
"ServerPlayerInteractionManagerMixin"
],
Expand Down

0 comments on commit ab15490

Please sign in to comment.