Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-09-08 12:32:53 +02:00
Ensure skull operations are done on the player thread
Dieser Commit ist enthalten in:
Ursprung
ab540b1951
Commit
a1d167d5f1
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -123,36 +123,45 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkullPlayerEntity existingSkull = session.getSkullCache().get(blockPosition);
|
if (session.getEventLoop().inEventLoop()) {
|
||||||
if (existingSkull != null) {
|
spawnPlayer(session, gameProfile, blockPosition, entityPosition, entityRotation, blockState);
|
||||||
// Ensure that two skulls can't spawn on the same point
|
} else {
|
||||||
existingSkull.despawnEntity(session, blockPosition);
|
session.executeInEventLoop(() -> spawnPlayer(session, gameProfile, blockPosition, entityPosition, entityRotation, blockState));
|
||||||
}
|
|
||||||
|
|
||||||
SkullPlayerEntity player = new SkullPlayerEntity(gameProfile, geyserId, entityPosition, entityRotation);
|
|
||||||
player.setBlockState(blockState);
|
|
||||||
|
|
||||||
// Cache entity
|
|
||||||
session.getSkullCache().put(blockPosition, player);
|
|
||||||
|
|
||||||
// Only send to session if we are initialized, otherwise it will happen then.
|
|
||||||
if (session.getUpstream().isInitialized()) {
|
|
||||||
player.spawnEntity(session);
|
|
||||||
|
|
||||||
SkullSkinManager.requestAndHandleSkin(player, session, (skin -> session.scheduleInEventLoop(() -> {
|
|
||||||
// Delay to minimize split-second "player" pop-in
|
|
||||||
player.getMetadata().getFlags().setFlag(EntityFlag.INVISIBLE, false);
|
|
||||||
player.updateBedrockMetadata(session);
|
|
||||||
}, 250, TimeUnit.MILLISECONDS)));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (existingSkull != null) {
|
||||||
|
// Ensure that two skulls can't spawn on the same point
|
||||||
|
existingSkull.despawnEntity(session, blockPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
SkullPlayerEntity player = new SkullPlayerEntity(profile, geyserId, entityPosition, entityRotation, blockState);
|
||||||
|
|
||||||
|
// Cache entity
|
||||||
|
session.getSkullCache().put(blockPosition, player);
|
||||||
|
|
||||||
|
// Only send to session if we are initialized, otherwise it will happen then.
|
||||||
|
if (session.getUpstream().isInitialized()) {
|
||||||
|
player.spawnEntity(session);
|
||||||
|
|
||||||
|
SkullSkinManager.requestAndHandleSkin(player, session, (skin -> session.scheduleInEventLoop(() -> {
|
||||||
|
// Delay to minimize split-second "player" pop-in
|
||||||
|
player.getMetadata().getFlags().setFlag(EntityFlag.INVISIBLE, false);
|
||||||
|
player.updateBedrockMetadata(session);
|
||||||
|
}, 250, TimeUnit.MILLISECONDS)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren