Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor out some reflective constructor calls #860

Merged
merged 27 commits into from Mar 17, 2018
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6c68b2f
Merge remote-tracking branch 'refs/remotes/GlowstoneMC/dev' into remo…
Pr0methean Mar 8, 2018
644fe73
Refactor out some reflective constructor calls
Pr0methean Mar 8, 2018
dc37fa5
Remove reflection from CompoundTag.putList()
Pr0methean Mar 8, 2018
0ec47a6
Unused import
Pr0methean Mar 8, 2018
c5db810
Delete TagType.getConstructor()
Pr0methean Mar 8, 2018
22d24e3
Use MethodHandle to cache reflection where possible
Pr0methean Mar 8, 2018
aba6086
Style fix
Pr0methean Mar 8, 2018
7e3d638
Revert change to LibraryManager (doesn't quite work)
Pr0methean Mar 8, 2018
65cecaa
Work around https://github.com/mojohaus/animal-sniffer/issues/18
Pr0methean Mar 8, 2018
b907db0
Switch to ConcurrentHashMap
Pr0methean Mar 8, 2018
f7a3508
Unused imports
Pr0methean Mar 8, 2018
d70bf6d
Test reducing heap to 512MB
Pr0methean Mar 8, 2018
b80967a
Make entityCtors static
Pr0methean Mar 8, 2018
d78caf8
One-arg ctor for GlowTntPrimed, instead of special handling
Pr0methean Mar 10, 2018
63e4cce
Extract put*List
Pr0methean Mar 10, 2018
3a2762d
Javadoc fix
Pr0methean Mar 10, 2018
754c395
Unused imports
Pr0methean Mar 10, 2018
06d80f9
Style fixes
Pr0methean Mar 10, 2018
617e78c
Merge remote-tracking branch 'refs/remotes/GlowstoneMC/dev' into remo…
Pr0methean Mar 11, 2018
6c6774b
Map entity types to ctors in EntityRegistry
Pr0methean Mar 11, 2018
7b89ce9
Unused imports
Pr0methean Mar 11, 2018
6baa9be
Address https://github.com/GlowstoneMC/Glowstone/pull/860#discussion_…
Pr0methean Mar 12, 2018
28a4319
Merge remote-tracking branch 'refs/remotes/GlowstoneMC/dev' into remo…
Pr0methean Mar 12, 2018
0a3fd5d
Bug fix
Pr0methean Mar 12, 2018
326250c
Merge branch 'dev' into removeReflection
mastercoms Mar 17, 2018
aa74dbb
Javadoc fix
Pr0methean Mar 17, 2018
45a6d91
pom.xml bugfix
Pr0methean Mar 17, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions .circleci/config.yml
@@ -1,7 +1,7 @@
version: 2
machine:
environment:
_JAVA_OPTIONS: "-Xms1024m -Xmx1024m"
_JAVA_OPTIONS: "-Xms512m -Xmx512m"
jobs:
build:
docker:
Expand All @@ -10,7 +10,7 @@ jobs:
working_directory: ~/glowstone

environment:
MAVEN_OPTS: -Xmx1024m
MAVEN_OPTS: -Xmx512m

steps:
- run: mvn --version
Expand Down Expand Up @@ -48,7 +48,7 @@ jobs:
working_directory: ~/glowstone

environment:
MAVEN_OPTS: -Xmx1024m
MAVEN_OPTS: -Xmx512m

steps:
- checkout
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Expand Up @@ -225,6 +225,7 @@
<artifactId>java18</artifactId>
<version>1.0</version>
</signature>
<ignores>java.lang.invoke.MethodHandle</ignores>
</configuration>
</plugin>

Expand Down
109 changes: 50 additions & 59 deletions src/main/java/net/glowstone/GlowWorld.java
Expand Up @@ -4,8 +4,6 @@
import com.google.common.base.Preconditions;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand Down Expand Up @@ -45,13 +43,13 @@
import net.glowstone.entity.GlowLightningStrike;
import net.glowstone.entity.GlowLivingEntity;
import net.glowstone.entity.GlowPlayer;
import net.glowstone.entity.GlowTntPrimed;
import net.glowstone.entity.objects.GlowFallingBlock;
import net.glowstone.entity.objects.GlowItem;
import net.glowstone.entity.physics.BoundingBox;
import net.glowstone.generator.structures.GlowStructure;
import net.glowstone.io.WorldMetadataService.WorldFinalValues;
import net.glowstone.io.WorldStorageProvider;
import net.glowstone.io.entity.EntityStorage;
import net.glowstone.net.message.play.entity.EntityStatusMessage;
import net.glowstone.net.message.play.game.BlockChangeMessage;
import net.glowstone.net.message.play.player.ServerDifficultyMessage;
Expand Down Expand Up @@ -86,7 +84,6 @@
import org.bukkit.entity.LightningStrike;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.TNTPrimed;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.bukkit.event.entity.EntitySpawnEvent;
Expand Down Expand Up @@ -839,7 +836,7 @@ public boolean setSpawnLocation(int x, int y, int z) {
* Sets the spawn location of the world.
*
* @param newSpawn the new spawn location
* @param anchor if true, the spawn is never unloaded while the world is running
* @param anchor if true, the spawn is never unloaded while the world is running
* @return true if the spawn location has changed
*/
public boolean setSpawnLocation(Location newSpawn, boolean anchor) {
Expand Down Expand Up @@ -1200,7 +1197,7 @@ public Block getHighestBlockAt(Location location) {
* and all blocks above it are either air or one of the given materials.
*
* @param location Coordinates to get the highest block
* @param except Blocks to exclude in addition to air
* @param except Blocks to exclude in addition to air
* @return Highest non-empty block
*/
public Block getHighestBlockAt(Location location, Material... except) {
Expand Down Expand Up @@ -1405,48 +1402,42 @@ public <T extends Entity> T spawn(Location location, Class<T> clazz,
* Spawns an entity.
*
* @param location the {@link Location} to spawn the entity at
* @param clazz the class of the {@link Entity} to spawn
* @param reason the reason for the spawning of the entity
* @param clazz the class of the {@link Entity} to spawn
* @param reason the reason for the spawning of the entity
* @return an instance of the spawned {@link Entity}
* @throws IllegalArgumentException TODO: document the reason this can happen
*/
public GlowEntity spawn(Location location, Class<? extends GlowEntity> clazz,
SpawnReason reason) throws IllegalArgumentException {
GlowEntity entity = null;

if (TNTPrimed.class.isAssignableFrom(clazz)) {
entity = new GlowTntPrimed(location, null);
}
GlowEntity entity = null;

if (entity == null) {
try {
Constructor<? extends GlowEntity> constructor = clazz
.getConstructor(Location.class);
entity = constructor.newInstance(location);
GlowEntity impl = entity;
// function.accept(entity); TODO: work on type mismatches
EntitySpawnEvent spawnEvent = null;
if (entity instanceof LivingEntity) {
spawnEvent = EventFactory
.callEvent(new CreatureSpawnEvent((LivingEntity) entity, reason));
} else if (!(entity instanceof Item)) { // ItemSpawnEvent is called elsewhere
spawnEvent = EventFactory.callEvent(new EntitySpawnEvent(entity));
}
if (spawnEvent != null && spawnEvent.isCancelled()) {
// TODO: separate spawning and construction for better event cancellation
entity.remove();
} else {
List<Message> spawnMessage = entity.createSpawnMessage();
getRawPlayers().stream().filter(player -> player.canSeeEntity(impl))
.forEach(player -> player.getSession().sendAll(spawnMessage
.toArray(new Message[spawnMessage.size()])));
}
} catch (NoSuchMethodException e) {
GlowServer.logger.log(Level.WARNING, "Invalid entity spawn: ", e);
} catch (IllegalAccessException | InstantiationException | InvocationTargetException
e) {
GlowServer.logger.log(Level.SEVERE, "Unable to spawn entity: ", e);
try {
if (EntityRegistry.getEntity(clazz) != null) {
entity = EntityStorage.create(clazz, location);
}
// function.accept(entity); TODO: work on type mismatches
EntitySpawnEvent spawnEvent = null;
if (entity instanceof LivingEntity) {
spawnEvent = EventFactory
.callEvent(new CreatureSpawnEvent((LivingEntity) entity, reason));
} else if (!(entity instanceof Item)) { // ItemSpawnEvent is called elsewhere
spawnEvent = EventFactory.callEvent(new EntitySpawnEvent(entity));
}
if (spawnEvent != null && spawnEvent.isCancelled()) {
// TODO: separate spawning and construction for better event cancellation
entity.remove();
} else {
List<Message> spawnMessage = entity.createSpawnMessage();
final GlowEntity finalEntity = entity;
getRawPlayers().stream().filter(player -> player.canSeeEntity(finalEntity))
.forEach(player -> player.getSession().sendAll(spawnMessage
.toArray(new Message[spawnMessage.size()])));
}
} catch (NoSuchMethodError | IllegalAccessError e) {
GlowServer.logger.log(Level.WARNING, "Invalid entity spawn: ", e);
} catch (Throwable t) {
GlowServer.logger.log(Level.SEVERE, "Unable to spawn entity: ", t);
}

if (entity != null) {
Expand Down Expand Up @@ -1743,11 +1734,11 @@ public <T> void playEffect(Location location, Effect effect, T data, int radius)
* Plays an effect to all but one player within a given radius around a location.
*
* @param location the {@link Location} around which players must be to
* hear the effect
* @param effect the {@link Effect}
* @param data a data bit needed for some effects
* @param radius the radius around the location
* @param exclude the player who won't see the effect
* hear the effect
* @param effect the {@link Effect}
* @param data a data bit needed for some effects
* @param radius the radius around the location
* @param exclude the player who won't see the effect
*/
public void playEffectExceptTo(Location location, Effect effect, int data, int radius,
Player exclude) {
Expand Down Expand Up @@ -1795,13 +1786,13 @@ public Spigot spigot() {
/**
* Displays the given particle to all players.
*
* @param loc the location
* @param loc the location
* @param particle the particle type
* @param offsetX TODO: document this parameter
* @param offsetY TODO: document this parameter
* @param offsetZ TODO: document this parameter
* @param speed TODO: document this parameter
* @param amount the number of particles
* @param offsetX TODO: document this parameter
* @param offsetY TODO: document this parameter
* @param offsetZ TODO: document this parameter
* @param speed TODO: document this parameter
* @param amount the number of particles
*/
//@Override
public void showParticle(Location loc, Effect particle, float offsetX, float offsetY,
Expand All @@ -1820,15 +1811,15 @@ public void showParticle(Location loc, Effect particle, float offsetX, float off
/**
* Displays the given particle to all players.
*
* @param loc the location
* @param loc the location
* @param particle the particle type
* @param id the block or item type ID
* @param data the block or item data
* @param offsetX TODO: document this parameter
* @param offsetY TODO: document this parameter
* @param offsetZ TODO: document this parameter
* @param speed TODO: document this parameter
* @param amount the number of particles
* @param id the block or item type ID
* @param data the block or item data
* @param offsetX TODO: document this parameter
* @param offsetY TODO: document this parameter
* @param offsetZ TODO: document this parameter
* @param speed TODO: document this parameter
* @param amount the number of particles
*/
//@Override
public void showParticle(Location loc, Effect particle, int id, int data, float offsetX,
Expand Down
2 changes: 0 additions & 2 deletions src/main/java/net/glowstone/block/blocktype/BlockFence.java
@@ -1,13 +1,11 @@
package net.glowstone.block.blocktype;

import com.google.common.collect.ImmutableList;

import net.glowstone.EventFactory;
import net.glowstone.block.GlowBlock;
import net.glowstone.entity.GlowPlayer;
import net.glowstone.entity.objects.GlowLeashHitch;
import net.glowstone.inventory.MaterialMatcher;

import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.LeashHitch;
Expand Down
3 changes: 0 additions & 3 deletions src/main/java/net/glowstone/block/itemtype/ItemItemFrame.java
@@ -1,14 +1,11 @@
package net.glowstone.block.itemtype;

import com.flowpowered.network.Message;

import java.util.List;

import net.glowstone.EventFactory;
import net.glowstone.block.GlowBlock;
import net.glowstone.entity.GlowPlayer;
import net.glowstone.entity.objects.GlowItemFrame;

import org.bukkit.block.BlockFace;
import org.bukkit.event.hanging.HangingPlaceEvent;
import org.bukkit.inventory.EquipmentSlot;
Expand Down
2 changes: 0 additions & 2 deletions src/main/java/net/glowstone/command/GameModeUtils.java
@@ -1,9 +1,7 @@
package net.glowstone.command;

import com.google.common.collect.ImmutableList;

import java.util.List;

import org.bukkit.GameMode;

/**
Expand Down
11 changes: 10 additions & 1 deletion src/main/java/net/glowstone/entity/GlowTntPrimed.java
Expand Up @@ -35,11 +35,20 @@ public GlowPlayer getPlayer() {
return (source instanceof GlowPlayer) ? (GlowPlayer) source : null;
}

/**
* Creates a primed TNT block, not associated with any igniting entity.
*
* @param location the location
*/
public GlowTntPrimed(Location location) {
this(location, null);
}

/**
* Creates a primed TNT block.
*
* @param location the location
* @param source the entity that ignited this
* @param source the entity that ignited this; may be null
*/
public GlowTntPrimed(Location location, Entity source) {
super(location, Explosion.POWER_TNT);
Expand Down
@@ -1,15 +1,14 @@
package net.glowstone.generator.decorators.overworld;

import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.function.BiFunction;
import lombok.Data;
import net.glowstone.generator.decorators.BlockDecorator;
import net.glowstone.generator.objects.trees.GenericTree;
import net.glowstone.util.BlockStateDelegate;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;

Expand Down Expand Up @@ -37,16 +36,15 @@ public void decorate(World world, Random random, Chunk source) {
int sourceX = (source.getX() << 4) + random.nextInt(16);
int sourceZ = (source.getZ() << 4) + random.nextInt(16);
Block sourceBlock = world
.getBlockAt(sourceX, world.getHighestBlockYAt(sourceX, sourceZ), sourceZ);
.getBlockAt(sourceX, world.getHighestBlockYAt(sourceX, sourceZ), sourceZ);

Class<? extends GenericTree> clazz = getRandomTree(random, trees);
if (clazz != null) {
BiFunction<Random, BlockStateDelegate, ? extends GenericTree> ctor
= getRandomTree(random, trees);
if (ctor != null) {
BlockStateDelegate delegate = new BlockStateDelegate();
GenericTree tree;
try {
Constructor<? extends GenericTree> c = clazz
.getConstructor(Random.class, Location.class, BlockStateDelegate.class);
tree = c.newInstance(random, sourceBlock.getLocation(), delegate);
tree = ctor.apply(random, delegate);
} catch (Exception ex) {
tree = new GenericTree(random, delegate);
}
Expand All @@ -56,8 +54,8 @@ public void decorate(World world, Random random, Chunk source) {
}
}

private Class<? extends GenericTree> getRandomTree(Random random,
List<TreeDecoration> decorations) {
private BiFunction<Random, BlockStateDelegate, ? extends GenericTree>
getRandomTree(Random random, List<TreeDecoration> decorations) {
int totalWeight = 0;
for (TreeDecoration decoration : decorations) {
totalWeight += decoration.getWeight();
Expand All @@ -66,15 +64,15 @@ private Class<? extends GenericTree> getRandomTree(Random random,
for (TreeDecoration decoration : decorations) {
weight -= decoration.getWeight();
if (weight < 0) {
return decoration.getTree();
return decoration.getConstructor();
}
}
return null;
}

@Data
public static final class TreeDecoration {
private final Class<? extends GenericTree> tree;
private final BiFunction<Random, BlockStateDelegate, ? extends GenericTree> constructor;
private final int weight;
}
}
Expand Up @@ -2,7 +2,6 @@

import java.util.Random;
import net.glowstone.util.BlockStateDelegate;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
Expand All @@ -16,11 +15,10 @@ public class MegaPineTree extends MegaRedwoodTree {
* Initializes this tree with a random height, preparing it to attempt to generate.
*
* @param random the PRNG
* @param location the base of the trunk
* @param delegate the BlockStateDelegate used to check for space and to fill wood and leaf
* blocks
*/
public MegaPineTree(Random random, Location location, BlockStateDelegate delegate) {
public MegaPineTree(Random random, BlockStateDelegate delegate) {
super(random, delegate);
setLeavesHeight(random.nextInt(5) + 3);
}
Expand Down
Expand Up @@ -2,20 +2,18 @@

import java.util.Random;
import net.glowstone.util.BlockStateDelegate;
import org.bukkit.Location;

public class MegaSpruceTree extends MegaPineTree {

/**
* Initializes this tree, preparing it to attempt to generate.
*
* @param random the PRNG
* @param location the base of the trunk
* @param delegate the BlockStateDelegate used to check for space and to fill wood and leaf
* blocks
*/
public MegaSpruceTree(Random random, Location location, BlockStateDelegate delegate) {
super(random, location, delegate);
public MegaSpruceTree(Random random, BlockStateDelegate delegate) {
super(random, delegate);
setLeavesHeight(leavesHeight + 10);
}
}