Skip to content

Commit e951a9e

Browse files
committed
fix: velocity as client failed to start
1 parent 19cf08d commit e951a9e

9 files changed

Lines changed: 627 additions & 96 deletions

File tree

backends/src/main/java/dev/objz/commandbridge/backends/net/out/InvokedCommandEvent.java

Lines changed: 244 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -14,102 +14,28 @@
1414
import dev.objz.commandbridge.net.proto.MessageType;
1515
import dev.objz.commandbridge.scripting.model.enums.ArgType;
1616
import dev.objz.commandbridge.scripting.model.records.mapping.ArgMapping;
17+
1718
import java.util.ArrayList;
19+
import java.util.Collection;
1820
import java.util.List;
19-
import org.bukkit.command.BlockCommandSender;
20-
import org.bukkit.command.CommandSender;
21-
import org.bukkit.command.ConsoleCommandSender;
22-
import org.bukkit.entity.Player;
21+
import java.util.Objects;
22+
import java.util.UUID;
2323

2424
public final class InvokedCommandEvent extends OutboundHandler<InvokedCommandContext> {
2525

2626
@Override
2727
public SendOperation accept(InvokedCommandContext ctx) {
28-
CommandSender sender = ctx.sender;
29-
SenderContext senderCtx;
30-
if (sender instanceof Player p) {
31-
senderCtx = new SenderContext.Player(p.getName(), p.getUniqueId().toString());
32-
} else if (sender instanceof ConsoleCommandSender) {
33-
senderCtx = new SenderContext.Console();
34-
} else if (sender instanceof BlockCommandSender b) {
35-
var l = b.getBlock().getLocation();
36-
senderCtx = new SenderContext.Block(
37-
new Location3D(
38-
l.getWorld().getName(),
39-
l.getX(),
40-
l.getY(),
41-
l.getZ()));
42-
} else {
43-
senderCtx = new SenderContext.Other(sender.getClass().getSimpleName());
44-
}
28+
SenderContext senderCtx = mapSender(ctx.sender);
4529

4630
List<InvokedCommand.TypedArgument> typedArgs = new ArrayList<>();
4731
CommandStub stub = ctx.stub;
4832
CommandArguments args = ctx.args;
4933

5034
if (stub.args() != null && !stub.args().isEmpty()) {
51-
for (ArgMapping m : stub.args()) {
52-
String name = m.name();
53-
ArgType type = m.type();
54-
Object raw = args.getOptional(name).orElse(null);
55-
56-
Object value = switch (type) {
57-
case STRING, TEXT, GREEDY_STRING -> (raw != null ? raw.toString() : null);
58-
59-
case INTEGER, TIME -> (raw != null ? ((Number) raw).intValue() : 0);
60-
61-
case DOUBLE -> (raw != null ? ((Number) raw).doubleValue() : 0.0);
62-
63-
case BOOLEAN -> (raw instanceof Boolean b ? b
64-
: raw != null && Boolean.TRUE.equals(raw));
65-
66-
case LOCATION -> {
67-
org.bukkit.Location l = (org.bukkit.Location) raw;
68-
yield (l == null) ? null
69-
: new Location3D(
70-
l.getWorld().getName(),
71-
l.getX(),
72-
l.getY(),
73-
l.getZ());
74-
}
75-
76-
case LOCATION_2D -> {
77-
org.bukkit.Location l = (org.bukkit.Location) raw;
78-
yield (l == null) ? null
79-
: new Location2D(
80-
l.getWorld().getName(),
81-
l.getX(),
82-
l.getZ());
83-
}
84-
85-
case PLAYERS, ENTITIES -> {
86-
var list = ((raw instanceof java.util.Collection<?>)
87-
? (java.util.Collection<?>) raw
88-
: List.of())
89-
.stream()
90-
.filter(o -> o instanceof org.bukkit.entity.Entity)
91-
.map(o -> {
92-
var e = (org.bukkit.entity.Entity) o;
93-
return new EntityRef(
94-
e.getType().name(),
95-
e.getUniqueId().toString(),
96-
e.getName());
97-
})
98-
.toList();
99-
yield list; // List<EntityRef>
100-
}
101-
102-
case ENTITY_TYPE -> (raw != null ? raw.toString() : null);
103-
104-
case OFFLINE_PLAYER -> (raw != null ? raw.toString() : null);
105-
106-
case RANGE -> (raw != null ? raw.toString() : null);
107-
108-
case WORLD, ANGLE, ROTATION, ITEM_STACK, ENCHANTMENT, POTION_EFFECT,
109-
SOUND, BIOME, SERVER ->
110-
(raw != null ? raw.toString() : null);
111-
};
112-
35+
for (ArgMapping mapping : stub.args()) {
36+
ArgType type = mapping.type();
37+
Object raw = args.getOptional(mapping.name()).orElse(null);
38+
Object value = mapArgument(type, raw);
11339
typedArgs.add(new InvokedCommand.TypedArgument(type, value));
11440
}
11541
}
@@ -127,4 +53,239 @@ public SendOperation accept(InvokedCommandContext ctx) {
12753
op.dispatch();
12854
return op;
12955
}
56+
57+
private SenderContext mapSender(Object sender) {
58+
if (sender == null) {
59+
return new SenderContext.Other("null");
60+
}
61+
62+
SenderContext.Player player = asPlayerSender(sender);
63+
if (player != null) {
64+
return player;
65+
}
66+
67+
if (isConsoleSender(sender)) {
68+
return new SenderContext.Console();
69+
}
70+
71+
Location3D block = extractBlockLocation(sender);
72+
if (block != null) {
73+
return new SenderContext.Block(block);
74+
}
75+
76+
return new SenderContext.Other(sender.getClass().getSimpleName());
77+
}
78+
79+
private SenderContext.Player asPlayerSender(Object sender) {
80+
UUID uuid = invokeUuid(sender, "getUniqueId");
81+
if (uuid == null) {
82+
return null;
83+
}
84+
85+
String name = invokeString(sender, "getUsername");
86+
if (name == null || name.isBlank()) {
87+
name = invokeString(sender, "getName");
88+
}
89+
if (name == null || name.isBlank()) {
90+
name = sender.getClass().getSimpleName();
91+
}
92+
93+
return new SenderContext.Player(name, uuid.toString());
94+
}
95+
96+
private boolean isConsoleSender(Object sender) {
97+
String className = sender.getClass().getName();
98+
return className.endsWith("ConsoleCommandSender")
99+
|| className.endsWith("ConsoleCommandSource");
100+
}
101+
102+
private Location3D extractBlockLocation(Object sender) {
103+
Object block = invoke(sender, "getBlock");
104+
if (block == null) {
105+
return null;
106+
}
107+
Object location = invoke(block, "getLocation");
108+
return toLocation3D(location);
109+
}
110+
111+
private Object mapArgument(ArgType type, Object raw) {
112+
return switch (type) {
113+
case STRING, TEXT, GREEDY_STRING, ENTITY_TYPE, OFFLINE_PLAYER, RANGE,
114+
WORLD, ANGLE, ROTATION, ITEM_STACK, ENCHANTMENT, POTION_EFFECT,
115+
SOUND, BIOME, SERVER -> raw != null ? raw.toString() : null;
116+
117+
case INTEGER, TIME -> toInt(raw);
118+
119+
case DOUBLE -> toDouble(raw);
120+
121+
case BOOLEAN -> toBoolean(raw);
122+
123+
case LOCATION -> toLocation3D(raw);
124+
125+
case LOCATION_2D -> toLocation2D(raw);
126+
127+
case PLAYERS, ENTITIES -> toEntityRefs(raw);
128+
};
129+
}
130+
131+
private int toInt(Object raw) {
132+
if (raw instanceof Number number) {
133+
return number.intValue();
134+
}
135+
if (raw == null) {
136+
return 0;
137+
}
138+
try {
139+
return Integer.parseInt(raw.toString());
140+
} catch (NumberFormatException ignored) {
141+
return 0;
142+
}
143+
}
144+
145+
private double toDouble(Object raw) {
146+
if (raw instanceof Number number) {
147+
return number.doubleValue();
148+
}
149+
if (raw == null) {
150+
return 0.0;
151+
}
152+
try {
153+
return Double.parseDouble(raw.toString());
154+
} catch (NumberFormatException ignored) {
155+
return 0.0;
156+
}
157+
}
158+
159+
private boolean toBoolean(Object raw) {
160+
if (raw instanceof Boolean value) {
161+
return value;
162+
}
163+
return raw != null && Boolean.parseBoolean(raw.toString());
164+
}
165+
166+
private Location3D toLocation3D(Object raw) {
167+
if (raw == null) {
168+
return null;
169+
}
170+
171+
Double x = invokeDouble(raw, "getX");
172+
Double y = invokeDouble(raw, "getY");
173+
Double z = invokeDouble(raw, "getZ");
174+
if (x == null || y == null || z == null) {
175+
return null;
176+
}
177+
178+
return new Location3D(resolveWorldName(raw), x, y, z);
179+
}
180+
181+
private Location2D toLocation2D(Object raw) {
182+
if (raw == null) {
183+
return null;
184+
}
185+
186+
Double x = invokeDouble(raw, "getX");
187+
Double z = invokeDouble(raw, "getZ");
188+
if (x == null || z == null) {
189+
return null;
190+
}
191+
192+
return new Location2D(resolveWorldName(raw), x, z);
193+
}
194+
195+
private String resolveWorldName(Object location) {
196+
Object world = invoke(location, "getWorld");
197+
String worldName = invokeString(world, "getName");
198+
if (worldName == null || worldName.isBlank()) {
199+
worldName = invokeString(location, "getWorldName");
200+
}
201+
return (worldName == null || worldName.isBlank()) ? "unknown" : worldName;
202+
}
203+
204+
private List<EntityRef> toEntityRefs(Object raw) {
205+
if (!(raw instanceof Collection<?> collection)) {
206+
return List.of();
207+
}
208+
209+
return collection.stream()
210+
.map(this::toEntityRef)
211+
.filter(Objects::nonNull)
212+
.toList();
213+
}
214+
215+
private EntityRef toEntityRef(Object entity) {
216+
if (entity == null) {
217+
return null;
218+
}
219+
220+
if (entity instanceof String name && !name.isBlank()) {
221+
return new EntityRef("PLAYER", null, name);
222+
}
223+
224+
String uuid = null;
225+
UUID parsedUuid = invokeUuid(entity, "getUniqueId");
226+
if (parsedUuid != null) {
227+
uuid = parsedUuid.toString();
228+
}
229+
230+
String name = invokeString(entity, "getName");
231+
232+
Object typeObj = invoke(entity, "getType");
233+
String type = invokeString(typeObj, "name");
234+
if (type == null || type.isBlank()) {
235+
type = typeObj != null ? typeObj.toString() : "UNKNOWN";
236+
}
237+
238+
if ((name == null || name.isBlank()) && uuid == null) {
239+
return null;
240+
}
241+
242+
return new EntityRef(type, uuid, name);
243+
}
244+
245+
private Object invoke(Object target, String method) {
246+
if (target == null) {
247+
return null;
248+
}
249+
250+
try {
251+
return target.getClass().getMethod(method).invoke(target);
252+
} catch (ReflectiveOperationException ignored) {
253+
return null;
254+
}
255+
}
256+
257+
private String invokeString(Object target, String method) {
258+
Object value = invoke(target, method);
259+
return value != null ? value.toString() : null;
260+
}
261+
262+
private UUID invokeUuid(Object target, String method) {
263+
Object value = invoke(target, method);
264+
if (value instanceof UUID uuid) {
265+
return uuid;
266+
}
267+
if (value instanceof String str) {
268+
try {
269+
return UUID.fromString(str);
270+
} catch (IllegalArgumentException ignored) {
271+
return null;
272+
}
273+
}
274+
return null;
275+
}
276+
277+
private Double invokeDouble(Object target, String method) {
278+
Object value = invoke(target, method);
279+
if (value instanceof Number number) {
280+
return number.doubleValue();
281+
}
282+
if (value instanceof String str) {
283+
try {
284+
return Double.parseDouble(str);
285+
} catch (NumberFormatException ignored) {
286+
return null;
287+
}
288+
}
289+
return null;
290+
}
130291
}

backends/src/main/java/dev/objz/commandbridge/backends/net/out/ctx/InvokedCommandContext.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,16 @@
55

66
import java.util.Objects;
77

8-
import org.bukkit.command.CommandSender;
9-
108
public final class InvokedCommandContext {
119

1210
public final String commandName;
13-
public final CommandSender sender;
11+
public final Object sender;
1412
public final CommandArguments args;
1513
public final CommandStub stub;
1614

1715
public InvokedCommandContext(
1816
String commandName,
19-
CommandSender sender,
17+
Object sender,
2018
CommandArguments args,
2119
CommandStub stub) {
2220
this.commandName = Objects.requireNonNull(commandName, "commandName");

0 commit comments

Comments
 (0)