feat: TU19 (Dec 2014) Features & Content (#155)
* try to resolve merge conflict
* feat: TU19 (Dec 2014) Features & Content (#32)
* December 2014 files
* Working release build
* Fix compilation issues
* Add sound to Windows64Media
* Add DLC content and force Tutorial DLC
* Revert "Add DLC content and force Tutorial DLC"
This reverts commit 97a4399472.
* Disable broken light packing
* Disable breakpoint during DLC texture map load
Allows DLC loading but the DLC textures are still broken
* Fix post build not working
* ...
* fix vs2022 build
* fix cmake build
---------
Co-authored-by: Loki <lokirautio@gmail.com>
This commit is contained in:
328
Minecraft.World/SpreadPlayersCommand.h
Normal file
328
Minecraft.World/SpreadPlayersCommand.h
Normal file
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
package net.minecraft.commands.common;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import net.minecraft.commands.*;
|
||||
import net.minecraft.commands.exceptions.*;
|
||||
import net.minecraft.network.chat.ChatMessageComponent;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
import net.minecraft.world.level.tile.Tile;
|
||||
import net.minecraft.world.scores.Team;
|
||||
|
||||
import com.google.common.collect.*;
|
||||
|
||||
public class SpreadPlayersCommand extends BaseCommand {
|
||||
private static final int MAX_ITERATION_COUNT = 10000;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "spreadplayers";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPermissionLevel() {
|
||||
return LEVEL_GAMEMASTERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsage(CommandSender source) {
|
||||
return "commands.spreadplayers.usage";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(CommandSender source, String[] args) {
|
||||
if (args.length < 6) throw new UsageException("commands.spreadplayers.usage");
|
||||
int index = 0;
|
||||
double x = convertArgToCoordinate(source, Double.NaN, args[index++]);
|
||||
double z = convertArgToCoordinate(source, Double.NaN, args[index++]);
|
||||
double minDist = convertArgToDouble(source, args[index++], 0);
|
||||
double maxDist = convertArgToDouble(source, args[index++], minDist + 1);
|
||||
boolean respectTeams = convertArgToBoolean(source, args[index++]);
|
||||
|
||||
List<LivingEntity> players = Lists.newArrayList();
|
||||
|
||||
while (index < args.length) {
|
||||
String arg = args[index++];
|
||||
|
||||
if (PlayerSelector.isPattern(arg)) {
|
||||
ServerPlayer[] result = PlayerSelector.getPlayers(source, arg);
|
||||
|
||||
if (result != null && result.length != 0) {
|
||||
Collections.addAll(players, result);
|
||||
} else {
|
||||
throw new PlayerNotFoundException();
|
||||
}
|
||||
} else {
|
||||
Player player = MinecraftServer.getInstance().getPlayers().getPlayer(arg);
|
||||
|
||||
if (player != null) {
|
||||
players.add(player);
|
||||
} else {
|
||||
throw new PlayerNotFoundException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (players.isEmpty()) {
|
||||
throw new PlayerNotFoundException();
|
||||
}
|
||||
|
||||
source.sendMessage(ChatMessageComponent.forTranslation("commands.spreadplayers.spreading." + (respectTeams ? "teams" : "players"), joinPlayerNames(players), x, z, minDist, maxDist));
|
||||
|
||||
spreadPlayers(source, players, new Position(x, z), minDist, maxDist, players.get(0).level, respectTeams);
|
||||
}
|
||||
|
||||
private void spreadPlayers(CommandSender source, List<LivingEntity> players, Position center, double spreadDist, double maxDistFromCenter, Level level, boolean respectTeams) {
|
||||
Random random = new Random();
|
||||
double minX = center.x - maxDistFromCenter;
|
||||
double minZ = center.z - maxDistFromCenter;
|
||||
double maxX = center.x + maxDistFromCenter;
|
||||
double maxZ = center.z + maxDistFromCenter;
|
||||
|
||||
Position[] positions = createInitialPositions(random, respectTeams ? getNumberOfTeams(players) : players.size(), minX, minZ, maxX, maxZ);
|
||||
int iterations = spreadPositions(center, spreadDist, level, random, minX, minZ, maxX, maxZ, positions, respectTeams);
|
||||
double avgDistance = setPlayerPositions(players, level, positions, respectTeams);
|
||||
|
||||
logAdminAction(source, "commands.spreadplayers.success." + (respectTeams ? "teams" : "players"), positions.length, center.x, center.z);
|
||||
if (positions.length > 1) source.sendMessage(ChatMessageComponent.forTranslation("commands.spreadplayers.info." + (respectTeams ? "teams" : "players"), String.format("%.2f", avgDistance),
|
||||
iterations));
|
||||
}
|
||||
|
||||
private int getNumberOfTeams(List<LivingEntity> players) {
|
||||
Set<Team> teams = Sets.newHashSet();
|
||||
|
||||
for (LivingEntity player : players) {
|
||||
if (player instanceof Player) {
|
||||
teams.add(((Player) player).getTeam());
|
||||
} else {
|
||||
teams.add(null);
|
||||
}
|
||||
}
|
||||
|
||||
return teams.size();
|
||||
}
|
||||
|
||||
private int spreadPositions(Position center, double spreadDist, Level level, Random random, double minX, double minZ, double maxX, double maxZ, Position[] positions, boolean respectTeams) {
|
||||
boolean hasCollisions = true;
|
||||
int iteration;
|
||||
double minDistance = Float.MAX_VALUE;
|
||||
|
||||
for (iteration = 0; iteration < MAX_ITERATION_COUNT && hasCollisions; iteration++) {
|
||||
hasCollisions = false;
|
||||
minDistance = Float.MAX_VALUE;
|
||||
|
||||
for (int i = 0; i < positions.length; i++) {
|
||||
Position position = positions[i];
|
||||
int neighbourCount = 0;
|
||||
Position averageNeighbourPos = new Position();
|
||||
|
||||
for (int j = 0; j < positions.length; j++) {
|
||||
if (i == j) continue;
|
||||
Position neighbour = positions[j];
|
||||
|
||||
double dist = position.dist(neighbour);
|
||||
minDistance = Math.min(dist, minDistance);
|
||||
if (dist < spreadDist) {
|
||||
neighbourCount++;
|
||||
averageNeighbourPos.x += neighbour.x - position.x;
|
||||
averageNeighbourPos.z += neighbour.z - position.z;
|
||||
}
|
||||
}
|
||||
|
||||
if (neighbourCount > 0) {
|
||||
averageNeighbourPos.x /= neighbourCount;
|
||||
averageNeighbourPos.z /= neighbourCount;
|
||||
double length = averageNeighbourPos.getLength();
|
||||
|
||||
if (length > 0) {
|
||||
averageNeighbourPos.normalize();
|
||||
|
||||
position.moveAway(averageNeighbourPos);
|
||||
} else {
|
||||
position.randomize(random, minX, minZ, maxX, maxZ);
|
||||
}
|
||||
|
||||
hasCollisions = true;
|
||||
}
|
||||
|
||||
if (position.clamp(minX, minZ, maxX, maxZ)) {
|
||||
hasCollisions = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasCollisions) {
|
||||
for (Position position : positions) {
|
||||
if (!position.isSafe(level)) {
|
||||
position.randomize(random, minX, minZ, maxX, maxZ);
|
||||
hasCollisions = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (iteration >= MAX_ITERATION_COUNT) {
|
||||
throw new CommandException("commands.spreadplayers.failure." + (respectTeams ? "teams" : "players"), positions.length, center.x, center.z, String.format("%.2f", minDistance));
|
||||
}
|
||||
|
||||
return iteration;
|
||||
}
|
||||
|
||||
private double setPlayerPositions(List<LivingEntity> players, Level level, Position[] positions, boolean respectTeams) {
|
||||
double avgDistance = 0;
|
||||
int positionIndex = 0;
|
||||
Map<Team, Position> teamPositions = Maps.newHashMap();
|
||||
|
||||
for (int i = 0; i < players.size(); i++) {
|
||||
LivingEntity player = players.get(i);
|
||||
Position position;
|
||||
|
||||
if (respectTeams) {
|
||||
Team team = player instanceof Player ? ((Player) player).getTeam() : null;
|
||||
|
||||
if (!teamPositions.containsKey(team)) {
|
||||
teamPositions.put(team, positions[positionIndex++]);
|
||||
}
|
||||
|
||||
position = teamPositions.get(team);
|
||||
} else {
|
||||
position = positions[positionIndex++];
|
||||
}
|
||||
|
||||
player.teleportTo(Mth.floor(position.x) + 0.5f, position.getSpawnY(level), Mth.floor(position.z) + 0.5);
|
||||
|
||||
double closest = Double.MAX_VALUE;
|
||||
for (int j = 0; j < positions.length; j++) {
|
||||
if (position == positions[j]) continue;
|
||||
|
||||
double dist = position.dist(positions[j]);
|
||||
closest = Math.min(dist, closest);
|
||||
}
|
||||
avgDistance += closest;
|
||||
}
|
||||
|
||||
avgDistance /= players.size();
|
||||
return avgDistance;
|
||||
}
|
||||
|
||||
private Position[] createInitialPositions(Random random, int count, double minX, double minZ, double maxX, double maxZ) {
|
||||
Position[] result = new Position[count];
|
||||
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
Position position = new Position();
|
||||
|
||||
position.randomize(random, minX, minZ, maxX, maxZ);
|
||||
|
||||
result[i] = position;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class Position {
|
||||
double x;
|
||||
double z;
|
||||
|
||||
Position() {
|
||||
}
|
||||
|
||||
Position(double x, double z) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
void set(double x, double z) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
double dist(Position target) {
|
||||
double dx = x - target.x;
|
||||
double dz = z - target.z;
|
||||
|
||||
return Math.sqrt(dx * dx + dz * dz);
|
||||
}
|
||||
|
||||
void normalize() {
|
||||
double dist = (double) getLength();
|
||||
x /= dist;
|
||||
z /= dist;
|
||||
}
|
||||
|
||||
float getLength() {
|
||||
return Mth.sqrt(x * x + z * z);
|
||||
}
|
||||
|
||||
public void moveAway(Position pos) {
|
||||
x -= pos.x;
|
||||
z -= pos.z;
|
||||
}
|
||||
|
||||
public boolean clamp(double minX, double minZ, double maxX, double maxZ) {
|
||||
boolean changed = false;
|
||||
|
||||
if (x < minX) {
|
||||
x = minX;
|
||||
changed = true;
|
||||
} else if (x > maxX) {
|
||||
x = maxX;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (z < minZ) {
|
||||
z = minZ;
|
||||
changed = true;
|
||||
} else if (z > maxZ) {
|
||||
z = maxZ;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
public int getSpawnY(Level level) {
|
||||
int xt = Mth.floor(x);
|
||||
int zt = Mth.floor(z);
|
||||
|
||||
for (int y = Level.maxBuildHeight; y > 0; y--) {
|
||||
int tile = level.getTile(xt, y, zt);
|
||||
|
||||
if (tile != 0) {
|
||||
return y + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return Level.maxBuildHeight + 1;
|
||||
}
|
||||
|
||||
public boolean isSafe(Level level) {
|
||||
int xt = Mth.floor(x);
|
||||
int zt = Mth.floor(z);
|
||||
|
||||
for (int y = Level.maxBuildHeight; y > 0; y--) {
|
||||
int tile = level.getTile(xt, y, zt);
|
||||
|
||||
if (tile != 0) {
|
||||
Material material = Tile.tiles[tile].material;
|
||||
|
||||
return !material.isLiquid() && material != Material.fire;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void randomize(Random random, double minX, double minZ, double maxX, double maxZ) {
|
||||
x = Mth.nextDouble(random, minX, maxX);
|
||||
z = Mth.nextDouble(random, minZ, maxZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
Reference in New Issue
Block a user