Ensure skull operations are done on the player thread

This commit is contained in:
Camotoy 2021-08-21 19:38:13 -04:00
parent ab540b1951
commit a1d167d5f1
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
3 changed files with 37 additions and 30 deletions

View file

@ -34,7 +34,6 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.AddPlayerPacket; import com.nukkitx.protocol.bedrock.packet.AddPlayerPacket;
import lombok.Getter; import lombok.Getter;
import lombok.Setter;
import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
@ -43,17 +42,16 @@ import org.geysermc.connector.network.session.GeyserSession;
* custom player skulls in Bedrock. * custom player skulls in Bedrock.
*/ */
public class SkullPlayerEntity extends PlayerEntity { public class SkullPlayerEntity extends PlayerEntity {
/** /**
* Stores the block state that the skull is associated with. Used to determine if the block in the skull's position * Stores the block state that the skull is associated with. Used to determine if the block in the skull's position
* has changed * has changed
*/ */
@Getter @Getter
@Setter private final int blockState;
private int blockState;
public SkullPlayerEntity(GameProfile gameProfile, long geyserId, Vector3f position, Vector3f rotation) { public SkullPlayerEntity(GameProfile gameProfile, long geyserId, Vector3f position, Vector3f rotation, int blockState) {
super(gameProfile, 0, geyserId, position, Vector3f.ZERO, rotation); super(gameProfile, 0, geyserId, position, Vector3f.ZERO, rotation);
this.blockState = blockState;
setPlayerList(false); setPlayerList(false);
//Set bounding box to almost nothing so the skull is able to be broken and not cause entity to cast a shadow //Set bounding box to almost nothing so the skull is able to be broken and not cause entity to cast a shadow

View file

@ -883,7 +883,7 @@ public class GeyserSession implements CommandSender {
try { try {
runnable.run(); runnable.run();
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); connector.getLogger().error("Error thrown in " + getName() + "'s event loop!", e);
} }
}); });
} }
@ -896,7 +896,7 @@ public class GeyserSession implements CommandSender {
try { try {
runnable.run(); runnable.run();
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); connector.getLogger().error("Error thrown in " + getName() + "'s event loop!", e);
} }
}, duration, timeUnit); }, duration, timeUnit);
} }

View file

@ -123,22 +123,32 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements
Vector3i blockPosition = Vector3i.from(posX, posY, posZ); Vector3i blockPosition = Vector3i.from(posX, posY, posZ);
Vector3f entityPosition = Vector3f.from(x, y, z); Vector3f entityPosition = Vector3f.from(x, y, z);
Vector3f entityRotation = Vector3f.from(rotation, 0, rotation); Vector3f entityRotation = Vector3f.from(rotation, 0, rotation);
long geyserId = session.getEntityCache().getNextEntityId().incrementAndGet();
getProfile(tag).whenComplete((gameProfile, throwable) -> { getProfile(tag).whenComplete((gameProfile, throwable) -> {
if (gameProfile == null) { if (gameProfile == null) {
session.getConnector().getLogger().debug("Custom skull with invalid SkullOwner tag: " + blockPosition.toString() + " " + tag.toString()); session.getConnector().getLogger().debug("Custom skull with invalid SkullOwner tag: " + blockPosition + " " + tag);
return; return;
} }
if (session.getEventLoop().inEventLoop()) {
spawnPlayer(session, gameProfile, blockPosition, entityPosition, entityRotation, blockState);
} else {
session.executeInEventLoop(() -> spawnPlayer(session, gameProfile, blockPosition, entityPosition, entityRotation, blockState));
}
});
}
private static void spawnPlayer(GeyserSession session, GameProfile profile, Vector3i blockPosition,
Vector3f entityPosition, Vector3f entityRotation, int blockState) {
long geyserId = session.getEntityCache().getNextEntityId().incrementAndGet();
SkullPlayerEntity existingSkull = session.getSkullCache().get(blockPosition); SkullPlayerEntity existingSkull = session.getSkullCache().get(blockPosition);
if (existingSkull != null) { if (existingSkull != null) {
// Ensure that two skulls can't spawn on the same point // Ensure that two skulls can't spawn on the same point
existingSkull.despawnEntity(session, blockPosition); existingSkull.despawnEntity(session, blockPosition);
} }
SkullPlayerEntity player = new SkullPlayerEntity(gameProfile, geyserId, entityPosition, entityRotation); SkullPlayerEntity player = new SkullPlayerEntity(profile, geyserId, entityPosition, entityRotation, blockState);
player.setBlockState(blockState);
// Cache entity // Cache entity
session.getSkullCache().put(blockPosition, player); session.getSkullCache().put(blockPosition, player);
@ -153,6 +163,5 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements
player.updateBedrockMetadata(session); player.updateBedrockMetadata(session);
}, 250, TimeUnit.MILLISECONDS))); }, 250, TimeUnit.MILLISECONDS)));
} }
});
} }
} }