Skip to content

Commit 8d64cc6

Browse files
committed
feat(plugin): support target command args (players only)
1 parent c8446b2 commit 8d64cc6

17 files changed

Lines changed: 284 additions & 28 deletions

File tree

examples/plugins/php/src/EffectCommand.php

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,17 @@
55
use Dragonfly\PluginLib\Commands\Command;
66
use Dragonfly\PluginLib\Commands\CommandSender;
77
use Dragonfly\PluginLib\Commands\Optional;
8+
use Dragonfly\PluginLib\Commands\Target;
89
use Dragonfly\PluginLib\Entity\Player;
910
use Dragonfly\PluginLib\Events\EventContext;
1011
use Df\Plugin\EffectType;
1112
use Dragonfly\PluginLib\Util\EnumResolver;
1213

1314
class EffectCommand extends Command {
1415
protected string $name = 'effect';
15-
protected string $description = 'Apply an effect to yourself';
16+
protected string $description = 'Apply an effect to a player';
1617

18+
public Target $target;
1719
public string $effect;
1820
/** @var Optional<int> */
1921
public Optional $level;
@@ -23,8 +25,9 @@ class EffectCommand extends Command {
2325
public Optional $showParticles;
2426

2527
public function execute(CommandSender $sender, EventContext $ctx): void {
26-
if (!$sender instanceof Player) {
27-
$sender->sendMessage("§cThis command can only be run by a player.");
28+
$target = $ctx->getServer()->getPlayer($this->target->uuid);
29+
if ($target === null) {
30+
$sender->sendMessage("§cPlayer not found or offline.");
2831
return;
2932
}
3033

@@ -39,7 +42,7 @@ public function execute(CommandSender $sender, EventContext $ctx): void {
3942
$show = $this->showParticles->getOr(true);
4043
$durationMs = $seconds * 1000;
4144

42-
$sender->addEffect($effectId, $level, $durationMs, $show);
45+
$target->addEffect($effectId, $level, $durationMs, $show);
4346
$sender->sendMessage("Applied effect " . $this->enumName($effectId) . " (id {$effectId}) level {$level} for {$seconds}s" . ($show ? '' : ' (hidden)'));
4447
}
4548

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
github.com/didntpot/pregdk v0.0.0-20251104095621-63cf2e4d7716
88
github.com/go-gl/mathgl v1.2.0
99
github.com/google/uuid v1.6.0
10+
github.com/joho/godotenv v1.5.1
1011
github.com/pelletier/go-toml v1.9.5
1112
github.com/sandertv/gophertunnel v1.51.0
1213
google.golang.org/grpc v1.76.0
@@ -23,7 +24,6 @@ require (
2324
github.com/didntpot/multiversion v0.0.0-20251103204415-8a06d981676a // indirect
2425
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
2526
github.com/golang/snappy v1.0.0 // indirect
26-
github.com/joho/godotenv v1.5.1 // indirect
2727
github.com/klauspost/compress v1.18.1 // indirect
2828
github.com/samber/lo v1.38.1 // indirect
2929
github.com/sandertv/go-raknet v1.14.3-0.20250525005230-991ee492a907 // indirect

packages/cpp/src/generated/command.pb.cc

Lines changed: 11 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/cpp/src/generated/command.pb.h

Lines changed: 6 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/node/src/generated/command.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ export var ParamType;
1515
ParamType[ParamType["PARAM_BOOL"] = 3] = "PARAM_BOOL";
1616
ParamType[ParamType["PARAM_VARARGS"] = 4] = "PARAM_VARARGS";
1717
ParamType[ParamType["PARAM_ENUM"] = 5] = "PARAM_ENUM";
18+
ParamType[ParamType["PARAM_TARGET"] = 6] = "PARAM_TARGET";
19+
ParamType[ParamType["PARAM_TARGETS"] = 7] = "PARAM_TARGETS";
1820
ParamType[ParamType["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
1921
})(ParamType || (ParamType = {}));
2022
export function paramTypeFromJSON(object) {
@@ -37,6 +39,12 @@ export function paramTypeFromJSON(object) {
3739
case 5:
3840
case "PARAM_ENUM":
3941
return ParamType.PARAM_ENUM;
42+
case 6:
43+
case "PARAM_TARGET":
44+
return ParamType.PARAM_TARGET;
45+
case 7:
46+
case "PARAM_TARGETS":
47+
return ParamType.PARAM_TARGETS;
4048
case -1:
4149
case "UNRECOGNIZED":
4250
default:
@@ -57,6 +65,10 @@ export function paramTypeToJSON(object) {
5765
return "PARAM_VARARGS";
5866
case ParamType.PARAM_ENUM:
5967
return "PARAM_ENUM";
68+
case ParamType.PARAM_TARGET:
69+
return "PARAM_TARGET";
70+
case ParamType.PARAM_TARGETS:
71+
return "PARAM_TARGETS";
6072
case ParamType.UNRECOGNIZED:
6173
default:
6274
return "UNRECOGNIZED";

packages/node/src/generated/command.ts

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/php/src/Commands/Command.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,11 +214,27 @@ private function parseTypedValue(string $arg, ?string $typeName): mixed {
214214
'int' => filter_var($arg, FILTER_VALIDATE_INT),
215215
'float' => filter_var($arg, FILTER_VALIDATE_FLOAT),
216216
'bool' => $this->parseBool($arg),
217+
'target' => $this->parseTarget($arg),
218+
'targets' => $this->parseTargetsList($arg),
217219
null, 'string' => $arg,
218220
default => null,
219221
};
220222
}
221223

224+
private function parseTarget(string $arg): ?Target {
225+
$val = trim($arg);
226+
if ($val === '') {
227+
return null;
228+
}
229+
// Prefer UUID when present; otherwise keep the raw name for caller-side resolution if needed.
230+
// TODO: remove this when we support entity targets
231+
$isUuid = (bool)preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i', $val);
232+
if ($isUuid) {
233+
return new Target(strtolower($val));
234+
}
235+
return new Target('', $val);
236+
}
237+
222238
private function parseBool(string $arg): ?bool {
223239
$v = strtolower($arg);
224240
return match ($v) {
@@ -248,10 +264,15 @@ private function inspectParameters(): array {
248264
$out[] = ['name' => $name, 'type' => $t, 'optional' => true];
249265
continue;
250266
}
267+
if ($typeName === 'array' && $this->isTargetsArray($prop)) {
268+
$out[] = ['name' => $name, 'type' => 'targets'];
269+
continue;
270+
}
251271
$mapped = match ($typeName) {
252272
'int' => 'int',
253273
'float', 'double' => 'float',
254274
'bool' => 'bool',
275+
Target::class => 'target',
255276
default => 'string',
256277
};
257278
$out[] = ['name' => $name, 'type' => $mapped];
@@ -305,10 +326,39 @@ private function getOptionalWrappedType(ReflectionProperty $prop): string {
305326
'float', 'double' => 'float',
306327
'bool', 'boolean' => 'bool',
307328
'string' => 'string',
329+
'target' => 'target',
308330
default => 'string',
309331
};
310332
}
311333
// Default to string if not annotated.
312334
return 'string';
313335
}
336+
337+
/**
338+
* Detect @var Target[] arrays for multi-target parameters.
339+
*/
340+
private function isTargetsArray(ReflectionProperty $prop): bool {
341+
$doc = $prop->getDocComment() ?: '';
342+
return (bool)preg_match('/@var\s+Target\[\]/i', $doc);
343+
}
344+
345+
/**
346+
* Parse a comma-separated list of targets into Target[].
347+
*
348+
* @return Target[]
349+
*/
350+
private function parseTargetsList(string $arg): array {
351+
$parts = preg_split('/\s*,\s*/', trim($arg)) ?: [];
352+
$out = [];
353+
foreach ($parts as $p) {
354+
if ($p === '') {
355+
continue;
356+
}
357+
$t = $this->parseTarget($p);
358+
if ($t !== null) {
359+
$out[] = $t;
360+
}
361+
}
362+
return $out;
363+
}
314364
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Dragonfly\PluginLib\Commands;
4+
5+
final class Target {
6+
public function __construct(
7+
public readonly string $uuid,
8+
public readonly string $name = ''
9+
) {}
10+
}

packages/php/src/PluginBase.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -305,8 +305,6 @@ private function resolveEventBinding(string $payloadFqcn): ?array {
305305
return ['type' => $type, 'getter' => $getter];
306306
}
307307

308-
// Action helpers moved to StreamSender and HandlerContext
309-
310308
// Runner
311309
public function run(): void {
312310
if (!\extension_loaded('grpc')) {
@@ -378,6 +376,8 @@ public function run(): void {
378376
'bool' => PbParamType::PARAM_BOOL,
379377
'enum' => PbParamType::PARAM_ENUM,
380378
'varargs' => PbParamType::PARAM_VARARGS,
379+
'target' => PbParamType::PARAM_TARGET,
380+
'targets' => PbParamType::PARAM_TARGETS,
381381
default => PbParamType::PARAM_STRING,
382382
});
383383
if (!empty($p['optional'])) {

packages/php/src/generated/Df/Plugin/GPBMetadata/Command.php

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)