mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-07 14:06:44 +01:00
Check against offline players when trying to see if a spell can modify blocks at a location. Closes #283
This commit is contained in:
parent
5109b67de2
commit
10dc8ce6d7
4 changed files with 65 additions and 6 deletions
|
@ -14,12 +14,14 @@ import com.minelittlepony.unicopia.entity.damage.UDamageSources;
|
|||
import com.minelittlepony.unicopia.particle.ParticleSource;
|
||||
import com.minelittlepony.unicopia.server.world.Ether;
|
||||
import com.minelittlepony.unicopia.server.world.ModificationType;
|
||||
import com.minelittlepony.unicopia.server.world.OfflinePlayerCache;
|
||||
import com.minelittlepony.unicopia.util.SoundEmitter;
|
||||
import com.minelittlepony.unicopia.util.VecHelper;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.GameRules;
|
||||
|
@ -67,10 +69,18 @@ public interface Caster<E extends Entity> extends
|
|||
}
|
||||
|
||||
if (getMaster() instanceof PlayerEntity player) {
|
||||
if (!asWorld().canPlayerModifyAt(player, pos)) {
|
||||
if (!player.canModifyBlocks() || !asWorld().canPlayerModifyAt(player, pos)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (asWorld() instanceof ServerWorld sw) {
|
||||
@Nullable
|
||||
PlayerEntity player = OfflinePlayerCache.getOfflinePlayer(sw, getMasterId().orElse(null));
|
||||
if (player != null && !player.canModifyBlocks() || !sw.canPlayerModifyAt(player, pos)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!asWorld().getGameRules().getBoolean(GameRules.DO_MOB_GRIEFING)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -61,7 +61,9 @@ public class HydrophobicSpell extends AbstractSpell {
|
|||
|
||||
storedFluidPositions.removeIf(entry -> {
|
||||
if (!area.isPointInside(Vec3d.ofCenter(entry.pos()))) {
|
||||
entry.restore(world);
|
||||
if (source.canModifyAt(entry.pos())) {
|
||||
entry.restore(world);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -72,7 +74,7 @@ public class HydrophobicSpell extends AbstractSpell {
|
|||
pos = new BlockPos(pos);
|
||||
BlockState state = world.getBlockState(pos);
|
||||
|
||||
if (state.getFluidState().isIn(affectedFluid)) {
|
||||
if (source.canModifyAt(pos) && state.getFluidState().isIn(affectedFluid)) {
|
||||
Block block = state.getBlock();
|
||||
|
||||
if (block instanceof FluidBlock) {
|
||||
|
@ -95,7 +97,7 @@ public class HydrophobicSpell extends AbstractSpell {
|
|||
|
||||
source.spawnParticles(new Sphere(true, range), 10, pos -> {
|
||||
BlockPos bp = BlockPos.ofFloored(pos);
|
||||
if (source.asWorld().getFluidState(bp.up()).isIn(affectedFluid)) {
|
||||
if (source.canModifyAt(bp) && source.asWorld().getFluidState(bp.up()).isIn(affectedFluid)) {
|
||||
source.addParticle(UParticles.RAIN_DROPS, pos, Vec3d.ZERO);
|
||||
}
|
||||
});
|
||||
|
@ -116,7 +118,9 @@ public class HydrophobicSpell extends AbstractSpell {
|
|||
protected void onDestroyed(Caster<?> caster) {
|
||||
Ether.get(caster.asWorld()).remove(this, caster);
|
||||
storedFluidPositions.removeIf(entry -> {
|
||||
entry.restore(caster.asWorld());
|
||||
if (caster.canModifyAt(entry.pos())) {
|
||||
entry.restore(caster.asWorld());
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -48,8 +48,9 @@ public class InfernoSpell extends FireSpell {
|
|||
for (int i = 0; i < radius * 2; i++) {
|
||||
if (w.random.nextInt(12) == 0) {
|
||||
Vec3d vec = shape.computePoint(w.random).add(origin);
|
||||
BlockPos pos = BlockPos.ofFloored(vec);
|
||||
|
||||
if (!applyBlocks(w, BlockPos.ofFloored(vec))) {
|
||||
if (source.canModifyAt(pos) && !applyBlocks(w, pos)) {
|
||||
applyEntities(source, vec);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package com.minelittlepony.unicopia.server.world;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
|
||||
import net.fabricmc.fabric.api.entity.FakePlayer;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
|
||||
public class OfflinePlayerCache {
|
||||
private static final LoadingCache<Key, Optional<ServerPlayerEntity>> CACHE = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(1, TimeUnit.MINUTES)
|
||||
.build(CacheLoader.from(key -> {
|
||||
ServerPlayerEntity offlinePlayer = FakePlayer.get(key.world(), new GameProfile(key.playerId(), "[Offline Player]"));
|
||||
|
||||
if (key.world().getServer().getPlayerManager().loadPlayerData(offlinePlayer) != null) {
|
||||
return Optional.of(offlinePlayer);
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}));
|
||||
|
||||
@Nullable
|
||||
public static ServerPlayerEntity getOfflinePlayer(ServerWorld world, UUID playerId) {
|
||||
ServerPlayerEntity player = (ServerPlayerEntity)world.getPlayerByUuid(playerId);
|
||||
if (player == null) {
|
||||
player = world.getServer().getPlayerManager().getPlayer(playerId);
|
||||
}
|
||||
if (player == null) {
|
||||
return CACHE.getUnchecked(new Key(world, playerId)).orElse(null);
|
||||
}
|
||||
return player;
|
||||
}
|
||||
|
||||
record Key (ServerWorld world, UUID playerId) {}
|
||||
}
|
Loading…
Reference in a new issue