-
Notifications
You must be signed in to change notification settings - Fork 651
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
Showing
18 changed files
with
444 additions
and
147 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
|
||
} |
Oops, something went wrong.