Skip to content

Commit ad05a0d

Browse files
author
xyzjesper
committed
Added an alpha version of the NPC Lib. Fixed some internal bugs. Changed some npc stuff for more customization.
1 parent 8eb7965 commit ad05a0d

File tree

11 files changed

+383
-196
lines changed

11 files changed

+383
-196
lines changed

crystalshard-test/src/main/kotlin/net/crystopia/crystalshardtest/Main.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,32 @@
11
package net.crystopia.crystalshardtest
22

33
import net.crystopia.crystalshard.CrystalShard
4+
import net.crystopia.crystalshardtest.events.PlayerJoin
45
import org.bukkit.plugin.java.JavaPlugin
56

67
class Main: JavaPlugin() {
78

9+
/*
10+
setEntityDataPacket(
11+
player,
12+
12321,
13+
mutableListOf(
14+
SynchedEntityData.DataValue.create(net.minecraft.world.entity.player.Player.DATA_PLAYER_MODE_CUSTOMISATION,
15+
(0x01 or 0x02 or 0x04 or 0x08 or 0x10 or 0x20 or 0x40).toByte())
16+
17+
)
18+
)
19+
*/
20+
821
override fun onLoad() {
922

1023
CrystalShard.init(this)
1124

1225
}
1326

1427
override fun onEnable() {
28+
29+
server.pluginManager.registerEvents(PlayerJoin, this)
1530

1631
}
1732

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
package net.crystopia.crystalshardtest.events
2+
3+
import com.google.common.collect.ImmutableMultimap
4+
import com.mojang.authlib.GameProfile
5+
import com.mojang.authlib.properties.Property
6+
import com.mojang.authlib.properties.PropertyMap
7+
import com.mojang.datafixers.util.Pair
8+
import net.crystopia.crystalshard.CrystalShard
9+
import net.crystopia.crystalshard.builder.EntityBuilder
10+
import net.crystopia.crystalshard.extra.npc.NPCUtil
11+
import net.crystopia.crystalshard.utils.Log
12+
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket
13+
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket
14+
import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket
15+
import net.minecraft.server.level.ServerPlayer
16+
import net.minecraft.world.entity.EntityType
17+
import net.minecraft.world.entity.EquipmentSlot
18+
import net.minecraft.world.item.ItemStack
19+
import net.minecraft.world.phys.Vec3
20+
import org.bukkit.Material
21+
import org.bukkit.NamespacedKey
22+
import org.bukkit.craftbukkit.entity.CraftPlayer
23+
import org.bukkit.craftbukkit.inventory.CraftItemStack
24+
import org.bukkit.entity.Player
25+
import org.bukkit.event.EventHandler
26+
import org.bukkit.event.Listener
27+
import org.bukkit.event.player.PlayerJoinEvent
28+
import java.util.*
29+
30+
31+
object PlayerJoin : Listener {
32+
33+
@EventHandler
34+
fun addNPCsOnJoin(event: PlayerJoinEvent) {
35+
EntityBuilder.createNpc(
36+
CrystalShard.plugin.server.worlds.first(),
37+
NamespacedKey("test", "test"),
38+
"I'm a NPC"
39+
) {
40+
playerEntity.setRot(0.0F, 0.0F)
41+
playerEntity.setYHeadRot(0.0F)
42+
playerEntity.xRot = 0.0F
43+
playerEntity.yRot = 0.0F
44+
playerEntity.setPos(0.0, 0.0, 0.0)
45+
46+
val actions = EnumSet.noneOf(ClientboundPlayerInfoUpdatePacket.Action::class.java)
47+
actions.add(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER)
48+
actions.add(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME)
49+
actions.add(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED)
50+
51+
52+
val value: String = "ewogICJ0aW1lc3RhbXAiIDogMTc1NDA3NDg0NDk0MiwKICAicHJvZmlsZUlkIiA6ICI5OGQxYTQyNmRlMmU0NjBkYjdjNWExMmY5MGNhODg0OSIsCiAgInByb2ZpbGVOYW1lIiA6ICJLdWJpbm9TSyIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9jMDc5NDZkNjJkMzNkYTg3YmVjOWRiNDNmNDRjMjRmMzM2MTFmZTMxZTE2OTllMDFkZTA1ZTI5YWZlYjhmMzcyIiwKICAgICAgIm1ldGFkYXRhIiA6IHsKICAgICAgICAibW9kZWwiIDogInNsaW0iCiAgICAgIH0KICAgIH0KICB9Cn0="
53+
val signature: String = "xblXSSWXrnkIy2R7OHWuwT+1Ky03cIkhfesnIrArAExN7iILwrDVHnVElF+l6N1wl+PjCx24yROXp+J5f2zTFC/LduuXB88lLv4Xw6TFMOU5FFp0kIgAXeYijOMQ8FhL4K50VUM30dIM1QUnfqEOHRf3s7DhUNr58PCxi01xUbEXJFNlGx5Nwjp8Q1yt87lwDwihasunKiCTEukgkUSptEa4xeZDRL/tZdZJUEML09757ErhSjzA1MdCX+YZOMrbov4PnA45z4x5Ms1lRu6BJ+tQqz0UMK2q4jKDdUYk6gm8nsXsBJUx4rTx2r4MgdBx0gqJ8EeV98ST9N2uyKV3yIfnTRrxGhi1DVKzT+atZZADf4GwMe1eU/5gkgjxL3I38Y9IfWG7X4w06p1bgV2muMj9zHl0rnXxfMLylgb6hUVqnJImvbrMU6fsBNGqbdD1v9hXhkMynldbfBnsVKDzf4gm5DHPs6IkYxWymw2tdjI2IY/nQ+C7ejiukMq46ABmazr0OK/CDnB5VnmCUNZo49cC4QJ9uxKQlrnpIm+ss0nKoOxmVESgo/vqj234jvUgJvSdOs9WSo6CPdW46dADt/rQUmWDASWAiN7sRm6iFT8X5QKFlPAiDMLvf+B1OdqUeGwXK1tUbjvYYs9/9b5JDOQrIByQ0z9fd7TdQKrB0sw="
54+
55+
val propertyMap = PropertyMap(
56+
ImmutableMultimap.of<String?, Property?>(
57+
"textures",
58+
Property("textures", value, signature)
59+
)
60+
)
61+
62+
63+
val textures = this.playerEntity.gameProfile.properties().get("textures")
64+
if (textures.isEmpty()) {
65+
playerEntity.gameProfile = GameProfile(playerEntity.uuid, "", propertyMap)
66+
} else {
67+
val prop = textures.iterator().next()
68+
if (!prop.value().equals(value)) {
69+
playerEntity.gameProfile = GameProfile(playerEntity.uuid, "", propertyMap)
70+
}
71+
}
72+
73+
CrystalShard.plugin.server.onlinePlayers.forEach { player ->
74+
NPCUtil.Packets.playerInfoUpdatePacket(
75+
player,
76+
playerEntity,
77+
playerEntity.gameProfile,
78+
actions = actions
79+
)
80+
}
81+
82+
83+
playerEntity.setPos(0.0, 0.0, 0.0)
84+
85+
val addEntityPacket = ClientboundAddEntityPacket(
86+
playerEntity.id, playerEntity.uuid, 0.0, 0.0, 0.0, 0.0F, 0.0F, EntityType.PLAYER, 0, Vec3.ZERO, 0.0
87+
)
88+
CrystalShard.plugin.server.onlinePlayers.forEach { player ->
89+
val serverPlayer = (player as CraftPlayer).handle
90+
serverPlayer.connection.send(addEntityPacket)
91+
}
92+
93+
val equipmentList: MutableList<Pair<EquipmentSlot, ItemStack?>> = mutableListOf()
94+
equipmentList.add(
95+
Pair(
96+
EquipmentSlot.MAINHAND, CraftItemStack.asNMSCopy(
97+
org.bukkit.inventory.ItemStack(Material.STONE_SHOVEL)
98+
)
99+
)
100+
)
101+
102+
val setEquipmentPacket = ClientboundSetEquipmentPacket(
103+
playerEntity.id, equipmentList
104+
)
105+
106+
CrystalShard.plugin.server.onlinePlayers.forEach { player ->
107+
val serverPlayer = (player as CraftPlayer).handle
108+
serverPlayer.connection.send(setEquipmentPacket)
109+
}
110+
111+
onInteract = { interactor ->
112+
113+
Log.info("${interactor.name} Clicked on NPC with UUID ${this.playerEntity.uuid}")
114+
115+
}
116+
NPCUtil.injectToPLayer(event.player, this)
117+
}
118+
}
119+
120+
}

src/main/kotlin/net/crystopia/crystalshard/builder/EntityBuilder.kt

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package net.crystopia.crystalshard.builder
22

33
import com.mojang.authlib.GameProfile
4+
import net.crystopia.crystalshard.extra.npc.INpc
5+
import net.crystopia.crystalshard.extra.npc.Npc
46
import net.minecraft.server.MinecraftServer
57
import net.minecraft.server.level.ClientInformation
68
import net.minecraft.server.level.ServerPlayer
79
import org.bukkit.Bukkit
810
import org.bukkit.Location
11+
import org.bukkit.NamespacedKey
912
import org.bukkit.World
1013
import org.bukkit.craftbukkit.CraftServer
1114
import org.bukkit.craftbukkit.CraftWorld
@@ -24,17 +27,31 @@ object EntityBuilder {
2427
return entity as T
2528
}
2629

27-
fun spawnNpc(
30+
fun createNpc(
2831
world: World,
32+
key: NamespacedKey,
2933
name: String?,
30-
callback: ServerPlayer.() -> Unit = {}
31-
): ServerPlayer {
32-
var npc: ServerPlayer? = null
34+
callback: INpc.() -> Unit = {}
35+
): INpc {
3336
val minecraftServer: MinecraftServer = (Bukkit.getServer() as CraftServer).server
34-
val gameProfile = GameProfile(UUID.randomUUID(), name ?: UUID.randomUUID().toString().split("-")[0])
35-
npc =
36-
ServerPlayer(minecraftServer, (world as CraftWorld).handle, GameProfile(UUID.randomUUID(), ""), ClientInformation.createDefault())
37-
npc.gameProfile = gameProfile
37+
val serverPlayer = ServerPlayer(
38+
minecraftServer,
39+
(world as CraftWorld).handle,
40+
GameProfile(UUID.randomUUID(), ""),
41+
ClientInformation.createDefault()
42+
)
43+
44+
val npc: INpc = Npc(
45+
gameProfile = GameProfile(UUID.randomUUID(), name ?: UUID.randomUUID().toString().split("-")[0]),
46+
clientInformation = serverPlayer.clientInformation(),
47+
level = serverPlayer.level(),
48+
server = minecraftServer,
49+
id = key,
50+
name = name,
51+
location = Location(Bukkit.getWorld("world"), 0.0, 0.0, 0.0, 0.0F, 0.0F),
52+
playerEntity = serverPlayer,
53+
entityId = serverPlayer.id
54+
)
3855

3956
callback(npc)
4057
return npc

src/main/kotlin/net/crystopia/crystalshard/extra/npc/INpc.kt

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,46 +3,45 @@ package net.crystopia.crystalshard.extra.npc
33
import com.mojang.authlib.properties.Property
44
import net.crystopia.crystalshard.extra.npc.config.NpcVisibility
55
import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket
6+
import net.minecraft.server.level.ServerPlayer
67
import net.minecraft.world.entity.EquipmentSlot
78
import org.bukkit.Location
89
import org.bukkit.NamespacedKey
910
import org.bukkit.entity.EntityType
1011
import org.bukkit.entity.Player
1112
import org.bukkit.inventory.ItemStack
1213
import java.util.*
13-
import java.util.function.Consumer
1414

1515

1616
interface INpc {
1717

18+
var playerEntity: ServerPlayer
1819
var isTeamCreated: MutableMap<UUID?, Boolean?>
1920
var isVisibleForPlayer: MutableMap<UUID?, Boolean?>
2021
var isLookingAtPlayer: MutableMap<UUID?, Boolean?>
2122
var lastPlayerInteraction: MutableMap<UUID?, Long?>
22-
2323
var id: NamespacedKey
24+
var entityId: Int
2425
val name: String?
25-
val permission: String
26+
val permission: String?
2627
val skin: Property?
27-
val mirrorSkin: Boolean
28+
val mirrorSkin: Boolean?
2829
val location: Location?
29-
val actions: EnumSet<ClientboundPlayerInfoUpdatePacket.Action>
30-
val glowing: Boolean
30+
val actions: EnumSet<ClientboundPlayerInfoUpdatePacket.Action?>?
31+
val glowing: Boolean?
3132
val type: EntityType?
3233
val equipment: MutableMap<EquipmentSlot?, ItemStack?>?
33-
val onInteract: Consumer<Player?>?
34-
val turnToPlayer: Boolean
35-
val turnToPlayerDistance: Int
36-
val visibilityDistance: Int
34+
var onInteract: (player: Player) -> Unit?
35+
val turnToPlayer: Boolean?
36+
val turnToPlayerDistance: Int?
37+
val visibilityDistance: Int?
3738
val visibility: NpcVisibility?
38-
39+
val injectOnJoin: Boolean?
3940
fun isShownFor(player: Player): Boolean {
4041
return isVisibleForPlayer.getOrDefault(player.uniqueId, false)!!
4142
}
42-
4343
fun spawn(player: Player)
4444
fun spawnAll()
4545
fun remove(player: Player)
4646
fun removeAll()
47-
48-
}
47+
}
Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,12 @@
11
package net.crystopia.crystalshard.extra.npc
22

33
import org.bukkit.NamespacedKey
4+
import org.ktorm.entity.Entity
45

56
interface INpcManager {
6-
7-
var registeredNpcs: MutableMap<NamespacedKey, net.minecraft.world.entity.npc.Npc>
8-
9-
fun register(
10-
key: NamespacedKey, npcObj: net.minecraft.world.entity.npc.Npc
11-
)
12-
13-
fun unRegister(
14-
key: NamespacedKey
15-
)
16-
17-
fun getNpc(key: NamespacedKey): Npc?
18-
7+
var registeredNpcs: MutableMap<NamespacedKey, INpc>
8+
fun register(key: NamespacedKey, npcObj: INpc)
9+
fun unRegister(key: NamespacedKey): Boolean
10+
fun getNpc(key: NamespacedKey): INpc?
11+
fun getNpcByEntityId(entityId: Int): INpc?
1912
}

0 commit comments

Comments
 (0)