-
-
Notifications
You must be signed in to change notification settings - Fork 44
/
TickThreading.java
120 lines (108 loc) · 5.16 KB
/
TickThreading.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package me.nallar.tickthreading.minecraft;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.event.FMLServerStartingEvent;
import cpw.mods.fml.common.network.NetworkMod;
import me.nallar.tickthreading.Log;
import me.nallar.tickthreading.minecraft.commands.TPSCommand;
import me.nallar.tickthreading.minecraft.commands.TicksCommand;
import me.nallar.tickthreading.minecraft.entitylist.EntityList;
import me.nallar.tickthreading.minecraft.entitylist.LoadedTileEntityList;
import me.nallar.tickthreading.util.FieldUtil;
import net.minecraft.command.ServerCommandManager;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.Configuration;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.Property;
import net.minecraftforge.event.ForgeSubscribe;
import net.minecraftforge.event.world.WorldEvent;
@SuppressWarnings ("WeakerAccess")
@Mod (modid = "TickThreading", name = "TickThreading", version = "1.0")
@NetworkMod (clientSideRequired = false, serverSideRequired = false)
public class TickThreading {
private final int loadedTileEntityFieldIndex = 2;
private final int loadedEntityFieldIndex = 0;
private int regionSize = 16;
private boolean variableTickRate = true;
final Map<World, TickManager> managers = new HashMap<World, TickManager>();
private static TickThreading instance;
@Mod.Init
public void init(FMLInitializationEvent event) {
MinecraftForge.EVENT_BUS.register(this);
instance = this;
}
@Mod.PreInit
public void preInit(FMLPreInitializationEvent event) {
Configuration config = new Configuration(event.getSuggestedConfigurationFile());
config.load();
Property regionSizeProperty = config.get(Configuration.CATEGORY_GENERAL, "regionSize", String.valueOf(regionSize));
regionSizeProperty.comment = "width/length of tick regions, specified in blocks.";
Property variableTickRateProperty = config.get(Configuration.CATEGORY_GENERAL, "variableRegionTickRate", variableTickRate);
variableTickRateProperty.comment = "Allows tick rate to vary per region so that each region uses at most 50ms on average per tick.";
Property ticksCommandName = config.get(Configuration.CATEGORY_GENERAL, "ticksCommandName", TicksCommand.name);
ticksCommandName.comment = "Name of the command to be used for performance stats. Defaults to ticks.";
Property tpsCommandName = config.get(Configuration.CATEGORY_GENERAL, "tpsCommandName", TPSCommand.name);
tpsCommandName.comment = "Name of the command to be used for TPS reports.";
config.save();
regionSize = regionSizeProperty.getInt(regionSize);
variableTickRate = variableTickRateProperty.getBoolean(variableTickRate);
TicksCommand.name = ticksCommandName.value;
TPSCommand.name = tpsCommandName.value;
}
@Mod.ServerStarting
public void serverStarting(FMLServerStartingEvent event) {
ServerCommandManager serverCommandManager = (ServerCommandManager) event.getServer().getCommandManager();
serverCommandManager.registerCommand(new TicksCommand());
serverCommandManager.registerCommand(new TPSCommand());
}
@ForgeSubscribe
public void onWorldLoad(WorldEvent.Load event) {
TickManager manager = new TickManager(event.world, regionSize);
manager.setVariableTickRate(variableTickRate);
try {
Field loadedTileEntityField = FieldUtil.getFields(World.class, List.class)[loadedTileEntityFieldIndex];
//Field loadedEntityField = FieldUtil.getFields(World.class)[loadedEntityFieldIndex];
new LoadedTileEntityList<TileEntity>(event.world, loadedTileEntityField, manager);
Log.info("Threading initialised for world " + Log.name(event.world));
// TODO: Enable entity tick threading
// Requires:
// - AxisAlignedBB pool threadLocal
// - ^automated patching
//new LoadedEntityList<TileEntity>(event.world, loadedEntityField, manager);
managers.put(event.world, manager);
} catch (Exception e) {
Log.severe("Failed to initialise tile threading for world " + Log.name(event.world), e);
}
}
@ForgeSubscribe
public void onWorldUnload(WorldEvent.Unload event) {
managers.remove(event.world);
try {
Field loadedTileEntityField = FieldUtil.getFields(World.class, List.class)[loadedTileEntityFieldIndex];
Object loadedTileEntityList = loadedTileEntityField.get(event.world);
if (loadedTileEntityList instanceof EntityList) {
((EntityList) loadedTileEntityList).unload();
} else {
Log.severe("Looks like another mod broke TickThreading in world: " + Log.name(event.world));
}
} catch (Exception e) {
Log.severe("Probable memory leak, failed to unload tile threading for world " + Log.name(event.world), e);
}
}
public TickManager getManager(World world) {
return managers.get(world);
}
public List<TickManager> getManagers() {
return new ArrayList<TickManager>(managers.values());
}
public static TickThreading instance() {
return instance;
}
}