-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Experimenting with Team and Freezer to manipulate mob's AI
- Loading branch information
Showing
7 changed files
with
235 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
src/main/java/org/arsparadox/mobtalkerredux/command/MobFreezer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package org.arsparadox.mobtalkerredux.command; | ||
|
||
import net.minecraft.server.level.ServerLevel; | ||
import net.minecraft.world.entity.Mob; | ||
import net.minecraft.world.entity.ai.attributes.AttributeModifier; | ||
import net.minecraft.world.entity.ai.attributes.Attributes; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.UUID; | ||
|
||
public class MobFreezer { | ||
private static final Map<UUID, Boolean> frozenMobs = new HashMap<>(); | ||
private static final UUID MOVEMENT_SPEED_MODIFIER = UUID.fromString("708396DC-7DEA-4EDD-B915-A3B97ADFF457"); | ||
|
||
/** | ||
* Freezes a mob in place, disabling AI and movement | ||
* @param mob The mob to freeze | ||
* @return true if the mob was frozen, false if already frozen | ||
*/ | ||
public static boolean freezeMob(Mob mob) { | ||
if (mob == null || frozenMobs.containsKey(mob.getUUID())) { | ||
return false; | ||
} | ||
|
||
// Store current AI state | ||
frozenMobs.put(mob.getUUID(), mob.isNoAi()); | ||
|
||
// Disable AI | ||
mob.setNoAi(true); | ||
|
||
// Stop all current goals | ||
// mob.goalSelector.removeAllGoals(); | ||
// mob.targetSelector.removeAllGoals(); | ||
|
||
// Freeze movement speed | ||
mob.getAttribute(Attributes.MOVEMENT_SPEED).addTransientModifier( | ||
new AttributeModifier(MOVEMENT_SPEED_MODIFIER, "Freeze movement", -1.0D, AttributeModifier.Operation.MULTIPLY_TOTAL) | ||
); | ||
|
||
// Stop any current movement/path | ||
mob.getNavigation().stop(); | ||
mob.setDeltaMovement(0, mob.getDeltaMovement().y, 0); // Preserve Y movement for gravity | ||
|
||
return true; | ||
} | ||
|
||
/** | ||
* Freezes a mob by UUID if it exists in the world | ||
* @param level The server level to search in | ||
* @param uuid The UUID of the mob to freeze | ||
* @return true if the mob was found and frozen | ||
*/ | ||
public static boolean freezeMobByUUID(ServerLevel level, UUID uuid) { | ||
if (level.getEntity(uuid) instanceof Mob mob) { | ||
return freezeMob(mob); | ||
} | ||
return false; | ||
} | ||
|
||
/** | ||
* Unfreezes a previously frozen mob | ||
* @param mob The mob to unfreeze | ||
* @return true if the mob was unfrozen, false if it wasn't frozen | ||
*/ | ||
public static boolean unfreezeMob(Mob mob) { | ||
if (mob == null || !frozenMobs.containsKey(mob.getUUID())) { | ||
return false; | ||
} | ||
|
||
// Restore original AI state | ||
mob.setNoAi(frozenMobs.remove(mob.getUUID())); | ||
|
||
// Remove movement speed modifier | ||
mob.getAttribute(Attributes.MOVEMENT_SPEED) | ||
.removeModifier(MOVEMENT_SPEED_MODIFIER); | ||
|
||
// The mob's AI goals will be reinstated automatically when needed | ||
return true; | ||
} | ||
|
||
/** | ||
* Unfreezes a mob by UUID if it exists in the world | ||
* @param level The server level to search in | ||
* @param uuid The UUID of the mob to unfreeze | ||
* @return true if the mob was found and unfrozen | ||
*/ | ||
public static boolean unfreezeMobByUUID(ServerLevel level, UUID uuid) { | ||
if (level.getEntity(uuid) instanceof Mob mob) { | ||
return unfreezeMob(mob); | ||
} | ||
return false; | ||
} | ||
|
||
/** | ||
* Checks if a mob is currently frozen | ||
*/ | ||
public static boolean isFrozen(UUID uuid) { | ||
return frozenMobs.containsKey(uuid); | ||
} | ||
} |
110 changes: 110 additions & 0 deletions
110
src/main/java/org/arsparadox/mobtalkerredux/command/TeamHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package org.arsparadox.mobtalkerredux.command; | ||
|
||
import net.minecraft.world.entity.Entity; | ||
import net.minecraft.world.entity.player.Player; | ||
import net.minecraft.world.scores.PlayerTeam; | ||
import net.minecraft.world.scores.Scoreboard; | ||
import net.minecraft.world.scores.Team; | ||
import net.minecraft.server.level.ServerLevel; | ||
|
||
public class TeamHandler { | ||
public static final String DEFAULT_TEAM_NAME = "harem_mobs"; | ||
|
||
/** | ||
* Creates a team if it doesn't exist | ||
*/ | ||
public static PlayerTeam getOrCreateTeam(ServerLevel level, String teamName) { | ||
Scoreboard scoreboard = level.getScoreboard(); | ||
PlayerTeam team = scoreboard.getPlayerTeam(teamName); | ||
|
||
if (team == null) { | ||
team = scoreboard.addPlayerTeam(teamName); | ||
setupTeamDefaults(team); | ||
} | ||
|
||
return team; | ||
} | ||
|
||
/** | ||
* Sets up default team options | ||
*/ | ||
private static void setupTeamDefaults(PlayerTeam team) { | ||
team.setSeeFriendlyInvisibles(true); | ||
team.setAllowFriendlyFire(false); | ||
team.setCollisionRule(Team.CollisionRule.NEVER); | ||
} | ||
|
||
/** | ||
* Adds an entity to the same team as a player | ||
*/ | ||
public static void addToPlayerTeam(Player player, Entity entity) { | ||
if (player.level().isClientSide()) return; | ||
|
||
ServerLevel level = (ServerLevel) player.level(); | ||
Scoreboard scoreboard = level.getScoreboard(); | ||
|
||
String teamName = getPlayerTeamName(player); | ||
if (teamName == null) { | ||
teamName = DEFAULT_TEAM_NAME; | ||
PlayerTeam team = getOrCreateTeam(level, teamName); | ||
scoreboard.addPlayerToTeam(player.getScoreboardName(), team); | ||
} | ||
|
||
scoreboard.addPlayerToTeam(entity.getScoreboardName(), scoreboard.getPlayerTeam(teamName)); | ||
} | ||
|
||
/** | ||
* Adds an entity to a specific team | ||
*/ | ||
public static void addToTeam(ServerLevel level, Entity entity, String teamName) { | ||
PlayerTeam team = getOrCreateTeam(level, teamName); | ||
level.getScoreboard().addPlayerToTeam(entity.getScoreboardName(), team); | ||
} | ||
|
||
/** | ||
* Removes an entity from its team | ||
*/ | ||
public static void removeFromTeam(Entity entity) { | ||
if (entity.level().isClientSide()) return; | ||
|
||
ServerLevel level = (ServerLevel) entity.level(); | ||
Scoreboard scoreboard = level.getScoreboard(); | ||
scoreboard.removePlayerFromTeam(entity.getScoreboardName()); | ||
} | ||
|
||
/** | ||
* Checks if an entity is in any team | ||
*/ | ||
public static boolean isInAnyTeam(Entity entity) { | ||
if (entity.level().isClientSide()) return false; | ||
|
||
ServerLevel level = (ServerLevel) entity.level(); | ||
return level.getScoreboard().getPlayersTeam(entity.getScoreboardName()) != null; | ||
} | ||
|
||
/** | ||
* Checks if two entities are in the same team | ||
*/ | ||
public static boolean areInSameTeam(Entity entity1, Entity entity2) { | ||
if (entity1.level().isClientSide()) return false; | ||
|
||
ServerLevel level = (ServerLevel) entity1.level(); | ||
Scoreboard scoreboard = level.getScoreboard(); | ||
|
||
PlayerTeam team1 = scoreboard.getPlayersTeam(entity1.getScoreboardName()); | ||
PlayerTeam team2 = scoreboard.getPlayersTeam(entity2.getScoreboardName()); | ||
|
||
return team1 != null && team1 == team2; | ||
} | ||
|
||
/** | ||
* Gets the name of the team a player is in | ||
*/ | ||
public static String getPlayerTeamName(Player player) { | ||
if (player.level().isClientSide()) return null; | ||
|
||
ServerLevel level = (ServerLevel) player.level(); | ||
PlayerTeam team = level.getScoreboard().getPlayersTeam(player.getScoreboardName()); | ||
return team != null ? team.getName() : null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters