Initial Commit
Initial commit of project.
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
package commands;
|
||||
|
||||
import core.Command;
|
||||
import dataStructures.*;
|
||||
|
||||
public class CommandBeansShow extends Command
|
||||
{
|
||||
public CommandBeansShow(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Displays how many beans you have"; };
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
String beans = "You have " + user.GetBeans() + " beans!";
|
||||
res.Call(beans);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package commands;
|
||||
|
||||
import core.Command;
|
||||
import dataStructures.*;
|
||||
|
||||
public class CommandBetBeans extends Command
|
||||
{
|
||||
public CommandBetBeans(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Allows you to bet your beans, set your amount after the command! Warning: House always wins!"
|
||||
+ "\nSets of 3 will get 5x, 4 will get 10x, and 5 will get 1000x"; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
String call = "";
|
||||
int bet = 0;
|
||||
int win = 0;
|
||||
try
|
||||
{
|
||||
bet = Integer.parseInt(input.args);
|
||||
if(bet < 50)
|
||||
{
|
||||
res.Call("Please bet with at least 50 beans!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
res.Call("That's not a valid bet!");
|
||||
return;
|
||||
}
|
||||
|
||||
if(user.GetBeans() < bet)
|
||||
{
|
||||
res.Call("You don't have enough beans!");
|
||||
return;
|
||||
}
|
||||
|
||||
user.ChangeBeans(-bet);
|
||||
int [] slots = getSlots();
|
||||
call += slotString(slots);
|
||||
slots = sort(slots);
|
||||
|
||||
win = getWinning(slots);
|
||||
|
||||
res.Call(call);
|
||||
|
||||
if(win == 0)
|
||||
{
|
||||
res.Call("Sorry, you didn't win, try again!");
|
||||
return;
|
||||
}
|
||||
|
||||
user.ChangeBeans(bet*win);
|
||||
res.Call("You won " + (bet*win) + " beans!");
|
||||
}
|
||||
|
||||
private int getWinning(int [] slots)
|
||||
{
|
||||
int winning = 0;
|
||||
int counter = 1;
|
||||
for(int j = 0; j < slots.length - 1; j++)
|
||||
{
|
||||
if(slots[j] == slots[j+1])
|
||||
counter++;
|
||||
else
|
||||
counter = 1;
|
||||
|
||||
if(counter == 3)
|
||||
winning = 5;
|
||||
|
||||
if(counter == 4)
|
||||
winning = 10;
|
||||
|
||||
if(counter == 5)
|
||||
winning = 1000;
|
||||
}
|
||||
|
||||
return winning;
|
||||
}
|
||||
|
||||
private int[] getSlots()
|
||||
{
|
||||
int[] nums = new int[5];
|
||||
for (int i = 0; i < nums.length; i++)
|
||||
{
|
||||
nums[i] = (int) (Math.random() * 5) + 1;
|
||||
}
|
||||
return nums;
|
||||
}
|
||||
|
||||
private int [] sort(int [] nums)
|
||||
{
|
||||
int [] sorted = new int [nums.length];
|
||||
|
||||
int smallest= Integer.MAX_VALUE;
|
||||
int index = 0;
|
||||
for(int i = 0; i < sorted.length; i++)
|
||||
{
|
||||
for(int j = 0; j < nums.length; j++)
|
||||
{
|
||||
if(nums[j] < smallest)
|
||||
{
|
||||
index = j;
|
||||
smallest = nums[j];
|
||||
}
|
||||
}
|
||||
|
||||
sorted[i] = smallest;
|
||||
smallest = Integer.MAX_VALUE;
|
||||
nums[index] = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
return sorted;
|
||||
}
|
||||
|
||||
private String slotString(int [] slots)
|
||||
{
|
||||
String slotHearts = "";
|
||||
for(int i = 0; i < slots.length; i++)
|
||||
{
|
||||
switch(slots[i])
|
||||
{
|
||||
case 1:
|
||||
slotHearts += ":heart:";
|
||||
break;
|
||||
case 2:
|
||||
slotHearts += ":yellow_heart:";
|
||||
break;
|
||||
case 3:
|
||||
slotHearts += ":green_heart:";
|
||||
break;
|
||||
case 4:
|
||||
slotHearts += ":blue_heart:";
|
||||
break;
|
||||
case 5:
|
||||
slotHearts += ":purple_heart:";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return slotHearts;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package commands;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import core.Command;
|
||||
import dataStructures.*;
|
||||
import utils.ImageUtils;
|
||||
|
||||
public class CommandBlurry extends Command
|
||||
{
|
||||
public CommandBlurry(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Blurs your icon or the icon of a friend you mentioned"; };
|
||||
|
||||
private static Long num = 0l;
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
String name = null;
|
||||
String filename = null;
|
||||
File preProcessed = null;
|
||||
File postProcessed = null;
|
||||
|
||||
synchronized(num)
|
||||
{
|
||||
name = "blurred_" + num + ".png";
|
||||
++num;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
filename = ImageUtils.DownloadFromURL(input.args.split(" ")[0], ".png");
|
||||
preProcessed = new File(filename);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
KittyUser person = user;
|
||||
if(input.mentions != null)
|
||||
person = input.mentions[0];
|
||||
|
||||
filename = ImageUtils.DownloadFromURL(person.avatarID, ".png");
|
||||
if(filename == null)
|
||||
return;
|
||||
}
|
||||
preProcessed = new File(filename);
|
||||
ApplySnap(ImageIO.read(preProcessed), name);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
postProcessed = new File(name);
|
||||
res.CallFile(postProcessed, "png");
|
||||
|
||||
ImageUtils.BlockingFileDelete(preProcessed);
|
||||
ImageUtils.BlockingFileDelete(postProcessed);
|
||||
}
|
||||
|
||||
private static void ApplySnap(BufferedImage image, String name) throws IOException
|
||||
{
|
||||
BufferedImage blurred = ImageUtils.copyImage(image);
|
||||
// Iterate over each column left to right and touch up each pixel
|
||||
for(int i = 0; i < 50; ++i)
|
||||
{
|
||||
for(int x = 1; x < image.getWidth() - 1; ++x)
|
||||
{
|
||||
for(int y = 1; y < image.getHeight() - 1; ++y)
|
||||
{
|
||||
blurred.setRGB(x, y, getColorAvg(image, x, y).getRGB());
|
||||
}
|
||||
}
|
||||
image = ImageUtils.copyImage(blurred);
|
||||
}
|
||||
|
||||
|
||||
File outputfile = new File(name);
|
||||
ImageIO.write(blurred, "png", outputfile);
|
||||
}
|
||||
|
||||
private static Color getColorAvg(BufferedImage image, int x, int y)
|
||||
{
|
||||
Color center = new Color(image.getRGB(x, y), true);
|
||||
Color one = new Color(image.getRGB(x - 1, y), true);
|
||||
Color two = new Color(image.getRGB(x - 1, y - 1), true);
|
||||
Color three = new Color(image.getRGB(x, y - 1), true);
|
||||
Color four = new Color(image.getRGB(x + 1, y - 1), true);
|
||||
Color five = new Color(image.getRGB(x + 1, y), true);
|
||||
Color six = new Color(image.getRGB(x + 1, y + 1), true);
|
||||
Color seven = new Color(image.getRGB(x, y + 1), true);
|
||||
Color eight = new Color(image.getRGB(x -1, y + 1), true);
|
||||
|
||||
int blue = center.getBlue() + one.getBlue() + two.getBlue() + three.getBlue() + four.getBlue() + five.getBlue() + six.getBlue() + seven.getBlue() + eight.getBlue();
|
||||
int red = center.getRed() + one.getRed() + two.getRed() + three.getRed() + four.getRed() + five.getRed() + six.getRed() + seven.getRed() + eight.getRed();
|
||||
int green = center.getGreen() + one.getGreen() + two.getGreen() + three.getGreen() + four.getGreen() + five.getGreen() + six.getGreen() + seven.getGreen() + eight.getGreen();
|
||||
int alpha = center.getAlpha() + one.getAlpha() + two.getAlpha() + three.getAlpha() + four.getAlpha() + five.getAlpha() + six.getAlpha() + seven.getAlpha() + eight.getAlpha();
|
||||
|
||||
blue /= 9;
|
||||
red /= 9;
|
||||
green /= 9;
|
||||
alpha /= 9;
|
||||
|
||||
Color blur = new Color(red, green, blue, alpha);
|
||||
|
||||
return blur;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package commands;
|
||||
|
||||
import core.*;
|
||||
import dataStructures.KittyChannel;
|
||||
import dataStructures.KittyGuild;
|
||||
import dataStructures.KittyRating;
|
||||
import dataStructures.KittyRole;
|
||||
import dataStructures.KittyUser;
|
||||
import dataStructures.Response;
|
||||
import dataStructures.UserInput;
|
||||
import utils.GlobalLog;
|
||||
import utils.LogFilter;
|
||||
|
||||
public class CommandBoop extends Command
|
||||
{
|
||||
public class BoopTracker extends DatabaseTrackedObject
|
||||
{
|
||||
private int boops = 0;
|
||||
|
||||
public BoopTracker() { super("booptracker"); }
|
||||
|
||||
public void ApplyBoop()
|
||||
{
|
||||
++boops;
|
||||
MarkDirty();
|
||||
}
|
||||
|
||||
public int HowMany()
|
||||
{
|
||||
return boops;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String Serialize() { return "" + boops; }
|
||||
|
||||
@Override
|
||||
public void DeSerialzie(String string)
|
||||
{
|
||||
try
|
||||
{
|
||||
boops = Integer.parseInt(string);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
GlobalLog.Warn(LogFilter.Command, "No valid value was found for boops! Starting over at 0!");
|
||||
boops = 0;
|
||||
MarkDirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static BoopTracker boopTracker;
|
||||
|
||||
// Constructor
|
||||
public CommandBoop(KittyRole level, KittyRating rating)
|
||||
{
|
||||
super(level, rating);
|
||||
boopTracker = new BoopTracker();
|
||||
DatabaseManager.instance.Register(boopTracker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Kitty will react with a counter"; }
|
||||
|
||||
// Called when the command is run!
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
if(input.mentions == null)
|
||||
{
|
||||
boopTracker.ApplyBoop();
|
||||
res.Call("Woah! " + user.name + " booped me! That's " + boopTracker.HowMany() + " total!");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(input.mentions.length == 1)
|
||||
{
|
||||
boopTracker.ApplyBoop();
|
||||
res.Call(user.name + " booped " + input.mentions[0].name + "!");
|
||||
return;
|
||||
}
|
||||
String booped = "";
|
||||
for(int i = 0; i < input.mentions.length; i++)
|
||||
{
|
||||
boopTracker.ApplyBoop();
|
||||
if(i < input.mentions.length-1)
|
||||
booped += input.mentions[i].name + ", ";
|
||||
else
|
||||
booped += "and " + input.mentions[i].name;
|
||||
}
|
||||
res.Call(user.name + " booped " + booped + "!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package commands;
|
||||
|
||||
import core.Command;
|
||||
import dataStructures.*;
|
||||
|
||||
public class CommandChangeIndicator extends Command
|
||||
{
|
||||
public CommandChangeIndicator(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Changes the command indicator to any single character. By default, it's '!'. If more than one character is provided, the first one is used!"; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
String arg = input.args.trim();
|
||||
if(arg.length() == 0)
|
||||
{
|
||||
res.Call("Please specify a letter or symbol to use!");
|
||||
return;
|
||||
}
|
||||
|
||||
guild.SetCommandIndicator(arg.substring(0, 1));
|
||||
res.Call("Indicator changed to `" + guild.GetCommandIndicator() +"`!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package commands;
|
||||
|
||||
import core.*;
|
||||
import dataStructures.KittyChannel;
|
||||
import dataStructures.KittyGuild;
|
||||
import dataStructures.KittyRating;
|
||||
import dataStructures.KittyRole;
|
||||
import dataStructures.KittyUser;
|
||||
import dataStructures.Response;
|
||||
import dataStructures.UserInput;
|
||||
|
||||
public class CommandChoose extends Command
|
||||
{
|
||||
public CommandChoose(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "With an input of x,y,z where x y and z are all choices, kitty will choose one"; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
String [] choices = input.args.split(",");
|
||||
if(choices.length == 1)
|
||||
{
|
||||
res.Call("I can't choose from *one* thing!");
|
||||
return;
|
||||
}
|
||||
|
||||
res.Call("I chooooooose" + choices[(int) (Math.random()*choices.length)] + "!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package commands;
|
||||
|
||||
import core.Command;
|
||||
import dataStructures.*;
|
||||
import network.NetworkColiru;
|
||||
|
||||
public class CommandColiru extends Command
|
||||
{
|
||||
NetworkColiru compiler = new NetworkColiru();
|
||||
|
||||
public CommandColiru(KittyRole level, KittyRating rating) { super(level, rating);}
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Will try to compile any c++ code you put in! Supports up to C++14 standard, uses g++."; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
res.Call(compiler.compileCPlus(input.args));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package commands;
|
||||
|
||||
import core.*;
|
||||
import dataStructures.KittyChannel;
|
||||
import dataStructures.KittyGuild;
|
||||
import dataStructures.KittyRating;
|
||||
import dataStructures.KittyRole;
|
||||
import dataStructures.KittyUser;
|
||||
import dataStructures.Response;
|
||||
import dataStructures.UserInput;
|
||||
|
||||
public class CommandDoWork extends Command
|
||||
{
|
||||
// Required constructor
|
||||
public CommandDoWork(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Occupies a core for a few seconds"; }
|
||||
|
||||
// Called when the command is run!
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
@SuppressWarnings("unused")
|
||||
long thispieceofshit = 0;
|
||||
for(int i = 0; i < 200000000 + Math.random() * 30; i ++)
|
||||
{
|
||||
thispieceofshit += Math.log((double)i);
|
||||
}
|
||||
|
||||
res.Call("I finished with my work! :D");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package commands;
|
||||
|
||||
import core.Command;
|
||||
import dataStructures.*;
|
||||
|
||||
public class CommandGiveBeans extends Command
|
||||
{
|
||||
public CommandGiveBeans (KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Gives beans to the mentioned users!"; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
int beans = 0;
|
||||
try {
|
||||
beans = Integer.parseInt(input.args.split(" ")[0]);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
res.Call("That's not a valid number!");
|
||||
return;
|
||||
}
|
||||
|
||||
if(input.mentions == null)
|
||||
{
|
||||
res.Call("You didn't mention anyone!");
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i = 0; i < input.mentions.length; i++)
|
||||
{
|
||||
input.mentions[i].ChangeBeans(beans);
|
||||
res.Call("Gave " + input.mentions[i].name + " " + beans + " beans!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package commands;
|
||||
|
||||
import core.*;
|
||||
import dataStructures.KittyChannel;
|
||||
import dataStructures.KittyGuild;
|
||||
import dataStructures.KittyRating;
|
||||
import dataStructures.KittyRole;
|
||||
import dataStructures.KittyUser;
|
||||
import dataStructures.Response;
|
||||
import dataStructures.UserInput;
|
||||
|
||||
// TODO: Convert this to a per-command help string! This lets us do all sorts of neat stuff,
|
||||
// mostly tho it lets us construct this on the fly or by hand for a specific command!
|
||||
public class CommandHelp extends Command
|
||||
{
|
||||
public CommandHelp(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Lets you look up specific commands, or get a link to a list of all commands."; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
String help = Stats.instance.GetHelpText(input.args);
|
||||
|
||||
if(help == null)
|
||||
{
|
||||
help = "You can get help with a specific command by typing `!help command`!"
|
||||
+ "\nYou can also look at <https://www.rinsnowmew.com/bot/info/#commands>"
|
||||
+ "\nGeneral Commands: `boop, roll, choose, help, info, vote, "
|
||||
+ "results, showpoll, wolfram, cplus, java,"
|
||||
+ "beans, role, bet, yeet`";
|
||||
}
|
||||
else
|
||||
{
|
||||
help = "`" + input.args + "`: " + help;
|
||||
}
|
||||
|
||||
res.Call(help);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package commands;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import core.Command;
|
||||
import core.Stats;
|
||||
import dataStructures.KittyChannel;
|
||||
import dataStructures.KittyGuild;
|
||||
import dataStructures.KittyRating;
|
||||
import dataStructures.KittyRole;
|
||||
import dataStructures.KittyUser;
|
||||
import dataStructures.Response;
|
||||
import dataStructures.UserInput;
|
||||
import utils.GlobalLog;
|
||||
import utils.ImageUtils;
|
||||
|
||||
public class CommandHelpBuilder extends Command {
|
||||
|
||||
public CommandHelpBuilder(KittyRole role, KittyRating rating) {
|
||||
super(role, rating);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Emit help for all commands as formatted HTML"; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
// Holds command groups
|
||||
HashMap<KittyRole, ArrayList<Command>> commandsByRole = new HashMap<KittyRole, ArrayList<Command>>();
|
||||
|
||||
// Populate w/ empty array lists
|
||||
for(int i = 0; i < KittyRole.values().length; ++i)
|
||||
commandsByRole.put(KittyRole.values()[i], new ArrayList<Command>());
|
||||
|
||||
// Sort commands out
|
||||
ArrayList<Command> commands = Stats.instance.GetAllCommands();
|
||||
for(int i = 0; i < commands.size(); ++i)
|
||||
{
|
||||
Command current = commands.get(i);
|
||||
commandsByRole.get(current.RequiredRole()).add(current);
|
||||
}
|
||||
|
||||
// Format outstring and send it back for now
|
||||
String out = "";
|
||||
out += PopulateSection(KittyRole.Admin, commandsByRole, true) + "\n";
|
||||
out += PopulateSection(KittyRole.Mod, commandsByRole, true) + "\n";
|
||||
out += PopulateSection(KittyRole.General, commandsByRole, false) + "\n";
|
||||
|
||||
// Write out file
|
||||
String filename = "buildhelp_out.txt";
|
||||
|
||||
try {
|
||||
PrintWriter writer = new PrintWriter(filename);
|
||||
writer.println(out);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
GlobalLog.Error(e.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
File file = new File(filename);
|
||||
res.CallFile(file, "txt");
|
||||
ImageUtils.BlockingFileDelete(file);
|
||||
}
|
||||
|
||||
// Generates the section for a specific role, optionally adding spacing after for another section
|
||||
private String PopulateSection(KittyRole role, HashMap<KittyRole, ArrayList<Command>> commandsByRole, boolean delimitSection)
|
||||
{
|
||||
// Formatting variables
|
||||
final String headerStart = "<h2>";
|
||||
final String headerEnd = "</h2>\n";
|
||||
final String sectionStart = "<p>\n";
|
||||
final String sectionEnd = "</p>";
|
||||
final String indent = " ";
|
||||
final String leadStart = "<code>";
|
||||
final String leadEnd = "</code>";
|
||||
final String leadFollow = ": ";
|
||||
final String lineDelimiter = "<br/>\n";
|
||||
final String sectionDelimiter = "\n\n";
|
||||
|
||||
String accumulated = "";
|
||||
ArrayList<Command> commands = commandsByRole.get(role);
|
||||
ArrayList<Command> commandsSoFar = new ArrayList<Command>();
|
||||
if(commands.size() > 0)
|
||||
{
|
||||
String roleStr = role.toString();
|
||||
roleStr = roleStr.substring(0, 1).toUpperCase() + roleStr.toLowerCase().substring(1);
|
||||
|
||||
// Section header
|
||||
accumulated += headerStart + roleStr + " commands" + headerEnd;
|
||||
accumulated += sectionStart;
|
||||
|
||||
// Section content
|
||||
for(int i = 0; i < commands.size(); ++i)
|
||||
{
|
||||
accumulated += indent;
|
||||
Command command = commands.get(i);
|
||||
|
||||
// Skip multiples
|
||||
if(commandsSoFar.contains(command))
|
||||
continue;
|
||||
else
|
||||
commandsSoFar.add(command);
|
||||
|
||||
// Write out all the keys and the help text
|
||||
ArrayList<String> keys = command.RegisteredNames();
|
||||
for(int j = 0; j < keys.size(); ++j)
|
||||
{
|
||||
if(j != 0)
|
||||
accumulated += ", ";
|
||||
|
||||
accumulated += leadStart + keys.get(j) + leadEnd;
|
||||
}
|
||||
|
||||
accumulated += leadFollow + commands.get(i).HelpText() + lineDelimiter;;
|
||||
}
|
||||
|
||||
accumulated += sectionEnd;
|
||||
|
||||
// Add spaces after if needed
|
||||
if(delimitSection)
|
||||
accumulated += sectionDelimiter;
|
||||
}
|
||||
|
||||
return accumulated;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package commands;
|
||||
|
||||
import core.Command;
|
||||
import dataStructures.KittyChannel;
|
||||
import dataStructures.KittyGuild;
|
||||
import dataStructures.KittyRating;
|
||||
import dataStructures.KittyRole;
|
||||
import dataStructures.KittyUser;
|
||||
import dataStructures.Response;
|
||||
import dataStructures.UserInput;
|
||||
|
||||
public class CommandInfo extends Command
|
||||
{
|
||||
public CommandInfo(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Provides author info and a link to Kitty's website"; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
String info = "I'm made by `Rin#8904` and `Reverie Wisp#3703`!\n"
|
||||
+ "You can find more info about me along with a Patreon link to support us and GitHub link for filing bugs https://www.rinsnowmew.com/bot/" ;
|
||||
res.Call(info);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package commands;
|
||||
|
||||
import core.Command;
|
||||
import dataStructures.*;
|
||||
import offline.Ref;
|
||||
|
||||
public class CommandInvite extends Command
|
||||
{
|
||||
public CommandInvite(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Provies a direct invite link for KittyBot"; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
res.Call("https://discordapp.com/oauth2/authorize?&client_id="+ Ref.CliID
|
||||
+"&scope=bot&permissions=8");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package commands;
|
||||
|
||||
import core.Command;
|
||||
import dataStructures.*;
|
||||
import network.NetworkJDoodle;
|
||||
|
||||
public class CommandJDoodle extends Command
|
||||
{
|
||||
NetworkJDoodle compiler = new NetworkJDoodle();
|
||||
|
||||
public CommandJDoodle(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Will compile any java code you put in! Supports Java 1.8"; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
res.Call(compiler.compileJava(input.args));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,362 @@
|
||||
package commands;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import core.Command;
|
||||
import dataStructures.KittyChannel;
|
||||
import dataStructures.KittyGuild;
|
||||
import dataStructures.KittyRating;
|
||||
import dataStructures.KittyRole;
|
||||
import dataStructures.KittyUser;
|
||||
import dataStructures.Response;
|
||||
import dataStructures.UserInput;
|
||||
import utils.OptionParser;
|
||||
|
||||
// This command is a port of worldGen command line program by Matthew Cech (https://www.matthewcech.com/)
|
||||
// Permissions were granted for use and modification in this bot.
|
||||
public class CommandMap extends Command
|
||||
{
|
||||
final int MaxWidth = 50;
|
||||
final int MaxHeight = 35;
|
||||
|
||||
public CommandMap(KittyRole roleLevel, KittyRating contentRating) { super(roleLevel, contentRating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Generates a map! You can pass additional information if you want with the flags `-s<seed> -w<width> -h<height>`. If one of the fields isn't provided, its default will be used. Note that adjusting the width and height impacts the map outcomes.\n\nDefault seed: Random,\nDefault Width: 35(max "+ MaxWidth + "),\nDefault Height: 25(max " + MaxHeight + ")"; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
// Variables
|
||||
int width = 35;
|
||||
int height = 25;
|
||||
long seed = 0;
|
||||
String header = "";
|
||||
String body = "";
|
||||
Random randGenerator = null;
|
||||
|
||||
// Parse out a seed if one was provided
|
||||
boolean hasSeed = false;
|
||||
if(input.args != null && input.args.length() > 0)
|
||||
try
|
||||
{
|
||||
OptionParser parser = new OptionParser(input.args);
|
||||
|
||||
String seedStr = parser.GetOption("-s", true);
|
||||
if(seedStr != null)
|
||||
{
|
||||
seed = Long.parseLong(seedStr);
|
||||
hasSeed = true;
|
||||
}
|
||||
|
||||
String widthStr = parser.GetOption("-w", true);
|
||||
if(widthStr != null)
|
||||
width = ValidateSize(Integer.parseInt(widthStr), MaxWidth);
|
||||
|
||||
String heightStr = parser.GetOption("-h", true);
|
||||
if(heightStr != null)
|
||||
height = ValidateSize(Integer.parseInt(heightStr), MaxHeight);
|
||||
}
|
||||
catch(NumberFormatException e)
|
||||
{
|
||||
res.Call("Invalid arguments provided!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set up the random generator, creating a seed if needed.
|
||||
if(hasSeed)
|
||||
{
|
||||
randGenerator = new Random(seed);
|
||||
}
|
||||
else
|
||||
{
|
||||
seed = new Random().nextLong();
|
||||
randGenerator = new Random(seed);
|
||||
}
|
||||
|
||||
// Response header creation
|
||||
header += "Using mapgen v0.1\n";
|
||||
header += "Seed: `" + seed + "`, Width: `"+ width +"`, Height: `"+ height + "`\n";
|
||||
|
||||
// Response body creation
|
||||
body += "```\n";
|
||||
body += GenerateMap(width, height, randGenerator);
|
||||
body += "\n```";
|
||||
|
||||
// Send back the map
|
||||
res.Call(header + body);
|
||||
}
|
||||
|
||||
// Verifies and appropriately caps input as necessary
|
||||
int ValidateSize(int input, int max)
|
||||
{
|
||||
if(input < 0)
|
||||
throw new NumberFormatException();
|
||||
|
||||
if(input > max)
|
||||
input = max;
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
|
||||
// Does the map generation
|
||||
String GenerateMap(int width, int height, Random gen)
|
||||
{
|
||||
String landscape[][] = new String[width][height];
|
||||
int r1 = rand(gen);
|
||||
|
||||
// Variables to determine various feature quantities.
|
||||
int LandScarcity = (r1 % 200) + 100; // Higher = more water.
|
||||
int landPasses = 7; // Higher = larger land chunks.
|
||||
int MountainScarcity = 50; // Higher = fewer mountains;
|
||||
int mountainPasses = r1 % 8 + 2; // Times to plant mountains.
|
||||
int marshPasses = r1 % 3 + 10; // Times to plant marshes.
|
||||
int lavaPasses = 1; // Times to plant lava.
|
||||
int beachPasses = 1;
|
||||
int i, j;
|
||||
int sizeX = height;
|
||||
int sizeY = width;
|
||||
|
||||
// Previously defines
|
||||
String LAND = "\u02F6"; // Used to be "
|
||||
String WATER = " "; // Used to be ~
|
||||
String MOUNTAIN = "\u25B2"; // Used to be ^
|
||||
String BEACH = "="; // Used to be ~
|
||||
String MARSH = "\u00A5"; // Used to be ,
|
||||
String LAVA = "#"; // Used to be *
|
||||
//String SPACE = " ";
|
||||
|
||||
////////////////////
|
||||
//GENERATION LOOPS//
|
||||
////////////////////
|
||||
|
||||
// Populate grid with water.
|
||||
for(i = 0; i < sizeY; i++)
|
||||
for(j = 0; j < sizeX; j++)
|
||||
landscape[i][j] = WATER;
|
||||
|
||||
// land initial distribution.
|
||||
for(i = 0; i < sizeY; i++)
|
||||
for(j = 0; j < sizeX; j++)
|
||||
{
|
||||
r1 = rand(gen) % LandScarcity;
|
||||
if(r1 == 0)
|
||||
landscape[i][j] = LAND;
|
||||
}
|
||||
|
||||
// Land expansion, standard land.
|
||||
while(landPasses-- > 0)
|
||||
for(i = 0; i < sizeY; i++)
|
||||
for(j = 0; j < sizeX; j++)
|
||||
if(landscape[i][j] == LAND)
|
||||
{
|
||||
if((rand(gen) % 3) == 0)
|
||||
expandLand(sizeX, sizeY, landscape, i, j, LAND);
|
||||
}
|
||||
|
||||
//Beach creation based on land
|
||||
while(beachPasses-- > 0)
|
||||
for(i = 0; i < sizeY; i++)
|
||||
for(j = 0; j < sizeX; j++)
|
||||
if(landscape[i][j] == LAND)
|
||||
{
|
||||
Surround beachQuals = new Surround(new String[]{WATER, WATER, WATER, WATER});
|
||||
|
||||
if((rand(gen) % 3) == 0)
|
||||
replaceIf(sizeX, sizeY, landscape, beachQuals, i, j, BEACH);
|
||||
}
|
||||
|
||||
//Mountain creation based on land
|
||||
for(i = 0; i < sizeY; i++)
|
||||
for(j = 0; j < sizeX; j++)
|
||||
if(landscape[i][j] == LAND)
|
||||
{
|
||||
Surround MountainQuals = new Surround(new String[]{LAND, LAND, LAND, LAND});
|
||||
|
||||
if((rand(gen) % MountainScarcity) == 0)
|
||||
{
|
||||
replaceIf(sizeX, sizeY, landscape, MountainQuals, i, j, MOUNTAIN);
|
||||
landscape[i][j] = MOUNTAIN;
|
||||
}
|
||||
}
|
||||
|
||||
//Mountain creation based on Mountain
|
||||
while(mountainPasses-- > 0)
|
||||
for(i = 0; i < sizeY; i++)
|
||||
for(j = 0; j < sizeX; j++)
|
||||
if(landscape[i][j] == LAND)
|
||||
{
|
||||
Surround MountainQuals = new Surround(new String[]{MOUNTAIN, MOUNTAIN, MOUNTAIN, MOUNTAIN});
|
||||
|
||||
int scalar = 0;
|
||||
scalar = replaceIf(sizeX, sizeY, landscape, MountainQuals, i, j, MOUNTAIN);
|
||||
if(scalar > 0)
|
||||
if((rand(gen) % (30 / scalar)) == 0)
|
||||
landscape[i][j] = MOUNTAIN;
|
||||
|
||||
}
|
||||
|
||||
//Marsh creation based on land
|
||||
while(marshPasses-- > 0)
|
||||
for(i = 0; i < sizeY; i++)
|
||||
for(j = 0; j < sizeX; j++)
|
||||
if( landscape[i][j] == LAND)
|
||||
{
|
||||
Surround ForestQuals = new Surround();
|
||||
ForestQuals.left = BEACH;
|
||||
ForestQuals.right = BEACH;
|
||||
ForestQuals.up = BEACH;
|
||||
ForestQuals.down = BEACH;
|
||||
|
||||
if((rand(gen) % 80) == 0)
|
||||
{
|
||||
replaceIf(sizeX, sizeY, landscape, ForestQuals, i, j, MARSH);
|
||||
landscape[i][j] = MARSH;
|
||||
}
|
||||
}
|
||||
|
||||
//Lava creation based on land
|
||||
while(lavaPasses-- > 0)
|
||||
for(i = 0; i < sizeY; i++)
|
||||
for(j = 0; j < sizeX; j++)
|
||||
if( landscape[i][j] == MOUNTAIN)
|
||||
{
|
||||
Surround Mountains = new Surround(new String[]{MOUNTAIN, MOUNTAIN, MOUNTAIN, MOUNTAIN});
|
||||
|
||||
if((rand(gen) % 5) == 0)
|
||||
if(replaceIf(sizeX, sizeY, landscape, Mountains, i, j, MOUNTAIN) == 4)
|
||||
landscape[i][j] = LAVA;
|
||||
}
|
||||
|
||||
////////////
|
||||
//CLEAN UP//
|
||||
////////////
|
||||
|
||||
//Remove lone islands, with the exception of things on the edge.
|
||||
for(i = 0; i < sizeY; i++)
|
||||
for(j = 0; j < sizeX; j++)
|
||||
{
|
||||
Surround water = new Surround(new String[]{WATER, WATER, WATER, WATER});
|
||||
if(replaceIf(sizeX, sizeY, landscape, water, i, j, WATER) == 4)
|
||||
landscape[i][j] = WATER;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Build the map
|
||||
String output = "";
|
||||
for(int y = 0; y < height; ++y)
|
||||
{
|
||||
if(y != 0)
|
||||
output += '\n';
|
||||
|
||||
for(int x = 0; x < width; ++x)
|
||||
output += landscape[x][y];
|
||||
}
|
||||
|
||||
// Return the map
|
||||
return output;
|
||||
}
|
||||
|
||||
// Standardized application of rand for the purposes of this generaton
|
||||
int rand(Random rand)
|
||||
{
|
||||
return rand.nextInt();
|
||||
}
|
||||
|
||||
// Ported from C struct
|
||||
class Surround
|
||||
{
|
||||
public String left;
|
||||
public String right;
|
||||
public String up;
|
||||
public String down;
|
||||
|
||||
public Surround()
|
||||
{
|
||||
left = null;
|
||||
right = null;
|
||||
up = null;
|
||||
down = null;
|
||||
}
|
||||
|
||||
public Surround(String[] args)
|
||||
{
|
||||
if(args.length > 0)
|
||||
left = args[0];
|
||||
|
||||
if(args.length > 1)
|
||||
right = args[1];
|
||||
|
||||
if(args.length > 2)
|
||||
up = args[2];
|
||||
|
||||
if(args.length > 3)
|
||||
down = args[3];
|
||||
}
|
||||
}
|
||||
|
||||
// Expands the current land block
|
||||
static void expandLand(int x, int y, String landscape[][], int i, int j, String toAdd)
|
||||
{
|
||||
// Four checks, one for each block in the 4 cardinal directions.
|
||||
if(i - 1 > -1)
|
||||
landscape[i - 1][j] = toAdd;
|
||||
|
||||
if(i + 1 < y)
|
||||
landscape[i + 1][j] = toAdd;
|
||||
|
||||
if(j - 1 > -1)
|
||||
landscape[i][j - 1] = toAdd;
|
||||
|
||||
if(j + 1 < x)
|
||||
landscape[i][j + 1] = toAdd;
|
||||
}
|
||||
|
||||
// Replaces surrounding stuff
|
||||
int replaceIf(int x, int y, String[][] landscape, Surround spaces, int i, int j, String toAdd)
|
||||
{
|
||||
// Running total of tiles changed.
|
||||
int tilesChanged = 0;
|
||||
|
||||
// Check square left of me.
|
||||
if(spaces.left != null)
|
||||
if(j - 1 > -1)
|
||||
if(landscape[i][j - 1] == spaces.left)
|
||||
{
|
||||
landscape[i][j - 1] = toAdd;
|
||||
tilesChanged++;
|
||||
}
|
||||
|
||||
// Check square right of me.
|
||||
if(spaces.right != null)
|
||||
if(j + 1 < x)
|
||||
if(landscape[i][j + 1] == spaces.right)
|
||||
{
|
||||
landscape[i][j + 1] = toAdd;
|
||||
tilesChanged++;
|
||||
}
|
||||
|
||||
// Check square above me.
|
||||
if(spaces.up != null)
|
||||
if(i - 1 > -1)
|
||||
if(landscape[i - 1][j] == spaces.up)
|
||||
{
|
||||
landscape[i - 1][j] = toAdd;
|
||||
tilesChanged++;
|
||||
}
|
||||
|
||||
// Check square below me.
|
||||
if(spaces.down != null)
|
||||
if(i + 1 < y)
|
||||
if(landscape[i + 1][j] == spaces.down)
|
||||
{
|
||||
landscape[i + 1][j] = toAdd;
|
||||
tilesChanged++;
|
||||
}
|
||||
|
||||
return tilesChanged;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package commands;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import core.Command;
|
||||
import dataStructures.KittyChannel;
|
||||
import dataStructures.KittyGuild;
|
||||
import dataStructures.KittyRating;
|
||||
import dataStructures.KittyRole;
|
||||
import dataStructures.KittyUser;
|
||||
import dataStructures.Response;
|
||||
import dataStructures.UserInput;
|
||||
import utils.ImageUtils;
|
||||
|
||||
public class CommandPerish extends Command
|
||||
{
|
||||
public CommandPerish(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Adds a red, 'a n g e r y' overlay to your icon or the icon of a friend you mentioned"; };
|
||||
|
||||
private static Long num = 0l;
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
String name = null;
|
||||
String filename = null;
|
||||
File preProcessed = null;
|
||||
File postProcessed = null;
|
||||
|
||||
synchronized(num)
|
||||
{
|
||||
name = "perish_" + num + ".png";
|
||||
++num;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
filename = ImageUtils.DownloadFromURL(input.args.split(" ")[0], ".png");
|
||||
preProcessed = new File(filename);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
KittyUser person = user;
|
||||
if(input.mentions != null)
|
||||
person = input.mentions[0];
|
||||
|
||||
filename = ImageUtils.DownloadFromURL(person.avatarID, ".png");
|
||||
if(filename == null)
|
||||
return;
|
||||
}
|
||||
preProcessed = new File(filename);
|
||||
ApplyTintEffect(ImageIO.read(preProcessed), name);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
postProcessed = new File(name);
|
||||
res.CallFile(postProcessed, "png");
|
||||
|
||||
ImageUtils.BlockingFileDelete(preProcessed);
|
||||
ImageUtils.BlockingFileDelete(postProcessed);
|
||||
}
|
||||
|
||||
private static void ApplyTintEffect(BufferedImage image, String name) throws IOException
|
||||
{
|
||||
// Iterate over each column left to right and touch up each pixel
|
||||
for(int x = 0; x < image.getWidth(); ++x)
|
||||
{
|
||||
for(int y = 0; y < image.getHeight(); ++y)
|
||||
{
|
||||
Color c = new Color(image.getRGB(x, y), true);
|
||||
|
||||
int red = c.getRed();
|
||||
red += 100;
|
||||
if(red > 255)
|
||||
red = 255;
|
||||
|
||||
int green = c.getGreen();
|
||||
|
||||
int blue = c.getBlue();
|
||||
blue += 20;
|
||||
if(blue > 255)
|
||||
blue = 255;
|
||||
|
||||
Color tinted = new Color(red, green, blue, c.getAlpha());
|
||||
image.setRGB(x, y, tinted.getRGB());
|
||||
}
|
||||
}
|
||||
|
||||
File outputfile = new File(name);
|
||||
ImageIO.write(image, "png", outputfile);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package commands;
|
||||
|
||||
import core.*;
|
||||
import dataStructures.KittyChannel;
|
||||
import dataStructures.KittyGuild;
|
||||
import dataStructures.KittyRating;
|
||||
import dataStructures.KittyRole;
|
||||
import dataStructures.KittyUser;
|
||||
import dataStructures.Response;
|
||||
import dataStructures.UserInput;
|
||||
|
||||
// A ping! Good example command.
|
||||
public class CommandPing extends Command
|
||||
{
|
||||
public CommandPing(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Will respond with Pong!"; }
|
||||
|
||||
// Called when the command is run!
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
res.Call("Pong!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package commands;
|
||||
|
||||
import core.*;
|
||||
import dataStructures.KittyChannel;
|
||||
import dataStructures.KittyGuild;
|
||||
import dataStructures.KittyRating;
|
||||
import dataStructures.KittyRole;
|
||||
import dataStructures.KittyUser;
|
||||
import dataStructures.Response;
|
||||
import dataStructures.UserInput;
|
||||
|
||||
public class CommandPollManage extends Command
|
||||
{
|
||||
public CommandPollManage(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "'start' will start a new poll with the query of the line you put after, 'choice' will add a choice to the poll, 'stop' will end the poll"; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
switch(input.args.split(" ")[0].toLowerCase())
|
||||
{
|
||||
case "start":
|
||||
res.Call(guild.startPoll(input.args.substring(input.args.indexOf(' ')).trim()));
|
||||
break;
|
||||
|
||||
case "choice":
|
||||
res.Call(guild.addChoiceToPoll(input.args.substring(input.args.indexOf(' ')).trim()));
|
||||
break;
|
||||
|
||||
case "stop":
|
||||
res.Call(guild.endPoll());
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import core.*;
|
||||
import dataStructures.*;
|
||||
|
||||
public class CommandPollResults extends Command
|
||||
{
|
||||
public CommandPollResults(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Will show current results of a poll and percentages of votes per choice"; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
String results = "";
|
||||
int totalVotes = 0;
|
||||
ArrayList<KittyPoll> votes = guild.choices;
|
||||
|
||||
for(int i = 0; i < votes.size(); i++)
|
||||
{
|
||||
totalVotes += votes.get(i).votes;
|
||||
}
|
||||
|
||||
for(int i = 0; i < votes.size(); i++)
|
||||
{
|
||||
|
||||
results += votes.get(i).votes + " people voted for `" + votes.get(i).choice + "` with `" + (int)(((double)votes.get(i).votes) / ((double)totalVotes) * 100) + "%`!\n";
|
||||
}
|
||||
|
||||
res.Call(results);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package commands;
|
||||
|
||||
import core.*;
|
||||
import dataStructures.*;
|
||||
|
||||
public class CommandPollShow extends Command
|
||||
{
|
||||
public CommandPollShow(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Will show the current poll running"; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
if(!guild.polling)
|
||||
{
|
||||
res.Call("There is no poll running!");
|
||||
return;
|
||||
}
|
||||
String poll = "The current poll is `" + guild.poll + "`\n";
|
||||
poll += "And the choices are:\n";
|
||||
for(int i = 0; i < guild.choices.size(); i++)
|
||||
{
|
||||
poll += (i+1) + ": `" + guild.choices.get(i).choice + "`\n";
|
||||
}
|
||||
|
||||
res.Call(poll);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package commands;
|
||||
|
||||
import core.*;
|
||||
import dataStructures.*;
|
||||
|
||||
public class CommandPollVote extends Command
|
||||
{
|
||||
public CommandPollVote(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Vote in a poll with the choice number, won't work if no poll is running, you can't change your vote once you have cast it! Be careful!"; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
if(guild.polling)
|
||||
{
|
||||
if(guild.hasVoted.contains(user.uniqueID))
|
||||
{
|
||||
res.Call("You already voted");
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
int voteNum = Integer.parseInt(input.args)-1;
|
||||
if(voteNum >= guild.choices.size() || voteNum < 0)
|
||||
{
|
||||
res.Call(voteNum + " That's not a vaild vote!");
|
||||
return;
|
||||
}
|
||||
KittyPoll polled = guild.choices.get(voteNum);
|
||||
polled.votes++;
|
||||
guild.hasVoted.add(user.uniqueID);
|
||||
res.Call("You successfully voted for `" + polled.choice + "`!");
|
||||
return;
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
res.Call("That's not a vaild number!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
res.Call("There is no poll running!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package commands;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import core.Command;
|
||||
import core.RPManager;
|
||||
import dataStructures.*;
|
||||
|
||||
public class CommandRPEnd extends Command
|
||||
{
|
||||
public CommandRPEnd (KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Ends RP in channel"; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
File sending = null;
|
||||
try {
|
||||
sending = RPManager.instance.endRP(channel, user);
|
||||
} catch (FileNotFoundException | UnsupportedEncodingException e)
|
||||
{
|
||||
System.out.println("I don't know how you got here");
|
||||
}
|
||||
if(sending != null)
|
||||
{
|
||||
res.CallFile(sending, "txt");
|
||||
res.Call("Here's your file!");
|
||||
}
|
||||
else
|
||||
res.Call("You can't end this RP!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package commands;
|
||||
|
||||
import core.Command;
|
||||
import core.rpg.RPGFramework;
|
||||
import dataStructures.KittyChannel;
|
||||
import dataStructures.KittyGuild;
|
||||
import dataStructures.KittyRating;
|
||||
import dataStructures.KittyRole;
|
||||
import dataStructures.KittyUser;
|
||||
import dataStructures.Response;
|
||||
import dataStructures.UserInput;
|
||||
|
||||
|
||||
public class CommandRPG extends Command
|
||||
{
|
||||
private RPGFramework framework;
|
||||
|
||||
public CommandRPG(KittyRole role, KittyRating rating)
|
||||
{
|
||||
super(role, rating);
|
||||
framework = new RPGFramework();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Admin+ command only right now - experimental text RPG! Format is !rpg <rpg command>"; };
|
||||
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
if(input.args == null || input.args.length() == 0)
|
||||
{
|
||||
res.Call(HelpText());
|
||||
return;
|
||||
}
|
||||
|
||||
String result = null;
|
||||
synchronized(framework)
|
||||
{
|
||||
result = framework.Run(user.uniqueID, input.args.trim());
|
||||
}
|
||||
|
||||
if(result == null)
|
||||
{
|
||||
res.Call("Invalid RPG Command!");
|
||||
return;
|
||||
}
|
||||
|
||||
res.Call(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package commands;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import core.Command;
|
||||
import core.RPManager;
|
||||
import dataStructures.*;
|
||||
|
||||
public class CommandRPStart extends Command
|
||||
{
|
||||
public CommandRPStart (KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Starts an rp, add people to it by mentioning them!"; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
ArrayList <KittyUser> users = new ArrayList<KittyUser>();
|
||||
users.add(user);
|
||||
if(input.mentions != null)
|
||||
{
|
||||
for(int i = 0; i < input.mentions.length; i++)
|
||||
{
|
||||
users.add(input.mentions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
res.Call(RPManager.instance.newRP(channel, users));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package commands;
|
||||
|
||||
import core.Command;
|
||||
import dataStructures.KittyChannel;
|
||||
import dataStructures.KittyGuild;
|
||||
import dataStructures.KittyRating;
|
||||
import dataStructures.KittyRole;
|
||||
import dataStructures.KittyUser;
|
||||
import dataStructures.Response;
|
||||
import dataStructures.UserInput;
|
||||
|
||||
public class CommandRating extends Command
|
||||
{
|
||||
public CommandRating(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "'0' is fully sfw (Derpi and e621 searches are disabled), '1' is filtered (kitty auto appends a sfw tag on any searches), '2' is nsfw (any search will go through). Some other words are supported for setting filter as well."; }
|
||||
|
||||
// Called when the command is run!
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
String newRating = null;
|
||||
switch(input.args.toLowerCase().trim())
|
||||
{
|
||||
case "0":
|
||||
case "sfw":
|
||||
case "safe":
|
||||
case "clean":
|
||||
case "work":
|
||||
case "safeforwork":
|
||||
guild.contentRating = KittyRating.Safe;
|
||||
newRating = "Safe";
|
||||
break;
|
||||
case "1":
|
||||
case "questionable":
|
||||
case "intermediate":
|
||||
case "middle":
|
||||
case "search filter":
|
||||
case "filter":
|
||||
case "filtered":
|
||||
guild.contentRating = KittyRating.Filtered;
|
||||
newRating = "Filtered";
|
||||
break;
|
||||
case "2":
|
||||
case "rude":
|
||||
case "nsfw":
|
||||
case "explicit":
|
||||
case "lewd":
|
||||
case "notsafeforwork":
|
||||
guild.contentRating = KittyRating.Explicit;
|
||||
newRating = "Explicit";
|
||||
break;
|
||||
}
|
||||
|
||||
if(newRating != null)
|
||||
res.Call("Kittybot content set to " + newRating);
|
||||
else
|
||||
res.Call("Invalid content rating `" + input.args + "`");
|
||||
|
||||
if(newRating.equals("Filtered"))
|
||||
res.Call("Warning: NSFW may slip through, images are only based on tags on their respective sites!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package commands;
|
||||
|
||||
import core.Command;
|
||||
import dataStructures.*;
|
||||
|
||||
public class CommandRole extends Command
|
||||
{
|
||||
public CommandRole (KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Will show the current role you have, Admins can change others roles with input of 'role x @y' with x being blacklist, general, mod, or admin. Blacklist will not allow the user to interact with kitty anymore, general mod and admin will give the user access to those commands."; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
if(input.args.isEmpty())
|
||||
{
|
||||
res.Call("Your role is " + user.GetRole().name() + "!");
|
||||
return;
|
||||
}
|
||||
|
||||
if(user.GetRole().getValue() < KittyRole.Admin.getValue())
|
||||
{
|
||||
res.Call("You aren't allowed to do that! You must have the KittyRole '" + KittyRole.Admin.toString() + "' or higher!");
|
||||
return;
|
||||
}
|
||||
|
||||
KittyRole newRole;
|
||||
switch(input.args.split(" ")[0].toLowerCase())
|
||||
{
|
||||
case "blacklist":
|
||||
newRole = KittyRole.Blacklisted;
|
||||
break;
|
||||
|
||||
case "general":
|
||||
newRole = KittyRole.General;
|
||||
break;
|
||||
|
||||
case "mod":
|
||||
newRole = KittyRole.Mod;
|
||||
break;
|
||||
|
||||
case "admin":
|
||||
newRole = KittyRole.Admin;
|
||||
break;
|
||||
|
||||
default:
|
||||
res.Call("Please enter `general`, `mod`, or `admin`!");
|
||||
return;
|
||||
}
|
||||
String users = "";
|
||||
for(int i = 0; i < input.mentions.length; i++)
|
||||
{
|
||||
input.mentions[i].ChangeRole(newRole);
|
||||
users += input.mentions[i].name + " ";
|
||||
}
|
||||
|
||||
res.Call("Changed " + users + " to role `" + newRole.name() + "`!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package commands;
|
||||
|
||||
import core.*;
|
||||
import dataStructures.KittyChannel;
|
||||
import dataStructures.KittyGuild;
|
||||
import dataStructures.KittyRating;
|
||||
import dataStructures.KittyRole;
|
||||
import dataStructures.KittyUser;
|
||||
import dataStructures.Response;
|
||||
import dataStructures.UserInput;
|
||||
|
||||
public class CommandRoll extends Command
|
||||
{
|
||||
public CommandRoll(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Based on input of xdy where x is number of dice and y is faces kitty will roll that amount of dice, display the individual rolls and total"; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
int dice;
|
||||
int sides;
|
||||
String dicenum [] = input.args.split("d");
|
||||
|
||||
try
|
||||
{
|
||||
dice = Integer.parseInt(dicenum[0]);
|
||||
sides = Integer.parseInt(dicenum[1]);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
res.Call("Rude.");
|
||||
return;
|
||||
}
|
||||
|
||||
res.Call(rollDice(dice,sides));
|
||||
}
|
||||
|
||||
private String rollDice(int dice, int sides)
|
||||
{
|
||||
int total = 0;
|
||||
int roll = 0;
|
||||
String nums = "";
|
||||
|
||||
//checks for lower than 1 dice or dice size
|
||||
if(dice > 100 || sides > 100)
|
||||
{
|
||||
return ("*drowns in dice*");
|
||||
}
|
||||
|
||||
if(dice < 1 || sides < 1)
|
||||
{
|
||||
return("I can't do that!");
|
||||
}
|
||||
|
||||
for(int i = 0; dice > i; i ++)
|
||||
{
|
||||
roll = (int)(Math.random() * sides) + 1;
|
||||
nums += roll + " ";
|
||||
total += roll;
|
||||
}
|
||||
|
||||
//makes output look nicer
|
||||
String prettyNums = "";
|
||||
String[] splitNums = nums.split(" ");
|
||||
if(splitNums.length > 10)
|
||||
{
|
||||
final int len = 5;
|
||||
for(int i = 0; i < splitNums.length; i += len)
|
||||
{
|
||||
prettyNums += "\n";
|
||||
for(int j = 0; j < len; ++j)
|
||||
{
|
||||
if(j != 0)
|
||||
prettyNums += " ";
|
||||
|
||||
prettyNums += splitNums[i + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
prettyNums = nums;
|
||||
}
|
||||
|
||||
return ("Rolls are\n" + prettyNums + "\n" + "Total is: " + total);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package commands;
|
||||
|
||||
import core.Command;
|
||||
import core.DatabaseManager;
|
||||
import core.Stats;
|
||||
import dataStructures.KittyChannel;
|
||||
import dataStructures.KittyGuild;
|
||||
import dataStructures.KittyRating;
|
||||
import dataStructures.KittyRole;
|
||||
import dataStructures.KittyUser;
|
||||
import dataStructures.Response;
|
||||
import dataStructures.UserInput;
|
||||
|
||||
// NOTE(wisp): This is a sort of special command.
|
||||
public class CommandShutdown extends Command
|
||||
{
|
||||
public CommandShutdown(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Stops kitty. `-s` or `safe` as an argument attempts to sync off the database before shutdown."; }
|
||||
|
||||
// Called when the command is run!
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
// Flag the shutdown immediately.
|
||||
Stats.instance.IndicateShutdown();
|
||||
|
||||
boolean isSafe = false;
|
||||
switch(input.args.toLowerCase().trim())
|
||||
{
|
||||
case "s":
|
||||
case "safe":
|
||||
case "-s":
|
||||
case "-safe":
|
||||
case "snafe":
|
||||
isSafe = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if(isSafe)
|
||||
{
|
||||
DatabaseManager.instance.Upkeep(); // Force upkeep, this works so long as on main thread.
|
||||
res.CallImmediate("Forced shutdown, database synced before abandoning threads.");
|
||||
System.exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
res.CallImmediate("Forced immediate shutdown, threads abandoned without sync.");
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package commands;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import core.Command;
|
||||
import dataStructures.*;
|
||||
import utils.ImageUtils;
|
||||
|
||||
public class CommandStark extends Command
|
||||
{
|
||||
public CommandStark(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Snaps your icon or the icon of a friend you mentioned"; };
|
||||
|
||||
private static Long num = 0l;
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
String name = null;
|
||||
String filename = null;
|
||||
File preProcessed = null;
|
||||
File postProcessed = null;
|
||||
|
||||
synchronized(num)
|
||||
{
|
||||
name = "snapped_" + num + ".png";
|
||||
++num;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
filename = ImageUtils.DownloadFromURL(input.args.split(" ")[0], ".png");
|
||||
preProcessed = new File(filename);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
KittyUser person = user;
|
||||
if(input.mentions != null)
|
||||
person = input.mentions[0];
|
||||
|
||||
filename = ImageUtils.DownloadFromURL(person.avatarID, ".png");
|
||||
if(filename == null)
|
||||
return;
|
||||
}
|
||||
preProcessed = new File(filename);
|
||||
ApplySnap(ImageIO.read(preProcessed), name);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
postProcessed = new File(name);
|
||||
res.CallFile(postProcessed, "png");
|
||||
|
||||
ImageUtils.BlockingFileDelete(preProcessed);
|
||||
ImageUtils.BlockingFileDelete(postProcessed);
|
||||
}
|
||||
|
||||
private static void ApplySnap(BufferedImage image, String name) throws IOException
|
||||
{
|
||||
BufferedImage snap = ImageUtils.copyImage(image);
|
||||
// Iterate over each column left to right and touch up each pixel
|
||||
for(int x = 0; x < snap.getWidth(); ++x)
|
||||
{
|
||||
for(int y = 0; y < snap.getHeight(); ++y)
|
||||
{
|
||||
Color c = new Color(snap.getRGB(x, y), true);
|
||||
|
||||
int alpha = c.getAlpha();
|
||||
if(x * Math.random() > 25)
|
||||
alpha = (int)((1 - (x / ((float)snap.getWidth()))) * 255);
|
||||
|
||||
|
||||
Color snapped = new Color(c.getRed(),c.getGreen(), c.getBlue(), alpha);
|
||||
snap.setRGB(x, y, snapped.getRGB());
|
||||
}
|
||||
}
|
||||
|
||||
File outputfile = new File(name);
|
||||
ImageIO.write(snap, "png", outputfile);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package commands;
|
||||
|
||||
import core.Command;
|
||||
import core.CommandManager.ThreadData;
|
||||
import dataStructures.KittyChannel;
|
||||
import dataStructures.KittyGuild;
|
||||
import dataStructures.KittyRating;
|
||||
import dataStructures.KittyRole;
|
||||
import dataStructures.KittyUser;
|
||||
import dataStructures.Response;
|
||||
import dataStructures.UserInput;
|
||||
import core.Stats;
|
||||
|
||||
public class CommandStats extends Command
|
||||
{
|
||||
public CommandStats(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Displays the actively running KittyBot application information"; }
|
||||
|
||||
// Called when the command is run!
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
String out = "```\n";
|
||||
Stats stats = Stats.instance;
|
||||
|
||||
out += "----- [General] -----\n";
|
||||
out += " Messages observed: " + stats.GetMessagesSeen() + "\n";
|
||||
out += "Commands processed: " + stats.GetCommandsProcessed() + "\n";
|
||||
out += " KittyBot uptime: " + stats.GetFormattedUptime() + "\n";
|
||||
out += "\n";
|
||||
out += "----- [Health] -----\n";
|
||||
out += " SMT cores: " + stats.GetCPUAvailable() + "\n";
|
||||
|
||||
// If CPU load works on this OS, list it.
|
||||
double CPULoad = stats.GetSystemCPULoad();
|
||||
if(CPULoad > -0.9) // -1.0 is the error state
|
||||
out += "System CPU Load: " + (CPULoad * 100) + "%\n";
|
||||
|
||||
ThreadData data = stats.GetThreadData();
|
||||
Integer terminated = data.states.get(Thread.State.TERMINATED);
|
||||
Integer runnable = data.states.get(Thread.State.RUNNABLE);
|
||||
Integer blocked = data.states.get(Thread.State.BLOCKED);
|
||||
Integer timed_waiting = data.states.get(Thread.State.TIMED_WAITING);
|
||||
Integer waiting = data.states.get(Thread.State.WAITING);
|
||||
|
||||
out += " Child threads:"
|
||||
+ " run: " + (runnable == null ? 0 : runnable)
|
||||
+ " block: " + (blocked == null ? 0 : blocked)
|
||||
+ " sleep: " + (timed_waiting == null ? 0 : timed_waiting)
|
||||
+ " wait: " + (waiting == null ? 0 : waiting)
|
||||
+ " term: " + (terminated == null ? 0 : terminated)
|
||||
+ "\n";
|
||||
|
||||
Integer guildCount = stats.GetGuildCount();
|
||||
Integer userCount = stats.GetUserCount();
|
||||
|
||||
out += "\n----- [Counts] -----\n"
|
||||
+ "Guilds: " + guildCount + "\n"
|
||||
+ " Users: " + userCount;
|
||||
out += "\n```";
|
||||
|
||||
res.Call(out);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package commands;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import core.Command;
|
||||
import dataStructures.*;
|
||||
import network.*;
|
||||
import utils.ImageUtils;
|
||||
|
||||
public class CommandWolfram extends Command
|
||||
{
|
||||
NetworkWolfram searcher = new NetworkWolfram();
|
||||
|
||||
public CommandWolfram(KittyRole level, KittyRating rating) { super(level, rating);}
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Will query wolframalpha with your question and give a full image output of the answer"; }
|
||||
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
if(input.args == null || input.args.trim().length() == 0)
|
||||
res.Call("You need to provide some arguments!");
|
||||
|
||||
try
|
||||
{
|
||||
File pic = new File(searcher.getWolfram(input.args));
|
||||
res.CallFile(pic, "png");
|
||||
ImageUtils.BlockingFileDelete(pic);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
res.Call("Something went wrong!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,336 @@
|
||||
package commands;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBufferByte;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Calendar;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.IIOImage;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.ImageTypeSpecifier;
|
||||
import javax.imageio.ImageWriteParam;
|
||||
import javax.imageio.ImageWriter;
|
||||
import javax.imageio.metadata.IIOMetadata;
|
||||
import javax.imageio.metadata.IIOMetadataNode;
|
||||
import javax.imageio.stream.FileImageOutputStream;
|
||||
import javax.imageio.stream.ImageOutputStream;
|
||||
|
||||
import core.Command;
|
||||
import dataStructures.KittyChannel;
|
||||
import dataStructures.KittyGuild;
|
||||
import dataStructures.KittyRating;
|
||||
import dataStructures.KittyRole;
|
||||
import dataStructures.KittyUser;
|
||||
import dataStructures.Response;
|
||||
import dataStructures.UserInput;
|
||||
import utils.ImageUtils;
|
||||
|
||||
public class CommandYeet extends Command
|
||||
{
|
||||
|
||||
// Required constructor
|
||||
public CommandYeet(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
private static Long num = 0l;
|
||||
|
||||
@Override
|
||||
public String HelpText() { return "Yeet yourself or yeet a friend with @!"; }
|
||||
|
||||
// Called when the command is run!
|
||||
@Override
|
||||
public void OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
|
||||
{
|
||||
String name = null;
|
||||
File yeetFile = null;
|
||||
File yeeteeFile = null;
|
||||
|
||||
synchronized(num)
|
||||
{
|
||||
name = "yeet_" + num + ".gif";
|
||||
++num;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
KittyUser person = null;
|
||||
|
||||
if(input.mentions == null)
|
||||
{
|
||||
person = user;
|
||||
}
|
||||
else
|
||||
{
|
||||
person = input.mentions[0];
|
||||
}
|
||||
|
||||
String yeeteeFilename = ImageUtils.DownloadFromURL(person.avatarID, ".png");
|
||||
if(yeeteeFilename == null)
|
||||
return;
|
||||
|
||||
yeeteeFile = new File(yeeteeFilename);
|
||||
YEET(ImageIO.read(yeeteeFile), name);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
yeetFile = new File (name);
|
||||
res.CallFile(yeetFile, "gif");
|
||||
|
||||
// Thread cleanup...
|
||||
ImageUtils.BlockingFileDelete(yeetFile);
|
||||
ImageUtils.BlockingFileDelete(yeeteeFile);
|
||||
}
|
||||
|
||||
// Lets get some trash established for the yeet
|
||||
public static final boolean VERBOSE = false;
|
||||
public static final int NONE = -1;
|
||||
public static final int PIXEL_BYTE_LENGTH = 4; // 32-bit PNG, RGBA
|
||||
public static final String YEET_BASE_PATH = "yeet/frames/";
|
||||
public static final int YEET_BASE_SIZE = 24;
|
||||
public static final int YEET_FPS = 18;
|
||||
|
||||
// Some small logging functions... cause we're professionals...
|
||||
public static void Verbose(String str) { if(VERBOSE) Log("[Verbose] " + str); }
|
||||
public static void Log(String str) { System.out.println("[Log] " + str); }
|
||||
public static void Warn(String str) { System.out.println("[Warn] " + str); }
|
||||
public static void Error(String str) { System.out.println("[Error] " + str); }
|
||||
|
||||
// Performs the Y E E T (image overlay per frame specified, catches IO errors as a note.)
|
||||
public static void YEET(BufferedImage overlay, String outpath)
|
||||
{
|
||||
try
|
||||
{
|
||||
long start = Calendar.getInstance().getTimeInMillis();
|
||||
|
||||
ProcessYeet(overlay, outpath);
|
||||
|
||||
long end = Calendar.getInstance().getTimeInMillis();
|
||||
Log("Took " + (end - start) + "ms");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Processing the image frames to construct a gif. Relies on (0,255,0) pixel for image center specification.
|
||||
public static void ProcessYeet(BufferedImage overlay, String outfileName) throws IOException
|
||||
{
|
||||
BufferedImage[] frames = new BufferedImage[YEET_BASE_SIZE];
|
||||
|
||||
for(int i = 0; i < YEET_BASE_SIZE; ++i)
|
||||
{
|
||||
BufferedImage out = CombineImages(YEET_BASE_PATH + "yeet " + i + ".png", overlay);
|
||||
|
||||
if(out != null)
|
||||
frames[i] = out;
|
||||
else
|
||||
Error("There was an issue with frame " + i);
|
||||
}
|
||||
|
||||
Verbose("Processed " + YEET_BASE_SIZE + " frames, writing...");
|
||||
ImageOutputStream output = new FileImageOutputStream(new File(outfileName));
|
||||
GifSequenceWriter writer = new GifSequenceWriter(output, frames[0].getType(), YEET_FPS, true);
|
||||
|
||||
for(int i = 0; i < YEET_BASE_SIZE; ++i)
|
||||
writer.writeToSequence(frames[i]);
|
||||
|
||||
writer.close();
|
||||
output.close();
|
||||
}
|
||||
|
||||
// Performs an overlay at a pixel location. We're making some assumptions here, mostly that there is going
|
||||
// to be an RGBA-32-bit encoded PNG image read in for our parsing purposes. We then look for a 0, 255, 0
|
||||
// green pixel on the base frame to apply the overlay buffer to, centered.
|
||||
public static BufferedImage CombineImages(String pathBase, BufferedImage overlay) throws IOException
|
||||
{
|
||||
// Acquire images
|
||||
BufferedImage imageBase = null;
|
||||
BufferedImage imageOverlay = overlay;
|
||||
|
||||
imageBase = ImageIO.read(new File(pathBase));
|
||||
|
||||
// Grab data we know won't change. As a side note, I discovered you can get specific pixels a bit
|
||||
// differently later, but it was too late, I wrote the pixel specific code already.
|
||||
final byte[] pixelsBase = ((DataBufferByte) imageBase.getRaster().getDataBuffer()).getData();
|
||||
final int baseWidth = imageBase.getWidth();
|
||||
final int overlayWidth = imageOverlay.getWidth();
|
||||
final int baseHeight = imageBase.getHeight();
|
||||
final int overlayHeight = imageOverlay.getHeight();
|
||||
|
||||
// Warn about odd sizing when applicable
|
||||
if(overlayHeight > baseHeight || overlayWidth > baseWidth)
|
||||
Warn("Size mismatch, overlay is larger. May function, but not supported.");
|
||||
|
||||
// Skim base picture for solid green pixel to use as target center
|
||||
int targetX = NONE;
|
||||
int targetY = NONE;
|
||||
for(int i = 0; i < pixelsBase.length; i += PIXEL_BYTE_LENGTH)
|
||||
{
|
||||
final int x = ((i / PIXEL_BYTE_LENGTH) % baseWidth);
|
||||
final int y = ((i / PIXEL_BYTE_LENGTH) / baseWidth);
|
||||
|
||||
final int r = (pixelsBase[i]);
|
||||
final int g = (pixelsBase[i + 1]);
|
||||
final int b = (pixelsBase[i + 2]);
|
||||
//final int a = (pixelsBase[i + 3]);
|
||||
|
||||
// Max contrast in 32-bit PNG for green is no red no blue, max green (ratio), max alpha (implied 0 here)
|
||||
if(r == -1 && g == 0 && b == -1)
|
||||
{
|
||||
//Log("Found target pixel at x: " + x + " y: " + y);
|
||||
targetX = x;
|
||||
targetY = y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Skip overlay if we have no target location
|
||||
if(targetX == NONE || targetY == NONE)
|
||||
{
|
||||
Verbose("No overlay required for this frame.");
|
||||
return imageBase;
|
||||
}
|
||||
|
||||
// Re-create a new byte array and establish overlay bounds
|
||||
final int left = targetX - overlayWidth / 2;
|
||||
final int right = targetX + overlayWidth / 2;
|
||||
final int top = targetY - overlayHeight / 2;
|
||||
final int bottom = targetY + overlayHeight / 2;
|
||||
|
||||
// Apply overlay when appropriate
|
||||
for(int i = 0; i < pixelsBase.length; i += PIXEL_BYTE_LENGTH)
|
||||
{
|
||||
final int x = ((i / PIXEL_BYTE_LENGTH) % baseWidth);
|
||||
final int y = ((i / PIXEL_BYTE_LENGTH) / baseWidth);
|
||||
|
||||
// If we're within the bounds of where the overlay picture should go...
|
||||
if(x > left && x < right && y > top && y < bottom)
|
||||
{
|
||||
final int overlayX = x - left;
|
||||
final int overlayY = y - top;
|
||||
|
||||
// Skip out of bounds pixels
|
||||
if(overlayX < 0 || overlayY < 0 || overlayX >= baseWidth || overlayY >= baseHeight)
|
||||
continue;
|
||||
|
||||
// Re-write bytes as overlay
|
||||
imageBase.setRGB(x, y, imageOverlay.getRGB(overlayX, overlayY));
|
||||
}
|
||||
}
|
||||
|
||||
// Give the frame back
|
||||
return imageBase;
|
||||
}
|
||||
|
||||
|
||||
// GifSequenceWriter.java
|
||||
//
|
||||
// Created by Elliot Kroo on 2009-04-25,
|
||||
// (Small modifications by wisp in 2018)
|
||||
//
|
||||
// This work is licensed under the Creative Commons Attribution 3.0 Unported License.
|
||||
// To view a copy of this license visit http://creativecommons.org/licenses/by/3.0/
|
||||
// NOTE(wisp): This is Elliot's original license
|
||||
public static class GifSequenceWriter
|
||||
{
|
||||
protected ImageWriter gifWriter;
|
||||
protected ImageWriteParam imageWriteParam;
|
||||
protected IIOMetadata imageMetaData;
|
||||
|
||||
// NOTE: This is limited to things that divide into 1000 cleanly as multiples of 10.
|
||||
public GifSequenceWriter(ImageOutputStream outputStream, int imageType, int framesPerSecond, boolean isLooping) throws IIOException, IOException
|
||||
{
|
||||
gifWriter = getWriter();
|
||||
imageWriteParam = gifWriter.getDefaultWriteParam();
|
||||
ImageTypeSpecifier imageTypeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(imageType);
|
||||
|
||||
imageMetaData = gifWriter.getDefaultImageMetadata(imageTypeSpecifier, imageWriteParam);
|
||||
|
||||
String metaFormatName = imageMetaData.getNativeMetadataFormatName();
|
||||
|
||||
IIOMetadataNode root = (IIOMetadataNode) imageMetaData.getAsTree(metaFormatName);
|
||||
IIOMetadataNode graphicsControlExtensionNode = getNode(root, "GraphicControlExtension");
|
||||
graphicsControlExtensionNode.setAttribute("disposalMethod", "none");
|
||||
graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE");
|
||||
graphicsControlExtensionNode.setAttribute("transparentColorFlag", "FALSE");
|
||||
graphicsControlExtensionNode.setAttribute("delayTime", "" + (int) ((1000.0 / framesPerSecond) / 10.0)); // THis line isn't super well honored
|
||||
graphicsControlExtensionNode.setAttribute("transparentColorIndex","0");
|
||||
|
||||
IIOMetadataNode appEntensionsNode = getNode( root, "ApplicationExtensions");
|
||||
IIOMetadataNode child = new IIOMetadataNode("ApplicationExtension");
|
||||
child.setAttribute("applicationID", "NETSCAPE");
|
||||
child.setAttribute("authenticationCode", "2.0");
|
||||
|
||||
int loopValue = isLooping ? 0 : 1;
|
||||
child.setUserObject(new byte[]{ 0x1, (byte) (loopValue & 0xFF), (byte) ((loopValue >> 8) & 0xFF)});
|
||||
appEntensionsNode.appendChild(child);
|
||||
|
||||
imageMetaData.setFromTree(metaFormatName, root);
|
||||
|
||||
gifWriter.setOutput(outputStream);
|
||||
gifWriter.prepareWriteSequence(null);
|
||||
}
|
||||
|
||||
public void writeToSequence(RenderedImage img) throws IOException
|
||||
{
|
||||
gifWriter.writeToSequence(new IIOImage(img, null, imageMetaData), imageWriteParam);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close this GifSequenceWriter object. This does not close the underlying
|
||||
* stream, just finishes off the GIF.
|
||||
*/
|
||||
public void close() throws IOException
|
||||
{
|
||||
gifWriter.endWriteSequence();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first available GIF ImageWriter using
|
||||
* ImageIO.getImageWritersBySuffix("gif").
|
||||
*
|
||||
* @return a GIF ImageWriter object
|
||||
* @throws IIOException if no GIF image writers are returned
|
||||
*/
|
||||
private static ImageWriter getWriter() throws IIOException
|
||||
{
|
||||
Iterator<ImageWriter> iter = ImageIO.getImageWritersBySuffix("gif");
|
||||
|
||||
if(!iter.hasNext())
|
||||
throw new IIOException("No GIF Image Writers Exist");
|
||||
else
|
||||
return iter.next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an existing child node, or creates and returns a new child node (if
|
||||
* the requested node does not exist).
|
||||
*
|
||||
* @param rootNode the <tt>IIOMetadataNode</tt> to search for the child node.
|
||||
* @param nodeName the name of the child node.
|
||||
*
|
||||
* @return the child node, if found or a new node created with the given name.
|
||||
*/
|
||||
private static IIOMetadataNode getNode(IIOMetadataNode rootNode, String nodeName)
|
||||
{
|
||||
int nodeCount = rootNode.getLength();
|
||||
for (int i = 0; i < nodeCount; i++)
|
||||
{
|
||||
if (rootNode.item(i).getNodeName().compareToIgnoreCase(nodeName) == 0)
|
||||
return((IIOMetadataNode) rootNode.item(i));
|
||||
}
|
||||
|
||||
IIOMetadataNode node = new IIOMetadataNode(nodeName);
|
||||
rootNode.appendChild(node);
|
||||
|
||||
return(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package commands.rpg;
|
||||
|
||||
import core.rpg.RPGCommand;
|
||||
import core.rpg.RPGInput;
|
||||
import core.rpg.RPGState;
|
||||
|
||||
public class RPGCommandBattleFight extends RPGCommand
|
||||
{
|
||||
|
||||
@Override
|
||||
public String OnRun(RPGState state, RPGInput input)
|
||||
{
|
||||
if(state.battleContext == null)
|
||||
return "```There's nothing to fight!```";
|
||||
|
||||
String out = null;
|
||||
String reward = null;
|
||||
|
||||
out = "No one ever trained you to fight, so you do a silly dance and it weirds your opponent out and they leave. (i need to implement this still)";
|
||||
reward = "+150xp";
|
||||
|
||||
state.battleContext = null;
|
||||
state.player.ApplyEXP(150);
|
||||
|
||||
if(out != null && reward != null)
|
||||
{
|
||||
out += "\n";
|
||||
out += "\n";
|
||||
out += "[" + reward + "]";
|
||||
}
|
||||
|
||||
if(out != null)
|
||||
out = "```\n" + out + "```";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package commands.rpg;
|
||||
|
||||
import core.rpg.RPGCommand;
|
||||
import core.rpg.RPGInput;
|
||||
import core.rpg.RPGState;
|
||||
|
||||
public class RPGCommandBattleRun extends RPGCommand
|
||||
{
|
||||
@Override
|
||||
public String OnRun(RPGState state, RPGInput input)
|
||||
{
|
||||
if(state.battleContext == null)
|
||||
return "```There's nothing to run from!```";
|
||||
|
||||
long lostGold = (long)(state.player.GetGold() * .1);
|
||||
String out = null;
|
||||
|
||||
state.player.SpendGold(lostGold);
|
||||
state.battleContext = null;
|
||||
|
||||
out = "You duck behind a tree and manage to escape from encounter just barely!";
|
||||
if(lostGold > 0)
|
||||
{
|
||||
out += " As you make your final move to escape, you accidentally drop some of your gold behind. You don't dare try to go back and pick it up.";
|
||||
out += "\n";
|
||||
out += "\n";
|
||||
out += "[-" + lostGold + "gp]";
|
||||
}
|
||||
|
||||
if(out != null)
|
||||
out = "```\n" + out + "```";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package commands.rpg;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import core.rpg.RPGBattleContext;
|
||||
import core.rpg.RPGCommand;
|
||||
import core.rpg.RPGInput;
|
||||
import core.rpg.RPGState;
|
||||
|
||||
public class RPGCommandExplore extends RPGCommand
|
||||
{
|
||||
private class Chance
|
||||
{
|
||||
double rand;
|
||||
float lastSection;
|
||||
|
||||
public Chance(float percentChanceTotal)
|
||||
{
|
||||
rand = new Random().nextDouble() * percentChanceTotal;
|
||||
lastSection = 0;
|
||||
}
|
||||
|
||||
public boolean Next(float amount)
|
||||
{
|
||||
lastSection += amount;
|
||||
return rand < lastSection;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String OnRun(RPGState state, RPGInput input)
|
||||
{
|
||||
Chance chance = new Chance(100);
|
||||
|
||||
String out = null;
|
||||
String reward = null;
|
||||
|
||||
if(state.battleContext != null)
|
||||
return "```You can't explore right now, you're in a fight! Try either 'fight' or 'run'!```";
|
||||
|
||||
if(chance.Next(20))
|
||||
{
|
||||
out = "A creature jumps out of a bush at you!";
|
||||
reward = "Prepare to fight!";
|
||||
state.battleContext = new RPGBattleContext(state);
|
||||
}
|
||||
else if(chance.Next(20))
|
||||
{
|
||||
final int gp = 1;
|
||||
|
||||
out = "As you take a stroll, you spy a small shiny glint from a bush and decide to investigate! Looks like it's your lucky day!";
|
||||
reward = "+" + gp + "gp";
|
||||
state.player.GiveGold(gp);
|
||||
}
|
||||
else if(chance.Next(20))
|
||||
{
|
||||
final int healing = 1;
|
||||
final int xp = 25;
|
||||
|
||||
out = "You head out on a lovely stroll down a familiar path - the sun is out and the birds are chirping! Nothing much comes of it, but you feel refreshed.";
|
||||
reward = "+" + xp + "xp, +" + healing + "hp";
|
||||
state.player.ApplyHealing(healing);
|
||||
state.player.ApplyEXP(xp);
|
||||
}
|
||||
else if(chance.Next(20))
|
||||
{
|
||||
final int xp = 75;
|
||||
final int damage = 1;
|
||||
|
||||
out = "Today's the day you head out on a new path. You find a lot of little nicknacks and trinkets on the trail, but leave them be. The trail gets really steep, the rocks jagged, but you keep going. Eventually, you make it out to the other side into a small but pleasant town, and collapse on a bench to catch your breath.";
|
||||
reward = "+" + xp + "xp, -" + damage + "hp";
|
||||
state.player.ApplyEXP(xp);
|
||||
state.player.ApplyDamage(damage);
|
||||
}
|
||||
else
|
||||
{
|
||||
final int hp = 2;
|
||||
|
||||
out = "You step outside but it starts to rain. You decide not to do much today, and hang about the inn and the tavern.";
|
||||
reward = "+" + hp + "hp";
|
||||
state.player.ApplyHealing(hp);
|
||||
}
|
||||
|
||||
if(out != null && reward != null)
|
||||
{
|
||||
out += "\n";
|
||||
out += "\n";
|
||||
out += "[" + reward + "]";
|
||||
}
|
||||
|
||||
if(out != null)
|
||||
out = "```\n" + out + "```";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package commands.rpg;
|
||||
|
||||
import core.rpg.RPGArmor;
|
||||
import core.rpg.RPGCommand;
|
||||
import core.rpg.RPGInput;
|
||||
import core.rpg.RPGState;
|
||||
import core.rpg.RPGWeapon;
|
||||
|
||||
public class RPGCommandInfo extends RPGCommand
|
||||
{
|
||||
|
||||
@Override
|
||||
public String OnRun(RPGState state, RPGInput input)
|
||||
{
|
||||
String out = null;
|
||||
switch(input.value.trim().toLowerCase())
|
||||
{
|
||||
case "weapon":
|
||||
case "weapo":
|
||||
case "weap":
|
||||
case "wea":
|
||||
case "we":
|
||||
case "w":
|
||||
case "wepon":
|
||||
case "wepo":
|
||||
case "wep":
|
||||
case "hand":
|
||||
case "att":
|
||||
case "attack":
|
||||
out = WeaponStats(state.player.GetWeapon());
|
||||
break;
|
||||
|
||||
case "armour":
|
||||
case "armou":
|
||||
case "armor":
|
||||
case "armr":
|
||||
case "armo":
|
||||
case "arm":
|
||||
case "ar":
|
||||
case "a":
|
||||
case "def":
|
||||
case "defense":
|
||||
case "body":
|
||||
case "dress":
|
||||
case "wear":
|
||||
case "outfit":
|
||||
out = ArmorStats(state.player.GetArmor());
|
||||
break;
|
||||
}
|
||||
|
||||
if(out != null)
|
||||
out = "```\n" + out + "```";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
private String WeaponStats(RPGWeapon weapon)
|
||||
{
|
||||
if(weapon == null)
|
||||
return null;
|
||||
|
||||
String out = "";
|
||||
out += "[" + weapon.GetName() + "]";
|
||||
out += "\n";
|
||||
out += " att: " + weapon.GetAttack();
|
||||
out += "\n";
|
||||
out += "value: " + weapon.GetValue() + "gp";
|
||||
out += "\n";
|
||||
out += "\n";
|
||||
out += weapon.GetDescription();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
private String ArmorStats(RPGArmor armor)
|
||||
{
|
||||
if(armor == null)
|
||||
return null;
|
||||
|
||||
String out = "";
|
||||
out += "[" + armor.GetName() + "]";
|
||||
out += "\n";
|
||||
out += " def: " + armor.GetDefense();
|
||||
out += "\n";
|
||||
out += "value: " + armor.GetValue() + "gp";
|
||||
out += "\n";
|
||||
out += "\n";
|
||||
out += armor.GetDescription();
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package commands.rpg;
|
||||
|
||||
import core.rpg.RPGArmor;
|
||||
import core.rpg.RPGCommand;
|
||||
import core.rpg.RPGExpTable;
|
||||
import core.rpg.RPGInput;
|
||||
import core.rpg.RPGPlayer;
|
||||
import core.rpg.RPGState;
|
||||
import core.rpg.RPGWeapon;
|
||||
|
||||
public class RPGCommandStats extends RPGCommand
|
||||
{
|
||||
@Override
|
||||
public String OnRun(RPGState state, RPGInput input)
|
||||
{
|
||||
RPGPlayer player = state.player;
|
||||
long exp = player.GetEXP();
|
||||
long level = RPGExpTable.LevelFromEXP(player.GetEXP());
|
||||
long ceil = RPGExpTable.EXPCeil(level);
|
||||
|
||||
String indent = "";
|
||||
String linebreak = "\n";
|
||||
|
||||
String out = "";
|
||||
out += indent + "[" + player.GetName() + ", lv. " + level + "]";
|
||||
out += indent + linebreak;
|
||||
out += indent + "_______________";
|
||||
out += indent + linebreak;
|
||||
|
||||
out += indent + " EXP: " + exp;
|
||||
out += indent + " (until next: " + (ceil - exp) + ")";
|
||||
out += indent + linebreak;
|
||||
|
||||
out += indent + " Gold: " + player.GetGold();
|
||||
out += indent + linebreak;
|
||||
|
||||
out += indent + "Health: " + player.GetHealthCurrent() + "/" + player.GetHealthMax();
|
||||
out += indent + linebreak;
|
||||
|
||||
RPGWeapon weapon = player.GetWeapon();
|
||||
out += indent + "_____";
|
||||
out += indent + linebreak;
|
||||
out += indent + "Weapon: " + weapon.GetName();
|
||||
out += indent + linebreak;
|
||||
out += indent + " att: " + weapon.GetAttack();
|
||||
out += indent + linebreak;
|
||||
|
||||
RPGArmor armor = player.GetArmor();
|
||||
out += indent + "_____";
|
||||
out += indent + linebreak;
|
||||
out += indent + "Armor: " + armor.GetName();
|
||||
out += indent + linebreak;
|
||||
out += indent + " def: " + armor.GetDefense() ;
|
||||
out += indent + linebreak;
|
||||
|
||||
out += indent + linebreak;
|
||||
out += "Use 'info armor' / 'info weapon' for details!";
|
||||
|
||||
return "```\n" + out + "```";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user