mirror of
https://github.com/Eaglercraft-Archive/Eaglercraftx-1.8.8-src.git
synced 2025-06-27 18:38:14 -05:00
Update #22 - Singleplayer and shared worlds, shader fixes
This commit is contained in:
@ -0,0 +1,98 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.ipc.*;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IntegratedServerState {
|
||||
|
||||
public static final int WORLD_WORKER_NOT_RUNNING = -2;
|
||||
public static final int WORLD_WORKER_BOOTING = -1;
|
||||
public static final int WORLD_NONE = 0;
|
||||
public static final int WORLD_LOADING = 2;
|
||||
public static final int WORLD_LOADED = 3;
|
||||
public static final int WORLD_UNLOADING = 4;
|
||||
public static final int WORLD_DELETING = 5;
|
||||
public static final int WORLD_RENAMING = 6;
|
||||
public static final int WORLD_DUPLICATING = 7;
|
||||
public static final int WORLD_PAUSED = 9;
|
||||
public static final int WORLD_LISTING = 10;
|
||||
public static final int WORLD_SAVING = 11;
|
||||
public static final int WORLD_IMPORTING = 12;
|
||||
public static final int WORLD_EXPORTING = 13;
|
||||
public static final int WORLD_GET_NBT = 14;
|
||||
|
||||
public static final int WORLD_LIST_FILE = 15;
|
||||
public static final int WORLD_FILE_READ = 16;
|
||||
public static final int WORLD_FILE_WRITE = 17;
|
||||
public static final int WORLD_FILE_MOVE = 18;
|
||||
public static final int WORLD_FILE_COPY = 19;
|
||||
public static final int WORLD_CLEAR_PLAYERS = 20;
|
||||
|
||||
public static String getStateName(int i) {
|
||||
switch(i) {
|
||||
case WORLD_WORKER_NOT_RUNNING: return "WORLD_WORKER_NOT_RUNNING";
|
||||
case WORLD_WORKER_BOOTING: return "WORLD_WORKER_BOOTING";
|
||||
case WORLD_NONE: return "WORLD_NONE";
|
||||
case WORLD_LOADING: return "WORLD_LOADING";
|
||||
case WORLD_LOADED: return "WORLD_LOADED";
|
||||
case WORLD_UNLOADING: return "WORLD_UNLOADING";
|
||||
case WORLD_DELETING: return "WORLD_DELETING";
|
||||
case WORLD_RENAMING: return "WORLD_RENAMING";
|
||||
case WORLD_DUPLICATING: return "WORLD_DUPLICATING";
|
||||
case WORLD_PAUSED: return "WORLD_PAUSED";
|
||||
case WORLD_LISTING: return "WORLD_LISTING";
|
||||
case WORLD_SAVING: return "WORLD_SAVING";
|
||||
case WORLD_IMPORTING: return "WORLD_IMPORTING";
|
||||
case WORLD_EXPORTING: return "WORLD_EXPORTING";
|
||||
case WORLD_GET_NBT: return "WORLD_GET_NBT";
|
||||
case WORLD_LIST_FILE: return "WORLD_LIST_FILE";
|
||||
case WORLD_FILE_READ: return "WORLD_FILE_READ";
|
||||
case WORLD_FILE_WRITE: return "WORLD_FILE_WRITE";
|
||||
case WORLD_FILE_MOVE: return "WORLD_FILE_MOVE";
|
||||
case WORLD_FILE_COPY: return "WORLD_FILE_COPY";
|
||||
case WORLD_CLEAR_PLAYERS: return "WORLD_CLEAR_PLAYERS";
|
||||
default: return "INVALID";
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isACKValidInState(int ack, int state) {
|
||||
switch(ack) {
|
||||
case 0xFF: return state == WORLD_WORKER_BOOTING;
|
||||
case IPCPacketFFProcessKeepAlive.EXITED: return true;
|
||||
case IPCPacketFFProcessKeepAlive.FAILURE: return true;
|
||||
case IPCPacket01StopServer.ID: return true;
|
||||
case IPCPacket00StartServer.ID: return state == WORLD_LOADING;
|
||||
case IPCPacket03DeleteWorld.ID: return state == WORLD_DELETING;
|
||||
case IPCPacket06RenameWorldNBT.ID: return (state == WORLD_DUPLICATING || state == WORLD_RENAMING);
|
||||
case IPCPacket07ImportWorld.ID: return state == WORLD_IMPORTING;
|
||||
case IPCPacket0BPause.ID:
|
||||
case IPCPacket19Autosave.ID: return (state == WORLD_SAVING || state == WORLD_PAUSED || state == WORLD_LOADED || state == WORLD_UNLOADING);
|
||||
case IPCPacket12FileWrite.ID: return state == WORLD_FILE_WRITE;
|
||||
case IPCPacket13FileCopyMove.ID: return (state == WORLD_FILE_MOVE || state == WORLD_FILE_COPY);
|
||||
case IPCPacket18ClearPlayers.ID: return state == WORLD_CLEAR_PLAYERS;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertState(int ack, int state) {
|
||||
if(!isACKValidInState(ack, state)) {
|
||||
String msg = "Recieved ACK " + ack + " while the client state was " + state + " '" + getStateName(state) + "'";
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp;
|
||||
|
||||
import net.minecraft.world.storage.SaveHandlerMP;
|
||||
import net.minecraft.world.storage.WorldInfo;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class SingleplayerSaveHandler extends SaveHandlerMP {
|
||||
|
||||
private final WorldInfo worldInfo;
|
||||
|
||||
public SingleplayerSaveHandler(WorldInfo worldInfo) {
|
||||
this.worldInfo = worldInfo;
|
||||
}
|
||||
|
||||
public WorldInfo loadWorldInfo() {
|
||||
return worldInfo;
|
||||
}
|
||||
}
|
@ -0,0 +1,586 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.EnumEaglerConnectionState;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IPCPacketData;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformApplication;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.profile.EaglerProfile;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.internal.ClientPlatformSingleplayer;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.ipc.*;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.lan.LANServerController;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.socket.ClientIntegratedServerNetworkManager;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.IProgressUpdate;
|
||||
import net.minecraft.util.StringTranslate;
|
||||
import net.minecraft.world.WorldSettings;
|
||||
import net.minecraft.world.storage.ISaveFormat;
|
||||
import net.minecraft.world.storage.ISaveHandler;
|
||||
import net.minecraft.world.storage.SaveFormatComparator;
|
||||
import net.minecraft.world.storage.WorldInfo;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class SingleplayerServerController implements ISaveFormat {
|
||||
|
||||
public static final String IPC_CHANNEL = "~!IPC";
|
||||
public static final String PLAYER_CHANNEL = "~!LOCAL_PLAYER";
|
||||
|
||||
private static int statusState = IntegratedServerState.WORLD_WORKER_NOT_RUNNING;
|
||||
private static boolean loggingState = true;
|
||||
private static String worldStatusString = "";
|
||||
private static float worldStatusProgress = 0.0f;
|
||||
private static final LinkedList<IPCPacket15Crashed> exceptions = new LinkedList();
|
||||
|
||||
public static final SingleplayerServerController instance = new SingleplayerServerController();
|
||||
public static final Logger logger = LogManager.getLogger("SingleplayerServerController");
|
||||
public static final List<SaveFormatComparator> saveListCache = new ArrayList();
|
||||
public static final Map<String, WorldInfo> saveListMap = new HashMap();
|
||||
public static final List<NBTTagCompound> saveListNBT = new ArrayList();
|
||||
|
||||
private static boolean isPaused = false;
|
||||
private static List<String> integratedServerTPS = new ArrayList();
|
||||
private static long integratedServerLastTPSUpdate = 0;
|
||||
public static final ClientIntegratedServerNetworkManager localPlayerNetworkManager = new ClientIntegratedServerNetworkManager(PLAYER_CHANNEL);
|
||||
private static final List<String> openLANChannels = new ArrayList();
|
||||
|
||||
private SingleplayerServerController() {
|
||||
}
|
||||
|
||||
public static void startIntegratedServerWorker() {
|
||||
if(statusState == IntegratedServerState.WORLD_WORKER_NOT_RUNNING) {
|
||||
exceptions.clear();
|
||||
statusState = IntegratedServerState.WORLD_WORKER_BOOTING;
|
||||
loggingState = true;
|
||||
ClientPlatformSingleplayer.startIntegratedServer();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isIntegratedServerWorkerStarted() {
|
||||
return statusState != IntegratedServerState.WORLD_WORKER_NOT_RUNNING && statusState != IntegratedServerState.WORLD_WORKER_BOOTING;
|
||||
}
|
||||
|
||||
public static boolean isIntegratedServerWorkerAlive() {
|
||||
return statusState != IntegratedServerState.WORLD_WORKER_NOT_RUNNING;
|
||||
}
|
||||
|
||||
public static boolean isRunningSingleThreadMode() {
|
||||
return ClientPlatformSingleplayer.isRunningSingleThreadMode();
|
||||
}
|
||||
|
||||
public static boolean isReady() {
|
||||
return statusState == IntegratedServerState.WORLD_NONE;
|
||||
}
|
||||
|
||||
public static boolean isWorldNotLoaded() {
|
||||
return statusState == IntegratedServerState.WORLD_NONE || statusState == IntegratedServerState.WORLD_WORKER_NOT_RUNNING ||
|
||||
statusState == IntegratedServerState.WORLD_WORKER_BOOTING;
|
||||
}
|
||||
|
||||
public static boolean isWorldRunning() {
|
||||
return statusState == IntegratedServerState.WORLD_LOADED || statusState == IntegratedServerState.WORLD_PAUSED ||
|
||||
statusState == IntegratedServerState.WORLD_LOADING || statusState == IntegratedServerState.WORLD_SAVING;
|
||||
}
|
||||
|
||||
public static boolean isWorldReady() {
|
||||
return statusState == IntegratedServerState.WORLD_LOADED || statusState == IntegratedServerState.WORLD_PAUSED ||
|
||||
statusState == IntegratedServerState.WORLD_SAVING;
|
||||
}
|
||||
|
||||
public static int getStatusState() {
|
||||
return statusState;
|
||||
}
|
||||
|
||||
public static boolean isChannelOpen(String ch) {
|
||||
return openLANChannels.contains(ch);
|
||||
}
|
||||
|
||||
public static boolean isChannelNameAllowed(String ch) {
|
||||
return !IPC_CHANNEL.equals(ch) && !PLAYER_CHANNEL.equals(ch);
|
||||
}
|
||||
|
||||
public static void openPlayerChannel(String ch) {
|
||||
if(openLANChannels.contains(ch)) {
|
||||
logger.error("Tried to open channel that already exists: \"{}\"", ch);
|
||||
} else if (!isChannelNameAllowed(ch)) {
|
||||
logger.error("Tried to open disallowed channel name: \"{}\"", ch);
|
||||
}else {
|
||||
openLANChannels.add(ch);
|
||||
sendIPCPacket(new IPCPacket0CPlayerChannel(ch, true));
|
||||
PlatformWebRTC.serverLANCreatePeer(ch);
|
||||
}
|
||||
}
|
||||
|
||||
public static void closePlayerChannel(String ch) {
|
||||
if(!openLANChannels.remove(ch)) {
|
||||
logger.error("Tried to close channel that doesn't exist: \"{}\"", ch);
|
||||
}else {
|
||||
sendIPCPacket(new IPCPacket0CPlayerChannel(ch, false));
|
||||
PlatformWebRTC.serverLANDisconnectPeer(ch);
|
||||
}
|
||||
}
|
||||
|
||||
public static void openLocalPlayerChannel() {
|
||||
localPlayerNetworkManager.isPlayerChannelOpen = true;
|
||||
sendIPCPacket(new IPCPacket0CPlayerChannel(PLAYER_CHANNEL, true));
|
||||
}
|
||||
|
||||
public static void closeLocalPlayerChannel() {
|
||||
localPlayerNetworkManager.isPlayerChannelOpen = false;
|
||||
sendIPCPacket(new IPCPacket0CPlayerChannel(PLAYER_CHANNEL, false));
|
||||
}
|
||||
|
||||
private static void ensureReady() {
|
||||
if(!isReady()) {
|
||||
String msg = "Server is in state " + statusState + " '" + IntegratedServerState.getStateName(statusState) + "' which is not the 'WORLD_NONE' state for the requested IPC operation";
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ensureWorldReady() {
|
||||
if(!isWorldReady()) {
|
||||
String msg = "Server is in state " + statusState + " '" + IntegratedServerState.getStateName(statusState) + "' which is not the 'WORLD_LOADED' state for the requested IPC operation";
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public static void launchEaglercraftServer(String folderName, int difficulty, int viewDistance, WorldSettings settings) {
|
||||
ensureReady();
|
||||
clearTPS();
|
||||
if(settings != null) {
|
||||
sendIPCPacket(new IPCPacket02InitWorld(folderName, settings.getGameType().getID(),
|
||||
settings.getTerrainType().getWorldTypeID(), settings.getWorldName(), settings.getSeed(),
|
||||
settings.areCommandsAllowed(), settings.isMapFeaturesEnabled(), settings.isBonusChestEnabled(),
|
||||
settings.getHardcoreEnabled()));
|
||||
}
|
||||
statusState = IntegratedServerState.WORLD_LOADING;
|
||||
worldStatusProgress = 0.0f;
|
||||
sendIPCPacket(new IPCPacket00StartServer(folderName, EaglerProfile.getName(), difficulty, viewDistance, EagRuntime.getConfiguration().isDemo()));
|
||||
}
|
||||
|
||||
public static void clearTPS() {
|
||||
integratedServerTPS.clear();
|
||||
integratedServerLastTPSUpdate = 0l;
|
||||
}
|
||||
|
||||
public static List<String> getTPS() {
|
||||
return integratedServerTPS;
|
||||
}
|
||||
|
||||
public static long getTPSAge() {
|
||||
return System.currentTimeMillis() - integratedServerLastTPSUpdate;
|
||||
}
|
||||
|
||||
public static boolean hangupEaglercraftServer() {
|
||||
LANServerController.closeLAN();
|
||||
if(isWorldRunning()) {
|
||||
logger.error("Shutting down integrated server due to unexpected client hangup, this is a memleak");
|
||||
statusState = IntegratedServerState.WORLD_UNLOADING;
|
||||
sendIPCPacket(new IPCPacket01StopServer());
|
||||
return true;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean shutdownEaglercraftServer() {
|
||||
LANServerController.closeLAN();
|
||||
if(isWorldRunning()) {
|
||||
logger.info("Shutting down integrated server");
|
||||
statusState = IntegratedServerState.WORLD_UNLOADING;
|
||||
sendIPCPacket(new IPCPacket01StopServer());
|
||||
return true;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void autoSave() {
|
||||
if(!isPaused) {
|
||||
statusState = IntegratedServerState.WORLD_SAVING;
|
||||
sendIPCPacket(new IPCPacket19Autosave());
|
||||
}
|
||||
}
|
||||
|
||||
public static void setPaused(boolean pause) {
|
||||
if(statusState != IntegratedServerState.WORLD_LOADED && statusState != IntegratedServerState.WORLD_PAUSED && statusState != IntegratedServerState.WORLD_SAVING) {
|
||||
return;
|
||||
}
|
||||
if(isPaused != pause) {
|
||||
sendIPCPacket(new IPCPacket0BPause(pause));
|
||||
isPaused = pause;
|
||||
}
|
||||
}
|
||||
|
||||
public static void runTick() {
|
||||
List<IPCPacketData> pktList = ClientPlatformSingleplayer.recieveAllPacket();
|
||||
if(pktList != null) {
|
||||
IPCPacketData packetData;
|
||||
for(int i = 0, l = pktList.size(); i < l; ++i) {
|
||||
packetData = pktList.get(i);
|
||||
if(packetData.channel.equals(SingleplayerServerController.IPC_CHANNEL)) {
|
||||
IPCPacketBase ipc;
|
||||
try {
|
||||
ipc = IPCPacketManager.IPCDeserialize(packetData.contents);
|
||||
}catch(IOException ex) {
|
||||
throw new RuntimeException("Failed to deserialize IPC packet", ex);
|
||||
}
|
||||
handleIPCPacket(ipc);
|
||||
}else if(packetData.channel.equals(SingleplayerServerController.PLAYER_CHANNEL)) {
|
||||
if(localPlayerNetworkManager.getConnectStatus() != EnumEaglerConnectionState.CLOSED) {
|
||||
localPlayerNetworkManager.addRecievedPacket(packetData.contents);
|
||||
}else {
|
||||
logger.warn("Recieved {} byte packet on closed local player connection", packetData.contents.length);
|
||||
}
|
||||
}else {
|
||||
PlatformWebRTC.serverLANWritePacket(packetData.channel, packetData.contents);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean logWindowState = PlatformApplication.isShowingDebugConsole();
|
||||
if(loggingState != logWindowState) {
|
||||
loggingState = logWindowState;
|
||||
sendIPCPacket(new IPCPacket21EnableLogging(logWindowState));
|
||||
}
|
||||
|
||||
LANServerController.updateLANServer();
|
||||
}
|
||||
|
||||
private static void handleIPCPacket(IPCPacketBase ipc) {
|
||||
switch(ipc.id()) {
|
||||
case IPCPacketFFProcessKeepAlive.ID: {
|
||||
IPCPacketFFProcessKeepAlive pkt = (IPCPacketFFProcessKeepAlive)ipc;
|
||||
IntegratedServerState.assertState(pkt.ack, statusState);
|
||||
switch(pkt.ack) {
|
||||
case 0xFF:
|
||||
logger.info("Integrated server signaled a successful boot");
|
||||
sendIPCPacket(new IPCPacket14StringList(IPCPacket14StringList.LOCALE, StringTranslate.dump()));
|
||||
statusState = IntegratedServerState.WORLD_NONE;
|
||||
break;
|
||||
case IPCPacket00StartServer.ID:
|
||||
statusState = IntegratedServerState.WORLD_LOADED;
|
||||
isPaused = false;
|
||||
break;
|
||||
case IPCPacket0BPause.ID:
|
||||
case IPCPacket19Autosave.ID:
|
||||
if(statusState != IntegratedServerState.WORLD_UNLOADING) {
|
||||
statusState = isPaused ? IntegratedServerState.WORLD_PAUSED : IntegratedServerState.WORLD_LOADED;
|
||||
}
|
||||
break;
|
||||
case IPCPacketFFProcessKeepAlive.FAILURE:
|
||||
logger.error("Server signaled 'FAILURE' response in state '{}'", IntegratedServerState.getStateName(statusState));
|
||||
statusState = IntegratedServerState.WORLD_NONE;
|
||||
callFailed = true;
|
||||
break;
|
||||
case IPCPacket01StopServer.ID:
|
||||
LANServerController.closeLAN();
|
||||
localPlayerNetworkManager.isPlayerChannelOpen = false;
|
||||
statusState = IntegratedServerState.WORLD_NONE;
|
||||
break;
|
||||
case IPCPacket06RenameWorldNBT.ID:
|
||||
statusState = IntegratedServerState.WORLD_NONE;
|
||||
break;
|
||||
case IPCPacket03DeleteWorld.ID:
|
||||
case IPCPacket07ImportWorld.ID:
|
||||
case IPCPacket12FileWrite.ID:
|
||||
case IPCPacket13FileCopyMove.ID:
|
||||
case IPCPacket18ClearPlayers.ID:
|
||||
statusState = IntegratedServerState.WORLD_NONE;
|
||||
break;
|
||||
case IPCPacketFFProcessKeepAlive.EXITED:
|
||||
logger.error("Server signaled 'EXITED' response in state '{}'", IntegratedServerState.getStateName(statusState));
|
||||
if(ClientPlatformSingleplayer.canKillWorker()) {
|
||||
ClientPlatformSingleplayer.killWorker();
|
||||
}
|
||||
LANServerController.closeLAN();
|
||||
localPlayerNetworkManager.isPlayerChannelOpen = false;
|
||||
statusState = IntegratedServerState.WORLD_WORKER_NOT_RUNNING;
|
||||
callFailed = true;
|
||||
break;
|
||||
default:
|
||||
logger.error("IPC acknowledge packet type 0x{} was not handled", Integer.toHexString(pkt.ack));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCPacket09RequestResponse.ID: {
|
||||
IPCPacket09RequestResponse pkt = (IPCPacket09RequestResponse)ipc;
|
||||
if(statusState == IntegratedServerState.WORLD_EXPORTING) {
|
||||
statusState = IntegratedServerState.WORLD_NONE;
|
||||
exportResponse = pkt.response;
|
||||
}else {
|
||||
logger.error("IPCPacket09RequestResponse was recieved but statusState was '{}' instead of 'WORLD_EXPORTING'", IntegratedServerState.getStateName(statusState));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCPacket0DProgressUpdate.ID: {
|
||||
IPCPacket0DProgressUpdate pkt = (IPCPacket0DProgressUpdate)ipc;
|
||||
worldStatusString = pkt.updateMessage;
|
||||
worldStatusProgress = pkt.updateProgress;
|
||||
break;
|
||||
}
|
||||
case IPCPacket15Crashed.ID: {
|
||||
exceptions.add((IPCPacket15Crashed)ipc);
|
||||
if(exceptions.size() > 64) {
|
||||
exceptions.remove(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCPacket16NBTList.ID: {
|
||||
IPCPacket16NBTList pkt = (IPCPacket16NBTList)ipc;
|
||||
if(pkt.opCode == IPCPacket16NBTList.WORLD_LIST && statusState == IntegratedServerState.WORLD_LISTING) {
|
||||
statusState = IntegratedServerState.WORLD_NONE;
|
||||
saveListNBT.clear();
|
||||
saveListNBT.addAll(pkt.nbtTagList);
|
||||
loadSaveComparators();
|
||||
}else {
|
||||
logger.error("IPC packet type 0x{} class '{}' contained invalid opCode {} in state {} '{}'", Integer.toHexString(ipc.id()), ipc.getClass().getSimpleName(), pkt.opCode, statusState, IntegratedServerState.getStateName(statusState));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCPacket0CPlayerChannel.ID: {
|
||||
IPCPacket0CPlayerChannel pkt = (IPCPacket0CPlayerChannel)ipc;
|
||||
if(!pkt.open) {
|
||||
if(pkt.channel.equals(PLAYER_CHANNEL)) {
|
||||
LANServerController.closeLAN();
|
||||
localPlayerNetworkManager.isPlayerChannelOpen = false;
|
||||
logger.error("Local player channel was closed");
|
||||
}else {
|
||||
PlatformWebRTC.serverLANDisconnectPeer(pkt.channel);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCPacket14StringList.ID: {
|
||||
IPCPacket14StringList pkt = (IPCPacket14StringList)ipc;
|
||||
if(pkt.opCode == IPCPacket14StringList.SERVER_TPS) {
|
||||
integratedServerTPS.clear();
|
||||
integratedServerTPS.addAll(pkt.stringList);
|
||||
integratedServerLastTPSUpdate = System.currentTimeMillis();
|
||||
}else {
|
||||
logger.warn("Strange string list type {} recieved!", pkt.opCode);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCPacket20LoggerMessage.ID: {
|
||||
IPCPacket20LoggerMessage pkt = (IPCPacket20LoggerMessage)ipc;
|
||||
PlatformApplication.addLogMessage(pkt.logMessage, pkt.isError);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new RuntimeException("Unexpected IPC packet type recieved on client: " + ipc.id());
|
||||
}
|
||||
}
|
||||
|
||||
public static void sendIPCPacket(IPCPacketBase ipc) {
|
||||
byte[] pkt;
|
||||
try {
|
||||
pkt = IPCPacketManager.IPCSerialize(ipc);
|
||||
}catch (IOException ex) {
|
||||
throw new RuntimeException("Failed to serialize IPC packet", ex);
|
||||
}
|
||||
ClientPlatformSingleplayer.sendPacket(new IPCPacketData(IPC_CHANNEL, pkt));
|
||||
}
|
||||
|
||||
|
||||
private static boolean callFailed = false;
|
||||
|
||||
public static boolean didLastCallFail() {
|
||||
boolean c = callFailed;
|
||||
callFailed = false;
|
||||
return c;
|
||||
}
|
||||
|
||||
public static void importWorld(String name, byte[] data, int format, byte gameRules) {
|
||||
ensureReady();
|
||||
statusState = IntegratedServerState.WORLD_IMPORTING;
|
||||
sendIPCPacket(new IPCPacket07ImportWorld(name, data, (byte)format, gameRules));
|
||||
}
|
||||
|
||||
public static void exportWorld(String name, int format) {
|
||||
ensureReady();
|
||||
statusState = IntegratedServerState.WORLD_EXPORTING;
|
||||
if(format == IPCPacket05RequestData.REQUEST_LEVEL_EAG) {
|
||||
name = name + (new String(new char[] { (char)253, (char)233, (char)233 })) + EaglerProfile.getName();
|
||||
}
|
||||
sendIPCPacket(new IPCPacket05RequestData(name, (byte)format));
|
||||
}
|
||||
|
||||
private static byte[] exportResponse = null;
|
||||
|
||||
public static byte[] getExportResponse() {
|
||||
byte[] dat = exportResponse;
|
||||
exportResponse = null;
|
||||
return dat;
|
||||
}
|
||||
|
||||
public static String worldStatusString() {
|
||||
return worldStatusString;
|
||||
}
|
||||
|
||||
public static float worldStatusProgress() {
|
||||
return worldStatusProgress;
|
||||
}
|
||||
|
||||
public static IPCPacket15Crashed worldStatusError() {
|
||||
return exceptions.size() > 0 ? exceptions.remove(0) : null;
|
||||
}
|
||||
|
||||
public static IPCPacket15Crashed[] worldStatusErrors() {
|
||||
int l = exceptions.size();
|
||||
if(l == 0) {
|
||||
return null;
|
||||
}
|
||||
IPCPacket15Crashed[] pkts = exceptions.toArray(new IPCPacket15Crashed[l]);
|
||||
exceptions.clear();
|
||||
return pkts;
|
||||
}
|
||||
|
||||
public static void clearPlayerData(String worldName) {
|
||||
ensureReady();
|
||||
statusState = IntegratedServerState.WORLD_CLEAR_PLAYERS;
|
||||
sendIPCPacket(new IPCPacket18ClearPlayers(worldName));
|
||||
}
|
||||
|
||||
private static void loadSaveComparators() {
|
||||
saveListMap.clear();
|
||||
saveListCache.clear();
|
||||
for(NBTTagCompound nbt : saveListNBT) {
|
||||
String folderName = nbt.getString("folderNameEagler");
|
||||
if(!StringUtils.isEmpty(folderName)) {
|
||||
WorldInfo worldinfo = new WorldInfo(nbt.getCompoundTag("Data"));
|
||||
saveListMap.put(folderName, worldinfo);
|
||||
String s1 = worldinfo.getWorldName();
|
||||
if (StringUtils.isEmpty(s1)) {
|
||||
s1 = folderName;
|
||||
}
|
||||
|
||||
long i = 0L;
|
||||
saveListCache.add(new SaveFormatComparator(folderName, s1, worldinfo.getLastTimePlayed(), i,
|
||||
worldinfo.getGameType(), false, worldinfo.isHardcoreModeEnabled(),
|
||||
worldinfo.areCommandsAllowed(), nbt));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "eaglercraft";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ISaveHandler getSaveLoader(String var1, boolean var2) {
|
||||
return new SingleplayerSaveHandler(saveListMap.get(var1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SaveFormatComparator> getSaveList() {
|
||||
return saveListCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushCache() {
|
||||
sendIPCPacket(new IPCPacket0EListWorlds());
|
||||
statusState = IntegratedServerState.WORLD_LISTING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldInfo getWorldInfo(String var1) {
|
||||
return saveListMap.get(var1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean func_154335_d(String var1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteWorldDirectory(String var1) {
|
||||
sendIPCPacket(new IPCPacket03DeleteWorld(var1));
|
||||
statusState = IntegratedServerState.WORLD_DELETING;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renameWorld(String var1, String var2) {
|
||||
sendIPCPacket(new IPCPacket06RenameWorldNBT(var1, var2, false));
|
||||
statusState = IntegratedServerState.WORLD_RENAMING;
|
||||
}
|
||||
|
||||
public static void duplicateWorld(String var1, String var2) {
|
||||
sendIPCPacket(new IPCPacket06RenameWorldNBT(var1, var2, true));
|
||||
statusState = IntegratedServerState.WORLD_DUPLICATING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean func_154334_a(String var1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOldMapFormat(String var1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean convertMapFormat(String var1, IProgressUpdate var2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canLoadWorld(String var1) {
|
||||
return saveListMap.containsKey(var1);
|
||||
}
|
||||
|
||||
public static boolean canKillWorker() {
|
||||
return ClientPlatformSingleplayer.canKillWorker();
|
||||
}
|
||||
|
||||
public static void killWorker() {
|
||||
statusState = IntegratedServerState.WORLD_WORKER_NOT_RUNNING;
|
||||
ClientPlatformSingleplayer.killWorker();
|
||||
LANServerController.closeLAN();
|
||||
}
|
||||
|
||||
public static void updateLocale(List<String> dump) {
|
||||
if(statusState != IntegratedServerState.WORLD_WORKER_NOT_RUNNING) {
|
||||
sendIPCPacket(new IPCPacket14StringList(IPCPacket14StringList.LOCALE, dump));
|
||||
}
|
||||
}
|
||||
|
||||
public static void setDifficulty(int difficultyId) {
|
||||
if(isWorldRunning()) {
|
||||
sendIPCPacket(new IPCPacket0ASetWorldDifficulty((byte)difficultyId));
|
||||
}
|
||||
}
|
||||
|
||||
public static void configureLAN(net.minecraft.world.WorldSettings.GameType enumGameType, boolean allowCommands) {
|
||||
sendIPCPacket(new IPCPacket17ConfigureLAN(enumGameType.getID(), allowCommands, LANServerController.currentICEServers));
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.FileChooserResult;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.ImageData;
|
||||
import net.lax1dude.eaglercraft.v1_8.profile.SkinPackets;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.network.play.client.C17PacketCustomPayload;
|
||||
import net.minecraft.util.ChatComponentTranslation;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class SkullCommand {
|
||||
|
||||
private final Minecraft mc;
|
||||
private boolean waitingForSelection = false;
|
||||
|
||||
public SkullCommand(Minecraft mc) {
|
||||
this.mc = mc;
|
||||
}
|
||||
|
||||
public void openFileChooser() {
|
||||
EagRuntime.displayFileChooser("image/png", "png");
|
||||
waitingForSelection = true;
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if(waitingForSelection && EagRuntime.fileChooserHasResult()) {
|
||||
waitingForSelection = false;
|
||||
FileChooserResult fr = EagRuntime.getFileChooserResult();
|
||||
if(fr == null || mc.thePlayer == null || mc.thePlayer.sendQueue == null) {
|
||||
return;
|
||||
}
|
||||
ImageData loaded = ImageData.loadImageFile(fr.fileData);
|
||||
if(loaded == null) {
|
||||
mc.ingameGUI.getChatGUI().printChatMessage(new ChatComponentTranslation("command.skull.error.invalid.png"));
|
||||
return;
|
||||
}
|
||||
if(loaded.width != 64 || loaded.height > 64) {
|
||||
mc.ingameGUI.getChatGUI().printChatMessage(new ChatComponentTranslation("command.skull.error.invalid.skin", loaded.width, loaded.height));
|
||||
return;
|
||||
}
|
||||
byte[] rawSkin = new byte[loaded.pixels.length << 2];
|
||||
for(int i = 0, j, k; i < 4096; ++i) {
|
||||
j = i << 2;
|
||||
k = loaded.pixels[i];
|
||||
rawSkin[j] = (byte)(k >> 24);
|
||||
rawSkin[j + 1] = (byte)(k >> 16);
|
||||
rawSkin[j + 2] = (byte)(k >> 8);
|
||||
rawSkin[j + 3] = (byte)(k & 0xFF);
|
||||
}
|
||||
mc.thePlayer.sendQueue.addToSendQueue(new C17PacketCustomPayload("EAG|Skins-1.8", SkinPackets.writeCreateCustomSkull(rawSkin)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class WorkerStartupFailedException extends RuntimeException {
|
||||
|
||||
public WorkerStartupFailedException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.internal.ClientPlatformSingleplayer;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class CrashScreen {
|
||||
|
||||
public static void showCrashReportOverlay(String report, int x, int y, int w, int h) {
|
||||
ClientPlatformSingleplayer.showCrashReportOverlay(report, x, y, w, h);
|
||||
}
|
||||
|
||||
public static void hideCrashReportOverlay() {
|
||||
ClientPlatformSingleplayer.hideCrashReportOverlay();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.SingleplayerServerController;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiSelectWorld;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiIntegratedServerStartup extends GuiScreen {
|
||||
|
||||
private final GuiScreen backScreen;
|
||||
private static final String[] dotDotDot = new String[] { "", ".", "..", "..." };
|
||||
|
||||
private int counter = 0;
|
||||
|
||||
public GuiIntegratedServerStartup(GuiScreen backScreen) {
|
||||
this.backScreen = backScreen;
|
||||
}
|
||||
|
||||
protected void keyTyped(char parChar1, int parInt1) {
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
this.buttonList.clear();
|
||||
}
|
||||
|
||||
public void updateScreen() {
|
||||
++counter;
|
||||
if(counter > 1 && SingleplayerServerController.isIntegratedServerWorkerStarted()) {
|
||||
mc.displayGuiScreen(new GuiSelectWorld(backScreen));
|
||||
}else if(counter == 2) {
|
||||
SingleplayerServerController.startIntegratedServerWorker();
|
||||
}
|
||||
}
|
||||
|
||||
public void drawScreen(int i, int j, float f) {
|
||||
this.drawBackground(0);
|
||||
String txt = I18n.format("singleplayer.integratedStartup");
|
||||
int w = this.fontRendererObj.getStringWidth(txt);
|
||||
this.drawString(this.fontRendererObj, txt + dotDotDot[(int)((System.currentTimeMillis() / 300L) % 4L)], (this.width - w) / 2, this.height / 2 - 50, 16777215);
|
||||
super.drawScreen(i, j, f);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.Mouse;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.EnumCursorType;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.lan.LANServerController;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.audio.PositionedSoundRecord;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiNetworkSettingsButton extends Gui {
|
||||
|
||||
private final GuiScreen screen;
|
||||
private final String text;
|
||||
private final Minecraft mc;
|
||||
|
||||
public GuiNetworkSettingsButton(GuiScreen screen) {
|
||||
this.screen = screen;
|
||||
this.text = I18n.format("directConnect.lanWorldRelay");
|
||||
this.mc = Minecraft.getMinecraft();
|
||||
}
|
||||
|
||||
public void drawScreen(int xx, int yy) {
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.scale(0.75f, 0.75f, 0.75f);
|
||||
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
int w = mc.fontRendererObj.getStringWidth(text);
|
||||
boolean hover = xx > 1 && yy > 1 && xx < (w * 3 / 4) + 7 && yy < 12;
|
||||
if(hover) {
|
||||
Mouse.showCursor(EnumCursorType.HAND);
|
||||
}
|
||||
|
||||
drawString(mc.fontRendererObj, EnumChatFormatting.UNDERLINE + text, 5, 5, hover ? 0xFFEEEE22 : 0xFFCCCCCC);
|
||||
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
public void mouseClicked(int xx, int yy, int btn) {
|
||||
int w = mc.fontRendererObj.getStringWidth(text);
|
||||
if(xx > 2 && yy > 2 && xx < (w * 3 / 4) + 5 && yy < 12) {
|
||||
if(LANServerController.supported()) {
|
||||
mc.displayGuiScreen(GuiScreenLANInfo.showLANInfoScreen(new GuiScreenRelay(screen)));
|
||||
}else {
|
||||
mc.displayGuiScreen(new GuiScreenLANNotSupported(screen));
|
||||
}
|
||||
this.mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.Keyboard;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayManager;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenAddRelay extends GuiScreen {
|
||||
|
||||
/** This GUI's parent GUI. */
|
||||
private GuiScreenRelay parentGui;
|
||||
private GuiTextField serverAddress;
|
||||
private GuiTextField serverName;
|
||||
|
||||
public GuiScreenAddRelay(GuiScreenRelay par1GuiScreen) {
|
||||
this.parentGui = par1GuiScreen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the main game loop to update the screen.
|
||||
*/
|
||||
public void updateScreen() {
|
||||
this.serverName.updateCursorCounter();
|
||||
this.serverAddress.updateCursorCounter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the buttons (and other controls) to the screen in question.
|
||||
*/
|
||||
public void initGui() {
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
this.buttonList.clear();
|
||||
this.parentGui.addNewName = RelayManager.relayManager.makeNewRelayName();
|
||||
this.parentGui.addNewAddr = "";
|
||||
this.parentGui.addNewPrimary = RelayManager.relayManager.count() == 0;
|
||||
int sslOff = EagRuntime.requireSSL() ? 36 : 0;
|
||||
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 + 96 + 12 + sslOff, I18n.format("addRelay.add")));
|
||||
this.buttonList.add(new GuiButton(1, this.width / 2 - 100, this.height / 4 + 120 + 12 + sslOff, I18n.format("gui.cancel")));
|
||||
this.buttonList.add(new GuiButton(2, this.width / 2 - 100, 142, I18n.format("addRelay.primary") + ": " + (this.parentGui.addNewPrimary ? I18n.format("gui.yes") : I18n.format("gui.no"))));
|
||||
this.serverName = new GuiTextField(3, this.fontRendererObj, this.width / 2 - 100, 106, 200, 20);
|
||||
this.serverAddress = new GuiTextField(4, this.fontRendererObj, this.width / 2 - 100, 66, 200, 20);
|
||||
this.serverAddress.setMaxStringLength(128);
|
||||
this.serverAddress.setFocused(true);
|
||||
((GuiButton) this.buttonList.get(0)).enabled = this.serverAddress.getText().length() > 0 && this.serverAddress.getText().split(":").length > 0 && this.serverName.getText().length() > 0;
|
||||
this.serverName.setText(this.parentGui.addNewName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the screen is unloaded. Used to disable keyboard repeat events
|
||||
*/
|
||||
public void onGuiClosed() {
|
||||
Keyboard.enableRepeatEvents(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when a control is clicked. This is the equivalent of
|
||||
* ActionListener.actionPerformed(ActionEvent e).
|
||||
*/
|
||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||
if (par1GuiButton.enabled) {
|
||||
if (par1GuiButton.id == 1) {
|
||||
this.parentGui.confirmClicked(false, 0);
|
||||
} else if (par1GuiButton.id == 0) {
|
||||
this.parentGui.addNewName = this.serverName.getText();
|
||||
this.parentGui.addNewAddr = this.serverAddress.getText();
|
||||
this.parentGui.confirmClicked(true, 0);
|
||||
} else if (par1GuiButton.id == 2) {
|
||||
this.parentGui.addNewPrimary = !this.parentGui.addNewPrimary;
|
||||
((GuiButton) this.buttonList.get(2)).displayString = I18n.format("addRelay.primary") + ": " + (this.parentGui.addNewPrimary ? I18n.format("gui.yes") : I18n.format("gui.no"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when a key is typed. This is the equivalent of
|
||||
* KeyListener.keyTyped(KeyEvent e).
|
||||
*/
|
||||
protected void keyTyped(char par1, int par2) {
|
||||
this.serverName.textboxKeyTyped(par1, par2);
|
||||
this.serverAddress.textboxKeyTyped(par1, par2);
|
||||
|
||||
if (par1 == 9) {
|
||||
if (this.serverName.isFocused()) {
|
||||
this.serverName.setFocused(false);
|
||||
this.serverAddress.setFocused(true);
|
||||
} else {
|
||||
this.serverName.setFocused(true);
|
||||
this.serverAddress.setFocused(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (par1 == 13) {
|
||||
this.actionPerformed((GuiButton) this.buttonList.get(0));
|
||||
}
|
||||
|
||||
((GuiButton) this.buttonList.get(0)).enabled = this.serverAddress.getText().length() > 0 && this.serverAddress.getText().split(":").length > 0 && this.serverName.getText().length() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the mouse is clicked.
|
||||
*/
|
||||
protected void mouseClicked(int par1, int par2, int par3) {
|
||||
super.mouseClicked(par1, par2, par3);
|
||||
this.serverAddress.mouseClicked(par1, par2, par3);
|
||||
this.serverName.mouseClicked(par1, par2, par3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the screen and all the components in it.
|
||||
*/
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawBackground(0);
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("addRelay.title"), this.width / 2, 17, 16777215);
|
||||
this.drawString(this.fontRendererObj, I18n.format("addRelay.address"), this.width / 2 - 100, 53, 10526880);
|
||||
this.drawString(this.fontRendererObj, I18n.format("addRelay.name"), this.width / 2 - 100, 94, 10526880);
|
||||
if(EagRuntime.requireSSL()) {
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("addServer.SSLWarn1"), this.width / 2, 169, 0xccccff);
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("addServer.SSLWarn2"), this.width / 2, 181, 0xccccff);
|
||||
}
|
||||
this.serverName.drawTextBox();
|
||||
this.serverAddress.drawTextBox();
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.profile.EaglerProfile;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.SingleplayerServerController;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.ipc.IPCPacket05RequestData;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiCreateWorld;
|
||||
import net.minecraft.client.gui.GuiRenameWorld;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiYesNo;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.world.storage.WorldInfo;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenBackupWorldSelection extends GuiScreen {
|
||||
|
||||
private GuiScreen selectWorld;
|
||||
|
||||
private GuiButton worldRecreate = null;
|
||||
private GuiButton worldDuplicate = null;
|
||||
private GuiButton worldExport = null;
|
||||
private GuiButton worldConvert = null;
|
||||
private GuiButton worldBackup = null;
|
||||
private long worldSeed;
|
||||
private NBTTagCompound levelDat;
|
||||
|
||||
private String worldName;
|
||||
|
||||
public GuiScreenBackupWorldSelection(GuiScreen selectWorld, String worldName, NBTTagCompound levelDat) {
|
||||
this.selectWorld = selectWorld;
|
||||
this.worldName = worldName;
|
||||
this.levelDat = levelDat;
|
||||
this.worldSeed = levelDat.getCompoundTag("Data").getLong("RandomSeed");
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
this.buttonList.add(worldRecreate = new GuiButton(1, this.width / 2 - 100, this.height / 5 + 5, I18n.format("singleplayer.backup.recreate")));
|
||||
this.buttonList.add(worldDuplicate = new GuiButton(2, this.width / 2 - 100, this.height / 5 + 30, I18n.format("singleplayer.backup.duplicate")));
|
||||
this.buttonList.add(worldExport = new GuiButton(3, this.width / 2 - 100, this.height / 5 + 80, I18n.format("singleplayer.backup.export")));
|
||||
this.buttonList.add(worldConvert = new GuiButton(4, this.width / 2 - 100, this.height / 5 + 105, I18n.format("singleplayer.backup.vanilla")));
|
||||
this.buttonList.add(worldBackup = new GuiButton(5, this.width / 2 - 100, this.height / 5 + 136, I18n.format("singleplayer.backup.clearPlayerData")));
|
||||
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 + 155, I18n.format("gui.cancel")));
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawDefaultBackground();
|
||||
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("singleplayer.backup.title", worldName), this.width / 2, this.height / 5 - 35, 16777215);
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("singleplayer.backup.seed") + " " + worldSeed, this.width / 2, this.height / 5 + 62, 0xAAAAFF);
|
||||
|
||||
int toolTipColor = 0xDDDDAA;
|
||||
if(worldRecreate.isMouseOver()) {
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("singleplayer.backup.recreate.tooltip"), this.width / 2, this.height / 5 - 12, toolTipColor);
|
||||
}else if(worldDuplicate.isMouseOver()) {
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("singleplayer.backup.duplicate.tooltip"), this.width / 2, this.height / 5 - 12, toolTipColor);
|
||||
}else if(worldExport.isMouseOver()) {
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("singleplayer.backup.export.tooltip"), this.width / 2, this.height / 5 - 12, toolTipColor);
|
||||
}else if(worldConvert.isMouseOver()) {
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("singleplayer.backup.vanilla.tooltip"), this.width / 2, this.height / 5 - 12, toolTipColor);
|
||||
}else if(worldBackup.isMouseOver()) {
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("singleplayer.backup.clearPlayerData.tooltip"), this.width / 2, this.height / 5 - 12, toolTipColor);
|
||||
}
|
||||
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||
if(par1GuiButton.id == 0) {
|
||||
this.mc.displayGuiScreen(selectWorld);
|
||||
}else if(par1GuiButton.id == 1) {
|
||||
GuiCreateWorld cw = new GuiCreateWorld(selectWorld);
|
||||
cw.func_146318_a(new WorldInfo(this.levelDat.getCompoundTag("Data")));
|
||||
this.mc.displayGuiScreen(cw);
|
||||
}else if(par1GuiButton.id == 2) {
|
||||
this.mc.displayGuiScreen(new GuiRenameWorld(this.selectWorld, this.worldName, true));
|
||||
}else if(par1GuiButton.id == 3) {
|
||||
SingleplayerServerController.exportWorld(worldName, IPCPacket05RequestData.REQUEST_LEVEL_EAG);
|
||||
this.mc.displayGuiScreen(new GuiScreenIntegratedServerBusy(selectWorld, "singleplayer.busy.exporting.1", "singleplayer.failed.exporting.1", () -> {
|
||||
byte[] b = SingleplayerServerController.getExportResponse();
|
||||
if(b != null) {
|
||||
EagRuntime.downloadFileWithName(worldName + ".epk", b);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}));
|
||||
}else if(par1GuiButton.id == 4) {
|
||||
SingleplayerServerController.exportWorld(worldName, IPCPacket05RequestData.REQUEST_LEVEL_MCA);
|
||||
this.mc.displayGuiScreen(new GuiScreenIntegratedServerBusy(selectWorld, "singleplayer.busy.exporting.2", "singleplayer.failed.exporting.2", () -> {
|
||||
byte[] b = SingleplayerServerController.getExportResponse();
|
||||
if(b != null) {
|
||||
EagRuntime.downloadFileWithName(worldName + ".zip", b);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}));
|
||||
}else if(par1GuiButton.id == 5) {
|
||||
this.mc.displayGuiScreen(new GuiYesNo(this, I18n.format("singleplayer.backup.clearPlayerData.warning1"),
|
||||
I18n.format("singleplayer.backup.clearPlayerData.warning2", worldName, EaglerProfile.getName()), 0));
|
||||
}
|
||||
}
|
||||
|
||||
public void confirmClicked(boolean par1, int par2) {
|
||||
if(par1) {
|
||||
SingleplayerServerController.clearPlayerData(worldName);
|
||||
this.mc.displayGuiScreen(new GuiScreenIntegratedServerBusy(this, "singleplayer.busy.clearplayers", "singleplayer.failed.clearplayers", () -> SingleplayerServerController.isReady()));
|
||||
}else {
|
||||
mc.displayGuiScreen(this);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenChangeRelayTimeout extends GuiScreen {
|
||||
|
||||
private GuiScreen parent;
|
||||
private GuiSlider2 slider;
|
||||
private String title;
|
||||
|
||||
public GuiScreenChangeRelayTimeout(GuiScreen parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
title = I18n.format("networkSettings.relayTimeoutTitle");
|
||||
buttonList.clear();
|
||||
buttonList.add(new GuiButton(0, width / 2 - 100, height / 3 + 55, I18n.format("gui.done")));
|
||||
buttonList.add(new GuiButton(1, width / 2 - 100, height / 3 + 85, I18n.format("gui.cancel")));
|
||||
slider = new GuiSlider2(0, width / 2 - 100, height / 3 + 10, 200, 20, (mc.gameSettings.relayTimeout - 1) / 14.0f, 1.0f) {
|
||||
public boolean mousePressed(Minecraft par1Minecraft, int par2, int par3) {
|
||||
if(super.mousePressed(par1Minecraft, par2, par3)) {
|
||||
this.displayString = "" + (int)((sliderValue * 14.0f) + 1.0f) + "s";
|
||||
return true;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public void mouseDragged(Minecraft par1Minecraft, int par2, int par3) {
|
||||
super.mouseDragged(par1Minecraft, par2, par3);
|
||||
this.displayString = "" + (int)((sliderValue * 14.0f) + 1.0f) + "s";
|
||||
}
|
||||
};
|
||||
slider.displayString = "" + mc.gameSettings.relayTimeout + "s";
|
||||
}
|
||||
|
||||
public void actionPerformed(GuiButton btn) {
|
||||
if(btn.id == 0) {
|
||||
mc.gameSettings.relayTimeout = (int)((slider.sliderValue * 14.0f) + 1.0f);
|
||||
mc.gameSettings.saveOptions();
|
||||
mc.displayGuiScreen(parent);
|
||||
}else if(btn.id == 1) {
|
||||
mc.displayGuiScreen(parent);
|
||||
}
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
drawBackground(0);
|
||||
drawCenteredString(fontRendererObj, title, width / 2, height / 3 - 20, 0xFFFFFF);
|
||||
slider.drawButton(mc, par1, par2);
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
|
||||
public void mouseClicked(int mx, int my, int button) {
|
||||
slider.mousePressed(mc, mx, my);
|
||||
super.mouseClicked(mx, my, button);
|
||||
}
|
||||
|
||||
public void mouseReleased(int par1, int par2, int par3) {
|
||||
if(par3 == 0) {
|
||||
slider.mouseReleased(par1, par2);
|
||||
}
|
||||
super.mouseReleased(par1, par2, par3);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,74 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.lan.LANServerController;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiMultiplayer;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiScreenServerList;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenConnectOption extends GuiScreen {
|
||||
|
||||
private final GuiMultiplayer guiScreen;
|
||||
private String title;
|
||||
private String prompt;
|
||||
|
||||
private final GuiNetworkSettingsButton relaysButton;
|
||||
|
||||
public GuiScreenConnectOption(GuiMultiplayer guiScreen) {
|
||||
this.guiScreen = guiScreen;
|
||||
this.relaysButton = new GuiNetworkSettingsButton(this);
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
title = I18n.format("selectServer.direct");
|
||||
prompt = I18n.format("directConnect.prompt");
|
||||
buttonList.clear();
|
||||
buttonList.add(new GuiButton(1, this.width / 2 - 100, this.height / 4 - 60 + 90, I18n.format("directConnect.serverJoin")));
|
||||
buttonList.add(new GuiButton(2, this.width / 2 - 100, this.height / 4 - 60 + 115, I18n.format("directConnect.lanWorld")));
|
||||
buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 - 60 + 155, I18n.format("gui.cancel")));
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||
if(par1GuiButton.id == 0) {
|
||||
mc.displayGuiScreen(guiScreen);
|
||||
}else if(par1GuiButton.id == 1) {
|
||||
mc.displayGuiScreen(new GuiScreenServerList(guiScreen, guiScreen.getSelectedServer()));
|
||||
}else if(par1GuiButton.id == 2) {
|
||||
if(LANServerController.supported()) {
|
||||
mc.displayGuiScreen(GuiScreenLANInfo.showLANInfoScreen(new GuiScreenLANConnect(guiScreen)));
|
||||
}else {
|
||||
mc.displayGuiScreen(new GuiScreenLANNotSupported(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawDefaultBackground();
|
||||
this.drawCenteredString(this.fontRendererObj, title, this.width / 2, this.height / 4 - 60 + 20, 16777215);
|
||||
this.drawCenteredString(this.fontRendererObj, prompt, this.width / 2, this.height / 4 - 60 + 55, 0x999999);
|
||||
super.drawScreen(par1, par2, par3);
|
||||
relaysButton.drawScreen(par1, par2);
|
||||
}
|
||||
|
||||
protected void mouseClicked(int par1, int par2, int par3) {
|
||||
relaysButton.mouseClicked(par1, par2, par3);
|
||||
super.mouseClicked(par1, par2, par3);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.FileChooserResult;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiCreateWorld;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenCreateWorldSelection extends GuiScreen {
|
||||
|
||||
private GuiScreen mainmenu;
|
||||
private GuiButton worldCreate = null;
|
||||
private GuiButton worldImport = null;
|
||||
private GuiButton worldVanilla = null;
|
||||
private boolean isImportingEPK = false;
|
||||
private boolean isImportingMCA = false;
|
||||
|
||||
public GuiScreenCreateWorldSelection(GuiScreen mainmenu) {
|
||||
this.mainmenu = mainmenu;
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
this.buttonList.add(worldCreate = new GuiButton(1, this.width / 2 - 100, this.height / 4 + 40, I18n.format("singleplayer.create.create")));
|
||||
this.buttonList.add(worldImport = new GuiButton(2, this.width / 2 - 100, this.height / 4 + 65, I18n.format("singleplayer.create.import")));
|
||||
this.buttonList.add(worldVanilla = new GuiButton(3, this.width / 2 - 100, this.height / 4 + 90, I18n.format("singleplayer.create.vanilla")));
|
||||
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 + 130, I18n.format("gui.cancel")));
|
||||
}
|
||||
|
||||
public void updateScreen() {
|
||||
if(EagRuntime.fileChooserHasResult() && (isImportingEPK || isImportingMCA)) {
|
||||
FileChooserResult fr = EagRuntime.getFileChooserResult();
|
||||
if(fr != null) {
|
||||
this.mc.displayGuiScreen(new GuiScreenNameWorldImport(mainmenu, fr, isImportingEPK ? 0 : (isImportingMCA ? 1 : -1)));
|
||||
}
|
||||
isImportingEPK = isImportingMCA = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawDefaultBackground();
|
||||
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("singleplayer.create.title"), this.width / 2, this.height / 4, 16777215);
|
||||
|
||||
int toolTipColor = 0xDDDDAA;
|
||||
if(worldCreate.isMouseOver()) {
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("singleplayer.create.create.tooltip"), this.width / 2, this.height / 4 + 20, toolTipColor);
|
||||
}else if(worldImport.isMouseOver()) {
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("singleplayer.create.import.tooltip"), this.width / 2, this.height / 4 + 20, toolTipColor);
|
||||
}else if(worldVanilla.isMouseOver()) {
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("singleplayer.create.vanilla.tooltip"), this.width / 2, this.height / 4 + 20, toolTipColor);
|
||||
}
|
||||
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||
if(par1GuiButton.id == 0) {
|
||||
this.mc.displayGuiScreen(mainmenu);
|
||||
}else if(par1GuiButton.id == 1) {
|
||||
this.mc.displayGuiScreen(new GuiCreateWorld(mainmenu));
|
||||
}else if(par1GuiButton.id == 2) {
|
||||
isImportingEPK = true;
|
||||
EagRuntime.displayFileChooser(null, "epk");
|
||||
}else if(par1GuiButton.id == 3) {
|
||||
isImportingMCA = true;
|
||||
EagRuntime.displayFileChooser(null, "zip");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenDemoIntegratedServerFailed extends GuiScreen {
|
||||
|
||||
private String str1;
|
||||
private String str2;
|
||||
|
||||
public GuiScreenDemoIntegratedServerFailed() {
|
||||
this.str1 = I18n.format("singleplayer.failed.demo.title");
|
||||
this.str2 = I18n.format("singleplayer.failed.demo.desc");
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawDefaultBackground();
|
||||
this.drawCenteredString(fontRendererObj, str1, this.width / 2, 70, 11184810);
|
||||
this.drawCenteredString(fontRendererObj, str2, this.width / 2, 90, 16777215);
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.SingleplayerServerController;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.WorkerStartupFailedException;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.ipc.IPCPacket15Crashed;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenDemoIntegratedServerStartup extends GuiScreen {
|
||||
|
||||
private final GuiScreen contScreen;
|
||||
private static final String[] dotDotDot = new String[] { "", ".", "..", "..." };
|
||||
|
||||
private int counter = 0;
|
||||
|
||||
public GuiScreenDemoIntegratedServerStartup(GuiScreen contScreen) {
|
||||
this.contScreen = contScreen;
|
||||
}
|
||||
|
||||
protected void keyTyped(char parChar1, int parInt1) {
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
this.buttonList.clear();
|
||||
}
|
||||
|
||||
public void updateScreen() {
|
||||
++counter;
|
||||
if(counter == 2) {
|
||||
try {
|
||||
SingleplayerServerController.startIntegratedServerWorker();
|
||||
}catch(WorkerStartupFailedException ex) {
|
||||
mc.displayGuiScreen(new GuiScreenIntegratedServerFailed(ex.getMessage(), new GuiScreenDemoIntegratedServerFailed()));
|
||||
return;
|
||||
}
|
||||
}else if(counter > 2) {
|
||||
IPCPacket15Crashed[] crashReport = SingleplayerServerController.worldStatusErrors();
|
||||
if(crashReport != null) {
|
||||
mc.displayGuiScreen(GuiScreenIntegratedServerBusy.createException(new GuiScreenDemoIntegratedServerFailed(), "singleplayer.failed.notStarted", crashReport));
|
||||
}else if(SingleplayerServerController.isIntegratedServerWorkerStarted()) {
|
||||
mc.displayGuiScreen(contScreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void drawScreen(int i, int j, float f) {
|
||||
this.drawBackground(0);
|
||||
String txt = I18n.format("singleplayer.integratedStartup");
|
||||
int w = this.fontRendererObj.getStringWidth(txt);
|
||||
this.drawString(this.fontRendererObj, txt + dotDotDot[(int)((System.currentTimeMillis() / 300L) % 4L)], (this.width - w) / 2, this.height / 2 - 50, 16777215);
|
||||
super.drawScreen(i, j, f);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.lan.LANServerController;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiCreateWorld;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.world.demo.DemoWorldServer;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenDemoPlayWorldSelection extends GuiScreen {
|
||||
|
||||
private GuiScreen mainmenu;
|
||||
private GuiButton playWorld = null;
|
||||
private GuiButton joinWorld = null;
|
||||
|
||||
public GuiScreenDemoPlayWorldSelection(GuiScreen mainmenu) {
|
||||
this.mainmenu = mainmenu;
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
this.buttonList.add(playWorld = new GuiButton(1, this.width / 2 - 100, this.height / 4 + 40, I18n.format("singleplayer.demo.create.create")));
|
||||
this.buttonList.add(joinWorld = new GuiButton(2, this.width / 2 - 100, this.height / 4 + 65, I18n.format("singleplayer.demo.create.join")));
|
||||
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 + 130, I18n.format("gui.cancel")));
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawDefaultBackground();
|
||||
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("singleplayer.demo.create.title"), this.width / 2, this.height / 4, 16777215);
|
||||
|
||||
int toolTipColor = 0xDDDDAA;
|
||||
if(playWorld.isMouseOver()) {
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("singleplayer.demo.create.create.tooltip"), this.width / 2, this.height / 4 + 20, toolTipColor);
|
||||
}else if(joinWorld.isMouseOver()) {
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("singleplayer.demo.create.join.tooltip"), this.width / 2, this.height / 4 + 20, toolTipColor);
|
||||
}
|
||||
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||
if(par1GuiButton.id == 0) {
|
||||
this.mc.displayGuiScreen(mainmenu);
|
||||
}else if(par1GuiButton.id == 1) {
|
||||
this.mc.gameSettings.hasCreatedDemoWorld = true;
|
||||
this.mc.gameSettings.saveOptions();
|
||||
this.mc.launchIntegratedServer("Demo World", "Demo World", DemoWorldServer.demoWorldSettings);
|
||||
}else if(par1GuiButton.id == 2) {
|
||||
if(LANServerController.supported()) {
|
||||
this.mc.displayGuiScreen(GuiScreenLANInfo.showLANInfoScreen(new GuiScreenLANConnect(mainmenu)));
|
||||
}else {
|
||||
this.mc.displayGuiScreen(new GuiScreenLANNotSupported(mainmenu));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.SingleplayerServerController;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.ipc.IPCPacket15Crashed;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiMainMenu;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenIntegratedServerBusy extends GuiScreen {
|
||||
|
||||
public final GuiScreen menu;
|
||||
private GuiButton killTask;
|
||||
public final String failMessage;
|
||||
private BooleanSupplier checkTaskComplete;
|
||||
private Runnable taskKill;
|
||||
private String lastStatus;
|
||||
private String currentStatus;
|
||||
private BiConsumer<GuiScreen, IPCPacket15Crashed[]> onException;
|
||||
private int areYouSure;
|
||||
|
||||
private long startStartTime;
|
||||
|
||||
private static final Runnable defaultTerminateAction = () -> {
|
||||
if(SingleplayerServerController.canKillWorker()) {
|
||||
SingleplayerServerController.killWorker();
|
||||
Minecraft.getMinecraft().displayGuiScreen(new GuiScreenIntegratedServerFailed("singleplayer.failed.killed", new GuiMainMenu()));
|
||||
}else {
|
||||
EagRuntime.showPopup("Cannot kill worker tasks on desktop runtime!");
|
||||
}
|
||||
};
|
||||
|
||||
public static GuiScreen createException(GuiScreen ok, String msg, IPCPacket15Crashed[] exceptions) {
|
||||
ok = new GuiScreenIntegratedServerFailed(msg, ok);
|
||||
if(exceptions != null) {
|
||||
for(int i = exceptions.length - 1; i >= 0; --i) {
|
||||
ok = new GuiScreenIntegratedServerCrashed(ok, exceptions[i].crashReport);
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private static final BiConsumer<GuiScreen, IPCPacket15Crashed[]> defaultExceptionAction = (t, u) -> {
|
||||
GuiScreenIntegratedServerBusy tt = (GuiScreenIntegratedServerBusy) t;
|
||||
Minecraft.getMinecraft().displayGuiScreen(createException(tt.menu, tt.failMessage, u));
|
||||
};
|
||||
|
||||
public GuiScreenIntegratedServerBusy(GuiScreen menu, String progressMessage, String failMessage, BooleanSupplier checkTaskComplete) {
|
||||
this(menu, progressMessage, failMessage, checkTaskComplete, defaultExceptionAction, defaultTerminateAction);
|
||||
}
|
||||
|
||||
public GuiScreenIntegratedServerBusy(GuiScreen menu, String progressMessage, String failMessage, BooleanSupplier checkTaskComplete, BiConsumer<GuiScreen, IPCPacket15Crashed[]> exceptionAction) {
|
||||
this(menu, progressMessage, failMessage, checkTaskComplete, exceptionAction, defaultTerminateAction);
|
||||
}
|
||||
|
||||
public GuiScreenIntegratedServerBusy(GuiScreen menu, String progressMessage, String failMessage, BooleanSupplier checkTaskComplete, Runnable onTerminate) {
|
||||
this(menu, progressMessage, failMessage, checkTaskComplete, defaultExceptionAction, onTerminate);
|
||||
}
|
||||
|
||||
public GuiScreenIntegratedServerBusy(GuiScreen menu, String progressMessage, String failMessage, BooleanSupplier checkTaskComplete, BiConsumer<GuiScreen, IPCPacket15Crashed[]> onException, Runnable onTerminate) {
|
||||
this.menu = menu;
|
||||
this.failMessage = failMessage;
|
||||
this.checkTaskComplete = checkTaskComplete;
|
||||
this.onException = onException;
|
||||
this.taskKill = onTerminate;
|
||||
this.lastStatus = SingleplayerServerController.worldStatusString();
|
||||
this.currentStatus = progressMessage;
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
if(startStartTime == 0) this.startStartTime = System.currentTimeMillis();
|
||||
areYouSure = 0;
|
||||
this.buttonList.add(killTask = new GuiButton(0, this.width / 2 - 100, this.height / 3 + 50, I18n.format("singleplayer.busy.killTask")));
|
||||
killTask.enabled = false;
|
||||
}
|
||||
|
||||
public boolean doesGuiPauseGame() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawDefaultBackground();
|
||||
int top = this.height / 3;
|
||||
|
||||
long millis = System.currentTimeMillis();
|
||||
|
||||
String str = I18n.format(currentStatus);
|
||||
|
||||
long dots = (millis / 500l) % 4l;
|
||||
this.drawString(fontRendererObj, str + (dots > 0 ? "." : "") + (dots > 1 ? "." : "") + (dots > 2 ? "." : ""), (this.width - this.fontRendererObj.getStringWidth(str)) / 2, top + 10, 0xFFFFFF);
|
||||
|
||||
if(areYouSure > 0) {
|
||||
this.drawCenteredString(fontRendererObj, I18n.format("singleplayer.busy.cancelWarning"), this.width / 2, top + 25, 0xFF8888);
|
||||
}else {
|
||||
float prog = SingleplayerServerController.worldStatusProgress();
|
||||
if(this.currentStatus.equals(this.lastStatus) && prog > 0.01f) {
|
||||
this.drawCenteredString(fontRendererObj, (prog > 1.0f ? ("(" + (prog > 1000000.0f ? "" + (int)(prog / 1000000.0f) + "MB" :
|
||||
(prog > 1000.0f ? "" + (int)(prog / 1000.0f) + "kB" : "" + (int)prog + "B")) + ")") : "" + (int)(prog * 100.0f) + "%"), this.width / 2, top + 25, 0xFFFFFF);
|
||||
}else {
|
||||
long elapsed = (millis - startStartTime) / 1000l;
|
||||
if(elapsed > 3) {
|
||||
this.drawCenteredString(fontRendererObj, "(" + elapsed + "s)", this.width / 2, top + 25, 0xFFFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
|
||||
public void updateScreen() {
|
||||
long millis = System.currentTimeMillis();
|
||||
if(millis - startStartTime > 6000l && SingleplayerServerController.canKillWorker()) {
|
||||
killTask.enabled = true;
|
||||
}
|
||||
if(SingleplayerServerController.didLastCallFail() || !SingleplayerServerController.isIntegratedServerWorkerAlive()) {
|
||||
onException.accept(this, SingleplayerServerController.worldStatusErrors());
|
||||
return;
|
||||
}
|
||||
if(checkTaskComplete.getAsBoolean()) {
|
||||
this.mc.displayGuiScreen(menu);
|
||||
}
|
||||
String str = SingleplayerServerController.worldStatusString();
|
||||
if(!lastStatus.equals(str)) {
|
||||
lastStatus = str;
|
||||
currentStatus = str;
|
||||
}
|
||||
killTask.displayString = I18n.format(areYouSure > 0 ? "singleplayer.busy.confirmCancel" : "singleplayer.busy.killTask");
|
||||
if(areYouSure > 0) {
|
||||
--areYouSure;
|
||||
}
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||
if(par1GuiButton.id == 0) {
|
||||
if(areYouSure <= 0) {
|
||||
areYouSure = 80;
|
||||
}else if(areYouSure <= 65) {
|
||||
taskKill.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean shouldHangupIntegratedServer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.ScaledResolution;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenIntegratedServerCrashed extends GuiScreen {
|
||||
|
||||
private GuiScreen mainmenu;
|
||||
private String crashReport;
|
||||
|
||||
public GuiScreenIntegratedServerCrashed(GuiScreen mainmenu, String crashReport) {
|
||||
this.mainmenu = mainmenu;
|
||||
this.crashReport = crashReport;
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
this.buttonList.clear();
|
||||
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height - 50, I18n.format("singleplayer.crashed.continue")));
|
||||
ScaledResolution res = new ScaledResolution(mc);
|
||||
int i = res.getScaleFactor();
|
||||
CrashScreen.showCrashReportOverlay(crashReport, 90 * i, 60 * i, (width - 180) * i, (height - 130) * i);
|
||||
}
|
||||
|
||||
public void onGuiClosed() {
|
||||
CrashScreen.hideCrashReportOverlay();
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawDefaultBackground();
|
||||
|
||||
this.drawCenteredString(fontRendererObj, I18n.format("singleplayer.crashed.title"), this.width / 2, 25, 0xFFAAAA);
|
||||
this.drawCenteredString(fontRendererObj, I18n.format("singleplayer.crashed.checkConsole"), this.width / 2, 40, 0xBBBBBB);
|
||||
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||
if(par1GuiButton.id == 0) {
|
||||
this.mc.displayGuiScreen(mainmenu);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenIntegratedServerFailed extends GuiScreen {
|
||||
|
||||
private String str1;
|
||||
private String str2;
|
||||
private GuiScreen cont;
|
||||
|
||||
public GuiScreenIntegratedServerFailed(String str1, String str2, GuiScreen cont) {
|
||||
this.str1 = I18n.format(str1);
|
||||
this.str2 = I18n.format(str2);
|
||||
this.cont = cont;
|
||||
}
|
||||
|
||||
public GuiScreenIntegratedServerFailed(String str2, GuiScreen cont) {
|
||||
this.str1 = I18n.format("singleplayer.failed.title");
|
||||
this.str2 = I18n.format(str2);
|
||||
this.cont = cont;
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
this.buttonList.clear();
|
||||
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 6 + 96, I18n.format("singleplayer.crashed.continue")));
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawDefaultBackground();
|
||||
this.drawCenteredString(fontRendererObj, str1, this.width / 2, 70, 11184810);
|
||||
this.drawCenteredString(fontRendererObj, str2, this.width / 2, 90, 16777215);
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||
if(par1GuiButton.id == 0) {
|
||||
this.mc.displayGuiScreen(cont);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.SingleplayerServerController;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.WorkerStartupFailedException;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.ipc.IPCPacket15Crashed;
|
||||
import net.minecraft.client.gui.GuiMainMenu;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiSelectWorld;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenIntegratedServerStartup extends GuiScreen {
|
||||
|
||||
private final GuiScreen backScreen;
|
||||
private static final String[] dotDotDot = new String[] { "", ".", "..", "..." };
|
||||
|
||||
private int counter = 0;
|
||||
|
||||
public GuiScreenIntegratedServerStartup(GuiScreen backScreen) {
|
||||
this.backScreen = backScreen;
|
||||
}
|
||||
|
||||
protected void keyTyped(char parChar1, int parInt1) {
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
this.buttonList.clear();
|
||||
}
|
||||
|
||||
public void updateScreen() {
|
||||
++counter;
|
||||
if(counter == 2) {
|
||||
try {
|
||||
SingleplayerServerController.startIntegratedServerWorker();
|
||||
}catch(WorkerStartupFailedException ex) {
|
||||
mc.displayGuiScreen(new GuiScreenIntegratedServerFailed(ex.getMessage(), new GuiMainMenu()));
|
||||
return;
|
||||
}
|
||||
}else if(counter > 2) {
|
||||
IPCPacket15Crashed[] crashReport = SingleplayerServerController.worldStatusErrors();
|
||||
if(crashReport != null) {
|
||||
mc.displayGuiScreen(GuiScreenIntegratedServerBusy.createException(new GuiMainMenu(), "singleplayer.failed.notStarted", crashReport));
|
||||
}else if(SingleplayerServerController.isIntegratedServerWorkerStarted()) {
|
||||
GuiScreen cont = new GuiSelectWorld(backScreen);
|
||||
if(SingleplayerServerController.isRunningSingleThreadMode()) {
|
||||
cont = new GuiScreenIntegratedServerFailed("singleplayer.failed.singleThreadWarning.1", "singleplayer.failed.singleThreadWarning.2", cont);
|
||||
}
|
||||
mc.displayGuiScreen(cont);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void drawScreen(int i, int j, float f) {
|
||||
this.drawBackground(0);
|
||||
String txt = I18n.format("singleplayer.integratedStartup");
|
||||
int w = this.fontRendererObj.getStringWidth(txt);
|
||||
this.drawString(this.fontRendererObj, txt + dotDotDot[(int)((System.currentTimeMillis() / 300L) % 4L)], (this.width - w) / 2, this.height / 2 - 50, 16777215);
|
||||
super.drawScreen(i, j, f);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.Keyboard;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenLANConnect extends GuiScreen {
|
||||
|
||||
private final GuiScreen parent;
|
||||
private GuiTextField codeTextField;
|
||||
private final GuiNetworkSettingsButton relaysButton;
|
||||
|
||||
private static String lastCode = "";
|
||||
|
||||
public GuiScreenLANConnect(GuiScreen parent) {
|
||||
this.parent = parent;
|
||||
this.relaysButton = new GuiNetworkSettingsButton(this);
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
this.buttonList.clear();
|
||||
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 + 96 + 12, I18n.format("directConnect.lanWorldJoin")));
|
||||
this.buttonList.add(new GuiButton(1, this.width / 2 - 100, this.height / 4 + 120 + 12, I18n.format("gui.cancel")));
|
||||
this.codeTextField = new GuiTextField(2, this.fontRendererObj, this.width / 2 - 100, this.height / 4 + 27, 200, 20);
|
||||
this.codeTextField.setMaxStringLength(48);
|
||||
this.codeTextField.setFocused(true);
|
||||
this.codeTextField.setText(lastCode);
|
||||
this.buttonList.get(0).enabled = this.codeTextField.getText().trim().length() > 0;
|
||||
}
|
||||
|
||||
public void onGuiClosed() {
|
||||
Keyboard.enableRepeatEvents(false);
|
||||
lastCode = this.codeTextField.getText().trim();
|
||||
}
|
||||
|
||||
protected void keyTyped(char par1, int par2) {
|
||||
if (this.codeTextField.textboxKeyTyped(par1, par2)) {
|
||||
((GuiButton) this.buttonList.get(0)).enabled = this.codeTextField.getText().trim().length() > 0;
|
||||
} else if (par2 == 28) {
|
||||
this.actionPerformed(this.buttonList.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
public void updateScreen() {
|
||||
this.codeTextField.updateCursorCounter();
|
||||
}
|
||||
|
||||
protected void mouseClicked(int par1, int par2, int par3) {
|
||||
super.mouseClicked(par1, par2, par3);
|
||||
this.codeTextField.mouseClicked(par1, par2, par3);
|
||||
this.relaysButton.mouseClicked(par1, par2, par3);
|
||||
}
|
||||
|
||||
public void drawScreen(int xx, int yy, float pt) {
|
||||
this.drawDefaultBackground();
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("selectServer.direct"), this.width / 2, this.height / 4 - 60 + 20, 16777215);
|
||||
this.drawString(this.fontRendererObj, I18n.format("directConnect.lanWorldCode"), this.width / 2 - 100, this.height / 4 + 12, 10526880);
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("directConnect.networkSettingsNote"), this.width / 2, this.height / 4 + 63, 10526880);
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("directConnect.ipGrabNote"), this.width / 2, this.height / 4 + 77, 10526880);
|
||||
this.codeTextField.drawTextBox();
|
||||
super.drawScreen(xx, yy, pt);
|
||||
this.relaysButton.drawScreen(xx, yy);
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||
if(par1GuiButton.id == 1) {
|
||||
mc.displayGuiScreen(parent);
|
||||
}else if(par1GuiButton.id == 0) {
|
||||
mc.displayGuiScreen(new GuiScreenLANConnecting(parent, this.codeTextField.getText().trim()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,125 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC;
|
||||
import net.lax1dude.eaglercraft.v1_8.profile.EaglerProfile;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.lan.LANClientNetworkManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServer;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerSocket;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.socket.NetHandlerSingleplayerLogin;
|
||||
import net.minecraft.client.LoadingScreenRenderer;
|
||||
import net.minecraft.client.gui.GuiDisconnected;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.network.EnumConnectionState;
|
||||
import net.minecraft.network.login.client.C00PacketLoginStart;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenLANConnecting extends GuiScreen {
|
||||
|
||||
private final GuiScreen parent;
|
||||
private final String code;
|
||||
private final RelayServer relay;
|
||||
|
||||
private boolean completed = false;
|
||||
|
||||
private LANClientNetworkManager networkManager = null;
|
||||
|
||||
private int renderCount = 0;
|
||||
|
||||
public GuiScreenLANConnecting(GuiScreen parent, String code) {
|
||||
this.parent = parent;
|
||||
this.code = code;
|
||||
this.relay = null;
|
||||
}
|
||||
|
||||
public GuiScreenLANConnecting(GuiScreen parent, String code, RelayServer relay) {
|
||||
this.parent = parent;
|
||||
this.code = code;
|
||||
this.relay = relay;
|
||||
}
|
||||
|
||||
public boolean doesGuiPauseGame() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void updateScreen() {
|
||||
if(networkManager != null) {
|
||||
if (networkManager.isChannelOpen()) {
|
||||
try {
|
||||
networkManager.processReceivedPackets();
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
} else {
|
||||
if (networkManager.checkDisconnected()) {
|
||||
this.mc.getSession().reset();
|
||||
if (mc.currentScreen == this) {
|
||||
mc.loadWorld(null);
|
||||
mc.displayGuiScreen(new GuiDisconnected(parent, "connect.failed", new ChatComponentText("LAN Connection Refused")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawDefaultBackground();
|
||||
if(completed) {
|
||||
String message = I18n.format("connect.authorizing");
|
||||
this.drawString(fontRendererObj, message, (this.width - this.fontRendererObj.getStringWidth(message)) / 2, this.height / 3 + 10, 0xFFFFFF);
|
||||
}else {
|
||||
LoadingScreenRenderer ls = mc.loadingScreen;
|
||||
|
||||
String message = I18n.format("lanServer.pleaseWait");
|
||||
this.drawString(fontRendererObj, message, (this.width - this.fontRendererObj.getStringWidth(message)) / 2, this.height / 3 + 10, 0xFFFFFF);
|
||||
|
||||
PlatformWebRTC.startRTCLANClient();
|
||||
|
||||
if(++renderCount > 1) {
|
||||
RelayServerSocket sock;
|
||||
if(relay == null) {
|
||||
sock = RelayManager.relayManager.getWorkingRelay((str) -> ls.resetProgressAndMessage("Connecting: " + str), 0x02, code);
|
||||
}else {
|
||||
sock = RelayManager.relayManager.connectHandshake(relay, 0x02, code);
|
||||
}
|
||||
if(sock == null) {
|
||||
this.mc.displayGuiScreen(new GuiScreenNoRelays(parent, I18n.format("noRelay.worldNotFound1").replace("$code$", code),
|
||||
I18n.format("noRelay.worldNotFound2").replace("$code$", code), I18n.format("noRelay.worldNotFound3")));
|
||||
return;
|
||||
}
|
||||
|
||||
networkManager = LANClientNetworkManager.connectToWorld(sock, code, sock.getURI());
|
||||
if(networkManager == null) {
|
||||
this.mc.displayGuiScreen(new GuiDisconnected(parent, "connect.failed", new ChatComponentText(I18n.format("noRelay.worldFail").replace("$code$", code))));
|
||||
return;
|
||||
}
|
||||
|
||||
completed = true;
|
||||
|
||||
this.mc.getSession().setLAN();
|
||||
this.mc.clearTitles();
|
||||
networkManager.setConnectionState(EnumConnectionState.LOGIN);
|
||||
networkManager.setNetHandler(new NetHandlerSingleplayerLogin(networkManager, mc, parent));
|
||||
networkManager.sendPacket(new C00PacketLoginStart(this.mc.getSession().getProfile(), EaglerProfile.getSkinPacket()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenLANInfo extends GuiScreen {
|
||||
private GuiScreen parent;
|
||||
|
||||
public GuiScreenLANInfo(GuiScreen parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
buttonList.clear();
|
||||
buttonList.add(new GuiButton(0, this.width / 2 - 100, height / 6 + 168, I18n.format("gui.continue")));
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawDefaultBackground();
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("lanInfo.title"), this.width / 2, this.height / 4 - 60 + 20, 16777215);
|
||||
this.fontRendererObj.drawSplitString(I18n.format("lanInfo.desc.0") + "\n\n\n" + I18n.format("lanInfo.desc.1", I18n.format("menu.multiplayer"), I18n.format("menu.openToLan")), this.width / 2 - 100, this.height / 4 - 60 + 60, 200, -6250336);
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||
if(par1GuiButton.id == 0) {
|
||||
mc.displayGuiScreen(parent);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasShown = false;
|
||||
|
||||
public static GuiScreen showLANInfoScreen(GuiScreen cont) {
|
||||
if(!hasShown) {
|
||||
hasShown = true;
|
||||
return new GuiScreenLANInfo(cont);
|
||||
}else {
|
||||
return cont;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenLANNotSupported extends GuiScreen {
|
||||
|
||||
private GuiScreen cont;
|
||||
|
||||
public GuiScreenLANNotSupported(GuiScreen cont) {
|
||||
this.cont = cont;
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
this.buttonList.clear();
|
||||
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 6 + 96, I18n.format("singleplayer.crashed.continue")));
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawDefaultBackground();
|
||||
this.drawCenteredString(fontRendererObj, I18n.format("singleplayer.notSupported.title"), this.width / 2, 70, 11184810);
|
||||
this.drawCenteredString(fontRendererObj, I18n.format("singleplayer.notSupported.desc"), this.width / 2, 90, 16777215);
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||
if(par1GuiButton.id == 0) {
|
||||
this.mc.displayGuiScreen(cont);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,155 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.Keyboard;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.FileChooserResult;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.SingleplayerServerController;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiCreateWorld;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenNameWorldImport extends GuiScreen {
|
||||
private GuiScreen parentGuiScreen;
|
||||
private GuiTextField theGuiTextField;
|
||||
private GuiButton loadSpawnChunksBtn;
|
||||
private GuiButton enhancedGameRulesBtn;
|
||||
private int importFormat;
|
||||
private FileChooserResult world;
|
||||
private String name;
|
||||
private boolean timeToImport = false;
|
||||
private boolean definetlyTimeToImport = false;
|
||||
private boolean isImporting = false;
|
||||
private boolean loadSpawnChunks = false;
|
||||
private boolean enhancedGameRules = true;
|
||||
|
||||
public GuiScreenNameWorldImport(GuiScreen menu, FileChooserResult world, int format) {
|
||||
this.parentGuiScreen = menu;
|
||||
this.importFormat = format;
|
||||
this.world = world;
|
||||
this.name = world.fileName;
|
||||
if(name.length() > 4 && (name.endsWith(".epk") || name.endsWith(".zip"))) {
|
||||
name = name.substring(0, name.length() - 4);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the main game loop to update the screen.
|
||||
*/
|
||||
public void updateScreen() {
|
||||
if(!timeToImport) {
|
||||
this.theGuiTextField.updateCursorCounter();
|
||||
}
|
||||
if(definetlyTimeToImport && !isImporting) {
|
||||
isImporting = true;
|
||||
SingleplayerServerController.importWorld(GuiCreateWorld.func_146317_a(mc.getSaveLoader(), this.theGuiTextField.getText().trim()), world.fileData, importFormat, (byte) ((loadSpawnChunks ? 2 : 0) | (enhancedGameRules ? 1 : 0)));
|
||||
mc.displayGuiScreen(new GuiScreenIntegratedServerBusy(parentGuiScreen, "singleplayer.busy.importing." + (importFormat + 1), "singleplayer.failed.importing." + (importFormat + 1), () -> SingleplayerServerController.isReady()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the buttons (and other controls) to the screen in question.
|
||||
*/
|
||||
public void initGui() {
|
||||
if(!timeToImport) {
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
this.buttonList.clear();
|
||||
this.buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 + 96 + 12, I18n.format("singleplayer.import.continue")));
|
||||
this.buttonList.add(new GuiButton(1, this.width / 2 - 100, this.height / 4 + 120 + 12, I18n.format("gui.cancel")));
|
||||
this.theGuiTextField = new GuiTextField(2, this.fontRendererObj, this.width / 2 - 100, this.height / 4 + 3, 200, 20);
|
||||
this.theGuiTextField.setFocused(true);
|
||||
this.theGuiTextField.setText(name);
|
||||
this.buttonList.add(loadSpawnChunksBtn = new GuiButton(2, this.width / 2 - 100, this.height / 4 + 24 + 12, I18n.format("singleplayer.import.loadSpawnChunks", loadSpawnChunks ? I18n.format("gui.yes") : I18n.format("gui.no"))));
|
||||
this.buttonList.add(enhancedGameRulesBtn = new GuiButton(3, this.width / 2 - 100, this.height / 4 + 48 + 12, I18n.format("singleplayer.import.enhancedGameRules", enhancedGameRules ? I18n.format("gui.yes") : I18n.format("gui.no"))));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the screen is unloaded. Used to disable keyboard repeat events
|
||||
*/
|
||||
public void onGuiClosed() {
|
||||
Keyboard.enableRepeatEvents(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when a control is clicked. This is the equivalent of
|
||||
* ActionListener.actionPerformed(ActionEvent e).
|
||||
*/
|
||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||
if (par1GuiButton.enabled) {
|
||||
if (par1GuiButton.id == 1) {
|
||||
EagRuntime.clearFileChooserResult();
|
||||
this.mc.displayGuiScreen(this.parentGuiScreen);
|
||||
} else if (par1GuiButton.id == 0) {
|
||||
this.buttonList.clear();
|
||||
timeToImport = true;
|
||||
} else if (par1GuiButton.id == 2) {
|
||||
loadSpawnChunks = !loadSpawnChunks;
|
||||
loadSpawnChunksBtn.displayString = I18n.format("singleplayer.import.loadSpawnChunks", loadSpawnChunks ? I18n.format("gui.yes") : I18n.format("gui.no"));
|
||||
} else if (par1GuiButton.id == 3) {
|
||||
enhancedGameRules = !enhancedGameRules;
|
||||
enhancedGameRulesBtn.displayString = I18n.format("singleplayer.import.enhancedGameRules", enhancedGameRules ? I18n.format("gui.yes") : I18n.format("gui.no"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when a key is typed. This is the equivalent of
|
||||
* KeyListener.keyTyped(KeyEvent e).
|
||||
*/
|
||||
protected void keyTyped(char par1, int par2) {
|
||||
this.theGuiTextField.textboxKeyTyped(par1, par2);
|
||||
((GuiButton) this.buttonList.get(0)).enabled = this.theGuiTextField.getText().trim().length() > 0;
|
||||
|
||||
if (par1 == 13) {
|
||||
this.actionPerformed((GuiButton) this.buttonList.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the mouse is clicked.
|
||||
*/
|
||||
protected void mouseClicked(int par1, int par2, int par3) {
|
||||
super.mouseClicked(par1, par2, par3);
|
||||
if(!timeToImport) {
|
||||
this.theGuiTextField.mouseClicked(par1, par2, par3);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the screen and all the components in it.
|
||||
*/
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawDefaultBackground();
|
||||
if(!timeToImport) {
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("singleplayer.import.title"), this.width / 2, this.height / 4 - 60 + 20, 16777215);
|
||||
this.drawString(this.fontRendererObj, I18n.format("singleplayer.import.enterName"), this.width / 2 - 100, this.height / 4 - 60 + 50, 10526880);
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("createWorld.seedNote"), this.width / 2, this.height / 4 + 90, -6250336);
|
||||
this.theGuiTextField.drawTextBox();
|
||||
}else {
|
||||
definetlyTimeToImport = true;
|
||||
long dots = (System.currentTimeMillis() / 500l) % 4l;
|
||||
String str = I18n.format("singleplayer.import.reading", world.fileName);
|
||||
this.drawString(fontRendererObj, str + (dots > 0 ? "." : "") + (dots > 1 ? "." : "") + (dots > 2 ? "." : ""), (this.width - this.fontRendererObj.getStringWidth(str)) / 2, this.height / 3 + 10, 0xFFFFFF);
|
||||
}
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenNoRelays extends GuiScreen {
|
||||
|
||||
private GuiScreen parent;
|
||||
private String title1;
|
||||
private String title2;
|
||||
private String title3;
|
||||
|
||||
public GuiScreenNoRelays(GuiScreen parent, String title) {
|
||||
this.parent = parent;
|
||||
this.title1 = title;
|
||||
this.title2 = null;
|
||||
this.title3 = null;
|
||||
}
|
||||
|
||||
public GuiScreenNoRelays(GuiScreen parent, String title1, String title2, String title3) {
|
||||
this.parent = parent;
|
||||
this.title1 = title1;
|
||||
this.title2 = title2;
|
||||
this.title3 = title3;
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
buttonList.clear();
|
||||
buttonList.add(new GuiButton(0, this.width / 2 - 100, this.height / 4 - 60 + 145, I18n.format("gui.cancel")));
|
||||
buttonList.add(new GuiButton(1, this.width / 2 - 100, this.height / 4 - 60 + 115, I18n.format("directConnect.lanWorldRelay")));
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawDefaultBackground();
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format(title1), this.width / 2, this.height / 4 - 60 + 70, 16777215);
|
||||
if(title2 != null) {
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format(title2), this.width / 2, this.height / 4 - 60 + 80, 0xCCCCCC);
|
||||
}
|
||||
if(title3 != null) {
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format(title3), this.width / 2, this.height / 4 - 60 + 90, 0xCCCCCC);
|
||||
}
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||
if(par1GuiButton.id == 0) {
|
||||
mc.displayGuiScreen(parent);
|
||||
}else if(par1GuiButton.id == 1) {
|
||||
mc.displayGuiScreen(GuiScreenLANInfo.showLANInfoScreen(new GuiScreenRelay(parent)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,218 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.Mouse;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.EnumCursorType;
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServer;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.audio.PositionedSoundRecord;
|
||||
import net.minecraft.client.gui.*;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.EnumChatFormatting;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenRelay extends GuiScreen implements GuiYesNoCallback {
|
||||
|
||||
private final GuiScreen screen;
|
||||
private GuiSlotRelay slots;
|
||||
private boolean hasPinged;
|
||||
private boolean addingNew = false;
|
||||
private boolean deleting = false;
|
||||
int selected;
|
||||
|
||||
private GuiButton deleteRelay;
|
||||
private GuiButton setPrimary;
|
||||
|
||||
private String tooltipString = null;
|
||||
|
||||
private long lastRefresh = 0l;
|
||||
|
||||
public GuiScreenRelay(GuiScreen screen) {
|
||||
this.screen = screen;
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
selected = -1;
|
||||
buttonList.clear();
|
||||
buttonList.add(new GuiButton(0, this.width / 2 + 54, this.height - 28, 100, 20, I18n.format("gui.done")));
|
||||
buttonList.add(new GuiButton(1, this.width / 2 - 154, this.height - 52, 100, 20, I18n.format("networkSettings.add")));
|
||||
buttonList.add(deleteRelay = new GuiButton(2, this.width / 2 - 50, this.height - 52, 100, 20, I18n.format("networkSettings.delete")));
|
||||
buttonList.add(setPrimary = new GuiButton(3, this.width / 2 + 54, this.height - 52, 100, 20, I18n.format("networkSettings.default")));
|
||||
buttonList.add(new GuiButton(4, this.width / 2 - 50, this.height - 28, 100, 20, I18n.format("networkSettings.refresh")));
|
||||
buttonList.add(new GuiButton(5, this.width / 2 - 154, this.height - 28, 100, 20, I18n.format("networkSettings.loadDefaults")));
|
||||
buttonList.add(new GuiButton(6, this.width - 100, 0, 100, 20, I18n.format("networkSettings.downloadRelay")));
|
||||
updateButtons();
|
||||
this.slots = new GuiSlotRelay(this);
|
||||
if(!hasPinged) {
|
||||
hasPinged = true;
|
||||
slots.relayManager.ping();
|
||||
}
|
||||
}
|
||||
|
||||
void updateButtons() {
|
||||
if(selected < 0) {
|
||||
deleteRelay.enabled = false;
|
||||
setPrimary.enabled = false;
|
||||
}else {
|
||||
deleteRelay.enabled = true;
|
||||
setPrimary.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void actionPerformed(GuiButton btn) {
|
||||
if(btn.id == 0) {
|
||||
RelayManager.relayManager.save();
|
||||
mc.displayGuiScreen(screen);
|
||||
} else if(btn.id == 1) {
|
||||
addingNew = true;
|
||||
mc.displayGuiScreen(new GuiScreenAddRelay(this));
|
||||
} else if(btn.id == 2) {
|
||||
if(selected >= 0) {
|
||||
RelayServer srv = RelayManager.relayManager.get(selected);
|
||||
mc.displayGuiScreen(new GuiYesNo(this, I18n.format("networkSettings.delete"), I18n.format("addRelay.removeText1") +
|
||||
EnumChatFormatting.GRAY + " '" + srv.comment + "' (" + srv.address + ")", selected));
|
||||
deleting = true;
|
||||
}
|
||||
} else if(btn.id == 3) {
|
||||
if(selected >= 0) {
|
||||
slots.relayManager.setPrimary(selected);
|
||||
selected = 0;
|
||||
}
|
||||
} else if(btn.id == 4) {
|
||||
long millis = System.currentTimeMillis();
|
||||
if(millis - lastRefresh > 700l) {
|
||||
lastRefresh = millis;
|
||||
slots.relayManager.ping();
|
||||
}
|
||||
lastRefresh += 60l;
|
||||
} else if(btn.id == 5) {
|
||||
slots.relayManager.loadDefaults();
|
||||
long millis = System.currentTimeMillis();
|
||||
if(millis - lastRefresh > 700l) {
|
||||
lastRefresh = millis;
|
||||
slots.relayManager.ping();
|
||||
}
|
||||
lastRefresh += 60l;
|
||||
} else if(btn.id == 6) {
|
||||
EagRuntime.downloadFileWithName("EaglerSPRelay.zip", EagRuntime.getResourceBytes("relay_download.zip"));
|
||||
}
|
||||
}
|
||||
|
||||
public void updateScreen() {
|
||||
slots.relayManager.update();
|
||||
}
|
||||
|
||||
private int mx = 0;
|
||||
private int my = 0;
|
||||
|
||||
int getFrameMouseX() {
|
||||
return mx;
|
||||
}
|
||||
|
||||
int getFrameMouseY() {
|
||||
return my;
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
mx = par1;
|
||||
my = par2;
|
||||
slots.drawScreen(par1, par2, par3);
|
||||
|
||||
if(tooltipString != null) {
|
||||
int ww = mc.fontRendererObj.getStringWidth(tooltipString);
|
||||
Gui.drawRect(par1 + 1, par2 - 14, par1 + ww + 7, par2 - 2, 0xC0000000);
|
||||
screen.drawString(mc.fontRendererObj, tooltipString, par1 + 4, par2 - 12, 0xFF999999);
|
||||
tooltipString = null;
|
||||
}
|
||||
|
||||
this.drawCenteredString(fontRendererObj, I18n.format("networkSettings.title"), this.width / 2, 16, 16777215);
|
||||
|
||||
String str = I18n.format("networkSettings.relayTimeout") + " " + mc.gameSettings.relayTimeout;
|
||||
int w = fontRendererObj.getStringWidth(str);
|
||||
this.drawString(fontRendererObj, str, 3, 3, 0xDDDDDD);
|
||||
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate(w + 7, 4, 0.0f);
|
||||
GlStateManager.scale(0.75f, 0.75f, 0.75f);
|
||||
str = EnumChatFormatting.UNDERLINE + I18n.format("networkSettings.relayTimeoutChange");
|
||||
int w2 = fontRendererObj.getStringWidth(str);
|
||||
boolean b = par1 > w + 5 && par1 < w + 7 + w2 * 3 / 4 && par2 > 3 && par2 < 11;
|
||||
if(b) Mouse.showCursor(EnumCursorType.HAND);
|
||||
this.drawString(fontRendererObj, EnumChatFormatting.UNDERLINE + I18n.format("networkSettings.relayTimeoutChange"), 0, 0, b ? 0xCCCCCC : 0x999999);
|
||||
GlStateManager.popMatrix();
|
||||
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
|
||||
protected void mouseClicked(int par1, int par2, int par3) {
|
||||
super.mouseClicked(par1, par2, par3);
|
||||
if(par3 == 0) {
|
||||
String str = I18n.format("networkSettings.relayTimeout") + " " + mc.gameSettings.relayTimeout;
|
||||
int w = fontRendererObj.getStringWidth(str);
|
||||
str = I18n.format("networkSettings.relayTimeoutChange");
|
||||
int w2 = fontRendererObj.getStringWidth(str);
|
||||
if(par1 > w + 5 && par1 < w + 7 + w2 * 3 / 4 && par2 > 3 && par2 < 11) {
|
||||
this.mc.displayGuiScreen(new GuiScreenChangeRelayTimeout(this));
|
||||
this.mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setToolTip(String str) {
|
||||
tooltipString = str;
|
||||
}
|
||||
|
||||
String addNewName;
|
||||
String addNewAddr;
|
||||
boolean addNewPrimary;
|
||||
|
||||
public void confirmClicked(boolean par1, int par2) {
|
||||
if(par1) {
|
||||
if(addingNew) {
|
||||
RelayManager.relayManager.addNew(addNewAddr, addNewName, addNewPrimary);
|
||||
addNewAddr = null;
|
||||
addNewName = null;
|
||||
addNewPrimary = false;
|
||||
selected = -1;
|
||||
updateButtons();
|
||||
}else if(deleting) {
|
||||
RelayManager.relayManager.remove(par2);
|
||||
selected = -1;
|
||||
updateButtons();
|
||||
}
|
||||
}
|
||||
addingNew = false;
|
||||
deleting = false;
|
||||
this.mc.displayGuiScreen(this);
|
||||
}
|
||||
|
||||
static Minecraft getMinecraft(GuiScreenRelay screen) {
|
||||
return screen.mc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMouseInput() throws IOException {
|
||||
super.handleMouseInput();
|
||||
this.slots.handleMouseInput();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.profile.EaglerProfile;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.SingleplayerServerController;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.socket.ClientIntegratedServerNetworkManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.socket.NetHandlerSingleplayerLogin;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiDisconnected;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.network.EnumConnectionState;
|
||||
import net.minecraft.network.login.client.C00PacketLoginStart;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiScreenSingleplayerConnecting extends GuiScreen {
|
||||
|
||||
private GuiScreen menu;
|
||||
private String message;
|
||||
private GuiButton killTask;
|
||||
private ClientIntegratedServerNetworkManager networkManager = null;
|
||||
private int timer = 0;
|
||||
|
||||
private long startStartTime;
|
||||
private boolean hasOpened = false;
|
||||
|
||||
public GuiScreenSingleplayerConnecting(GuiScreen menu, String message) {
|
||||
this.menu = menu;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public void initGui() {
|
||||
if(startStartTime == 0) this.startStartTime = System.currentTimeMillis();
|
||||
this.buttonList.add(killTask = new GuiButton(0, this.width / 2 - 100, this.height / 3 + 50, I18n.format("singleplayer.busy.killTask")));
|
||||
killTask.enabled = false;
|
||||
}
|
||||
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawDefaultBackground();
|
||||
float f = 2.0f;
|
||||
int top = this.height / 3;
|
||||
|
||||
long millis = System.currentTimeMillis();
|
||||
|
||||
long dots = (millis / 500l) % 4l;
|
||||
this.drawString(fontRendererObj, message + (dots > 0 ? "." : "") + (dots > 1 ? "." : "") + (dots > 2 ? "." : ""), (this.width - this.fontRendererObj.getStringWidth(message)) / 2, top + 10, 0xFFFFFF);
|
||||
|
||||
long elapsed = (millis - startStartTime) / 1000l;
|
||||
if(elapsed > 3) {
|
||||
this.drawCenteredString(fontRendererObj, "(" + elapsed + "s)", this.width / 2, top + 25, 0xFFFFFF);
|
||||
}
|
||||
|
||||
super.drawScreen(par1, par2, par3);
|
||||
}
|
||||
|
||||
public boolean doesGuiPauseGame() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void updateScreen() {
|
||||
++timer;
|
||||
if (timer > 1) {
|
||||
if (this.networkManager == null) {
|
||||
this.networkManager = SingleplayerServerController.localPlayerNetworkManager;
|
||||
this.networkManager.connect();
|
||||
} else {
|
||||
if (this.networkManager.isChannelOpen()) {
|
||||
if (!hasOpened) {
|
||||
hasOpened = true;
|
||||
this.mc.getSession().setLAN();
|
||||
this.mc.clearTitles();
|
||||
this.networkManager.setConnectionState(EnumConnectionState.LOGIN);
|
||||
this.networkManager.setNetHandler(new NetHandlerSingleplayerLogin(this.networkManager, this.mc, this.menu));
|
||||
this.networkManager.sendPacket(new C00PacketLoginStart(this.mc.getSession().getProfile(), EaglerProfile.getSkinPacket()));
|
||||
}
|
||||
try {
|
||||
this.networkManager.processReceivedPackets();
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
} else {
|
||||
if (this.networkManager.checkDisconnected()) {
|
||||
this.mc.getSession().reset();
|
||||
if (mc.currentScreen == this) {
|
||||
mc.loadWorld(null);
|
||||
mc.displayGuiScreen(new GuiDisconnected(menu, "connect.failed", new ChatComponentText("Worker Connection Refused")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long millis = System.currentTimeMillis();
|
||||
if(millis - startStartTime > 6000l && SingleplayerServerController.canKillWorker()) {
|
||||
killTask.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||
if(par1GuiButton.id == 0) {
|
||||
SingleplayerServerController.killWorker();
|
||||
this.mc.loadWorld((WorldClient)null);
|
||||
this.mc.getSession().reset();
|
||||
this.mc.displayGuiScreen(menu);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean shouldHangupIntegratedServer() {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,198 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.SingleplayerServerController;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.lan.LANServerController;
|
||||
import net.minecraft.client.LoadingScreenRenderer;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.ChatComponentText;
|
||||
import net.minecraft.world.WorldSettings;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiShareToLan extends GuiScreen {
|
||||
/**
|
||||
* A reference to the screen object that created this. Used for navigating
|
||||
* between screens.
|
||||
*/
|
||||
private final GuiScreen parentScreen;
|
||||
private GuiButton buttonAllowCommandsToggle;
|
||||
private GuiButton buttonGameMode;
|
||||
private GuiButton buttonHiddenToggle;
|
||||
|
||||
/**
|
||||
* The currently selected game mode. One of 'survival', 'creative', or
|
||||
* 'adventure'
|
||||
*/
|
||||
private String gameMode;
|
||||
|
||||
/**
|
||||
* True if 'Allow Cheats' is currently enabled
|
||||
*/
|
||||
private boolean allowCommands = false;
|
||||
|
||||
private final GuiNetworkSettingsButton relaysButton;
|
||||
|
||||
private boolean hiddenToggle = false;
|
||||
|
||||
private GuiTextField codeTextField;
|
||||
|
||||
public GuiShareToLan(GuiScreen par1GuiScreen, String gameMode) {
|
||||
this.parentScreen = par1GuiScreen;
|
||||
this.relaysButton = new GuiNetworkSettingsButton(this);
|
||||
this.gameMode = gameMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the buttons (and other controls) to the screen in question.
|
||||
*/
|
||||
public void initGui() {
|
||||
this.buttonList.clear();
|
||||
this.buttonList.add(new GuiButton(101, this.width / 2 - 155, this.height - 28, 140, 20,
|
||||
I18n.format("lanServer.start")));
|
||||
this.buttonList.add(new GuiButton(102, this.width / 2 + 5, this.height - 28, 140, 20,
|
||||
I18n.format("gui.cancel")));
|
||||
this.buttonList.add(this.buttonGameMode = new GuiButton(104, this.width / 2 - 155, 135, 140, 20,
|
||||
I18n.format("selectWorld.gameMode")));
|
||||
this.buttonList.add(this.buttonAllowCommandsToggle = new GuiButton(103, this.width / 2 + 5, 135, 140, 20,
|
||||
I18n.format("selectWorld.allowCommands")));
|
||||
this.buttonGameMode.enabled = this.buttonAllowCommandsToggle.enabled = !mc.isDemo();
|
||||
this.buttonList.add(this.buttonHiddenToggle = new GuiButton(105, this.width / 2 - 75, 165, 140, 20,
|
||||
I18n.format("lanServer.hidden")));
|
||||
this.codeTextField = new GuiTextField(0, this.fontRendererObj, this.width / 2 - 100, 80, 200, 20);
|
||||
this.codeTextField.setText(mc.thePlayer.getName() + "'s World");
|
||||
this.codeTextField.setFocused(true);
|
||||
this.codeTextField.setMaxStringLength(252);
|
||||
this.func_74088_g();
|
||||
}
|
||||
|
||||
private void func_74088_g() {
|
||||
this.buttonGameMode.displayString = I18n.format("selectWorld.gameMode") + ": "
|
||||
+ I18n.format("selectWorld.gameMode." + this.gameMode);
|
||||
this.buttonAllowCommandsToggle.displayString = I18n.format("selectWorld.allowCommands")
|
||||
+ " ";
|
||||
this.buttonHiddenToggle.displayString = I18n.format("lanServer.hidden")
|
||||
+ " ";
|
||||
|
||||
if (this.allowCommands) {
|
||||
this.buttonAllowCommandsToggle.displayString = this.buttonAllowCommandsToggle.displayString
|
||||
+ I18n.format("options.on");
|
||||
} else {
|
||||
this.buttonAllowCommandsToggle.displayString = this.buttonAllowCommandsToggle.displayString
|
||||
+ I18n.format("options.off");
|
||||
}
|
||||
|
||||
if (this.hiddenToggle) {
|
||||
this.buttonHiddenToggle.displayString = this.buttonHiddenToggle.displayString
|
||||
+ I18n.format("options.on");
|
||||
} else {
|
||||
this.buttonHiddenToggle.displayString = this.buttonHiddenToggle.displayString
|
||||
+ I18n.format("options.off");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when a control is clicked. This is the equivalent of
|
||||
* ActionListener.actionPerformed(ActionEvent e).
|
||||
*/
|
||||
protected void actionPerformed(GuiButton par1GuiButton) {
|
||||
if (par1GuiButton.id == 102) {
|
||||
this.mc.displayGuiScreen(this.parentScreen);
|
||||
} else if (par1GuiButton.id == 104) {
|
||||
if(!mc.isDemo()) {
|
||||
if (this.gameMode.equals("survival")) {
|
||||
this.gameMode = "creative";
|
||||
} else if (this.gameMode.equals("creative")) {
|
||||
this.gameMode = "adventure";
|
||||
} else if (this.gameMode.equals("adventure")) {
|
||||
this.gameMode = "spectator";
|
||||
} else {
|
||||
this.gameMode = "survival";
|
||||
}
|
||||
|
||||
this.func_74088_g();
|
||||
}
|
||||
} else if (par1GuiButton.id == 103) {
|
||||
if(!mc.isDemo()) {
|
||||
this.allowCommands = !this.allowCommands;
|
||||
this.func_74088_g();
|
||||
}
|
||||
} else if (par1GuiButton.id == 105) {
|
||||
this.hiddenToggle = !this.hiddenToggle;
|
||||
this.func_74088_g();
|
||||
} else if (par1GuiButton.id == 101) {
|
||||
if (LANServerController.isLANOpen()) {
|
||||
return;
|
||||
}
|
||||
PlatformWebRTC.startRTCLANServer();
|
||||
String worldName = this.codeTextField.getText().trim();
|
||||
if (worldName.isEmpty()) {
|
||||
worldName = mc.thePlayer.getName() + "'s World";
|
||||
}
|
||||
if (worldName.length() >= 252) {
|
||||
worldName = worldName.substring(0, 252);
|
||||
}
|
||||
this.mc.displayGuiScreen(null);
|
||||
LoadingScreenRenderer ls = mc.loadingScreen;
|
||||
String code = LANServerController.shareToLAN((str) -> ls.resetProgressAndMessage(str), worldName, hiddenToggle);
|
||||
if (code != null) {
|
||||
SingleplayerServerController.configureLAN(WorldSettings.GameType.getByName(this.gameMode), this.allowCommands);
|
||||
this.mc.ingameGUI.getChatGUI().printChatMessage(new ChatComponentText(I18n.format("lanServer.opened")
|
||||
.replace("$relay$", LANServerController.getCurrentURI()).replace("$code$", code)));
|
||||
} else {
|
||||
SingleplayerServerController.configureLAN(mc.theWorld.getWorldInfo().getGameType(), false);
|
||||
this.mc.displayGuiScreen(new GuiScreenNoRelays(this, "noRelay.titleFail"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the screen and all the components in it.
|
||||
*/
|
||||
public void drawScreen(int par1, int par2, float par3) {
|
||||
this.drawDefaultBackground();
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("lanServer.title"), this.width / 2,
|
||||
35, 16777215);
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("lanServer.worldName"), this.width / 2,
|
||||
62, 16777215);
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("lanServer.otherPlayers"),
|
||||
this.width / 2, 112, 16777215);
|
||||
this.drawCenteredString(this.fontRendererObj, I18n.format("lanServer.ipGrabNote"),
|
||||
this.width / 2, 195, 16777215);
|
||||
super.drawScreen(par1, par2, par3);
|
||||
this.relaysButton.drawScreen(par1, par2);
|
||||
this.codeTextField.drawTextBox();
|
||||
}
|
||||
|
||||
public void mouseClicked(int par1, int par2, int par3) {
|
||||
super.mouseClicked(par1, par2, par3);
|
||||
this.relaysButton.mouseClicked(par1, par2, par3);
|
||||
this.codeTextField.mouseClicked(par1, par2, par3);
|
||||
}
|
||||
|
||||
protected void keyTyped(char c, int k) {
|
||||
super.keyTyped(c, k);
|
||||
this.codeTextField.textboxKeyTyped(c, k);
|
||||
}
|
||||
|
||||
public void updateScreen() {
|
||||
super.updateScreen();
|
||||
this.codeTextField.updateCursorCounter();
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class GuiSlider2 extends GuiButton {
|
||||
/** The value of this slider control. */
|
||||
public float sliderValue = 1.0F;
|
||||
public float sliderMax = 1.0F;
|
||||
|
||||
/** Is this slider control being dragged. */
|
||||
public boolean dragging = false;
|
||||
|
||||
public GuiSlider2(int par1, int par2, int par3, int par4, int par5, float par6, float par7) {
|
||||
super(par1, par2, par3, par4, par5, (int)(par6 * par7 * 100.0F) + "%");
|
||||
this.sliderValue = par6;
|
||||
this.sliderMax = par7;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 0 if the button is disabled, 1 if the mouse is NOT hovering over this
|
||||
* button and 2 if it IS hovering over this button.
|
||||
*/
|
||||
protected int getHoverState(boolean par1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when the mouse button is dragged. Equivalent of
|
||||
* MouseListener.mouseDragged(MouseEvent e).
|
||||
*/
|
||||
protected void mouseDragged(Minecraft par1Minecraft, int par2, int par3) {
|
||||
if (this.visible) {
|
||||
if (this.dragging) {
|
||||
this.sliderValue = (float) (par2 - (this.xPosition + 4)) / (float) (this.width - 8);
|
||||
|
||||
if (this.sliderValue < 0.0F) {
|
||||
this.sliderValue = 0.0F;
|
||||
}
|
||||
|
||||
if (this.sliderValue > 1.0F) {
|
||||
this.sliderValue = 1.0F;
|
||||
}
|
||||
|
||||
this.displayString = (int)(this.sliderValue * this.sliderMax * 100.0F) + "%";
|
||||
}
|
||||
|
||||
if(this.enabled) {
|
||||
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
this.drawTexturedModalRect(this.xPosition + (int) (this.sliderValue * (float) (this.width - 8)), this.yPosition, 0, 66, 4, 20);
|
||||
this.drawTexturedModalRect(this.xPosition + (int) (this.sliderValue * (float) (this.width - 8)) + 4, this.yPosition, 196, 66, 4, 20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the mouse has been pressed on this control. Equivalent of
|
||||
* MouseListener.mousePressed(MouseEvent e).
|
||||
*/
|
||||
public boolean mousePressed(Minecraft par1Minecraft, int par2, int par3) {
|
||||
if (super.mousePressed(par1Minecraft, par2, par3)) {
|
||||
this.sliderValue = (float) (par2 - (this.xPosition + 4)) / (float) (this.width - 8);
|
||||
|
||||
if (this.sliderValue < 0.0F) {
|
||||
this.sliderValue = 0.0F;
|
||||
}
|
||||
|
||||
if (this.sliderValue > 1.0F) {
|
||||
this.sliderValue = 1.0F;
|
||||
}
|
||||
|
||||
this.displayString = (int)(this.sliderValue * this.sliderMax * 100.0F) + "%";
|
||||
this.dragging = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when the mouse button is released. Equivalent of
|
||||
* MouseListener.mouseReleased(MouseEvent e).
|
||||
*/
|
||||
public void mouseReleased(int par1, int par2) {
|
||||
this.dragging = false;
|
||||
}
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.gui;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayQuery;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServer;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.gui.GuiSlot;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
class GuiSlotRelay extends GuiSlot {
|
||||
|
||||
private static final ResourceLocation eaglerGuiTex = new ResourceLocation("eagler:gui/eagler_gui.png");
|
||||
|
||||
final GuiScreenRelay screen;
|
||||
final RelayManager relayManager;
|
||||
|
||||
public GuiSlotRelay(GuiScreenRelay screen) {
|
||||
super(GuiScreenRelay.getMinecraft(screen), screen.width, screen.height, 32, screen.height - 64, 26);
|
||||
this.screen = screen;
|
||||
this.relayManager = RelayManager.relayManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSize() {
|
||||
return relayManager.count();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void elementClicked(int var1, boolean var2, int var3, int var4) {
|
||||
screen.selected = var1;
|
||||
screen.updateButtons();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSelected(int var1) {
|
||||
return screen.selected == var1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawBackground() {
|
||||
screen.drawDefaultBackground();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawSlot(int id, int xx, int yy, int width, int height, int ii) {
|
||||
if(id < relayManager.count()) {
|
||||
this.mc.getTextureManager().bindTexture(Gui.icons);
|
||||
RelayServer srv = relayManager.get(id);
|
||||
String comment = srv.comment;
|
||||
int var15 = 0;
|
||||
int var16 = 0;
|
||||
String str = null;
|
||||
int h = 12;
|
||||
long ping = srv.getPing();
|
||||
if(ping == 0l) {
|
||||
var16 = 5;
|
||||
str = "No Connection";
|
||||
}else if(ping < 0l) {
|
||||
var15 = 1;
|
||||
var16 = (int) (Minecraft.getSystemTime() / 100L + (long) (id * 2) & 7L);
|
||||
if (var16 > 4) {
|
||||
var16 = 8 - var16;
|
||||
}
|
||||
str = "Polling...";
|
||||
}else {
|
||||
RelayQuery.VersionMismatch vm = srv.getPingCompatible();
|
||||
if(!vm.isCompatible()) {
|
||||
var16 = 5;
|
||||
switch(vm) {
|
||||
case CLIENT_OUTDATED:
|
||||
str = "Outdated Client!";
|
||||
break;
|
||||
case RELAY_OUTDATED:
|
||||
str = "Outdated Relay!";
|
||||
break;
|
||||
default:
|
||||
case UNKNOWN:
|
||||
str = "Incompatible Relay!";
|
||||
break;
|
||||
}
|
||||
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate(xx + 205, yy + 11, 0.0f);
|
||||
GlStateManager.scale(0.6f, 0.6f, 0.6f);
|
||||
screen.drawTexturedModalRect(0, 0, 0, 144, 16, 16);
|
||||
GlStateManager.popMatrix();
|
||||
h += 10;
|
||||
}else {
|
||||
String pingComment = srv.getPingComment().trim();
|
||||
if(pingComment.length() > 0) {
|
||||
comment = pingComment;
|
||||
}
|
||||
str = "" + ping + "ms";
|
||||
if (ping < 150L) {
|
||||
var16 = 0;
|
||||
} else if (ping < 300L) {
|
||||
var16 = 1;
|
||||
} else if (ping < 600L) {
|
||||
var16 = 2;
|
||||
} else if (ping < 1000L) {
|
||||
var16 = 3;
|
||||
} else {
|
||||
var16 = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
screen.drawTexturedModalRect(xx + 205, yy, 0 + var15 * 10, 176 + var16 * 8, 10, 8);
|
||||
if(srv.isPrimary()) {
|
||||
GlStateManager.pushMatrix();
|
||||
GlStateManager.translate(xx + 4, yy + 5, 0.0f);
|
||||
GlStateManager.scale(0.8f, 0.8f, 0.8f);
|
||||
this.mc.getTextureManager().bindTexture(eaglerGuiTex);
|
||||
screen.drawTexturedModalRect(0, 0, 48, 0, 16, 16);
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
screen.drawString(mc.fontRendererObj, comment, xx + 22, yy + 2, 0xFFFFFFFF);
|
||||
screen.drawString(mc.fontRendererObj, srv.address, xx + 22, yy + 12, 0xFF999999);
|
||||
|
||||
if(str != null) {
|
||||
int mx = screen.getFrameMouseX();
|
||||
int my = screen.getFrameMouseY();
|
||||
int rx = xx + 202;
|
||||
if(mx > rx && mx < rx + 13 && my > yy - 1 && my < yy + h) {
|
||||
screen.setToolTip(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCInputStream extends InputStream {
|
||||
|
||||
private byte[] currentBuffer = null;
|
||||
private int idx = 0;
|
||||
private int markIDX = 0;
|
||||
private String errorName = null;
|
||||
|
||||
public void feedBuffer(byte[] b) {
|
||||
currentBuffer = b;
|
||||
idx = 0;
|
||||
errorName = null;
|
||||
markIDX = 0;
|
||||
}
|
||||
|
||||
public void nameBuffer(String str) {
|
||||
errorName = str;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
try {
|
||||
return ((int)currentBuffer[idx++]) & 0xFF;
|
||||
}catch(ArrayIndexOutOfBoundsException a) {
|
||||
throw new IOException("IPCInputStream buffer underflow" + (errorName == null ? "," : (" (while deserializing '" + errorName + "')")) + " no bytes remaining", a);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte b[], int off, int len) throws IOException {
|
||||
if(idx + len > currentBuffer.length) {
|
||||
throw new IOException("IPCInputStream buffer underflow" + (errorName == null ? "," : (" (while deserializing '" + errorName + "')")) + " tried to read " + len + " when there are only " + (currentBuffer.length - idx) + " bytes remaining", new ArrayIndexOutOfBoundsException(idx + len - 1));
|
||||
}
|
||||
if(off + len > b.length) {
|
||||
throw new ArrayIndexOutOfBoundsException(off + len - 1);
|
||||
}
|
||||
System.arraycopy(currentBuffer, idx, b, off, len);
|
||||
idx += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
public void markIndex() {
|
||||
markIDX = idx;
|
||||
}
|
||||
|
||||
public void rewindIndex() {
|
||||
idx = markIDX;
|
||||
}
|
||||
|
||||
public byte[] getLeftover() {
|
||||
if(currentBuffer.length - idx <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] buf = new byte[currentBuffer.length - idx];
|
||||
System.arraycopy(currentBuffer, idx, buf, 0, currentBuffer.length - idx);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
public int getLeftoverCount() {
|
||||
return currentBuffer.length - idx;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCOutputStream extends OutputStream {
|
||||
|
||||
private String className = null;
|
||||
private byte[] currentBuffer = null;
|
||||
private int idx = 0;
|
||||
private int originalSize = 0;
|
||||
|
||||
public void feedBuffer(byte[] buf, String clazzName) {
|
||||
currentBuffer = buf;
|
||||
idx = 0;
|
||||
originalSize = buf.length;
|
||||
className = clazzName;
|
||||
}
|
||||
|
||||
public byte[] returnBuffer() {
|
||||
if(className != null && currentBuffer.length != originalSize) {
|
||||
System.err.println("WARNING: Packet '" + className + "' was supposed to be " + originalSize + " bytes but buffer has grown by " + (currentBuffer.length - originalSize) + " to " + currentBuffer.length + " bytes");
|
||||
}
|
||||
return currentBuffer;
|
||||
}
|
||||
|
||||
void growBuffer(int i) {
|
||||
int ii = currentBuffer.length;
|
||||
int iii = i - ii;
|
||||
if(iii > 0) {
|
||||
byte[] n = new byte[i];
|
||||
System.arraycopy(currentBuffer, 0, n, 0, ii);
|
||||
currentBuffer = n;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
if(idx >= currentBuffer.length) {
|
||||
growBuffer(idx + 1);
|
||||
}
|
||||
currentBuffer[idx++] = (byte) b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte b[], int off, int len) throws IOException {
|
||||
if(idx + len > currentBuffer.length) {
|
||||
growBuffer(idx + len);
|
||||
}
|
||||
System.arraycopy(b, off, currentBuffer, idx, len);
|
||||
idx += len;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket00StartServer implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x00;
|
||||
|
||||
public String worldName;
|
||||
public String ownerName;
|
||||
public int initialDifficulty;
|
||||
public int initialViewDistance;
|
||||
public boolean demoMode;
|
||||
|
||||
public IPCPacket00StartServer() {
|
||||
}
|
||||
|
||||
public IPCPacket00StartServer(String worldName, String ownerName, int initialDifficulty, int initialViewDistance, boolean demoMode) {
|
||||
this.worldName = worldName;
|
||||
this.ownerName = ownerName;
|
||||
this.initialDifficulty = initialDifficulty;
|
||||
this.initialViewDistance = initialViewDistance;
|
||||
this.demoMode = demoMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
worldName = bin.readUTF();
|
||||
ownerName = bin.readUTF();
|
||||
initialDifficulty = bin.readByte();
|
||||
initialViewDistance = bin.readByte();
|
||||
demoMode = bin.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(worldName);
|
||||
bin.writeUTF(ownerName);
|
||||
bin.writeByte(initialDifficulty);
|
||||
bin.writeByte(initialViewDistance);
|
||||
bin.writeBoolean(demoMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(worldName) + IPCPacketBase.strLen(ownerName) + 3;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket01StopServer implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x01;
|
||||
|
||||
public IPCPacket01StopServer() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket02InitWorld implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x02;
|
||||
|
||||
public String worldName;
|
||||
public byte gamemode;
|
||||
public byte worldType;
|
||||
public String worldArgs;
|
||||
public long seed;
|
||||
public boolean cheats;
|
||||
public boolean structures;
|
||||
public boolean bonusChest;
|
||||
public boolean hardcore;
|
||||
|
||||
public IPCPacket02InitWorld() {
|
||||
}
|
||||
|
||||
public IPCPacket02InitWorld(String worldName, int gamemode, int worldType, String worldArgs, long seed, boolean cheats, boolean structures, boolean bonusChest, boolean hardcore) {
|
||||
this.worldName = worldName;
|
||||
this.gamemode = (byte)gamemode;
|
||||
this.worldType = (byte)worldType;
|
||||
this.worldArgs = worldArgs;
|
||||
this.seed = seed;
|
||||
this.cheats = cheats;
|
||||
this.structures = structures;
|
||||
this.bonusChest = bonusChest;
|
||||
this.hardcore = hardcore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
worldName = bin.readUTF();
|
||||
gamemode = bin.readByte();
|
||||
worldType = bin.readByte();
|
||||
worldArgs = bin.readUTF();
|
||||
seed = bin.readLong();
|
||||
cheats = bin.readBoolean();
|
||||
structures = bin.readBoolean();
|
||||
bonusChest = bin.readBoolean();
|
||||
hardcore = bin.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(worldName);
|
||||
bin.writeByte(gamemode);
|
||||
bin.writeByte(worldType);
|
||||
bin.writeUTF(worldArgs);
|
||||
bin.writeLong(seed);
|
||||
bin.writeBoolean(cheats);
|
||||
bin.writeBoolean(structures);
|
||||
bin.writeBoolean(bonusChest);
|
||||
bin.writeBoolean(hardcore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(worldName) + 1 + 1 + IPCPacketBase.strLen(worldArgs) + 8 + 4;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket03DeleteWorld implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x03;
|
||||
|
||||
public String worldName;
|
||||
|
||||
public IPCPacket03DeleteWorld() {
|
||||
}
|
||||
|
||||
public IPCPacket03DeleteWorld(String worldName) {
|
||||
this.worldName = worldName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
worldName = bin.readUTF();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(worldName);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket04RenameWorld implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x04;
|
||||
|
||||
public String worldOldName;
|
||||
public String worldNewName;
|
||||
public String displayName;
|
||||
public boolean copy;
|
||||
|
||||
public IPCPacket04RenameWorld() {
|
||||
}
|
||||
|
||||
public IPCPacket04RenameWorld(String worldOldName, String worldNewName, String displayName, boolean copy) {
|
||||
this.worldOldName = worldOldName;
|
||||
this.worldNewName = worldNewName;
|
||||
this.displayName = displayName;
|
||||
this.copy = copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
worldOldName = bin.readUTF();
|
||||
worldNewName = bin.readUTF();
|
||||
displayName = bin.readUTF();
|
||||
copy = bin.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(worldOldName);
|
||||
bin.writeUTF(worldNewName);
|
||||
bin.writeUTF(displayName);
|
||||
bin.writeBoolean(copy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(worldOldName) + IPCPacketBase.strLen(worldNewName) + IPCPacketBase.strLen(displayName) + 1;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket05RequestData implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x05;
|
||||
|
||||
public static final byte REQUEST_LEVEL_DAT = 0x00;
|
||||
public static final byte REQUEST_LEVEL_EAG = 0x01;
|
||||
public static final byte REQUEST_LEVEL_MCA = 0x02;
|
||||
|
||||
public String worldName;
|
||||
public byte request;
|
||||
|
||||
public IPCPacket05RequestData() {
|
||||
}
|
||||
|
||||
public IPCPacket05RequestData(String worldName, byte request) {
|
||||
this.worldName = worldName;
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
worldName = bin.readUTF();
|
||||
request = bin.readByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(worldName);
|
||||
bin.writeByte(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(worldName) + 1;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket06RenameWorldNBT implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x06;
|
||||
|
||||
public String worldName;
|
||||
public String displayName;
|
||||
public boolean duplicate;
|
||||
|
||||
public IPCPacket06RenameWorldNBT() {
|
||||
}
|
||||
|
||||
public IPCPacket06RenameWorldNBT(String worldName, String displayName, boolean duplicate) {
|
||||
this.worldName = worldName;
|
||||
this.displayName = displayName;
|
||||
this.duplicate = duplicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
this.worldName = bin.readUTF();
|
||||
this.displayName = bin.readUTF();
|
||||
this.duplicate = bin.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(worldName);
|
||||
bin.writeUTF(displayName);
|
||||
bin.writeBoolean(duplicate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(worldName) + IPCPacketBase.strLen(displayName) + 1;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket07ImportWorld implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x07;
|
||||
public byte gameRules;
|
||||
|
||||
public String worldName;
|
||||
public byte[] worldData;
|
||||
public byte worldFormat;
|
||||
|
||||
public static final byte WORLD_FORMAT_EAG = 0x00;
|
||||
public static final byte WORLD_FORMAT_MCA = 0x01;
|
||||
|
||||
public IPCPacket07ImportWorld() {
|
||||
}
|
||||
|
||||
public IPCPacket07ImportWorld(String worldName, byte[] worldData, byte worldFormat, byte gameRules) {
|
||||
this.worldName = worldName;
|
||||
this.worldData = worldData;
|
||||
this.worldFormat = worldFormat;
|
||||
this.gameRules = gameRules;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
worldName = bin.readUTF();
|
||||
worldData = new byte[bin.readInt()];
|
||||
worldFormat = bin.readByte();
|
||||
gameRules = bin.readByte();
|
||||
bin.readFully(worldData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(worldName);
|
||||
bin.writeInt(worldData.length);
|
||||
bin.writeByte(worldFormat);
|
||||
bin.writeByte(gameRules);
|
||||
bin.write(worldData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(worldName) + worldData.length + 6;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket09RequestResponse implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x09;
|
||||
|
||||
public byte[] response;
|
||||
|
||||
public IPCPacket09RequestResponse() {
|
||||
}
|
||||
|
||||
public IPCPacket09RequestResponse(byte[] dat) {
|
||||
this.response = dat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
response = new byte[bin.readInt()];
|
||||
bin.readFully(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeInt(response.length);
|
||||
bin.write(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 4 + response.length;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket0ASetWorldDifficulty implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x0A;
|
||||
|
||||
public byte difficulty;
|
||||
|
||||
public IPCPacket0ASetWorldDifficulty() {
|
||||
}
|
||||
|
||||
public IPCPacket0ASetWorldDifficulty(byte difficulty) {
|
||||
this.difficulty = difficulty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
difficulty = bin.readByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeByte(difficulty);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket0BPause implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x0B;
|
||||
|
||||
public boolean pause;
|
||||
|
||||
public IPCPacket0BPause() {
|
||||
}
|
||||
|
||||
public IPCPacket0BPause(boolean pause) {
|
||||
this.pause = pause;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
pause = bin.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeBoolean(pause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket0CPlayerChannel implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x0C;
|
||||
|
||||
public String channel;
|
||||
public boolean open;
|
||||
|
||||
public IPCPacket0CPlayerChannel() {
|
||||
}
|
||||
|
||||
public IPCPacket0CPlayerChannel(String channel, boolean open) {
|
||||
this.channel = channel;
|
||||
this.open = open;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
channel = bin.readUTF();
|
||||
open = bin.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(channel);
|
||||
bin.writeBoolean(open);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(channel) + 1;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket0DProgressUpdate implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x0D;
|
||||
|
||||
public String updateMessage;
|
||||
public float updateProgress;
|
||||
|
||||
public IPCPacket0DProgressUpdate() {
|
||||
}
|
||||
|
||||
public IPCPacket0DProgressUpdate(String updateMessage, float updateProgress) {
|
||||
this.updateMessage = updateMessage == null ? "" : updateMessage;
|
||||
this.updateProgress = updateProgress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
updateMessage = bin.readUTF();
|
||||
updateProgress = bin.readFloat();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(updateMessage);
|
||||
bin.writeFloat(updateProgress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(updateMessage) + 4;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket0EListWorlds implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x0E;
|
||||
|
||||
public IPCPacket0EListWorlds() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket0FListFiles implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x0F;
|
||||
|
||||
public String path;
|
||||
|
||||
public IPCPacket0FListFiles() {
|
||||
}
|
||||
|
||||
public IPCPacket0FListFiles(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
this.path = bin.readUTF();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(path);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket10FileRead implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x10;
|
||||
|
||||
public String file;
|
||||
|
||||
public IPCPacket10FileRead() {
|
||||
}
|
||||
|
||||
public IPCPacket10FileRead(String file) {
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
file = bin.readUTF();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(file);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket12FileWrite implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x12;
|
||||
|
||||
public String path;
|
||||
public byte[] data;
|
||||
|
||||
public IPCPacket12FileWrite() {
|
||||
}
|
||||
|
||||
public IPCPacket12FileWrite(String path, byte[] data) {
|
||||
this.path = path;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
path = bin.readUTF();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(path);
|
||||
bin.writeInt(data.length);
|
||||
bin.write(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(path) + 4 + data.length;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket13FileCopyMove implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x13;
|
||||
|
||||
public String fileOldName;
|
||||
public String fileNewName;
|
||||
public boolean copy;
|
||||
|
||||
public IPCPacket13FileCopyMove() {
|
||||
}
|
||||
|
||||
public IPCPacket13FileCopyMove(String fileOldName, String fileNewName, boolean copy) {
|
||||
this.fileOldName = fileOldName;
|
||||
this.fileNewName = fileNewName;
|
||||
this.copy = copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
fileOldName = bin.readUTF();
|
||||
fileNewName = bin.readUTF();
|
||||
copy = bin.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(fileOldName);
|
||||
bin.writeUTF(fileNewName);
|
||||
bin.writeBoolean(copy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(fileOldName) + IPCPacketBase.strLen(fileNewName) + 1;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket14StringList implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x14;
|
||||
|
||||
public static final int FILE_LIST = 0x0;
|
||||
public static final int LOCALE = 0x1;
|
||||
public static final int STAT_GUID = 0x2;
|
||||
public static final int SERVER_TPS = 0x3;
|
||||
|
||||
public int opCode;
|
||||
public final List<String> stringList;
|
||||
|
||||
public IPCPacket14StringList() {
|
||||
stringList = new ArrayList();
|
||||
}
|
||||
|
||||
public IPCPacket14StringList(int opcode, String[] list) {
|
||||
stringList = new ArrayList();
|
||||
for(String s : list) {
|
||||
s = s.trim();
|
||||
if(s.length() > 0) {
|
||||
stringList.add(s);
|
||||
}
|
||||
}
|
||||
this.opCode = opcode;
|
||||
}
|
||||
|
||||
public IPCPacket14StringList(int opcode, List<String> list) {
|
||||
stringList = new ArrayList();
|
||||
for(String s : list) {
|
||||
s = s.trim();
|
||||
if(s.length() > 0) {
|
||||
stringList.add(s);
|
||||
}
|
||||
}
|
||||
this.opCode = opcode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
stringList.clear();
|
||||
opCode = bin.readByte();
|
||||
int len = bin.readInt();
|
||||
for(int i = 0; i < len; ++i) {
|
||||
stringList.add(bin.readUTF());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeByte(opCode);
|
||||
bin.writeInt(stringList.size());
|
||||
for(String str : stringList) {
|
||||
bin.writeUTF(str);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
int len = 5;
|
||||
for(String str : stringList) {
|
||||
len += IPCPacketBase.strLen(str);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket15Crashed implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x15;
|
||||
|
||||
public String crashReport;
|
||||
|
||||
public IPCPacket15Crashed() {
|
||||
}
|
||||
|
||||
public IPCPacket15Crashed(String crashReport) {
|
||||
this.crashReport = crashReport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
crashReport = bin.readUTF();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(crashReport);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(crashReport);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.nbt.CompressedStreamTools;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket16NBTList implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x16;
|
||||
|
||||
public static final int WORLD_LIST = 0x0;
|
||||
|
||||
public int opCode;
|
||||
public final List<byte[]> tagList;
|
||||
public final List<NBTTagCompound> nbtTagList;
|
||||
|
||||
public IPCPacket16NBTList() {
|
||||
tagList = new LinkedList();
|
||||
nbtTagList = new LinkedList();
|
||||
}
|
||||
|
||||
public IPCPacket16NBTList(int opcode, NBTTagCompound[] list) {
|
||||
this(opcode, Arrays.asList(list));
|
||||
}
|
||||
|
||||
public IPCPacket16NBTList(int opcode, List<NBTTagCompound> list) {
|
||||
tagList = new LinkedList();
|
||||
nbtTagList = list;
|
||||
for(int i = 0, size = list.size(); i < size; ++i) {
|
||||
NBTTagCompound tag = list.get(i);
|
||||
try {
|
||||
ByteArrayOutputStream bao = new ByteArrayOutputStream();
|
||||
CompressedStreamTools.write(tag, new DataOutputStream(bao));
|
||||
tagList.add(bao.toByteArray());
|
||||
}catch(IOException e) {
|
||||
System.err.println("Failed to write tag '" + tag.getId() + "' (#" + i + ") in IPCPacket16NBTList");
|
||||
}
|
||||
}
|
||||
opCode = opcode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
tagList.clear();
|
||||
nbtTagList.clear();
|
||||
opCode = bin.readInt();
|
||||
int count = bin.readInt();
|
||||
for(int i = 0; i < count; ++i) {
|
||||
byte[] toRead = new byte[bin.readInt()];
|
||||
bin.readFully(toRead);
|
||||
tagList.add(toRead);
|
||||
try {
|
||||
nbtTagList.add(CompressedStreamTools.read(new DataInputStream(new ByteArrayInputStream(toRead))));
|
||||
}catch(IOException e) {
|
||||
System.err.println("Failed to read tag #" + i + " in IPCPacket16NBTList");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeInt(opCode);
|
||||
bin.writeInt(tagList.size());
|
||||
for(byte[] str : tagList) {
|
||||
bin.writeInt(str.length);
|
||||
bin.write(str);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
int len = 8;
|
||||
for(byte[] str : tagList) {
|
||||
len += 4;
|
||||
len += str.length;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket17ConfigureLAN implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x17;
|
||||
|
||||
public int gamemode;
|
||||
public boolean cheats;
|
||||
public final List<String> iceServers;
|
||||
|
||||
public IPCPacket17ConfigureLAN() {
|
||||
iceServers = new ArrayList();
|
||||
}
|
||||
|
||||
public IPCPacket17ConfigureLAN(int gamemode, boolean cheats, List<String> iceServers) {
|
||||
this.gamemode = gamemode;
|
||||
this.cheats = cheats;
|
||||
this.iceServers = iceServers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
gamemode = bin.readUnsignedByte();
|
||||
cheats = bin.readBoolean();
|
||||
iceServers.clear();
|
||||
int iceCount = bin.readUnsignedByte();
|
||||
for(int i = 0; i < iceCount; ++i) {
|
||||
iceServers.add(bin.readUTF());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeByte(gamemode);
|
||||
bin.writeBoolean(cheats);
|
||||
bin.writeByte(iceServers.size());
|
||||
for(int i = 0, l = iceServers.size(); i < l; ++i) {
|
||||
bin.writeUTF(iceServers.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
int s = 0;
|
||||
for(int i = 0, l = iceServers.size(); i < l; ++i) {
|
||||
s += 2;
|
||||
s += iceServers.get(i).length();
|
||||
}
|
||||
return 2 + 1 + s;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket18ClearPlayers implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x18;
|
||||
|
||||
public String worldName = null;
|
||||
|
||||
public IPCPacket18ClearPlayers(String worldName) {
|
||||
this.worldName = worldName;
|
||||
}
|
||||
|
||||
public IPCPacket18ClearPlayers() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
worldName = bin.readUTF();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(worldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(worldName);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket19Autosave implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x19;
|
||||
|
||||
public IPCPacket19Autosave() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket20LoggerMessage implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x20;
|
||||
|
||||
public String logMessage;
|
||||
public boolean isError;
|
||||
|
||||
public IPCPacket20LoggerMessage() {
|
||||
}
|
||||
|
||||
public IPCPacket20LoggerMessage(String logMessage, boolean isError) {
|
||||
this.logMessage = logMessage;
|
||||
this.isError = isError;
|
||||
}
|
||||
|
||||
public IPCPacket20LoggerMessage(String logMessage) {
|
||||
this.logMessage = logMessage;
|
||||
this.isError = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
this.logMessage = bin.readUTF();
|
||||
this.isError = bin.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeUTF(this.logMessage);
|
||||
bin.writeBoolean(this.isError);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return IPCPacketBase.strLen(logMessage) + 1;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacket21EnableLogging implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0x21;
|
||||
|
||||
public boolean enable;
|
||||
|
||||
public IPCPacket21EnableLogging() {
|
||||
}
|
||||
|
||||
public IPCPacket21EnableLogging(boolean enable) {
|
||||
this.enable = enable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
enable = bin.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeBoolean(enable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public interface IPCPacketBase {
|
||||
|
||||
public void deserialize(DataInput bin) throws IOException;
|
||||
public void serialize(DataOutput bin) throws IOException;
|
||||
public int id();
|
||||
public int size();
|
||||
|
||||
public static int strLen(String s) {
|
||||
int strlen = s.length();
|
||||
int utflen = 2;
|
||||
int c;
|
||||
|
||||
for (int i = 0; i < strlen; ++i) {
|
||||
c = s.charAt(i);
|
||||
if ((c >= 0x0001) && (c <= 0x007F)) {
|
||||
++utflen;
|
||||
} else if (c > 0x07FF) {
|
||||
utflen += 3;
|
||||
} else {
|
||||
utflen += 2;
|
||||
}
|
||||
}
|
||||
|
||||
return utflen;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacketFFProcessKeepAlive implements IPCPacketBase {
|
||||
|
||||
public static final int ID = 0xFF;
|
||||
|
||||
public static final int KEEPALIVE = 0;
|
||||
public static final int FAILURE = 0xFE;
|
||||
public static final int EXITED = 0xFC;
|
||||
|
||||
public int ack;
|
||||
|
||||
public IPCPacketFFProcessKeepAlive() {
|
||||
}
|
||||
|
||||
public IPCPacketFFProcessKeepAlive(int ack) {
|
||||
this.ack = ack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserialize(DataInput bin) throws IOException {
|
||||
ack = bin.readUnsignedByte();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize(DataOutput bin) throws IOException {
|
||||
bin.writeByte(ack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.ipc;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPCPacketManager {
|
||||
|
||||
public static final HashMap<Integer, Supplier<IPCPacketBase>> mappings = new HashMap();
|
||||
|
||||
public static final IPCInputStream IPC_INPUT_STREAM = new IPCInputStream();
|
||||
public static final IPCOutputStream IPC_OUTPUT_STREAM = new IPCOutputStream();
|
||||
|
||||
public static final DataInputStream IPC_DATA_INPUT_STREAM = new DataInputStream(IPC_INPUT_STREAM);
|
||||
public static final DataOutputStream IPC_DATA_OUTPUT_STREAM = new DataOutputStream(IPC_OUTPUT_STREAM);
|
||||
|
||||
static {
|
||||
mappings.put(IPCPacket00StartServer.ID, () -> new IPCPacket00StartServer());
|
||||
mappings.put(IPCPacket01StopServer.ID, () -> new IPCPacket01StopServer());
|
||||
mappings.put(IPCPacket02InitWorld.ID, () -> new IPCPacket02InitWorld());
|
||||
mappings.put(IPCPacket03DeleteWorld.ID, () -> new IPCPacket03DeleteWorld());
|
||||
mappings.put(IPCPacket05RequestData.ID, () -> new IPCPacket05RequestData());
|
||||
mappings.put(IPCPacket06RenameWorldNBT.ID, () -> new IPCPacket06RenameWorldNBT());
|
||||
mappings.put(IPCPacket07ImportWorld.ID, () -> new IPCPacket07ImportWorld());
|
||||
mappings.put(IPCPacket09RequestResponse.ID, () -> new IPCPacket09RequestResponse());
|
||||
mappings.put(IPCPacket0ASetWorldDifficulty.ID, () -> new IPCPacket0ASetWorldDifficulty());
|
||||
mappings.put(IPCPacket0BPause.ID, () -> new IPCPacket0BPause());
|
||||
mappings.put(IPCPacket0CPlayerChannel.ID, () -> new IPCPacket0CPlayerChannel());
|
||||
mappings.put(IPCPacket0DProgressUpdate.ID, () -> new IPCPacket0DProgressUpdate());
|
||||
mappings.put(IPCPacket0EListWorlds.ID, () -> new IPCPacket0EListWorlds());
|
||||
mappings.put(IPCPacket0FListFiles.ID, () -> new IPCPacket0FListFiles());
|
||||
mappings.put(IPCPacket10FileRead.ID, () -> new IPCPacket10FileRead());
|
||||
mappings.put(IPCPacket12FileWrite.ID, () -> new IPCPacket12FileWrite());
|
||||
mappings.put(IPCPacket13FileCopyMove.ID, () -> new IPCPacket13FileCopyMove());
|
||||
mappings.put(IPCPacket14StringList.ID, () -> new IPCPacket14StringList());
|
||||
mappings.put(IPCPacket15Crashed.ID, () -> new IPCPacket15Crashed());
|
||||
mappings.put(IPCPacket16NBTList.ID, () -> new IPCPacket16NBTList());
|
||||
mappings.put(IPCPacket17ConfigureLAN.ID, () -> new IPCPacket17ConfigureLAN());
|
||||
mappings.put(IPCPacket18ClearPlayers.ID, () -> new IPCPacket18ClearPlayers());
|
||||
mappings.put(IPCPacket19Autosave.ID, () -> new IPCPacket19Autosave());
|
||||
mappings.put(IPCPacket20LoggerMessage.ID, () -> new IPCPacket20LoggerMessage());
|
||||
mappings.put(IPCPacket21EnableLogging.ID, () -> new IPCPacket21EnableLogging());
|
||||
mappings.put(IPCPacketFFProcessKeepAlive.ID, () -> new IPCPacketFFProcessKeepAlive());
|
||||
}
|
||||
|
||||
public static byte[] IPCSerialize(IPCPacketBase pkt) throws IOException {
|
||||
|
||||
IPC_OUTPUT_STREAM.feedBuffer(new byte[pkt.size() + 1], pkt.getClass().getSimpleName());
|
||||
IPC_OUTPUT_STREAM.write(pkt.id());
|
||||
pkt.serialize(IPC_DATA_OUTPUT_STREAM);
|
||||
|
||||
return IPC_OUTPUT_STREAM.returnBuffer();
|
||||
}
|
||||
|
||||
public static IPCPacketBase IPCDeserialize(byte[] pkt) throws IOException {
|
||||
|
||||
IPC_INPUT_STREAM.feedBuffer(pkt);
|
||||
int i = IPC_INPUT_STREAM.read();
|
||||
|
||||
Supplier<IPCPacketBase> pk = mappings.get(Integer.valueOf(i));
|
||||
if(pk == null) {
|
||||
throw new IOException("Packet type 0x" + Integer.toHexString(i) + " doesn't exist");
|
||||
}
|
||||
|
||||
IPCPacketBase p = pk.get();
|
||||
|
||||
IPC_INPUT_STREAM.nameBuffer(p.getClass().getSimpleName());
|
||||
|
||||
p.deserialize(IPC_DATA_INPUT_STREAM);
|
||||
|
||||
int lo = IPC_INPUT_STREAM.getLeftoverCount();
|
||||
if(lo > 0) {
|
||||
System.err.println("Packet type 0x" + Integer.toHexString(i) + " class '" + p.getClass().getSimpleName() + "' was size " + (pkt.length - 1) + " but only " + (pkt.length - 1 - lo) + " bytes were read");
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,413 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.lan;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagUtils;
|
||||
import net.lax1dude.eaglercraft.v1_8.EaglerZLIB;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.EnumEaglerConnectionState;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.netty.ByteBuf;
|
||||
import net.lax1dude.eaglercraft.v1_8.netty.Unpooled;
|
||||
import net.lax1dude.eaglercraft.v1_8.socket.EaglercraftNetworkManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerSocket;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.pkt.*;
|
||||
import net.minecraft.network.EnumPacketDirection;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.ChatComponentTranslation;
|
||||
import net.minecraft.util.IChatComponent;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class LANClientNetworkManager extends EaglercraftNetworkManager {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger("LANClientNetworkManager");
|
||||
|
||||
private static final int PRE = 0, INIT = 1, SENT_ICE_CANDIDATE = 2, SENT_DESCRIPTION = 3;
|
||||
|
||||
public static final int fragmentSize = 0xFF00;
|
||||
|
||||
private static final String[] initStateNames = new String[] { "PRE", "INIT", "SENT_ICE_CANDIDATE", "SENT_DESCRIPTION" };
|
||||
|
||||
public final String displayCode;
|
||||
public final String displayRelay;
|
||||
|
||||
private boolean firstPacket = true;
|
||||
|
||||
private LANClientNetworkManager(String displayCode, String displayRelay) {
|
||||
super("");
|
||||
this.displayCode = displayCode;
|
||||
this.displayRelay = displayRelay;
|
||||
this.nethandler = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
fragmentedPacket.clear();
|
||||
firstPacket = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumEaglerConnectionState getConnectStatus() {
|
||||
return clientDisconnected ? EnumEaglerConnectionState.CLOSED : EnumEaglerConnectionState.CONNECTED;
|
||||
}
|
||||
|
||||
public static LANClientNetworkManager connectToWorld(RelayServerSocket sock, String displayCode, String displayRelay) {
|
||||
PlatformWebRTC.clearLANClientState();
|
||||
int connectState = PRE;
|
||||
IPacket pkt;
|
||||
mainLoop: while(!sock.isClosed()) {
|
||||
if((pkt = sock.readPacket()) != null) {
|
||||
if(pkt instanceof IPacket00Handshake) {
|
||||
if(connectState == PRE) {
|
||||
|
||||
// %%%%%% Process IPacket00Handshake %%%%%%
|
||||
|
||||
logger.info("Relay [{}|{}] recieved handshake, client id: {}", displayRelay, displayCode, ((IPacket00Handshake)pkt).connectionCode);
|
||||
connectState = INIT;
|
||||
|
||||
}else {
|
||||
sock.close();
|
||||
logger.error("Relay [{}|{}] unexpected packet: IPacket00Handshake in state {}", displayRelay, displayCode, initStateNames[connectState]);
|
||||
return null;
|
||||
}
|
||||
}else if(pkt instanceof IPacket01ICEServers) {
|
||||
if(connectState == INIT) {
|
||||
|
||||
// %%%%%% Process IPacket01ICEServers %%%%%%
|
||||
|
||||
IPacket01ICEServers ipkt = (IPacket01ICEServers) pkt;
|
||||
|
||||
// print servers
|
||||
logger.info("Relay [{}|{}] provided ICE servers:", displayRelay, displayCode);
|
||||
List<String> servers = new ArrayList();
|
||||
for(ICEServerSet.RelayServer srv : ipkt.servers) {
|
||||
logger.info("Relay [{}|{}] {}: {}", displayRelay, displayCode, srv.type.name(), srv.address);
|
||||
servers.add(srv.getICEString());
|
||||
}
|
||||
|
||||
// process
|
||||
PlatformWebRTC.clientLANSetICEServersAndConnect(servers.toArray(new String[servers.size()]));
|
||||
|
||||
// await result
|
||||
long lm = System.currentTimeMillis();
|
||||
do {
|
||||
String c = PlatformWebRTC.clientLANAwaitDescription();
|
||||
if(c != null) {
|
||||
logger.info("Relay [{}|{}] client sent description", displayRelay, displayCode);
|
||||
|
||||
// 'this.descriptionHandler' was called, send result:
|
||||
sock.writePacket(new IPacket04Description("", c));
|
||||
|
||||
connectState = SENT_DESCRIPTION;
|
||||
continue mainLoop;
|
||||
}
|
||||
EagUtils.sleep(20l);
|
||||
}while(System.currentTimeMillis() - lm < 5000l);
|
||||
|
||||
// no description was sent
|
||||
sock.close();
|
||||
logger.error("Relay [{}|{}] client provide description timeout", displayRelay, displayCode);
|
||||
return null;
|
||||
|
||||
}else {
|
||||
sock.close();
|
||||
logger.error("Relay [{}|{}] unexpected packet: IPacket01ICEServers in state {}", displayRelay, displayCode, initStateNames[connectState]);
|
||||
return null;
|
||||
}
|
||||
}else if(pkt instanceof IPacket03ICECandidate) {
|
||||
if(connectState == SENT_ICE_CANDIDATE) {
|
||||
|
||||
// %%%%%% Process IPacket03ICECandidate %%%%%%
|
||||
|
||||
IPacket03ICECandidate ipkt = (IPacket03ICECandidate) pkt;
|
||||
|
||||
// process
|
||||
logger.info("Relay [{}|{}] recieved server ICE candidate", displayRelay, displayCode);
|
||||
PlatformWebRTC.clientLANSetICECandidate(ipkt.candidate);
|
||||
|
||||
// await result
|
||||
long lm = System.currentTimeMillis();
|
||||
do {
|
||||
if(PlatformWebRTC.clientLANAwaitChannel()) {
|
||||
logger.info("Relay [{}|{}] client opened data channel", displayRelay, displayCode);
|
||||
|
||||
// 'this.remoteDataChannelHandler' was called, success
|
||||
sock.writePacket(new IPacket05ClientSuccess(ipkt.peerId));
|
||||
sock.close();
|
||||
return new LANClientNetworkManager(displayCode, displayRelay);
|
||||
|
||||
}
|
||||
EagUtils.sleep(20l);
|
||||
}while(System.currentTimeMillis() - lm < 5000l);
|
||||
|
||||
// no channel was opened
|
||||
sock.writePacket(new IPacket06ClientFailure(ipkt.peerId));
|
||||
sock.close();
|
||||
logger.error("Relay [{}|{}] client open data channel timeout", displayRelay, displayCode);
|
||||
return null;
|
||||
|
||||
}else {
|
||||
sock.close();
|
||||
logger.error("Relay [{}|{}] unexpected packet: IPacket03ICECandidate in state {}", displayRelay, displayCode, initStateNames[connectState]);
|
||||
return null;
|
||||
}
|
||||
}else if(pkt instanceof IPacket04Description) {
|
||||
if(connectState == SENT_DESCRIPTION) {
|
||||
|
||||
// %%%%%% Process IPacket04Description %%%%%%
|
||||
|
||||
IPacket04Description ipkt = (IPacket04Description) pkt;
|
||||
|
||||
// process
|
||||
logger.info("Relay [{}|{}] recieved server description", displayRelay, displayCode);
|
||||
PlatformWebRTC.clientLANSetDescription(ipkt.description);
|
||||
|
||||
// await result
|
||||
long lm = System.currentTimeMillis();
|
||||
do {
|
||||
String c = PlatformWebRTC.clientLANAwaitICECandidate();
|
||||
if(c != null) {
|
||||
logger.info("Relay [{}|{}] client sent ICE candidate", displayRelay, displayCode);
|
||||
|
||||
// 'this.iceCandidateHandler' was called, send result:
|
||||
sock.writePacket(new IPacket03ICECandidate("", c));
|
||||
|
||||
connectState = SENT_ICE_CANDIDATE;
|
||||
continue mainLoop;
|
||||
}
|
||||
EagUtils.sleep(20l);
|
||||
}while(System.currentTimeMillis() - lm < 5000l);
|
||||
|
||||
// no ice candidates were sent
|
||||
sock.close();
|
||||
logger.error("Relay [{}|{}] client provide ICE candidate timeout", displayRelay, displayCode);
|
||||
return null;
|
||||
|
||||
}else {
|
||||
sock.close();
|
||||
logger.error("Relay [{}|{}] unexpected packet: IPacket04Description in state {}", displayRelay, displayCode, initStateNames[connectState]);
|
||||
return null;
|
||||
}
|
||||
}else if(pkt instanceof IPacketFFErrorCode) {
|
||||
|
||||
// %%%%%% Process IPacketFFErrorCode %%%%%%
|
||||
|
||||
IPacketFFErrorCode ipkt = (IPacketFFErrorCode) pkt;
|
||||
logger.error("Relay [{}|{}] connection failed: {}({}): {}", displayRelay, displayCode, IPacketFFErrorCode.code2string(ipkt.code), ipkt.code, ipkt.desc);
|
||||
Throwable t;
|
||||
while((t = sock.getException()) != null) {
|
||||
logger.error(t);
|
||||
}
|
||||
sock.close();
|
||||
return null;
|
||||
|
||||
}else {
|
||||
|
||||
// %%%%%% Unexpected Packet %%%%%%
|
||||
|
||||
logger.error("Relay [{}|{}] unexpected packet: {}", displayRelay, displayCode, pkt.getClass().getSimpleName());
|
||||
sock.close();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
EagUtils.sleep(20l);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPacket(Packet pkt) {
|
||||
if(!isChannelOpen()) {
|
||||
logger.error("Packet was sent on a closed connection: {}", pkt.getClass().getSimpleName());
|
||||
return;
|
||||
}
|
||||
|
||||
int i;
|
||||
try {
|
||||
i = packetState.getPacketId(EnumPacketDirection.SERVERBOUND, pkt);
|
||||
}catch(Throwable t) {
|
||||
logger.error("Incorrect packet for state: {}", pkt.getClass().getSimpleName());
|
||||
return;
|
||||
}
|
||||
|
||||
temporaryBuffer.clear();
|
||||
temporaryBuffer.writeVarIntToBuffer(i);
|
||||
try {
|
||||
pkt.writePacketData(temporaryBuffer);
|
||||
}catch(IOException ex) {
|
||||
logger.error("Failed to write packet {}!", pkt.getClass().getSimpleName());
|
||||
return;
|
||||
}
|
||||
|
||||
int len = temporaryBuffer.readableBytes();
|
||||
int fragmentSizeN1 = fragmentSize - 1;
|
||||
if(len > fragmentSizeN1) {
|
||||
do {
|
||||
int readLen = len > fragmentSizeN1 ? fragmentSizeN1 : len;
|
||||
byte[] frag = new byte[readLen + 1];
|
||||
temporaryBuffer.readBytes(frag, 1, readLen);
|
||||
frag[0] = temporaryBuffer.readableBytes() == 0 ? (byte)0 : (byte)1;
|
||||
PlatformWebRTC.clientLANSendPacket(frag);
|
||||
}while((len = temporaryBuffer.readableBytes()) > 0);
|
||||
}else {
|
||||
byte[] bytes = new byte[len + 1];
|
||||
bytes[0] = 0;
|
||||
temporaryBuffer.readBytes(bytes, 1, len);
|
||||
PlatformWebRTC.clientLANSendPacket(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLocalChannel() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChannelOpen() {
|
||||
if (PlatformWebRTC.clientLANClosed()) {
|
||||
clientDisconnected = true;
|
||||
}
|
||||
return !clientDisconnected;
|
||||
}
|
||||
|
||||
private List<byte[]> fragmentedPacket = new ArrayList();
|
||||
|
||||
@Override
|
||||
public void processReceivedPackets() throws IOException {
|
||||
if(this.nethandler != null) {
|
||||
List<byte[]> packets = PlatformWebRTC.clientLANReadAllPacket();
|
||||
if(packets == null) {
|
||||
return;
|
||||
}
|
||||
for(byte[] data : packets) {
|
||||
byte[] fullData;
|
||||
boolean compressed = false;
|
||||
|
||||
if (data[0] == 0 || data[0] == 2) {
|
||||
if(fragmentedPacket.isEmpty()) {
|
||||
fullData = new byte[data.length - 1];
|
||||
System.arraycopy(data, 1, fullData, 0, fullData.length);
|
||||
}else {
|
||||
fragmentedPacket.add(data);
|
||||
int len = 0;
|
||||
int fragCount = fragmentedPacket.size();
|
||||
for(int i = 0; i < fragCount; ++i) {
|
||||
len += fragmentedPacket.get(i).length - 1;
|
||||
}
|
||||
fullData = new byte[len];
|
||||
len = 0;
|
||||
for(int i = 0; i < fragCount; ++i) {
|
||||
byte[] f = fragmentedPacket.get(i);
|
||||
System.arraycopy(f, 1, fullData, len, f.length - 1);
|
||||
len += f.length - 1;
|
||||
}
|
||||
fragmentedPacket.clear();
|
||||
}
|
||||
compressed = data[0] == 2;
|
||||
} else if (data[0] == 1) {
|
||||
fragmentedPacket.add(data);
|
||||
continue;
|
||||
} else {
|
||||
logger.error("Recieved {} byte fragment of unknown type: {}", data.length, ((int)data[0] & 0xFF));
|
||||
continue;
|
||||
}
|
||||
|
||||
if(compressed) {
|
||||
if(fullData.length < 4) {
|
||||
throw new IOException("Recieved invalid " + fullData.length + " byte compressed packet");
|
||||
}
|
||||
ByteArrayInputStream bi = new ByteArrayInputStream(fullData);
|
||||
int i = (bi.read() << 24) | (bi.read() << 16) | (bi.read() << 8) | bi.read();
|
||||
InputStream inflaterInputStream = EaglerZLIB.newInflaterInputStream(bi);
|
||||
fullData = new byte[i];
|
||||
inflaterInputStream.read(fullData);
|
||||
}
|
||||
|
||||
if(firstPacket) {
|
||||
// 1.5 kick packet
|
||||
if(fullData.length == 31 && fullData[0] == (byte)0xFF && fullData[1] == (byte)0x00 && fullData[2] == (byte)0x0E) {
|
||||
logger.error("Detected a 1.5 LAN server!");
|
||||
this.closeChannel(new ChatComponentTranslation("singleplayer.outdatedLANServerKick"));
|
||||
firstPacket = false;
|
||||
return;
|
||||
}
|
||||
firstPacket = false;
|
||||
}
|
||||
|
||||
ByteBuf nettyBuffer = Unpooled.buffer(fullData, fullData.length);
|
||||
nettyBuffer.writerIndex(fullData.length);
|
||||
PacketBuffer input = new PacketBuffer(nettyBuffer);
|
||||
int pktId = input.readVarIntFromBuffer();
|
||||
|
||||
Packet pkt;
|
||||
try {
|
||||
pkt = packetState.getPacket(EnumPacketDirection.CLIENTBOUND, pktId);
|
||||
}catch(IllegalAccessException | InstantiationException ex) {
|
||||
throw new IOException("Recieved a packet with type " + pktId + " which is invalid!");
|
||||
}
|
||||
|
||||
if(pkt == null) {
|
||||
throw new IOException("Recieved packet type " + pktId + " which is undefined in state " + packetState);
|
||||
}
|
||||
|
||||
try {
|
||||
pkt.readPacketData(input);
|
||||
}catch(Throwable t) {
|
||||
throw new IOException("Failed to read packet type '" + pkt.getClass().getSimpleName() + "'", t);
|
||||
}
|
||||
|
||||
try {
|
||||
pkt.processPacket(nethandler);
|
||||
}catch(Throwable t) {
|
||||
logger.error("Failed to process {}! It'll be skipped for debug purposes.", pkt.getClass().getSimpleName());
|
||||
logger.error(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeChannel(IChatComponent reason) {
|
||||
if(!PlatformWebRTC.clientLANClosed()) {
|
||||
PlatformWebRTC.clientLANCloseConnection();
|
||||
}
|
||||
if(nethandler != null) {
|
||||
nethandler.onDisconnect(reason);
|
||||
}
|
||||
clientDisconnected = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkDisconnected() {
|
||||
if(PlatformWebRTC.clientLANClosed()) {
|
||||
clientDisconnected = false;
|
||||
try {
|
||||
processReceivedPackets(); // catch kick message
|
||||
} catch (IOException e) {
|
||||
}
|
||||
doClientDisconnect(new ChatComponentTranslation("disconnect.endOfStream"));
|
||||
}
|
||||
return clientDisconnected;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,175 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.lan;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagUtils;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IPCPacketData;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.SingleplayerServerController;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.internal.ClientPlatformSingleplayer;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.pkt.IPacket03ICECandidate;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.pkt.IPacket04Description;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
class LANClientPeer {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger("LANClientPeer");
|
||||
|
||||
private static final int PRE = 0, SENT_ICE_CANDIDATE = 2, SENT_DESCRIPTION = 3, CONNECTED = 4, CLOSED = 5;
|
||||
|
||||
protected final String clientId;
|
||||
|
||||
protected int state = PRE;
|
||||
protected boolean dead = false;
|
||||
|
||||
protected LANClientPeer(String clientId) {
|
||||
this.clientId = clientId;
|
||||
PlatformWebRTC.serverLANCreatePeer(clientId);
|
||||
}
|
||||
|
||||
protected void handleICECandidates(String candidates) {
|
||||
if(state == SENT_DESCRIPTION) {
|
||||
PlatformWebRTC.serverLANPeerICECandidates(clientId, candidates);
|
||||
long millis = System.currentTimeMillis();
|
||||
do {
|
||||
LANPeerEvent evt;
|
||||
if((evt = PlatformWebRTC.serverLANGetEvent(clientId)) != null) {
|
||||
if(evt instanceof LANPeerEvent.LANPeerICECandidateEvent) {
|
||||
LANServerController.lanRelaySocket.writePacket(new IPacket03ICECandidate(clientId, ((LANPeerEvent.LANPeerICECandidateEvent)evt).candidates));
|
||||
state = SENT_ICE_CANDIDATE;
|
||||
return;
|
||||
}else if(evt instanceof LANPeerEvent.LANPeerDisconnectEvent) {
|
||||
logger.error("LAN client '{}' disconnected while waiting for server ICE candidates", clientId);
|
||||
}else {
|
||||
logger.error("LAN client '{}' had an accident: {}", clientId, evt.getClass().getSimpleName());
|
||||
}
|
||||
disconnect();
|
||||
return;
|
||||
}
|
||||
EagUtils.sleep(20l);
|
||||
}while(System.currentTimeMillis() - millis < 5000l);
|
||||
logger.error("Getting server ICE candidates for '{}' timed out!", clientId);
|
||||
disconnect();
|
||||
}else {
|
||||
logger.error("Relay [{}] unexpected IPacket03ICECandidate for '{}'", LANServerController.lanRelaySocket.getURI(), clientId);
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleDescription(String description) {
|
||||
if(state == PRE) {
|
||||
PlatformWebRTC.serverLANPeerDescription(clientId, description);
|
||||
long millis = System.currentTimeMillis();
|
||||
do {
|
||||
LANPeerEvent evt;
|
||||
if((evt = PlatformWebRTC.serverLANGetEvent(clientId)) != null) {
|
||||
if(evt instanceof LANPeerEvent.LANPeerDescriptionEvent) {
|
||||
LANServerController.lanRelaySocket.writePacket(new IPacket04Description(clientId, ((LANPeerEvent.LANPeerDescriptionEvent)evt).description));
|
||||
state = SENT_DESCRIPTION;
|
||||
return;
|
||||
}else if(evt instanceof LANPeerEvent.LANPeerDisconnectEvent) {
|
||||
logger.error("LAN client '{}' disconnected while waiting for server description", clientId);
|
||||
}else {
|
||||
logger.error("LAN client '{}' had an accident: {}", clientId, evt.getClass().getSimpleName());
|
||||
}
|
||||
disconnect();
|
||||
return;
|
||||
}
|
||||
EagUtils.sleep(20l);
|
||||
}while(System.currentTimeMillis() - millis < 5000l);
|
||||
logger.error("Getting server description for '{}' timed out!", clientId);
|
||||
disconnect();
|
||||
}else {
|
||||
logger.error("Relay [{}] unexpected IPacket04Description for '{}'", LANServerController.lanRelaySocket.getURI(), clientId);
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleSuccess() {
|
||||
if(state == SENT_ICE_CANDIDATE) {
|
||||
long millis = System.currentTimeMillis();
|
||||
do {
|
||||
LANPeerEvent evt;
|
||||
while((evt = PlatformWebRTC.serverLANGetEvent(clientId)) != null && evt instanceof LANPeerEvent.LANPeerICECandidateEvent) {
|
||||
// skip ice candidates
|
||||
}
|
||||
if(evt != null) {
|
||||
if(evt instanceof LANPeerEvent.LANPeerDataChannelEvent) {
|
||||
SingleplayerServerController.openPlayerChannel(clientId);
|
||||
state = CONNECTED;
|
||||
return;
|
||||
}else if(evt instanceof LANPeerEvent.LANPeerDisconnectEvent) {
|
||||
logger.error("LAN client '{}' disconnected while waiting for connection", clientId);
|
||||
}else {
|
||||
logger.error("LAN client '{}' had an accident: {}", clientId, evt.getClass().getSimpleName());
|
||||
}
|
||||
disconnect();
|
||||
return;
|
||||
}
|
||||
EagUtils.sleep(20l);
|
||||
}while(System.currentTimeMillis() - millis < 5000l);
|
||||
logger.error("Getting server description for '{}' timed out!", clientId);
|
||||
disconnect();
|
||||
}else {
|
||||
logger.error("Relay [{}] unexpected IPacket05ClientSuccess for '{}'", LANServerController.lanRelaySocket.getURI(), clientId);
|
||||
}
|
||||
}
|
||||
|
||||
protected void handleFailure() {
|
||||
if(state == SENT_ICE_CANDIDATE) {
|
||||
logger.error("Client '{}' failed to connect", clientId);
|
||||
disconnect();
|
||||
}else {
|
||||
logger.error("Relay [{}] unexpected IPacket06ClientFailure for '{}'", LANServerController.lanRelaySocket.getURI(), clientId);
|
||||
}
|
||||
}
|
||||
|
||||
protected void update() {
|
||||
if(state == CONNECTED) {
|
||||
List<LANPeerEvent> l = PlatformWebRTC.serverLANGetAllEvent(clientId);
|
||||
if(l == null) {
|
||||
return;
|
||||
}
|
||||
Iterator<LANPeerEvent> itr = l.iterator();
|
||||
while(state == CONNECTED && itr.hasNext()) {
|
||||
LANPeerEvent evt = itr.next();
|
||||
if(evt instanceof LANPeerEvent.LANPeerPacketEvent) {
|
||||
ClientPlatformSingleplayer.sendPacket(new IPCPacketData(clientId, ((LANPeerEvent.LANPeerPacketEvent)evt).payload));
|
||||
}else if(evt instanceof LANPeerEvent.LANPeerDisconnectEvent) {
|
||||
logger.info("LAN client '{}' disconnected", clientId);
|
||||
disconnect();
|
||||
}else {
|
||||
logger.error("LAN client '{}' had an accident: {}", clientId, evt.getClass().getSimpleName());
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void disconnect() {
|
||||
if(!dead) {
|
||||
if(state == CONNECTED) {
|
||||
SingleplayerServerController.closePlayerChannel(clientId);
|
||||
}
|
||||
state = CLOSED;
|
||||
PlatformWebRTC.serverLANDisconnectPeer(clientId);
|
||||
dead = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.lan;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public interface LANPeerEvent {
|
||||
|
||||
String getPeerId();
|
||||
|
||||
public static class LANPeerICECandidateEvent implements LANPeerEvent {
|
||||
|
||||
public final String clientId;
|
||||
public final String candidates;
|
||||
|
||||
public LANPeerICECandidateEvent(String clientId, String candidates) {
|
||||
this.clientId = clientId;
|
||||
this.candidates = candidates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPeerId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class LANPeerDescriptionEvent implements LANPeerEvent {
|
||||
|
||||
public final String clientId;
|
||||
public final String description;
|
||||
|
||||
public LANPeerDescriptionEvent(String clientId, String description) {
|
||||
this.clientId = clientId;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPeerId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class LANPeerDataChannelEvent implements LANPeerEvent {
|
||||
|
||||
public final String clientId;
|
||||
|
||||
public LANPeerDataChannelEvent(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPeerId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class LANPeerPacketEvent implements LANPeerEvent {
|
||||
|
||||
public final String clientId;
|
||||
public final byte[] payload;
|
||||
|
||||
public LANPeerPacketEvent(String clientId, byte[] payload) {
|
||||
this.clientId = clientId;
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPeerId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class LANPeerDisconnectEvent implements LANPeerEvent {
|
||||
|
||||
public final String clientId;
|
||||
|
||||
public LANPeerDisconnectEvent(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPeerId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,207 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.lan;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagUtils;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerSocket;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.pkt.*;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class LANServerController {
|
||||
|
||||
public static final Logger logger = LogManager.getLogger("IntegratedServerLAN");
|
||||
|
||||
public static final List<String> currentICEServers = new ArrayList();
|
||||
|
||||
static RelayServerSocket lanRelaySocket = null;
|
||||
|
||||
private static String currentCode = null;
|
||||
|
||||
public static String shareToLAN(Consumer<String> progressCallback, String worldName, boolean worldHidden) {
|
||||
currentCode = null;
|
||||
RelayServerSocket sock = RelayManager.relayManager.getWorkingRelay((str) -> progressCallback.accept("Connecting: " + str),
|
||||
RelayManager.preferredRelayVersion, worldName + (worldHidden ? ";1" : ";0"));
|
||||
if(sock == null) {
|
||||
lanRelaySocket = null;
|
||||
return null;
|
||||
}else {
|
||||
progressCallback.accept("Opening: " + sock.getURI());
|
||||
IPacket00Handshake hs = (IPacket00Handshake)sock.readPacket();
|
||||
lanRelaySocket = sock;
|
||||
String code = hs.connectionCode;
|
||||
logger.info("Relay [{}] connected as 'server', code: {}", sock.getURI(), code);
|
||||
progressCallback.accept("Opened '" + code + "' on " + sock.getURI());
|
||||
long millis = System.currentTimeMillis();
|
||||
do {
|
||||
if(sock.isClosed()) {
|
||||
logger.info("Relay [{}] connection lost", sock.getURI());
|
||||
lanRelaySocket = null;
|
||||
return null;
|
||||
}
|
||||
IPacket pkt = sock.readPacket();
|
||||
if(pkt != null) {
|
||||
if(pkt instanceof IPacket01ICEServers) {
|
||||
IPacket01ICEServers ipkt = (IPacket01ICEServers)pkt;
|
||||
logger.info("Relay [{}] provided ICE servers:", sock.getURI());
|
||||
currentICEServers.clear();
|
||||
for(net.lax1dude.eaglercraft.v1_8.sp.relay.pkt.ICEServerSet.RelayServer srv : ipkt.servers) {
|
||||
logger.info("Relay [{}] {}: {}", sock.getURI(), srv.type.name(), srv.address);
|
||||
currentICEServers.add(srv.getICEString());
|
||||
}
|
||||
PlatformWebRTC.serverLANInitializeServer(currentICEServers.toArray(new String[currentICEServers.size()]));
|
||||
return currentCode = code;
|
||||
}else {
|
||||
logger.error("Relay [{}] unexpected packet: {}", sock.getURI(), pkt.getClass().getSimpleName());
|
||||
closeLAN();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
EagUtils.sleep(50l);
|
||||
}while(System.currentTimeMillis() - millis < 1000l);
|
||||
logger.info("Relay [{}] relay provide ICE servers timeout", sock.getURI());
|
||||
closeLAN();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getCurrentURI() {
|
||||
return lanRelaySocket == null ? "<disconnected>" : lanRelaySocket.getURI();
|
||||
}
|
||||
|
||||
public static String getCurrentCode() {
|
||||
return currentCode == null ? "<undefined>" : currentCode;
|
||||
}
|
||||
|
||||
public static void closeLAN() {
|
||||
closeLANNoKick();
|
||||
cleanupLAN();
|
||||
if (isLANOpen()) {
|
||||
PlatformWebRTC.serverLANCloseServer();
|
||||
}
|
||||
}
|
||||
|
||||
public static void closeLANNoKick() {
|
||||
if(lanRelaySocket != null) {
|
||||
lanRelaySocket.close();
|
||||
lanRelaySocket = null;
|
||||
currentCode = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void cleanupLAN() {
|
||||
Iterator<LANClientPeer> itr = clients.values().iterator();
|
||||
while(itr.hasNext()) {
|
||||
itr.next().disconnect();
|
||||
}
|
||||
clients.clear();
|
||||
}
|
||||
|
||||
public static boolean hasPeers() {
|
||||
return PlatformWebRTC.countPeers() > 0;
|
||||
}
|
||||
|
||||
public static boolean isHostingLAN() {
|
||||
return lanRelaySocket != null || PlatformWebRTC.countPeers() > 0;
|
||||
}
|
||||
|
||||
public static boolean isLANOpen() {
|
||||
return lanRelaySocket != null;
|
||||
}
|
||||
|
||||
private static final Map<String, LANClientPeer> clients = new HashMap();
|
||||
|
||||
public static void updateLANServer() {
|
||||
if(lanRelaySocket != null) {
|
||||
IPacket pkt;
|
||||
while((pkt = lanRelaySocket.readPacket()) != null) {
|
||||
if(pkt instanceof IPacket02NewClient) {
|
||||
IPacket02NewClient ipkt = (IPacket02NewClient) pkt;
|
||||
if(clients.containsKey(ipkt.clientId)) {
|
||||
logger.error("Relay [{}] relay provided duplicate client '{}'", lanRelaySocket.getURI(), ipkt.clientId);
|
||||
}else {
|
||||
clients.put(ipkt.clientId, new LANClientPeer(ipkt.clientId));
|
||||
}
|
||||
}else if(pkt instanceof IPacket03ICECandidate) {
|
||||
IPacket03ICECandidate ipkt = (IPacket03ICECandidate) pkt;
|
||||
LANClientPeer c = clients.get(ipkt.peerId);
|
||||
if(c != null) {
|
||||
c.handleICECandidates(ipkt.candidate);
|
||||
}else {
|
||||
logger.error("Relay [{}] relay sent IPacket03ICECandidate for unknown client '{}'", lanRelaySocket.getURI(), ipkt.peerId);
|
||||
}
|
||||
}else if(pkt instanceof IPacket04Description) {
|
||||
IPacket04Description ipkt = (IPacket04Description) pkt;
|
||||
LANClientPeer c = clients.get(ipkt.peerId);
|
||||
if(c != null) {
|
||||
c.handleDescription(ipkt.description);
|
||||
}else {
|
||||
logger.error("Relay [{}] relay sent IPacket04Description for unknown client '{}'", lanRelaySocket.getURI(), ipkt.peerId);
|
||||
}
|
||||
}else if(pkt instanceof IPacket05ClientSuccess) {
|
||||
IPacket05ClientSuccess ipkt = (IPacket05ClientSuccess) pkt;
|
||||
LANClientPeer c = clients.get(ipkt.clientId);
|
||||
if(c != null) {
|
||||
c.handleSuccess();
|
||||
}else {
|
||||
logger.error("Relay [{}] relay sent IPacket05ClientSuccess for unknown client '{}'", lanRelaySocket.getURI(), ipkt.clientId);
|
||||
}
|
||||
}else if(pkt instanceof IPacket06ClientFailure) {
|
||||
IPacket06ClientFailure ipkt = (IPacket06ClientFailure) pkt;
|
||||
LANClientPeer c = clients.get(ipkt.clientId);
|
||||
if(c != null) {
|
||||
c.handleFailure();
|
||||
}else {
|
||||
logger.error("Relay [{}] relay sent IPacket06ClientFailure for unknown client '{}'", lanRelaySocket.getURI(), ipkt.clientId);
|
||||
}
|
||||
}else if(pkt instanceof IPacketFFErrorCode) {
|
||||
IPacketFFErrorCode ipkt = (IPacketFFErrorCode) pkt;
|
||||
logger.error("Relay [{}] error code thrown: {}({}): {}", lanRelaySocket.getURI(), IPacketFFErrorCode.code2string(ipkt.code), ipkt.code, ipkt.desc);
|
||||
Throwable t;
|
||||
while((t = lanRelaySocket.getException()) != null) {
|
||||
logger.error(t);
|
||||
}
|
||||
}else {
|
||||
logger.error("Relay [{}] unexpected packet: {}", lanRelaySocket.getURI(), pkt.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
if(lanRelaySocket.isClosed()) {
|
||||
lanRelaySocket = null;
|
||||
}
|
||||
}
|
||||
Iterator<LANClientPeer> itr = clients.values().iterator();
|
||||
while(itr.hasNext()) {
|
||||
LANClientPeer cl = itr.next();
|
||||
cl.update();
|
||||
if(cl.dead) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean supported() {
|
||||
return PlatformWebRTC.supported();
|
||||
}
|
||||
}
|
@ -0,0 +1,166 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.lan;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServer;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayWorldsQuery;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.pkt.IPacket07LocalWorlds;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class LANServerList {
|
||||
|
||||
private final List<LanServer> lanServersList = new LinkedList();
|
||||
private final Map<String, RelayWorldsQuery> lanServersQueryList = new LinkedHashMap();
|
||||
private final Set<String> deadURIs = new HashSet();
|
||||
|
||||
private long lastRefresh = 0l;
|
||||
private int refreshCounter = 0;
|
||||
|
||||
public boolean update() {
|
||||
long millis = System.currentTimeMillis();
|
||||
if(millis - lastRefresh > 20000l) {
|
||||
if(++refreshCounter < 10) {
|
||||
refresh();
|
||||
}else {
|
||||
lastRefresh = millis;
|
||||
}
|
||||
}else {
|
||||
boolean changed = false;
|
||||
Iterator<Entry<String,RelayWorldsQuery>> itr = lanServersQueryList.entrySet().iterator();
|
||||
while(itr.hasNext()) {
|
||||
Entry<String,RelayWorldsQuery> etr = itr.next();
|
||||
String uri = etr.getKey();
|
||||
RelayWorldsQuery q = etr.getValue();
|
||||
if(!q.isQueryOpen()) {
|
||||
itr.remove();
|
||||
if(q.isQueryFailed()) {
|
||||
deadURIs.add(uri);
|
||||
Iterator<LanServer> itr2 = lanServersList.iterator();
|
||||
while(itr2.hasNext()) {
|
||||
if(itr2.next().lanServerRelay.address.equals(uri)) {
|
||||
itr2.remove();
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}else {
|
||||
RelayServer rl = RelayManager.relayManager.getByURI(uri);
|
||||
Iterator<LanServer> itr2 = lanServersList.iterator();
|
||||
while(itr2.hasNext()) {
|
||||
LanServer l = itr2.next();
|
||||
if(l.lanServerRelay.address.equals(uri)) {
|
||||
l.flagged = false;
|
||||
}
|
||||
}
|
||||
if(rl != null) {
|
||||
Iterator<IPacket07LocalWorlds.LocalWorld> itr3 = q.getWorlds().iterator();
|
||||
yee: while(itr3.hasNext()) {
|
||||
IPacket07LocalWorlds.LocalWorld l = itr3.next();
|
||||
itr2 = lanServersList.iterator();
|
||||
while(itr2.hasNext()) {
|
||||
LanServer l2 = itr2.next();
|
||||
if(l2.lanServerRelay.address.equals(uri) && l2.lanServerCode.equals(l.worldCode)) {
|
||||
l2.lanServerMotd = l.worldName;
|
||||
l2.flagged = true;
|
||||
continue yee;
|
||||
}
|
||||
}
|
||||
lanServersList.add(new LanServer(l.worldName, rl, l.worldCode));
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
itr2 = lanServersList.iterator();
|
||||
while(itr2.hasNext()) {
|
||||
LanServer l = itr2.next();
|
||||
if(l.lanServerRelay.address.equals(uri)) {
|
||||
if(!l.flagged) {
|
||||
itr2.remove();
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void forceRefresh() {
|
||||
deadURIs.clear();
|
||||
refreshCounter = 0;
|
||||
refresh();
|
||||
}
|
||||
|
||||
private void refresh() {
|
||||
lastRefresh = System.currentTimeMillis();
|
||||
if(PlatformWebRTC.supported()) {
|
||||
for(int i = 0, l = RelayManager.relayManager.count(); i < l; ++i) {
|
||||
RelayServer srv = RelayManager.relayManager.get(i);
|
||||
if(!lanServersQueryList.containsKey(srv.address) && !deadURIs.contains(srv.address)) {
|
||||
lanServersQueryList.put(srv.address, PlatformWebRTC.openRelayWorldsQuery(srv.address));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public LanServer getServer(int idx) {
|
||||
return lanServersList.get(idx);
|
||||
}
|
||||
|
||||
public int countServers() {
|
||||
return lanServersList.size();
|
||||
}
|
||||
|
||||
public class LanServer {
|
||||
|
||||
private String lanServerMotd;
|
||||
private RelayServer lanServerRelay;
|
||||
private String lanServerCode;
|
||||
|
||||
protected boolean flagged = true;
|
||||
|
||||
protected LanServer(String lanServerMotd, RelayServer lanServerRelay, String lanServerCode) {
|
||||
this.lanServerMotd = lanServerMotd;
|
||||
this.lanServerRelay = lanServerRelay;
|
||||
this.lanServerCode = lanServerCode;
|
||||
}
|
||||
|
||||
public String getLanServerMotd() {
|
||||
return lanServerMotd;
|
||||
}
|
||||
|
||||
public RelayServer getLanServerRelay() {
|
||||
return lanServerRelay;
|
||||
}
|
||||
|
||||
public String getLanServerCode() {
|
||||
return lanServerCode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class RelayEntry {
|
||||
|
||||
public final String address;
|
||||
public final String comment;
|
||||
public final boolean primary;
|
||||
|
||||
public RelayEntry(String address, String comment, boolean primary) {
|
||||
this.address = address;
|
||||
this.comment = comment;
|
||||
this.primary = primary;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,360 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.EagUtils;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.pkt.IPacket;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.pkt.IPacket00Handshake;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.pkt.IPacketFFErrorCode;
|
||||
import net.minecraft.nbt.CompressedStreamTools;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.nbt.NBTTagList;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class RelayManager {
|
||||
|
||||
public static final Logger logger = LogManager.getLogger("RelayManager");
|
||||
|
||||
public static final RelayManager relayManager = new RelayManager();
|
||||
public static final int preferredRelayVersion = 1;
|
||||
|
||||
private final List<RelayServer> relays = new ArrayList();
|
||||
private long lastPingThrough = 0l;
|
||||
|
||||
public void load(NBTTagList relayConfig) {
|
||||
relays.clear();
|
||||
if(relayConfig != null && relayConfig.tagCount() > 0) {
|
||||
boolean gotAPrimary = false;
|
||||
for(int i = 0, l = relayConfig.tagCount(); i < l; ++i) {
|
||||
NBTTagCompound relay = relayConfig.getCompoundTagAt(i);
|
||||
boolean p = relay.getBoolean("primary");
|
||||
if(p) {
|
||||
if(gotAPrimary) {
|
||||
p = false;
|
||||
}else {
|
||||
gotAPrimary = true;
|
||||
}
|
||||
}
|
||||
relays.add(new RelayServer(relay.getString("addr"), relay.getString("comment"), p));
|
||||
}
|
||||
}
|
||||
sort();
|
||||
}
|
||||
|
||||
public void save() {
|
||||
try {
|
||||
NBTTagList lst = new NBTTagList();
|
||||
for(int i = 0, l = relays.size(); i < l; ++i) {
|
||||
RelayServer srv = relays.get(i);
|
||||
NBTTagCompound etr = new NBTTagCompound();
|
||||
etr.setString("addr", srv.address);
|
||||
etr.setString("comment", srv.comment);
|
||||
etr.setBoolean("primary", srv.isPrimary());
|
||||
lst.appendTag(etr);
|
||||
}
|
||||
|
||||
NBTTagCompound nbttagcompound = new NBTTagCompound();
|
||||
nbttagcompound.setTag("relays", lst);
|
||||
|
||||
ByteArrayOutputStream bao = new ByteArrayOutputStream();
|
||||
CompressedStreamTools.writeCompressed(nbttagcompound, bao);
|
||||
EagRuntime.setStorage("r", bao.toByteArray());
|
||||
} catch (Exception exception) {
|
||||
logger.error("Couldn\'t save relay list!");
|
||||
logger.error(exception);
|
||||
}
|
||||
}
|
||||
|
||||
private void sort() {
|
||||
if(relays.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
int j = -1;
|
||||
for(int i = 0, l = relays.size(); i < l; ++i) {
|
||||
if(relays.get(i).isPrimary()) {
|
||||
if(j == -1) {
|
||||
j = i;
|
||||
}else {
|
||||
relays.get(i).setPrimary(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(j == -1) {
|
||||
boolean found = false;
|
||||
for(int i = 0, l = relays.size(); i < l; ++i) {
|
||||
RelayServer srv = relays.get(i);
|
||||
if(srv.getPing() > 0l) {
|
||||
found = true;
|
||||
srv.setPrimary(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
relays.get(0).setPrimary(true);
|
||||
}
|
||||
}else {
|
||||
RelayServer srv = relays.remove(j);
|
||||
relays.add(0, srv);
|
||||
}
|
||||
}
|
||||
|
||||
public void ping() {
|
||||
lastPingThrough = System.currentTimeMillis();
|
||||
for(int i = 0, l = relays.size(); i < l; ++i) {
|
||||
relays.get(i).ping();
|
||||
}
|
||||
}
|
||||
|
||||
public void update() {
|
||||
for(int i = 0, l = relays.size(); i < l; ++i) {
|
||||
relays.get(i).update();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
for(int i = 0, l = relays.size(); i < l; ++i) {
|
||||
relays.get(i).close();
|
||||
}
|
||||
}
|
||||
|
||||
public int count() {
|
||||
return relays.size();
|
||||
}
|
||||
|
||||
public RelayServer get(int idx) {
|
||||
return relays.get(idx);
|
||||
}
|
||||
|
||||
public void add(String addr, String comment, boolean primary) {
|
||||
lastPingThrough = 0l;
|
||||
int i = relays.size();
|
||||
relays.add(new RelayServer(addr, comment, false));
|
||||
if(primary) {
|
||||
setPrimary0(i);
|
||||
}
|
||||
save();
|
||||
}
|
||||
|
||||
public void addNew(String addr, String comment, boolean primary) {
|
||||
lastPingThrough = 0l;
|
||||
int i = relays.size();
|
||||
int j = primary || i == 0 ? 0 : 1;
|
||||
RelayServer newServer = new RelayServer(addr, comment, false);
|
||||
relays.add(j, newServer);
|
||||
newServer.ping();
|
||||
if(primary) {
|
||||
setPrimary0(j);
|
||||
}
|
||||
save();
|
||||
}
|
||||
|
||||
public void setPrimary(int idx) {
|
||||
setPrimary0(idx);
|
||||
save();
|
||||
}
|
||||
|
||||
private void setPrimary0(int idx) {
|
||||
if(idx >= 0 && idx < relays.size()) {
|
||||
for(int i = 0, l = relays.size(); i < l; ++i) {
|
||||
RelayServer srv = relays.get(i);
|
||||
if(srv.isPrimary()) {
|
||||
srv.setPrimary(false);
|
||||
}
|
||||
}
|
||||
RelayServer pr = relays.remove(idx);
|
||||
pr.setPrimary(true);
|
||||
relays.add(0, pr);
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(int idx) {
|
||||
RelayServer srv = relays.remove(idx);
|
||||
srv.close();
|
||||
sort();
|
||||
save();
|
||||
}
|
||||
|
||||
public RelayServer getPrimary() {
|
||||
if(!relays.isEmpty()) {
|
||||
for(int i = 0, l = relays.size(); i < l; ++i) {
|
||||
RelayServer srv = relays.get(i);
|
||||
if(srv.isPrimary()) {
|
||||
return srv;
|
||||
}
|
||||
}
|
||||
sort();
|
||||
save();
|
||||
return getPrimary();
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public RelayServerSocket connectHandshake(RelayServer relay, int type, String code) {
|
||||
RelayServerSocket sock = relay.openSocket();
|
||||
while(!sock.isClosed()) {
|
||||
if(sock.isOpen()) {
|
||||
sock.writePacket(new IPacket00Handshake(type, preferredRelayVersion, code));
|
||||
while(!sock.isClosed()) {
|
||||
IPacket pkt = sock.nextPacket();
|
||||
if(pkt != null) {
|
||||
if(pkt instanceof IPacket00Handshake) {
|
||||
return sock;
|
||||
}else if(pkt instanceof IPacketFFErrorCode) {
|
||||
IPacketFFErrorCode ipkt = (IPacketFFErrorCode) pkt;
|
||||
logger.error("Relay [{}] failed: {}({}): {}", relay.address, IPacketFFErrorCode.code2string(ipkt.code), ipkt.code, ipkt.desc);
|
||||
Throwable t;
|
||||
while((t = sock.getException()) != null) {
|
||||
logger.error(t);
|
||||
}
|
||||
sock.close();
|
||||
return null;
|
||||
}else {
|
||||
logger.error("Relay [{}] unexpected packet: {}", relay.address, pkt.getClass().getSimpleName());
|
||||
sock.close();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
EagUtils.sleep(20l);
|
||||
}
|
||||
}
|
||||
EagUtils.sleep(20l);
|
||||
}
|
||||
logger.error("Relay [{}] connection failed!", relay.address);
|
||||
Throwable t;
|
||||
while((t = sock.getException()) != null) {
|
||||
logger.error(t);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private final List<RelayServer> brokenServers = new LinkedList();
|
||||
|
||||
public RelayServerSocket getWorkingRelay(Consumer<String> progressCallback, int type, String code) {
|
||||
brokenServers.clear();
|
||||
if(!relays.isEmpty()) {
|
||||
long millis = System.currentTimeMillis();
|
||||
if(millis - lastPingThrough < 10000l) {
|
||||
RelayServer relay = getPrimary();
|
||||
if(relay.getPing() > 0l && relay.getPingCompatible().isCompatible()) {
|
||||
progressCallback.accept(relay.address);
|
||||
RelayServerSocket sock = connectHandshake(relay, type, code);
|
||||
if(sock != null) {
|
||||
if(!sock.isFailed()) {
|
||||
return sock;
|
||||
}
|
||||
}else {
|
||||
brokenServers.add(relay);
|
||||
}
|
||||
}
|
||||
for(int i = 0, l = relays.size(); i < l; ++i) {
|
||||
RelayServer relayEtr = relays.get(i);
|
||||
if(relayEtr != relay) {
|
||||
if(relayEtr.getPing() > 0l && relayEtr.getPingCompatible().isCompatible()) {
|
||||
progressCallback.accept(relayEtr.address);
|
||||
RelayServerSocket sock = connectHandshake(relayEtr, type, code);
|
||||
if(sock != null) {
|
||||
if(!sock.isFailed()) {
|
||||
return sock;
|
||||
}
|
||||
}else {
|
||||
brokenServers.add(relayEtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return getWorkingCodeRelayActive(progressCallback, type, code);
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private RelayServerSocket getWorkingCodeRelayActive(Consumer<String> progressCallback, int type, String code) {
|
||||
if(!relays.isEmpty()) {
|
||||
for(int i = 0, l = relays.size(); i < l; ++i) {
|
||||
RelayServer srv = relays.get(i);
|
||||
if(!brokenServers.contains(srv)) {
|
||||
progressCallback.accept(srv.address);
|
||||
RelayServerSocket sock = connectHandshake(srv, type, code);
|
||||
if(sock != null) {
|
||||
if(!sock.isFailed()) {
|
||||
return sock;
|
||||
}
|
||||
}else {
|
||||
brokenServers.add(srv);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void loadDefaults() {
|
||||
int setPrimary = relays.size();
|
||||
eee: for(RelayEntry etr : EagRuntime.getConfiguration().getRelays()) {
|
||||
for(RelayServer exEtr : relays) {
|
||||
if(exEtr.address.equalsIgnoreCase(etr.address)) {
|
||||
continue eee;
|
||||
}
|
||||
}
|
||||
relays.add(new RelayServer(etr));
|
||||
}
|
||||
setPrimary(setPrimary);
|
||||
}
|
||||
|
||||
public String makeNewRelayName() {
|
||||
String str = "Relay Server #" + (relays.size() + 1);
|
||||
for(int i = relays.size() + 2, l = relays.size() + 50; i < l; ++i) {
|
||||
if(str.equalsIgnoreCase("Relay Server #" + i)) {
|
||||
str = "Relay Server #" + (i + 1);
|
||||
}
|
||||
}
|
||||
eee: while(true) {
|
||||
for(int i = 0, l = relays.size(); i < l; ++i) {
|
||||
if(str.equalsIgnoreCase(relays.get(i).comment)) {
|
||||
str = str + "_";
|
||||
continue eee;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public RelayServer getByURI(String uri) {
|
||||
Iterator<RelayServer> itr = relays.iterator();
|
||||
while(itr.hasNext()) {
|
||||
RelayServer rl = itr.next();
|
||||
if(rl.address.equals(uri)) {
|
||||
return rl;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public interface RelayQuery {
|
||||
|
||||
enum RateLimit {
|
||||
NONE, FAILED, BLOCKED, FAILED_POSSIBLY_LOCKED, LOCKED, NOW_LOCKED
|
||||
}
|
||||
|
||||
enum VersionMismatch {
|
||||
COMPATIBLE, CLIENT_OUTDATED, RELAY_OUTDATED, UNKNOWN;
|
||||
public boolean isCompatible() {
|
||||
return this == COMPATIBLE;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isQueryOpen();
|
||||
boolean isQueryFailed();
|
||||
RateLimit isQueryRateLimit();
|
||||
void close();
|
||||
|
||||
int getVersion();
|
||||
String getComment();
|
||||
String getBrand();
|
||||
long getPing();
|
||||
|
||||
VersionMismatch getCompatible();
|
||||
|
||||
}
|
@ -0,0 +1,144 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagUtils;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayQuery.VersionMismatch;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class RelayServer {
|
||||
|
||||
public final String address;
|
||||
public final String comment;
|
||||
private boolean primary;
|
||||
|
||||
private RelayQuery query = null;
|
||||
private int queriedVersion = -1;
|
||||
private String queriedComment;
|
||||
private String queriedVendor;
|
||||
private VersionMismatch queriedCompatible;
|
||||
private long ping = 0l;
|
||||
private long workingPing = 0l;
|
||||
public long lastPing = 0l;
|
||||
|
||||
public RelayServer(String address, String comment, boolean primary) {
|
||||
this.address = address;
|
||||
this.comment = comment;
|
||||
this.primary = primary;
|
||||
}
|
||||
|
||||
public RelayServer(RelayEntry etr) {
|
||||
this(etr.address, etr.comment, etr.primary);
|
||||
}
|
||||
|
||||
public boolean isPrimary() {
|
||||
return primary;
|
||||
}
|
||||
|
||||
public void setPrimary(boolean primaryee) {
|
||||
primary = primaryee;
|
||||
}
|
||||
|
||||
public long getPing() {
|
||||
return ping;
|
||||
}
|
||||
|
||||
public long getWorkingPing() {
|
||||
return workingPing;
|
||||
}
|
||||
|
||||
public int getPingVersion() {
|
||||
return queriedVersion;
|
||||
}
|
||||
|
||||
public String getPingComment() {
|
||||
return queriedComment == null ? "" : queriedComment;
|
||||
}
|
||||
|
||||
public String getPingVendor() {
|
||||
return queriedVendor == null ? "" : queriedVendor;
|
||||
}
|
||||
|
||||
public VersionMismatch getPingCompatible() {
|
||||
return queriedCompatible;
|
||||
}
|
||||
|
||||
public void pingBlocking() {
|
||||
ping();
|
||||
while(getPing() < 0l) {
|
||||
EagUtils.sleep(250l);
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
public void ping() {
|
||||
if(PlatformWebRTC.supported()) {
|
||||
close();
|
||||
query = PlatformWebRTC.openRelayQuery(address);
|
||||
queriedVersion = -1;
|
||||
queriedComment = null;
|
||||
queriedVendor = null;
|
||||
queriedCompatible = VersionMismatch.UNKNOWN;
|
||||
ping = -1l;
|
||||
}else {
|
||||
query = null;
|
||||
queriedVersion = 1;
|
||||
queriedComment = "LAN NOT SUPPORTED";
|
||||
queriedVendor = "NULL";
|
||||
queriedCompatible = VersionMismatch.CLIENT_OUTDATED;
|
||||
ping = -1l;
|
||||
}
|
||||
}
|
||||
|
||||
public void update() {
|
||||
if(query != null && !query.isQueryOpen()) {
|
||||
if(query.isQueryFailed()) {
|
||||
queriedVersion = -1;
|
||||
queriedComment = null;
|
||||
queriedVendor = null;
|
||||
queriedCompatible = VersionMismatch.UNKNOWN;
|
||||
ping = 0l;
|
||||
}else {
|
||||
queriedVersion = query.getVersion();
|
||||
queriedComment = query.getComment();
|
||||
queriedVendor = query.getBrand();
|
||||
ping = query.getPing();
|
||||
queriedCompatible = query.getCompatible();
|
||||
workingPing = ping;
|
||||
}
|
||||
lastPing = System.currentTimeMillis();
|
||||
query = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
if(query != null && query.isQueryOpen()) {
|
||||
query.close();
|
||||
query = null;
|
||||
queriedVersion = -1;
|
||||
queriedComment = null;
|
||||
queriedVendor = null;
|
||||
queriedCompatible = VersionMismatch.UNKNOWN;
|
||||
ping = 0l;
|
||||
}
|
||||
}
|
||||
|
||||
public RelayServerSocket openSocket() {
|
||||
return PlatformWebRTC.openRelayConnection(address, Minecraft.getMinecraft().gameSettings.relayTimeout * 1000);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.pkt.IPacket;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public interface RelayServerSocket {
|
||||
|
||||
boolean isOpen();
|
||||
boolean isClosed();
|
||||
void close();
|
||||
|
||||
boolean isFailed();
|
||||
Throwable getException();
|
||||
|
||||
void writePacket(IPacket pkt);
|
||||
|
||||
IPacket readPacket();
|
||||
IPacket nextPacket();
|
||||
|
||||
RelayQuery.RateLimit getRatelimitHistory();
|
||||
|
||||
String getURI();
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayQuery.VersionMismatch;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.relay.pkt.IPacket07LocalWorlds;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public interface RelayWorldsQuery {
|
||||
|
||||
boolean isQueryOpen();
|
||||
boolean isQueryFailed();
|
||||
RelayQuery.RateLimit isQueryRateLimit();
|
||||
void close();
|
||||
|
||||
List<IPacket07LocalWorlds.LocalWorld> getWorlds();
|
||||
|
||||
VersionMismatch getCompatible();
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class ICEServerSet {
|
||||
|
||||
public static enum RelayType {
|
||||
STUN, TURN;
|
||||
}
|
||||
|
||||
public static class RelayServer {
|
||||
|
||||
public final RelayType type;
|
||||
public final String address;
|
||||
public final String username;
|
||||
public final String password;
|
||||
|
||||
protected RelayServer(RelayType type, String address, String username, String password) {
|
||||
this.type = type;
|
||||
this.address = address;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
protected RelayServer(RelayType type, String address) {
|
||||
this.type = type;
|
||||
this.address = address;
|
||||
this.username = null;
|
||||
this.password = null;
|
||||
}
|
||||
|
||||
public String getICEString() {
|
||||
if(username == null) {
|
||||
return address;
|
||||
}else {
|
||||
return address + ";" + username + ";" + password;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,165 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPacket {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger("RelayPacket");
|
||||
|
||||
private static final Map<Integer,Class<? extends IPacket>> definedPacketClasses = new HashMap();
|
||||
private static final Map<Class<? extends IPacket>,Integer> definedPacketIds = new HashMap();
|
||||
|
||||
private static void register(int id, Class<? extends IPacket> clazz) {
|
||||
definedPacketClasses.put(id, clazz);
|
||||
definedPacketIds.put(clazz, id);
|
||||
}
|
||||
|
||||
static {
|
||||
register(0x00, IPacket00Handshake.class);
|
||||
register(0x01, IPacket01ICEServers.class);
|
||||
register(0x02, IPacket02NewClient.class);
|
||||
register(0x03, IPacket03ICECandidate.class);
|
||||
register(0x04, IPacket04Description.class);
|
||||
register(0x05, IPacket05ClientSuccess.class);
|
||||
register(0x06, IPacket06ClientFailure.class);
|
||||
register(0x07, IPacket07LocalWorlds.class);
|
||||
register(0x69, IPacket69Pong.class);
|
||||
register(0x70, IPacket70SpecialUpdate.class);
|
||||
register(0xFE, IPacketFEDisconnectClient.class);
|
||||
register(0xFF, IPacketFFErrorCode.class);
|
||||
}
|
||||
|
||||
public static IPacket readPacket(DataInputStream input) throws IOException {
|
||||
int i = input.read();
|
||||
try {
|
||||
Class<? extends IPacket> clazz = definedPacketClasses.get(i);
|
||||
if(clazz == null) {
|
||||
throw new IOException("Unknown packet type: " + i);
|
||||
}
|
||||
IPacket pkt = clazz.newInstance();
|
||||
pkt.read(input);
|
||||
return pkt;
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
throw new IOException("Unknown packet type: " + i);
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] writePacket(IPacket packet) throws IOException {
|
||||
Integer i = definedPacketIds.get(packet.getClass());
|
||||
if(i != null) {
|
||||
int len = packet.packetLength();
|
||||
ByteArrayOutputStream bao = len == -1 ? new ByteArrayOutputStream() :
|
||||
new ByteArrayOutputStream(len + 1);
|
||||
bao.write(i);
|
||||
packet.write(new DataOutputStream(bao));
|
||||
byte[] ret = bao.toByteArray();
|
||||
if(len != -1 && ret.length != len + 1) {
|
||||
logger.error("writePacket buffer for packet {} {} by {} bytes", packet.getClass().getSimpleName(),
|
||||
(len + 1 < ret.length ? "overflowed" : "underflowed"),
|
||||
(len + 1 < ret.length ? ret.length - len - 1 : len + 1 - ret.length));
|
||||
}
|
||||
return ret;
|
||||
}else {
|
||||
throw new IOException("Unknown packet type: " + packet.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
public void read(DataInputStream input) throws IOException {
|
||||
}
|
||||
|
||||
public void write(DataOutputStream output) throws IOException {
|
||||
}
|
||||
|
||||
public int packetLength() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static String readASCII(InputStream is, int len) throws IOException {
|
||||
char[] ret = new char[len];
|
||||
for(int i = 0; i < len; ++i) {
|
||||
int j = is.read();
|
||||
if(j < 0) {
|
||||
return null;
|
||||
}
|
||||
ret[i] = (char)j;
|
||||
}
|
||||
return new String(ret);
|
||||
}
|
||||
|
||||
public static void writeASCII(OutputStream is, String txt) throws IOException {
|
||||
for(int i = 0, l = txt.length(); i < l; ++i) {
|
||||
is.write((int)txt.charAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
public static String readASCII8(InputStream is) throws IOException {
|
||||
int i = is.read();
|
||||
if(i < 0) {
|
||||
return null;
|
||||
}else {
|
||||
return readASCII(is, i);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeASCII8(OutputStream is, String txt) throws IOException {
|
||||
if(txt == null) {
|
||||
is.write(0);
|
||||
}else {
|
||||
int l = txt.length();
|
||||
is.write(l);
|
||||
for(int i = 0; i < l; ++i) {
|
||||
is.write((int)txt.charAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String readASCII16(InputStream is) throws IOException {
|
||||
int hi = is.read();
|
||||
int lo = is.read();
|
||||
if(hi < 0 || lo < 0) {
|
||||
return null;
|
||||
}else {
|
||||
return readASCII(is, (hi << 8) | lo);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeASCII16(OutputStream is, String txt) throws IOException {
|
||||
if(txt == null) {
|
||||
is.write(0);
|
||||
is.write(0);
|
||||
}else {
|
||||
int l = txt.length();
|
||||
is.write((l >> 8) & 0xFF);
|
||||
is.write(l & 0xFF);
|
||||
for(int i = 0; i < l; ++i) {
|
||||
is.write((int)txt.charAt(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPacket00Handshake extends IPacket {
|
||||
|
||||
public int connectionType = 0;
|
||||
public int connectionVersion = 1;
|
||||
public String connectionCode = null;
|
||||
|
||||
public IPacket00Handshake() {
|
||||
}
|
||||
|
||||
public IPacket00Handshake(int connectionType, int connectionVersion,
|
||||
String connectionCode) {
|
||||
this.connectionType = connectionType;
|
||||
this.connectionVersion = connectionVersion;
|
||||
this.connectionCode = connectionCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInputStream input) throws IOException {
|
||||
connectionType = input.read();
|
||||
connectionVersion = input.read();
|
||||
connectionCode = IPacket.readASCII8(input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutputStream output) throws IOException {
|
||||
output.write(connectionType);
|
||||
output.write(connectionVersion);
|
||||
IPacket.writeASCII8(output, connectionCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int packetLength() {
|
||||
return 1 + 1 + (connectionCode != null ? 1 + connectionCode.length() : 0);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPacket01ICEServers extends IPacket {
|
||||
|
||||
public final Collection<ICEServerSet.RelayServer> servers;
|
||||
|
||||
public IPacket01ICEServers() {
|
||||
servers = new ArrayList();
|
||||
}
|
||||
|
||||
public void read(DataInputStream input) throws IOException {
|
||||
servers.clear();
|
||||
int l = input.readUnsignedShort();
|
||||
for(int i = 0; i < l; ++i) {
|
||||
char type = (char)input.read();
|
||||
ICEServerSet.RelayType typeEnum;
|
||||
if(type == 'S') {
|
||||
typeEnum = ICEServerSet.RelayType.STUN;
|
||||
}else if(type == 'T') {
|
||||
typeEnum = ICEServerSet.RelayType.TURN;
|
||||
}else {
|
||||
throw new IOException("Unknown/Unsupported Relay Type: '" + type + "'");
|
||||
}
|
||||
servers.add(new ICEServerSet.RelayServer(
|
||||
typeEnum,
|
||||
readASCII16(input),
|
||||
readASCII8(input),
|
||||
readASCII8(input)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPacket02NewClient extends IPacket {
|
||||
|
||||
public String clientId;
|
||||
|
||||
public IPacket02NewClient(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public IPacket02NewClient() {
|
||||
}
|
||||
|
||||
public void read(DataInputStream input) throws IOException {
|
||||
clientId = readASCII8(input);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPacket03ICECandidate extends IPacket {
|
||||
|
||||
public String peerId;
|
||||
public String candidate;
|
||||
|
||||
public IPacket03ICECandidate(String peerId, String desc) {
|
||||
this.peerId = peerId;
|
||||
this.candidate = desc;
|
||||
}
|
||||
|
||||
public IPacket03ICECandidate() {
|
||||
}
|
||||
|
||||
public void read(DataInputStream input) throws IOException {
|
||||
peerId = readASCII8(input);
|
||||
candidate = readASCII16(input);
|
||||
}
|
||||
|
||||
public void write(DataOutputStream output) throws IOException {
|
||||
writeASCII8(output, peerId);
|
||||
writeASCII16(output, candidate);
|
||||
}
|
||||
|
||||
public int packetLength() {
|
||||
return 1 + peerId.length() + 2 + candidate.length();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPacket04Description extends IPacket {
|
||||
|
||||
public String peerId;
|
||||
public String description;
|
||||
|
||||
public IPacket04Description(String peerId, String desc) {
|
||||
this.peerId = peerId;
|
||||
this.description = desc;
|
||||
}
|
||||
|
||||
public IPacket04Description() {
|
||||
}
|
||||
|
||||
public void read(DataInputStream input) throws IOException {
|
||||
peerId = readASCII8(input);
|
||||
description = readASCII16(input);
|
||||
}
|
||||
|
||||
public void write(DataOutputStream output) throws IOException {
|
||||
writeASCII8(output, peerId);
|
||||
writeASCII16(output, description);
|
||||
}
|
||||
|
||||
public int packetLength() {
|
||||
return 1 + peerId.length() + 2 + description.length();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPacket05ClientSuccess extends IPacket {
|
||||
|
||||
public String clientId;
|
||||
|
||||
public IPacket05ClientSuccess() {
|
||||
}
|
||||
|
||||
public IPacket05ClientSuccess(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public void read(DataInputStream input) throws IOException {
|
||||
clientId = readASCII8(input);
|
||||
}
|
||||
|
||||
public void write(DataOutputStream output) throws IOException {
|
||||
writeASCII8(output, clientId);
|
||||
}
|
||||
|
||||
public int packetLength() {
|
||||
return 1 + clientId.length();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPacket06ClientFailure extends IPacket {
|
||||
|
||||
public String clientId;
|
||||
|
||||
public IPacket06ClientFailure() {
|
||||
}
|
||||
|
||||
public IPacket06ClientFailure(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public void read(DataInputStream input) throws IOException {
|
||||
clientId = readASCII8(input);
|
||||
}
|
||||
|
||||
public void write(DataOutputStream output) throws IOException {
|
||||
writeASCII8(output, clientId);
|
||||
}
|
||||
|
||||
public int packetLength() {
|
||||
return 1 + clientId.length();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPacket07LocalWorlds extends IPacket {
|
||||
|
||||
public static class LocalWorld {
|
||||
|
||||
public final String worldName;
|
||||
public final String worldCode;
|
||||
|
||||
public LocalWorld(String worldName, String worldCode) {
|
||||
this.worldName = worldName;
|
||||
this.worldCode = worldCode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final List<LocalWorld> worldsList;
|
||||
|
||||
public IPacket07LocalWorlds() {
|
||||
this.worldsList = new ArrayList();
|
||||
}
|
||||
|
||||
public void read(DataInputStream input) throws IOException {
|
||||
int l = input.read();
|
||||
for(int i = 0; i < l; ++i) {
|
||||
worldsList.add(new LocalWorld(readASCII8(input), readASCII8(input)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPacket69Pong extends IPacket {
|
||||
|
||||
public int protcolVersion;
|
||||
public String comment;
|
||||
public String brand;
|
||||
|
||||
public IPacket69Pong(int protcolVersion, String comment, String brand) {
|
||||
if(comment.length() > 255) {
|
||||
comment = comment.substring(0, 256);
|
||||
}
|
||||
this.protcolVersion = protcolVersion;
|
||||
this.comment = comment;
|
||||
this.brand = brand;
|
||||
}
|
||||
|
||||
public IPacket69Pong() {
|
||||
}
|
||||
|
||||
public void read(DataInputStream output) throws IOException {
|
||||
protcolVersion = output.read();
|
||||
comment = readASCII8(output);
|
||||
brand = readASCII8(output);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPacket70SpecialUpdate extends IPacket {
|
||||
|
||||
public static final int OPERATION_UPDATE_CERTIFICATE = 0x69;
|
||||
|
||||
public int operation;
|
||||
public byte[] updatePacket;
|
||||
|
||||
public IPacket70SpecialUpdate() {
|
||||
}
|
||||
|
||||
public IPacket70SpecialUpdate(int operation, byte[] updatePacket) {
|
||||
this.operation = operation;
|
||||
this.updatePacket = updatePacket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInputStream input) throws IOException {
|
||||
operation = input.read();
|
||||
updatePacket = new byte[input.readUnsignedShort()];
|
||||
input.read(updatePacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutputStream output) throws IOException {
|
||||
output.write(operation);
|
||||
output.writeShort(updatePacket.length);
|
||||
output.write(updatePacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int packetLength() {
|
||||
return 3 + updatePacket.length;
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPacketFEDisconnectClient extends IPacket {
|
||||
|
||||
public static final int TYPE_FINISHED_SUCCESS = 0x00;
|
||||
public static final int TYPE_FINISHED_FAILED = 0x01;
|
||||
public static final int TYPE_TIMEOUT = 0x02;
|
||||
public static final int TYPE_INVALID_OPERATION = 0x03;
|
||||
public static final int TYPE_INTERNAL_ERROR = 0x04;
|
||||
public static final int TYPE_SERVER_DISCONNECT = 0x05;
|
||||
public static final int TYPE_UNKNOWN = 0xFF;
|
||||
|
||||
public String clientId;
|
||||
public int code;
|
||||
public String reason;
|
||||
|
||||
public IPacketFEDisconnectClient() {
|
||||
}
|
||||
|
||||
public IPacketFEDisconnectClient(String clientId, int code, String reason) {
|
||||
this.clientId = clientId;
|
||||
this.code = code;
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public void read(DataInputStream input) throws IOException {
|
||||
clientId = readASCII8(input);
|
||||
code = input.read();
|
||||
reason = readASCII16(input);
|
||||
}
|
||||
|
||||
public void write(DataOutputStream output) throws IOException {
|
||||
writeASCII8(output, clientId);
|
||||
output.write(code);
|
||||
writeASCII16(output, reason);
|
||||
}
|
||||
|
||||
public int packetLength() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static final ByteBuffer ratelimitPacketTooMany = ByteBuffer.wrap(new byte[] { (byte)0xFC, (byte)0x00 });
|
||||
public static final ByteBuffer ratelimitPacketBlock = ByteBuffer.wrap(new byte[] { (byte)0xFC, (byte)0x01 });
|
||||
public static final ByteBuffer ratelimitPacketBlockLock = ByteBuffer.wrap(new byte[] { (byte)0xFC, (byte)0x02 });
|
||||
public static final ByteBuffer ratelimitPacketLocked = ByteBuffer.wrap(new byte[] { (byte)0xFC, (byte)0x03 });
|
||||
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.relay.pkt;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IPacketFFErrorCode extends IPacket {
|
||||
|
||||
public static final int TYPE_INTERNAL_ERROR = 0x00;
|
||||
public static final int TYPE_PROTOCOL_VERSION = 0x01;
|
||||
public static final int TYPE_INVALID_PACKET = 0x02;
|
||||
public static final int TYPE_ILLEGAL_OPERATION = 0x03;
|
||||
public static final int TYPE_CODE_LENGTH = 0x04;
|
||||
public static final int TYPE_INCORRECT_CODE = 0x05;
|
||||
public static final int TYPE_SERVER_DISCONNECTED = 0x06;
|
||||
public static final int TYPE_UNKNOWN_CLIENT = 0x07;
|
||||
|
||||
public static final String[] packetTypes = new String[0x08];
|
||||
|
||||
static {
|
||||
packetTypes[TYPE_INTERNAL_ERROR] = "TYPE_INTERNAL_ERROR";
|
||||
packetTypes[TYPE_PROTOCOL_VERSION] = "TYPE_PROTOCOL_VERSION";
|
||||
packetTypes[TYPE_INVALID_PACKET] = "TYPE_INVALID_PACKET";
|
||||
packetTypes[TYPE_ILLEGAL_OPERATION] = "TYPE_ILLEGAL_OPERATION";
|
||||
packetTypes[TYPE_CODE_LENGTH] = "TYPE_CODE_LENGTH";
|
||||
packetTypes[TYPE_INCORRECT_CODE] = "TYPE_INCORRECT_CODE";
|
||||
packetTypes[TYPE_SERVER_DISCONNECTED] = "TYPE_SERVER_DISCONNECTED";
|
||||
packetTypes[TYPE_UNKNOWN_CLIENT] = "TYPE_UNKNOWN_CLIENT";
|
||||
}
|
||||
|
||||
public static String code2string(int i) {
|
||||
if(i >= 0 || i < packetTypes.length) {
|
||||
return packetTypes[i];
|
||||
}else {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
public int code;
|
||||
public String desc;
|
||||
|
||||
public IPacketFFErrorCode() {
|
||||
}
|
||||
|
||||
public IPacketFFErrorCode(int code, String desc) {
|
||||
this.code = code;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInputStream input) throws IOException {
|
||||
code = input.read();
|
||||
desc = readASCII16(input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutputStream input) throws IOException {
|
||||
input.write(code);
|
||||
writeASCII16(input, desc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int packetLength() {
|
||||
return 1 + 2 + desc.length();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.server;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.command.CommandBase;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.command.CommandException;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.command.ICommandSender;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.util.ChatComponentTranslation;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class ClientCommandDummy extends CommandBase {
|
||||
|
||||
private final String commandName;
|
||||
private final int permissionLevel;
|
||||
private final String commandUsage;
|
||||
|
||||
public ClientCommandDummy(String commandName, int permissionLevel, String commandUsage) {
|
||||
this.commandName = commandName;
|
||||
this.permissionLevel = permissionLevel;
|
||||
this.commandUsage = commandUsage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return commandName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRequiredPermissionLevel() {
|
||||
return permissionLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCommandUsage(ICommandSender var1) {
|
||||
return commandUsage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processCommand(ICommandSender var1, String[] var2) throws CommandException {
|
||||
var1.addChatMessage(new ChatComponentTranslation("command.clientStub"));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.server;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.HString;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.block.Block;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.block.state.IBlockState;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.util.BlockPos;
|
||||
import net.minecraft.crash.CrashReportCategory;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class CrashReportHelper {
|
||||
|
||||
public static void addIntegratedServerBlockInfo(CrashReportCategory category, final BlockPos pos, final Block blockIn,
|
||||
final int blockData) {
|
||||
final int i = Block.getIdFromBlock(blockIn);
|
||||
category.addCrashSectionCallable("Block type", new Callable<String>() {
|
||||
public String call() throws Exception {
|
||||
try {
|
||||
return HString.format("ID #%d (%s // %s)", new Object[] { Integer.valueOf(i),
|
||||
blockIn.getUnlocalizedName(), blockIn.getClass().getName() });
|
||||
} catch (Throwable var2) {
|
||||
return "ID #" + i;
|
||||
}
|
||||
}
|
||||
});
|
||||
category.addCrashSectionCallable("Block data value", new Callable<String>() {
|
||||
public String call() throws Exception {
|
||||
if (blockData < 0) {
|
||||
return "Unknown? (Got " + blockData + ")";
|
||||
} else {
|
||||
String s = HString.format("%4s", new Object[] { Integer.toBinaryString(blockData) }).replace(" ",
|
||||
"0");
|
||||
return HString.format("%1$d / 0x%1$X / 0b%2$s", new Object[] { Integer.valueOf(blockData), s });
|
||||
}
|
||||
}
|
||||
});
|
||||
category.addCrashSectionCallable("Block location", new Callable<String>() {
|
||||
public String call() throws Exception {
|
||||
return CrashReportCategory.getCoordinateInfo(new net.minecraft.util.BlockPos(pos.getX(), pos.getY(), pos.getZ()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void addIntegratedServerBlockInfo(CrashReportCategory category, final BlockPos pos, final IBlockState state) {
|
||||
category.addCrashSectionCallable("Block", new Callable<String>() {
|
||||
public String call() throws Exception {
|
||||
return state.toString();
|
||||
}
|
||||
});
|
||||
category.addCrashSectionCallable("Block location", new Callable<String>() {
|
||||
public String call() throws Exception {
|
||||
return CrashReportCategory.getCoordinateInfo(new net.minecraft.util.BlockPos(pos.getX(), pos.getY(), pos.getZ()));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFile2;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.ChunkCoordIntPair;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.MinecraftException;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.World;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.chunk.Chunk;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.chunk.storage.AnvilChunkLoader;
|
||||
import net.minecraft.nbt.CompressedStreamTools;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class EaglerChunkLoader extends AnvilChunkLoader {
|
||||
|
||||
private static final String hex = "0123456789ABCDEF";
|
||||
private static final Logger logger = LogManager.getLogger("EaglerChunkLoader");
|
||||
|
||||
public static String getChunkPath(int x, int z) {
|
||||
int unsignedX = x + 1900000;
|
||||
int unsignedZ = z + 1900000;
|
||||
|
||||
char[] path = new char[12];
|
||||
for(int i = 5; i >= 0; --i) {
|
||||
path[i] = hex.charAt((unsignedX >> (i * 4)) & 0xF);
|
||||
path[i + 6] = hex.charAt((unsignedZ >> (i * 4)) & 0xF);
|
||||
}
|
||||
|
||||
return new String(path);
|
||||
}
|
||||
|
||||
public static ChunkCoordIntPair getChunkCoords(String filename) {
|
||||
String strX = filename.substring(0, 6);
|
||||
String strZ = filename.substring(6);
|
||||
|
||||
int retX = 0;
|
||||
int retZ = 0;
|
||||
|
||||
for(int i = 0; i < 6; ++i) {
|
||||
retX |= hex.indexOf(strX.charAt(i)) << (i << 2);
|
||||
retZ |= hex.indexOf(strZ.charAt(i)) << (i << 2);
|
||||
}
|
||||
|
||||
return new ChunkCoordIntPair(retX - 1900000, retZ - 1900000);
|
||||
}
|
||||
|
||||
public final VFile2 chunkDirectory;
|
||||
|
||||
public EaglerChunkLoader(VFile2 chunkDirectory) {
|
||||
this.chunkDirectory = chunkDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk loadChunk(World var1, int var2, int var3) throws IOException {
|
||||
VFile2 file = new VFile2(chunkDirectory, getChunkPath(var2, var3) + ".dat");
|
||||
if(!file.exists()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
NBTTagCompound nbt;
|
||||
try(InputStream is = file.getInputStream()) {
|
||||
nbt = CompressedStreamTools.readCompressed(is);
|
||||
}
|
||||
return checkedReadChunkFromNBT(var1, var2, var3, nbt);
|
||||
}catch(Throwable t) {
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveChunk(World var1, Chunk var2) throws IOException, MinecraftException {
|
||||
NBTTagCompound chunkData = new NBTTagCompound();
|
||||
this.writeChunkToNBT(var2, var1, chunkData);
|
||||
NBTTagCompound fileData = new NBTTagCompound();
|
||||
fileData.setTag("Level", chunkData);
|
||||
VFile2 file = new VFile2(chunkDirectory, getChunkPath(var2.xPosition, var2.zPosition) + ".dat");
|
||||
try(OutputStream os = file.getOutputStream()) {
|
||||
CompressedStreamTools.writeCompressed(fileData, os);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveExtraChunkData(World var1, Chunk var2) throws IOException {
|
||||
// ?
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chunkTick() {
|
||||
// ?
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveExtraData() {
|
||||
// ?
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,499 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
import net.lax1dude.eaglercraft.v1_8.EagUtils;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.IPCPacketData;
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFile2;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.ILogRedirector;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.SingleplayerServerController;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.ipc.*;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.network.EnumConnectionState;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.server.network.NetHandlerLoginServer;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.util.ChatComponentText;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.util.ReportedException;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.util.StringTranslate;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.EnumDifficulty;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.WorldSettings;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.WorldSettings.GameType;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.WorldType;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.export.WorldConverterEPK;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.export.WorldConverterMCA;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.internal.ServerPlatformSingleplayer;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.socket.IntegratedServerPlayerNetworkManager;
|
||||
import net.minecraft.nbt.CompressedStreamTools;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class EaglerIntegratedServerWorker {
|
||||
|
||||
public static final Logger logger = LogManager.getLogger("EaglerIntegratedServer");
|
||||
|
||||
private static EaglerMinecraftServer currentProcess = null;
|
||||
private static WorldSettings newWorldSettings = null;
|
||||
|
||||
public static final EaglerSaveFormat saveFormat = new EaglerSaveFormat(EaglerSaveFormat.worldsFolder);
|
||||
|
||||
private static final Map<String, IntegratedServerPlayerNetworkManager> openChannels = new HashMap();
|
||||
|
||||
private static void processAsyncMessageQueue() {
|
||||
List<IPCPacketData> pktList = ServerPlatformSingleplayer.recieveAllPacket();
|
||||
if(pktList != null) {
|
||||
IPCPacketData packetData;
|
||||
for(int i = 0, l = pktList.size(); i < l; ++i) {
|
||||
packetData = pktList.get(i);
|
||||
if(packetData.channel.equals(SingleplayerServerController.IPC_CHANNEL)) {
|
||||
IPCPacketBase ipc;
|
||||
try {
|
||||
ipc = IPCPacketManager.IPCDeserialize(packetData.contents);
|
||||
}catch(IOException ex) {
|
||||
throw new RuntimeException("Failed to deserialize IPC packet", ex);
|
||||
}
|
||||
handleIPCPacket(ipc);
|
||||
}else {
|
||||
IntegratedServerPlayerNetworkManager netHandler = openChannels.get(packetData.channel);
|
||||
if(netHandler != null) {
|
||||
netHandler.addRecievedPacket(packetData.contents);
|
||||
}else {
|
||||
logger.error("Recieved packet on channel that does not exist: \"{}\"", packetData.channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void tick() {
|
||||
List<IntegratedServerPlayerNetworkManager> ocs = new ArrayList<>(openChannels.values());
|
||||
for(IntegratedServerPlayerNetworkManager i : ocs) {
|
||||
i.tick();
|
||||
}
|
||||
}
|
||||
|
||||
public static EaglerMinecraftServer getServer() {
|
||||
return currentProcess;
|
||||
}
|
||||
|
||||
public static boolean getChannelExists(String channel) {
|
||||
return openChannels.containsKey(channel);
|
||||
}
|
||||
|
||||
public static void closeChannel(String channel) {
|
||||
IntegratedServerPlayerNetworkManager netmanager = openChannels.remove(channel);
|
||||
if(netmanager != null) {
|
||||
netmanager.closeChannel(new ChatComponentText("End of stream"));
|
||||
sendIPCPacket(new IPCPacket0CPlayerChannel(channel, false));
|
||||
}
|
||||
}
|
||||
|
||||
private static void startPlayerConnnection(String channel) {
|
||||
if(openChannels.containsKey(channel)) {
|
||||
logger.error("Tried opening player channel that already exists: {}", channel);
|
||||
return;
|
||||
}
|
||||
if(currentProcess == null) {
|
||||
logger.error("Tried opening player channel while server is stopped: {}", channel);
|
||||
return;
|
||||
}
|
||||
IntegratedServerPlayerNetworkManager networkmanager = new IntegratedServerPlayerNetworkManager(channel);
|
||||
networkmanager.setConnectionState(EnumConnectionState.LOGIN);
|
||||
networkmanager.setNetHandler(new NetHandlerLoginServer(currentProcess, networkmanager));
|
||||
openChannels.put(channel, networkmanager);
|
||||
}
|
||||
|
||||
private static void handleIPCPacket(IPCPacketBase ipc) {
|
||||
int id = ipc.id();
|
||||
try {
|
||||
switch(id) {
|
||||
case IPCPacket00StartServer.ID: {
|
||||
IPCPacket00StartServer pkt = (IPCPacket00StartServer)ipc;
|
||||
|
||||
if(!isServerStopped()) {
|
||||
currentProcess.stopServer();
|
||||
}
|
||||
|
||||
currentProcess = new EaglerMinecraftServer(pkt.worldName, pkt.ownerName, pkt.initialViewDistance, newWorldSettings, pkt.demoMode);
|
||||
currentProcess.setBaseServerProperties(EnumDifficulty.getDifficultyEnum(pkt.initialDifficulty), newWorldSettings == null ? GameType.SURVIVAL : newWorldSettings.getGameType());
|
||||
currentProcess.startServer();
|
||||
|
||||
String[] worlds = EaglerSaveFormat.worldsList.getAllLines();
|
||||
if(worlds == null || (worlds.length == 1 && worlds[0].trim().length() <= 0)) {
|
||||
worlds = null;
|
||||
}
|
||||
if(worlds == null) {
|
||||
EaglerSaveFormat.worldsList.setAllChars(pkt.worldName);
|
||||
}else {
|
||||
boolean found = false;
|
||||
for(String s : worlds) {
|
||||
if(s.equals(pkt.worldName)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found) {
|
||||
String[] s = new String[worlds.length + 1];
|
||||
s[0] = pkt.worldName;
|
||||
System.arraycopy(worlds, 0, s, 1, worlds.length);
|
||||
EaglerSaveFormat.worldsList.setAllChars(String.join("\n", s));
|
||||
}
|
||||
}
|
||||
|
||||
sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacket00StartServer.ID));
|
||||
break;
|
||||
}
|
||||
case IPCPacket01StopServer.ID: {
|
||||
if(currentProcess != null) {
|
||||
currentProcess.stopServer();
|
||||
currentProcess = null;
|
||||
}
|
||||
sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacket01StopServer.ID));
|
||||
break;
|
||||
}
|
||||
case IPCPacket02InitWorld.ID: {
|
||||
tryStopServer();
|
||||
IPCPacket02InitWorld pkt = (IPCPacket02InitWorld)ipc;
|
||||
newWorldSettings = new WorldSettings(pkt.seed, GameType.getByID(pkt.gamemode), pkt.structures,
|
||||
pkt.hardcore, WorldType.worldTypes[pkt.worldType]);
|
||||
newWorldSettings.setWorldName(pkt.worldArgs); // "setWorldName" is actually for setting generator arguments, MCP fucked up
|
||||
if(pkt.bonusChest) {
|
||||
newWorldSettings.enableBonusChest();
|
||||
}
|
||||
if(pkt.cheats) {
|
||||
newWorldSettings.enableCommands();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCPacket03DeleteWorld.ID: {
|
||||
tryStopServer();
|
||||
IPCPacket03DeleteWorld pkt = (IPCPacket03DeleteWorld)ipc;
|
||||
if(!saveFormat.deleteWorldDirectory(pkt.worldName)) {
|
||||
sendTaskFailed();
|
||||
break;
|
||||
}
|
||||
String[] worldsTxt = EaglerSaveFormat.worldsList.getAllLines();
|
||||
if(worldsTxt != null) {
|
||||
List<String> newWorlds = new ArrayList();
|
||||
for(String str : worldsTxt) {
|
||||
if(!str.equalsIgnoreCase(pkt.worldName)) {
|
||||
newWorlds.add(str);
|
||||
}
|
||||
}
|
||||
EaglerSaveFormat.worldsList.setAllChars(String.join("\n", newWorlds));
|
||||
}
|
||||
sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacket03DeleteWorld.ID));
|
||||
break;
|
||||
}
|
||||
case IPCPacket05RequestData.ID: {
|
||||
tryStopServer();
|
||||
IPCPacket05RequestData pkt = (IPCPacket05RequestData)ipc;
|
||||
if(pkt.request == IPCPacket05RequestData.REQUEST_LEVEL_EAG) {
|
||||
sendIPCPacket(new IPCPacket09RequestResponse(WorldConverterEPK.exportWorld(pkt.worldName)));
|
||||
}else if(pkt.request == IPCPacket05RequestData.REQUEST_LEVEL_MCA) {
|
||||
sendIPCPacket(new IPCPacket09RequestResponse(WorldConverterMCA.exportWorld(pkt.worldName)));
|
||||
}else {
|
||||
logger.error("Unknown IPCPacket05RequestData type {}", ((int)pkt.request & 0xFF));
|
||||
sendTaskFailed();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCPacket06RenameWorldNBT.ID: {
|
||||
tryStopServer();
|
||||
IPCPacket06RenameWorldNBT pkt = (IPCPacket06RenameWorldNBT)ipc;
|
||||
boolean b = false;
|
||||
if(pkt.duplicate) {
|
||||
b = saveFormat.duplicateWorld(pkt.worldName, pkt.displayName);
|
||||
}else {
|
||||
b = saveFormat.renameWorld(pkt.worldName, pkt.displayName);
|
||||
}
|
||||
if(!b) {
|
||||
sendTaskFailed();
|
||||
break;
|
||||
}
|
||||
sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacket06RenameWorldNBT.ID));
|
||||
break;
|
||||
}
|
||||
case IPCPacket07ImportWorld.ID: {
|
||||
tryStopServer();
|
||||
IPCPacket07ImportWorld pkt = (IPCPacket07ImportWorld)ipc;
|
||||
try {
|
||||
if(pkt.worldFormat == IPCPacket07ImportWorld.WORLD_FORMAT_EAG) {
|
||||
WorldConverterEPK.importWorld(pkt.worldData, pkt.worldName);
|
||||
}else if(pkt.worldFormat == IPCPacket07ImportWorld.WORLD_FORMAT_MCA) {
|
||||
WorldConverterMCA.importWorld(pkt.worldData, pkt.worldName, pkt.gameRules);
|
||||
}else {
|
||||
throw new IOException("Client requested an unsupported export format!");
|
||||
}
|
||||
sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacket07ImportWorld.ID));
|
||||
}catch(IOException ex) {
|
||||
sendIPCPacket(new IPCPacket15Crashed("COULD NOT IMPORT WORLD \"" + pkt.worldName + "\"!!!\n\n" + EagRuntime.getStackTrace(ex) + "\n\nFile is probably corrupt, try a different world"));
|
||||
sendTaskFailed();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCPacket0ASetWorldDifficulty.ID: {
|
||||
IPCPacket0ASetWorldDifficulty pkt = (IPCPacket0ASetWorldDifficulty)ipc;
|
||||
if(!isServerStopped()) {
|
||||
currentProcess.setDifficultyForAllWorlds(EnumDifficulty.getDifficultyEnum(pkt.difficulty));
|
||||
}else {
|
||||
logger.warn("Client tried to set difficulty while server was stopped");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCPacket0BPause.ID: {
|
||||
IPCPacket0BPause pkt = (IPCPacket0BPause)ipc;
|
||||
if(!isServerStopped()) {
|
||||
currentProcess.setPaused(pkt.pause);
|
||||
sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacket0BPause.ID));
|
||||
}else {
|
||||
logger.error("Client tried to {} while server was stopped", pkt.pause ? "pause" : "unpause");
|
||||
sendTaskFailed();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCPacket0CPlayerChannel.ID: {
|
||||
IPCPacket0CPlayerChannel pkt = (IPCPacket0CPlayerChannel)ipc;
|
||||
if(!isServerStopped()) {
|
||||
if(pkt.open) {
|
||||
startPlayerConnnection(pkt.channel);
|
||||
}else {
|
||||
closeChannel(pkt.channel);
|
||||
}
|
||||
}else {
|
||||
logger.error("Client tried to {} channel server was stopped", pkt.open ? "open" : "close");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCPacket0EListWorlds.ID: {
|
||||
IPCPacket0EListWorlds pkt = (IPCPacket0EListWorlds)ipc;
|
||||
if(!isServerStopped()) {
|
||||
logger.error("Client tried to list worlds while server was running");
|
||||
sendTaskFailed();
|
||||
}else {
|
||||
String[] worlds = EaglerSaveFormat.worldsList.getAllLines();
|
||||
if(worlds == null) {
|
||||
sendIPCPacket(new IPCPacket16NBTList(IPCPacket16NBTList.WORLD_LIST, new LinkedList<NBTTagCompound>()));
|
||||
break;
|
||||
}
|
||||
LinkedHashSet<String> updatedList = new LinkedHashSet();
|
||||
LinkedList<NBTTagCompound> sendListNBT = new LinkedList();
|
||||
boolean rewrite = false;
|
||||
for(int i = 0; i < worlds.length; ++i) {
|
||||
String w = worlds[i].trim();
|
||||
if(w.length() > 0) {
|
||||
VFile2 vf = new VFile2(EaglerSaveFormat.worldsFolder, w, "level.dat");
|
||||
if(!vf.exists()) {
|
||||
vf = new VFile2(EaglerSaveFormat.worldsFolder, w, "level.dat_old");
|
||||
}
|
||||
if(vf.exists()) {
|
||||
try(InputStream dat = vf.getInputStream()) {
|
||||
if(updatedList.add(w)) {
|
||||
NBTTagCompound worldDatNBT = CompressedStreamTools.readCompressed(dat);
|
||||
worldDatNBT.setString("folderNameEagler", w);
|
||||
sendListNBT.add(worldDatNBT);
|
||||
}else {
|
||||
rewrite = true;
|
||||
}
|
||||
continue;
|
||||
}catch(IOException e) {
|
||||
// shit fuck
|
||||
}
|
||||
}
|
||||
rewrite = true;
|
||||
logger.error("World level.dat for '{}' was not found, attempting to delete", w);
|
||||
if(!saveFormat.deleteWorldDirectory(w)) {
|
||||
logger.error("Failed to delete '{}'! It will be removed from the worlds list anyway", w);
|
||||
}
|
||||
}else {
|
||||
rewrite = true;
|
||||
}
|
||||
}
|
||||
if(rewrite) {
|
||||
EaglerSaveFormat.worldsList.setAllChars(String.join("\n", updatedList));
|
||||
}
|
||||
sendIPCPacket(new IPCPacket16NBTList(IPCPacket16NBTList.WORLD_LIST, sendListNBT));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCPacket14StringList.ID: {
|
||||
IPCPacket14StringList pkt = (IPCPacket14StringList)ipc;
|
||||
switch(pkt.opCode) {
|
||||
case IPCPacket14StringList.LOCALE:
|
||||
StringTranslate.init(pkt.stringList);
|
||||
break;
|
||||
//case IPCPacket14StringList.STAT_GUID:
|
||||
// AchievementMap.init(pkt.stringList);
|
||||
// AchievementList.init();
|
||||
// break;
|
||||
default:
|
||||
logger.error("Strange string list 0x{} with length{} recieved", Integer.toHexString(pkt.opCode), pkt.stringList.size());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCPacket17ConfigureLAN.ID: {
|
||||
|
||||
IPCPacket17ConfigureLAN pkt = (IPCPacket17ConfigureLAN)ipc;
|
||||
currentProcess.getConfigurationManager().configureLAN(pkt.gamemode, pkt.cheats); // don't use iceServers
|
||||
|
||||
break;
|
||||
}
|
||||
case IPCPacket18ClearPlayers.ID: {
|
||||
if(!isServerStopped()) {
|
||||
logger.error("Client tried to clear players while server was running");
|
||||
sendTaskFailed();
|
||||
}else {
|
||||
saveFormat.clearPlayers(((IPCPacket18ClearPlayers)ipc).worldName);
|
||||
sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacket18ClearPlayers.ID));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCPacket19Autosave.ID: {
|
||||
if(!isServerStopped()) {
|
||||
currentProcess.getConfigurationManager().saveAllPlayerData();
|
||||
currentProcess.saveAllWorlds(false);
|
||||
sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacket19Autosave.ID));
|
||||
}else {
|
||||
logger.error("Client tried to autosave while server was stopped");
|
||||
sendTaskFailed();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPCPacket21EnableLogging.ID: {
|
||||
enableLoggingRedirector(((IPCPacket21EnableLogging)ipc).enable);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
logger.error("IPC packet type 0x{} class \"{}\" was not handled", Integer.toHexString(id), ipc.getClass().getSimpleName());
|
||||
sendTaskFailed();
|
||||
break;
|
||||
}
|
||||
}catch(Throwable t) {
|
||||
logger.error("IPC packet type 0x{} class \"{}\" was not processed correctly", Integer.toHexString(id), ipc.getClass().getSimpleName());
|
||||
logger.error(t);
|
||||
sendIPCPacket(new IPCPacket15Crashed("IPC packet type 0x" + Integer.toHexString(id) + " class \"" + ipc.getClass().getSimpleName() + "\" was not processed correctly!\n\n" + EagRuntime.getStackTrace(t)));
|
||||
sendTaskFailed();
|
||||
}
|
||||
}
|
||||
|
||||
public static void enableLoggingRedirector(boolean en) {
|
||||
LogManager.logRedirector = en ? new ILogRedirector() {
|
||||
@Override
|
||||
public void log(String txt, boolean err) {
|
||||
sendLogMessagePacket(txt, err);
|
||||
}
|
||||
} : null;
|
||||
}
|
||||
|
||||
public static void sendLogMessagePacket(String txt, boolean err) {
|
||||
sendIPCPacket(new IPCPacket20LoggerMessage(txt, err));
|
||||
}
|
||||
|
||||
public static void sendIPCPacket(IPCPacketBase ipc) {
|
||||
byte[] pkt;
|
||||
try {
|
||||
pkt = IPCPacketManager.IPCSerialize(ipc);
|
||||
}catch (IOException ex) {
|
||||
throw new RuntimeException("Failed to serialize IPC packet", ex);
|
||||
}
|
||||
ServerPlatformSingleplayer.sendPacket(new IPCPacketData(SingleplayerServerController.IPC_CHANNEL, pkt));
|
||||
}
|
||||
|
||||
public static void reportTPS(List<String> texts) {
|
||||
sendIPCPacket(new IPCPacket14StringList(IPCPacket14StringList.SERVER_TPS, texts));
|
||||
}
|
||||
|
||||
public static void sendTaskFailed() {
|
||||
sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacketFFProcessKeepAlive.FAILURE));
|
||||
}
|
||||
|
||||
public static void sendProgress(String updateMessage, float updateProgress) {
|
||||
sendIPCPacket(new IPCPacket0DProgressUpdate(updateMessage, updateProgress));
|
||||
}
|
||||
|
||||
private static boolean isServerStopped() {
|
||||
return currentProcess == null || !currentProcess.isServerRunning();
|
||||
}
|
||||
|
||||
private static void tryStopServer() {
|
||||
if(!isServerStopped()) {
|
||||
currentProcess.stopServer();
|
||||
}
|
||||
currentProcess = null;
|
||||
}
|
||||
|
||||
private static void mainLoop() {
|
||||
processAsyncMessageQueue();
|
||||
|
||||
if(currentProcess != null) {
|
||||
if(currentProcess.isServerRunning()) {
|
||||
currentProcess.mainLoop();
|
||||
}
|
||||
if(!currentProcess.isServerRunning()) {
|
||||
currentProcess.stopServer();
|
||||
currentProcess = null;
|
||||
sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacket01StopServer.ID));
|
||||
}
|
||||
}else {
|
||||
EagUtils.sleep(50l);
|
||||
}
|
||||
}
|
||||
|
||||
public static void serverMain() {
|
||||
try {
|
||||
currentProcess = null;
|
||||
logger.info("Starting EaglercraftX integrated server worker...");
|
||||
|
||||
// signal thread startup successful
|
||||
sendIPCPacket(new IPCPacketFFProcessKeepAlive(0xFF));
|
||||
|
||||
while(true) {
|
||||
mainLoop();
|
||||
EagUtils.sleep(1l);
|
||||
}
|
||||
}catch(Throwable tt) {
|
||||
if(tt instanceof ReportedException) {
|
||||
String fullReport = ((ReportedException)tt).getCrashReport().getCompleteReport();
|
||||
logger.error(fullReport);
|
||||
sendIPCPacket(new IPCPacket15Crashed(fullReport));
|
||||
}else {
|
||||
logger.error("Server process encountered a fatal error!");
|
||||
logger.error(tt);
|
||||
sendIPCPacket(new IPCPacket15Crashed("SERVER PROCESS EXITED!\n\n" + EagRuntime.getStackTrace(tt)));
|
||||
}
|
||||
}finally {
|
||||
if(!isServerStopped()) {
|
||||
try {
|
||||
currentProcess.stopServer();
|
||||
}catch(Throwable t) {
|
||||
logger.error("Encountered exception while stopping server!");
|
||||
logger.error(t);
|
||||
}
|
||||
}
|
||||
logger.error("Server process exited!");
|
||||
sendIPCPacket(new IPCPacketFFProcessKeepAlive(IPCPacketFFProcessKeepAlive.EXITED));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,291 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFile2;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.entity.player.EntityPlayer;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.init.Bootstrap;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.server.MinecraftServer;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.EnumDifficulty;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.WorldServer;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.WorldSettings;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.WorldSettings.GameType;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.skins.IntegratedSkinService;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class EaglerMinecraftServer extends MinecraftServer {
|
||||
|
||||
public static final Logger logger = EaglerIntegratedServerWorker.logger;
|
||||
|
||||
public static final VFile2 savesDir = new VFile2("worlds");
|
||||
|
||||
protected EnumDifficulty difficulty;
|
||||
protected GameType gamemode;
|
||||
protected WorldSettings newWorldSettings;
|
||||
protected boolean paused;
|
||||
protected EaglerSaveHandler saveHandler;
|
||||
protected IntegratedSkinService skinService;
|
||||
|
||||
private long lastTPSUpdate = 0l;
|
||||
|
||||
public static int counterTicksPerSecond = 0;
|
||||
public static int counterChunkRead = 0;
|
||||
public static int counterChunkGenerate = 0;
|
||||
public static int counterChunkWrite = 0;
|
||||
public static int counterTileUpdate = 0;
|
||||
public static int counterLightUpdate = 0;
|
||||
|
||||
private final List<Runnable> scheduledTasks = new LinkedList();
|
||||
|
||||
public EaglerMinecraftServer(String world, String owner, int viewDistance, WorldSettings currentWorldSettings, boolean demo) {
|
||||
super(world);
|
||||
Bootstrap.register();
|
||||
this.saveHandler = new EaglerSaveHandler(savesDir, world);
|
||||
this.skinService = new IntegratedSkinService(new VFile2(saveHandler.getWorldDirectory(), "eagler/skulls"));
|
||||
this.setServerOwner(owner);
|
||||
logger.info("server owner: " + owner);
|
||||
this.setDemo(demo);
|
||||
this.canCreateBonusChest(currentWorldSettings != null && currentWorldSettings.isBonusChestEnabled());
|
||||
this.setBuildLimit(256);
|
||||
this.setConfigManager(new EaglerPlayerList(this, viewDistance));
|
||||
this.newWorldSettings = currentWorldSettings;
|
||||
this.paused = false;
|
||||
}
|
||||
|
||||
public IntegratedSkinService getSkinService() {
|
||||
return skinService;
|
||||
}
|
||||
|
||||
public void setBaseServerProperties(EnumDifficulty difficulty, GameType gamemode) {
|
||||
this.difficulty = difficulty;
|
||||
this.gamemode = gamemode;
|
||||
this.setCanSpawnAnimals(true);
|
||||
this.setCanSpawnNPCs(true);
|
||||
this.setAllowPvp(true);
|
||||
this.setAllowFlight(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addScheduledTask(Runnable var1) {
|
||||
scheduledTasks.add(var1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean startServer() throws IOException {
|
||||
logger.info("Starting integrated eaglercraft server version 1.8.8");
|
||||
this.loadAllWorlds(saveHandler, this.getWorldName(), newWorldSettings);
|
||||
serverRunning = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void deleteWorldAndStopServer() {
|
||||
super.deleteWorldAndStopServer();
|
||||
logger.info("Deleting world...");
|
||||
EaglerIntegratedServerWorker.saveFormat.deleteWorldDirectory(getFolderName());
|
||||
}
|
||||
|
||||
public void mainLoop() {
|
||||
long k = getCurrentTimeMillis();
|
||||
this.sendTPSToClient(k);
|
||||
if(paused && this.playersOnline.size() <= 1) {
|
||||
currentTime = k;
|
||||
return;
|
||||
}
|
||||
|
||||
long j = k - this.currentTime;
|
||||
if (j > 2000L && this.currentTime - this.timeOfLastWarning >= 15000L) {
|
||||
logger.warn(
|
||||
"Can\'t keep up! Did the system time change, or is the server overloaded? Running {}ms behind, skipping {} tick(s)",
|
||||
new Object[] { Long.valueOf(j), Long.valueOf(j / 50L) });
|
||||
j = 100L;
|
||||
this.currentTime = k - 100l;
|
||||
this.timeOfLastWarning = this.currentTime;
|
||||
}
|
||||
|
||||
if (j < 0L) {
|
||||
logger.warn("Time ran backwards! Did the system time change?");
|
||||
j = 0L;
|
||||
this.currentTime = k;
|
||||
}
|
||||
|
||||
if (this.worldServers[0].areAllPlayersAsleep()) {
|
||||
this.currentTime = k;
|
||||
this.tick();
|
||||
++counterTicksPerSecond;
|
||||
} else {
|
||||
if (j > 50L) {
|
||||
this.currentTime += 50l;
|
||||
this.tick();
|
||||
++counterTicksPerSecond;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateTimeLightAndEntities() {
|
||||
this.skinService.flushCache();
|
||||
super.updateTimeLightAndEntities();
|
||||
}
|
||||
|
||||
protected void sendTPSToClient(long millis) {
|
||||
if(millis - lastTPSUpdate > 1000l) {
|
||||
lastTPSUpdate = millis;
|
||||
if(serverRunning && this.worldServers != null) {
|
||||
List<String> lst = new ArrayList<>(Arrays.asList(
|
||||
"TPS: " + counterTicksPerSecond + "/20",
|
||||
"Chunks: " + countChunksLoaded(this.worldServers) + "/" + countChunksTotal(this.worldServers),
|
||||
"Entities: " + countEntities(this.worldServers) + "+" + countTileEntities(this.worldServers),
|
||||
"R: " + counterChunkRead + ", G: " + counterChunkGenerate + ", W: " + counterChunkWrite,
|
||||
"TU: " + counterTileUpdate + ", LU: " + counterLightUpdate
|
||||
));
|
||||
int players = countPlayerEntities(this.worldServers);
|
||||
if(players > 1) {
|
||||
lst.add("Players: " + players);
|
||||
}
|
||||
counterTicksPerSecond = counterChunkRead = counterChunkGenerate = 0;
|
||||
counterChunkWrite = counterTileUpdate = counterLightUpdate = 0;
|
||||
EaglerIntegratedServerWorker.reportTPS(lst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int countChunksLoaded(WorldServer[] worlds) {
|
||||
int i = 0;
|
||||
for(int j = 0; j < worlds.length; ++j) {
|
||||
if(worlds[j] != null) {
|
||||
i += worlds[j].theChunkProviderServer.getLoadedChunkCount();
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
private static int countChunksTotal(WorldServer[] worlds) {
|
||||
int i = 0;
|
||||
for(int j = 0; j < worlds.length; ++j) {
|
||||
if(worlds[j] != null) {
|
||||
List<EntityPlayer> players = worlds[j].playerEntities;
|
||||
for(int l = 0, n = players.size(); l < n; ++l) {
|
||||
i += ((EntityPlayerMP)players.get(l)).loadedChunks.size();
|
||||
}
|
||||
i += worlds[j].theChunkProviderServer.getLoadedChunkCount();
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
private static int countEntities(WorldServer[] worlds) {
|
||||
int i = 0;
|
||||
for(int j = 0; j < worlds.length; ++j) {
|
||||
if(worlds[j] != null) {
|
||||
i += worlds[j].loadedEntityList.size();
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
private static int countTileEntities(WorldServer[] worlds) {
|
||||
int i = 0;
|
||||
for(int j = 0; j < worlds.length; ++j) {
|
||||
if(worlds[j] != null) {
|
||||
i += worlds[j].loadedTileEntityList.size();
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
private static int countPlayerEntities(WorldServer[] worlds) {
|
||||
int i = 0;
|
||||
for(int j = 0; j < worlds.length; ++j) {
|
||||
if(worlds[j] != null) {
|
||||
i += worlds[j].playerEntities.size();
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
public void setPaused(boolean p) {
|
||||
paused = p;
|
||||
if(!p) {
|
||||
currentTime = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getPaused() {
|
||||
return paused;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canStructuresSpawn() {
|
||||
return worldServers != null ? worldServers[0].getWorldInfo().isMapFeaturesEnabled() : newWorldSettings.isMapFeaturesEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameType getGameType() {
|
||||
return worldServers != null ? worldServers[0].getWorldInfo().getGameType() : newWorldSettings.getGameType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EnumDifficulty getDifficulty() {
|
||||
return difficulty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHardcore() {
|
||||
return worldServers != null ? worldServers[0].getWorldInfo().isHardcoreModeEnabled() : newWorldSettings.getHardcoreEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpPermissionLevel() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean func_181034_q() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean func_183002_r() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDedicatedServer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean func_181035_ah() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCommandBlockEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String shareToLAN(GameType var1, boolean var2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.server;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.server.MinecraftServer;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.server.management.ServerConfigurationManager;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class EaglerPlayerList extends ServerConfigurationManager {
|
||||
|
||||
private NBTTagCompound hostPlayerNBT = null;
|
||||
|
||||
public EaglerPlayerList(MinecraftServer par1MinecraftServer, int viewDistance) {
|
||||
super(par1MinecraftServer);
|
||||
this.viewDistance = viewDistance;
|
||||
}
|
||||
|
||||
protected void writePlayerData(EntityPlayerMP par1EntityPlayerMP) {
|
||||
if (par1EntityPlayerMP.getName().equals(this.getServerInstance().getServerOwner())) {
|
||||
this.hostPlayerNBT = new NBTTagCompound();
|
||||
par1EntityPlayerMP.writeToNBT(hostPlayerNBT);
|
||||
}
|
||||
super.writePlayerData(par1EntityPlayerMP);
|
||||
}
|
||||
|
||||
public NBTTagCompound getHostPlayerData() {
|
||||
return this.hostPlayerNBT;
|
||||
}
|
||||
|
||||
public void playerLoggedOut(EntityPlayerMP playerIn) {
|
||||
super.playerLoggedOut(playerIn);
|
||||
((EaglerMinecraftServer)getServerInstance()).skinService.unregisterPlayer(playerIn.getUniqueID());
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.server;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFile2;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.storage.ISaveHandler;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.storage.SaveFormatComparator;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.storage.SaveFormatOld;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.storage.WorldInfo;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class EaglerSaveFormat extends SaveFormatOld {
|
||||
|
||||
public static final VFile2 worldsList = new VFile2("worlds_list.txt");
|
||||
public static final VFile2 worldsFolder = new VFile2("worlds");
|
||||
|
||||
public EaglerSaveFormat(VFile2 parFile) {
|
||||
super(parFile);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "eagler";
|
||||
}
|
||||
|
||||
public ISaveHandler getSaveLoader(String s, boolean flag) {
|
||||
return new EaglerSaveHandler(this.savesDirectory, s);
|
||||
}
|
||||
|
||||
public List<SaveFormatComparator> getSaveList() {
|
||||
ArrayList arraylist = Lists.newArrayList();
|
||||
if(worldsList.exists()) {
|
||||
String[] lines = worldsList.getAllLines();
|
||||
for (int i = 0; i < lines.length; ++i) {
|
||||
String s = lines[i];
|
||||
WorldInfo worldinfo = this.getWorldInfo(s);
|
||||
if (worldinfo != null
|
||||
&& (worldinfo.getSaveVersion() == 19132 || worldinfo.getSaveVersion() == 19133)) {
|
||||
boolean flag = worldinfo.getSaveVersion() != this.getSaveVersion();
|
||||
String s1 = worldinfo.getWorldName();
|
||||
if (StringUtils.isEmpty(s1)) {
|
||||
s1 = s;
|
||||
}
|
||||
|
||||
arraylist.add(new SaveFormatComparator(s, s1, worldinfo.getLastTimePlayed(), 0l,
|
||||
worldinfo.getGameType(), flag, worldinfo.isHardcoreModeEnabled(),
|
||||
worldinfo.areCommandsAllowed()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return arraylist;
|
||||
}
|
||||
|
||||
public void clearPlayers(String worldFolder) {
|
||||
VFile2 file1 = new VFile2(this.savesDirectory, worldFolder, "player");
|
||||
deleteFiles(file1.listFiles(true), null);
|
||||
}
|
||||
|
||||
protected int getSaveVersion() {
|
||||
return 19133; // why notch?
|
||||
}
|
||||
|
||||
public boolean duplicateWorld(String worldFolder, String displayName) {
|
||||
String newFolderName = displayName.replaceAll("[\\./\"]", "_");
|
||||
VFile2 newFolder = new VFile2(savesDirectory, newFolderName);
|
||||
while((new VFile2(newFolder, "level.dat")).exists() || (new VFile2(newFolder, "level.dat_old")).exists()) {
|
||||
newFolderName += "_";
|
||||
newFolder = new VFile2(savesDirectory, newFolderName);
|
||||
}
|
||||
VFile2 oldFolder = new VFile2(this.savesDirectory, worldFolder);
|
||||
String oldPath = oldFolder.getPath();
|
||||
int totalSize = 0;
|
||||
int lastUpdate = 0;
|
||||
final VFile2 finalNewFolder = newFolder;
|
||||
for(VFile2 vf : oldFolder.listFiles(true)) {
|
||||
String fileNameRelative = vf.getPath().substring(oldPath.length() + 1);
|
||||
totalSize += VFile2.copyFile(vf, new VFile2(finalNewFolder, fileNameRelative));
|
||||
if (totalSize - lastUpdate > 10000) {
|
||||
lastUpdate = totalSize;
|
||||
EaglerIntegratedServerWorker.sendProgress("singleplayer.busy.duplicating", totalSize);
|
||||
}
|
||||
}
|
||||
String[] worldsTxt = worldsList.getAllLines();
|
||||
if(worldsTxt == null || worldsTxt.length <= 0) {
|
||||
worldsTxt = new String[] { newFolderName };
|
||||
}else {
|
||||
String[] tmp = worldsTxt;
|
||||
worldsTxt = new String[worldsTxt.length + 1];
|
||||
System.arraycopy(tmp, 0, worldsTxt, 0, tmp.length);
|
||||
worldsTxt[worldsTxt.length - 1] = newFolderName;
|
||||
}
|
||||
worldsList.setAllChars(String.join("\n", worldsTxt));
|
||||
return renameWorld(newFolderName, displayName);
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.server;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFile2;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.WorldProvider;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.chunk.storage.IChunkLoader;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.storage.SaveHandler;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.storage.WorldInfo;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2023-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class EaglerSaveHandler extends SaveHandler {
|
||||
|
||||
public EaglerSaveHandler(VFile2 savesDirectory, String directoryName) {
|
||||
super(savesDirectory, directoryName);
|
||||
}
|
||||
|
||||
public IChunkLoader getChunkLoader(WorldProvider provider) {
|
||||
return new EaglerChunkLoader(new VFile2(this.getWorldDirectory(), "level" + provider.getDimensionId()));
|
||||
}
|
||||
|
||||
public void saveWorldInfoWithPlayer(WorldInfo worldInformation, NBTTagCompound tagCompound) {
|
||||
worldInformation.setSaveVersion(19133);
|
||||
super.saveWorldInfoWithPlayer(worldInformation, tagCompound);
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.server.classes;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class ContextUtil {
|
||||
|
||||
public static final Logger LOGGER = LogManager.getLogger("ContextUtil");
|
||||
|
||||
private static boolean GUARD_CONTEXT = false; // disable guard, for stability
|
||||
|
||||
public static void enterContext() {
|
||||
if(!GUARD_CONTEXT) {
|
||||
GUARD_CONTEXT = true;
|
||||
LOGGER.info("Entered context");
|
||||
}
|
||||
}
|
||||
|
||||
public static void exitContext() {
|
||||
if(GUARD_CONTEXT) {
|
||||
GUARD_CONTEXT = false;
|
||||
LOGGER.info("Exited context");
|
||||
}
|
||||
}
|
||||
|
||||
public static void __checkIntegratedContextValid(String id) {
|
||||
if(GUARD_CONTEXT) {
|
||||
throw new IllegalContextAccessException("Illegal integrated server class access: " + id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.server.classes;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.json.JSONTypeProvider;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.util.ChatStyle;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.util.IChatComponent;
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.gen.ChunkProviderSettings;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class EaglerServerBootstrap {
|
||||
|
||||
private static boolean isCLInit = false;
|
||||
|
||||
public static void staticInit() {
|
||||
if(isCLInit) {
|
||||
return;
|
||||
}
|
||||
registerJSONTypes();
|
||||
isCLInit = true;
|
||||
}
|
||||
|
||||
public static void registerJSONTypes() {
|
||||
JSONTypeProvider.registerType(IChatComponent.class, new IChatComponent.Serializer());
|
||||
JSONTypeProvider.registerType(ChatStyle.class, new ChatStyle.Serializer());
|
||||
JSONTypeProvider.registerType(ChunkProviderSettings.Factory.class, new ChunkProviderSettings.Serializer());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.server.classes;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class IllegalContextAccessException extends RuntimeException {
|
||||
|
||||
public IllegalContextAccessException() {
|
||||
}
|
||||
|
||||
public IllegalContextAccessException(String s) {
|
||||
super(s);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.entity;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.sp.server.classes.net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public interface EntityConstructor<T> {
|
||||
|
||||
T createEntity(World world);
|
||||
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
package net.lax1dude.eaglercraft.v1_8.sp.server.export;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
|
||||
/**
|
||||
* Copyright (c) 2022-2024 lax1dude. All Rights Reserved.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
public class EPKCompiler {
|
||||
|
||||
private final ByteArrayOutputStream os;
|
||||
private final CRC32 checkSum = new CRC32();
|
||||
private int lengthIntegerOffset = 0;
|
||||
private int totalFileCount = 0;
|
||||
|
||||
public EPKCompiler(String name, String owner, String type) {
|
||||
os = new ByteArrayOutputStream(0x200000);
|
||||
try {
|
||||
|
||||
os.write(new byte[]{(byte)69,(byte)65,(byte)71,(byte)80,(byte)75,(byte)71,(byte)36,(byte)36}); // EAGPKG$$
|
||||
os.write(new byte[]{(byte)6,(byte)118,(byte)101,(byte)114,(byte)50,(byte)46,(byte)48}); // 6 + ver2.0
|
||||
Date d = new Date();
|
||||
|
||||
byte[] filename = (name + ".epk").getBytes(StandardCharsets.UTF_8);
|
||||
os.write(filename.length);
|
||||
os.write(filename);
|
||||
|
||||
byte[] comment = ("\n\n # Eagler EPK v2.0 (c) " + EagRuntime.fixDateFormat(new SimpleDateFormat("yyyy")).format(d) + " " +
|
||||
owner + "\n # export: on " + EagRuntime.fixDateFormat(new SimpleDateFormat("MM/dd/yyyy")).format(d) + " at " +
|
||||
EagRuntime.fixDateFormat(new SimpleDateFormat("hh:mm:ss aa")).format(d) + "\n\n # world name: " + name + "\n\n")
|
||||
.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
os.write((comment.length >> 8) & 255);
|
||||
os.write(comment.length & 255);
|
||||
os.write(comment);
|
||||
|
||||
writeLong(d.getTime(), os);
|
||||
|
||||
lengthIntegerOffset = os.size();
|
||||
os.write(new byte[]{(byte)255,(byte)255,(byte)255,(byte)255}); // this will be replaced with the file count
|
||||
|
||||
os.write('0'); // compression type: none
|
||||
|
||||
os.write(new byte[]{(byte)72,(byte)69,(byte)65,(byte)68}); // HEAD
|
||||
os.write(new byte[]{(byte)9,(byte)102,(byte)105,(byte)108,(byte)101,(byte)45,(byte)116,(byte)121,
|
||||
(byte)112,(byte)101}); // 9 + file-type
|
||||
|
||||
byte[] typeBytes = type.getBytes(StandardCharsets.UTF_8);
|
||||
writeInt(typeBytes.length, os);
|
||||
os.write(typeBytes); // write type
|
||||
os.write('>');
|
||||
|
||||
++totalFileCount;
|
||||
|
||||
os.write(new byte[]{(byte)72,(byte)69,(byte)65,(byte)68}); // HEAD
|
||||
os.write(new byte[]{(byte)10,(byte)119,(byte)111,(byte)114,(byte)108,(byte)100,(byte)45,(byte)110,
|
||||
(byte)97,(byte)109,(byte)101}); // 10 + world-name
|
||||
|
||||
byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8);
|
||||
writeInt(nameBytes.length, os);
|
||||
os.write(nameBytes); // write name
|
||||
os.write('>');
|
||||
|
||||
++totalFileCount;
|
||||
|
||||
os.write(new byte[]{(byte)72,(byte)69,(byte)65,(byte)68}); // HEAD
|
||||
os.write(new byte[]{(byte)11,(byte)119,(byte)111,(byte)114,(byte)108,(byte)100,(byte)45,(byte)111,
|
||||
(byte)119,(byte)110,(byte)101,(byte)114}); // 11 + world-owner
|
||||
|
||||
byte[] ownerBytes = owner.getBytes(StandardCharsets.UTF_8);
|
||||
writeInt(ownerBytes.length, os);
|
||||
os.write(ownerBytes); // write owner
|
||||
os.write('>');
|
||||
|
||||
++totalFileCount;
|
||||
|
||||
}catch(IOException ex) {
|
||||
throw new RuntimeException("This happened somehow", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void append(String name, byte[] dat) {
|
||||
try {
|
||||
|
||||
checkSum.reset();
|
||||
checkSum.update(dat, 0, dat.length);
|
||||
long sum = checkSum.getValue();
|
||||
|
||||
os.write(new byte[]{(byte)70,(byte)73,(byte)76,(byte)69}); // FILE
|
||||
|
||||
byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8);
|
||||
os.write(nameBytes.length);
|
||||
os.write(nameBytes);
|
||||
|
||||
writeInt(dat.length + 5, os);
|
||||
writeInt((int)sum, os);
|
||||
|
||||
os.write(dat);
|
||||
|
||||
os.write(':');
|
||||
os.write('>');
|
||||
|
||||
++totalFileCount;
|
||||
|
||||
}catch(IOException ex) {
|
||||
throw new RuntimeException("This happened somehow", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] complete() {
|
||||
try {
|
||||
|
||||
os.write(new byte[]{(byte)69,(byte)78,(byte)68,(byte)36}); // END$
|
||||
os.write(new byte[]{(byte)58,(byte)58,(byte)58,(byte)89,(byte)69,(byte)69,(byte)58,(byte)62}); // :::YEE:>
|
||||
|
||||
byte[] ret = os.toByteArray();
|
||||
|
||||
ret[lengthIntegerOffset] = (byte)((totalFileCount >> 24) & 0xFF);
|
||||
ret[lengthIntegerOffset + 1] = (byte)((totalFileCount >> 16) & 0xFF);
|
||||
ret[lengthIntegerOffset + 2] = (byte)((totalFileCount >> 8) & 0xFF);
|
||||
ret[lengthIntegerOffset + 3] = (byte)(totalFileCount & 0xFF);
|
||||
|
||||
return ret;
|
||||
|
||||
}catch(IOException ex) {
|
||||
throw new RuntimeException("This happened somehow", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeInt(int i, OutputStream os) throws IOException {
|
||||
os.write((i >> 24) & 0xFF);
|
||||
os.write((i >> 16) & 0xFF);
|
||||
os.write((i >> 8) & 0xFF);
|
||||
os.write(i & 0xFF);
|
||||
}
|
||||
|
||||
public static void writeLong(long i, OutputStream os) throws IOException {
|
||||
os.write((int)((i >> 56) & 0xFF));
|
||||
os.write((int)((i >> 48) & 0xFF));
|
||||
os.write((int)((i >> 40) & 0xFF));
|
||||
os.write((int)((i >> 32) & 0xFF));
|
||||
os.write((int)((i >> 24) & 0xFF));
|
||||
os.write((int)((i >> 16) & 0xFF));
|
||||
os.write((int)((i >> 8) & 0xFF));
|
||||
os.write((int)(i & 0xFF));
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user