Skip to content

Commit 3a1c125

Browse files
committed
non unit controls
1 parent 2c581e4 commit 3a1c125

10 files changed

+87
-45
lines changed

TODO.txt

+7-8
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,8 @@ HEROES (in order of priority)
2222
Controlling non-RoN mobs
2323
------------------------
2424

25-
[❌] Continue moving past the follow range
26-
- echo the original packet once we reach the end goal
27-
[❌] Sending a move command doesn't immediately enact the move if the unit has a target
28-
29-
[❌] Allow selecting multiple non-units, but do not mix with units (and prioritise units)
30-
- Also allow double-click to select multiple
31-
32-
[❌] Attack move (just make it a move action but don't cancel NearestAttackableTargetGoal)
25+
[🟡] Attack move (just make it a move action but don't cancel NearestAttackableTargetGoal)
26+
- Still only attacks whatever is naturally aggroed with these goals...
3327

3428

3529
Bugfixes
@@ -41,8 +35,13 @@ Quality of Life
4135
---------------
4236
[🟡] Updated /rts-help list
4337

38+
39+
4440
Balancing
4541
---------
42+
[🟡] The Killer Rabbit now has increased knockback resistance and attack jump height
43+
44+
4645
- Nerf sculk amplifiers? (can reduce damage)
4746
- Nerf ravager artillery? (take away bonus damage?)
4847
- Buff creepers?

src/main/java/com/solegendary/reignofnether/cursor/CursorClientEvents.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.solegendary.reignofnether.cursor;
22

33
import com.mojang.blaze3d.systems.RenderSystem;
4+
import com.solegendary.reignofnether.unit.NonUnitClientEvents;
45
import org.joml.Vector3d;
56
import com.solegendary.reignofnether.building.Building;
67
import com.solegendary.reignofnether.building.BuildingClientEvents;
@@ -169,15 +170,15 @@ public static void onDrawScreen(ScreenEvent.Render evt) {
169170
RenderSystem.setShaderTexture(0, TEXTURE_CURSOR);
170171
texture = TEXTURE_CURSOR;
171172
}
172-
evt.getGuiGraphics().pose().translate(0,0,1000);
173+
evt.getGuiGraphics().pose().translate(0,0,2500);
173174
evt.getGuiGraphics().blit(texture,
174175
cursorDrawX, cursorDrawY,
175176
16,
176177
16, 16,
177178
16, 16,
178179
16, 16
179180
);
180-
evt.getGuiGraphics().pose().translate(0,0,-1000);
181+
evt.getGuiGraphics().pose().translate(0,0,-2500);
181182

182183
// ***********************************************
183184
// Convert cursor on-screen 2d pos to world 3d pos
@@ -337,13 +338,13 @@ public static void onMouseRelease(ScreenEvent.MouseButtonReleased.Post evt) {
337338
// only act if there is at least 1 owned entity so we don't deselect things by box selecting only non-owned entities
338339
int ownedEntities = 0;
339340
for (LivingEntity unit : preselectedUnit)
340-
if (UnitClientEvents.getPlayerToEntityRelationship(unit) == Relationship.OWNED)
341+
if (UnitClientEvents.getPlayerToEntityRelationship(unit) == Relationship.OWNED || NonUnitClientEvents.canControlNonUnits())
341342
ownedEntities += 1;
342343

343344
if (ownedEntities > 0) {
344345
ArrayList<LivingEntity> unitsToAdd = new ArrayList<>();
345346
for (LivingEntity unit : preselectedUnit)
346-
if (UnitClientEvents.getPlayerToEntityRelationship(unit) == Relationship.OWNED)
347+
if (UnitClientEvents.getPlayerToEntityRelationship(unit) == Relationship.OWNED || NonUnitClientEvents.canControlNonUnits())
347348
unitsToAdd.add(unit);
348349

349350
if (Keybindings.shiftMod.isDown()) {

src/main/java/com/solegendary/reignofnether/hud/HudClientEvents.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,7 @@ else if (hudSelectedEntity != null && portraitRendererUnit.model != null
778778
if (selUnits.size() > 0 && SandboxClientEvents.isSandboxPlayer() && hudSelectedEntity instanceof Unit &&
779779
getPlayerToEntityRelationship(selUnits.get(0)) != Relationship.OWNED) {
780780
blitX = 0;
781-
blitY = screenHeight - iconFrameSize;
781+
blitY = screenHeight - (iconFrameSize * 2);
782782
ArrayList<Button> actionButtons = new ArrayList<>();
783783

784784
if (hudSelectedEntity instanceof AttackerUnit) {
@@ -1613,6 +1613,8 @@ public static void onClientTick(TickEvent.ClientTickEvent evt) {
16131613
@SubscribeEvent
16141614
// hudSelectedEntity and portraitRendererUnit should be assigned in the same event to avoid desyncs
16151615
public static void onRenderLivingEntity(RenderLivingEvent.Post<? extends LivingEntity, ? extends Model> evt) {
1616+
if (hudSelectedEntity != null && hudSelectedEntity.isRemoved())
1617+
hudSelectedEntity = null;
16161618

16171619
ArrayList<LivingEntity> units = UnitClientEvents.getSelectedUnits();
16181620

src/main/java/com/solegendary/reignofnether/mixin/goals/NearestAttackableTargetGoalMixin.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import org.spongepowered.asm.mixin.injection.At;
1010
import org.spongepowered.asm.mixin.injection.Inject;
1111
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
12-
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
1312

1413
@Mixin(NearestAttackableTargetGoal.class)
1514
public abstract class NearestAttackableTargetGoalMixin extends TargetGoal {
@@ -23,8 +22,8 @@ public abstract class NearestAttackableTargetGoalMixin extends TargetGoal {
2322
cancellable = true
2423
)
2524
public void findTarget(CallbackInfo ci) {
26-
synchronized (NonUnitServerEvents.controlledNonUnits) {
27-
if (mob instanceof PathfinderMob pfMob && NonUnitServerEvents.controlledNonUnits.contains(pfMob))
25+
synchronized (NonUnitServerEvents.attackSuppressedNonUnits) {
26+
if (mob instanceof PathfinderMob pfMob && NonUnitServerEvents.attackSuppressedNonUnits.contains(pfMob))
2827
ci.cancel();
2928
}
3029
}

src/main/java/com/solegendary/reignofnether/mixin/goals/RandomStrollGoalMixin.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ public abstract class RandomStrollGoalMixin {
2121
cancellable = true
2222
)
2323
public void canContinueToUse(CallbackInfoReturnable<Boolean> cir) {
24-
synchronized (NonUnitServerEvents.controlledNonUnits) {
25-
if (NonUnitServerEvents.controlledNonUnits.contains(mob))
24+
synchronized (NonUnitServerEvents.moveSuppressedNonUnits) {
25+
if (NonUnitServerEvents.moveSuppressedNonUnits.contains(mob))
2626
cir.setReturnValue(false);
2727
}
2828
}

src/main/java/com/solegendary/reignofnether/unit/NonUnitClientEvents.java

+10-6
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ public class NonUnitClientEvents {
3030

3131
private static final Minecraft MC = Minecraft.getInstance();
3232

33+
public static boolean isMoveCheckpointGreen = true;
34+
3335
public static boolean canControlNonUnits() {
3436
return MC.player != null &&
35-
!getSelectedUnits().isEmpty() &&
36-
(ResearchClient.hasCheat("wouldyoukindly") ||
37-
SandboxClientEvents.isSandboxPlayer(MC.player.getName().getString()));
37+
(ResearchClient.hasCheat("wouldyoukindly") ||
38+
SandboxClientEvents.isSandboxPlayer(MC.player.getName().getString()));
3839
}
3940

4041
public static boolean canAttack(LivingEntity le) {
@@ -75,17 +76,20 @@ else if (!mob.getNavigation().isDone() && mob.getNavigation().getTargetPos() !=
7576
if (a > 0) {
7677
BlockPos bp = mob.getNavigation().getTargetPos().below();
7778
Vec3 pos = new Vec3(bp.getX() + 0.5f, bp.getY() + 1.0f, bp.getZ() + 0.5f);
78-
MyRenderer.drawLine(evt.getPoseStack(), firstPos, pos, 0, 1, 0, a);
79+
MyRenderer.drawLine(evt.getPoseStack(), firstPos, pos, isMoveCheckpointGreen ? 0 : 1, isMoveCheckpointGreen ? 1 : 0, 0, a);
7980

8081
if (MC.level.getBlockState(bp.offset(0, 1, 0)).getBlock() instanceof SnowLayerBlock) {
8182
AABB aabb = new AABB(bp);
8283
aabb = aabb.setMaxY(aabb.maxY + 0.13f);
83-
MyRenderer.drawSolidBox(evt.getPoseStack(), aabb, Direction.UP, 0, 1, 0, a * 0.5f,
84+
MyRenderer.drawSolidBox(evt.getPoseStack(), aabb, Direction.UP, isMoveCheckpointGreen ? 0 : 1, isMoveCheckpointGreen ? 1 : 0, 0, a * 0.5f,
8485
new ResourceLocation("forge:textures/white.png"));
8586
} else {
86-
MyRenderer.drawBlockFace(evt.getPoseStack(), Direction.UP, bp, 0, 1, 0, a * 0.5f);
87+
MyRenderer.drawBlockFace(evt.getPoseStack(), Direction.UP, bp, isMoveCheckpointGreen ? 0 : 1, isMoveCheckpointGreen ? 1 : 0, 0, a * 0.5f);
8788
}
8889
}
90+
} else {
91+
mob.getNavigation().stop();
92+
mob.setTarget(null);
8993
}
9094
}
9195
}

src/main/java/com/solegendary/reignofnether/unit/NonUnitServerEvents.java

+28-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package com.solegendary.reignofnether.unit;
22

3+
import com.mojang.datafixers.util.Pair;
34
import com.solegendary.reignofnether.research.ResearchServerEvents;
45
import com.solegendary.reignofnether.sandbox.SandboxServer;
6+
import net.minecraft.core.BlockPos;
57
import net.minecraft.world.entity.PathfinderMob;
68
import net.minecraft.world.level.Level;
9+
import net.minecraft.world.level.pathfinder.Path;
710
import net.minecraftforge.event.TickEvent;
811
import net.minecraftforge.eventbus.api.SubscribeEvent;
912

@@ -13,8 +16,11 @@
1316

1417
public class NonUnitServerEvents {
1518

16-
// any mobs in this list will have their basic movement and attack goals cancelled until they become idle
17-
public static final List<PathfinderMob> controlledNonUnits = Collections.synchronizedList(new ArrayList<>());
19+
// list of units to cancel specific goals for so they don't interfere with player commands
20+
public static final List<PathfinderMob> attackSuppressedNonUnits = Collections.synchronizedList(new ArrayList<>());
21+
public static final List<PathfinderMob> moveSuppressedNonUnits = Collections.synchronizedList(new ArrayList<>());
22+
23+
public static final List<Pair<PathfinderMob, BlockPos>> nonUnitMoveTargets = Collections.synchronizedList(new ArrayList<>());
1824

1925
public static boolean canControlNonUnits(Level level, String playerName) {
2026
return SandboxServer.isSandboxPlayer(playerName) || ResearchServerEvents.playerHasCheat(playerName, "wouldyoukindly");
@@ -26,8 +32,26 @@ public static void onWorldTick(TickEvent.LevelTickEvent evt) {
2632
return;
2733
}
2834

29-
synchronized (controlledNonUnits) {
30-
controlledNonUnits.removeIf(mob -> (mob.isDeadOrDying() || mob.isRemoved() || (mob.getNavigation().isDone() && mob.getTarget() == null)));
35+
synchronized (nonUnitMoveTargets) {
36+
nonUnitMoveTargets.removeIf(pair -> {
37+
PathfinderMob mob = pair.getFirst();
38+
BlockPos finalTargetBp = pair.getSecond();
39+
Path navPath = mob.getNavigation().getPath();
40+
if (mob.distanceToSqr(finalTargetBp.getCenter()) < 4) {
41+
return true;
42+
} else if (mob.tickCount % 20 == 0 && navPath == null ||
43+
(navPath != null && navPath.getEndNode() != null && mob.distanceToSqr(navPath.getEndNode().asBlockPos().getCenter()) < 4)) {
44+
Path path = mob.getNavigation().createPath(finalTargetBp.getX(), finalTargetBp.getY(), finalTargetBp.getZ(), 0);
45+
mob.getNavigation().moveTo(path, 1);
46+
}
47+
return false;
48+
});
49+
}
50+
synchronized (attackSuppressedNonUnits) {
51+
attackSuppressedNonUnits.removeIf(mob -> (mob.isDeadOrDying() || mob.isRemoved() || (mob.getNavigation().isDone() && mob.getTarget() == null)));
52+
}
53+
synchronized (moveSuppressedNonUnits) {
54+
moveSuppressedNonUnits.removeIf(mob -> (mob.isDeadOrDying() || mob.isRemoved() || (mob.getNavigation().isDone() && mob.getTarget() == null)));
3155
}
3256
}
3357
}

src/main/java/com/solegendary/reignofnether/unit/UnitActionItem.java

+18-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
package com.solegendary.reignofnether.unit;
22

3+
import com.mojang.datafixers.util.Pair;
34
import com.solegendary.reignofnether.ability.Ability;
45
import com.solegendary.reignofnether.building.Building;
56
import com.solegendary.reignofnether.building.BuildingUtils;
67
import com.solegendary.reignofnether.building.GarrisonableBuilding;
78
import com.solegendary.reignofnether.building.buildings.piglins.Portal;
89
import com.solegendary.reignofnether.hud.HudClientEvents;
9-
import com.solegendary.reignofnether.research.ResearchClient;
10-
import com.solegendary.reignofnether.research.ResearchServerEvents;
1110
import com.solegendary.reignofnether.resources.ResourceName;
1211
import com.solegendary.reignofnether.resources.ResourceSources;
1312
import com.solegendary.reignofnether.sandbox.SandboxClientEvents;
@@ -31,6 +30,8 @@
3130
import java.util.Arrays;
3231
import java.util.List;
3332

33+
import static com.solegendary.reignofnether.unit.NonUnitServerEvents.nonUnitMoveTargets;
34+
3435
public class UnitActionItem {
3536
private final String ownerName;
3637
private final UnitAction action;
@@ -394,18 +395,30 @@ public void action(Level level) {
394395
mob.getNavigation().stop();
395396
mob.setTarget(null);
396397

397-
if (action == UnitAction.MOVE) {
398+
if (List.of(UnitAction.MOVE, UnitAction.FOLLOW, UnitAction.ATTACK_MOVE).contains(action)) {
398399
mob.getNavigation().stop();
399400
BlockPos bp = preselectedBlockPos;
400401
Path path = mob.getNavigation().createPath(bp.getX(), bp.getY(), bp.getZ(), 0);
401402
mob.getNavigation().moveTo(path, 1);
403+
if (!level.isClientSide()) {
404+
synchronized (NonUnitServerEvents.nonUnitMoveTargets) {
405+
NonUnitServerEvents.nonUnitMoveTargets.removeIf(p -> p.getFirst() == mob);
406+
NonUnitServerEvents.nonUnitMoveTargets.add(new Pair<>(mob, preselectedBlockPos));
407+
}
408+
}
402409
} else if (action == UnitAction.ATTACK) {
403410
if (level.getEntity(unitId) instanceof LivingEntity le) {
404411
mob.setTarget(le);
405412
}
406413
}
407-
if (!level.isClientSide())
408-
NonUnitServerEvents.controlledNonUnits.add(mob);
414+
if (!level.isClientSide()) {
415+
if (action != UnitAction.ATTACK_MOVE) {
416+
NonUnitServerEvents.attackSuppressedNonUnits.add(mob);
417+
} else {
418+
NonUnitClientEvents.isMoveCheckpointGreen = false;
419+
}
420+
NonUnitServerEvents.moveSuppressedNonUnits.add(mob);
421+
}
409422
}
410423
}
411424
}

src/main/java/com/solegendary/reignofnether/unit/UnitClientEvents.java

+10-11
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,14 @@ public static void addSelectedUnit(LivingEntity unit) {
122122
selectedUnits.sort(Comparator.comparing(HudClientEvents::getSimpleEntityName));
123123
selectedUnits.sort(Comparator.comparing(Entity::getId));
124124
BuildingClientEvents.clearSelectedBuildings();
125+
NonUnitClientEvents.isMoveCheckpointGreen = true;
125126
}
126127
public static void clearPreselectedUnits() {
127128
preselectedUnits.clear();
128129
}
129130
public static void clearSelectedUnits() {
130131
selectedUnits.clear();
132+
NonUnitClientEvents.isMoveCheckpointGreen = true;
131133
}
132134

133135
private static long lastLeftClickTime = 0; // to track double clicks
@@ -325,13 +327,7 @@ MC.level, selectedUnits, getPreselectedBlockPos()
325327
int entityId = pair.getFirst();
326328
BlockPos targetPos = pair.getSecond();
327329
Entity entity = MC.level.getEntity(entityId);
328-
if (entity instanceof Unit unit &&
329-
unit.getMoveGoal() != null) {
330-
331-
//sendUnitCommandManual(UnitAction.MOVE, -1, new int[]{entityId}, targetPos, true, false);
332-
333-
sendUnitCommandManual(UnitAction.MOVE, -1, new int[]{entityId}, targetPos);
334-
}
330+
sendUnitCommandManual(UnitAction.MOVE, -1, new int[]{entityId}, targetPos);
335331
}
336332
for (LivingEntity le : selectedUnits)
337333
if (le instanceof Unit unit && unit.getMoveGoal() != null)
@@ -574,10 +570,10 @@ else if (selectedUnits.size() == 1 && MC.level != null && !Keybindings.shiftMod.
574570
selectedUnits.get(0).getClass(),
575571
MC.level
576572
);
577-
if (getPlayerToEntityRelationship(selectedUnit) == Relationship.OWNED) {
573+
if (getPlayerToEntityRelationship(selectedUnit) == Relationship.OWNED || NonUnitClientEvents.canControlNonUnits()) {
578574
clearSelectedUnits();
579575
for (LivingEntity entity : nearbyEntities)
580-
if (getPlayerToEntityRelationship(entity) == Relationship.OWNED)
576+
if (getPlayerToEntityRelationship(entity) == Relationship.OWNED || NonUnitClientEvents.canControlNonUnits())
581577
addSelectedUnit(entity);
582578
HudClientEvents.setLowestCdHudEntity();
583579
}
@@ -610,8 +606,11 @@ else if (!deselected) { // select a single unit - this should be the only code p
610606
}
611607
// deselect any non-owned units if we managed to select them with owned units
612608
// and disallow selecting > 1 non-owned unit or the client player
613-
if (selectedUnits.size() > 1)
614-
selectedUnits.removeIf(e -> getPlayerToEntityRelationship(e) != Relationship.OWNED || e.getId() == MC.player.getId());
609+
if (selectedUnits.size() > 1) {
610+
selectedUnits.removeIf(e ->
611+
(getPlayerToEntityRelationship(e) != Relationship.OWNED && !NonUnitClientEvents.canControlNonUnits()) || e.getId() == MC.player.getId()
612+
);
613+
}
615614

616615
lastLeftClickTime = System.currentTimeMillis();
617616
}

src/main/java/com/solegendary/reignofnether/unit/units/neutral/KillerRabbitUnit.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ public static AttributeSupplier.Builder createAttributes() {
143143
.add(Attributes.MOVEMENT_SPEED, KillerRabbitUnit.movementSpeed)
144144
.add(Attributes.MAX_HEALTH, KillerRabbitUnit.maxHealth)
145145
.add(Attributes.FOLLOW_RANGE, Unit.getFollowRange())
146+
.add(Attributes.KNOCKBACK_RESISTANCE, 0.75d)
146147
.add(Attributes.ARMOR, KillerRabbitUnit.armorValue);
147148
}
148149

@@ -157,7 +158,7 @@ protected float getJumpPower() {
157158
}
158159

159160
if (xz2 != null && getTarget().getY() - getY() > 6 && xz1.distanceTo(xz2) < 4) {
160-
return jumpPower * 4;
161+
return jumpPower * 4.5f;
161162
}
162163
else if (jumpPower > 0.1f && jumpPower < 0.3f) {
163164
// prevents getting stuck jumping on the spot when pushed flush against a block

0 commit comments

Comments
 (0)