use of net.glowstone.net.message.play.entity.SetPassengerMessage 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.SetPassengerMessage in project Glowstone by GlowstoneMC.
the class GlowEntity method createUpdateMessage.
/**
* Creates a {@link Message} which can be sent to a client to update this entity.
*
* @param session Session to update this entity for
* @return A message which can update this entity.
*/
public List<Message> createUpdateMessage(GlowSession session) {
double x = location.getX();
double y = location.getY();
double z = location.getZ();
double dx = x * 32 - previousLocation.getX() * 32;
double dy = y * 32 - previousLocation.getY() * 32;
double dz = z * 32 - previousLocation.getZ() * 32;
dx *= 128;
dy *= 128;
dz *= 128;
boolean teleport = dx > Short.MAX_VALUE || dy > Short.MAX_VALUE || dz > Short.MAX_VALUE || dx < Short.MIN_VALUE || dy < Short.MIN_VALUE || dz < Short.MIN_VALUE;
List<Message> result = new LinkedList<>();
boolean moved = hasMoved();
boolean rotated = hasRotated();
if (teleported || moved && teleport) {
result.add(new EntityTeleportMessage(entityId, location));
} else if (rotated) {
int yaw = Position.getIntYaw(location);
int pitch = Position.getIntPitch(location);
if (moved) {
result.add(new RelativeEntityPositionRotationMessage(entityId, (short) dx, (short) dy, (short) dz, yaw, pitch));
} else {
result.add(new EntityRotationMessage(entityId, yaw, pitch));
}
} else if (moved) {
result.add(new RelativeEntityPositionMessage(entityId, (short) dx, (short) dy, (short) dz));
}
// send changed metadata
List<Entry> changes = metadata.getChanges();
if (!changes.isEmpty()) {
result.add(new EntityMetadataMessage(entityId, changes));
}
// send velocity if needed
if (velocityChanged) {
result.add(new EntityVelocityMessage(entityId, velocity));
}
if (passengerChanged) {
// A player can be a passenger of any arbitrary entity, e.g. a boat
// In case the current session belongs to this player passenger
// We need to send the self_id
List<Integer> passengerIds = new ArrayList<>();
getPassengers().forEach(e -> passengerIds.add(e.getEntityId()));
result.add(new SetPassengerMessage(getEntityId(), passengerIds.stream().mapToInt(Integer::intValue).toArray()));
passengerChanged = false;
}
if (leashHolderChanged) {
int attached = isLeashed() && session.getPlayer().getEntityId() == leashHolder.getEntityId() ? 0 : this.getEntityId();
int holder = !isLeashed() ? -1 : leashHolder.getEntityId();
// createAfterSpawnMessage()
if (!isLeashed() || session.getPlayer().canSeeEntity(leashHolder)) {
result.add(new AttachEntityMessage(attached, holder));
}
}
return result;
}
Aggregations