Skip to content

Commit

Permalink
Fixes #5069: Fix crash in uninitialised worlds without any AE2 tile. (#…
Browse files Browse the repository at this point in the history
…5070)

* Fixes #5069: Fix crash in uninitialised worlds without any AE2 tile.

Also refactored the `TickHandler` and extracted all inner classes to
avoid direct field access to avoid accessing it in an initialised state.

Further replaced the used jdk collections with fastutil ones as these
are slightly faster for adding or iterating over them, but more
noticeable these will resize themselves once the fall below a certain
load factor. This prevents large, but mostly empty collections after a
server start or similiarly adding hundreds or even thousands of AE2
tiles.

Co-authored-by: Sebastian Hartte <sebastian@hartte.de>
  • Loading branch information
yueh and shartte authored Mar 16, 2021
1 parent 38bb72a commit 060594e
Show file tree
Hide file tree
Showing 18 changed files with 444 additions and 147 deletions.
2 changes: 1 addition & 1 deletion src/main/java/appeng/core/AppEng.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
import appeng.entity.SingularityEntity;
import appeng.entity.TinyTNTPrimedEntity;
import appeng.entity.TinyTNTPrimedRenderer;
import appeng.hooks.TickHandler;
import appeng.hooks.ticking.TickHandler;
import appeng.integration.Integrations;
import appeng.parts.PartPlacement;
import appeng.server.ServerHelper;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
import appeng.api.util.AEColor;
import appeng.core.sync.BasePacket;
import appeng.core.sync.network.INetworkInfo;
import appeng.hooks.TickHandler;
import appeng.hooks.TickHandler.PlayerColor;
import appeng.hooks.ticking.PlayerColor;
import appeng.hooks.ticking.TickHandler;

public class PaintedEntityPacket extends BasePacket {

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/appeng/crafting/CraftingJob.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
import appeng.api.util.DimensionalCoord;
import appeng.core.AELog;
import appeng.core.Api;
import appeng.hooks.TickHandler;
import appeng.hooks.ticking.TickHandler;

public class CraftingJob implements Runnable, ICraftingJob {
private static final String LOG_CRAFTING_JOB = "CraftingJob (%s) issued by %s requesting [%s] using %s bytes took %s ms";
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/appeng/debug/DebugCardItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
import appeng.api.parts.IPart;
import appeng.api.parts.IPartHost;
import appeng.api.util.AEPartLocation;
import appeng.hooks.TickHandler;
import appeng.hooks.ticking.TickHandler;
import appeng.items.AEBaseItem;
import appeng.me.Grid;
import appeng.me.GridNode;
Expand Down
63 changes: 63 additions & 0 deletions src/main/java/appeng/hooks/ticking/PlayerColor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2021, TeamAppliedEnergistics, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/

package appeng.hooks.ticking;

import appeng.api.util.AEColor;
import appeng.core.sync.packets.PaintedEntityPacket;

/**
* Handles how long the color overlay for a player is valid
*/
public class PlayerColor {

private final AEColor myColor;
private final int myEntity;
private int ticksLeft;

public PlayerColor(final int id, final AEColor col, final int ticks) {
this.myEntity = id;
this.myColor = col;
this.ticksLeft = ticks;
}

public PaintedEntityPacket getPacket() {
return new PaintedEntityPacket(this.myEntity, this.myColor, this.ticksLeft);
}

public AEColor getColor() {
return myColor;
}

/**
* Tick this player color once.
*/
void tick() {
this.ticksLeft--;
}

/**
* Indicates that this color is done and can be removed.
*
* @return true once done.
*/
boolean isDone() {
return this.ticksLeft <= 0;
}

}
93 changes: 93 additions & 0 deletions src/main/java/appeng/hooks/ticking/ServerGridRepo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2021, TeamAppliedEnergistics, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/

package appeng.hooks.ticking;

import java.util.Objects;

import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import it.unimi.dsi.fastutil.objects.ObjectSet;

import appeng.me.Grid;

/**
* A class to hold data related to ticking networks.
*/
class ServerGridRepo {
private final ObjectSet<Grid> networks = new ObjectOpenHashSet<>();
private final ObjectSet<Grid> toAdd = new ObjectOpenHashSet<>();
private final ObjectSet<Grid> toRemove = new ObjectOpenHashSet<>();

/**
* Resets all internal data
*/
void clear() {
this.networks.clear();
this.toAdd.clear();
this.toRemove.clear();
}

/**
* Queues adding a new network.
* <p>
* Is added once {@link ServerGridRepo#updateNetworks()} is called.
* <p>
* Also removes it from the removal list, in case the network is validated again.
*/
synchronized void addNetwork(Grid g) {
Objects.requireNonNull(g);

this.toAdd.add(g);
this.toRemove.remove(g);
}

/**
* Queues removal of a network.
* <p>
* Is fully removed once {@link ServerGridRepo#updateNetworks()} is called.
* <p>
* Also removes it from the list to add in case it got invalid.
*/
synchronized void removeNetwork(Grid g) {
Objects.requireNonNull(g);

this.toRemove.add(g);
this.toAdd.remove(g);
}

/**
* Processes all networks to add or remove.
* <p>
* First all removals are handled, then the ones queued to be added.
*/
synchronized void updateNetworks() {
this.networks.removeAll(this.toRemove);
this.toRemove.clear();

this.networks.addAll(this.toAdd);
this.toAdd.clear();
}

/**
* Get all registered {@link Grid}s
*/
public Iterable<Grid> getNetworks() {
return networks;
}

}
103 changes: 103 additions & 0 deletions src/main/java/appeng/hooks/ticking/ServerTileRepo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2021, TeamAppliedEnergistics, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/

package appeng.hooks.ticking;

import java.util.ArrayDeque;
import java.util.Map;
import java.util.Queue;

import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.IWorld;

import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;

import appeng.tile.AEBaseTileEntity;

/**
* A class to hold data related to ticking tiles.
*/
class ServerTileRepo {

private final Map<IWorld, Long2ObjectMap<Queue<AEBaseTileEntity>>> tiles = new Object2ObjectOpenHashMap<>();

/**
* Resets all internal data
*
*/
void clear() {
this.tiles.clear();
}

/**
* Add a new tile to be initializes in a later tick.
*/
synchronized void addTile(AEBaseTileEntity tile) {
final IWorld world = tile.getWorld();
final int x = tile.getPos().getX() >> 4;
final int z = tile.getPos().getZ() >> 4;
final long chunkPos = ChunkPos.asLong(x, z);

Long2ObjectMap<Queue<AEBaseTileEntity>> worldQueue = this.tiles.get(world);

Queue<AEBaseTileEntity> queue = worldQueue.computeIfAbsent(chunkPos, key -> {
return new ArrayDeque<>();
});

queue.add(tile);
}

/**
* Sets up the necessary defaults when a new world is loaded
*/
synchronized void addWorld(IWorld world) {
this.tiles.computeIfAbsent(world, (key) -> {
return new Long2ObjectOpenHashMap<>();
});
}

/**
* Tears down data related to a now unloaded world
*/
synchronized void removeWorld(IWorld world) {
this.tiles.remove(world);
}

/**
* Removes a unloaded chunk within a world.
*
* There is no related addWorldChunk. The necessary queue will be created once the first tile is added to a chunk to
* save memory.
*/
synchronized void removeWorldChunk(IWorld world, long chunkPos) {
Map<Long, Queue<AEBaseTileEntity>> queue = this.tiles.get(world);
if (queue != null) {
queue.remove(chunkPos);
}
}

/**
* Get the tiles needing to be initialized in this specific {@link IWorld}.
*/
public Long2ObjectMap<Queue<AEBaseTileEntity>> getTiles(IWorld world) {
return tiles.get(world);
}

}
Loading

0 comments on commit 060594e

Please sign in to comment.