use of org.spongepowered.api.entity.living.player.server.ServerPlayer in project SpongeCommon by SpongePowered.
the class SpongeScoreCriterionProgress method set.
@Override
public Optional<Instant> set(final int score) {
checkState(score >= 0 && score <= this.goal(), "Score cannot be negative or greater than the goal.");
int lastScore = this.score();
if (lastScore == score) {
return this.get();
}
final CriterionEvent.Score.Change event;
final Cause cause = PhaseTracker.getCauseStackManager().currentCause();
final Advancement advancement = this.progress.advancement();
final ServerPlayer player = ((PlayerAdvancementsBridge) ((AdvancementProgressBridge) this.progress).bridge$getPlayerAdvancements()).bridge$getPlayer();
if (lastScore == this.goal()) {
event = SpongeEventFactory.createCriterionEventScoreRevoke(cause, advancement, this.criterion(), player, lastScore, score);
} else if (score == this.goal()) {
event = SpongeEventFactory.createCriterionEventScoreGrant(cause, advancement, this.criterion(), player, Instant.now(), lastScore, score);
} else {
event = SpongeEventFactory.createCriterionEventScoreChange(cause, advancement, this.criterion(), player, lastScore, score);
}
if (SpongeCommon.post(event)) {
return this.get();
}
SpongeScoreCriterion.BYPASS_EVENT = true;
// This is the only case a instant will be returned
if (score == this.goal()) {
Instant instant = null;
for (final AdvancementCriterion criterion : this.criterion.internalCriteria) {
final org.spongepowered.api.advancement.criteria.CriterionProgress progress = this.progress.get(criterion).get();
if (!progress.achieved()) {
instant = progress.grant();
}
}
this.score = score;
return Optional.of(instant == null ? Instant.now() : instant);
}
for (final AdvancementCriterion criterion : this.criterion.internalCriteria) {
final org.spongepowered.api.advancement.criteria.CriterionProgress progress = this.progress.get(criterion).get();
// We don't have enough score, grant more criteria
if (lastScore < score && !progress.achieved()) {
progress.grant();
lastScore++;
// We have too much score, revoke more criteria
} else if (lastScore > score && progress.achieved()) {
progress.revoke();
lastScore--;
}
// We reached the target score
if (lastScore == score) {
break;
}
}
this.score = score;
SpongeScoreCriterion.BYPASS_EVENT = false;
return Optional.empty();
}
use of org.spongepowered.api.entity.living.player.server.ServerPlayer in project SpongeCommon by SpongePowered.
the class SpongePacketHandler method init.
public static void init(final SpongeChannelManager registry) {
SpongePacketHandler.channel = registry.createChannel(ResourceKey.sponge("default"), PacketChannel.class);
SpongePacketHandler.channel.registerTransactional(RequestBlockTrackerDataPacket.class, TrackerDataResponsePacket.class, 0).setRequestHandler(EngineConnectionTypes.SERVER_PLAYER, (requestPacket, connection, response) -> {
final ServerPlayer player = connection.player();
if (!player.hasPermission("sponge.debug.block-tracking")) {
return;
}
final net.minecraft.server.level.ServerPlayer sender = (net.minecraft.server.level.ServerPlayer) player;
final BlockPos pos = new BlockPos(requestPacket.x, requestPacket.y, requestPacket.z);
if (!sender.level.hasChunkAt(pos)) {
return;
}
final LevelChunkBridge levelChunkBridge = (LevelChunkBridge) sender.level.getChunkAt(pos);
final Optional<UUID> owner = levelChunkBridge.bridge$getBlockCreatorUUID(pos);
final Optional<UUID> notifier = levelChunkBridge.bridge$getBlockNotifierUUID(pos);
response.success(SpongePacketHandler.createTrackerDataResponse(owner, notifier));
});
SpongePacketHandler.channel.registerTransactional(RequestEntityTrackerDataPacket.class, TrackerDataResponsePacket.class, 1).setRequestHandler(EngineConnectionTypes.SERVER_PLAYER, (requestPacket, connection, response) -> {
final ServerPlayer player = connection.player();
if (!player.hasPermission("sponge.debug.entity-tracking")) {
return;
}
final net.minecraft.server.level.ServerPlayer sender = (net.minecraft.server.level.ServerPlayer) player;
final Entity entity = sender.level.getEntity(requestPacket.entityId);
if (!(entity instanceof CreatorTrackedBridge)) {
return;
}
final CreatorTrackedBridge creatorTrackedBridge = (CreatorTrackedBridge) entity;
final Optional<UUID> owner = creatorTrackedBridge.tracker$getCreatorUUID();
final Optional<UUID> notifier = creatorTrackedBridge.tracker$getNotifierUUID();
response.success(SpongePacketHandler.createTrackerDataResponse(owner, notifier));
});
SpongePacketHandler.channel.register(ChangeViewerEnvironmentPacket.class, 3).addHandler(ClientSideConnection.class, (packet, connection) -> {
final ClientLevel world = Minecraft.getInstance().level;
if (world == null) {
return;
}
final DimensionType dimensionType = SpongeCommon.server().registryAccess().dimensionTypes().get(packet.dimensionLogic);
((LevelBridge) world).bridge$adjustDimensionLogic(dimensionType);
});
}
use of org.spongepowered.api.entity.living.player.server.ServerPlayer in project SpongeCommon by SpongePowered.
the class MinecraftServerMixin_API method shutdown.
@Override
public void shutdown(final Component kickMessage) {
Objects.requireNonNull(kickMessage, "kickMessage");
for (final ServerPlayer player : this.onlinePlayers()) {
player.kick(kickMessage);
}
this.shadow$halt(false);
}
use of org.spongepowered.api.entity.living.player.server.ServerPlayer in project SpongeCommon by SpongePowered.
the class ServerGamePacketListenerImplMixin method impl$callMoveEntityEvent.
/**
* Effectively, hooking into the following code block:
* <pre>
* if (isMovePlayerPacketInvalid(packetIn)) {
* this.disconnect(new TranslationTextComponent("multiplayer.disconnect.invalid_player_movement"));
* } else {
* ServerWorld serverworld = this.server.world(this.player.dimension);
* if (!this.player.queuedEndExit) { // <---- Here is where we're injecting
* if (this.networkTickCount == 0) {
* this.captureCurrentPosition();
* }
* </pre>
* we can effectively short circuit the method to handle movement code where
* returning {@code true} will escape the packet being processed further entirely and
* {@code false} will allow the remaining processing of the method run.
*
* @param packetIn The movement packet
*/
@Inject(method = "handleMovePlayer", at = @At(value = "FIELD", opcode = Opcodes.GETFIELD, target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;awaitingPositionFromClient:Lnet/minecraft/world/phys/Vec3;"), slice = @Slice(from = @At(value = "FIELD", target = "Lnet/minecraft/server/level/ServerPlayer;wonGame:Z"), to = @At(value = "FIELD", target = "Lnet/minecraft/server/network/ServerGamePacketListenerImpl;tickCount:I", ordinal = 1)), cancellable = true)
private void impl$callMoveEntityEvent(final ServerboundMovePlayerPacket packetIn, final CallbackInfo ci) {
// If the movement is modified we pretend that the player has queuedEndExit = true
// so that vanilla wont process that packet further
final ServerboundMovePlayerPacketAccessor packetInAccessor = (ServerboundMovePlayerPacketAccessor) packetIn;
// We don't fire an event to avoid confusing plugins.
if (!packetInAccessor.accessor$hasPos() && !packetInAccessor.accessor$hasRot()) {
return;
}
final boolean goodMovementPacket = this.receivedMovePacketCount - this.knownMovePacketCount <= 5;
final boolean fireMoveEvent = goodMovementPacket && packetInAccessor.accessor$hasPos() && ShouldFire.MOVE_ENTITY_EVENT;
final boolean fireRotationEvent = goodMovementPacket && packetInAccessor.accessor$hasRot() && ShouldFire.ROTATE_ENTITY_EVENT;
final ServerPlayer player = (ServerPlayer) this.player;
final Vector3d fromRotation = new Vector3d(this.player.yRot, this.player.xRot, 0);
// Use the position of the last movement with an event or the current player position if never called
// We need this because we ignore very small position changes as to not spam as many move events.
final Vector3d fromPosition = player.position();
Vector3d toPosition = new Vector3d(packetIn.getX(this.player.getX()), packetIn.getY(this.player.getY()), packetIn.getZ(this.player.getZ()));
Vector3d toRotation = new Vector3d(packetIn.getYRot(this.player.yRot), packetIn.getXRot(this.player.xRot), 0);
final boolean significantRotation = fromRotation.distanceSquared(toRotation) > (.15f * .15f);
final Vector3d originalToPosition = toPosition;
boolean cancelMovement = false;
boolean cancelRotation = false;
// Call move & rotate event as needed...
if (fireMoveEvent) {
final MoveEntityEvent event = SpongeEventFactory.createMoveEntityEvent(PhaseTracker.getCauseStackManager().currentCause(), (ServerPlayer) this.player, fromPosition, toPosition, toPosition);
if (SpongeCommon.post(event)) {
cancelMovement = true;
} else {
toPosition = event.destinationPosition();
}
}
if (significantRotation && fireRotationEvent) {
final RotateEntityEvent event = SpongeEventFactory.createRotateEntityEvent(PhaseTracker.getCauseStackManager().currentCause(), (ServerPlayer) this.player, fromRotation, toRotation);
if (SpongeCommon.post(event)) {
cancelRotation = true;
toRotation = fromRotation;
} else {
toRotation = event.toRotation();
}
}
// player position and update the player's relation in the chunk manager.
if (cancelMovement) {
if (fromPosition.distanceSquared(toPosition) > 0) {
// Set the location, as if the player was teleporting
this.awaitingTeleportTime = this.tickCount;
this.shadow$teleport(fromPosition.x(), fromPosition.y(), fromPosition.z(), (float) toRotation.x(), (float) toRotation.y());
} else {
// If this is only rotation do not teleport back
this.player.absMoveTo(fromPosition.x(), fromPosition.y(), fromPosition.z(), (float) toRotation.x(), (float) toRotation.y());
}
ci.cancel();
return;
}
// Handle event results
if (!toPosition.equals(originalToPosition)) {
// Check if we have to say it's a "teleport" vs a standard move
final double d4 = packetIn.getX(this.player.getX());
final double d5 = packetIn.getY(this.player.getY());
final double d6 = packetIn.getZ(this.player.getZ());
final double d7 = d4 - this.firstGoodX;
final double d8 = d5 - this.firstGoodY;
final double d9 = d6 - this.firstGoodZ;
final double d10 = this.player.getDeltaMovement().lengthSqr();
final double d11 = d7 * d7 + d8 * d8 + d9 * d9;
final float f2 = this.player.isFallFlying() ? 300.0F : 100.0F;
final int i = this.receivedMovePacketCount - this.knownMovePacketCount;
if (d11 - d10 > (double) (f2 * (float) i) && !this.shadow$isSingleplayerOwner()) {
// At this point, we need to set the target position so the teleport code forces it
this.awaitingPositionFromClient = VecHelper.toVanillaVector3d(toPosition);
((EntityAccessor) this.player).invoker$setRot((float) toRotation.x(), (float) toRotation.y());
// And reset the position update so the force set is done.
this.awaitingTeleportTime = this.tickCount - Constants.Networking.MAGIC_TRIGGER_TELEPORT_CONFIRM_DIFF;
} else {
// otherwise, set the data back onto the packet
packetInAccessor.accessor$hasPos(true);
packetInAccessor.accessor$x(toPosition.x());
packetInAccessor.accessor$y(toPosition.y());
packetInAccessor.accessor$z(toPosition.z());
}
}
}
use of org.spongepowered.api.entity.living.player.server.ServerPlayer in project SpongeCommon by SpongePowered.
the class PlayerListMixin method impl$onInitPlayer_join.
@Inject(method = "placeNewPlayer", at = @At(value = "RETURN"))
private void impl$onInitPlayer_join(final Connection networkManager, final net.minecraft.server.level.ServerPlayer mcPlayer, final CallbackInfo ci) {
final ServerPlayer player = (ServerPlayer) mcPlayer;
final ServerSideConnection connection = player.connection();
final Cause cause = Cause.of(EventContext.empty(), connection, player);
final Audience audience = Audiences.onlinePlayers();
final Component joinComponent = SpongeAdventure.asAdventure(((ServerPlayerBridge) mcPlayer).bridge$getConnectionMessageToSend());
final ServerSideConnectionEvent.Join event = SpongeEventFactory.createServerSideConnectionEventJoin(cause, audience, Optional.of(audience), joinComponent, joinComponent, connection, player, false);
SpongeCommon.post(event);
if (!event.isMessageCancelled()) {
event.audience().ifPresent(audience1 -> audience1.sendMessage(Identity.nil(), event.message()));
}
((ServerPlayerBridge) mcPlayer).bridge$setConnectionMessageToSend(null);
final PhaseContext<?> context = PhaseTracker.SERVER.getPhaseContext();
PhaseTracker.SERVER.pushCause(event);
final TransactionalCaptureSupplier transactor = context.getTransactor();
transactor.logPlayerInventoryChange(mcPlayer, PlayerInventoryTransaction.EventCreator.STANDARD);
try (EffectTransactor ignored = BroadcastInventoryChangesEffect.transact(transactor)) {
// in case plugins modified it
mcPlayer.inventoryMenu.broadcastChanges();
}
}
Aggregations