Skip to content

Commit

Permalink
2.0.1
Browse files Browse the repository at this point in the history
- Adds Minecraft Version Check for animating heads
- ReIntroduce the Geyser Event code that I had taken out before in hindsight. Accurately animate when joining server!
- ToDo: Dimension Switch and Respawns are still inaccurate.
  • Loading branch information
MrBsng committed May 3, 2024
1 parent 5a2772a commit 39553af
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 81 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.tbyt</groupId>
<artifactId>bedrockparity</artifactId>
<version>2.0.0</version>
<version>2.0.1</version>

<properties>
<java.version>1.8</java.version>
Expand Down
68 changes: 24 additions & 44 deletions src/main/java/com/tbyt/AnimateHeadsForGeyser.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
package com.tbyt;

//import java.io.ByteArrayOutputStream;
//import java.io.IOException;
//import java.io.ObjectOutputStream;
import java.util.ArrayList;
//import java.util.Collection;
//import java.util.Iterator;
//import java.util.LinkedHashMap;

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
Expand All @@ -19,18 +12,17 @@
import org.bukkit.event.player.PlayerChangedWorldEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.plugin.Plugin;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
import org.geysermc.api.Geyser;
import org.geysermc.api.connection.Connection;
import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.floodgate.api.player.FloodgatePlayer;

//import com.google.gson.Gson;
//import com.google.gson.JsonElement;
import org.geysermc.geyser.api.connection.GeyserConnection;

/*
* Made by TBYT
Expand All @@ -43,8 +35,10 @@ public class AnimateHeadsForGeyser implements Listener {
private ArrayList<Location> headsToAnimate = new ArrayList<Location>();
private ArrayList<Location> animatedHeads = new ArrayList<Location>();
private int radius;
private GeyserConnection playerConn;

public AnimateHeadsForGeyser(Plugin plugin, int animateHeadBlockDistance) {
public AnimateHeadsForGeyser(Plugin plugin, @NonNull GeyserConnection playerConn, int animateHeadBlockDistance) {
this.playerConn = playerConn;
this.plugin = plugin;
radius = animateHeadBlockDistance;
}
Expand All @@ -54,28 +48,28 @@ public void geyserPlayerDimensionSwitch(PlayerChangedWorldEvent event)
{
if (!FloodgateApi.getInstance().isFloodgatePlayer(event.getPlayer().getUniqueId()))
return;
headsToAnimate = new ArrayList<Location>();
animatedHeads = new ArrayList<Location>();
headsToAnimate.clear();
animatedHeads.clear();
}

@EventHandler
public void geyserPlayerDeath(PlayerRespawnEvent event)
{
if (!FloodgateApi.getInstance().isFloodgatePlayer(event.getPlayer().getUniqueId()))
return;
headsToAnimate = new ArrayList<Location>();
animatedHeads = new ArrayList<Location>();
headsToAnimate.clear();
animatedHeads.clear();
}

public void animateForBedrockPlayer(FloodgatePlayer player){
public void animateForBedrockPlayer() {
Player BukkitPlayer = null;
try {
BukkitPlayer = Bukkit.getPlayer(player.getCorrectUniqueId());
BukkitPlayer = Bukkit.getPlayer(playerConn.javaUuid());
}
catch(IllegalArgumentException e)
catch(NullPointerException e)
{
return;
//may be null in the very first milliseconds of connecting to the server.
//Not sure if this is still the case anymore, todo: test for null.
}
if(BukkitPlayer==null)
return;
Expand All @@ -95,16 +89,16 @@ public void animateForBedrockPlayer(FloodgatePlayer player){
// send deanimate packet
switch (currentMaterial) {
case DRAGON_HEAD:
sendAnimatePacket(player, activeHead.getBlock(), 5, 0);
sendAnimatePacket(playerConn, activeHead.getBlock(), 5, 0);
break;
case DRAGON_WALL_HEAD:
sendAnimatePacket(player, activeHead.getBlock(), 5, 0);
sendAnimatePacket(playerConn, activeHead.getBlock(), 5, 0);
break;
case PIGLIN_HEAD:
sendAnimatePacket(player, activeHead.getBlock(), 6, 0);
sendAnimatePacket(playerConn, activeHead.getBlock(), 6, 0);
break;
case PIGLIN_WALL_HEAD:
sendAnimatePacket(player, activeHead.getBlock(), 6, 0);
sendAnimatePacket(playerConn, activeHead.getBlock(), 6, 0);
break;
default:
break;
Expand Down Expand Up @@ -140,16 +134,16 @@ public void animateForBedrockPlayer(FloodgatePlayer player){
Material materialOfBlock = headBlock.getType();
switch (materialOfBlock) {
case DRAGON_HEAD:
sendAnimatePacket(player, headBlock, 5, 1);
sendAnimatePacket(playerConn, headBlock, 5, 1);
break;
case DRAGON_WALL_HEAD:
sendAnimatePacket(player, headBlock, 5, 1);
sendAnimatePacket(playerConn, headBlock, 5, 1);
break;
case PIGLIN_HEAD:
sendAnimatePacket(player, headBlock, 6, 1);
sendAnimatePacket(playerConn, headBlock, 6, 1);
break;
case PIGLIN_WALL_HEAD:
sendAnimatePacket(player, headBlock, 6, 1);
sendAnimatePacket(playerConn, headBlock, 6, 1);
break;
default:
break;
Expand All @@ -173,7 +167,7 @@ public boolean isHead(Material material) {
}

// animate or deanimate bedrock animations for vanilla skulls.
public void sendAnimatePacket(FloodgatePlayer player, Block head, int headType, int animationStatus) {
public void sendAnimatePacket(Connection playerConn, Block head, int headType, int animationStatus) {
NbtMapBuilder builder = NbtMap.builder();
builder.putByte("DoingAnimation", (byte) animationStatus);
builder.putInt("MouthTickCount", animationStatus);
Expand Down Expand Up @@ -246,20 +240,6 @@ public void sendAnimatePacket(FloodgatePlayer player, Block head, int headType,
headAnimationPacket.setBlockPosition(Vector3i.from(head.getX(), head.getY(), head.getZ()));
headAnimationPacket.setData(builder.build());
GeyserImpl geyserInstance = (GeyserImpl) Geyser.api();
geyserInstance.connectionByUuid(player.getCorrectUniqueId()).sendUpstreamPacket((BedrockPacket) headAnimationPacket);

// When I was testing sending packet through floodgate api but obviously this is not how you do it. You have to use geyser api.

// ByteArrayOutputStream bos = new ByteArrayOutputStream();
// ObjectOutputStream oos = new ObjectOutputStream(bos);
//oos.writeObject(builder.build().toString());

// Gson gson = new Gson();
// String PacketdataString = "{'DoingAnimation':"+animationStatus+",'MouthTickCount':"+animationStatus+",'Rotation':"+rotationDegree+",'SkullType':"+headType+",'id':'Skull','isMovable':"+1+",'x':"+head.getX()+",'y':"+head.getY()+",'z':"+head.getZ()+"}";
// JsonElement PacketdataJson = gson.fromJson(PacketdataString,JsonElement.class);
//String HeadPacketString = "BlockEntityDataPacket(blockPosition=("+head.getX()+","+head.getY()+","+head.getZ()+"),data="+PacketdataJson+")";
//plugin.getLogger().info(headAnimationPacket.toString());
//FloodgateApi.getInstance().unsafe().sendPacket(player, 0x38, headAnimationPacket.toString().getBytes());

geyserInstance.connectionByUuid(playerConn.javaUuid()).sendUpstreamPacket((BedrockPacket) headAnimationPacket);
}
}
32 changes: 32 additions & 0 deletions src/main/java/com/tbyt/BedrockEvents.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.tbyt;

import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitScheduler;
import org.geysermc.geyser.api.GeyserApi;
import org.geysermc.geyser.api.event.EventRegistrar;
import org.geysermc.geyser.api.event.bedrock.SessionJoinEvent;

public class BedrockEvents implements EventRegistrar {

public int animateHeadBlockDistance = 0;
private final Plugin plugin;

public BedrockEvents(int animateHeadBlockDistance, Plugin plugin) {
this.animateHeadBlockDistance = animateHeadBlockDistance;
this.plugin = plugin;
GeyserApi.api().eventBus().subscribe(this, SessionJoinEvent.class, this::onGeyserPlayerJoin);
}

public void onGeyserPlayerJoin(SessionJoinEvent event) {
AnimateHeadsForGeyser animateHeadsForGeyser = new AnimateHeadsForGeyser(plugin, event.connection(), animateHeadBlockDistance);
Bukkit.getPluginManager().registerEvents(animateHeadsForGeyser, plugin);
BukkitScheduler scheduler = plugin.getServer().getScheduler();
scheduler.scheduleSyncRepeatingTask(plugin, new Runnable() {
@Override
public void run() {
animateHeadsForGeyser.animateForBedrockPlayer();
}
}, 0L, 4L);
}
}
59 changes: 23 additions & 36 deletions src/main/java/com/tbyt/BedrockParity.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,58 +3,45 @@
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitScheduler;
import org.geysermc.floodgate.api.FloodgateApi;
import org.geysermc.floodgate.api.player.FloodgatePlayer;

import java.util.UUID;
import java.util.function.Predicate;

public class BedrockParity extends JavaPlugin {
private Predicate<UUID> playerChecker;
@Override
public void onEnable() {
FileConfiguration config = getConfig();
config.addDefault("sweeping-edge-book-anvil-fix", true);
config.addDefault("animate-heads-for-bedrock", true);
config.options().copyDefaults(true);
saveDefaultConfig();

@Override
public void onEnable() {
FileConfiguration config = getConfig();
config.addDefault("sweeping-edge-book-anvil-fix", true);
config.addDefault("animate-heads-for-bedrock", true);
config.options().copyDefaults(true);
saveDefaultConfig();
try {
Class.forName("org.geysermc.floodgate.api.FloodgateApi");
playerChecker = uuid -> FloodgateApi.getInstance().isFloodgatePlayer(uuid);
} catch (ClassNotFoundException e) {
getLogger().warning("Could not find Floodgate; Bedrock Parity is disabled.");
}

if (playerChecker != null) {
if(this.getConfig().getBoolean("sweeping-edge-book-anvil-fix"))
{
if (this.getConfig().getBoolean("sweeping-edge-book-anvil-fix")) {
Bukkit.getPluginManager().registerEvents(new SweepingEdgeFix(this), this);
getLogger().info("Sweeping Edge Book Fix in Anvil is enabled.");
}
else
} else
getLogger().info("Sweeping Edge Book Fix in Anvil is manually disabled.");
if(this.getConfig().getInt("animate-head-blocks-distance")!=0&&Bukkit.getPluginManager().getPlugin("Geyser-Spigot")!=null)
{
getLogger().info("Animating Dragon and Piglin Heads is enabled.");
int animateHeadBlockDistance = this.getConfig().getInt("animate-head-blocks-distance");
AnimateHeadsForGeyser animateHeadsForGeyser = new AnimateHeadsForGeyser(this, animateHeadBlockDistance);
Bukkit.getPluginManager().registerEvents(animateHeadsForGeyser, this);
BukkitScheduler scheduler = getServer().getScheduler();
scheduler.scheduleSyncRepeatingTask(this, new Runnable() {
@Override
public void run() {
//Player player : Bukkit.getOnlinePlayers()
for (FloodgatePlayer player : FloodgateApi.getInstance().getPlayers()) {
// Update every 4 ticks
animateHeadsForGeyser.animateForBedrockPlayer(player);
}
}
}, 0L, 4L);
}
else
getLogger().info("Animating Heads for Bedrock Players is manually disabled, or Geyser-Spigot could not be found.");
// getLogger().info("Animating Heads for Bedrock Players is disabled in BedrockParity because Geyser natively supports it Minecraft Java 1.20.2 and up.");
if (Bukkit.getUnsafe().getDataVersion() < 3466) {
if (Bukkit.getPluginManager().getPlugin("Geyser-Spigot") != null) {
int animateHeadBlockDistance = this.getConfig().getInt("animate-head-blocks-distance");
if (animateHeadBlockDistance != 0) {
new BedrockEvents(animateHeadBlockDistance, this);
getLogger().info("Animating Dragon and Piglin Heads is enabled.");

} else
getLogger().info("Animating Heads for Bedrock Players is manually disabled in config.yml");
} else
getLogger().info("Geyser-Spigot could not be found. Animating Heads for Bedrock Players is disabled.");
} else
getLogger().info("Animating Heads for Bedrock Players is disabled because Geyser natively supports it Minecraft Java v1.20.2 and up.");
}
}
}

0 comments on commit 39553af

Please sign in to comment.