use of net.glowstone.net.message.play.entity.DestroyEntitiesMessage in project Glowstone by GlowstoneMC.
the class GlowSession method pulse.
/**
* Pulse this session, performing any updates needed.
*/
void pulse() {
// process messages
Message message;
while ((message = messageQueue.poll()) != null) {
if (disconnected) {
// disconnected, we are just seeing extra messages now
break;
}
super.messageReceived(message);
}
// check if the client is disconnected
if (disconnected) {
connectionManager.sessionInactivated(this);
if (player == null) {
return;
}
player.remove();
Message userListMessage = UserListItemMessage.removeOne(player.getUniqueId());
for (GlowPlayer player : server.getRawOnlinePlayers()) {
if (player.canSee(this.player)) {
player.getSession().send(userListMessage);
} else {
player.stopHidingDisconnectedPlayer(this.player);
}
}
GlowServer.logger.info(player.getName() + " [" + address + "] lost connection");
if (player.isSleeping()) {
player.leaveBed(false);
}
Collection<BossBar> bars;
do {
bars = player.getBossBars();
for (BossBar bar : bars) {
bar.removePlayer(player);
player.removeBossBar(bar);
}
} while (!bars.isEmpty());
String text = EventFactory.getInstance().onPlayerQuit(player).getQuitMessage();
if (online && text != null && !text.isEmpty()) {
server.broadcastMessage(text);
}
// statistics
player.incrementStatistic(Statistic.LEAVE_GAME);
for (Player p : server.getOnlinePlayers()) {
if (p.getUniqueId().equals(player.getUniqueId())) {
continue;
}
GlowPlayer other = (GlowPlayer) p;
if (!other.canSee(player)) {
continue;
}
other.getSession().send(new DestroyEntitiesMessage(Collections.singletonList(player.getEntityId())));
}
// in case we are disposed twice
player = null;
}
}
use of net.glowstone.net.message.play.entity.DestroyEntitiesMessage in project Glowstone by GlowstoneMC.
the class GlowFishingHook method setShooter.
@Override
public void setShooter(ProjectileSource shooter) {
ProjectileSource oldShooter = getShooter();
if (oldShooter == shooter) {
return;
}
// Shooter is immutable client-side (a situation peculiar to fishing hooks), so if it
// changes then all clients who can see this fishing hook must be told that this hook has
// despawned and a new one has spawned.
super.setShooter(shooter);
World world = location.getWorld();
if (world instanceof GlowWorld) {
List<Message> respawnMessages = new LinkedList<>();
DestroyEntitiesMessage destroyOldCopy = new DestroyEntitiesMessage(Collections.singletonList(getObjectId()));
respawnMessages.add(destroyOldCopy);
respawnMessages.addAll(createSpawnMessage(getShooterId()));
((GlowWorld) world).getRawPlayers().stream().filter(player -> !Objects.equal(player, shooter)).filter(player -> player.canSeeEntity(this)).forEach(player -> player.getSession().sendAll(respawnMessages.toArray(EMPTY_MESSAGE_ARRAY)));
if (shooter instanceof GlowPlayer) {
GlowSession session = ((GlowPlayer) shooter).getSession();
session.send(destroyOldCopy);
session.sendAll(createSpawnMessage(getEntityId()).toArray(EMPTY_MESSAGE_ARRAY));
}
}
}
use of net.glowstone.net.message.play.entity.DestroyEntitiesMessage in project Glowstone by GlowstoneMC.
the class GlowPlayer method pulse.
@Override
public void pulse() {
super.pulse();
incrementStatistic(Statistic.TIME_SINCE_DEATH);
if (usageItem != null) {
if (usageItem.equals(getItemInHand())) {
// todo: implement offhand
if (--usageTime == 0) {
ItemType item = ItemTable.instance().getItem(usageItem.getType());
if (item instanceof ItemFood) {
((ItemFood) item).eat(this, usageItem);
}
}
} else {
usageItem = null;
usageTime = 0;
}
}
if (digging != null) {
pulseDigging();
}
if (exhaustion > 4.0f) {
exhaustion -= 4.0f;
if (saturation > 0f) {
saturation = Math.max(saturation - 1f, 0f);
sendHealth();
} else if (world.getDifficulty() != Difficulty.PEACEFUL) {
FoodLevelChangeEvent event = EventFactory.getInstance().callEvent(new FoodLevelChangeEvent(this, Math.max(foodLevel - 1, 0)));
if (!event.isCancelled()) {
foodLevel = event.getFoodLevel();
}
sendHealth();
}
}
if (getHealth() < getMaxHealth() && !isDead()) {
if (foodLevel >= 18 && ticksLived % 80 == 0 || world.getDifficulty() == Difficulty.PEACEFUL) {
EntityUtils.heal(this, 1, EntityRegainHealthEvent.RegainReason.SATIATED);
exhaustion = Math.min(exhaustion + 3.0f, 40.0f);
saturation -= 3;
}
}
// Process food level and starvation based on difficulty.
switch(world.getDifficulty()) {
case PEACEFUL:
{
if (foodLevel < 20 && ticksLived % 20 == 0) {
foodLevel++;
}
break;
}
case EASY:
{
if (foodLevel == 0 && getHealth() > 10 && ticksLived % 80 == 0) {
damage(1, DamageCause.STARVATION);
}
break;
}
case NORMAL:
{
if (foodLevel == 0 && getHealth() > 1 && ticksLived % 80 == 0) {
damage(1, DamageCause.STARVATION);
}
break;
}
case HARD:
{
if (foodLevel == 0 && ticksLived % 80 == 0) {
damage(1, DamageCause.STARVATION);
}
break;
}
default:
{
// Do nothing when there are other game difficulties.
}
}
// process ender pearl cooldown, decrease by 1 every game tick.
if (enderPearlCooldown > 0) {
enderPearlCooldown--;
}
// stream world
streamBlocks();
processBlockChanges();
// add to playtime (despite inaccurate name, this counts ticks rather than minutes)
incrementStatistic(Statistic.PLAY_ONE_MINUTE);
if (isSneaking()) {
incrementStatistic(Statistic.SNEAK_TIME);
}
// update inventory
for (InventoryMonitor.Entry entry : invMonitor.getChanges()) {
sendItemChange(entry.slot, entry.item);
}
// send changed metadata
List<MetadataMap.Entry> changes = metadata.getChanges();
if (!changes.isEmpty()) {
session.send(new EntityMetadataMessage(getEntityId(), changes));
}
// Entity IDs are only unique per world, so we can't spawn or teleport between worlds while
// updating them.
worldLock.writeLock().lock();
try {
// update or remove entities
List<GlowEntity> destroyEntities = new LinkedList<>();
for (Iterator<GlowEntity> it = knownEntities.iterator(); it.hasNext(); ) {
GlowEntity entity = it.next();
if (!isWithinDistance(entity) || entity.isRemoved()) {
destroyEntities.add(entity);
} else {
entity.createUpdateMessage(session).forEach(session::send);
}
}
if (!destroyEntities.isEmpty()) {
List<Integer> destroyIds = new ArrayList<>(destroyEntities.size());
for (GlowEntity entity : destroyEntities) {
knownEntities.remove(entity);
destroyIds.add(entity.getEntityId());
}
session.send(new DestroyEntitiesMessage(destroyIds));
}
// add entities
knownChunks.forEach(key -> world.getChunkAt(key.getX(), key.getZ()).getRawEntities().stream().filter(entity -> this != entity && isWithinDistance(entity) && !entity.isDead() && !knownEntities.contains(entity) && !hiddenEntities.contains(entity.getUniqueId())).forEach((entity) -> Bukkit.getScheduler().runTaskAsynchronously(null, () -> {
worldLock.readLock().lock();
try {
knownEntities.add(entity);
} finally {
worldLock.readLock().unlock();
}
entity.createSpawnMessage().forEach(session::send);
entity.createAfterSpawnMessage(session).forEach(session::send);
})));
} finally {
worldLock.writeLock().unlock();
}
if (passengerChanged) {
session.send(new SetPassengerMessage(getEntityId(), getPassengers().stream().mapToInt(Entity::getEntityId).toArray()));
}
getAttributeManager().sendMessages(session);
GlowFishingHook hook = currentFishingHook.get();
if (hook != null) {
// bobber, or if the player stops holding a fishing rod.
if (getInventory().getItemInMainHand().getType() != Material.FISHING_ROD && getInventory().getItemInOffHand().getType() != Material.FISHING_ROD) {
setCurrentFishingHook(null);
}
if (hook.location.distanceSquared(location) > HOOK_MAX_DISTANCE * HOOK_MAX_DISTANCE) {
setCurrentFishingHook(null);
}
}
}
use of net.glowstone.net.message.play.entity.DestroyEntitiesMessage in project Glowstone by GlowstoneMC.
the class GlowPlayer method hidePlayer.
@Override
public void hidePlayer(Player player) {
checkNotNull(player, "player cannot be null");
if (equals(player) || !player.isOnline() || !session.isActive()) {
return;
}
if (hiddenEntities.contains(player.getUniqueId())) {
return;
}
hiddenEntities.add(player.getUniqueId());
worldLock.writeLock().lock();
try {
if (knownEntities.remove(player)) {
session.send(new DestroyEntitiesMessage(Collections.singletonList(player.getEntityId())));
}
} finally {
worldLock.writeLock().unlock();
}
session.send(UserListItemMessage.removeOne(player.getUniqueId()));
}
use of net.glowstone.net.message.play.entity.DestroyEntitiesMessage in project Glowstone by GlowstoneMC.
the class GlowPlayer method respawn.
/**
* Respawn the player after they have died.
*/
public void respawn() {
if (!isDead()) {
return;
}
// restore health
setHealth(getMaxHealth());
setFoodLevel(20);
// reset fire ticks
setFireTicks(0);
worldLock.writeLock().lock();
try {
// determine spawn destination
boolean spawnAtBed = true;
Location dest = getBedSpawnLocation();
if (dest == null) {
dest = world.getSpawnLocation();
spawnAtBed = false;
if (bedSpawn != null) {
setBedSpawnLocation(null);
sendMessage("Your home bed was missing or obstructed");
}
}
if (!spawnAtBed) {
dest = findSafeSpawnLocation(dest);
}
// fire event and perform spawn
PlayerRespawnEvent event = new PlayerRespawnEvent(this, dest, spawnAtBed);
EventFactory.getInstance().callEvent(event);
if (event.getRespawnLocation().getWorld().equals(getWorld()) && !knownEntities.isEmpty()) {
// we need to manually reset all known entities if the player respawns in the
// same world
List<Integer> entityIds = new ArrayList<>(knownEntities.size());
entityIds.addAll(knownEntities.stream().map(GlowEntity::getEntityId).collect(Collectors.toList()));
session.send(new DestroyEntitiesMessage(entityIds));
knownEntities.clear();
}
active = true;
deathTicks = 0;
setStatistic(Statistic.TIME_SINCE_DEATH, 0);
spawnAt(event.getRespawnLocation());
} finally {
worldLock.writeLock().unlock();
}
// just in case any items are left in their inventory after they respawn
updateInventory();
}
Aggregations