Allocation time

This commit is contained in:
Brady
2020-03-03 14:47:50 -06:00
parent d82fd04f5f
commit 6844bc0922
8 changed files with 160 additions and 54 deletions

View File

@@ -17,7 +17,9 @@
package baritone.api.bot;
import baritone.api.bot.connect.ConnectionStatus;
import baritone.api.bot.connect.IConnectionResult;
import baritone.api.event.events.TickEvent;
import com.mojang.authlib.GameProfile;
import net.minecraft.util.Session;
@@ -32,7 +34,9 @@ import java.util.UUID;
public interface IUserManager {
/**
* Connects a new user with the specified {@link Session} to the current server.
* Connects a new user with the specified {@link Session} to the current server. Returns
* a {@link IConnectionResult} describing the result of the attempted connection as well
* as a {@link IBaritoneUser} instance if it was {@link ConnectionStatus#SUCCESS}.
*
* @param session The user session
* @return The result of the attempted connection
@@ -40,7 +44,8 @@ public interface IUserManager {
IConnectionResult connect(Session session);
/**
* Disconnects the specified {@link IBaritoneUser} from its current server.
* Disconnects the specified {@link IBaritoneUser} from its current server. All valid users
* are automatically disconnected when the current game state becomes {@link TickEvent.Type#OUT}.
*
* @param user The user to disconnect
*/
@@ -53,7 +58,9 @@ public interface IUserManager {
* @return The user, {@link Optional#empty()} if no match or {@code profile} is {@code null}
*/
default Optional<IBaritoneUser> getUserByProfile(GameProfile profile) {
return profile == null ? Optional.empty() : users().stream().filter(user -> user.getProfile().equals(profile)).findFirst();
return profile == null
? Optional.empty()
: this.getUsers().stream().filter(user -> user.getProfile().equals(profile)).findFirst();
}
/**
@@ -63,11 +70,13 @@ public interface IUserManager {
* @return The user, {@link Optional#empty()} if no match or {@code uuid} is {@code null}
*/
default Optional<IBaritoneUser> getUserByUUID(UUID uuid) {
return uuid == null ? Optional.empty() : users().stream().filter(user -> user.getProfile().getId().equals(uuid)).findFirst();
return uuid == null
? Optional.empty()
: this.getUsers().stream().filter(user -> user.getProfile().getId().equals(uuid)).findFirst();
}
/**
* @return All of the users held by this manager
*/
List<IBaritoneUser> users();
List<IBaritoneUser> getUsers();
}

View File

@@ -58,7 +58,7 @@ public final class BaritoneProvider implements IBaritoneProvider {
public List<IBaritone> getAllBaritones() {
List<IBaritone> baritones = new ArrayList<>();
baritones.add(getPrimaryBaritone());
for (IBaritoneUser ibu : UserManager.INSTANCE.users()) {
for (IBaritoneUser ibu : UserManager.INSTANCE.getUsers()) {
baritones.add(ibu.getBaritone());
}
return baritones;

View File

@@ -20,8 +20,8 @@ package baritone.bot;
import baritone.Baritone;
import baritone.api.IBaritone;
import baritone.api.bot.IBaritoneUser;
import baritone.api.bot.IUserManager;
import baritone.api.utils.IPlayerController;
import baritone.bot.spec.BotMinecraft;
import baritone.bot.spec.BotWorld;
import baritone.bot.spec.EntityBot;
import com.mojang.authlib.GameProfile;
@@ -44,6 +44,7 @@ public class BaritoneUser implements IBaritoneUser {
private GameProfile profile;
private INetHandlerPlayClient netHandlerPlayClient;
private BotMinecraft mc;
private BotWorld world;
private EntityBot player;
private IPlayerController playerController;
@@ -51,6 +52,7 @@ public class BaritoneUser implements IBaritoneUser {
private final Baritone baritone;
BaritoneUser(UserManager manager, NetworkManager networkManager, Session session) {
this.mc = BotMinecraft.allocate(this);
this.manager = manager;
this.networkManager = networkManager;
this.session = session;
@@ -107,4 +109,8 @@ public class BaritoneUser implements IBaritoneUser {
public IBaritone getBaritone() {
return baritone;
}
public BotMinecraft getMinecraft() {
return this.mc;
}
}

View File

@@ -151,14 +151,16 @@ public final class UserManager implements IUserManager, Helper {
@Override
public final void disconnect(IBaritoneUser user) {
// It's probably fine to pass null to this, because the handlers aren't doing anything with it
// noinspection ConstantConditions
user.getNetworkManager().closeChannel(null);
this.users.remove(user);
if (this.users.contains(user)) {
// It's probably fine to pass null to this, because the handlers aren't doing anything with it
// noinspection ConstantConditions
user.getNetworkManager().closeChannel(null);
this.users.remove(user);
}
}
@Override
public final List<IBaritoneUser> users() {
public final List<IBaritoneUser> getUsers() {
return Collections.unmodifiableList(this.users);
}
}

View File

@@ -62,52 +62,16 @@ public class BotNetHandlerLoginClient extends NetHandlerLoginClient {
private final BaritoneUser user;
public BotNetHandlerLoginClient(NetworkManager networkManager, BaritoneUser user) {
super(networkManager, Minecraft.getMinecraft(), null);
super(networkManager, user.getMinecraft(), null);
this.networkManager = networkManager;
this.mc = Minecraft.getMinecraft();
this.mc = user.getMinecraft();
this.user = user;
}
@Override
public void handleEncryptionRequest(SPacketEncryptionRequest packetIn) {
SecretKey secretkey = CryptManager.createNewSharedKey();
PublicKey publicKey = packetIn.getPublicKey();
// Setup joinServer payload info
GameProfile profile = this.user.getSession().getProfile();
String authenticationToken = this.user.getSession().getToken();
String serverId = new BigInteger(CryptManager.getServerIdHash(packetIn.getServerId(), publicKey, secretkey)).toString(16);
if (this.mc.getCurrentServerData() != null && this.mc.getCurrentServerData().isOnLAN()) {
try {
this.mc.getSessionService().joinServer(profile, authenticationToken, serverId);
} catch (AuthenticationException e) {
// Couldn't connect to auth servers but will continue to join LAN
}
} else {
try {
this.mc.getSessionService().joinServer(profile, authenticationToken, serverId);
} catch (AuthenticationUnavailableException e) {
this.networkManager.closeChannel(new TextComponentTranslation("disconnect.loginFailedInfo", new TextComponentTranslation("disconnect.loginFailedInfo.serversUnavailable")));
return;
} catch (InvalidCredentialsException e) {
this.networkManager.closeChannel(new TextComponentTranslation("disconnect.loginFailedInfo", new TextComponentTranslation("disconnect.loginFailedInfo.invalidSession")));
return;
} catch (AuthenticationException e) {
this.networkManager.closeChannel(new TextComponentTranslation("disconnect.loginFailedInfo", e.getMessage()));
return;
}
}
// noinspection unchecked
this.networkManager.sendPacket(new CPacketEncryptionResponse(secretkey, publicKey, packetIn.getVerifyToken()),
future -> BotNetHandlerLoginClient.this.networkManager.enableEncryption(secretkey));
}
@Override
public void handleLoginSuccess(SPacketLoginSuccess packetIn) {
this.networkManager.setConnectionState(EnumConnectionState.PLAY);
this.networkManager.setNetHandler(new BotNetHandlerPlayClient(this.networkManager, this.user, Minecraft.getMinecraft(), packetIn.getProfile()));
this.networkManager.setNetHandler(new BotNetHandlerPlayClient(this.networkManager, this.user, this.mc, packetIn.getProfile()));
}
@Override

View File

@@ -0,0 +1,73 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.bot.spec;
import baritone.api.bot.IBaritoneUser;
import baritone.api.utils.Helper;
import baritone.utils.ObjectAllocator;
import com.google.common.util.concurrent.ListenableFuture;
import com.mojang.authlib.minecraft.MinecraftSessionService;
import net.minecraft.client.Minecraft;
import net.minecraft.client.main.GameConfiguration;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.util.Session;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.concurrent.Callable;
/**
* @author Brady
* @since 3/3/2020
*/
public final class BotMinecraft extends Minecraft implements Helper {
private IBaritoneUser user;
private BotMinecraft(GameConfiguration gameConfig) {
super(gameConfig);
}
@Nonnull
@Override
public Session getSession() {
return this.user.getSession();
}
@Nullable
@Override
public ServerData getCurrentServerData() {
return mc.getCurrentServerData();
}
@Override
public MinecraftSessionService getSessionService() {
return mc.getSessionService();
}
@Override
public <V> ListenableFuture<V> addScheduledTask(Callable<V> callableToSchedule) {
return mc.addScheduledTask(callableToSchedule);
}
public static BotMinecraft allocate(IBaritoneUser user) {
BotMinecraft mc = ObjectAllocator.allocate(BotMinecraft.class);
mc.user = user;
return mc;
}
}

View File

@@ -68,9 +68,6 @@ public final class GameEventHandler implements IEventBus, Helper {
@Override
public final void onSendChatMessage(ChatEvent event) {
// Ensure UserManager is created to prevent a ConcurrentModificationException
Objects.requireNonNull(UserManager.INSTANCE);
listeners.forEach(l -> l.onSendChatMessage(event));
}

View File

@@ -0,0 +1,55 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.utils;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
/**
* Hacky util to allocate objects without needing to invoke their constructor.
*
* @author Brady
* @since 3/3/2020
*/
public final class ObjectAllocator {
private static final Unsafe theUnsafe;
static {
try {
Class clazz = Class.forName("sun.misc.Unsafe");
Field field = clazz.getDeclaredField("theUnsafe");
field.setAccessible(true);
theUnsafe = (Unsafe) field.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private ObjectAllocator() {}
public static <T> T allocate(Class<T> clazz) {
try {
// noinspection unchecked
return (T) theUnsafe.allocateInstance(clazz);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}