Closed ReOp14 closed 8 years ago
Hello,
You'd need to build a ChatBot.
As a variable it it you could use a HashSet
Then on detection of "joined game" messages, test if the player was already seen. Of course, that does not handle UUID so changing names would trigger the welcome action again.
Alright so I need to build a chat bot, im really still new to scripts, but this is different. May I have some help with Chat Bots? I can't seem to find any things about HashSet examples in your ChatBots.
Here is the Chat Syntax for when someone joins:
Join> ReOp
Join> (?!.*AntzBot)([a-zA-Z0-9_]+)$
It is not often that someone changes their name, so im not very worried about UUIDs. I also found something about grabbing from a file in HangmanGame.cs (string chooseword)
Also Mineplex moderators are telling me not to use bots, even though its not listed on the rules, so sorta mad.
Don't know how you are writing your C# scripts but for developing ChatBots I'd recommend loading the whole Minecraft Console Client (Indev
branch) project in Visual Studio (If you don't have it, Visual C# 2010 or greater is free) and head to ChatBot.cs.
Regarding HashSets, as other classes, when you do not know how to use it, I'd suggest declaring it eg by adding a variable eg private HashSet<string> seenPlayers = new HashSet<string>();
then in a method such as GetText()
try using the hash set, eg type seenPlayers.
and Visual Studio will suggests all the available methods as soon as you type the dot.
Alternatively you can read MSDN documentation: HashSet(T).
EDIT: Regarding moderation, I'd suggest to avoid making annoying/spammy bots. Even on my own server I usually refrain from using the Hangman bot. Although calculator is useful, that increases chat load. Maybe allow calculations by PM instead?
Okay, this is quite a difficult task. I already have Visual Studio working. I see there is already TestBot.cs in the ChatBots folder and im using this as an example and a test. I am also not sure how to enable TestBot, but I tried putting
[TestBot]
enabled=true
in the INI file at the bottom but no luck with that.
Regarding that, I tried adding this using Visual Studio, a copy of TestBot but with a few changes.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MinecraftClient.ChatBots
{
/// <summary>
/// Example of message receiving.
/// </summary>
public class TestJoin : ChatBot
{
HashSet<string> seenPlayers = new HashSet<string>();
public override void GetText(string text)
{
string message = "";
string username = "";
text = GetVerbatim(text);
seenPlayers.GetHashCode;
if (IsPrivateMessage(text, ref message, ref username))
{
ConsoleIO.WriteLine("Bot: " + username + " told me : " + message);
}
else if (IsChatMessage(text, ref message, ref username))
{
ConsoleIO.WriteLine("ReOp: " + username + " said : " + message);
}
}
}
}
Obviously I can't test if this works if I can't enable TestBot, but I also don't know what/how to setup seenPlayers.
. And how do I compile the code back into the "normal folder" with the exe, because you can't just put the code into a file ChatBot.cs because its not a script, but it is a ChatBot. (It would also say that you need to put "//MCCScript 1.0" at the top of the file.)
I really need some help making the ChatBot, although I am still really really new to this.
Try looking at sample-script-with-chatbot.cs, it gives an example.
So for instance, you could write a script like this to register a chatbot:
//MCCScript 1.0
MCC.LoadBot(new TestJoin());
//MCCScript Extensions
class TestJoin : ChatBot
{
HashSet<string> seenPlayers = new HashSet<string>();
public override void GetText(string text)
{
string message = "";
string username = "";
text = GetVerbatim(text);
//seenPlayers.GetHashCode;
if (IsPrivateMessage(text, ref message, ref username))
{
ConsoleIO.WriteLine("Bot: " + username + " told me : " + message);
}
else if (IsChatMessage(text, ref message, ref username))
{
ConsoleIO.WriteLine("ReOp: " + username + " said : " + message);
}
}
}
Please fully read comments in ChatBot.cs, it explains how to load and debug your bot. Once finished, you can export it in a script as @Pokechu22 says above.
Hey im having a problem with the chat bot I have been making.
//MCCScript 1.0
MCC.LoadBot(new TestJoin());
//MCCScript Extensions
class TestJoin : ChatBot
{
private HashSet<string> seenPlayers = new HashSet<string>();
public override void GetText(string text)
{
string message = "";
string username = "";
text = GetVerbatim(text);
if (message == Join> )
{
SendText{"Welcome to the MPS for the first time" + seenPlayers + "!"};
}
}
}
It doesn't work at all and just gives bracket error. But when it does work, it doesn't detect when someone joins and I have no idea how HashSet even works. I did notice that there was LoadDistinctEntriesFromFile in ChatBot.cs. Can you please fix the whole script? I have been trying to find a solution for 3 hours with no luck.
Please use Visual Studio. It underlines your code for syntax errors and facilitates debugging. So do NOT embed your ChatBot into a script file until it is finished and ready to use.
Quote from ChatBot.cs (Indev branch, not master):
Welcome to the Bot API file ! The virtual class "ChatBot" contains anything you need for creating chat bots Inherit from this class while adding your bot class to the "ChatBots" folder. Override the methods you want for handling events: Initialize, Update, GetText.
For testing your bot you can add it in McTcpClient.cs (see comment at line ~119). Your bot will be loaded everytime MCC is started so that you can test/debug.
Once your bot is fully written and tested, you can export it a standalone script. This way it can be loaded in newer MCC builds, without modifying MCC itself. See config/sample-script-with-chatbot.cs for a ChatBot script example.
In McTcpClient.cs:
if (Settings.AutoRespond_Enabled) { BotLoad(/* ... */); }
//Add your ChatBot here by uncommenting and adapting
//BotLoad(new ChatBots.YourBot());
Then you can compile and debug your bot from Visual Studio, that is MUCH EASIER. The bot gets loaded automatically upon joining (for testing purposes).
This line:
if (message == Join> )
Contains two mistakes:
"Join>"
Join>
So use instead:if (message.StartsWith("Join>"))
The seenplayers
hashset must be loaded on bot load from a file, the LoadDistinctEntriesFromFile
method is indeed suited for that. For writing you can convert to a string array and write everything:
File.WriteAllLines("seenplayers.txt", seenplayers.ToArray());
I can't get the script to do anything when I test it.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace MinecraftClient.ChatBots
{
/// <summary>
/// Example of message receiving.
/// </summary>
class TestJoin : ChatBot
{
private HashSet<string> SeenPlayers = new HashSet<string>();
public override void GetText(string text)
{
string message = "";
string username = "";
text = GetVerbatim(text);
if (message.StartsWith("Join>"))
{
LogToConsole("test");
File.WriteAllLines("seenplayers.txt", SeenPlayers.ToArray());
SendText("Welcome to the server for the first time " + username);
}
}
}
}
There is no errors or anything (in visual studio), its just I'm not sure how to make the script work correctly. I tried joining the game a few times, Join> ReOp
and the LogToConsole does not log "test". When I do put LogToConsole without the If statement, it will log "test".
I also tried to see whether the File.WriteAllLines("seenplayers.txt", SeenPlayers.ToArray());
worked without If, I put it under the GetVerbatim line and it did nothing. I also manually created a seenplayers.txt for it also.
I don't have a lot of time today because im heading over to Anaheim for MineCon this weekend, so apologizes if I missed something obvious.
Are you sure you added BotLoad(new ChatBots.TestJoin());
at the right place in McTcpClient.cs
?
Also don't forget to put the newly seen username in the hashset with SeenPlayers.Add(/* the name */);
And load the hashset on bot load, of course ;)
Alright, back from Minecon. I put the code and put it in its own file (Join.cs) under ChatBots folder in Visual Studio.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace MinecraftClient.ChatBots
{
/// <summary>
/// Example of message receiving.
/// </summary>
class Join : ChatBot
{
private HashSet<string> SeenPlayers = new HashSet<string>();
public override void GetText(string text)
{
string message = "";
string username = "";
text = GetVerbatim(text);
File.WriteAllLines("seenplayers.txt", SeenPlayers.ToArray());
if (message.StartsWith("Join>"))
{
LogToConsole("test");
SeenPlayers.Add(username);
File.WriteAllLines("seenplayers.txt", SeenPlayers.ToArray());
SendText("Welcome to the server for the first time " + username);
}
}
}
}
And I also put if (Settings.AutoRespond_Enabled) { BotLoad(new ChatBots.Join()); }
in McTcpClient.cs (in the correct location) (before I tried just /script on startup) and I compiled using "f5" and found the exe file and used it, but I have not gotten it to work at all and no text of usernames in seenplayers.txt
Not sure what is going on. I think the script does not start perhaps?
As you put in your condition, the bot will load only if AutoRespond is enabled. The 'if' part is not needed, just leave the BotLoad() instruction alone, not wrapped in a condition ^^
... Was Minecon great this year? :)
I removed the condition into: BotLoad(new ChatBots.Join());
there was no errors in visual studio. I tested a few times at after joining Join> ReOp
it would not log my name in SeenPlayers.txt nor respond in anyway at all.
Minecon was pretty good, a ton of little kids but that's alright, there was a band and lots of work done at Minecon this year. I have honestly never watched any of the other Minecons on the live stream so I can't compare it.
Just print everything you get from the server, that's the easiest way to check you are receiving messages:
ConsoleIO.WriteLine("GetText: " + text);
Insert the above as first line in your GetText() method. Alternatively you can use debugging by putting a breakpoint on GetText() (click on the left column on the right line while editing code) but when the breakpoint gets hit, your MCC instance will pause, and the server times out and closes connection if you stay in that paused state for more than 30 seconds. So use either debug prints or Visual Studio debugging depending on what you need ;)
Regarding Minecon, I never went to a Minecon nor watched stream but, well, thanks for your feedback :smile:
I think the problem is that the if (message.StartsWith("Join> "))
is not detecting the message, (I also used this without a space).
I did that GetText thing you said, it repeated everything said in chat. GetText: Join> ReOp
Also, I am not sure how breakpoints work nor how they can help me so I didn't try that.
I also tried using different accounts to see if it was my player name.
string message = "";
string username = "";
text = GetVerbatim(text);
File.WriteAllLines("seenplayers.txt", SeenPlayers.ToArray());
if (message.StartsWith("Join>"))
The script is never assigning the message
variable so it stays empty.
Maybe you were intending either if (text.StartsWith
or message = GetVerbatim(text)
?
Using this bot code I found a few things:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace MinecraftClient.ChatBots
{
/// <summary>
/// Example of message receiving.
/// </summary>
class Join : ChatBot
{
private HashSet<string> SeenPlayers = new HashSet<string>();
public override void GetText(string text)
{
string message = "";
string username = "";
message = GetVerbatim(text);
File.WriteAllLines("SeenPlayers.txt", SeenPlayers.ToArray());
if (message.StartsWith("Join> "))
{
ConsoleIO.WriteLine("GetText: " + text);
ConsoleIO.WriteLine("UserName: " + username);
SeenPlayers.Add(username);
SeenPlayers.Add(text);
File.WriteAllLines("SeenPlayers.txt", SeenPlayers.ToArray());
SendText("Welcome to the Server for the first time " + username + "!");
}
}
}
}
It does detect with "Join> ", Thanks easy fix. Although, while testing it says:
Welcome to the Server for the first time !
in Minecraft chat.
Although in the GetText, there is a problem. (Weird characters)
GetText: 88Join> r77ReOpr
Also this is logged into the Seen Players with the same weird characters.
About the SeenPlayers.Add(username);
it says no text at all and
makes a blank line in the SeenPlayers.txt file.
I am also still not allowed to use "bots" on Mineplex, not because it spams, it just they don't want bots. Although not posted on the rules, they still come on the server and tell me not to use them. I tried talking to the Mineplex staff team at Minecon, but they also said no.
username
is never assigned, that's why it stays empty and empty lines are added to your file. Maybe you'd like to perform username = message.Substring(6);
to extract username from the message.
Weird characters are §c
color codes. These can be stripped with GetVerbatim()
already in your code.
Regarding bots on the server you are playing on, I can't really help on that side, sorry :sweat_smile:
Hey, got that to work luckily. I still need to make sure it only does it once still. I tried using LoadDistinctEntriesFromFile
but I couldn't find how to use it correctly.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace MinecraftClient.ChatBots
{
/// <summary>
/// Example of message receiving.
/// </summary>
class Join : ChatBot
{
private HashSet<string> SeenPlayers = new HashSet<string>();
public override void GetText(string text)
{
string message = "";
string username = "";
message = GetVerbatim(text);
File.WriteAllLines("SeenPlayers.txt", SeenPlayers.ToArray());
if (message.StartsWith("Join> "))
{
username = message.Substring(6);
text = GetVerbatim(text);
ConsoleIO.WriteLine("UserName: " + username);
SeenPlayers.Add(username);
File.WriteAllLines("SeenPlayers.txt", SeenPlayers.ToArray());
SendText("Welcome to the Server for the first time " + username + "!");
}
}
}
}
How can I make it only welcome the player if they only joined for the first time. How to grab and check the string from SeenPlayers.txt?
public Join()
{
for (string name in LoadDistinctEntriesFromFile("SeenPlayers.txt"))
SeenPlayers.Add(name);
}
Got pretty far in concept but It keeps bypassing my if statement. I am not sure how to make the code colored but It would help a lot I think if I shared an image also. (And im getting that weird warning, not sure why that is) or
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace MinecraftClient.ChatBots
{
/// <summary>
/// Example of message receiving.
/// </summary>
class Join : ChatBot
{
private string name;
private HashSet<string> SeenPlayers = new HashSet<string>();
public override void GetText(string text)
{
string message = "";
string username = "";
message = GetVerbatim(text);
foreach (string name in LoadDistinctEntriesFromFile("SeenPlayers.txt")) //Checks to see if username is in SeenPlayers.txt
{
SeenPlayers.Add(name);
}
if (message.StartsWith("Join> ")) //If message is a player joining the server
{
username = message.Substring(6);
text = GetVerbatim(text);
ConsoleIO.WriteLine("Username: " + username);
if (username == name) //Checks to see if username is in SeenPlayers.txt
{
ConsoleIO.WriteLine("Join: The username " + username + " has already joined before.");
}
else //If username is not in SeenPlayers.txt
{
ConsoleIO.WriteLine("Join: " + username + " has been logged into SeenPlayers.txt");
SeenPlayers.Add(username);
File.WriteAllLines("SeenPlayers.txt", SeenPlayers.ToArray());
SendText("Welcome to the Server for the first time " + username + "!");
}
}
}
}
}
The problem is that the if statement is NOT true so it goes to the else below it. I also tried replacing else with if (username != name)
but I received the same result. In the SeenPlayers.txt file it does list the name inside it.
AntzBot
ReOp
DeOp
To post colored code on GitHub:
// ````C# <- Or any language name here
// Your code here
// ````
Of course remove the //
on your case, I'm putting them because otherwise GitHub would interpret them.
Regarding your code:
1) Loading the file should happen only once, in the constructor.
Just move it in a separate method called Join()
, see my message above.
2) What is this unused "name" variable? Just remove it and and use SeenPlayers:
if (SeenPlayers.Contains(username))
{
instead of if (username == name)
(name
is always null so obviously that's always false.)
Okay this is very strange. Got it working until I tried restarting it and it forgot everything. Ill try and explain but its hard enough to even think about it. Alright so it welcomes me to the MPS for the first time and I try rejoining and it says:
16:36:56 Join> ReOp
Username: ReOp
Join: The username ReOp has already joined before.
So that's what I was aiming for, but when I restarted AntzBot, it welcomes itself for the first time even though the username is already in the SeenPlayers.txt, but it also deletes ReOp from the bottom of the file but I also noticed lowercase of the usernames which I did not put there. (When I join on ReOp it also says Welcome for the first time)
antzbot
reop
AntzBot
ReOp
My code for Join.cs: (sorry for the 46 lines of spam) (yay colors) EDIT: Visual studio gives an error when I use for, so I use foreach
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace MinecraftClient.ChatBots
{
/// <summary>
/// Example of message receiving.
/// </summary>
class Join : ChatBot
{
private string name;
private HashSet<string> SeenPlayers = new HashSet<string>();
public Join()
{
foreach (string username in LoadDistinctEntriesFromFile("SeenPlayers.txt"))
SeenPlayers.Add(username);
}
public override void GetText(string text)
{
string message = "";
string username = "";
message = GetVerbatim(text);
if (message.StartsWith("Join> ")) //If message is a player joining the server
{
username = message.Substring(6);
text = GetVerbatim(text);
ConsoleIO.WriteLine("Username: " + username);
if (SeenPlayers.Contains(username))
{
ConsoleIO.WriteLine("Join: The username " + username + " has already joined before.");
}
else //If username is not in SeenPlayers.txt
{
ConsoleIO.WriteLine("Join: " + username + " has been logged into SeenPlayers.txt");
SeenPlayers.Add(username);
File.WriteAllLines("SeenPlayers.txt", SeenPlayers.ToArray());
SendText("Welcome to the Server for the first time " + username + "!");
}
}
}
}
}
Oh, that's because LoadDistinctEntries
will provide lowercase usernames: Source.
You can use username = message.Substring(6).ToLower();
to use lowercase usernames too.
This way everything is lowercase and names are properly saved and compared.
Thanks got it all to work! Can't use it because of Mineplex's rules, but I'm having tons of enjoyment making these. Your .ToLower() fixed it, I also had to add things so the message printed in chat was also not lowercase. All is well.
So I had a cool idea to add to my bot but its difficult in concept. Is it possible to make it so when someone joins the game for The First Time it says "Player joined for the first time! Welcome!"?
Like when someone joins, it puts their name into a text file and if they havn't been logged into the text file before it would send the welcome message. Kinda like the Hangman game word file?
I understand if its impossible, but it would still be pretty cool!