diff --git a/.gitignore b/.gitignore
index cf71df70..960877d2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+/DebugTools/MinecraftClientProxy.suo
+/DebugTools/MinecraftClientProxy.v11.suo
/MinecraftClient.v11.suo
/MinecraftClient.suo
/MinecraftClientGUI.v11.suo
diff --git a/MinecraftClient/ChatBots/AutoAttack.cs b/MinecraftClient/ChatBots/AutoAttack.cs
index 49390bd9..1f18f245 100644
--- a/MinecraftClient/ChatBots/AutoAttack.cs
+++ b/MinecraftClient/ChatBots/AutoAttack.cs
@@ -24,8 +24,8 @@ namespace MinecraftClient.ChatBots
{
if (!GetEntityHandlingEnabled())
{
- ConsoleIO.WriteLine("[AutoAttack] Entity Handling is not enabled in the config file!");
- ConsoleIO.WriteLine("[AutoAttack] This bot will be unloaded.");
+ LogToConsole("Entity Handling is not enabled in the config file!");
+ LogToConsole("This bot will be unloaded.");
UnloadBot();
}
}
diff --git a/MinecraftClient/ChatBots/AutoFishing.cs b/MinecraftClient/ChatBots/AutoFishing.cs
index 7fb1f4ba..92d22165 100644
--- a/MinecraftClient/ChatBots/AutoFishing.cs
+++ b/MinecraftClient/ChatBots/AutoFishing.cs
@@ -26,8 +26,8 @@ namespace MinecraftClient.ChatBots
{
if (!GetEntityHandlingEnabled())
{
- ConsoleIO.WriteLine("[AutoFishing] Entity Handling is not enabled in the config file!");
- ConsoleIO.WriteLine("[AutoFishing] This bot will be unloaded.");
+ LogToConsole("Entity Handling is not enabled in the config file!");
+ LogToConsole("This bot will be unloaded.");
UnloadBot();
}
inventoryEnabled = GetInventoryEnabled();
@@ -39,7 +39,7 @@ namespace MinecraftClient.ChatBots
{
if (GetCurrentLocation().Distance(entity.Location) < 2 && !isFishing)
{
- ConsoleIO.WriteLine("Threw a fishing rod");
+ LogToConsole("Threw a fishing rod");
fishingRod = entity;
LastPos = entity.Location;
isFishing = true;
@@ -93,14 +93,14 @@ namespace MinecraftClient.ChatBots
///
public void OnCaughtFish()
{
- ConsoleIO.WriteLine(GetTimestamp()+": Caught a fish!");
+ LogToConsole(GetTimestamp() + ": Caught a fish!");
// retract fishing rod
UseItemOnHand();
if (inventoryEnabled)
{
if (!hasFishingRod())
{
- ConsoleIO.WriteLine(GetTimestamp() + ": No Fishing Rod on hand. Maybe broken?");
+ LogToConsole(GetTimestamp() + ": No Fishing Rod on hand. Maybe broken?");
return;
}
}
diff --git a/MinecraftClient/ConsoleIO.cs b/MinecraftClient/ConsoleIO.cs
index 2ed377d6..fe57fd63 100644
--- a/MinecraftClient/ConsoleIO.cs
+++ b/MinecraftClient/ConsoleIO.cs
@@ -384,8 +384,11 @@ namespace MinecraftClient
/// Write a prefixed log line. Prefix is set in LogPrefix.
///
/// Text of the log line
- public static void WriteLogLine(string text)
+ /// Allow line breaks
+ public static void WriteLogLine(string text, bool acceptnewlines = true)
{
+ if (!acceptnewlines)
+ text = text.Replace('\n', ' ');
WriteLineFormatted(LogPrefix + text);
}
diff --git a/MinecraftClient/McTcpClient.cs b/MinecraftClient/McTcpClient.cs
index f4596f5f..67f29360 100644
--- a/MinecraftClient/McTcpClient.cs
+++ b/MinecraftClient/McTcpClient.cs
@@ -11,7 +11,6 @@ using MinecraftClient.Proxy;
using MinecraftClient.Protocol.Handlers.Forge;
using MinecraftClient.Mapping;
using MinecraftClient.Inventory;
-using System.Threading.Tasks;
namespace MinecraftClient
{
@@ -56,6 +55,7 @@ namespace MinecraftClient
private string sessionid;
private DateTime lastKeepAlive;
private object lastKeepAliveLock = new object();
+ private int respawnTicks = 0;
private int playerEntityID;
// not really understand the Inventory Class
@@ -279,7 +279,7 @@ namespace MinecraftClient
}
else if (response_msg.Length > 0)
{
- ConsoleIO.WriteLineFormatted("§8MCC: " + response_msg);
+ ConsoleIO.WriteLogLine(response_msg);
}
}
else SendText(text);
@@ -342,7 +342,7 @@ namespace MinecraftClient
}
catch (Exception e)
{
- ConsoleIO.WriteLine(e.Message);
+ ConsoleIO.WriteLogLine(e.Message);
}
}
}
@@ -756,7 +756,7 @@ namespace MinecraftClient
ConsoleIO.WriteLineFormatted(text, true);
if (Settings.DisplayChatLinks)
foreach (string link in links)
- ConsoleIO.WriteLineFormatted("§8MCC: Link: " + link, false);
+ ConsoleIO.WriteLogLine("Link: " + link, false);
foreach (ChatBot bot in bots.ToArray())
{
try
@@ -769,7 +769,7 @@ namespace MinecraftClient
{
if (!(e is ThreadAbortException))
{
- ConsoleIO.WriteLineFormatted("§8GetText: Got error from " + bot.ToString() + ": " + e.ToString());
+ ConsoleIO.WriteLogLine("GetText: Got error from " + bot.ToString() + ": " + e.ToString());
}
else throw; //ThreadAbortException should not be caught
}
@@ -904,7 +904,7 @@ namespace MinecraftClient
{
if (!(e is ThreadAbortException))
{
- ConsoleIO.WriteLineFormatted("§8Update: Got error from " + bot.ToString() + ": " + e.ToString());
+ ConsoleIO.WriteLogLine("Update: Got error from " + bot.ToString() + ": " + e.ToString());
}
else throw; //ThreadAbortException should not be caught
}
@@ -941,6 +941,13 @@ namespace MinecraftClient
pitch = null;
}
}
+
+ if (Settings.AutoRespawn && respawnTicks > 0)
+ {
+ respawnTicks--;
+ if (respawnTicks == 0)
+ SendRespawnPacket();
+ }
}
///
@@ -1361,7 +1368,8 @@ namespace MinecraftClient
public bool PlaceBlock(Location location)
{
//WORK IN PROGRESS. MAY NOT WORK YET
- ConsoleIO.WriteLine(location.ToString());
+ if (Settings.DebugMessages)
+ ConsoleIO.WriteLogLine(location.ToString());
return handler.SendPlayerBlockPlacement(0, location, 1, 0.5f, 0.5f, 0.5f, false);
}
@@ -1388,18 +1396,16 @@ namespace MinecraftClient
/// Player current health
public void OnUpdateHealth(float health)
{
- if (Settings.AutoRespawn)
+ if (health <= 0)
{
- if (health <= 0)
+ if (Settings.AutoRespawn)
{
- ConsoleIO.WriteLine("Client player dead.");
- ConsoleIO.WriteLine("Respawn after 1 second...");
- Task.Factory.StartNew(delegate
- {
- // wait before respawn
- Thread.Sleep(1000);
- SendRespawnPacket();
- });
+ ConsoleIO.WriteLogLine("You are dead. Automatically respawning after 1 second.");
+ respawnTicks = 10;
+ }
+ else
+ {
+ ConsoleIO.WriteLogLine("You are dead. Type /respawn to respawn.");
}
}
}
diff --git a/MinecraftClient/Protocol/Handlers/Protocol16.cs b/MinecraftClient/Protocol/Handlers/Protocol16.cs
index 30f83fb2..43fbd6a1 100644
--- a/MinecraftClient/Protocol/Handlers/Protocol16.cs
+++ b/MinecraftClient/Protocol/Handlers/Protocol16.cs
@@ -41,6 +41,18 @@ namespace MinecraftClient.Protocol.Handlers
ConsoleIO.WriteLineFormatted("§8Terrain & Movements currently not handled for that MC version.");
Handler.SetTerrainEnabled(false);
}
+
+ if (handler.GetInventoryEnabled())
+ {
+ ConsoleIO.WriteLineFormatted("§8Inventories are currently not handled for that MC version.");
+ handler.SetInventoryEnabled(false);
+ }
+
+ if (handler.GetEntityHandlingEnabled())
+ {
+ ConsoleIO.WriteLineFormatted("§8Entities are currently not handled for that MC version.");
+ handler.SetEntityHandlingEnabled(false);
+ }
}
private Protocol16Handler(TcpClient Client)
@@ -155,7 +167,7 @@ namespace MinecraftClient.Protocol.Handlers
case 0x84: readData(11); nbr = readNextShort(); if (nbr > 0) { readData(nbr); } break;
case 0x85: if (protocolversion >= 74) { readData(13); } break;
case 0xC8:
- if (readNextInt() == 2022) { ConsoleIO.WriteLineFormatted("§MCC: You are dead. Type /reco to respawn & reconnect."); }
+ if (readNextInt() == 2022) { ConsoleIO.WriteLogLine("You are dead. Type /respawn to respawn."); }
if (protocolversion >= 72) { readData(4); } else readData(1);
break;
case 0xC9:
diff --git a/MinecraftClient/config/Modules/VkMessager.cs b/MinecraftClient/config/Modules/VkMessager.cs
new file mode 100644
index 00000000..9e801089
--- /dev/null
+++ b/MinecraftClient/config/Modules/VkMessager.cs
@@ -0,0 +1,168 @@
+//MCCScript 1.0
+//using System.Threading.Tasks;
+
+//==== CONFIG START ====
+string vkToken = "";
+string chatId = "";
+string botCommunityId = "";
+//==== CONFIG END ====
+
+MCC.LoadBot(new VkMessager(vkToken, chatId, botCommunityId));
+
+//MCCScript Extensions
+
+///
+/// This bot forwarding messages between Minecraft and VKonrakte chats.
+/// Shares only messages that starts with dot ("."). Example: .Hello!
+/// Also, send message to VK when any player joins or leaves.
+///
+/// Needs:
+/// - VK Community token (also LongPool API with NewMessageEvent, api >= 5.80),
+/// - VK ChatId (typically 2000000001, etc.)
+/// - Bot's CommunityId
+///
+public class VkMessager : ChatBot
+{
+ private VkLongPoolClient VkLongPoolClient { get; set; }
+ private readonly string ChatId;
+
+ ///
+ /// This bot forwarding messages between Minecraft and VKonrakte chats.
+ /// Shares only messages that starts with dot ("."). Example: .Hello!
+ /// Also, send message to VK when any player joins or leaves.
+ ///
+ /// VK Community token
+ /// VK ChatId
+ /// Bot's CommunityId
+ public VkMessager(string vkToken, string chatId, string botCommunityId)
+ {
+ VkLongPoolClient = new VkLongPoolClient(vkToken, botCommunityId, ProcessMsgFromVk);
+ ChatId = chatId;
+ }
+
+ public override void GetText(string text)
+ {
+ text = GetVerbatim(text);
+ string sender = "";
+ string message = "";
+
+ if (IsChatMessage(text, ref message, ref sender))
+ {
+ ProcessMsgFromMinecraft(sender, message);
+ }
+ else if (IsPrivateMessage(text, ref message, ref sender))
+ {
+ ProcessMsgFromMinecraft(sender, message);
+ }
+ else
+ {
+ ProcessMsgFromMinecraft("Server", text);
+ }
+ }
+
+ private void ProcessMsgFromVk(string senderId, string text)
+ {
+ if (!text.StartsWith(".")) return;
+
+ SendText("[VK " + senderId.Substring(0, 2) + "]: " + text.TrimStart('.'));
+ }
+
+ private void ProcessMsgFromMinecraft(string senderName, string text)
+ {
+ if (!text.StartsWith(".") && !text.Contains("left") && !text.Contains("joined")) return;
+ if (text.Contains("[VK")) return; // loop protection
+
+ VkLongPoolClient.SendMessage(ChatId, String.Format("[MC {0}]\r\n{1}", senderName, text.TrimStart('.')));
+ }
+}
+
+///
+/// Client for VK Community (bot) LongPool API.
+/// Also can send messages.
+///
+internal class VkLongPoolClient
+{
+ public VkLongPoolClient(string token, string botCommunityId, Action onMessageReceivedCallback, IWebProxy webProxy = null)
+ {
+ Token = token;
+ BotCommunityId = botCommunityId;
+ OnMessageReceivedCallback = onMessageReceivedCallback;
+ ReceiverWebClient = new WebClient() { Proxy = webProxy, Encoding = Encoding.UTF8 };
+ SenderWebClient = new WebClient() { Proxy = webProxy, Encoding = Encoding.UTF8 };
+
+ Init();
+ StartLongPoolAsync();
+ }
+
+ private WebClient ReceiverWebClient { get; set; }
+ private WebClient SenderWebClient { get; set; }
+ private string Token { get; set; }
+ private string LastTs { get; set; }
+ private string Server { get; set; }
+ private string Key { get; set; }
+ private Action OnMessageReceivedCallback { get; set; }
+ private string BotCommunityId { get; set; }
+
+ private void Init()
+ {
+ var jsonResult = CallVkMethod("groups.getLongPollServer", "group_id=" + BotCommunityId);
+ var data = Json.ParseJson(jsonResult);
+
+ Key = data.Properties["response"].Properties["key"].StringValue;
+ Server = data.Properties["response"].Properties["server"].StringValue;
+ LastTs = data.Properties["response"].Properties["ts"].StringValue;
+ }
+
+ public void SendMessage(string chatId, string text)
+ {
+ CallVkMethod("messages.send", "peer_id=" + chatId + "&message=" + text);
+ }
+
+ private void StartLongPoolAsync()
+ {
+ var baseUrl = String.Format("{0}?act=a_check&version=2&wait=25&key={1}&ts=", Server, Key);
+ Task.Factory.StartNew(() =>
+ {
+ while (true)
+ {
+ var data = ReceiverWebClient.DownloadString(baseUrl + LastTs);
+ var messages = ProcessResponse(data);
+
+ foreach (var message in messages)
+ {
+ OnMessageReceivedCallback(message.Item1, message.Item2);
+ }
+ }
+ });
+ }
+
+ private IEnumerable> ProcessResponse(string jsonData)
+ {
+ var data = Json.ParseJson(jsonData);
+ LastTs = data.Properties["ts"].StringValue;
+
+ var updates = data.Properties["updates"].DataArray;
+ var messages = new List>();
+ foreach (var str in updates)
+ {
+ if (str.Properties["type"].StringValue != "message_new") continue;
+
+ var msgData = str.Properties["object"].Properties;
+
+ var userId = msgData["from_id"].StringValue;
+ var msgText = msgData["text"].StringValue;
+
+ messages.Add(new Tuple(userId, msgText));
+ }
+
+ return messages;
+ }
+
+ private string CallVkMethod(string methodName, string data)
+ {
+ var url = String.Format("https://api.vk.com/method/{0}?v=5.80&access_token={1}&{2}", methodName, Token, data);
+ var jsonResult = SenderWebClient.DownloadString(url);
+
+ return jsonResult;
+ }
+}
\ No newline at end of file