Search in sources :

Example 1 with IMixinWorldServer

use of org.spongepowered.common.interfaces.world.IMixinWorldServer in project SpongeCommon by SpongePowered.

the class MixinMinecraftServer method onUpdateTimeLightAndEntitiesHead.

// All chunk unload queuing needs to be processed BEFORE the future tasks are run as mods/plugins may have tasks that request chunks.
// This prevents a situation where a chunk is requested to load then unloads at end of tick.
@Inject(method = "updateTimeLightAndEntities", at = @At("HEAD"))
public void onUpdateTimeLightAndEntitiesHead(CallbackInfo ci) {
    for (int i = 0; i < this.worlds.length; ++i) {
        WorldServer worldServer = this.worlds[i];
        // ChunkGC needs to be processed before a world tick in order to guarantee any chunk  queued for unload
        // can still be marked active and avoid unload if accessed during the same tick.
        // Note: This injection must come before Forge's pre world tick event or it will cause issues with mods.
        IMixinWorldServer spongeWorld = (IMixinWorldServer) worldServer;
        if (spongeWorld.getChunkGCTickInterval() > 0) {
            spongeWorld.doChunkGC();
        }
        // Moved from PlayerChunkMap to avoid chunks from unloading after being requested in same tick
        if (worldServer.getPlayerChunkMap().players.isEmpty()) {
            WorldProvider worldprovider = worldServer.provider;
            if (!worldprovider.canRespawnHere()) {
                worldServer.getChunkProvider().queueUnloadAll();
            }
        }
    }
}
Also used : WorldProvider(net.minecraft.world.WorldProvider) WorldServer(net.minecraft.world.WorldServer) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) Inject(org.spongepowered.asm.mixin.injection.Inject)

Example 2 with IMixinWorldServer

use of org.spongepowered.common.interfaces.world.IMixinWorldServer in project SpongeCommon by SpongePowered.

the class MixinPlayerList method initializeConnectionToPlayer.

public void initializeConnectionToPlayer(NetworkManager netManager, EntityPlayerMP playerIn, @Nullable NetHandlerPlayServer handler) {
    GameProfile gameprofile = playerIn.getGameProfile();
    PlayerProfileCache playerprofilecache = this.mcServer.getPlayerProfileCache();
    GameProfile gameprofile1 = playerprofilecache.getProfileByUUID(gameprofile.getId());
    String s = gameprofile1 == null ? gameprofile.getName() : gameprofile1.getName();
    playerprofilecache.addEntry(gameprofile);
    // Sponge start - save changes to offline User before reading player data
    SpongeUser user = (SpongeUser) ((IMixinEntityPlayerMP) playerIn).getUserObject();
    if (SpongeUser.dirtyUsers.contains(user)) {
        user.save();
    }
    // Sponge end
    NBTTagCompound nbttagcompound = this.readPlayerDataFromFile(playerIn);
    WorldServer worldServer = this.mcServer.getWorld(playerIn.dimension);
    int actualDimensionId = ((IMixinWorldServer) worldServer).getDimensionId();
    BlockPos spawnPos = null;
    // Join data
    Optional<Instant> firstJoined = SpongePlayerDataHandler.getFirstJoined(playerIn.getUniqueID());
    Instant lastJoined = Instant.now();
    SpongePlayerDataHandler.setPlayerInfo(playerIn.getUniqueID(), firstJoined.orElse(lastJoined), lastJoined);
    if (actualDimensionId != playerIn.dimension) {
        SpongeImpl.getLogger().warn("Player [{}] has attempted to login to unloaded world [{}]. This is not safe so we have moved them to " + "the default world's spawn point.", playerIn.getName(), playerIn.dimension);
        if (!firstJoined.isPresent()) {
            spawnPos = SpongeImplHooks.getRandomizedSpawnPoint(worldServer);
        } else {
            spawnPos = worldServer.getSpawnPoint();
        }
        playerIn.dimension = actualDimensionId;
        playerIn.setPosition(spawnPos.getX(), spawnPos.getY(), spawnPos.getZ());
    }
    // Sponge start - fire login event
    @Nullable String kickReason = allowUserToConnect(netManager.getRemoteAddress(), gameprofile);
    Text disconnectMessage;
    if (kickReason != null) {
        disconnectMessage = SpongeTexts.fromLegacy(kickReason);
    } else {
        disconnectMessage = Text.of("You are not allowed to log in to this server.");
    }
    Player player = (Player) playerIn;
    Transform<World> fromTransform = player.getTransform().setExtent((World) worldServer);
    Sponge.getCauseStackManager().pushCause(player);
    ClientConnectionEvent.Login loginEvent = SpongeEventFactory.createClientConnectionEventLogin(Sponge.getCauseStackManager().getCurrentCause(), fromTransform, fromTransform, (RemoteConnection) netManager, new MessageEvent.MessageFormatter(disconnectMessage), (org.spongepowered.api.profile.GameProfile) gameprofile, player, false);
    if (kickReason != null) {
        loginEvent.setCancelled(true);
    }
    if (SpongeImpl.postEvent(loginEvent)) {
        Sponge.getCauseStackManager().popCause();
        disconnectClient(netManager, loginEvent.isMessageCancelled() ? Optional.empty() : Optional.of(loginEvent.getMessage()), gameprofile);
        return;
    }
    Sponge.getCauseStackManager().popCause();
    // Sponge end
    worldServer = (WorldServer) loginEvent.getToTransform().getExtent();
    double x = loginEvent.getToTransform().getPosition().getX();
    double y = loginEvent.getToTransform().getPosition().getY();
    double z = loginEvent.getToTransform().getPosition().getZ();
    float pitch = (float) loginEvent.getToTransform().getPitch();
    float yaw = (float) loginEvent.getToTransform().getYaw();
    playerIn.dimension = ((IMixinWorldServer) worldServer).getDimensionId();
    playerIn.setWorld(worldServer);
    playerIn.interactionManager.setWorld((WorldServer) playerIn.world);
    playerIn.setPositionAndRotation(x, y, z, yaw, pitch);
    // make sure the chunk is loaded for login
    worldServer.getChunkProvider().loadChunk(loginEvent.getToTransform().getLocation().getChunkPosition().getX(), loginEvent.getToTransform().getLocation().getChunkPosition().getZ());
    // Sponge end
    String s1 = "local";
    if (netManager.getRemoteAddress() != null) {
        s1 = netManager.getRemoteAddress().toString();
    }
    final WorldInfo worldinfo = worldServer.getWorldInfo();
    final BlockPos spawnBlockPos = worldServer.getSpawnPoint();
    this.setPlayerGameTypeBasedOnOther(playerIn, null, worldServer);
    // Sponge start
    if (handler == null) {
        // Create the handler here (so the player's gets set)
        handler = new NetHandlerPlayServer(this.mcServer, netManager, playerIn);
    }
    playerIn.connection = handler;
    // Sponge end
    // Support vanilla clients logging into custom dimensions
    final int dimensionId = WorldManager.getClientDimensionId(playerIn, worldServer);
    // Send dimension registration
    WorldManager.sendDimensionRegistration(playerIn, worldServer.provider);
    handler.sendPacket(new SPacketJoinGame(playerIn.getEntityId(), playerIn.interactionManager.getGameType(), worldinfo.isHardcoreModeEnabled(), dimensionId, worldServer.getDifficulty(), this.getMaxPlayers(), worldinfo.getTerrainType(), worldServer.getGameRules().getBoolean("reducedDebugInfo")));
    handler.sendPacket(new SPacketCustomPayload("MC|Brand", (new PacketBuffer(Unpooled.buffer())).writeString(this.getServerInstance().getServerModName())));
    handler.sendPacket(new SPacketServerDifficulty(worldinfo.getDifficulty(), worldinfo.isDifficultyLocked()));
    handler.sendPacket(new SPacketSpawnPosition(spawnBlockPos));
    handler.sendPacket(new SPacketPlayerAbilities(playerIn.capabilities));
    handler.sendPacket(new SPacketHeldItemChange(playerIn.inventory.currentItem));
    this.updatePermissionLevel(playerIn);
    playerIn.getStatFile().markAllDirty();
    playerIn.getRecipeBook().init(playerIn);
    this.mcServer.refreshStatusNextTick();
    handler.setPlayerLocation(x, y, z, yaw, pitch);
    this.playerLoggedIn(playerIn);
    // Sponge start - add world name to message
    LOGGER.info(playerIn.getName() + "[" + s1 + "] logged in with entity id " + playerIn.getEntityId() + " in " + worldServer.getWorldInfo().getWorldName() + "(" + ((IMixinWorldServer) worldServer).getDimensionId() + ") at (" + playerIn.posX + ", " + playerIn.posY + ", " + playerIn.posZ + ")");
    // Sponge end
    this.updateTimeAndWeatherForPlayer(playerIn, worldServer);
    // Sponge Start - Use the server's ResourcePack object
    Optional<ResourcePack> pack = ((Server) this.mcServer).getDefaultResourcePack();
    if (pack.isPresent()) {
        ((Player) playerIn).sendResourcePack(pack.get());
    }
    // Sponge End
    // Sponge Start
    // 
    // This sends the objective/score creation packets
    // to the player, without attempting to remove them from their
    // previous scoreboard (which is set in a field initializer).
    // This allows #getWorldScoreboard to function
    // as normal, without causing issues when it is initialized on the client.
    ((IMixinEntityPlayerMP) playerIn).initScoreboard();
    for (PotionEffect potioneffect : playerIn.getActivePotionEffects()) {
        handler.sendPacket(new SPacketEntityEffect(playerIn.getEntityId(), potioneffect));
    }
    if (nbttagcompound != null) {
        if (nbttagcompound.hasKey("RootVehicle", 10)) {
            NBTTagCompound nbttagcompound1 = nbttagcompound.getCompoundTag("RootVehicle");
            Entity entity2 = AnvilChunkLoader.readWorldEntity(nbttagcompound1.getCompoundTag("Entity"), worldServer, true);
            if (entity2 != null) {
                UUID uuid = nbttagcompound1.getUniqueId("Attach");
                if (entity2.getUniqueID().equals(uuid)) {
                    playerIn.startRiding(entity2, true);
                } else {
                    for (Entity entity : entity2.getRecursivePassengers()) {
                        if (entity.getUniqueID().equals(uuid)) {
                            playerIn.startRiding(entity, true);
                            break;
                        }
                    }
                }
                if (!playerIn.isRiding()) {
                    LOGGER.warn("Couldn\'t reattach entity to player");
                    worldServer.removeEntityDangerously(entity2);
                    for (Entity entity3 : entity2.getRecursivePassengers()) {
                        worldServer.removeEntityDangerously(entity3);
                    }
                }
            }
        } else if (nbttagcompound.hasKey("Riding", 10)) {
            Entity entity1 = AnvilChunkLoader.readWorldEntity(nbttagcompound.getCompoundTag("Riding"), worldServer, true);
            if (entity1 != null) {
                playerIn.startRiding(entity1, true);
            }
        }
    }
    playerIn.addSelfToInternalCraftingInventory();
    TextComponentTranslation chatcomponenttranslation;
    if (!playerIn.getName().equalsIgnoreCase(s)) {
        chatcomponenttranslation = new TextComponentTranslation("multiplayer.player.joined.renamed", playerIn.getDisplayName(), s);
    } else {
        chatcomponenttranslation = new TextComponentTranslation("multiplayer.player.joined", playerIn.getDisplayName());
    }
    chatcomponenttranslation.getStyle().setColor(TextFormatting.YELLOW);
    // Fire PlayerJoinEvent
    Text originalMessage = SpongeTexts.toText(chatcomponenttranslation);
    MessageChannel originalChannel = player.getMessageChannel();
    Sponge.getCauseStackManager().pushCause(player);
    final ClientConnectionEvent.Join event = SpongeEventFactory.createClientConnectionEventJoin(Sponge.getCauseStackManager().getCurrentCause(), originalChannel, Optional.of(originalChannel), new MessageEvent.MessageFormatter(originalMessage), player, false);
    SpongeImpl.postEvent(event);
    Sponge.getCauseStackManager().popCause();
    // Send to the channel
    if (!event.isMessageCancelled()) {
        event.getChannel().ifPresent(channel -> channel.send(player, event.getMessage()));
    }
// Sponge end
}
Also used : SPacketPlayerAbilities(net.minecraft.network.play.server.SPacketPlayerAbilities) IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) Entity(net.minecraft.entity.Entity) SPacketSpawnPosition(net.minecraft.network.play.server.SPacketSpawnPosition) MinecraftServer(net.minecraft.server.MinecraftServer) NetHandlerPlayServer(net.minecraft.network.NetHandlerPlayServer) Server(org.spongepowered.api.Server) WorldServer(net.minecraft.world.WorldServer) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) PlayerProfileCache(net.minecraft.server.management.PlayerProfileCache) PotionEffect(net.minecraft.potion.PotionEffect) MessageEvent(org.spongepowered.api.event.message.MessageEvent) ResourcePack(org.spongepowered.api.resourcepack.ResourcePack) NBTTagCompound(net.minecraft.nbt.NBTTagCompound) WorldServer(net.minecraft.world.WorldServer) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) IMixinEntityPlayerMP(org.spongepowered.common.interfaces.entity.player.IMixinEntityPlayerMP) World(org.spongepowered.api.world.World) SPacketServerDifficulty(net.minecraft.network.play.server.SPacketServerDifficulty) SPacketHeldItemChange(net.minecraft.network.play.server.SPacketHeldItemChange) WorldInfo(net.minecraft.world.storage.WorldInfo) BlockPos(net.minecraft.util.math.BlockPos) UUID(java.util.UUID) PacketBuffer(net.minecraft.network.PacketBuffer) Player(org.spongepowered.api.entity.living.player.Player) TextComponentTranslation(net.minecraft.util.text.TextComponentTranslation) Instant(java.time.Instant) ClientConnectionEvent(org.spongepowered.api.event.network.ClientConnectionEvent) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) Text(org.spongepowered.api.text.Text) NetHandlerPlayServer(net.minecraft.network.NetHandlerPlayServer) SpongeUser(org.spongepowered.common.entity.player.SpongeUser) SPacketJoinGame(net.minecraft.network.play.server.SPacketJoinGame) SPacketCustomPayload(net.minecraft.network.play.server.SPacketCustomPayload) MessageChannel(org.spongepowered.api.text.channel.MessageChannel) GameProfile(com.mojang.authlib.GameProfile) SPacketEntityEffect(net.minecraft.network.play.server.SPacketEntityEffect) Nullable(javax.annotation.Nullable)

Example 3 with IMixinWorldServer

use of org.spongepowered.common.interfaces.world.IMixinWorldServer in project SpongeCommon by SpongePowered.

the class MixinPlayerList method recreatePlayerEntity.

/**
 * @author Zidane - June 13th, 2015
 * @author simon816 - June 24th, 2015
 * @author Zidane - March 29th, 2016
 * @author gabizou - June 5th, 2016 - Update for teleportation changes to keep the same player.
 *
 * @reason - Direct respawning players to use Sponge events
 * and process appropriately.
 *
 * @param playerIn The player being respawned/created
 * @param targetDimension The target dimension
 * @param conqueredEnd Whether the end was conquered
 * @return The new player
 */
@Overwrite
public EntityPlayerMP recreatePlayerEntity(EntityPlayerMP playerIn, int targetDimension, boolean conqueredEnd) {
    // UNLESS comming back from the end.
    if (!conqueredEnd && targetDimension == 0) {
        targetDimension = playerIn.dimension;
    }
    if (playerIn.isBeingRidden()) {
        playerIn.removePassengers();
    }
    if (playerIn.isRiding()) {
        playerIn.dismountRidingEntity();
    }
    final Player player = (Player) playerIn;
    final Transform<World> fromTransform = player.getTransform();
    WorldServer worldServer = this.mcServer.getWorld(targetDimension);
    Transform<World> toTransform = new Transform<>(EntityUtil.getPlayerRespawnLocation(playerIn, worldServer), Vector3d.ZERO, Vector3d.ZERO);
    targetDimension = ((IMixinWorldServer) toTransform.getExtent()).getDimensionId();
    Location<World> location = toTransform.getLocation();
    // If coming from end, fire a teleport event for plugins
    if (conqueredEnd) {
        // When leaving the end, players are never placed inside the teleporter but instead "respawned" in the target world
        MoveEntityEvent.Teleport teleportEvent = EntityUtil.handleDisplaceEntityTeleportEvent(playerIn, location);
        if (teleportEvent.isCancelled()) {
            playerIn.queuedEndExit = false;
            return playerIn;
        }
        toTransform = teleportEvent.getToTransform();
        location = toTransform.getLocation();
    }
    // Keep players out of blocks
    Vector3d tempPos = player.getLocation().getPosition();
    playerIn.setPosition(location.getX(), location.getY(), location.getZ());
    while (!((WorldServer) location.getExtent()).getCollisionBoxes(playerIn, playerIn.getEntityBoundingBox()).isEmpty()) {
        playerIn.setPosition(playerIn.posX, playerIn.posY + 1.0D, playerIn.posZ);
        location = location.add(0, 1, 0);
    }
    playerIn.setPosition(tempPos.getX(), tempPos.getY(), tempPos.getZ());
    // ### PHASE 2 ### Remove player from current dimension
    playerIn.getServerWorld().getEntityTracker().removePlayerFromTrackers(playerIn);
    playerIn.getServerWorld().getEntityTracker().untrack(playerIn);
    playerIn.getServerWorld().getPlayerChunkMap().removePlayer(playerIn);
    this.playerEntityList.remove(playerIn);
    this.mcServer.getWorld(playerIn.dimension).removeEntityDangerously(playerIn);
    final BlockPos bedPos = SpongeImplHooks.getBedLocation(playerIn, targetDimension);
    // ### PHASE 3 ### Reset player (if applicable)
    // Recreate the player object in order to support Forge's PlayerEvent.Clone
    PlayerInteractionManager playerinteractionmanager;
    if (this.mcServer.isDemo()) {
        playerinteractionmanager = new DemoPlayerInteractionManager(this.mcServer.getWorld(targetDimension));
    } else {
        playerinteractionmanager = new PlayerInteractionManager(this.mcServer.getWorld(targetDimension));
    }
    EntityPlayerMP newPlayer = new EntityPlayerMP(SpongeImpl.getServer(), worldServer, playerIn.getGameProfile(), playerinteractionmanager);
    newPlayer.connection = playerIn.connection;
    newPlayer.copyFrom(playerIn, conqueredEnd);
    // set player dimension for RespawnPlayerEvent
    newPlayer.dimension = targetDimension;
    newPlayer.setEntityId(playerIn.getEntityId());
    newPlayer.setCommandStats(playerIn);
    newPlayer.setPrimaryHand(playerIn.getPrimaryHand());
    // over to the new player
    if (bedPos != null) {
        newPlayer.setSpawnPoint(bedPos, playerIn.isSpawnForced());
    }
    for (String s : playerIn.getTags()) {
        newPlayer.addTag(s);
    }
    this.setPlayerGameTypeBasedOnOther(newPlayer, playerIn, worldServer);
    newPlayer.setSneaking(false);
    // update to safe location
    toTransform = toTransform.setLocation(location);
    // ### PHASE 4 ### Fire event and set new location on the player
    Sponge.getCauseStackManager().pushCause(newPlayer);
    final RespawnPlayerEvent event = SpongeEventFactory.createRespawnPlayerEvent(Sponge.getCauseStackManager().getCurrentCause(), fromTransform, toTransform, (Player) playerIn, (Player) newPlayer, EntityUtil.tempIsBedSpawn, !conqueredEnd);
    EntityUtil.tempIsBedSpawn = false;
    SpongeImpl.postEvent(event);
    Sponge.getCauseStackManager().popCause();
    ((IMixinEntity) player).setLocationAndAngles(event.getToTransform());
    toTransform = event.getToTransform();
    location = toTransform.getLocation();
    if (!(location.getExtent() instanceof WorldServer)) {
        SpongeImpl.getLogger().warn("Location set in PlayerRespawnEvent was invalid, using original location instead");
        location = event.getFromTransform().getLocation();
    }
    worldServer = (WorldServer) location.getExtent();
    final IMixinWorldServer mixinWorldServer = (IMixinWorldServer) worldServer;
    // Set the dimension again in case a plugin changed the target world during RespawnPlayerEvent
    newPlayer.dimension = mixinWorldServer.getDimensionId();
    newPlayer.setWorld(worldServer);
    newPlayer.interactionManager.setWorld(worldServer);
    worldServer.getChunkProvider().loadChunk((int) location.getX() >> 4, (int) location.getZ() >> 4);
    // ### PHASE 5 ### Respawn player in new world
    // Support vanilla clients logging into custom dimensions
    final int dimensionId = WorldManager.getClientDimensionId(newPlayer, worldServer);
    // Send dimension registration
    if (((IMixinEntityPlayerMP) newPlayer).usesCustomClient()) {
        WorldManager.sendDimensionRegistration(newPlayer, worldServer.provider);
    } else {
        // Force vanilla client to refresh its chunk cache if same dimension type
        if (fromTransform.getExtent() != worldServer && fromTransform.getExtent().getDimension().getType() == toTransform.getExtent().getDimension().getType()) {
            newPlayer.connection.sendPacket(new SPacketRespawn((dimensionId >= 0 ? -1 : 0), worldServer.getDifficulty(), worldServer.getWorldInfo().getTerrainType(), newPlayer.interactionManager.getGameType()));
        }
    }
    newPlayer.connection.sendPacket(new SPacketRespawn(dimensionId, worldServer.getDifficulty(), worldServer.getWorldInfo().getTerrainType(), newPlayer.interactionManager.getGameType()));
    newPlayer.connection.setPlayerLocation(location.getX(), location.getY(), location.getZ(), (float) toTransform.getYaw(), (float) toTransform.getPitch());
    final BlockPos spawnLocation = worldServer.getSpawnPoint();
    newPlayer.connection.sendPacket(new SPacketSpawnPosition(spawnLocation));
    newPlayer.connection.sendPacket(new SPacketSetExperience(newPlayer.experience, newPlayer.experienceTotal, newPlayer.experienceLevel));
    this.updateTimeAndWeatherForPlayer(newPlayer, worldServer);
    this.updatePermissionLevel(newPlayer);
    worldServer.getPlayerChunkMap().addPlayer(newPlayer);
    org.spongepowered.api.entity.Entity spongeEntity = (org.spongepowered.api.entity.Entity) newPlayer;
    ((org.spongepowered.api.world.World) worldServer).spawnEntity(spongeEntity);
    this.playerEntityList.add(newPlayer);
    this.uuidToPlayerMap.put(newPlayer.getUniqueID(), newPlayer);
    newPlayer.addSelfToInternalCraftingInventory();
    // Update reducedDebugInfo game rule
    newPlayer.connection.sendPacket(new SPacketEntityStatus(newPlayer, worldServer.getGameRules().getBoolean(DefaultGameRules.REDUCED_DEBUG_INFO) ? (byte) 22 : 23));
    for (PotionEffect potioneffect : newPlayer.getActivePotionEffects()) {
        newPlayer.connection.sendPacket(new SPacketEntityEffect(newPlayer.getEntityId(), potioneffect));
    }
    ((IMixinEntityPlayerMP) newPlayer).refreshScaledHealth();
    return newPlayer;
}
Also used : IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) Entity(net.minecraft.entity.Entity) MoveEntityEvent(org.spongepowered.api.event.entity.MoveEntityEvent) SPacketSpawnPosition(net.minecraft.network.play.server.SPacketSpawnPosition) PotionEffect(net.minecraft.potion.PotionEffect) WorldServer(net.minecraft.world.WorldServer) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) IMixinEntityPlayerMP(org.spongepowered.common.interfaces.entity.player.IMixinEntityPlayerMP) World(org.spongepowered.api.world.World) SPacketSetExperience(net.minecraft.network.play.server.SPacketSetExperience) BlockPos(net.minecraft.util.math.BlockPos) SPacketRespawn(net.minecraft.network.play.server.SPacketRespawn) Player(org.spongepowered.api.entity.living.player.Player) RespawnPlayerEvent(org.spongepowered.api.event.entity.living.humanoid.player.RespawnPlayerEvent) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) SPacketEntityStatus(net.minecraft.network.play.server.SPacketEntityStatus) Vector3d(com.flowpowered.math.vector.Vector3d) DemoPlayerInteractionManager(net.minecraft.server.management.DemoPlayerInteractionManager) PlayerInteractionManager(net.minecraft.server.management.PlayerInteractionManager) EntityPlayerMP(net.minecraft.entity.player.EntityPlayerMP) IMixinEntityPlayerMP(org.spongepowered.common.interfaces.entity.player.IMixinEntityPlayerMP) SPacketEntityEffect(net.minecraft.network.play.server.SPacketEntityEffect) Transform(org.spongepowered.api.entity.Transform) DemoPlayerInteractionManager(net.minecraft.server.management.DemoPlayerInteractionManager) Overwrite(org.spongepowered.asm.mixin.Overwrite)

Example 4 with IMixinWorldServer

use of org.spongepowered.common.interfaces.world.IMixinWorldServer in project SpongeCommon by SpongePowered.

the class TrackingUtil method randomTickBlock.

public static void randomTickBlock(PhaseTracker phaseTracker, IMixinWorldServer mixinWorld, Block block, BlockPos pos, IBlockState state, Random random) {
    final WorldServer minecraftWorld = mixinWorld.asMinecraftWorld();
    try (@SuppressWarnings("unused") StackFrame frame = Sponge.getCauseStackManager().pushCauseFrame()) {
        Sponge.getCauseStackManager().pushCause(minecraftWorld);
        if (ShouldFire.TICK_BLOCK_EVENT) {
            final BlockSnapshot currentTickBlock = mixinWorld.createSpongeBlockSnapshot(state, state, pos, BlockChangeFlags.NONE);
            final TickBlockEvent event = SpongeEventFactory.createTickBlockEventRandom(Sponge.getCauseStackManager().getCurrentCause(), currentTickBlock);
            SpongeImpl.postEvent(event);
            if (event.isCancelled()) {
                return;
            }
        }
        final LocatableBlock locatable = LocatableBlock.builder().location(new Location<>(mixinWorld.asSpongeWorld(), pos.getX(), pos.getY(), pos.getZ())).state((BlockState) state).build();
        Sponge.getCauseStackManager().pushCause(locatable);
        IPhaseState<BlockTickContext> phase = ((IMixinBlock) block).requiresBlockCapture() ? TickPhase.Tick.RANDOM_BLOCK : TickPhase.Tick.NO_CAPTURE_BLOCK;
        final BlockTickContext phaseContext = phase.createPhaseContext().source(locatable);
        checkAndAssignBlockTickConfig(block, minecraftWorld, phaseContext);
        // We have to associate any notifiers in case of scheduled block updates from other sources
        final PhaseData current = phaseTracker.getCurrentPhaseData();
        final IPhaseState<?> currentState = current.state;
        ((IPhaseState) currentState).appendNotifierPreBlockTick(mixinWorld, pos, current.context, phaseContext);
        // Now actually switch to the new phase
        try (PhaseContext<?> context = phaseContext.buildAndSwitch()) {
            block.randomTick(minecraftWorld, pos, state, random);
        } catch (Exception | NoClassDefFoundError e) {
            phaseTracker.printExceptionFromPhase(e, phaseContext);
        }
    }
}
Also used : SpongeBlockSnapshot(org.spongepowered.common.block.SpongeBlockSnapshot) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) WorldServer(net.minecraft.world.WorldServer) TickBlockEvent(org.spongepowered.api.event.block.TickBlockEvent) BlockState(org.spongepowered.api.block.BlockState) IBlockState(net.minecraft.block.state.IBlockState) BlockTickContext(org.spongepowered.common.event.tracking.phase.tick.BlockTickContext) StackFrame(org.spongepowered.api.event.CauseStackManager.StackFrame) LocatableBlock(org.spongepowered.api.world.LocatableBlock)

Example 5 with IMixinWorldServer

use of org.spongepowered.common.interfaces.world.IMixinWorldServer in project SpongeCommon by SpongePowered.

the class TrackingUtil method performBlockAdditions.

@SuppressWarnings("rawtypes")
public static boolean performBlockAdditions(List<Transaction<BlockSnapshot>> transactions, IPhaseState<?> phaseState, PhaseContext<?> phaseContext, boolean noCancelledTransactions) {
    // We have to use a proxy so that our pending changes are notified such that any accessors from block
    // classes do not fail on getting the incorrect block state from the IBlockAccess
    // final SpongeProxyBlockAccess proxyBlockAccess = new SpongeProxyBlockAccess(transactions);
    final CapturedMultiMapSupplier<BlockPos, ItemDropData> capturedBlockDrops = phaseContext.getBlockDropSupplier();
    final CapturedMultiMapSupplier<BlockPos, EntityItem> capturedBlockItemEntityDrops = phaseContext.getBlockItemDropSupplier();
    final CapturedMultiMapSupplier<BlockPos, net.minecraft.entity.Entity> capturedBlockEntitySpawns = phaseContext.getBlockEntitySpawnSupplier();
    for (Transaction<BlockSnapshot> transaction : transactions) {
        if (!transaction.isValid()) {
            // Rememver that this value needs to be set to false to return because of the fact that
            // a transaction was marked as invalid or cancelled. This is used primarily for
            // things like portal creation, and if false, removes the portal from the cache
            noCancelledTransactions = false;
            // Don't use invalidated block transactions during notifications, these only need to be restored
            continue;
        }
        // Handle custom replacements
        if (transaction.getCustom().isPresent()) {
            transaction.getFinal().restore(true, BlockChangeFlags.NONE);
        }
        final SpongeBlockSnapshot oldBlockSnapshot = (SpongeBlockSnapshot) transaction.getOriginal();
        final SpongeBlockSnapshot newBlockSnapshot = (SpongeBlockSnapshot) transaction.getFinal();
        final Location<World> worldLocation = oldBlockSnapshot.getLocation().get();
        final IMixinWorldServer mixinWorldServer = (IMixinWorldServer) worldLocation.getExtent();
        // Handle item drops captured
        final BlockPos pos = ((IMixinLocation) (Object) oldBlockSnapshot.getLocation().get()).getBlockPos();
        // This is for pre-merged items
        capturedBlockDrops.acceptAndRemoveIfPresent(pos, items -> spawnItemDataForBlockDrops(items, oldBlockSnapshot, phaseContext, phaseState));
        // And this is for un-pre-merged items, these will be EntityItems, not ItemDropDatas.
        capturedBlockItemEntityDrops.acceptAndRemoveIfPresent(pos, items -> spawnItemEntitiesForBlockDrops(items, oldBlockSnapshot, phaseContext, phaseState));
        // This is for entities actually spawned
        capturedBlockEntitySpawns.acceptAndRemoveIfPresent(pos, items -> spawnEntitiesForBlock(items, oldBlockSnapshot, phaseContext, phaseState));
        final WorldServer worldServer = mixinWorldServer.asMinecraftWorld();
        SpongeHooks.logBlockAction(worldServer, oldBlockSnapshot.blockChange, transaction);
        final SpongeBlockChangeFlag changeFlag = oldBlockSnapshot.getChangeFlag();
        final IBlockState originalState = (IBlockState) oldBlockSnapshot.getState();
        final IBlockState newState = (IBlockState) newBlockSnapshot.getState();
        // We call onBlockAdded here for blocks without a TileEntity.
        // MixinChunk#setBlockState will call onBlockAdded for blocks
        // with a TileEntity or when capturing is not being done.
        final PhaseTracker phaseTracker = PhaseTracker.getInstance();
        if (!SpongeImplHooks.hasBlockTileEntity(newState.getBlock(), newState) && changeFlag.performBlockPhysics() && originalState.getBlock() != newState.getBlock()) {
            newState.getBlock().onBlockAdded(worldServer, pos, newState);
            final PhaseData peek = phaseTracker.getCurrentPhaseData();
            if (peek.state == GeneralPhase.Post.UNWINDING) {
                ((IPhaseState) peek.state).unwind(peek.context);
            }
        }
        // proxyBlockAccess.proceed();
        ((IPhaseState) phaseState).handleBlockChangeWithUser(oldBlockSnapshot.blockChange, transaction, phaseContext);
        if (changeFlag.isNotifyClients()) {
            // Always try to notify clients of the change.
            worldServer.notifyBlockUpdate(pos, originalState, newState, changeFlag.getRawFlag());
        }
        if (changeFlag.updateNeighbors()) {
            // Notify neighbors only if the change flag allowed it.
            mixinWorldServer.spongeNotifyNeighborsPostBlockChange(pos, originalState, newState, changeFlag);
        } else if (changeFlag.notifyObservers()) {
            worldServer.updateObservingBlocksAt(pos, newState.getBlock());
        }
        final PhaseData peek = phaseTracker.getCurrentPhaseData();
        if (peek.state == GeneralPhase.Post.UNWINDING) {
            ((IPhaseState) peek.state).unwind(peek.context);
        }
    }
    return noCancelledTransactions;
}
Also used : IMixinEntity(org.spongepowered.common.interfaces.entity.IMixinEntity) TileEntity(org.spongepowered.api.block.tileentity.TileEntity) IMixinTileEntity(org.spongepowered.common.interfaces.block.tile.IMixinTileEntity) Entity(org.spongepowered.api.entity.Entity) SpongeBlockChangeFlag(org.spongepowered.common.world.SpongeBlockChangeFlag) IBlockState(net.minecraft.block.state.IBlockState) IMixinLocation(org.spongepowered.common.interfaces.world.IMixinLocation) SpongeBlockSnapshot(org.spongepowered.common.block.SpongeBlockSnapshot) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) IMixinWorldServer(org.spongepowered.common.interfaces.world.IMixinWorldServer) WorldServer(net.minecraft.world.WorldServer) World(org.spongepowered.api.world.World) SpongeBlockSnapshot(org.spongepowered.common.block.SpongeBlockSnapshot) BlockPos(net.minecraft.util.math.BlockPos) ItemDropData(org.spongepowered.common.event.tracking.context.ItemDropData) EntityItem(net.minecraft.entity.item.EntityItem)

Aggregations

IMixinWorldServer (org.spongepowered.common.interfaces.world.IMixinWorldServer)61 WorldServer (net.minecraft.world.WorldServer)25 BlockPos (net.minecraft.util.math.BlockPos)19 ArrayList (java.util.ArrayList)17 Entity (org.spongepowered.api.entity.Entity)15 World (org.spongepowered.api.world.World)15 IBlockState (net.minecraft.block.state.IBlockState)13 SpawnEntityEvent (org.spongepowered.api.event.entity.SpawnEntityEvent)13 CauseStackManager (org.spongepowered.api.event.CauseStackManager)11 Overwrite (org.spongepowered.asm.mixin.Overwrite)11 BlockSnapshot (org.spongepowered.api.block.BlockSnapshot)9 IMixinEntity (org.spongepowered.common.interfaces.entity.IMixinEntity)9 EntityItem (net.minecraft.entity.item.EntityItem)8 User (org.spongepowered.api.entity.living.player.User)8 LocatableBlock (org.spongepowered.api.world.LocatableBlock)8 PhaseTracker (org.spongepowered.common.event.tracking.PhaseTracker)7 Entity (net.minecraft.entity.Entity)6 EntityPlayer (net.minecraft.entity.player.EntityPlayer)6 Chunk (net.minecraft.world.chunk.Chunk)6 IMixinChunk (org.spongepowered.common.interfaces.IMixinChunk)6