2018-09-05 00:23:45 +00:00
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
2019-07-20 03:33:15 +00:00
@@ -191,7 +191,7 @@
2019-05-23 23:02:15 +00:00
private final GameProfileRepository field_152365_W;
private final PlayerProfileCache field_152366_X;
private long field_147142_T;
- protected final Thread field_175590_aa = Util.func_200696_a(new Thread(this, "Server thread"), (p_213187_0_) -> {
+ protected final Thread field_175590_aa = Util.func_200696_a(new Thread(net.minecraftforge.fml.common.thread.SidedThreadGroups.SERVER, this, "Server thread"), (p_213187_0_) -> {
p_213187_0_.setUncaughtExceptionHandler((p_213206_0_, p_213206_1_) -> {
field_147145_h.error(p_213206_1_);
});
2019-07-20 03:33:15 +00:00
@@ -327,6 +327,8 @@
2019-06-22 23:58:10 +00:00
this.func_200245_b(new TranslationTextComponent("menu.loadingLevel"));
SaveHandler savehandler = this.func_71254_M().func_197715_a(p_71247_1_, this);
this.func_175584_a(this.func_71270_I(), savehandler);
+ // Move factory creation earlier to prevent startupquery deadlock
+ IChunkStatusListener ichunkstatuslistener = this.field_213220_d.create(11);
WorldInfo worldinfo = savehandler.func_75757_d();
WorldSettings worldsettings;
if (worldinfo == null) {
2019-08-01 05:43:46 +00:00
@@ -347,13 +349,13 @@
2019-06-22 23:58:10 +00:00
}
this.func_195560_a(savehandler.func_75765_b(), worldinfo);
- IChunkStatusListener ichunkstatuslistener = this.field_213220_d.create(11);
this.func_213194_a(savehandler, worldinfo, worldsettings, ichunkstatuslistener);
this.func_147139_a(this.func_147135_j(), true);
this.func_213186_a(ichunkstatuslistener);
2019-08-01 05:43:46 +00:00
}
protected void func_213194_a(SaveHandler p_213194_1_, WorldInfo p_213194_2_, WorldSettings p_213194_3_, IChunkStatusListener p_213194_4_) {
+ net.minecraftforge.common.DimensionManager.fireRegister();
if (this.func_71242_L()) {
p_213194_2_.func_176127_a(field_213219_c);
}
@@ -395,6 +397,7 @@
2019-06-25 02:01:03 +00:00
if (dimensiontype != DimensionType.field_223227_a_) {
2019-05-23 23:02:15 +00:00
this.field_71305_c.put(dimensiontype, new ServerMultiWorld(serverworld1, this, this.field_213217_au, p_213194_1_, dimensiontype, this.field_71304_b, p_213194_4_));
2019-02-14 23:08:53 +00:00
}
2019-05-23 23:02:15 +00:00
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.world.WorldEvent.Load(field_71305_c.get(dimensiontype)));
2019-02-14 23:08:53 +00:00
}
2019-05-23 23:02:15 +00:00
}
2019-08-01 05:43:46 +00:00
@@ -552,6 +555,7 @@
2019-05-23 23:02:15 +00:00
for(ServerWorld serverworld1 : this.func_212370_w()) {
if (serverworld1 != null) {
try {
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.world.WorldEvent.Unload(serverworld1));
serverworld1.close();
} catch (IOException ioexception) {
field_147145_h.error("Exception closing the level", (Throwable)ioexception);
2019-08-01 05:43:46 +00:00
@@ -592,6 +596,7 @@
2018-09-05 00:23:45 +00:00
public void run() {
try {
2018-09-22 03:28:47 +00:00
if (this.func_71197_b()) {
2018-09-05 00:23:45 +00:00
+ net.minecraftforge.fml.server.ServerLifecycleHooks.handleServerStarted(this);
this.field_211151_aa = Util.func_211177_b();
2019-05-23 23:02:15 +00:00
this.field_147147_p.func_151315_a(new StringTextComponent(this.field_71286_C));
this.field_147147_p.func_151321_a(new ServerStatusResponse.Version(SharedConstants.func_215069_a().getName(), SharedConstants.func_215069_a().getProtocolVersion()));
2019-08-01 05:43:46 +00:00
@@ -623,9 +628,15 @@
2019-05-23 23:02:15 +00:00
this.field_71304_b.func_219897_b();
2018-09-22 03:28:47 +00:00
this.field_71296_Q = true;
2018-09-05 00:23:45 +00:00
}
+ net.minecraftforge.fml.server.ServerLifecycleHooks.handleServerStopping(this);
+ net.minecraftforge.fml.server.ServerLifecycleHooks.expectServerStopped(); // has to come before finalTick to avoid race conditions
} else {
+ net.minecraftforge.fml.server.ServerLifecycleHooks.expectServerStopped(); // has to come before finalTick to avoid race conditions
2018-09-22 03:28:47 +00:00
this.func_71228_a((CrashReport)null);
2018-09-05 00:23:45 +00:00
}
2019-07-18 20:31:37 +00:00
+ } catch (net.minecraftforge.fml.StartupQuery.AbortedException e) {
+ // ignore silently
+ net.minecraftforge.fml.server.ServerLifecycleHooks.expectServerStopped(); // has to come before finalTick to avoid race conditions
2018-09-05 00:23:45 +00:00
} catch (Throwable throwable1) {
2019-07-18 20:31:37 +00:00
field_147145_h.error("Encountered an unexpected exception", throwable1);
CrashReport crashreport;
2019-08-01 05:43:46 +00:00
@@ -642,6 +653,7 @@
2018-09-22 03:28:47 +00:00
field_147145_h.error("We were unable to save this crash report to disk.");
2018-09-05 00:23:45 +00:00
}
+ net.minecraftforge.fml.server.ServerLifecycleHooks.expectServerStopped(); // has to come before finalTick to avoid race conditions
2018-09-22 03:28:47 +00:00
this.func_71228_a(crashreport);
2018-09-05 00:23:45 +00:00
} finally {
try {
2019-08-01 05:43:46 +00:00
@@ -650,6 +662,7 @@
2018-09-05 00:23:45 +00:00
} catch (Throwable throwable) {
2018-09-22 03:28:47 +00:00
field_147145_h.error("Exception stopping the server", throwable);
2018-09-05 00:23:45 +00:00
} finally {
+ net.minecraftforge.fml.server.ServerLifecycleHooks.handleServerStopped(this);
2018-09-22 03:28:47 +00:00
this.func_71240_o();
2018-09-05 00:23:45 +00:00
}
2019-08-01 05:43:46 +00:00
@@ -746,6 +759,7 @@
2019-01-24 20:27:05 +00:00
2019-05-23 23:02:15 +00:00
protected void func_71217_p(BooleanSupplier p_71217_1_) {
2019-01-24 20:27:05 +00:00
long i = Util.func_211178_c();
+ net.minecraftforge.fml.hooks.BasicEventHooks.onPreServerTick();
++this.field_71315_w;
2019-05-23 23:02:15 +00:00
this.func_71190_q(p_71217_1_);
if (i - this.field_147142_T >= 5000000000L) {
2019-08-01 05:43:46 +00:00
@@ -760,6 +774,7 @@
2018-09-21 06:50:50 +00:00
Collections.shuffle(Arrays.asList(agameprofile));
2018-09-22 03:28:47 +00:00
this.field_147147_p.func_151318_b().func_151330_a(agameprofile);
+ this.field_147147_p.invalidateJson();
2018-09-21 06:50:50 +00:00
}
2019-05-23 23:02:15 +00:00
if (this.field_71315_w % 6000 == 0) {
2019-08-01 05:43:46 +00:00
@@ -787,6 +802,7 @@
2019-05-23 23:02:15 +00:00
long i1 = Util.func_211178_c();
this.field_213215_ap.func_181747_a(i1 - i);
2019-01-24 20:27:05 +00:00
this.field_71304_b.func_76319_b();
+ net.minecraftforge.fml.hooks.BasicEventHooks.onPostServerTick();
}
2019-05-23 23:02:15 +00:00
protected void func_71190_q(BooleanSupplier p_71190_1_) {
2019-08-01 05:43:46 +00:00
@@ -794,7 +810,8 @@
2019-07-16 16:59:33 +00:00
this.func_193030_aL().func_73660_a();
2019-06-25 02:01:03 +00:00
this.field_71304_b.func_219895_b("levels");
2019-07-16 16:59:33 +00:00
- for(ServerWorld serverworld : this.func_212370_w()) {
+ for(ServerWorld serverworld : this.getWorldArray()) {
2019-06-25 02:01:03 +00:00
+ long tickStart = Util.func_211178_c();
if (serverworld.field_73011_w.func_186058_p() == DimensionType.field_223227_a_ || this.func_71255_r()) {
this.field_71304_b.func_194340_a(() -> {
return serverworld.func_72912_H().func_76065_j() + " " + Registry.field_212622_k.func_177774_c(serverworld.field_73011_w.func_186058_p());
2019-08-01 05:43:46 +00:00
@@ -806,6 +823,7 @@
2018-09-21 06:50:50 +00:00
}
2019-01-24 20:27:05 +00:00
this.field_71304_b.func_76320_a("tick");
2019-05-23 23:02:15 +00:00
+ net.minecraftforge.fml.hooks.BasicEventHooks.onPreWorldTick(serverworld);
2019-01-24 20:27:05 +00:00
try {
2019-05-23 23:02:15 +00:00
serverworld.func_72835_b(p_71190_1_);
2019-08-01 05:43:46 +00:00
@@ -814,12 +832,16 @@
2019-05-23 23:02:15 +00:00
serverworld.func_72914_a(crashreport);
throw new ReportedException(crashreport);
2019-01-24 20:27:05 +00:00
}
2019-05-23 23:02:15 +00:00
+ net.minecraftforge.fml.hooks.BasicEventHooks.onPostWorldTick(serverworld);
2019-01-24 20:27:05 +00:00
this.field_71304_b.func_76319_b();
2019-05-23 23:02:15 +00:00
this.field_71304_b.func_76319_b();
2019-06-25 02:01:03 +00:00
}
2019-09-05 05:33:17 +00:00
+ perWorldTickTimes.computeIfAbsent(serverworld.func_201675_m().func_186058_p(), k -> new long[100])[this.field_71315_w % 100] = Util.func_211178_c() - tickStart;
2018-09-18 04:04:02 +00:00
}
2019-05-23 23:02:15 +00:00
+ this.field_71304_b.func_219895_b("dim_unloading");
2019-02-14 23:08:53 +00:00
+ net.minecraftforge.common.DimensionManager.unloadWorlds(this, this.field_71315_w % 200 == 0);
2019-05-23 23:02:15 +00:00
this.field_71304_b.func_219895_b("connection");
2018-09-22 03:28:47 +00:00
this.func_147137_ag().func_151269_c();
2019-05-23 23:02:15 +00:00
this.field_71304_b.func_219895_b("players");
2019-08-01 05:43:46 +00:00
@@ -856,6 +878,7 @@
2019-06-09 18:19:01 +00:00
OptionSpec<Integer> optionspec10 = optionparser.accepts("port").withRequiredArg().ofType(Integer.class).defaultsTo(-1);
OptionSpec<String> optionspec11 = optionparser.accepts("serverId").withRequiredArg();
OptionSpec<String> optionspec12 = optionparser.nonOptions();
+ optionparser.accepts("gameDir").withRequiredArg().ofType(File.class).defaultsTo(new File(".")); //Forge: Consume this argument, we use it in the launcher, and the client side.
try {
OptionSet optionset = optionparser.parse(p_main_0_);
2019-08-28 17:45:08 +00:00
@@ -887,6 +910,10 @@
GameProfileRepository gameprofilerepository = yggdrasilauthenticationservice.createProfileRepository();
PlayerProfileCache playerprofilecache = new PlayerProfileCache(gameprofilerepository, new File(s, field_152367_a.getName()));
String s1 = Optional.ofNullable(optionset.valueOf(optionspec9)).orElse(serverpropertiesprovider.func_219034_a().field_219021_o);
+ if (s1 == null || s1.isEmpty() || new File(s, s1).getAbsolutePath().equals(new File(s).getAbsolutePath())) {
+ field_147145_h.error("Invalid world directory specified, must not be null, empty or the same directory as your universe! " + s1);
+ return;
+ }
final DedicatedServer dedicatedserver = new DedicatedServer(new File(s), serverpropertiesprovider, DataFixesManager.func_210901_a(), yggdrasilauthenticationservice, minecraftsessionservice, gameprofilerepository, playerprofilecache, LoggingChunkStatusListener::new, s1);
dedicatedserver.func_71224_l(optionset.valueOf(optionspec7));
dedicatedserver.func_71208_b(optionset.valueOf(optionspec10));
@@ -948,7 +975,7 @@
2018-09-21 06:50:50 +00:00
}
2019-05-23 23:02:15 +00:00
public ServerWorld func_71218_a(DimensionType p_71218_1_) {
2019-02-14 23:08:53 +00:00
- return this.field_71305_c.get(p_71218_1_);
+ return net.minecraftforge.common.DimensionManager.getWorld(this, p_71218_1_, true, true);
2018-09-21 06:50:50 +00:00
}
2019-05-23 23:02:15 +00:00
public Iterable<ServerWorld> func_212370_w() {
2019-08-28 17:45:08 +00:00
@@ -987,7 +1014,7 @@
2018-09-21 06:50:50 +00:00
}
public String getServerModName() {
- return "vanilla";
2018-09-30 00:47:47 +00:00
+ return net.minecraftforge.fml.BrandingControl.getServerBranding();
2018-09-21 06:50:50 +00:00
}
2018-09-22 03:28:47 +00:00
public CrashReport func_71230_b(CrashReport p_71230_1_) {
2019-08-28 17:45:08 +00:00
@@ -1529,6 +1556,31 @@
2019-05-23 23:02:15 +00:00
public abstract boolean func_213199_b(GameProfile p_213199_1_);
2019-07-20 03:33:15 +00:00
2019-09-05 05:33:17 +00:00
+ private Map<DimensionType, long[]> perWorldTickTimes = Maps.newIdentityHashMap();
2019-02-14 23:08:53 +00:00
+ @Nullable
+ public long[] getTickTime(DimensionType dim) {
2019-09-05 05:33:17 +00:00
+ return perWorldTickTimes.get(dim);
2019-02-14 23:08:53 +00:00
+ }
+
+ @Deprecated //Forge Internal use Only, You can screw up a lot of things if you mess with this map.
2019-05-23 23:02:15 +00:00
+ public synchronized Map<DimensionType, ServerWorld> forgeGetWorldMap() {
2019-02-14 23:08:53 +00:00
+ return this.field_71305_c;
2019-07-16 16:59:33 +00:00
+ }
+ private int worldArrayMarker = 0;
+ private int worldArrayLast = -1;
+ private ServerWorld[] worldArray;
+ @Deprecated //Forge Internal use Only, use to protect against concurrent modifications in the world tick loop.
+ public synchronized void markWorldsDirty() {
+ worldArrayMarker++;
+ }
+ private ServerWorld[] getWorldArray() {
+ if (worldArrayMarker == worldArrayLast && worldArray != null)
+ return worldArray;
+ worldArray = this.field_71305_c.values().stream().toArray(x -> new ServerWorld[x]);
+ worldArrayLast = worldArrayMarker;
+ return worldArray;
2019-02-14 23:08:53 +00:00
+ }
2019-07-20 03:33:15 +00:00
+
public void func_223711_a(Path p_223711_1_) throws IOException {
Path path = p_223711_1_.resolve("levels");