Prevent worlds from unloading while players are in out-of-world states by tracking all worlds references by every player in the server's player list.

This commit is contained in:
LexManos committed 2019-08-20 15:31:08 -07:00
1 parent 5291ea7270
commit 283c3d1664
6 files changed
+107 -40

No files matched your search

@@ -23,8 +23,10 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;
@@ -45,6 +47,7 @@ import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.network.PacketBuffer;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.management.PlayerList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.registry.MutableRegistry;
@@ -80,6 +83,7 @@ public class DimensionManager
private static final ConcurrentMap<World, World> weakWorldMap = new MapMaker().weakKeys().weakValues().makeMap();
private static final Multiset<Integer> leakedWorlds = HashMultiset.create();
private static final Map<ResourceLocation, SavedEntry> savedEntries = new HashMap<>();
private static volatile Set<World> playerWorlds = new HashSet<>();
/**
* Registers a real unique dimension, Should be called on server init, or when the dimension is created.
@@ -144,7 +148,7 @@ public class DimensionManager
/**
* Retrieves the world from the server allowing for null return, and optionally resetting it's unload timer.
*
* @param server The server that controlls this world.
* @param server The server that controls this world.
* @param dim Dimension to load.
* @param resetUnloadDelay True to reset the unload timer, which is a delay that is used to prevent constant world loading/unloading cycle.
* @param forceLoad True to attempt to load the dimension if the server has it unloaded.
@@ -222,7 +226,8 @@ public class DimensionManager
return world.getDimension().getType() != DimensionType.OVERWORLD
&& world.getPlayers().isEmpty()
&& world.getForcedChunks().isEmpty()
&& !getData(world.getDimension().getType()).keepLoaded;
&& !getData(world.getDimension().getType()).keepLoaded
&& !playerWorlds.contains(world);
}
/**
@@ -484,4 +489,10 @@ public class DimensionManager
@Override public void statusChanged(ChunkPos p_219508_1_, ChunkStatus p_219508_2_) { }
@Override public void stop() { }
}
public static boolean rebuildPlayerMap(PlayerList players, boolean changed)
{
playerWorlds = players.getPlayers().stream().map(e -> e.world).collect(Collectors.toSet());
return changed;
}
}
@@ -21,12 +21,14 @@ package net.minecraftforge.common;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.client.CloudRenderer;
import net.minecraftforge.common.util.FakePlayerFactory;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.EventPriority;
@@ -46,18 +48,16 @@ public class ForgeInternalHandler
{
ItemStack stack = ((ItemEntity)entity).getItem();
Item item = stack.getItem();
/*
if (item.hasCustomEntity(stack))
{
Entity newEntity = item.createEntity(event.getWorld(), entity, stack);
if (newEntity != null)
{
entity.setDead();
entity.remove();
event.setCanceled(true);
event.getWorld().spawnEntity(newEntity);
event.getWorld().addEntity(newEntity);
}
}
*/
}
}
@@ -88,5 +88,18 @@ public class ForgeInternalHandler
if (!event.getWorld().isRemote())
FarmlandWaterManager.removeTickets(event.getChunk());
}
@SubscribeEvent
public void playerChangeDimension(PlayerEvent.PlayerChangedDimensionEvent event)
{
if (event.getPlayer() instanceof ServerPlayerEntity)
DimensionManager.rebuildPlayerMap(((ServerPlayerEntity)event.getPlayer()).server.getPlayerList(), true);
}
@SubscribeEvent
public void playerLogin(PlayerEvent.PlayerLoggedInEvent event)
{
UsernameCache.setUsername(event.getPlayer().getUniqueID(), event.getPlayer().getGameProfile().getName());
}
}
@@ -49,7 +49,6 @@ import net.minecraftforge.common.data.ForgeItemTagsProvider;
import net.minecraftforge.common.data.ForgeRecipeProvider;
import net.minecraftforge.common.model.animation.CapabilityAnimation;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.fml.event.lifecycle.GatherDataEvent;
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
import net.minecraftforge.items.CapabilityItemHandler;
@@ -93,7 +92,6 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
modEventBus.addListener(this::preInit);
modEventBus.addListener(this::gatherData);
MinecraftForge.EVENT_BUS.addListener(this::serverStarting);
MinecraftForge.EVENT_BUS.addListener(this::playerLogin);
MinecraftForge.EVENT_BUS.addListener(this::serverStopping);
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ForgeConfig.clientSpec);
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, ForgeConfig.serverSpec);
@@ -103,12 +101,6 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
StartupMessageManager.addModMessage("Forge version "+ForgeVersion.getVersion());
}
public void playerLogin(PlayerEvent.PlayerLoggedInEvent event)
{
UsernameCache.setUsername(event.getPlayer().getUniqueID(), event.getPlayer().getGameProfile().getName());
}
public void preInit(FMLCommonSetupEvent evt)
{
CapabilityItemHandler.register();