Expanded the Mod check to test for missing mods and display a GUI screen for the client if it is missing any.
The client now downloads NetworkMod ID's from the server upon connecting.
This commit is contained in:
parent
70fbe4f403
commit
a6f93ed528
6 changed files with 310 additions and 4 deletions
|
@ -0,0 +1,39 @@
|
|||
package net.minecraft.src.forge;
|
||||
|
||||
import net.minecraft.src.*;
|
||||
import net.minecraft.src.forge.packets.PacketMissingMods;
|
||||
|
||||
public class GuiMissingMods extends GuiScreen
|
||||
{
|
||||
PacketMissingMods packet;
|
||||
public GuiMissingMods(PacketMissingMods pkt)
|
||||
{
|
||||
packet = pkt;
|
||||
}
|
||||
|
||||
public void initGui()
|
||||
{
|
||||
controlList.clear();
|
||||
controlList.add(new GuiButton(0, width / 2 - 100, height - 60, StringTranslate.getInstance().translateKey("gui.toMenu")));
|
||||
}
|
||||
|
||||
protected void actionPerformed(GuiButton guibutton)
|
||||
{
|
||||
if (guibutton.id == 0)
|
||||
{
|
||||
mc.displayGuiScreen(new GuiMainMenu());
|
||||
}
|
||||
}
|
||||
|
||||
public void drawScreen(int i, int j, float f)
|
||||
{
|
||||
drawDefaultBackground();
|
||||
drawCenteredString(fontRenderer, "The server requires the following mods:", width / 2, height / 2 - 50, 0xffffff);
|
||||
int y = 0;
|
||||
for (String mod : packet.Mods)
|
||||
{
|
||||
drawCenteredString(fontRenderer, mod, width / 2, (height / 2 - 10) + y++ * 10, 0xffffff);
|
||||
}
|
||||
super.drawScreen(i, j, f);
|
||||
}
|
||||
}
|
|
@ -33,6 +33,26 @@ public class PacketHandlerClient implements IPacketHandler
|
|||
pkt.readData(data);
|
||||
onEntitySpawnPacket((PacketEntitySpawn)pkt, data, ModLoader.getMinecraftInstance().theWorld);
|
||||
break;
|
||||
|
||||
case ForgePacket.MODLIST:
|
||||
/*
|
||||
pkt = new PacketModList(false);
|
||||
pkt.readData(data);
|
||||
*/
|
||||
onModListCheck(net);
|
||||
break;
|
||||
|
||||
case ForgePacket.MOD_MISSING:
|
||||
pkt = new PacketMissingMods(false);
|
||||
pkt.readData(data);
|
||||
onMissingMods((PacketMissingMods)pkt, net);
|
||||
break;
|
||||
|
||||
case ForgePacket.MOD_IDS:
|
||||
pkt = new PacketModIDs();
|
||||
pkt.readData(data);
|
||||
onModIDs((PacketModIDs)pkt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(IOException e)
|
||||
|
@ -125,4 +145,51 @@ public class PacketHandlerClient implements IPacketHandler
|
|||
}
|
||||
net.addToSendQueue(pkt.getPacket());
|
||||
}
|
||||
|
||||
/**
|
||||
* Received when the client does not have a mod installed that the server requires them to.
|
||||
* Displays a informative screen, and disconnects from the server.
|
||||
*
|
||||
* @param pkt The missing mods packet
|
||||
* @param net The network handler
|
||||
*/
|
||||
private void onMissingMods(PacketMissingMods pkt, NetClientHandler net)
|
||||
{
|
||||
net.disconnect();
|
||||
Minecraft mc = ModLoader.getMinecraftInstance();
|
||||
mc.changeWorld1(null);
|
||||
mc.displayGuiScreen(new GuiMissingMods(pkt));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the list of ID to mod mappings.
|
||||
* TODO; Make it display an error, and prompt if the user wishes to continue anyways
|
||||
* if it detects that the server does not have a corresponding mod to one it has installed.
|
||||
*
|
||||
* @param pkt The mod id packet
|
||||
*/
|
||||
private void onModIDs(PacketModIDs pkt)
|
||||
{
|
||||
ForgeHooks.networkMods.clear();
|
||||
NetworkMod[] mods = MinecraftForge.getNetworkMods();
|
||||
for (NetworkMod mod : mods)
|
||||
{
|
||||
for (Entry<Integer, String> entry : pkt.Mods.entrySet())
|
||||
{
|
||||
if (mod.toString().equals(entry.getValue()))
|
||||
{
|
||||
ForgeHooks.networkMods.put(entry.getKey(), mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
ArrayList<NetworkMod> missing = new ArrayList<NetworkMod>();
|
||||
for (NetworkMod mod : mods)
|
||||
{
|
||||
if (MinecraftForge.getModID(mod) == -1 && mod.serverSideRequired())
|
||||
{
|
||||
missing.add(mod);
|
||||
}
|
||||
}
|
||||
//TODO: Display error/confirmation screen
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package net.minecraft.src.forge.packets;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PacketMissingMods extends PacketModList
|
||||
{
|
||||
|
||||
public PacketMissingMods(boolean server)
|
||||
{
|
||||
super(!server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getID()
|
||||
{
|
||||
return ForgePacket.MOD_MISSING;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package net.minecraft.src.forge.packets;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class PacketModIDs extends ForgePacket
|
||||
{
|
||||
public Hashtable<Integer, String> Mods = new Hashtable<Integer, String>();
|
||||
public int Length;
|
||||
|
||||
@Override
|
||||
public void writeData(DataOutputStream data) throws IOException
|
||||
{
|
||||
data.writeInt(Mods.size());
|
||||
for (Entry<Integer, String> entry : Mods.entrySet())
|
||||
{
|
||||
data.writeInt(entry.getKey());
|
||||
data.writeUTF(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readData(DataInputStream data) throws IOException
|
||||
{
|
||||
Length = data.readInt();
|
||||
for(int x = 0; x < Length; x++)
|
||||
{
|
||||
Mods.put(data.readInt(), data.readUTF());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getID()
|
||||
{
|
||||
return ForgePacket.MOD_IDS;
|
||||
}
|
||||
|
||||
}
|
|
@ -2,8 +2,8 @@ package net.minecraft.src.forge;
|
|||
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.src.Entity;
|
||||
import net.minecraft.src.EntityTracker;
|
||||
import net.minecraft.src.*;
|
||||
import net.minecraft.src.forge.packets.PacketModList;
|
||||
|
||||
public class ForgeHooksServer
|
||||
{
|
||||
|
@ -26,6 +26,12 @@ public class ForgeHooksServer
|
|||
return false;
|
||||
}
|
||||
|
||||
public static void sendModListRequest(NetworkManager net)
|
||||
{
|
||||
PacketModList pkt = new PacketModList(true);
|
||||
((NetServerHandler)net.getNetHandler()).sendPacket(pkt.getPacket());
|
||||
}
|
||||
|
||||
|
||||
private static boolean hasInit = false;
|
||||
public static void init()
|
||||
|
|
|
@ -1,11 +1,143 @@
|
|||
package net.minecraft.src.forge;
|
||||
|
||||
import net.minecraft.src.NetworkManager;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.src.*;
|
||||
import net.minecraft.src.forge.packets.*;
|
||||
|
||||
public class PacketHandlerServer implements IPacketHandler
|
||||
{
|
||||
@Override
|
||||
public void onPacketData(NetworkManager network, String channel, byte[] data)
|
||||
public void onPacketData(NetworkManager network, String channel, byte[] bytes)
|
||||
{
|
||||
NetServerHandler net = (NetServerHandler)network.getNetHandler();
|
||||
DataInputStream data = new DataInputStream(new ByteArrayInputStream(bytes));
|
||||
ForgePacket pkt = null;
|
||||
|
||||
try
|
||||
{
|
||||
int packetID = data.read();
|
||||
switch(packetID)
|
||||
{
|
||||
case ForgePacket.MODLIST:
|
||||
pkt = new PacketModList(true);
|
||||
pkt.readData(data);
|
||||
onModListResponse(net, (PacketModList)pkt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
ModLoader.getLogger().log(Level.SEVERE, "Exception in PacketHandlerServer.onPacketData", e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void onModListResponse(NetServerHandler net, PacketModList pkt) throws IOException
|
||||
{
|
||||
if (pkt.Length < 0)
|
||||
{
|
||||
net.kickPlayer("Invalid mod list response, Size: " + pkt.Length);
|
||||
return;
|
||||
}
|
||||
if (pkt.Mods.length == 0)
|
||||
{
|
||||
ModLoader.getLogger().log(Level.INFO, net.getUsername() + " joined with no mods");
|
||||
}
|
||||
else
|
||||
{
|
||||
ModLoader.getLogger().log(Level.INFO, net.getUsername() + " joined with: " + Arrays.toString(pkt.Mods).replaceAll("mod_", ""));
|
||||
}
|
||||
|
||||
//TODO: Write a 'banned mods' system and do the checks here
|
||||
|
||||
NetworkMod[] serverMods = MinecraftForge.getNetworkMods();
|
||||
ArrayList<NetworkMod> missing = new ArrayList<NetworkMod>();
|
||||
for (NetworkMod mod : serverMods)
|
||||
{
|
||||
if (!mod.clientSideRequired())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
boolean found = true;
|
||||
for (String modName : pkt.Mods)
|
||||
{
|
||||
if (modName.equals(mod.toString()))
|
||||
{
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
missing.add(mod);
|
||||
}
|
||||
}
|
||||
if (missing.size() > 0)
|
||||
{
|
||||
doMissingMods(net, missing);
|
||||
}
|
||||
else
|
||||
{
|
||||
sendModIDs(net, serverMods);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the user a list of mods they are missing and then disconnects them
|
||||
* @param net The network handler
|
||||
*/
|
||||
private void doMissingMods(NetServerHandler net, ArrayList<NetworkMod> list)
|
||||
{
|
||||
PacketMissingMods pkt = new PacketMissingMods(true);
|
||||
pkt.Mods = new String[list.size()];
|
||||
int x = 0;
|
||||
for(NetworkMod mod : list)
|
||||
{
|
||||
pkt.Mods[x++] = mod.toString();
|
||||
}
|
||||
net.sendPacket(pkt.getPacket());
|
||||
disconnectUser(net);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends a list of mod id mappings to the client.
|
||||
* Only mod ID's are sent, not item or blocks.
|
||||
*
|
||||
* @param net The network handler
|
||||
* @param list A list of network mods
|
||||
*/
|
||||
private void sendModIDs(NetServerHandler net, NetworkMod[] list)
|
||||
{
|
||||
PacketModIDs pkt = new PacketModIDs();
|
||||
for (NetworkMod mod : list)
|
||||
{
|
||||
pkt.Mods.put(MinecraftForge.getModID(mod), mod.toString());
|
||||
}
|
||||
net.sendPacket(pkt.getPacket());
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects the player just like kicking them, just without the kick message.
|
||||
* @param net The network handler
|
||||
*/
|
||||
private void disconnectUser(NetServerHandler net)
|
||||
{
|
||||
MinecraftServer mc = ModLoader.getMinecraftServerInstance();
|
||||
net.getPlayerEntity().func_30002_A();
|
||||
net.netManager.serverShutdown();
|
||||
mc.configManager.sendPacketToAllPlayers(new Packet3Chat("\247e" + net.getUsername() + " left the game."));
|
||||
mc.configManager.playerLoggedOut(net.getPlayerEntity());
|
||||
net.connectionClosed = true;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue