Initial Commit

Initial commit of project.
This commit is contained in:
Alex Stewart
2019-03-09 01:21:44 -08:00
parent e54e9653ed
commit 13420951b1
124 changed files with 5883 additions and 0 deletions
+19
View File
@@ -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);
}
}
+146
View File
@@ -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;
}
}
+116
View File
@@ -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;
}
}
+94
View File
@@ -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 + "!");
}
}
}
+26
View File
@@ -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() +"`!");
}
}
+31
View File
@@ -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)] + "!");
}
}
+22
View File
@@ -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));
}
}
+33
View File
@@ -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");
}
}
+38
View File
@@ -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!");
}
}
}
+42
View File
@@ -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);
}
}
+135
View File
@@ -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;
}
}
+26
View File
@@ -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);
}
}
+20
View File
@@ -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");
}
}
+21
View File
@@ -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));
}
}
+362
View File
@@ -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;
}
}
+104
View File
@@ -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);
}
}
+26
View File
@@ -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!");
}
}
+40
View File
@@ -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;
}
}
}
+35
View File
@@ -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);
}
}
+30
View File
@@ -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);
}
}
+45
View File
@@ -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!");
}
}
+36
View File
@@ -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!");
}
}
+51
View File
@@ -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);
}
}
+31
View File
@@ -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));
}
}
+64
View File
@@ -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!");
}
}
+60
View File
@@ -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() + "`!");
}
}
+89
View File
@@ -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);
}
}
+53
View File
@@ -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);
}
}
}
+92
View File
@@ -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);
}
}
+66
View File
@@ -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);
}
}
+36
View File
@@ -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!");
}
}
}
+336
View File
@@ -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;
}
}
+36
View File
@@ -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;
}
}
+97
View File
@@ -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;
}
}
+92
View File
@@ -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;
}
}
+61
View File
@@ -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 + "```";
}
}