Search in sources :

Example 1 with ServerLevelBridge

use of org.spongepowered.common.bridge.server.level.ServerLevelBridge in project SpongeCommon by SpongePowered.

the class ServerLevelMixin method save.

/**
 * @author zidane - December 17th, 2020 - Minecraft 1.16.4
 * @reason Honor our serialization behavior in performing saves
 */
@Overwrite
public void save(@Nullable final ProgressListener progress, final boolean flush, final boolean skipSave) {
    final Cause currentCause = Sponge.server().causeStackManager().currentCause();
    if (Sponge.eventManager().post(SpongeEventFactory.createSaveWorldEventPre(currentCause, ((ServerWorld) this)))) {
        // cancelled save
        return;
    }
    final PrimaryLevelData levelData = (PrimaryLevelData) this.shadow$getLevelData();
    final ServerChunkCache chunkProvider = ((ServerLevel) (Object) this).getChunkSource();
    if (!skipSave) {
        final SerializationBehavior behavior = ((PrimaryLevelDataBridge) levelData).bridge$serializationBehavior().orElse(SerializationBehavior.AUTOMATIC);
        if (progress != null) {
            progress.progressStartNoAbort(new TranslatableComponent("menu.savingLevel"));
        }
        // We always save the metadata unless it is NONE
        if (behavior != SerializationBehavior.NONE) {
            this.shadow$saveLevelData();
            // Sponge Start - We do per-world WorldInfo/WorldBorders/BossBars
            levelData.setWorldBorder(this.getWorldBorder().createSettings());
            levelData.setCustomBossEvents(((ServerLevelBridge) this).bridge$getBossBarManager().save());
            ((ServerLevelBridge) this).bridge$getLevelSave().saveDataTag(SpongeCommon.server().registryAccess(), (PrimaryLevelData) this.shadow$getLevelData(), this.shadow$dimension() == Level.OVERWORLD ? SpongeCommon.server().getPlayerList().getSingleplayerData() : null);
        // Sponge End
        }
        if (progress != null) {
            progress.progressStage(new TranslatableComponent("menu.savingChunks"));
        }
        final boolean canAutomaticallySave = !this.impl$isManualSave && behavior == SerializationBehavior.AUTOMATIC;
        final boolean canManuallySave = this.impl$isManualSave && behavior == SerializationBehavior.MANUAL;
        if (canAutomaticallySave || canManuallySave) {
            chunkProvider.save(flush);
        }
        Sponge.eventManager().post(SpongeEventFactory.createSaveWorldEventPost(currentCause, ((ServerWorld) this)));
    }
    this.impl$isManualSave = false;
}
Also used : PrimaryLevelData(net.minecraft.world.level.storage.PrimaryLevelData) ServerLevel(net.minecraft.server.level.ServerLevel) TranslatableComponent(net.minecraft.network.chat.TranslatableComponent) Cause(org.spongepowered.api.event.Cause) SerializationBehavior(org.spongepowered.api.world.SerializationBehavior) ServerChunkCache(net.minecraft.server.level.ServerChunkCache) ServerLevelBridge(org.spongepowered.common.bridge.server.level.ServerLevelBridge) PlatformServerLevelBridge(org.spongepowered.common.bridge.world.level.PlatformServerLevelBridge) Overwrite(org.spongepowered.asm.mixin.Overwrite)

Example 2 with ServerLevelBridge

use of org.spongepowered.common.bridge.server.level.ServerLevelBridge in project SpongeCommon by SpongePowered.

the class SpongeCommonEventFactory method handlePistonEvent.

/**
 * This simulates the blocks a piston moves and calls the event for saner
 * debugging.
 *
 * @return if the event was cancelled
 */
public static boolean handlePistonEvent(final TrackedWorldBridge world, final BlockPos pos, final net.minecraft.world.level.block.state.BlockState blockstate, final int eventId) {
    final boolean extending = (eventId == 0);
    final net.minecraft.core.Direction direction = blockstate.getValue(DirectionalBlock.FACING);
    final LocatableBlock locatable = new SpongeLocatableBlockBuilder().world((ServerWorld) world).state((BlockState) blockstate).position(pos.getX(), pos.getY(), pos.getZ()).build();
    // Sets toss out duplicate values (even though there shouldn't be any)
    final HashSet<ServerLocation> locations = new HashSet<>();
    locations.add(ServerLocation.of((ServerWorld) world, pos.getX(), pos.getY(), pos.getZ()));
    final PistonStructureResolver movedBlocks = new PistonStructureResolver((ServerLevel) world, pos, direction, extending);
    // calculates blocks to be moved
    movedBlocks.resolve();
    Stream.concat(movedBlocks.getToPush().stream(), movedBlocks.getToDestroy().stream()).map(block -> ServerLocation.of((ServerWorld) world, block.getX(), block.getY(), block.getZ())).collect(// SUPER
    Collectors.toCollection(() -> locations));
    // If the piston is extending and there are no blocks to destroy, add the offset location for protection purposes
    if (extending && movedBlocks.getToDestroy().isEmpty()) {
        final List<BlockPos> movedPositions = movedBlocks.getToPush();
        final BlockPos offsetPos;
        // If there are no blocks to move, add the offset of piston
        if (movedPositions.isEmpty()) {
            offsetPos = pos.relative(direction);
        } else {
            // Add the offset of last block set to move
            offsetPos = movedPositions.get(movedPositions.size() - 1).relative(direction);
        }
        locations.add(ServerLocation.of((ServerWorld) world, offsetPos.getX(), offsetPos.getY(), offsetPos.getZ()));
    }
    try (final CauseStackManager.StackFrame frame = PhaseTracker.getInstance().pushCauseFrame()) {
        if (extending) {
            frame.addContext(EventContextKeys.PISTON_EXTEND, (ServerWorld) world);
        } else {
            frame.addContext(EventContextKeys.PISTON_RETRACT, (ServerWorld) world);
        }
        return SpongeCommonEventFactory.callChangeBlockEventPre((ServerLevelBridge) world, ImmutableList.copyOf(locations), locatable).isCancelled();
    }
}
Also used : ServerLevelBridge(org.spongepowered.common.bridge.server.level.ServerLevelBridge) ChangeBlockEvent(org.spongepowered.api.event.block.ChangeBlockEvent) SpongeAdventure(org.spongepowered.common.adventure.SpongeAdventure) CreatorTrackedBridge(org.spongepowered.common.bridge.CreatorTrackedBridge) Living(org.spongepowered.api.entity.living.Living) JukeboxBlockEntity(net.minecraft.world.level.block.entity.JukeboxBlockEntity) ServerboundPlayerActionPacket(net.minecraft.network.protocol.game.ServerboundPlayerActionPacket) Set(java.util.Set) MapIdTrackerBridge(org.spongepowered.common.bridge.map.MapIdTrackerBridge) BlockState(org.spongepowered.api.block.BlockState) Direction(org.spongepowered.api.util.Direction) ConstructEntityEvent(org.spongepowered.api.event.entity.ConstructEntityEvent) Stream(java.util.stream.Stream) World(org.spongepowered.api.world.World) ItemStack(net.minecraft.world.item.ItemStack) Player(org.spongepowered.api.entity.living.player.Player) MoveEntityEvent(org.spongepowered.api.event.entity.MoveEntityEvent) ServerLocation(org.spongepowered.api.world.server.ServerLocation) SpongeMapStorage(org.spongepowered.common.map.SpongeMapStorage) LevelChunkBridge(org.spongepowered.common.bridge.world.level.chunk.LevelChunkBridge) EventContextKeys(org.spongepowered.api.event.EventContextKeys) ServerWorld(org.spongepowered.api.world.server.ServerWorld) DestructEntityEvent(org.spongepowered.api.event.entity.DestructEntityEvent) Agent(org.spongepowered.api.entity.living.Agent) Supplier(java.util.function.Supplier) ArrayList(java.util.ArrayList) EntityBridge(org.spongepowered.common.bridge.world.entity.EntityBridge) RotateEntityEvent(org.spongepowered.api.event.entity.RotateEntityEvent) PlaySoundEvent(org.spongepowered.api.event.sound.PlaySoundEvent) DetonateExplosiveEvent(org.spongepowered.api.event.entity.explosive.DetonateExplosiveEvent) InteractBlockEvent(org.spongepowered.api.event.block.InteractBlockEvent) CauseStackManager(org.spongepowered.api.event.CauseStackManager) GeneralPhase(org.spongepowered.common.event.tracking.phase.general.GeneralPhase) SpongeEventFactory(org.spongepowered.api.event.SpongeEventFactory) PlayerTracker(org.spongepowered.common.entity.PlayerTracker) UnknownProjectileSource(org.spongepowered.common.entity.projectile.UnknownProjectileSource) PhaseTracker(org.spongepowered.common.event.tracking.PhaseTracker) Entity(org.spongepowered.api.entity.Entity) Cause(org.spongepowered.api.event.Cause) Explosive(org.spongepowered.api.entity.explosive.Explosive) PistonStructureResolver(net.minecraft.world.level.block.piston.PistonStructureResolver) Audience(net.kyori.adventure.audience.Audience) VecHelper(org.spongepowered.common.util.VecHelper) InteractionHand(net.minecraft.world.InteractionHand) ServerPlayer(org.spongepowered.api.entity.living.player.server.ServerPlayer) LivingEntity(net.minecraft.world.entity.LivingEntity) MapItemSavedData(net.minecraft.world.level.saveddata.maps.MapItemSavedData) MusicDisc(org.spongepowered.api.effect.sound.music.MusicDisc) ItemStackSnapshot(org.spongepowered.api.item.inventory.ItemStackSnapshot) HandType(org.spongepowered.api.data.type.HandType) DropItemEvent(org.spongepowered.api.event.item.inventory.DropItemEvent) ExplosiveBridge(org.spongepowered.common.bridge.explosives.ExplosiveBridge) CollideBlockEvent(org.spongepowered.api.event.block.CollideBlockEvent) SetAITargetEvent(org.spongepowered.api.event.entity.ai.SetAITargetEvent) TrackedWorldBridge(org.spongepowered.common.bridge.world.TrackedWorldBridge) ActiveChunkReferantBridge(org.spongepowered.common.bridge.world.level.chunk.ActiveChunkReferantBridge) CollideEntityEvent(org.spongepowered.api.event.entity.CollideEntityEvent) NotePitch(org.spongepowered.api.data.type.NotePitch) InteractEntityEvent(org.spongepowered.api.event.entity.InteractEntityEvent) LocatableBlock(org.spongepowered.api.world.LocatableBlock) SoundType(org.spongepowered.api.effect.sound.SoundType) BlockHitResult(net.minecraft.world.phys.BlockHitResult) GameRules(net.minecraft.world.level.GameRules) Sponge(org.spongepowered.api.Sponge) InstrumentType(org.spongepowered.api.data.type.InstrumentType) UUID(java.util.UUID) ProjectileSource(org.spongepowered.api.projectile.source.ProjectileSource) Collectors(java.util.stream.Collectors) Tristate(org.spongepowered.api.util.Tristate) List(java.util.List) Sound(net.kyori.adventure.sound.Sound) MapInfo(org.spongepowered.api.map.MapInfo) BlockPos(net.minecraft.core.BlockPos) SoundEvent(net.minecraft.sounds.SoundEvent) Explosion(org.spongepowered.api.world.explosion.Explosion) PhaseContext(org.spongepowered.common.event.tracking.PhaseContext) Optional(java.util.Optional) InteractItemEvent(org.spongepowered.api.event.item.inventory.InteractItemEvent) Level(net.minecraft.world.level.Level) BlockSnapshot(org.spongepowered.api.block.BlockSnapshot) NonNull(org.checkerframework.checker.nullness.qual.NonNull) Constants(org.spongepowered.common.util.Constants) ServerLevel(net.minecraft.server.level.ServerLevel) Value(org.spongepowered.api.data.value.Value) EntityDamageSource(net.minecraft.world.damagesource.EntityDamageSource) HashSet(java.util.HashSet) ImmutableList(com.google.common.collect.ImmutableList) EntityTypes(org.spongepowered.api.entity.EntityTypes) ItemStackUtil(org.spongepowered.common.item.util.ItemStackUtil) Component(net.kyori.adventure.text.Component) DamageSource(net.minecraft.world.damagesource.DamageSource) SoundTypes(org.spongepowered.api.effect.sound.SoundTypes) PlatformEntityBridge(org.spongepowered.common.bridge.world.entity.PlatformEntityBridge) Nullable(org.checkerframework.checker.nullness.qual.Nullable) LevelBridge(org.spongepowered.common.bridge.world.level.LevelBridge) DirectionFacingProvider(org.spongepowered.common.registry.provider.DirectionFacingProvider) EntityHitResult(net.minecraft.world.phys.EntityHitResult) SpongeLocatableBlockBuilder(org.spongepowered.common.world.server.SpongeLocatableBlockBuilder) SpongeCommon(org.spongepowered.common.SpongeCommon) MapIndex(net.minecraft.world.level.saveddata.maps.MapIndex) HitResult(net.minecraft.world.phys.HitResult) MovementTypes(org.spongepowered.api.event.cause.entity.MovementTypes) Vector3d(org.spongepowered.math.vector.Vector3d) CreateMapEvent(org.spongepowered.api.event.action.CreateMapEvent) Block(net.minecraft.world.level.block.Block) SpawnTypes(org.spongepowered.api.event.cause.entity.SpawnTypes) Collections(java.util.Collections) DirectionalBlock(net.minecraft.world.level.block.DirectionalBlock) Jukebox(org.spongepowered.api.block.entity.Jukebox) SpongeLocatableBlockBuilder(org.spongepowered.common.world.server.SpongeLocatableBlockBuilder) ServerLocation(org.spongepowered.api.world.server.ServerLocation) ServerWorld(org.spongepowered.api.world.server.ServerWorld) CauseStackManager(org.spongepowered.api.event.CauseStackManager) PistonStructureResolver(net.minecraft.world.level.block.piston.PistonStructureResolver) LocatableBlock(org.spongepowered.api.world.LocatableBlock) BlockPos(net.minecraft.core.BlockPos) ServerLevelBridge(org.spongepowered.common.bridge.server.level.ServerLevelBridge) HashSet(java.util.HashSet)

Example 3 with ServerLevelBridge

use of org.spongepowered.common.bridge.server.level.ServerLevelBridge in project SpongeCommon by SpongePowered.

the class SpongeWorldManager method unloadWorld0.

private void unloadWorld0(final ServerLevel world) throws IOException {
    final net.minecraft.resources.ResourceKey<Level> registryKey = world.dimension();
    if (world.getPlayers(p -> true).size() != 0) {
        throw new IOException(String.format("World '%s' was told to unload but players remain.", registryKey.location()));
    }
    SpongeCommon.logger().info("Unloading world '{}' ({})", registryKey.location(), RegistryTypes.WORLD_TYPE.get().valueKey((WorldType) world.dimensionType()));
    SpongeCommon.post(SpongeEventFactory.createUnloadWorldEvent(PhaseTracker.getCauseStackManager().currentCause(), (org.spongepowered.api.world.server.ServerWorld) world));
    final BlockPos spawnPoint = world.getSharedSpawnPos();
    world.getChunkSource().removeRegionTicket(SpongeWorldManager.SPAWN_CHUNKS, new ChunkPos(spawnPoint), 11, registryKey.location());
    ((PrimaryLevelDataBridge) world.getLevelData()).bridge$configAdapter().save();
    ((ServerLevelBridge) world).bridge$setManualSave(true);
    try {
        world.save(null, true, world.noSave);
        world.close();
        ((ServerLevelBridge) world).bridge$getLevelSave().close();
    } catch (final Exception ex) {
        throw new IOException(ex);
    }
    this.worlds.remove(registryKey);
}
Also used : IOException(java.io.IOException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) ReportedException(net.minecraft.ReportedException) WorldType(org.spongepowered.api.world.WorldType) Level(net.minecraft.world.level.Level) ServerLevel(net.minecraft.server.level.ServerLevel) BlockPos(net.minecraft.core.BlockPos) ChunkPos(net.minecraft.world.level.ChunkPos) ServerLevelBridge(org.spongepowered.common.bridge.server.level.ServerLevelBridge)

Example 4 with ServerLevelBridge

use of org.spongepowered.common.bridge.server.level.ServerLevelBridge in project SpongeCommon by SpongePowered.

the class SpongeWorldManager method loadSpawnChunks.

private void loadSpawnChunks(final ServerLevel world) {
    final BlockPos spawnPoint = world.getSharedSpawnPos();
    final ChunkPos chunkPos = new ChunkPos(spawnPoint);
    final ChunkProgressListener chunkStatusListener = ((ServerLevelBridge) world).bridge$getChunkStatusListener();
    chunkStatusListener.updateSpawnPos(chunkPos);
    final ServerChunkCache serverChunkProvider = world.getChunkSource();
    serverChunkProvider.getLightEngine().setTaskPerBatch(500);
    ((MinecraftServerAccessor) this.server).accessor$nextTickTime(Util.getMillis());
    serverChunkProvider.addRegionTicket(SpongeWorldManager.SPAWN_CHUNKS, chunkPos, 11, world.dimension().location());
    while (serverChunkProvider.getTickingGenerated() != 441) {
        ((MinecraftServerAccessor) this.server).accessor$nextTickTime(Util.getMillis() + 10L);
        ((MinecraftServerAccessor) this.server).accessor$waitUntilNextTick();
    }
    ((MinecraftServerAccessor) this.server).accessor$nextTickTime(Util.getMillis() + 10L);
    ((MinecraftServerAccessor) this.server).accessor$waitUntilNextTick();
    this.updateForcedChunks(world, serverChunkProvider);
    ((MinecraftServerAccessor) this.server).accessor$nextTickTime(Util.getMillis() + 10L);
    ((MinecraftServerAccessor) this.server).accessor$waitUntilNextTick();
    chunkStatusListener.stop();
    serverChunkProvider.getLightEngine().setTaskPerBatch(5);
    // Sponge Start - Release the chunk ticket if spawn is not set to be kept loaded...
    if (!((PrimaryLevelDataBridge) world.getLevelData()).bridge$performsSpawnLogic()) {
        serverChunkProvider.removeRegionTicket(SpongeWorldManager.SPAWN_CHUNKS, chunkPos, 11, world.dimension().location());
    }
}
Also used : MinecraftServerAccessor(org.spongepowered.common.accessor.server.MinecraftServerAccessor) ChunkProgressListener(net.minecraft.server.level.progress.ChunkProgressListener) BlockPos(net.minecraft.core.BlockPos) ChunkPos(net.minecraft.world.level.ChunkPos) ServerChunkCache(net.minecraft.server.level.ServerChunkCache) ServerLevelBridge(org.spongepowered.common.bridge.server.level.ServerLevelBridge)

Example 5 with ServerLevelBridge

use of org.spongepowered.common.bridge.server.level.ServerLevelBridge in project SpongeCommon by SpongePowered.

the class ServerLevelMixin_Tracker method tracker$associatePhaseContextDataWithBlockEvent.

@Redirect(method = "blockEvent", at = @At(value = "INVOKE", target = "Lit/unimi/dsi/fastutil/objects/ObjectLinkedOpenHashSet;add(Ljava/lang/Object;)Z", remap = false))
private boolean tracker$associatePhaseContextDataWithBlockEvent(final ObjectLinkedOpenHashSet<BlockEventData> list, final Object data, final BlockPos pos, final Block blockIn, final int eventID, final int eventParam) {
    final PhaseContext<@NonNull ?> currentContext = PhaseTracker.getInstance().getPhaseContext();
    final BlockEventData blockEventData = (BlockEventData) data;
    final TrackableBlockEventDataBridge blockEvent = (TrackableBlockEventDataBridge) blockEventData;
    // Short circuit phase states who do not track during block events
    if (currentContext.ignoresBlockEvent()) {
        return list.add(blockEventData);
    }
    final BlockState state = this.shadow$getBlockState(pos);
    if (((TrackableBridge) blockIn).bridge$allowsBlockEventCreation()) {
        blockEvent.bridge$setSourceUserUUID(currentContext.getActiveUserUUID());
        if (((BlockStateBridge) state).bridge$hasTileEntity()) {
            blockEvent.bridge$setTileEntity((BlockEntity) this.shadow$getBlockEntity(pos));
        }
        if (blockEvent.bridge$getTileEntity() == null) {
            final LocatableBlock locatable = new SpongeLocatableBlockBuilder().world((org.spongepowered.api.world.server.ServerWorld) this).position(pos.getX(), pos.getY(), pos.getZ()).state((org.spongepowered.api.block.BlockState) state).build();
            blockEvent.bridge$setTickingLocatable(locatable);
        }
    }
    // allow tracking to take place for other/future phases
    if (!((TrackableBridge) blockIn).bridge$allowsBlockEventCreation()) {
        return list.add((BlockEventData) data);
    }
    // In pursuant with our block updates management, we chose to
    // effectively allow the block event get added to the list, but
    // we log the transaction so that we can call the change block event
    // pre, and if needed, undo the add to the list.
    currentContext.appendNotifierToBlockEvent(this, pos, blockEvent);
    // This is very common with pistons as they add block events while blocks are being notified.
    if (ShouldFire.CHANGE_BLOCK_EVENT_PRE) {
        if (blockIn instanceof PistonBaseBlock) {
            // We only fire pre events for pistons
            if (SpongeCommonEventFactory.handlePistonEvent(this, pos, state, eventID)) {
                return false;
            }
        } else {
            if (SpongeCommonEventFactory.callChangeBlockEventPre((ServerLevelBridge) this, pos).isCancelled()) {
                return false;
            }
        }
    }
    currentContext.getTransactor().logBlockEvent(state, this, pos, blockEvent);
    return list.add(blockEventData);
}
Also used : SpongeLocatableBlockBuilder(org.spongepowered.common.world.server.SpongeLocatableBlockBuilder) TrackableBlockEventDataBridge(org.spongepowered.common.bridge.world.level.TrackableBlockEventDataBridge) TrackableBridge(org.spongepowered.common.bridge.TrackableBridge) PistonBaseBlock(net.minecraft.world.level.block.piston.PistonBaseBlock) BlockState(net.minecraft.world.level.block.state.BlockState) LocatableBlock(org.spongepowered.api.world.LocatableBlock) ServerLevelBridge(org.spongepowered.common.bridge.server.level.ServerLevelBridge) BlockEventData(net.minecraft.world.level.BlockEventData) BlockStateBridge(org.spongepowered.common.bridge.world.level.block.state.BlockStateBridge) Redirect(org.spongepowered.asm.mixin.injection.Redirect)

Aggregations

ServerLevelBridge (org.spongepowered.common.bridge.server.level.ServerLevelBridge)5 BlockPos (net.minecraft.core.BlockPos)3 ServerLevel (net.minecraft.server.level.ServerLevel)3 ServerChunkCache (net.minecraft.server.level.ServerChunkCache)2 ChunkPos (net.minecraft.world.level.ChunkPos)2 Level (net.minecraft.world.level.Level)2 Cause (org.spongepowered.api.event.Cause)2 ImmutableList (com.google.common.collect.ImmutableList)1 IOException (java.io.IOException)1 ArrayList (java.util.ArrayList)1 Collections (java.util.Collections)1 HashSet (java.util.HashSet)1 List (java.util.List)1 Optional (java.util.Optional)1 Set (java.util.Set)1 UUID (java.util.UUID)1 ExecutionException (java.util.concurrent.ExecutionException)1 Supplier (java.util.function.Supplier)1 Collectors (java.util.stream.Collectors)1 Stream (java.util.stream.Stream)1