Skip to content

Commit

Permalink
Network Ticking Optimizations (#8131)
Browse files Browse the repository at this point in the history
  • Loading branch information
shartte authored Aug 9, 2024
1 parent fbc2621 commit 1a277e6
Show file tree
Hide file tree
Showing 9 changed files with 233 additions and 63 deletions.
55 changes: 50 additions & 5 deletions src/main/java/appeng/api/networking/GridServices.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,16 @@
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import net.minecraft.world.level.Level;

import appeng.me.helpers.GridServiceContainer;

/**
* A registry of grid services to extend grid functionality.
*/
Expand Down Expand Up @@ -92,14 +96,37 @@ private static boolean isRegistered(Class<?> publicInterface) {
* <p/>
* This is used by AE2 internally to initialize the services for a grid.
*/
static Map<Class<?>, IGridServiceProvider> createServices(IGrid g) {
var result = new LinkedHashMap<Class<?>, IGridServiceProvider>(registry.size());
static GridServiceContainer createServices(IGrid g) {
var services = new IdentityHashMap<Class<?>, IGridServiceProvider>(registry.size());
var serverStartTickServices = new ArrayList<IGridServiceProvider>(registry.size());
var levelStartTickServices = new ArrayList<IGridServiceProvider>(registry.size());
var levelEndTickServices = new ArrayList<IGridServiceProvider>(registry.size());
var serverEndTickServices = new ArrayList<IGridServiceProvider>(registry.size());

for (var registration : registry) {
result.put(registration.publicInterface, registration.construct(g, result));
var service = registration.construct(g, services);
services.put(registration.publicInterface, service);

if (registration.hasServerStartTick) {
serverStartTickServices.add(service);
}
if (registration.hasLevelStartTick) {
levelStartTickServices.add(service);
}
if (registration.hasLevelEndTick) {
levelEndTickServices.add(service);
}
if (registration.hasServerEndTick) {
serverEndTickServices.add(service);
}
}

return result;
return new GridServiceContainer(
services,
serverStartTickServices.toArray(IGridServiceProvider[]::new),
levelStartTickServices.toArray(IGridServiceProvider[]::new),
levelEndTickServices.toArray(IGridServiceProvider[]::new),
serverEndTickServices.toArray(IGridServiceProvider[]::new));
}

private static class GridCacheRegistration<T extends IGridServiceProvider> {
Expand All @@ -114,6 +141,11 @@ private static class GridCacheRegistration<T extends IGridServiceProvider> {

private final Set<Class<?>> dependencies;

private final boolean hasServerStartTick;
private final boolean hasLevelStartTick;
private final boolean hasLevelEndTick;
private final boolean hasServerEndTick;

@SuppressWarnings("unchecked")
public GridCacheRegistration(Class<T> implClass, Class<?> publicInterface) {
this.publicInterface = publicInterface;
Expand All @@ -130,6 +162,19 @@ public GridCacheRegistration(Class<T> implClass, Class<?> publicInterface) {
this.dependencies = Arrays.stream(this.constructorParameterTypes)
.filter(t -> !t.equals(IGrid.class))
.collect(Collectors.toSet());

try {
this.hasServerStartTick = implClass.getMethod("onServerStartTick")
.getDeclaringClass() != IGridServiceProvider.class;
this.hasLevelStartTick = implClass.getMethod("onLevelStartTick", Level.class)
.getDeclaringClass() != IGridServiceProvider.class;
this.hasLevelEndTick = implClass.getMethod("onLevelEndTick", Level.class)
.getDeclaringClass() != IGridServiceProvider.class;
this.hasServerEndTick = implClass.getMethod("onServerEndTick")
.getDeclaringClass() != IGridServiceProvider.class;
} catch (NoSuchMethodException exception) {
throw new RuntimeException("Failed to check which methods the grid service implements", exception);
}
}

public IGridServiceProvider construct(IGrid g, Map<Class<?>, IGridServiceProvider> createdServices) {
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/appeng/api/networking/GridServicesInternal.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@

package appeng.api.networking;

import java.util.Map;
import appeng.me.helpers.GridServiceContainer;

/**
* Allows access to non-public features of {@link GridServices}.
*/
public class GridServicesInternal {

public static Map<Class<?>, IGridServiceProvider> createServices(IGrid g) {
public static GridServiceContainer createServices(IGrid g) {
return GridServices.createServices(g);
}

Expand Down
10 changes: 10 additions & 0 deletions src/main/java/appeng/crafting/execution/CraftingCpuLogic.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import appeng.core.network.clientbound.CraftingJobStatusPacket;
import appeng.crafting.CraftingLink;
import appeng.crafting.inv.ListCraftingInventory;
import appeng.hooks.ticking.TickHandler;
import appeng.me.cluster.implementations.CraftingCPUCluster;
import appeng.me.service.CraftingService;

Expand All @@ -75,6 +76,8 @@ public class CraftingCpuLogic {
*/
private boolean cantStoreItems = false;

private long lastModifiedOnTick = TickHandler.instance().getCurrentTick();

public CraftingCpuLogic(CraftingCPUCluster cluster) {
this.cluster = cluster;
}
Expand Down Expand Up @@ -390,11 +393,16 @@ public void storeItems() {
}

private void postChange(AEKey what) {
lastModifiedOnTick = TickHandler.instance().getCurrentTick();
for (var listener : listeners) {
listener.accept(what);
}
}

public long getLastModifiedOnTick() {
return lastModifiedOnTick;
}

public boolean hasJob() {
return this.job != null;
}
Expand Down Expand Up @@ -509,6 +517,8 @@ public boolean isCantStoreItems() {
}

private void notifyJobOwner(ExecutingCraftingJob job, CraftingJobStatusPacket.Status status) {
this.lastModifiedOnTick = TickHandler.instance().getCurrentTick();

var playerId = job.playerId;
if (playerId == null) {
return;
Expand Down
26 changes: 11 additions & 15 deletions src/main/java/appeng/me/Grid.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
import appeng.api.networking.IGridNode;
import appeng.api.networking.IGridNodeListener;
import appeng.api.networking.IGridService;
import appeng.api.networking.IGridServiceProvider;
import appeng.api.networking.crafting.ICraftingService;
import appeng.api.networking.energy.IEnergyService;
import appeng.api.networking.events.GridEvent;
Expand All @@ -58,6 +57,7 @@
import appeng.api.networking.ticking.ITickManager;
import appeng.core.AELog;
import appeng.hooks.ticking.TickHandler;
import appeng.me.helpers.GridServiceContainer;
import appeng.me.service.P2PService;
import appeng.parts.AEBasePart;
import appeng.util.IDebugExportable;
Expand All @@ -71,7 +71,7 @@ public class Grid implements IGrid {
private static int nextSerial = 0;

private final SetMultimap<Class<?>, IGridNode> machines = MultimapBuilder.hashKeys().hashSetValues().build();
private final Map<Class<?>, IGridServiceProvider> services;
private final GridServiceContainer services;
// Becomes null after the last node has left the grid.
@Nullable
private GridNode pivot;
Expand Down Expand Up @@ -103,17 +103,13 @@ int getPriority() {
return this.priority;
}

Collection<IGridServiceProvider> getProviders() {
return this.services.values();
}

@Override
public int size() {
return this.machines.size();
}

void remove(GridNode gridNode) {
for (var c : this.services.values()) {
for (var c : services.services().values()) {
c.removeNode(gridNode);
}

Expand All @@ -137,21 +133,21 @@ void add(GridNode gridNode, @Nullable CompoundTag savedData) {
// track node.
this.machines.put(gridNode.getOwner().getClass(), gridNode);

for (var service : this.services.values()) {
for (var service : services.services().values()) {
service.addNode(gridNode, savedData);
}
}

void saveNodeData(GridNode gridNode, CompoundTag savedData) {
for (var service : this.services.values()) {
for (var service : services.services().values()) {
service.saveNodeData(gridNode, savedData);
}
}

@SuppressWarnings("unchecked")
@Override
public <C extends IGridService> C getService(Class<C> iface) {
var service = this.services.get(iface);
var service = this.services.services().get(iface);
if (service == null) {
throw new IllegalArgumentException("Service " + iface + " is not registered");
}
Expand Down Expand Up @@ -224,7 +220,7 @@ public void onServerStartTick() {
return;
}

for (var gc : this.services.values()) {
for (var gc : this.services.serverStartTickServices()) {
gc.onServerStartTick();
}
}
Expand All @@ -234,7 +230,7 @@ public void onLevelStartTick(Level level) {
return;
}

for (var gc : this.services.values()) {
for (var gc : this.services.levelStartTickServices()) {
gc.onLevelStartTick(level);
}
}
Expand All @@ -244,7 +240,7 @@ public void onLevelEndTick(Level level) {
return;
}

for (var gc : this.services.values()) {
for (var gc : this.services.levelEndtickServices()) {
gc.onLevelEndTick(level);
}
}
Expand All @@ -254,7 +250,7 @@ public void onServerEndTick() {
return;
}

for (var gc : this.services.values()) {
for (var gc : this.services.serverEndTickServices()) {
gc.onServerEndTick();
}
}
Expand Down Expand Up @@ -354,7 +350,7 @@ public void export(JsonWriter jsonWriter) throws IOException {

jsonWriter.name("services");
jsonWriter.beginObject();
for (var entry : services.entrySet()) {
for (var entry : services.services().entrySet()) {
jsonWriter.name(getServiceExportKey(entry.getKey()));
jsonWriter.beginObject();
entry.getValue().debugDump(jsonWriter, registries);
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/appeng/me/helpers/GridServiceContainer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package appeng.me.helpers;

import java.util.Map;

import appeng.api.networking.IGridServiceProvider;

public record GridServiceContainer(
Map<Class<?>, IGridServiceProvider> services,
IGridServiceProvider[] serverStartTickServices,
IGridServiceProvider[] levelStartTickServices,
IGridServiceProvider[] levelEndtickServices,
IGridServiceProvider[] serverEndTickServices) {
}
Loading

0 comments on commit 1a277e6

Please sign in to comment.