Merge branch 'master' into mapping

This commit is contained in:
Howard Stark 2018-08-21 18:05:33 -07:00
commit 9bbb89f616
No known key found for this signature in database
GPG Key ID: 9FA4E350B33067F3
31 changed files with 474 additions and 202 deletions

View File

@ -133,7 +133,22 @@ public class Settings {
* 3 won't deal any damage. But if you just want to get down the mountain quickly and you have
* Feather Falling IV, you might set it a bit higher, like 4 or 5.
*/
public Setting<Integer> maxFallHeight = new Setting<>(3);
public Setting<Integer> maxFallHeightNoWater = new Setting<>(3);
/**
* How far are you allowed to fall onto solid ground (with a water bucket)?
* It's not that reliable, so I've set it below what would kill an unarmored player (23)
*/
public Setting<Integer> maxFallHeightBucket = new Setting<>(20);
/**
* If your goal is a GoalBlock in an unloaded chunk, assume it's far enough away that the Y coord
* doesn't matter yet, and replace it with a GoalXZ to the same place before calculating a path.
* Once a segment ends within chunk load range of the GoalBlock, it will go back to normal behavior
* of considering the Y coord. The reasoning is that if your X and Z are 10,000 blocks away,
* your Y coordinate's accuracy doesn't matter at all until you get much much closer.
*/
public Setting<Boolean> simplifyUnloadedYCoord = new Setting<>(true);
/**
* If a movement takes this many ticks more than its initial cost estimate, cancel it
@ -163,7 +178,7 @@ public class Settings {
/**
* The big one. Download all chunks in simplified 2-bit format and save them for better very-long-distance pathing.
*/
public Setting<Boolean> chuckCaching = new Setting<>(false);
public Setting<Boolean> chunkCaching = new Setting<>(true);
/**
* Print all the debug messages to chat
@ -202,6 +217,11 @@ public class Settings {
*/
public Setting<Boolean> fadePath = new Setting<>(false);
/**
* Move without having to force the client-sided rotations
*/
public Setting<Boolean> freeLook = new Setting<>(true);
public final Map<String, Setting<?>> byLowerName;
public final List<Setting<?>> allSettings;
@ -210,6 +230,7 @@ public class Settings {
private String name;
private final Class<T> klass;
@SuppressWarnings("unchecked")
private Setting(T value) {
if (value == null) {
throw new IllegalArgumentException("Cannot determine value type class from null");
@ -218,6 +239,7 @@ public class Settings {
this.klass = (Class<T>) value.getClass();
}
@SuppressWarnings("unchecked")
public final <K extends T> K get() {
return (K) value;
}
@ -244,7 +266,7 @@ public class Settings {
try {
for (Field field : temp) {
if (field.getType().equals(Setting.class)) {
Setting<?> setting = (Setting<? extends Object>) field.get(this);
Setting<?> setting = (Setting<?>) field.get(this);
String name = field.getName();
setting.name = name;
name = name.toLowerCase();
@ -262,6 +284,7 @@ public class Settings {
allSettings = Collections.unmodifiableList(tmpAll);
}
@SuppressWarnings("unchecked")
public <T> List<Setting<T>> getByValueType(Class<T> klass) {
ArrayList<Setting<T>> result = new ArrayList<>();
for (Setting<?> setting : allSettings) {

View File

@ -17,7 +17,12 @@
package baritone.bot.behavior.impl;
import baritone.bot.Baritone;
import baritone.bot.Settings;
import baritone.bot.behavior.Behavior;
import baritone.bot.event.events.PlayerUpdateEvent;
import baritone.bot.event.events.RelativeMoveEvent;
import baritone.bot.event.events.type.EventState;
import baritone.bot.utils.Rotation;
public class LookBehavior extends Behavior {
@ -34,21 +39,50 @@ public class LookBehavior extends Behavior {
*/
private Rotation target;
public void updateTarget(Rotation target) {
/**
* Whether or not rotations are currently being forced
*/
private boolean force;
/**
* The last player yaw angle. Used when free looking
*
* @see Settings#freeLook
*/
private float lastYaw;
public void updateTarget(Rotation target, boolean force) {
this.target = target;
this.force = force || !Baritone.settings().freeLook.get();
}
@Override
public void onPlayerUpdate() {
if (target != null) {
player().rotationYaw = target.getFirst();
public void onPlayerUpdate(PlayerUpdateEvent event) {
if (event.getState() == EventState.PRE && this.target != null && this.force) {
player().rotationYaw = this.target.getFirst();
float oldPitch = player().rotationPitch;
float desiredPitch = target.getSecond();
float desiredPitch = this.target.getSecond();
player().rotationPitch = desiredPitch;
if (desiredPitch == oldPitch) {
nudgeToLevel();
}
target = null;
this.target = null;
}
}
@Override
public void onPlayerRelativeMove(RelativeMoveEvent event) {
if (this.target != null && !force) {
switch (event.getState()) {
case PRE:
this.lastYaw = player().rotationYaw;
player().rotationYaw = this.target.getFirst();
break;
case POST:
player().rotationYaw = this.lastYaw;
this.target = null;
break;
}
}
}

View File

@ -2,6 +2,8 @@ package baritone.bot.behavior.impl;
import baritone.bot.behavior.Behavior;
import baritone.bot.event.events.PacketEvent;
import baritone.bot.event.events.PlayerUpdateEvent;
import baritone.bot.event.events.type.EventState;
import net.minecraft.item.ItemStack;
import net.minecraft.network.Packet;
import net.minecraft.network.play.client.CPacketCloseWindow;
@ -35,8 +37,9 @@ public class MemoryBehavior extends Behavior {
private final Map<BlockPos, RememberedInventory> rememberedInventories = new HashMap<>();
@Override
public void onPlayerUpdate() {
updateInventory();
public void onPlayerUpdate(PlayerUpdateEvent event) {
if (event.getState() == EventState.PRE)
updateInventory();
}
@Override

View File

@ -19,18 +19,22 @@ package baritone.bot.behavior.impl;
import baritone.bot.Baritone;
import baritone.bot.behavior.Behavior;
import baritone.bot.event.events.PlayerUpdateEvent;
import baritone.bot.event.events.RenderEvent;
import baritone.bot.event.events.TickEvent;
import baritone.bot.pathing.calc.AStarPathFinder;
import baritone.bot.pathing.calc.AbstractNodeCostSearch;
import baritone.bot.pathing.calc.IPathFinder;
import baritone.bot.pathing.goals.Goal;
import baritone.bot.pathing.goals.GoalBlock;
import baritone.bot.pathing.goals.GoalXZ;
import baritone.bot.pathing.path.IPath;
import baritone.bot.pathing.path.PathExecutor;
import baritone.bot.utils.BlockStateInterface;
import baritone.bot.utils.PathRenderer;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.EmptyChunk;
import java.awt.*;
import java.util.Collections;
@ -53,11 +57,12 @@ public class PathingBehavior extends Behavior {
private final Object pathPlanLock = new Object();
private boolean lastAutoJump;
@Override
public void onTick(TickEvent event) {
if (event.getType() == TickEvent.Type.OUT) {
current = null;
next = null;
this.cancel();
return;
}
if (current == null) {
@ -133,6 +138,21 @@ public class PathingBehavior extends Behavior {
}
}
@Override
public void onPlayerUpdate(PlayerUpdateEvent event) {
if (current != null) {
switch (event.getState()) {
case PRE:
lastAutoJump = mc.gameSettings.autoJump;
mc.gameSettings.autoJump = false;
break;
case POST:
mc.gameSettings.autoJump = lastAutoJump;
break;
}
}
}
public Optional<Double> ticksRemainingInSegment() {
if (current == null) {
return Optional.empty();
@ -148,7 +168,9 @@ public class PathingBehavior extends Behavior {
return current;
}
public PathExecutor getNext() {return next;}
public PathExecutor getNext() {
return next;
}
public Optional<IPath> getPath() {
return Optional.ofNullable(current).map(PathExecutor::getPath);
@ -239,10 +261,18 @@ public class PathingBehavior extends Behavior {
* @return
*/
private Optional<IPath> findPath(BlockPos start, Optional<IPath> previous) {
Goal goal = this.goal;
if (goal == null) {
displayChatMessageRaw("no goal");
return Optional.empty();
}
if (Baritone.settings().simplifyUnloadedYCoord.get() && goal instanceof GoalBlock) {
BlockPos pos = ((GoalBlock) goal).getGoalPos();
if (world().getChunk(pos) instanceof EmptyChunk) {
displayChatMessageRaw("Simplifying GoalBlock to GoalXZ due to distance");
goal = new GoalXZ(pos.getX(), pos.getZ());
}
}
try {
IPathFinder pf = new AStarPathFinder(start, goal, previous.map(IPath::positions));
return pf.calculate();

View File

@ -40,11 +40,6 @@ public final class CachedChunk implements IBlockTypeAccess {
*/
public static final int SIZE_IN_BYTES = SIZE / 8;
/**
* An array of just 0s with the length of {@link CachedChunk#SIZE_IN_BYTES}
*/
public static final byte[] EMPTY_CHUNK = new byte[SIZE_IN_BYTES];
/**
* The chunk x coordinate
*/

View File

@ -17,25 +17,30 @@
package baritone.bot.chunk;
import baritone.bot.utils.pathing.IBlockTypeAccess;
import baritone.bot.utils.pathing.PathingBlockType;
import baritone.bot.utils.GZIPUtils;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.BitSet;
import java.util.function.Consumer;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
/**
* @author Brady
* @since 8/3/2018 9:35 PM
*/
public final class CachedRegion implements ICachedChunkAccess {
public final class CachedRegion implements IBlockTypeAccess {
private static final byte CHUNK_NOT_PRESENT = 0;
private static final byte CHUNK_PRESENT = 1;
/**
* Magic value to detect invalid cache files, or incompatible cache files saved in an old version of Baritone
*/
private static final int CACHED_REGION_MAGIC = 456022910;
/**
* All of the chunks in this region: A 32x32 array of them.
@ -52,9 +57,15 @@ public final class CachedRegion implements ICachedChunkAccess {
*/
private final int z;
/**
* Has this region been modified since its most recent load or save
*/
private boolean hasUnsavedChanges;
CachedRegion(int x, int z) {
this.x = x;
this.z = z;
this.hasUnsavedChanges = false;
}
@Override
@ -66,14 +77,14 @@ public final class CachedRegion implements ICachedChunkAccess {
return null;
}
@Override
public final void updateCachedChunk(int chunkX, int chunkZ, BitSet data) {
final void updateCachedChunk(int chunkX, int chunkZ, BitSet data) {
CachedChunk chunk = this.getChunk(chunkX, chunkZ);
if (chunk == null) {
this.chunks[chunkX][chunkZ] = new CachedChunk(chunkX, chunkZ, data);
} else {
chunk.updateContents(data);
}
hasUnsavedChanges = true;
}
private CachedChunk getChunk(int chunkX, int chunkZ) {
@ -92,21 +103,31 @@ public final class CachedRegion implements ICachedChunkAccess {
}
public final void save(String directory) {
if (!hasUnsavedChanges) {
return;
}
try {
Path path = Paths.get(directory);
if (!Files.exists(path))
Files.createDirectories(path);
System.out.println("Saving region " + x + "," + z + " to disk " + path);
Path regionFile = getRegionFile(path, this.x, this.z);
if (!Files.exists(regionFile))
Files.createFile(regionFile);
try (FileOutputStream fileOut = new FileOutputStream(regionFile.toFile()); GZIPOutputStream out = new GZIPOutputStream(fileOut)) {
try (
FileOutputStream fileOut = new FileOutputStream(regionFile.toFile());
GZIPOutputStream gzipOut = new GZIPOutputStream(fileOut);
DataOutputStream out = new DataOutputStream(gzipOut);
) {
out.writeInt(CACHED_REGION_MAGIC);
for (int z = 0; z < 32; z++) {
for (int x = 0; x < 32; x++) {
CachedChunk chunk = this.chunks[x][z];
if (chunk == null) {
out.write(CachedChunk.EMPTY_CHUNK);
out.write(CHUNK_NOT_PRESENT);
} else {
out.write(CHUNK_PRESENT);
byte[] chunkBytes = chunk.toByteArray();
out.write(chunkBytes);
// Messy, but fills the empty 0s that should be trailing to fill up the space.
@ -114,8 +135,13 @@ public final class CachedRegion implements ICachedChunkAccess {
}
}
}
out.writeInt(~CACHED_REGION_MAGIC);
}
} catch (IOException ignored) {}
hasUnsavedChanges = false;
System.out.println("Saved region successfully");
} catch (IOException ex) {
ex.printStackTrace();
}
}
public void load(String directory) {
@ -128,27 +154,48 @@ public final class CachedRegion implements ICachedChunkAccess {
if (!Files.exists(regionFile))
return;
byte[] decompressed;
try (FileInputStream in = new FileInputStream(regionFile.toFile())) {
decompressed = GZIPUtils.decompress(in);
}
System.out.println("Loading region " + x + "," + z + " from disk " + path);
if (decompressed == null)
return;
for (int z = 0; z < 32; z++) {
for (int x = 0; x < 32; x++) {
int index = (x + (z << 5)) * CachedChunk.SIZE_IN_BYTES;
byte[] bytes = Arrays.copyOfRange(decompressed, index, index + CachedChunk.SIZE_IN_BYTES);
if (isAllZeros(bytes)) {
this.chunks[x][z] = null;
} else {
BitSet bits = BitSet.valueOf(bytes);
updateCachedChunk(x, z, bits);
try (
FileInputStream fileIn = new FileInputStream(regionFile.toFile());
GZIPInputStream gzipIn = new GZIPInputStream(fileIn);
DataInputStream in = new DataInputStream(gzipIn);
) {
int magic = in.readInt();
if (magic != CACHED_REGION_MAGIC) {
// in the future, if we change the format on disk
// we can keep converters for the old format
// by switching on the magic value, and either loading it normally, or loading through a converter.
throw new IOException("Bad magic value " + magic);
}
for (int z = 0; z < 32; z++) {
for (int x = 0; x < 32; x++) {
int isChunkPresent = in.read();
switch (isChunkPresent) {
case CHUNK_PRESENT:
byte[] bytes = new byte[CachedChunk.SIZE_IN_BYTES];
in.readFully(bytes);
BitSet bits = BitSet.valueOf(bytes);
updateCachedChunk(x, z, bits);
break;
case CHUNK_NOT_PRESENT:
this.chunks[x][z] = null;
break;
default:
throw new IOException("Malformed stream");
}
}
}
int fileEndMagic = in.readInt();
if (fileEndMagic != ~magic) {
throw new IOException("Bad end of file magic");
}
}
} catch (IOException ignored) {}
hasUnsavedChanges = false;
System.out.println("Loaded region successfully");
} catch (IOException ex) {
ex.printStackTrace();
}
}
private static boolean isAllZeros(final byte[] array) {

View File

@ -17,18 +17,21 @@
package baritone.bot.chunk;
import baritone.bot.utils.pathing.IBlockTypeAccess;
import baritone.bot.utils.pathing.PathingBlockType;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import net.minecraft.world.chunk.Chunk;
import java.util.BitSet;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.Consumer;
/**
* @author Brady
* @since 8/4/2018 12:02 AM
*/
public final class CachedWorld implements ICachedChunkAccess {
public final class CachedWorld implements IBlockTypeAccess {
/**
* The maximum number of regions in any direction from (0,0)
@ -45,41 +48,42 @@ public final class CachedWorld implements ICachedChunkAccess {
*/
private final String directory;
private final LinkedBlockingQueue<Chunk> toPack = new LinkedBlockingQueue<>();
public CachedWorld(String directory) {
this.directory = directory;
// Insert an invalid region element
cachedRegions.put(0, null);
new PackerThread().start();
}
public final void queueForPacking(Chunk chunk) {
try {
toPack.put(chunk);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public final PathingBlockType getBlockType(int x, int y, int z) {
CachedRegion region = getRegion(x >> 9, z >> 9);
if (region != null) {
return region.getBlockType(x & 511, y, z & 511);
}
return null;
CachedRegion region = getOrCreateRegion(x >> 9, z >> 9);
return region.getBlockType(x & 511, y, z & 511);
}
@Override
public final void updateCachedChunk(int chunkX, int chunkZ, BitSet data) {
private void updateCachedChunk(int chunkX, int chunkZ, BitSet data) {
CachedRegion region = getOrCreateRegion(chunkX >> 5, chunkZ >> 5);
if (region != null) {
region.updateCachedChunk(chunkX & 31, chunkZ & 31, data);
}
region.updateCachedChunk(chunkX & 31, chunkZ & 31, data);
}
public final void save() {
long start = System.currentTimeMillis();
this.cachedRegions.values().forEach(region -> {
if (region != null)
region.save(this.directory);
});
}
public final void load() {
this.cachedRegions.values().forEach(region -> {
if (region != null)
region.load(this.directory);
});
long now = System.currentTimeMillis();
System.out.println("World save took " + (now - start) + "ms");
}
/**
@ -141,4 +145,24 @@ public final class CachedWorld implements ICachedChunkAccess {
private boolean isRegionInWorld(int regionX, int regionZ) {
return regionX <= REGION_MAX && regionX >= -REGION_MAX && regionZ <= REGION_MAX && regionZ >= -REGION_MAX;
}
private class PackerThread extends Thread {
public void run() {
while (true) {
LinkedBlockingQueue<Chunk> queue = toPack;
if (queue == null) {
break;
}
try {
Chunk chunk = queue.take();
BitSet packed = ChunkPacker.createPackedChunk(chunk);
CachedWorld.this.updateCachedChunk(chunk.x, chunk.z, packed);
//System.out.println("Processed chunk at " + chunk.x + "," + chunk.z);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
}
}

View File

@ -31,8 +31,6 @@ import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Brady
@ -42,8 +40,6 @@ public enum CachedWorldProvider implements Helper {
INSTANCE;
private static final Pattern REGION_REGEX = Pattern.compile("r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.bcr");
private final Map<String, CachedWorld> singlePlayerWorldCache = new HashMap<>();
private CachedWorld currentWorld;
@ -68,27 +64,22 @@ public enum CachedWorldProvider implements Helper {
}
this.currentWorld = this.singlePlayerWorldCache.computeIfAbsent(dir.toString(), CachedWorld::new);
try {
Files.list(dir).forEach(path -> {
String file = path.getFileName().toString();
Matcher matcher = REGION_REGEX.matcher(file);
if (matcher.matches()) {
int rx = Integer.parseInt(matcher.group(1));
int ry = Integer.parseInt(matcher.group(2));
// Recognize the region for when we load from file
this.currentWorld.getOrCreateRegion(rx, ry);
}
});
} catch (Exception ignored) {}
this.currentWorld.load();
}
// TODO: Store server worlds
}
public final void closeWorld() {
CachedWorld world = this.currentWorld;
this.currentWorld = null;
if (world == null) {
return;
}
new Thread() {
public void run() {
System.out.println("Started saving the world in a new thread");
world.save();
}
}.start();
}
public final void ifWorldLoaded(Consumer<CachedWorld> currentWorldConsumer) {

View File

@ -18,9 +18,9 @@
package baritone.bot.chunk;
import baritone.bot.pathing.movement.MovementHelper;
import baritone.bot.utils.pathing.PathingBlockType;
import baritone.bot.utils.BlockStateInterface;
import baritone.bot.utils.Helper;
import baritone.bot.utils.pathing.PathingBlockType;
import net.minecraft.block.Block;
import net.minecraft.block.BlockAir;
import net.minecraft.block.state.IBlockState;
@ -29,8 +29,6 @@ import net.minecraft.world.chunk.Chunk;
import java.util.BitSet;
import static net.minecraft.block.Block.NULL_AABB;
/**
* @author Brady
* @since 8/3/2018 1:09 AM
@ -40,6 +38,7 @@ public final class ChunkPacker implements Helper {
private ChunkPacker() {}
public static BitSet createPackedChunk(Chunk chunk) {
long start = System.currentTimeMillis();
BitSet bitSet = new BitSet(CachedChunk.SIZE);
try {
for (int y = 0; y < 256; y++) {
@ -55,6 +54,8 @@ public final class ChunkPacker implements Helper {
} catch (Exception e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
//System.out.println("Chunk packing took " + (end - start) + "ms for " + chunk.x + "," + chunk.z);
return bitSet;
}
@ -69,7 +70,7 @@ public final class ChunkPacker implements Helper {
return PathingBlockType.AVOID;
}
if (block instanceof BlockAir || state.getCollisionBoundingBox(mc.world, pos) == NULL_AABB) {
if (block instanceof BlockAir) {
return PathingBlockType.AIR;
}

View File

@ -35,9 +35,7 @@
package baritone.bot.event;
import baritone.bot.Baritone;
import baritone.bot.chunk.CachedWorld;
import baritone.bot.chunk.CachedWorldProvider;
import baritone.bot.chunk.ChunkPacker;
import baritone.bot.event.events.*;
import baritone.bot.event.events.type.EventState;
import baritone.bot.event.listener.IGameEventListener;
@ -49,6 +47,7 @@ import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.world.chunk.Chunk;
import org.lwjgl.input.Keyboard;
import java.util.ArrayList;
@ -69,8 +68,8 @@ public final class GameEventHandler implements IGameEventListener, Helper {
}
@Override
public final void onPlayerUpdate() {
dispatch(IGameEventListener::onPlayerUpdate);
public final void onPlayerUpdate(PlayerUpdateEvent event) {
dispatch(listener -> listener.onPlayerUpdate(event));
}
@Override
@ -112,11 +111,12 @@ public final class GameEventHandler implements IGameEventListener, Helper {
&& type == ChunkEvent.Type.UNLOAD
&& mc.world.getChunkProvider().isChunkGeneratedAt(event.getX(), event.getZ());
if (Baritone.settings().chuckCaching.get()) {
if (Baritone.settings().chunkCaching.get()) {
if (isPostPopulate || isPreUnload) {
CachedWorldProvider.INSTANCE.ifWorldLoaded(world ->
world.updateCachedChunk(event.getX(), event.getZ(),
ChunkPacker.createPackedChunk(mc.world.getChunk(event.getX(), event.getZ()))));
CachedWorldProvider.INSTANCE.ifWorldLoaded(world -> {
Chunk chunk = mc.world.getChunk(event.getX(), event.getZ());
world.queueForPacking(chunk);
});
}
}
@ -136,12 +136,12 @@ public final class GameEventHandler implements IGameEventListener, Helper {
@Override
public final void onWorldEvent(WorldEvent event) {
if (Baritone.settings().chuckCaching.get()) {
if (Baritone.settings().chunkCaching.get()) {
CachedWorldProvider cache = CachedWorldProvider.INSTANCE;
switch (event.getState()) {
case PRE:
cache.ifWorldLoaded(CachedWorld::save);
cache.closeWorld();
break;
case POST:
cache.closeWorld();
@ -156,17 +156,22 @@ public final class GameEventHandler implements IGameEventListener, Helper {
@Override
public final void onSendPacket(PacketEvent event) {
dispatch(behavior -> behavior.onSendPacket(event));
dispatch(listener -> listener.onSendPacket(event));
}
@Override
public final void onReceivePacket(PacketEvent event) {
dispatch(behavior -> behavior.onReceivePacket(event));
dispatch(listener -> listener.onReceivePacket(event));
}
@Override
public final void onQueryItemSlotForBlocks(ItemSlotEvent event) {
dispatch(behavior -> behavior.onQueryItemSlotForBlocks(event));
dispatch(listener -> listener.onQueryItemSlotForBlocks(event));
}
@Override
public void onPlayerRelativeMove(RelativeMoveEvent event) {
dispatch(listener -> listener.onPlayerRelativeMove(event));
}
public final void registerEventListener(IGameEventListener listener) {

View File

@ -15,17 +15,29 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.bot.chunk;
package baritone.bot.event.events;
import baritone.bot.utils.pathing.IBlockTypeAccess;
import java.util.BitSet;
import baritone.bot.event.events.type.EventState;
/**
* @author Brady
* @since 8/4/2018 1:10 AM
* @since 8/21/2018
*/
public interface ICachedChunkAccess extends IBlockTypeAccess {
public final class PlayerUpdateEvent {
void updateCachedChunk(int chunkX, int chunkZ, BitSet data);
/**
* The state of the event
*/
private final EventState state;
public PlayerUpdateEvent(EventState state) {
this.state = state;
}
/**
* @return The state of the event
*/
public final EventState getState() {
return this.state;
}
}

View File

@ -0,0 +1,43 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.bot.event.events;
import baritone.bot.event.events.type.EventState;
/**
* @author Brady
* @since 8/21/2018
*/
public final class RelativeMoveEvent {
/**
* The state of the event
*/
private final EventState state;
public RelativeMoveEvent(EventState state) {
this.state = state;
}
/**
* @return The state of the event
*/
public final EventState getState() {
return this.state;
}
}

View File

@ -52,7 +52,7 @@ public interface AbstractGameEventListener extends IGameEventListener {
default void onTick(TickEvent event) {}
@Override
default void onPlayerUpdate() {}
default void onPlayerUpdate(PlayerUpdateEvent event) {}
@Override
default void onProcessKeyBinds() {}
@ -77,4 +77,7 @@ public interface AbstractGameEventListener extends IGameEventListener {
@Override
default void onQueryItemSlotForBlocks(ItemSlotEvent event) {}
@Override
default void onPlayerRelativeMove(RelativeMoveEvent event) {}
}

View File

@ -42,6 +42,7 @@ import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.renderer.EntityRenderer;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.Packet;
@ -60,10 +61,11 @@ public interface IGameEventListener {
void onTick(TickEvent event);
/**
* Run once per game tick from before the player rotation is sent to the server.
* Run once per game tick from before and after the player rotation is sent to the server.
*
* @see EntityPlayerSP#onUpdate()
*/
void onPlayerUpdate();
void onPlayerUpdate(PlayerUpdateEvent event);
/**
* Run once per game tick from before keybinds are processed.
@ -123,4 +125,11 @@ public interface IGameEventListener {
* @see InventoryPlayer#canHarvestBlock(IBlockState)
*/
void onQueryItemSlotForBlocks(ItemSlotEvent event);
/**
* Run once per game tick from before and after the player's moveRelative method is called
*
* @see Entity#moveRelative(float, float, float, float)
*/
void onPlayerRelativeMove(RelativeMoveEvent event);
}

View File

@ -94,7 +94,7 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
int numNodes = 0;
int numEmptyChunk = 0;
boolean favoring = favoredPositions.isPresent();
boolean cache = Baritone.settings().chuckCaching.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
boolean cache = Baritone.settings().chunkCaching.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get();
double favorCoeff = Baritone.settings().backtrackCostFavoringCoefficient.get();
boolean minimumImprovementRepropagation = Baritone.settings().minimumImprovementRepropagation.get();

View File

@ -44,11 +44,11 @@ public class GoalYLevel implements Goal {
public double heuristic(BlockPos pos) {
if (pos.getY() > level) {
// need to descend
return FALL_N_BLOCKS_COST[1] * (pos.getY() - level);
return FALL_N_BLOCKS_COST[2] / 2 * (pos.getY() - level);
}
if (pos.getY() < level) {
// need to ascend
return (level - pos.getY()) * JUMP_ONE_BLOCK_COST;
return (level - pos.getY()) * JUMP_ONE_BLOCK_COST * 0.9;
}
return 0;
}

View File

@ -38,7 +38,8 @@ public class CalculationContext implements Helper {
private final boolean canSprint;
private final double placeBlockCost;
private final boolean allowBreak;
private final int maxFallHeight;
private final int maxFallHeightNoWater;
private final int maxFallHeightBucket;
public CalculationContext() {
this(new ToolSet());
@ -52,7 +53,8 @@ public class CalculationContext implements Helper {
this.canSprint = Baritone.settings().allowSprint.get() && player().getFoodStats().getFoodLevel() > 6;
this.placeBlockCost = Baritone.settings().blockPlacementPenalty.get();
this.allowBreak = Baritone.settings().allowBreak.get();
this.maxFallHeight = Baritone.settings().maxFallHeight.get();
this.maxFallHeightNoWater = Baritone.settings().maxFallHeightNoWater.get();
this.maxFallHeightBucket = Baritone.settings().maxFallHeightBucket.get();
// why cache these things here, why not let the movements just get directly from settings?
// because if some movements are calculated one way and others are calculated another way,
// then you get a wildly inconsistent path that isn't optimal for either scenario.
@ -82,7 +84,12 @@ public class CalculationContext implements Helper {
return allowBreak;
}
public int maxFallHeight(){
return maxFallHeight;
public int maxFallHeightNoWater() {
return maxFallHeightNoWater;
}
public int maxFallHeightBucket() {
return maxFallHeightBucket;
}
}

View File

@ -105,7 +105,13 @@ public abstract class Movement implements Helper, MovementHelper {
if (BlockStateInterface.isLiquid(playerFeet())) {
latestState.setInput(Input.JUMP, true);
}
latestState.getTarget().getRotation().ifPresent(LookBehavior.INSTANCE::updateTarget);
// If the movement target has to force the new rotations, or we aren't using silent move, then force the rotations
latestState.getTarget().getRotation().ifPresent(rotation ->
LookBehavior.INSTANCE.updateTarget(
rotation,
latestState.getTarget().hasToForceRotations()));
// TODO: calculate movement inputs from latestState.getGoal().position
// latestState.getTarget().position.ifPresent(null); NULL CONSUMER REALLY SHOULDN'T BE THE FINAL THING YOU SHOULD REALLY REPLACE THIS WITH ALMOST ACTUALLY ANYTHING ELSE JUST PLEASE DON'T LEAVE IT AS IT IS THANK YOU KANYE
latestState.getInputStates().forEach((input, forced) -> {
@ -131,7 +137,7 @@ public abstract class Movement implements Helper, MovementHelper {
Optional<Rotation> reachable = LookBehaviorUtils.reachable(blockPos);
if (reachable.isPresent()) {
player().inventory.currentItem = new ToolSet().getBestSlot(BlockStateInterface.get(blockPos));
state.setTarget(new MovementState.MovementTarget(reachable.get())).setInput(Input.CLICK_LEFT, true);
state.setTarget(new MovementState.MovementTarget(reachable.get(), true)).setInput(Input.CLICK_LEFT, true);
return false;
}
//get rekt minecraft
@ -139,7 +145,7 @@ public abstract class Movement implements Helper, MovementHelper {
//i dont care if theres snow in the way!!!!!!!
//you dont own me!!!!
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
Utils.getBlockPosCenter(blockPos)))
Utils.getBlockPosCenter(blockPos)), true)
).setInput(InputOverrideHandler.Input.CLICK_LEFT, true);
return false;
}

View File

@ -255,10 +255,12 @@ public interface MovementHelper extends ActionCosts, Helper {
}
static void moveTowards(MovementState state, BlockPos pos) {
state.setTarget(new MovementTarget(new Rotation(Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
Utils.getBlockPosCenter(pos),
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch)).getFirst(), mc.player.rotationPitch))
).setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
state.setTarget(new MovementTarget(
new Rotation(Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
Utils.getBlockPosCenter(pos),
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch)).getFirst(), mc.player.rotationPitch),
false
)).setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
}
static Movement generateMovementFallOrDescend(BlockPos pos, BlockPos dest, CalculationContext calcContext) {
@ -297,7 +299,7 @@ public interface MovementHelper extends ActionCosts, Helper {
continue;
}
if (canWalkOn(onto, ontoBlock)) {
if (calcContext.hasWaterBucket() || fallHeight <= 4) {
if ((calcContext.hasWaterBucket() && fallHeight <= calcContext.maxFallHeightBucket() + 1) || fallHeight <= calcContext.maxFallHeightNoWater() + 1) {
// fallHeight = 4 means onto.up() is 3 blocks down, which is the max
return new MovementFall(pos, onto.up());
} else {

View File

@ -93,21 +93,29 @@ public class MovementState {
*/
public Rotation rotation;
/**
* Whether or not this target must force rotations.
* <p>
* {@code true} if we're trying to place or break blocks, {@code false} if we're trying to look at the movement location
*/
private boolean forceRotations;
public MovementTarget() {
this(null, null);
this(null, null, false);
}
public MovementTarget(Vec3d position) {
this(position, null);
this(position, null, false);
}
public MovementTarget(Rotation rotation) {
this(null, rotation);
public MovementTarget(Rotation rotation, boolean forceRotations) {
this(null, rotation, forceRotations);
}
public MovementTarget(Vec3d position, Rotation rotation) {
public MovementTarget(Vec3d position, Rotation rotation, boolean forceRotations) {
this.position = position;
this.rotation = rotation;
this.forceRotations = forceRotations;
}
public final Optional<Vec3d> getPosition() {
@ -117,5 +125,9 @@ public class MovementState {
public final Optional<Rotation> getRotation() {
return Optional.ofNullable(this.rotation);
}
public boolean hasToForceRotations() {
return this.forceRotations;
}
}
}

View File

@ -139,7 +139,7 @@ public class MovementAscend extends Movement {
double faceX = (dest.getX() + anAgainst.getX() + 1.0D) * 0.5D;
double faceY = (dest.getY() + anAgainst.getY()) * 0.5D;
double faceZ = (dest.getZ() + anAgainst.getZ() + 1.0D) * 0.5D;
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations())));
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations()), true));
EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit;
if (Objects.equals(LookBehaviorUtils.getSelectedBlock().orElse(null), anAgainst) && LookBehaviorUtils.getSelectedBlock().get().offset(side).equals(positionsToPlace[0])) {
ticksWithoutPlacement++;

View File

@ -52,10 +52,13 @@ public class MovementFall extends Movement {
return COST_INF;
}
double placeBucketCost = 0.0;
if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > context.maxFallHeight()) {
if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > context.maxFallHeightNoWater()) {
if (!context.hasWaterBucket()) {
return COST_INF;
}
if (src.getY() - dest.getY() > context.maxFallHeightBucket()) {
return COST_INF;
}
placeBucketCost = context.placeBlockCost();
}
double frontTwo = MovementHelper.getMiningDurationTicks(context, positionsToBreak[0]) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[1]);
@ -89,7 +92,7 @@ public class MovementFall extends Movement {
}
BlockPos playerFeet = playerFeet();
Optional<Rotation> targetRotation = Optional.empty();
if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > Baritone.settings().maxFallHeight.get() && !playerFeet.equals(dest)) {
if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > Baritone.settings().maxFallHeightNoWater.get() && !playerFeet.equals(dest)) {
if (!player().inventory.hasItemStack(STACK_BUCKET_WATER) || world().provider.isNether()) { // TODO check if water bucket is on hotbar or main inventory
state.setStatus(MovementStatus.UNREACHABLE);
return state;
@ -101,9 +104,9 @@ public class MovementFall extends Movement {
}
if (targetRotation.isPresent()) {
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true)
.setTarget(new MovementTarget(targetRotation.get()));
.setTarget(new MovementTarget(targetRotation.get(), true));
} else {
state.setTarget(new MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.getBlockPosCenter(dest))));
state.setTarget(new MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.getBlockPosCenter(dest)), false));
}
if (playerFeet.equals(dest) && (player().posY - playerFeet.getY() < 0.094 // lilypads
|| BlockStateInterface.isWater(dest))) {

View File

@ -115,7 +115,7 @@ public class MovementPillar extends Movement {
if (!ladder) {
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
Utils.getBlockPosCenter(positionsToPlace[0]),
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch))));
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch)), true));
}
EntityPlayerSP thePlayer = Minecraft.getMinecraft().player;
boolean blockIsThere = MovementHelper.canWalkOn(src) || ladder;

View File

@ -111,7 +111,7 @@ public class MovementTraverse extends Movement {
return WC + context.placeBlockCost() + getTotalHardnessOfBlocksToBreak(context);
}
}
if (BlockStateInterface.get(src).getBlock().equals(Blocks.SOUL_SAND)) {
if (Blocks.SOUL_SAND.equals(srcDown)) {
return COST_INF; // can't sneak and backplace against soul sand =/
}
WC = WC * SNEAK_ONE_BLOCK_COST / WALK_ONE_BLOCK_COST;//since we are placing, we are sneaking
@ -148,7 +148,7 @@ public class MovementTraverse extends Movement {
}
if (isDoorActuallyBlockingUs) {
if (!(Blocks.IRON_DOOR.equals(srcBlock) || Blocks.IRON_DOOR.equals(pb0.getBlock()) || Blocks.IRON_DOOR.equals(pb1.getBlock()))) {
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.calcCenterFromCoords(positionsToBreak[0], world()))));
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.calcCenterFromCoords(positionsToBreak[0], world())), true));
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
return state;
}
@ -190,7 +190,7 @@ public class MovementTraverse extends Movement {
double faceX = (dest.getX() + against1.getX() + 1.0D) * 0.5D;
double faceY = (dest.getY() + against1.getY()) * 0.5D;
double faceZ = (dest.getZ() + against1.getZ() + 1.0D) * 0.5D;
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations())));
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations()), true));
EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit;
if (Objects.equals(LookBehaviorUtils.getSelectedBlock().orElse(null), against1) && Minecraft.getMinecraft().player.isSneaking()) {
@ -217,7 +217,7 @@ public class MovementTraverse extends Movement {
double faceZ = (dest.getZ() + src.getZ() + 1.0D) * 0.5D;
// faceX, faceY, faceZ is the middle of the face between from and to
BlockPos goalLook = src.down(); // this is the block we were just standing on, and the one we want to place against
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations())));
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations()), true));
state.setInput(InputOverrideHandler.Input.MOVE_BACK, true);
state.setInput(InputOverrideHandler.Input.SNEAK, true);

View File

@ -41,7 +41,7 @@ public class BlockStateInterface implements Helper {
if (chunk.isLoaded()) {
return chunk.getBlockState(pos);
}
if (Baritone.settings().chuckCaching.get()) {
if (Baritone.settings().chunkCaching.get()) {
CachedWorld world = CachedWorldProvider.INSTANCE.getCurrentWorld();
if (world != null) {
PathingBlockType type = world.getBlockType(pos);

View File

@ -23,7 +23,10 @@ import baritone.bot.behavior.Behavior;
import baritone.bot.behavior.impl.PathingBehavior;
import baritone.bot.event.events.ChatEvent;
import baritone.bot.pathing.calc.AStarPathFinder;
import baritone.bot.pathing.goals.*;
import baritone.bot.pathing.goals.Goal;
import baritone.bot.pathing.goals.GoalBlock;
import baritone.bot.pathing.goals.GoalXZ;
import baritone.bot.pathing.goals.GoalYLevel;
import baritone.bot.pathing.movement.ActionCosts;
import baritone.bot.pathing.movement.CalculationContext;
import baritone.bot.pathing.movement.Movement;

View File

@ -1,56 +0,0 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.bot.utils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
/**
* @author Brady
* @since 8/3/2018 10:18 PM
*/
public final class GZIPUtils {
private GZIPUtils() {
}
public static byte[] compress(byte[] in) throws IOException {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream(in.length);
try (GZIPOutputStream gzipStream = new GZIPOutputStream(byteStream)) {
gzipStream.write(in);
}
return byteStream.toByteArray();
}
public static byte[] decompress(InputStream in) throws IOException {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
try (GZIPInputStream gzipStream = new GZIPInputStream(in)) {
byte[] buffer = new byte[1024];
int len;
while ((len = gzipStream.read(buffer)) > 0) {
outStream.write(buffer, 0, len);
}
}
return outStream.toByteArray();
}
}

View File

@ -164,7 +164,7 @@ public class ToolSet implements Helper {
event.setSlot(this.overrideSlot);
}
public final void setOverrideSlot(int overrideSlot) {
final void setOverrideSlot(int overrideSlot) {
this.overrideSlot = overrideSlot;
}
}

View File

@ -0,0 +1,56 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.bot.Baritone;
import baritone.bot.event.events.RelativeMoveEvent;
import baritone.bot.event.events.type.EventState;
import baritone.bot.utils.Helper;
import net.minecraft.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* @author Brady
* @since 8/21/2018
*/
@Mixin(Entity.class)
public class MixinEntity {
@Inject(
method = "moveRelative",
at = @At("HEAD")
)
private void preMoveRelative(float strafe, float up, float forward, float friction, CallbackInfo ci) {
Entity _this = (Entity) (Object) this;
if (_this == Helper.mc.player)
Baritone.INSTANCE.getGameEventHandler().onPlayerRelativeMove(new RelativeMoveEvent(EventState.PRE));
}
@Inject(
method = "moveRelative",
at = @At("RETURN")
)
private void postMoveRelative(float strafe, float up, float forward, float friction, CallbackInfo ci) {
Entity _this = (Entity) (Object) this;
if (_this == Helper.mc.player)
Baritone.INSTANCE.getGameEventHandler().onPlayerRelativeMove(new RelativeMoveEvent(EventState.POST));
}
}

View File

@ -19,6 +19,8 @@ package baritone.launch.mixins;
import baritone.bot.Baritone;
import baritone.bot.event.events.ChatEvent;
import baritone.bot.event.events.PlayerUpdateEvent;
import baritone.bot.event.events.type.EventState;
import net.minecraft.client.entity.EntityPlayerSP;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@ -53,7 +55,20 @@ public class MixinEntityPlayerSP {
by = -3
)
)
private void onUpdate(CallbackInfo ci) {
Baritone.INSTANCE.getGameEventHandler().onPlayerUpdate();
private void onPreUpdate(CallbackInfo ci) {
Baritone.INSTANCE.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.PRE));
}
@Inject(
method = "onUpdate",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/entity/EntityPlayerSP.onUpdateWalkingPlayer()V",
shift = At.Shift.BY,
by = 2
)
)
private void onPostUpdate(CallbackInfo ci) {
Baritone.INSTANCE.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.POST));
}
}

View File

@ -4,7 +4,11 @@
"refmap": "mixins.client.refmap.json",
"compatibilityLevel": "JAVA_8",
"verbose": false,
"injectors": {
"maxShiftBy": 2
},
"client": [
"MixinEntity",
"MixinEntityPlayerSP",
"MixinEntityRenderer",
"MixinGameSettings",