Skip to content

Commit f81513e

Browse files
committed
fix: username length bypass
1 parent cbcb693 commit f81513e

1 file changed

Lines changed: 162 additions & 156 deletions

File tree

  • type.generic/src/main/java/net/swofty/type/generic/entity/npc

type.generic/src/main/java/net/swofty/type/generic/entity/npc/HypixelNPC.java

Lines changed: 162 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -13,160 +13,166 @@
1313
import java.util.concurrent.ConcurrentHashMap;
1414

1515
public abstract class HypixelNPC {
16-
private static final int SPAWN_DISTANCE = 48;
17-
private static final int LOOK_DISTANCE = 16;
18-
19-
@Getter
20-
private static List<HypixelNPC> npcs = new ArrayList<>();
21-
@Getter
22-
private static Map<UUID, PlayerNPCCache> perPlayerNPCs = new HashMap<>();
23-
24-
@Getter
25-
private final NPCParameters parameters;
26-
@Getter
27-
private final String name;
28-
29-
public abstract void onClick(PlayerClickNPCEvent e);
30-
31-
public HypixelNPC(NPCParameters defaultParams) {
32-
this.parameters = defaultParams;
33-
String className = getClass().getSimpleName().replace("NPC", "");
34-
this.name = className.replaceAll("(?<=.)(?=\\p{Lu})", " ");
35-
}
36-
37-
public void register() {
38-
npcs.add(this);
39-
}
40-
41-
public void sendNPCMessage(HypixelPlayer player, String message) {
42-
player.sendMessage("§e[NPC] " + getName() + "§f: " + message);
43-
}
44-
45-
public static HypixelNPC getFromImpl(HypixelPlayer player, NPCEntityImpl impl) {
46-
Map<HypixelNPC, NPCEntityImpl> npcs = perPlayerNPCs.get(player.getUuid()).getEntityImpls();
47-
if (npcs == null) return null;
48-
49-
for (Map.Entry<HypixelNPC, NPCEntityImpl> entry : npcs.entrySet()) {
50-
if (entry.getValue().equals(impl)) {
51-
return entry.getKey();
52-
}
53-
}
54-
55-
return null;
56-
}
57-
58-
public static void updateForPlayer(HypixelPlayer player) {
59-
perPlayerNPCs.putIfAbsent(player.getUuid(), new PlayerNPCCache());
60-
61-
Thread.startVirtualThread(() -> {
62-
HypixelNPC.getNpcs().forEach((npc) -> {
63-
boolean playerHasNPC = perPlayerNPCs.containsKey(player.getUuid()) && perPlayerNPCs.get(player.getUuid()).getEntityImpls().containsKey(npc);
64-
65-
if (!playerHasNPC) {
66-
NPCEntityImpl entity = new NPCEntityImpl(
67-
npc.getParameters().holograms(player)[npc.getParameters().holograms(player).length - 1],
68-
npc.getParameters().texture(player),
69-
npc.getParameters().signature(player),
70-
npc.getParameters().holograms(player));
71-
Pos position = npc.getParameters().position(player);
72-
73-
PlayerHolograms.ExternalPlayerHologram holo = PlayerHolograms.ExternalPlayerHologram.builder()
74-
.pos(position.add(0, 1.1, 0))
75-
.text(Arrays.copyOfRange(npc.getParameters().holograms(player), 0, npc.getParameters().holograms(player).length - 1))
76-
.player(player)
77-
.build();
78-
79-
entity.setAutoViewable(false);
80-
81-
PlayerHolograms.addExternalPlayerHologram(holo);
82-
entity.setInstance(HypixelConst.getInstanceContainer(), position);
83-
entity.addViewer(player);
84-
85-
PlayerNPCCache cache = perPlayerNPCs.get(player.getUuid());
86-
cache.add(npc, holo, entity);
87-
perPlayerNPCs.put(player.getUuid(), cache);
88-
return;
89-
}
90-
91-
PlayerNPCCache cache = perPlayerNPCs.get(player.getUuid());
92-
NPCEntityImpl entity = cache.get(npc).getValue();
93-
PlayerHolograms.ExternalPlayerHologram holo = cache.get(npc).getKey();
94-
95-
Pos npcPosition = npc.getParameters().position(player);
96-
String npcTexture = npc.getParameters().texture(player);
97-
String npcSignature = npc.getParameters().signature(player);
98-
String[] npcHolograms = npc.getParameters().holograms(player);
99-
100-
// If any of the parameters have changed, update the NPC
101-
if (!Arrays.equals(entity.getHolograms(), npcHolograms) ||
102-
!entity.getSkinTexture().equals(npcTexture) ||
103-
!entity.getSkinSignature().equals(npcSignature) ||
104-
!entity.getPosition().equals(npcPosition)) {
105-
entity.remove();
106-
PlayerHolograms.removeExternalPlayerHologram(holo);
107-
cache.remove(npc);
108-
return;
109-
}
110-
111-
Pos playerPosition = player.getPosition();
112-
List<HypixelPlayer> inRange = entity.getInRangeOf();
113-
double entityDistance = playerPosition.distance(npcPosition);
114-
boolean isLookingNPC = npc.getParameters().looking();
115-
116-
if (entityDistance <= SPAWN_DISTANCE) {
117-
if (!inRange.contains(player)) {
118-
inRange.add(player);
119-
entity.updateNewViewer(player);
120-
}
121-
122-
if (isLookingNPC && entityDistance <= LOOK_DISTANCE) {
123-
double diffX = playerPosition.x() - npcPosition.x();
124-
double diffZ = playerPosition.z() - npcPosition.z();
125-
double theta = Math.atan2(diffZ, diffX);
126-
double yaw = MathUtility.normalizeAngle(Math.toDegrees(theta) + 90, 360.0);
127-
128-
player.sendPackets(
129-
new EntityRotationPacket(entity.getEntityId(), (float) yaw, npcPosition.pitch(), true),
130-
new EntityHeadLookPacket(entity.getEntityId(), (float) yaw)
131-
);
132-
}
133-
} else {
134-
if (inRange.contains(player)) {
135-
inRange.remove(player);
136-
entity.updateOldViewer(player);
137-
138-
player.sendPackets(
139-
new EntityRotationPacket(entity.getEntityId(), npcPosition.yaw(), npcPosition.pitch(), true),
140-
new EntityHeadLookPacket(entity.getEntityId(), npcPosition.yaw())
141-
);
142-
}
143-
}
144-
});
145-
});
146-
}
147-
148-
public record PlayerClickNPCEvent(HypixelPlayer player, int entityId, HypixelNPC npc) {
149-
}
150-
151-
public static class PlayerNPCCache {
152-
private final Map<HypixelNPC, Map.Entry<PlayerHolograms.ExternalPlayerHologram, NPCEntityImpl>> npcs = new ConcurrentHashMap<>();
153-
154-
public void add(HypixelNPC npc, PlayerHolograms.ExternalPlayerHologram hologram, NPCEntityImpl entity) {
155-
npcs.put(npc, Map.entry(hologram, entity));
156-
}
157-
158-
public void remove(HypixelNPC npc) {
159-
npcs.remove(npc);
160-
}
161-
162-
public Map<HypixelNPC, NPCEntityImpl> getEntityImpls() {
163-
Map<HypixelNPC, NPCEntityImpl> entityImpls = new HashMap<>();
164-
npcs.forEach((npc, entry) -> entityImpls.put(npc, entry.getValue()));
165-
return entityImpls;
166-
}
167-
168-
public Map.Entry<PlayerHolograms.ExternalPlayerHologram, NPCEntityImpl> get(HypixelNPC npc) {
169-
return npcs.get(npc);
170-
}
171-
}
16+
private static final int SPAWN_DISTANCE = 48;
17+
private static final int LOOK_DISTANCE = 16;
18+
19+
@Getter
20+
private static List<HypixelNPC> npcs = new ArrayList<>();
21+
@Getter
22+
private static Map<UUID, PlayerNPCCache> perPlayerNPCs = new HashMap<>();
23+
24+
@Getter
25+
private final NPCParameters parameters;
26+
@Getter
27+
private final String name;
28+
29+
public HypixelNPC(NPCParameters defaultParams) {
30+
this.parameters = defaultParams;
31+
String className = getClass().getSimpleName().replace("NPC", "");
32+
this.name = className.replaceAll("(?<=.)(?=\\p{Lu})", " ");
33+
}
34+
35+
public static HypixelNPC getFromImpl(HypixelPlayer player, NPCEntityImpl impl) {
36+
Map<HypixelNPC, NPCEntityImpl> npcs = perPlayerNPCs.get(player.getUuid()).getEntityImpls();
37+
if (npcs == null) return null;
38+
39+
for (Map.Entry<HypixelNPC, NPCEntityImpl> entry : npcs.entrySet()) {
40+
if (entry.getValue().equals(impl)) {
41+
return entry.getKey();
42+
}
43+
}
44+
45+
return null;
46+
}
47+
48+
public static void updateForPlayer(HypixelPlayer player) {
49+
perPlayerNPCs.putIfAbsent(player.getUuid(), new PlayerNPCCache());
50+
51+
Thread.startVirtualThread(() -> {
52+
HypixelNPC.getNpcs().forEach((npc) -> {
53+
boolean playerHasNPC = perPlayerNPCs.containsKey(player.getUuid()) && perPlayerNPCs.get(player.getUuid()).getEntityImpls().containsKey(npc);
54+
55+
if (!playerHasNPC) {
56+
// If the main username can't be used (over 16 chars), use a blank space instead and use holograms for everything
57+
String username = npc.getParameters().holograms(player)[npc.getParameters().holograms(player).length - 1];
58+
boolean overflowing = username.length() > 16;
59+
if (overflowing) {
60+
username = " ";
61+
}
62+
NPCEntityImpl entity = new NPCEntityImpl(
63+
username,
64+
npc.getParameters().texture(player),
65+
npc.getParameters().signature(player),
66+
npc.getParameters().holograms(player));
67+
Pos position = npc.getParameters().position(player);
68+
69+
PlayerHolograms.ExternalPlayerHologram holo = PlayerHolograms.ExternalPlayerHologram.builder()
70+
.pos(overflowing ? position.add(0, 0.8, 0) : position.add(0, 1.1, 0))
71+
.text(Arrays.copyOfRange(npc.getParameters().holograms(player), 0, npc.getParameters().holograms(player).length - (overflowing ? 0 : 1)))
72+
.player(player)
73+
.build();
74+
75+
entity.setAutoViewable(false);
76+
77+
PlayerHolograms.addExternalPlayerHologram(holo);
78+
entity.setInstance(HypixelConst.getInstanceContainer(), position);
79+
entity.addViewer(player);
80+
81+
PlayerNPCCache cache = perPlayerNPCs.get(player.getUuid());
82+
cache.add(npc, holo, entity);
83+
perPlayerNPCs.put(player.getUuid(), cache);
84+
return;
85+
}
86+
87+
PlayerNPCCache cache = perPlayerNPCs.get(player.getUuid());
88+
NPCEntityImpl entity = cache.get(npc).getValue();
89+
PlayerHolograms.ExternalPlayerHologram holo = cache.get(npc).getKey();
90+
91+
Pos npcPosition = npc.getParameters().position(player);
92+
String npcTexture = npc.getParameters().texture(player);
93+
String npcSignature = npc.getParameters().signature(player);
94+
String[] npcHolograms = npc.getParameters().holograms(player);
95+
96+
// If any of the parameters have changed, update the NPC
97+
if (!Arrays.equals(entity.getHolograms(), npcHolograms) ||
98+
!entity.getSkinTexture().equals(npcTexture) ||
99+
!entity.getSkinSignature().equals(npcSignature) ||
100+
!entity.getPosition().equals(npcPosition)) {
101+
entity.remove();
102+
PlayerHolograms.removeExternalPlayerHologram(holo);
103+
cache.remove(npc);
104+
return;
105+
}
106+
107+
Pos playerPosition = player.getPosition();
108+
List<HypixelPlayer> inRange = entity.getInRangeOf();
109+
double entityDistance = playerPosition.distance(npcPosition);
110+
boolean isLookingNPC = npc.getParameters().looking();
111+
112+
if (entityDistance <= SPAWN_DISTANCE) {
113+
if (!inRange.contains(player)) {
114+
inRange.add(player);
115+
entity.updateNewViewer(player);
116+
}
117+
118+
if (isLookingNPC && entityDistance <= LOOK_DISTANCE) {
119+
double diffX = playerPosition.x() - npcPosition.x();
120+
double diffZ = playerPosition.z() - npcPosition.z();
121+
double theta = Math.atan2(diffZ, diffX);
122+
double yaw = MathUtility.normalizeAngle(Math.toDegrees(theta) + 90, 360.0);
123+
124+
player.sendPackets(
125+
new EntityRotationPacket(entity.getEntityId(), (float) yaw, npcPosition.pitch(), true),
126+
new EntityHeadLookPacket(entity.getEntityId(), (float) yaw)
127+
);
128+
}
129+
} else {
130+
if (inRange.contains(player)) {
131+
inRange.remove(player);
132+
entity.updateOldViewer(player);
133+
134+
player.sendPackets(
135+
new EntityRotationPacket(entity.getEntityId(), npcPosition.yaw(), npcPosition.pitch(), true),
136+
new EntityHeadLookPacket(entity.getEntityId(), npcPosition.yaw())
137+
);
138+
}
139+
}
140+
});
141+
});
142+
}
143+
144+
public abstract void onClick(PlayerClickNPCEvent e);
145+
146+
public void register() {
147+
npcs.add(this);
148+
}
149+
150+
public void sendNPCMessage(HypixelPlayer player, String message) {
151+
player.sendMessage("§e[NPC] " + getName() + "§f: " + message);
152+
}
153+
154+
public record PlayerClickNPCEvent(HypixelPlayer player, int entityId, HypixelNPC npc) {
155+
}
156+
157+
public static class PlayerNPCCache {
158+
private final Map<HypixelNPC, Map.Entry<PlayerHolograms.ExternalPlayerHologram, NPCEntityImpl>> npcs = new ConcurrentHashMap<>();
159+
160+
public void add(HypixelNPC npc, PlayerHolograms.ExternalPlayerHologram hologram, NPCEntityImpl entity) {
161+
npcs.put(npc, Map.entry(hologram, entity));
162+
}
163+
164+
public void remove(HypixelNPC npc) {
165+
npcs.remove(npc);
166+
}
167+
168+
public Map<HypixelNPC, NPCEntityImpl> getEntityImpls() {
169+
Map<HypixelNPC, NPCEntityImpl> entityImpls = new HashMap<>();
170+
npcs.forEach((npc, entry) -> entityImpls.put(npc, entry.getValue()));
171+
return entityImpls;
172+
}
173+
174+
public Map.Entry<PlayerHolograms.ExternalPlayerHologram, NPCEntityImpl> get(HypixelNPC npc) {
175+
return npcs.get(npc);
176+
}
177+
}
172178
}

0 commit comments

Comments
 (0)