Skip to content
7 changes: 5 additions & 2 deletions src/main/java/fr/openmc/core/features/dream/DreamManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
import fr.openmc.core.features.dream.mecanism.cold.ColdManager;
import fr.openmc.core.features.dream.mecanism.metaldetector.MetalDetectorManager;
import fr.openmc.core.features.dream.mecanism.rng.DreamLootListener;
import fr.openmc.core.features.dream.mecanism.sfx.PlayerCloneNpc;
import fr.openmc.core.features.dream.mecanism.sfx.clone.PlayerCloneNpc;
import fr.openmc.core.features.dream.mecanism.sfx.ghost.DreamGhostManager;
import fr.openmc.core.features.dream.mecanism.singularity.SingularityCraftListener;
import fr.openmc.core.features.dream.mecanism.singularity.SingularityManager;
import fr.openmc.core.features.dream.mecanism.tradernpc.GlaciteNpcManager;
Expand Down Expand Up @@ -83,6 +84,7 @@ public void init() {
MetalDetectorManager.init();
ColdManager.init();
SingularityManager.init();
DreamGhostManager.init();

// ** LOAD DATAS **
loadAllDreamPlayerData();
Expand Down Expand Up @@ -120,7 +122,8 @@ public Set<Listener> getListeners() {
new SingularityCraftListener(),
new PlayerDreamStructureListener(),
new PlayerFoodChangeListener(),
new DreamLootListener()
new DreamLootListener(),
new PlayerPickupListener()
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import fr.openmc.core.features.dream.DreamManager;
import fr.openmc.core.features.dream.DreamUtils;
import fr.openmc.core.features.dream.events.DreamEnterEvent;
import fr.openmc.core.features.dream.mecanism.sfx.PlayerCloneNpc;
import fr.openmc.core.features.dream.mecanism.sfx.clone.PlayerCloneNpc;
import fr.openmc.core.features.dream.models.db.DreamPlayer;
import fr.openmc.core.utils.bukkit.ParticleUtils;
import org.bukkit.Bukkit;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import fr.openmc.core.features.dream.DreamManager;
import fr.openmc.core.features.dream.events.DreamEndEvent;
import fr.openmc.core.features.dream.mecanism.sfx.PlayerCloneNpc;
import fr.openmc.core.features.dream.mecanism.sfx.clone.PlayerCloneNpc;
import fr.openmc.core.features.dream.models.db.DreamPlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package fr.openmc.core.features.dream.listeners.dream;

import fr.openmc.core.features.dream.DreamUtils;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityPickupItemEvent;

import java.util.UUID;

public class PlayerPickupListener implements Listener {

@EventHandler
public void onPickup(EntityPickupItemEvent event) {
if (!(event.getEntity() instanceof Player player)) return;
if (!DreamUtils.isInDreamWorld(player)) return;

Item item = event.getItem();

UUID thrower = item.getThrower();

if (thrower != null && !thrower.equals(player.getUniqueId())) {
event.setCancelled(true);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import fr.openmc.core.features.dream.DreamManager;
import fr.openmc.core.features.dream.DreamUtils;
import fr.openmc.core.features.dream.mecanism.sfx.PlayerCloneNpc;
import fr.openmc.core.features.dream.mecanism.sfx.clone.PlayerCloneNpc;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import fr.openmc.core.OMCPlugin;
import fr.openmc.core.features.dream.DreamManager;
import fr.openmc.core.features.dream.mecanism.sfx.PlayerCloneNpc;
import fr.openmc.core.features.dream.mecanism.sfx.clone.PlayerCloneNpc;
import fr.openmc.core.features.dream.models.db.DBDreamPlayer;
import org.bukkit.entity.Player;
import org.bukkit.entity.Pose;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package fr.openmc.core.features.dream.mecanism.sfx;
package fr.openmc.core.features.dream.mecanism.sfx.clone;

import fr.openmc.core.utils.bukkit.ParticleUtils;
import org.bukkit.Location;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package fr.openmc.core.features.dream.mecanism.sfx;
package fr.openmc.core.features.dream.mecanism.sfx.clone;

import de.oliver.fancynpcs.api.FancyNpcsPlugin;
import de.oliver.fancynpcs.api.Npc;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package fr.openmc.core.features.dream.mecanism.sfx.ghost;

import fr.openmc.core.OMCPlugin;
import fr.openmc.core.features.dream.DreamDimensionManager;
import fr.openmc.core.features.dream.DreamUtils;
import fr.openmc.core.features.dream.mecanism.sfx.ghost.listeners.DreamPlayerEnteredListener;
import fr.openmc.core.utils.bukkit.ParticleUtils;
import fr.openmc.core.utils.nms.SkullNMS;
import fr.openmc.core.utils.nms.entity.*;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.decoration.ArmorStand;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
* Gestion des intéractions joueurs dans les reves.
*
* Cache tous les joueurs + met juste leur tete d'affiché avec particule
*/
public class DreamGhostManager {
private static final Map<UUID, PlayerGhost> playerGhost = new HashMap<>();

public static void init() {
OMCPlugin.registerEvents(
new DreamPlayerEnteredListener()
);
}

public static void setupGhost(Player player) {
int entityId = player.getEntityId() + 100000;

ArmorStand stand = ArmorStandNMS.createFakeStand(player, entityId, player.getLocation());

AttributeInstance instance = stand.getAttribute(Attributes.SCALE);
if (instance == null) return;
instance.setBaseValue(1.7);

playerGhost.put(player.getUniqueId(), new PlayerGhost(entityId, stand));

World world = player.getWorld();

for (Player other : world.getPlayers()) {
if (other.equals(player)) continue;

hidePlayer(other, player);
hidePlayer(player, other);

sendGhostTo(other, player, entityId, stand);

PlayerGhost otherGhost = playerGhost.get(other.getUniqueId());
if (otherGhost != null) {
sendGhostTo(player, other, otherGhost.entityId(), otherGhost.stand());
}
}

new BukkitRunnable() {
@Override
public void run() {
if (!player.isOnline()
|| !DreamUtils.isInDreamWorld(player)) {
removeGhost(player);
this.cancel();
return;
}

if (player.getGameMode().equals(GameMode.SPECTATOR)) return;

Location newStand = player.getLocation().subtract(0, 0.5, 0);

Collection<Player> receivers = newStand.getNearbyEntitiesByType(Player.class, 20).stream()
.filter(p -> !p.equals(player)).toList();

ParticleUtils.spawnCloudParticlesToAll(
player.getLocation().add(0, 1.5, 0), Particle.SCULK_SOUL,
1, 1, 2, receivers);

Particle.SHRIEK.builder()
.location(newStand)
.data(10)
.receivers(receivers)
.spawn();

for (Player other : player.getWorld().getPlayers()) {
if (!other.equals(player)) {
EntityTeleportNMS.sendTeleportPacket(other, entityId, player.getLocation());
}
}
}
}.runTaskTimer(OMCPlugin.getInstance(), 0L, 2L);
}

private static void sendGhostTo(Player receiver, Player ghostOf, int entityId, ArmorStand stand) {
EntitySpawnNMS.sendSpawnPacket(receiver, EntityType.ARMOR_STAND, entityId, stand.getUUID(), ghostOf.getLocation());
EntitySpawnNMS.sendMetaDataEntity(receiver, stand);
EntityEquipmentNMS.sendHelmetPacket(receiver, entityId, SkullNMS.getPlayerSkullNMS(ghostOf));
}

public static void removeGhost(Player player) {
if (!playerGhost.containsKey(player.getUniqueId())) return;
PlayerGhost ghost = playerGhost.remove(player.getUniqueId());

if (ghost.stand() == null) return;
ghost.stand().remove(Entity.RemovalReason.DISCARDED);

for (Player other : DreamDimensionManager.DREAM_WORLD.getPlayers()) {
if (other.equals(player)) continue;

EntityRemoveNMS.sendRemovePacket(other, ghost.entityId());
}
}

public static void hidePlayer(Player receiver, Player toHide) {
EntityRemoveNMS.sendRemovePacket(receiver, toHide.getEntityId());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package fr.openmc.core.features.dream.mecanism.sfx.ghost;

import net.minecraft.world.entity.decoration.ArmorStand;

public record PlayerGhost(int entityId, ArmorStand stand) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package fr.openmc.core.features.dream.mecanism.sfx.ghost.listeners;

import fr.openmc.core.OMCPlugin;
import fr.openmc.core.features.dream.events.DreamEnterEvent;
import fr.openmc.core.features.dream.mecanism.sfx.ghost.DreamGhostManager;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

public class DreamPlayerEnteredListener implements Listener {

@EventHandler
public void onDreamEnter(DreamEnterEvent event) {
Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () ->
DreamGhostManager.setupGhost(event.getPlayer()), 20L);
}
}
16 changes: 10 additions & 6 deletions src/main/java/fr/openmc/core/utils/bukkit/ParticleUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ public class ParticleUtils {
public static Color color1;
public static Color color2;

// based on org.bukkit.craftbukkit.CraftParticle
/**
* based on {@link org.bukkit.craftbukkit.CraftParticle}
*/
private static final Map<String, Supplier<Object>> PARTICLE_FALLBACKS;

static {
Expand Down Expand Up @@ -113,9 +115,11 @@ public void run() {
}

public static void sendParticlePacket(Particle particle, Location loc, int radius) {
Collection<Player> players = loc.getNearbyEntitiesByType(Player.class, radius);
sendParticlePacket(particle, loc, loc.getNearbyEntitiesByType(Player.class, radius));
}

for (Player player : players) {
public static void sendParticlePacket(Particle particle, Location loc, Collection<Player> receivers) {
for (Player player : receivers) {
sendParticlePacket(player, particle, loc, 3, 0.2f, 0.2f, 0.2f, 0.01f, null);
}
}
Expand Down Expand Up @@ -264,9 +268,9 @@ public void run() {
}.runTaskTimerAsynchronously(OMCPlugin.getInstance(), 0L, 1L);
}

public static void spawnCloudParticles(Location center, Particle particle, int count, double radius, double height) {
for (Player player : center.getNearbyEntitiesByType(Player.class, radius)) {
spawnCloudParticles(player, particle, center, count, radius, height);
public static void spawnCloudParticlesToAll(Location center, Particle particle, int count, double radiusCloud, double height, Collection<Player> receivers) {
for (Player player : receivers) {
spawnCloudParticles(player, particle, center, count, radiusCloud, height);
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/main/java/fr/openmc/core/utils/bukkit/SkullUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.destroystokyo.paper.profile.PlayerProfile;
import com.destroystokyo.paper.profile.ProfileProperty;
import fr.openmc.core.utils.cache.CachePlayerProfile;
import io.papermc.paper.datacomponent.DataComponentTypes;
import io.papermc.paper.datacomponent.item.ResolvableProfile;
import net.kyori.adventure.text.Component;
Expand All @@ -27,7 +28,7 @@ public class SkullUtils {
*/
public static ItemStack getPlayerSkull(UUID playerUUID) {
ItemStack skull = new ItemStack(Material.PLAYER_HEAD);
PlayerProfile profile = Bukkit.createProfile(playerUUID);
PlayerProfile profile = CachePlayerProfile.getPlayerProfile(playerUUID);
skull.setData(DataComponentTypes.PROFILE, ResolvableProfile.resolvableProfile(profile));
return skull;
}
Expand Down
21 changes: 21 additions & 0 deletions src/main/java/fr/openmc/core/utils/nms/SkullNMS.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package fr.openmc.core.utils.nms;

import net.minecraft.core.component.DataComponents;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.component.ResolvableProfile;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;

public class SkullNMS {
public static ItemStack getPlayerSkullNMS(Player player) {
ServerPlayer nmsPlayer = ((CraftPlayer) player).getHandle();
ItemStack skull = new ItemStack(Items.PLAYER_HEAD);

ResolvableProfile profile = ResolvableProfile.createResolved(nmsPlayer.getGameProfile());

skull.set(DataComponents.PROFILE, profile);
return skull;
}
}
22 changes: 22 additions & 0 deletions src/main/java/fr/openmc/core/utils/nms/entity/ArmorStandNMS.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package fr.openmc.core.utils.nms.entity;

import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.decoration.ArmorStand;
import org.bukkit.Location;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.entity.Player;

public class ArmorStandNMS {

public static ArmorStand createFakeStand(Player playerOf, int entityId, Location loc) {
ServerLevel level = ((CraftWorld) playerOf.getWorld()).getHandle();

ArmorStand stand = new ArmorStand(level, loc.getX(), loc.getY(), loc.getZ());
stand.setId(entityId);
stand.setInvisible(true);
stand.setNoGravity(true);
stand.setMarker(false);

return stand;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package fr.openmc.core.utils.nms.entity;

import com.mojang.datafixers.util.Pair;
import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.ItemStack;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;

import java.util.List;

public class EntityEquipmentNMS {

public static void sendHelmetPacket(Player receiver, int entityId, ItemStack itemStackNMS) {
ServerPlayer nmsReceiver = ((CraftPlayer) receiver).getHandle();

ClientboundSetEquipmentPacket packet = new ClientboundSetEquipmentPacket(
entityId,
List.of(Pair.of(EquipmentSlot.HEAD, itemStackNMS))
);

nmsReceiver.connection.send(packet);
}
}
16 changes: 16 additions & 0 deletions src/main/java/fr/openmc/core/utils/nms/entity/EntityRemoveNMS.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package fr.openmc.core.utils.nms.entity;

import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket;
import net.minecraft.server.level.ServerPlayer;
import org.bukkit.craftbukkit.entity.CraftPlayer;
import org.bukkit.entity.Player;

public class EntityRemoveNMS {

public static void sendRemovePacket(Player receiver, int entityId) {
ServerPlayer nmsReceiver = ((CraftPlayer) receiver).getHandle();

ClientboundRemoveEntitiesPacket packet = new ClientboundRemoveEntitiesPacket(entityId);
nmsReceiver.connection.send(packet);
}
}
Loading
Loading