commit 3fef65b9030e49543700a67eac9d886fff43c648 Author: Big Pappa Date: Thu Aug 6 22:07:12 2026 -0500 Initial release v1.0.0 diff --git a/.git-pre-1.0/COMMIT_EDITMSG b/.git-pre-1.0/COMMIT_EDITMSG new file mode 100644 index 0000000..cf5c8bf --- /dev/null +++ b/.git-pre-1.0/COMMIT_EDITMSG @@ -0,0 +1,4 @@ +1.0.0 + +Fixed: +Issue with items showing in 2 spots when not assigned a spot. diff --git a/.git-pre-1.0/HEAD b/.git-pre-1.0/HEAD new file mode 100644 index 0000000..b870d82 --- /dev/null +++ b/.git-pre-1.0/HEAD @@ -0,0 +1 @@ +ref: refs/heads/main diff --git a/.git-pre-1.0/config b/.git-pre-1.0/config new file mode 100644 index 0000000..14107bf --- /dev/null +++ b/.git-pre-1.0/config @@ -0,0 +1,10 @@ +[core] + repositoryformatversion = 0 + filemode = false + bare = false + logallrefupdates = true + symlinks = false + ignorecase = true +[remote "origin"] + url = http://192.168.1.58:30008/truenas_admin/RS-Warehouse.git + fetch = +refs/heads/*:refs/remotes/origin/* diff --git a/.git-pre-1.0/description b/.git-pre-1.0/description new file mode 100644 index 0000000..498b267 --- /dev/null +++ b/.git-pre-1.0/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/.git-pre-1.0/hooks/applypatch-msg.sample b/.git-pre-1.0/hooks/applypatch-msg.sample new file mode 100644 index 0000000..a5d7b84 --- /dev/null +++ b/.git-pre-1.0/hooks/applypatch-msg.sample @@ -0,0 +1,15 @@ +#!/bin/sh +# +# An example hook script to check the commit log message taken by +# applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. The hook is +# allowed to edit the commit message file. +# +# To enable this hook, rename this file to "applypatch-msg". + +. git-sh-setup +commitmsg="$(git rev-parse --git-path hooks/commit-msg)" +test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"} +: diff --git a/.git-pre-1.0/hooks/commit-msg.sample b/.git-pre-1.0/hooks/commit-msg.sample new file mode 100644 index 0000000..f7458ef --- /dev/null +++ b/.git-pre-1.0/hooks/commit-msg.sample @@ -0,0 +1,74 @@ +#!/bin/sh +# +# An example hook script to check the commit log message. +# Called by "git commit" with one argument, the name of the file +# that has the commit message. The hook should exit with non-zero +# status after issuing an appropriate message if it wants to stop the +# commit. The hook is allowed to edit the commit message file. +# +# To enable this hook, rename this file to "commit-msg". + +# Uncomment the below to add a Signed-off-by line to the message. +# Doing this in a hook is a bad idea in general, but the prepare-commit-msg +# hook is more suited to it. +# +# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" + +# This example catches duplicate Signed-off-by lines and messages that +# would confuse 'git am'. + +ret=0 + +test "" = "$(grep '^Signed-off-by: ' "$1" | + sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { + echo >&2 Duplicate Signed-off-by lines. + ret=1 +} + +comment_re="$( + { + git config --get-regexp "^core\.comment(char|string)\$" || + echo '#' + } | sed -n -e ' + ${ + s/^[^ ]* // + s|[][*./\]|\\&|g + s/^auto$/[#;@!$%^&|:]/ + p + }' +)" +scissors_line="^${comment_re} -\{8,\} >8 -\{8,\}\$" +comment_line="^${comment_re}.*" +blank_line='^[ ]*$' +# Disallow lines starting with "diff -" or "Index: " in the body of the +# message. Stop looking if we see a scissors line. +line="$(sed -n -e " + # Skip comments and blank lines at the start of the file. + /${scissors_line}/q + /${comment_line}/d + /${blank_line}/d + # The first paragraph will become the subject header so + # does not need to be checked. + : subject + n + /${scissors_line}/q + /${blank_line}/!b subject + # Check the body of the message for problematic + # prefixes. + : body + n + /${scissors_line}/q + /${comment_line}/b body + /^diff -/{p;q;} + /^Index: /{p;q;} + b body + " "$1")" +if test -n "$line" +then + echo >&2 "Message contains a diff that will confuse 'git am'." + echo >&2 "To fix this indent the diff." + ret=1 +fi + +exit $ret diff --git a/.git-pre-1.0/hooks/fsmonitor-watchman.sample b/.git-pre-1.0/hooks/fsmonitor-watchman.sample new file mode 100644 index 0000000..429e0a5 --- /dev/null +++ b/.git-pre-1.0/hooks/fsmonitor-watchman.sample @@ -0,0 +1,168 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use IPC::Open2; + +# An example hook script to integrate Watchman +# (https://facebook.github.io/watchman/) with git to speed up detecting +# new and modified files. +# +# The hook is passed a version (currently 2) and last update token +# formatted as a string and outputs to stdout a new update token and +# all files that have been modified since the update token. Paths must +# be relative to the root of the working tree and separated by a single NUL. +# +# To enable this hook, rename this file to "query-watchman" and set +# 'git config core.fsmonitor .git/hooks/query-watchman' +# +my ($version, $last_update_token) = @ARGV; + +# Uncomment for debugging +# print STDERR "$0 $version $last_update_token\n"; + +# Check the hook interface version +if ($version ne 2) { + die "Unsupported query-fsmonitor hook version '$version'.\n" . + "Falling back to scanning...\n"; +} + +my $git_work_tree = get_working_dir(); + +my $json_pkg; +eval { + require JSON::XS; + $json_pkg = "JSON::XS"; + 1; +} or do { + require JSON::PP; + $json_pkg = "JSON::PP"; +}; + +launch_watchman(); + +sub launch_watchman { + my $o = watchman_query(); + if (is_work_tree_watched($o)) { + output_result($o->{clock}, @{$o->{files}}); + } +} + +sub output_result { + my ($clockid, @files) = @_; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # binmode $fh, ":utf8"; + # print $fh "$clockid\n@files\n"; + # close $fh; + + binmode STDOUT, ":utf8"; + print $clockid; + print "\0"; + local $, = "\0"; + print @files; +} + +sub watchman_clock { + my $response = qx/watchman clock "$git_work_tree"/; + die "Failed to get clock id on '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + + return $json_pkg->new->utf8->decode($response); +} + +sub watchman_query { + my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty') + or die "open2() failed: $!\n" . + "Falling back to scanning...\n"; + + # In the query expression below we're asking for names of files that + # changed since $last_update_token but not from the .git folder. + # + # To accomplish this, we're using the "since" generator to use the + # recency index to select candidate nodes and "fields" to limit the + # output to file names only. Then we're using the "expression" term to + # further constrain the results. + my $last_update_line = ""; + if (substr($last_update_token, 0, 1) eq "c") { + $last_update_token = "\"$last_update_token\""; + $last_update_line = qq[\n"since": $last_update_token,]; + } + my $query = <<" END"; + ["query", "$git_work_tree", {$last_update_line + "fields": ["name"], + "expression": ["not", ["dirname", ".git"]] + }] + END + + # Uncomment for debugging the watchman query + # open (my $fh, ">", ".git/watchman-query.json"); + # print $fh $query; + # close $fh; + + print CHLD_IN $query; + close CHLD_IN; + my $response = do {local $/; }; + + # Uncomment for debugging the watch response + # open ($fh, ">", ".git/watchman-response.json"); + # print $fh $response; + # close $fh; + + die "Watchman: command returned no output.\n" . + "Falling back to scanning...\n" if $response eq ""; + die "Watchman: command returned invalid output: $response\n" . + "Falling back to scanning...\n" unless $response =~ /^\{/; + + return $json_pkg->new->utf8->decode($response); +} + +sub is_work_tree_watched { + my ($output) = @_; + my $error = $output->{error}; + if ($error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) { + my $response = qx/watchman watch "$git_work_tree"/; + die "Failed to make watchman watch '$git_work_tree'.\n" . + "Falling back to scanning...\n" if $? != 0; + $output = $json_pkg->new->utf8->decode($response); + $error = $output->{error}; + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + # Uncomment for debugging watchman output + # open (my $fh, ">", ".git/watchman-output.out"); + # close $fh; + + # Watchman will always return all files on the first query so + # return the fast "everything is dirty" flag to git and do the + # Watchman query just to get it over with now so we won't pay + # the cost in git to look up each individual file. + my $o = watchman_clock(); + $error = $o->{error}; + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + output_result($o->{clock}, ("/")); + return 0; + } + + die "Watchman: $error.\n" . + "Falling back to scanning...\n" if $error; + + return 1; +} + +sub get_working_dir { + my $working_dir; + if ($^O =~ 'msys' || $^O =~ 'cygwin') { + $working_dir = Win32::GetCwd(); + $working_dir =~ tr/\\/\//; + } else { + require Cwd; + $working_dir = Cwd::cwd(); + } + + return $working_dir; +} diff --git a/.git-pre-1.0/hooks/post-update.sample b/.git-pre-1.0/hooks/post-update.sample new file mode 100644 index 0000000..ec17ec1 --- /dev/null +++ b/.git-pre-1.0/hooks/post-update.sample @@ -0,0 +1,8 @@ +#!/bin/sh +# +# An example hook script to prepare a packed repository for use over +# dumb transports. +# +# To enable this hook, rename this file to "post-update". + +exec git update-server-info diff --git a/.git-pre-1.0/hooks/pre-applypatch.sample b/.git-pre-1.0/hooks/pre-applypatch.sample new file mode 100644 index 0000000..4142082 --- /dev/null +++ b/.git-pre-1.0/hooks/pre-applypatch.sample @@ -0,0 +1,14 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed +# by applypatch from an e-mail message. +# +# The hook should exit with non-zero status after issuing an +# appropriate message if it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-applypatch". + +. git-sh-setup +precommit="$(git rev-parse --git-path hooks/pre-commit)" +test -x "$precommit" && exec "$precommit" ${1+"$@"} +: diff --git a/.git-pre-1.0/hooks/pre-commit.sample b/.git-pre-1.0/hooks/pre-commit.sample new file mode 100644 index 0000000..29ed5ee --- /dev/null +++ b/.git-pre-1.0/hooks/pre-commit.sample @@ -0,0 +1,49 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --type=bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 + +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff-index --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat <<\EOF +Error: Attempt to add a non-ASCII file name. + +This can cause problems if you want to work with people on other platforms. + +To be portable it is advisable to rename the file. + +If you know what you are doing you can disable this check using: + + git config hooks.allownonascii true +EOF + exit 1 +fi + +# If there are whitespace errors, print the offending file names and fail. +exec git diff-index --check --cached $against -- diff --git a/.git-pre-1.0/hooks/pre-merge-commit.sample b/.git-pre-1.0/hooks/pre-merge-commit.sample new file mode 100644 index 0000000..399eab1 --- /dev/null +++ b/.git-pre-1.0/hooks/pre-merge-commit.sample @@ -0,0 +1,13 @@ +#!/bin/sh +# +# An example hook script to verify what is about to be committed. +# Called by "git merge" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message to +# stderr if it wants to stop the merge commit. +# +# To enable this hook, rename this file to "pre-merge-commit". + +. git-sh-setup +test -x "$GIT_DIR/hooks/pre-commit" && + exec "$GIT_DIR/hooks/pre-commit" +: diff --git a/.git-pre-1.0/hooks/pre-push.sample b/.git-pre-1.0/hooks/pre-push.sample new file mode 100644 index 0000000..4ce688d --- /dev/null +++ b/.git-pre-1.0/hooks/pre-push.sample @@ -0,0 +1,53 @@ +#!/bin/sh + +# An example hook script to verify what is about to be pushed. Called by "git +# push" after it has checked the remote status, but before anything has been +# pushed. If this script exits with a non-zero status nothing will be pushed. +# +# This hook is called with the following parameters: +# +# $1 -- Name of the remote to which the push is being done +# $2 -- URL to which the push is being done +# +# If pushing without using a named remote those arguments will be equal. +# +# Information about the commits which are being pushed is supplied as lines to +# the standard input in the form: +# +# +# +# This sample shows how to prevent push of commits where the log message starts +# with "WIP" (work in progress). + +remote="$1" +url="$2" + +zero=$(git hash-object --stdin &2 "Found WIP commit in $local_ref, not pushing" + exit 1 + fi + fi +done + +exit 0 diff --git a/.git-pre-1.0/hooks/pre-rebase.sample b/.git-pre-1.0/hooks/pre-rebase.sample new file mode 100644 index 0000000..6cbef5c --- /dev/null +++ b/.git-pre-1.0/hooks/pre-rebase.sample @@ -0,0 +1,169 @@ +#!/bin/sh +# +# Copyright (c) 2006, 2008 Junio C Hamano +# +# The "pre-rebase" hook is run just before "git rebase" starts doing +# its job, and can prevent the command from running by exiting with +# non-zero status. +# +# The hook is called with the following parameters: +# +# $1 -- the upstream the series was forked from. +# $2 -- the branch being rebased (or empty when rebasing the current branch). +# +# This sample shows how to prevent topic branches that are already +# merged to 'next' branch from getting rebased, because allowing it +# would result in rebasing already published history. + +publish=next +basebranch="$1" +if test "$#" = 2 +then + topic="refs/heads/$2" +else + topic=`git symbolic-ref HEAD` || + exit 0 ;# we do not interrupt rebasing detached HEAD +fi + +case "$topic" in +refs/heads/??/*) + ;; +*) + exit 0 ;# we do not interrupt others. + ;; +esac + +# Now we are dealing with a topic branch being rebased +# on top of master. Is it OK to rebase it? + +# Does the topic really exist? +git show-ref -q "$topic" || { + echo >&2 "No such branch $topic" + exit 1 +} + +# Is topic fully merged to master? +not_in_master=`git rev-list --pretty=oneline ^master "$topic"` +if test -z "$not_in_master" +then + echo >&2 "$topic is fully merged to master; better remove it." + exit 1 ;# we could allow it, but there is no point. +fi + +# Is topic ever merged to next? If so you should not be rebasing it. +only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` +only_next_2=`git rev-list ^master ${publish} | sort` +if test "$only_next_1" = "$only_next_2" +then + not_in_topic=`git rev-list "^$topic" master` + if test -z "$not_in_topic" + then + echo >&2 "$topic is already up to date with master" + exit 1 ;# we could allow it, but there is no point. + else + exit 0 + fi +else + not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` + /usr/bin/perl -e ' + my $topic = $ARGV[0]; + my $msg = "* $topic has commits already merged to public branch:\n"; + my (%not_in_next) = map { + /^([0-9a-f]+) /; + ($1 => 1); + } split(/\n/, $ARGV[1]); + for my $elem (map { + /^([0-9a-f]+) (.*)$/; + [$1 => $2]; + } split(/\n/, $ARGV[2])) { + if (!exists $not_in_next{$elem->[0]}) { + if ($msg) { + print STDERR $msg; + undef $msg; + } + print STDERR " $elem->[1]\n"; + } + } + ' "$topic" "$not_in_next" "$not_in_master" + exit 1 +fi + +<<\DOC_END + +This sample hook safeguards topic branches that have been +published from being rewound. + +The workflow assumed here is: + + * Once a topic branch forks from "master", "master" is never + merged into it again (either directly or indirectly). + + * Once a topic branch is fully cooked and merged into "master", + it is deleted. If you need to build on top of it to correct + earlier mistakes, a new topic branch is created by forking at + the tip of the "master". This is not strictly necessary, but + it makes it easier to keep your history simple. + + * Whenever you need to test or publish your changes to topic + branches, merge them into "next" branch. + +The script, being an example, hardcodes the publish branch name +to be "next", but it is trivial to make it configurable via +$GIT_DIR/config mechanism. + +With this workflow, you would want to know: + +(1) ... if a topic branch has ever been merged to "next". Young + topic branches can have stupid mistakes you would rather + clean up before publishing, and things that have not been + merged into other branches can be easily rebased without + affecting other people. But once it is published, you would + not want to rewind it. + +(2) ... if a topic branch has been fully merged to "master". + Then you can delete it. More importantly, you should not + build on top of it -- other people may already want to + change things related to the topic as patches against your + "master", so if you need further changes, it is better to + fork the topic (perhaps with the same name) afresh from the + tip of "master". + +Let's look at this example: + + o---o---o---o---o---o---o---o---o---o "next" + / / / / + / a---a---b A / / + / / / / + / / c---c---c---c B / + / / / \ / + / / / b---b C \ / + / / / / \ / + ---o---o---o---o---o---o---o---o---o---o---o "master" + + +A, B and C are topic branches. + + * A has one fix since it was merged up to "next". + + * B has finished. It has been fully merged up to "master" and "next", + and is ready to be deleted. + + * C has not merged to "next" at all. + +We would want to allow C to be rebased, refuse A, and encourage +B to be deleted. + +To compute (1): + + git rev-list ^master ^topic next + git rev-list ^master next + + if these match, topic has not merged in next at all. + +To compute (2): + + git rev-list master..topic + + if this is empty, it is fully merged to "master". + +DOC_END diff --git a/.git-pre-1.0/hooks/pre-receive.sample b/.git-pre-1.0/hooks/pre-receive.sample new file mode 100644 index 0000000..a1fd29e --- /dev/null +++ b/.git-pre-1.0/hooks/pre-receive.sample @@ -0,0 +1,24 @@ +#!/bin/sh +# +# An example hook script to make use of push options. +# The example simply echoes all push options that start with 'echoback=' +# and rejects all pushes when the "reject" push option is used. +# +# To enable this hook, rename this file to "pre-receive". + +if test -n "$GIT_PUSH_OPTION_COUNT" +then + i=0 + while test "$i" -lt "$GIT_PUSH_OPTION_COUNT" + do + eval "value=\$GIT_PUSH_OPTION_$i" + case "$value" in + echoback=*) + echo "echo from the pre-receive-hook: ${value#*=}" >&2 + ;; + reject) + exit 1 + esac + i=$((i + 1)) + done +fi diff --git a/.git-pre-1.0/hooks/prepare-commit-msg.sample b/.git-pre-1.0/hooks/prepare-commit-msg.sample new file mode 100644 index 0000000..10fa14c --- /dev/null +++ b/.git-pre-1.0/hooks/prepare-commit-msg.sample @@ -0,0 +1,42 @@ +#!/bin/sh +# +# An example hook script to prepare the commit log message. +# Called by "git commit" with the name of the file that has the +# commit message, followed by the description of the commit +# message's source. The hook's purpose is to edit the commit +# message file. If the hook fails with a non-zero status, +# the commit is aborted. +# +# To enable this hook, rename this file to "prepare-commit-msg". + +# This hook includes three examples. The first one removes the +# "# Please enter the commit message..." help message. +# +# The second includes the output of "git diff --name-status -r" +# into the message, just before the "git status" output. It is +# commented because it doesn't cope with --amend or with squashed +# commits. +# +# The third example adds a Signed-off-by line to the message, that can +# still be edited. This is rarely a good idea. + +COMMIT_MSG_FILE=$1 +COMMIT_SOURCE=$2 +SHA1=$3 + +/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE" + +# case "$COMMIT_SOURCE,$SHA1" in +# ,|template,) +# /usr/bin/perl -i.bak -pe ' +# print "\n" . `git diff --cached --name-status -r` +# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;; +# *) ;; +# esac + +# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') +# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE" +# if test -z "$COMMIT_SOURCE" +# then +# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE" +# fi diff --git a/.git-pre-1.0/hooks/push-to-checkout.sample b/.git-pre-1.0/hooks/push-to-checkout.sample new file mode 100644 index 0000000..af5a0c0 --- /dev/null +++ b/.git-pre-1.0/hooks/push-to-checkout.sample @@ -0,0 +1,78 @@ +#!/bin/sh + +# An example hook script to update a checked-out tree on a git push. +# +# This hook is invoked by git-receive-pack(1) when it reacts to git +# push and updates reference(s) in its repository, and when the push +# tries to update the branch that is currently checked out and the +# receive.denyCurrentBranch configuration variable is set to +# updateInstead. +# +# By default, such a push is refused if the working tree and the index +# of the remote repository has any difference from the currently +# checked out commit; when both the working tree and the index match +# the current commit, they are updated to match the newly pushed tip +# of the branch. This hook is to be used to override the default +# behaviour; however the code below reimplements the default behaviour +# as a starting point for convenient modification. +# +# The hook receives the commit with which the tip of the current +# branch is going to be updated: +commit=$1 + +# It can exit with a non-zero status to refuse the push (when it does +# so, it must not modify the index or the working tree). +die () { + echo >&2 "$*" + exit 1 +} + +# Or it can make any necessary changes to the working tree and to the +# index to bring them to the desired state when the tip of the current +# branch is updated to the new commit, and exit with a zero status. +# +# For example, the hook can simply run git read-tree -u -m HEAD "$1" +# in order to emulate git fetch that is run in the reverse direction +# with git push, as the two-tree form of git read-tree -u -m is +# essentially the same as git switch or git checkout that switches +# branches while keeping the local changes in the working tree that do +# not interfere with the difference between the branches. + +# The below is a more-or-less exact translation to shell of the C code +# for the default behaviour for git's push-to-checkout hook defined in +# the push_to_deploy() function in builtin/receive-pack.c. +# +# Note that the hook will be executed from the repository directory, +# not from the working tree, so if you want to perform operations on +# the working tree, you will have to adapt your code accordingly, e.g. +# by adding "cd .." or using relative paths. + +if ! git update-index -q --ignore-submodules --refresh +then + die "Up-to-date check failed" +fi + +if ! git diff-files --quiet --ignore-submodules -- +then + die "Working directory has unstaged changes" +fi + +# This is a rough translation of: +# +# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX +if git cat-file -e HEAD 2>/dev/null +then + head=HEAD +else + head=$(git hash-object -t tree --stdin &2 + exit 1 +} + +unset GIT_DIR GIT_WORK_TREE +cd "$worktree" && + +if grep -q "^diff --git " "$1" +then + validate_patch "$1" +else + validate_cover_letter "$1" +fi && + +if test "$GIT_SENDEMAIL_FILE_COUNTER" = "$GIT_SENDEMAIL_FILE_TOTAL" +then + git config --unset-all sendemail.validateWorktree && + trap 'git worktree remove -ff "$worktree"' EXIT && + validate_series +fi diff --git a/.git-pre-1.0/hooks/update.sample b/.git-pre-1.0/hooks/update.sample new file mode 100644 index 0000000..c4d426b --- /dev/null +++ b/.git-pre-1.0/hooks/update.sample @@ -0,0 +1,128 @@ +#!/bin/sh +# +# An example hook script to block unannotated tags from entering. +# Called by "git receive-pack" with arguments: refname sha1-old sha1-new +# +# To enable this hook, rename this file to "update". +# +# Config +# ------ +# hooks.allowunannotated +# This boolean sets whether unannotated tags will be allowed into the +# repository. By default they won't be. +# hooks.allowdeletetag +# This boolean sets whether deleting tags will be allowed in the +# repository. By default they won't be. +# hooks.allowmodifytag +# This boolean sets whether a tag may be modified after creation. By default +# it won't be. +# hooks.allowdeletebranch +# This boolean sets whether deleting branches will be allowed in the +# repository. By default they won't be. +# hooks.denycreatebranch +# This boolean sets whether remotely creating branches will be denied +# in the repository. By default this is allowed. +# + +# --- Command line +refname="$1" +oldrev="$2" +newrev="$3" + +# --- Safety check +if [ -z "$GIT_DIR" ]; then + echo "Don't run this script from the command line." >&2 + echo " (if you want, you could supply GIT_DIR then run" >&2 + echo " $0 )" >&2 + exit 1 +fi + +if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then + echo "usage: $0 " >&2 + exit 1 +fi + +# --- Config +allowunannotated=$(git config --type=bool hooks.allowunannotated) +allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch) +denycreatebranch=$(git config --type=bool hooks.denycreatebranch) +allowdeletetag=$(git config --type=bool hooks.allowdeletetag) +allowmodifytag=$(git config --type=bool hooks.allowmodifytag) + +# check for no description +projectdesc=$(sed -e '1q' "$GIT_DIR/description") +case "$projectdesc" in +"Unnamed repository"* | "") + echo "*** Project description file hasn't been set" >&2 + exit 1 + ;; +esac + +# --- Check types +# if $newrev is 0000...0000, it's a commit to delete a ref. +zero=$(git hash-object --stdin &2 + echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 + exit 1 + fi + ;; + refs/tags/*,delete) + # delete tag + if [ "$allowdeletetag" != "true" ]; then + echo "*** Deleting a tag is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/tags/*,tag) + # annotated tag + if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 + then + echo "*** Tag '$refname' already exists." >&2 + echo "*** Modifying a tag is not allowed in this repository." >&2 + exit 1 + fi + ;; + refs/heads/*,commit) + # branch + if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then + echo "*** Creating a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/heads/*,delete) + # delete branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + refs/remotes/*,commit) + # tracking branch + ;; + refs/remotes/*,delete) + # delete tracking branch + if [ "$allowdeletebranch" != "true" ]; then + echo "*** Deleting a tracking branch is not allowed in this repository" >&2 + exit 1 + fi + ;; + *) + # Anything else (is there anything else?) + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 + exit 1 + ;; +esac + +# --- Finished +exit 0 diff --git a/.git-pre-1.0/index b/.git-pre-1.0/index new file mode 100644 index 0000000..ae2e5ce Binary files /dev/null and b/.git-pre-1.0/index differ diff --git a/.git-pre-1.0/info/exclude b/.git-pre-1.0/info/exclude new file mode 100644 index 0000000..a5196d1 --- /dev/null +++ b/.git-pre-1.0/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/.git-pre-1.0/info/refs b/.git-pre-1.0/info/refs new file mode 100644 index 0000000..308a435 --- /dev/null +++ b/.git-pre-1.0/info/refs @@ -0,0 +1,2 @@ +b01f07cdfffd00ab4f70a530de81473dbaa79268 refs/heads/main +67941294fcc5198d307f35b7d1342d24c4e6cba1 refs/remotes/origin/main diff --git a/.git-pre-1.0/logs/HEAD b/.git-pre-1.0/logs/HEAD new file mode 100644 index 0000000..e33cd42 --- /dev/null +++ b/.git-pre-1.0/logs/HEAD @@ -0,0 +1,63 @@ +0000000000000000000000000000000000000000 2499874d7abf86a7ca0a32f7ef613ef211f17ebe Big Pappa 1781583929 -0500 commit (initial): Initial RS-Warehouse 0.0.0 +2499874d7abf86a7ca0a32f7ef613ef211f17ebe ca60ded60927ff58cc2d09e4aaacac830d2faed9 Big Pappa 1781594437 -0500 commit: Development Backup +ca60ded60927ff58cc2d09e4aaacac830d2faed9 82e3d21ca71d70033417d25d24fd18164cfe5702 Big Pappa 1781620812 -0500 commit: RS-Warehouse update to 0.0.2 +82e3d21ca71d70033417d25d24fd18164cfe5702 cbb0d10b30dfe8e99c6caf73b0593860f56d8675 Big Pappa 1781668541 -0500 commit: RS-Warehouse update to 0.0.3 +cbb0d10b30dfe8e99c6caf73b0593860f56d8675 aa7a3bc819db9bc6d7132bcc594c72053862319e Big Pappa 1781679011 -0500 commit: RS-Warehouse update to 0.0.4 +aa7a3bc819db9bc6d7132bcc594c72053862319e aa58ab74124fa31b472271dd1d467cba759c1dd2 Big Pappa 1781733670 -0500 commit: RS-Warehouse update to 0.0.5 +aa58ab74124fa31b472271dd1d467cba759c1dd2 b858ac9f30e078742944a86da1a07843bd4722ee Big Pappa 1781749935 -0500 commit: RS-Warehouse update to 0.0.6 +b858ac9f30e078742944a86da1a07843bd4722ee 73c049e8a05c09d847432337cab0bb415c9f55a2 Big Pappa 1781812099 -0500 commit: RS-Warehouse update to 0.0.7 +73c049e8a05c09d847432337cab0bb415c9f55a2 f4695ccf82f3c3003f12e10f296ad79098470962 Big Pappa 1781897083 -0500 commit: RS-Warehouse update to 0.0. +f4695ccf82f3c3003f12e10f296ad79098470962 3509a0df128df4188510c91b2abf1f38d0d1161c Big Pappa 1781981169 -0500 commit: RS-Warehouse update to 0.0.9 +3509a0df128df4188510c91b2abf1f38d0d1161c fc5565421b78e6e840c8d4fe15e317d1f388d377 Big Pappa 1781984020 -0500 commit: v0.0.10 +fc5565421b78e6e840c8d4fe15e317d1f388d377 b9867afc856a0bd21c84c43dcfb07b2049d1783d Big Pappa 1781984098 -0500 commit: v0.0.10 +b9867afc856a0bd21c84c43dcfb07b2049d1783d 2fe1d389f6b2bed2de8bd3606bb48bee48987824 Big Pappa 1781988464 -0500 commit: v0.0.11 +2fe1d389f6b2bed2de8bd3606bb48bee48987824 5ce977460035814b4d74b8737454d37e59e3d693 Big Pappa 1782102937 -0500 commit: v0.1.00 +5ce977460035814b4d74b8737454d37e59e3d693 aef5157e4c1e0a4d5daa4bd0b578d77bf167cc4f Big Pappa 1782113792 -0500 commit: v0.1.1 +aef5157e4c1e0a4d5daa4bd0b578d77bf167cc4f 872a129f08c4b020e414be5bfab77a3c8a53f26e Big Pappa 1782150397 -0500 commit: v0.1.2 +872a129f08c4b020e414be5bfab77a3c8a53f26e b8402c623396ad0784a99f99e7dd0dfa0d35730d Big Pappa 1782181698 -0500 commit: v0.2.0 +b8402c623396ad0784a99f99e7dd0dfa0d35730d efa20aedd22d171eee782abed595dd630099959d Big Pappa 1782186723 -0500 commit: v0.2.1 +efa20aedd22d171eee782abed595dd630099959d 7549a5a61af35d0fccfecef05c78f7e833d47799 Big Pappa 1782189618 -0500 commit: v0.3.0 +7549a5a61af35d0fccfecef05c78f7e833d47799 43e5314e778e82fc85dbd8f593c64409cce682e7 Big Pappa 1782202439 -0500 commit: v0.4.0 +43e5314e778e82fc85dbd8f593c64409cce682e7 38fc2130a465dfc46910ed90e53593c0b26c1c70 Big Pappa 1782272226 -0500 commit: v0.5.0 +38fc2130a465dfc46910ed90e53593c0b26c1c70 fa7d51df8c534570079c6d2c242a206405c6725e Big Pappa 1782272237 -0500 commit: v0.5.0 +fa7d51df8c534570079c6d2c242a206405c6725e b712addcfbeb95fca6782544500a5dd8bbfa7c28 Big Pappa 1782291273 -0500 commit: v0.6.0 +b712addcfbeb95fca6782544500a5dd8bbfa7c28 a2fe1972b46d94dbd7b9a3f86f8e8609afaee548 Big Pappa 1782320347 -0500 commit: v0.7.0 +a2fe1972b46d94dbd7b9a3f86f8e8609afaee548 a6e27369c699b6288c08932f04562f8800cc4ba0 Big Pappa 1782329883 -0500 commit: v0.7.1 +a6e27369c699b6288c08932f04562f8800cc4ba0 7e26b590c8f8663b06ce7fa5374520c6bc859073 Big Pappa 1782334831 -0500 commit: v0.7.2 +7e26b590c8f8663b06ce7fa5374520c6bc859073 f3d2015c396bb8bfb4dfe97f00f28b40ac7e5cbb Big Pappa 1782413022 -0500 commit: v0.8.0 +f3d2015c396bb8bfb4dfe97f00f28b40ac7e5cbb fbc09dca61cabd6a166d79a89fffd6fc96615ee3 Big Pappa 1782475989 -0500 commit: v0.9.0 +fbc09dca61cabd6a166d79a89fffd6fc96615ee3 c54b678ac7eec3e8ed82a38c87f46b3d1e7b0b23 Big Pappa 1782505517 -0500 commit: v0.9.1 +c54b678ac7eec3e8ed82a38c87f46b3d1e7b0b23 c355e563fb38e5e7998e8615aae71e1df1c4feaa Big Pappa 1782679800 -0500 commit: v0.9.2 +c355e563fb38e5e7998e8615aae71e1df1c4feaa 6097d189a04f6375d6ec441001ab8c72e69e7c76 Big Pappa 1782843548 -0500 commit: v0.10.0 +6097d189a04f6375d6ec441001ab8c72e69e7c76 6629401c3ac909a5270f4ac64f385df4d429caf3 Big Pappa 1782847021 -0500 commit: v0.10.1 +6629401c3ac909a5270f4ac64f385df4d429caf3 2016ea053f9845718f4435230f6581d40e05f4fa Big Pappa 1782848401 -0500 commit: v0.11.0 +2016ea053f9845718f4435230f6581d40e05f4fa dfc3727739f18ce14dfc5f364282ced02376df2f Big Pappa 1782858345 -0500 commit: v0.12.0 +dfc3727739f18ce14dfc5f364282ced02376df2f 5cc78a6d4caef52de0d3b77e07347f1b2710d6cc Big Pappa 1782883259 -0500 commit: v0.13.0 +5cc78a6d4caef52de0d3b77e07347f1b2710d6cc 3d4ebb9b18fa516ed0483f823203e63d908f2139 Big Pappa 1782892078 -0500 commit: v0.14.0 +3d4ebb9b18fa516ed0483f823203e63d908f2139 39eaa3f67a0ef64fed37530320dedb134f25a6c3 Big Pappa 1782929554 -0500 commit: v0.15.0 +39eaa3f67a0ef64fed37530320dedb134f25a6c3 0418832a140a12154cc2587eced7ce2bfb27b9fd Big Pappa 1782945264 -0500 commit: v0.16.0 +0418832a140a12154cc2587eced7ce2bfb27b9fd b76c9f770786652151e0cf61818bd96961d57ba6 Big Pappa 1782948612 -0500 commit: v0.17.0 +b76c9f770786652151e0cf61818bd96961d57ba6 51a04152ea23980635070f0b721a65b3701694d1 Big Pappa 1783020022 -0500 commit: v0.18.0 +51a04152ea23980635070f0b721a65b3701694d1 4ccfc9e5faa358a5f133cc7cfb7ebaf82fc84919 Big Pappa 1783367177 -0500 commit: v0.19.0 +4ccfc9e5faa358a5f133cc7cfb7ebaf82fc84919 9c4ef251fd0b98b7e000e20a1c68540770c7d83c Big Pappa 1783416396 -0500 commit: v0.20.0 +9c4ef251fd0b98b7e000e20a1c68540770c7d83c 1ccc406dbf0f440e3ecc1d5da94a11ca2d66179e Big Pappa 1783431619 -0500 commit: v0.20.0 +1ccc406dbf0f440e3ecc1d5da94a11ca2d66179e 7d26cd4ddd04cafe90cc9d24b27b412eaccc02d4 Big Pappa 1783462003 -0500 commit: v0.21.0 +7d26cd4ddd04cafe90cc9d24b27b412eaccc02d4 76c6894f0073441c23ad48ac931c8f02a1f9cd2d Big Pappa 1783504717 -0500 commit: v0.22.0 +76c6894f0073441c23ad48ac931c8f02a1f9cd2d 89e0995c150c4f143759983a8d1357189667b44d Big Pappa 1783509550 -0500 commit: v0.22.0 +89e0995c150c4f143759983a8d1357189667b44d f0873fb455ee34404e74a573da151660219d5658 Big Pappa 1783923430 -0500 commit: v0.23.0 +f0873fb455ee34404e74a573da151660219d5658 d299a41ec6c9bb5e63a793eec1e8b3d129e5da46 Big Pappa 1783934388 -0500 commit: v0.23.0 +d299a41ec6c9bb5e63a793eec1e8b3d129e5da46 aab96a938507320fdca7937873d5562145b502d4 Big Pappa 1783973975 -0500 commit: v0.30.0 +aab96a938507320fdca7937873d5562145b502d4 1852e9f15e8af7150f466466297bb184d705eb97 Big Pappa 1784137506 -0500 commit: v0.40.0 +1852e9f15e8af7150f466466297bb184d705eb97 8805b55f68fb69ced0061abb3bdb0f3cf7cacb67 Big Pappa 1784170630 -0500 commit: v0.40.1 +8805b55f68fb69ced0061abb3bdb0f3cf7cacb67 d443ed90408a2e02009b6223b2a36a0704c63ec9 Big Pappa 1784266802 -0500 commit: v0.40.2 +d443ed90408a2e02009b6223b2a36a0704c63ec9 fc48398f5f3496b06d0a27ba8cf2bdb06e399858 Big Pappa 1784576271 -0500 commit: v0.40.4 +fc48398f5f3496b06d0a27ba8cf2bdb06e399858 7ab2a8928d89f5ca8301ce2a3daa4d13ddc68e79 Big Pappa 1784678893 -0500 commit: v0.40.4 +7ab2a8928d89f5ca8301ce2a3daa4d13ddc68e79 7d1eeb06bf9f352658aef8be00c8b0fc88abb718 Big Pappa 1785098931 -0500 commit: v0.40.5 +7d1eeb06bf9f352658aef8be00c8b0fc88abb718 67941294fcc5198d307f35b7d1342d24c4e6cba1 Big Pappa 1785296491 -0500 commit: v0.50.1 +67941294fcc5198d307f35b7d1342d24c4e6cba1 b01f07cdfffd00ab4f70a530de81473dbaa79268 Big Pappa 1785312925 -0500 commit: v0.50.2 +b01f07cdfffd00ab4f70a530de81473dbaa79268 153dbfe75bf61a8fbbabc19541e62f15cf3b5f68 Big Pappa 1785320034 -0500 commit: v0.50.2 +153dbfe75bf61a8fbbabc19541e62f15cf3b5f68 951db2564705080a8d51749ab7ca681a6c5fe37e Big Pappa 1785357975 -0500 commit: v0.50.2 +951db2564705080a8d51749ab7ca681a6c5fe37e 5c5363c25682a6dc8a19262fc63d4b1f123e318b Big Pappa 1786034617 -0500 commit: 1.0.0 +5c5363c25682a6dc8a19262fc63d4b1f123e318b 003f9724e48adcf06b0ab65d6f41864743d18ba0 Big Pappa 1786057922 -0500 commit: 1.0.0 +003f9724e48adcf06b0ab65d6f41864743d18ba0 0000000000000000000000000000000000000000 Big Pappa 1786071787 -0500 Branch: renamed refs/heads/main to refs/heads/main +003f9724e48adcf06b0ab65d6f41864743d18ba0 003f9724e48adcf06b0ab65d6f41864743d18ba0 Big Pappa 1786071787 -0500 Branch: renamed refs/heads/main to refs/heads/main diff --git a/.git-pre-1.0/logs/refs/heads/main b/.git-pre-1.0/logs/refs/heads/main new file mode 100644 index 0000000..13549d7 --- /dev/null +++ b/.git-pre-1.0/logs/refs/heads/main @@ -0,0 +1,62 @@ +0000000000000000000000000000000000000000 2499874d7abf86a7ca0a32f7ef613ef211f17ebe Big Pappa 1781583929 -0500 commit (initial): Initial RS-Warehouse 0.0.0 +2499874d7abf86a7ca0a32f7ef613ef211f17ebe ca60ded60927ff58cc2d09e4aaacac830d2faed9 Big Pappa 1781594437 -0500 commit: Development Backup +ca60ded60927ff58cc2d09e4aaacac830d2faed9 82e3d21ca71d70033417d25d24fd18164cfe5702 Big Pappa 1781620812 -0500 commit: RS-Warehouse update to 0.0.2 +82e3d21ca71d70033417d25d24fd18164cfe5702 cbb0d10b30dfe8e99c6caf73b0593860f56d8675 Big Pappa 1781668541 -0500 commit: RS-Warehouse update to 0.0.3 +cbb0d10b30dfe8e99c6caf73b0593860f56d8675 aa7a3bc819db9bc6d7132bcc594c72053862319e Big Pappa 1781679011 -0500 commit: RS-Warehouse update to 0.0.4 +aa7a3bc819db9bc6d7132bcc594c72053862319e aa58ab74124fa31b472271dd1d467cba759c1dd2 Big Pappa 1781733670 -0500 commit: RS-Warehouse update to 0.0.5 +aa58ab74124fa31b472271dd1d467cba759c1dd2 b858ac9f30e078742944a86da1a07843bd4722ee Big Pappa 1781749935 -0500 commit: RS-Warehouse update to 0.0.6 +b858ac9f30e078742944a86da1a07843bd4722ee 73c049e8a05c09d847432337cab0bb415c9f55a2 Big Pappa 1781812099 -0500 commit: RS-Warehouse update to 0.0.7 +73c049e8a05c09d847432337cab0bb415c9f55a2 f4695ccf82f3c3003f12e10f296ad79098470962 Big Pappa 1781897083 -0500 commit: RS-Warehouse update to 0.0. +f4695ccf82f3c3003f12e10f296ad79098470962 3509a0df128df4188510c91b2abf1f38d0d1161c Big Pappa 1781981169 -0500 commit: RS-Warehouse update to 0.0.9 +3509a0df128df4188510c91b2abf1f38d0d1161c fc5565421b78e6e840c8d4fe15e317d1f388d377 Big Pappa 1781984020 -0500 commit: v0.0.10 +fc5565421b78e6e840c8d4fe15e317d1f388d377 b9867afc856a0bd21c84c43dcfb07b2049d1783d Big Pappa 1781984098 -0500 commit: v0.0.10 +b9867afc856a0bd21c84c43dcfb07b2049d1783d 2fe1d389f6b2bed2de8bd3606bb48bee48987824 Big Pappa 1781988464 -0500 commit: v0.0.11 +2fe1d389f6b2bed2de8bd3606bb48bee48987824 5ce977460035814b4d74b8737454d37e59e3d693 Big Pappa 1782102937 -0500 commit: v0.1.00 +5ce977460035814b4d74b8737454d37e59e3d693 aef5157e4c1e0a4d5daa4bd0b578d77bf167cc4f Big Pappa 1782113792 -0500 commit: v0.1.1 +aef5157e4c1e0a4d5daa4bd0b578d77bf167cc4f 872a129f08c4b020e414be5bfab77a3c8a53f26e Big Pappa 1782150397 -0500 commit: v0.1.2 +872a129f08c4b020e414be5bfab77a3c8a53f26e b8402c623396ad0784a99f99e7dd0dfa0d35730d Big Pappa 1782181698 -0500 commit: v0.2.0 +b8402c623396ad0784a99f99e7dd0dfa0d35730d efa20aedd22d171eee782abed595dd630099959d Big Pappa 1782186723 -0500 commit: v0.2.1 +efa20aedd22d171eee782abed595dd630099959d 7549a5a61af35d0fccfecef05c78f7e833d47799 Big Pappa 1782189618 -0500 commit: v0.3.0 +7549a5a61af35d0fccfecef05c78f7e833d47799 43e5314e778e82fc85dbd8f593c64409cce682e7 Big Pappa 1782202439 -0500 commit: v0.4.0 +43e5314e778e82fc85dbd8f593c64409cce682e7 38fc2130a465dfc46910ed90e53593c0b26c1c70 Big Pappa 1782272226 -0500 commit: v0.5.0 +38fc2130a465dfc46910ed90e53593c0b26c1c70 fa7d51df8c534570079c6d2c242a206405c6725e Big Pappa 1782272237 -0500 commit: v0.5.0 +fa7d51df8c534570079c6d2c242a206405c6725e b712addcfbeb95fca6782544500a5dd8bbfa7c28 Big Pappa 1782291273 -0500 commit: v0.6.0 +b712addcfbeb95fca6782544500a5dd8bbfa7c28 a2fe1972b46d94dbd7b9a3f86f8e8609afaee548 Big Pappa 1782320347 -0500 commit: v0.7.0 +a2fe1972b46d94dbd7b9a3f86f8e8609afaee548 a6e27369c699b6288c08932f04562f8800cc4ba0 Big Pappa 1782329883 -0500 commit: v0.7.1 +a6e27369c699b6288c08932f04562f8800cc4ba0 7e26b590c8f8663b06ce7fa5374520c6bc859073 Big Pappa 1782334831 -0500 commit: v0.7.2 +7e26b590c8f8663b06ce7fa5374520c6bc859073 f3d2015c396bb8bfb4dfe97f00f28b40ac7e5cbb Big Pappa 1782413022 -0500 commit: v0.8.0 +f3d2015c396bb8bfb4dfe97f00f28b40ac7e5cbb fbc09dca61cabd6a166d79a89fffd6fc96615ee3 Big Pappa 1782475989 -0500 commit: v0.9.0 +fbc09dca61cabd6a166d79a89fffd6fc96615ee3 c54b678ac7eec3e8ed82a38c87f46b3d1e7b0b23 Big Pappa 1782505517 -0500 commit: v0.9.1 +c54b678ac7eec3e8ed82a38c87f46b3d1e7b0b23 c355e563fb38e5e7998e8615aae71e1df1c4feaa Big Pappa 1782679800 -0500 commit: v0.9.2 +c355e563fb38e5e7998e8615aae71e1df1c4feaa 6097d189a04f6375d6ec441001ab8c72e69e7c76 Big Pappa 1782843548 -0500 commit: v0.10.0 +6097d189a04f6375d6ec441001ab8c72e69e7c76 6629401c3ac909a5270f4ac64f385df4d429caf3 Big Pappa 1782847021 -0500 commit: v0.10.1 +6629401c3ac909a5270f4ac64f385df4d429caf3 2016ea053f9845718f4435230f6581d40e05f4fa Big Pappa 1782848401 -0500 commit: v0.11.0 +2016ea053f9845718f4435230f6581d40e05f4fa dfc3727739f18ce14dfc5f364282ced02376df2f Big Pappa 1782858345 -0500 commit: v0.12.0 +dfc3727739f18ce14dfc5f364282ced02376df2f 5cc78a6d4caef52de0d3b77e07347f1b2710d6cc Big Pappa 1782883259 -0500 commit: v0.13.0 +5cc78a6d4caef52de0d3b77e07347f1b2710d6cc 3d4ebb9b18fa516ed0483f823203e63d908f2139 Big Pappa 1782892078 -0500 commit: v0.14.0 +3d4ebb9b18fa516ed0483f823203e63d908f2139 39eaa3f67a0ef64fed37530320dedb134f25a6c3 Big Pappa 1782929554 -0500 commit: v0.15.0 +39eaa3f67a0ef64fed37530320dedb134f25a6c3 0418832a140a12154cc2587eced7ce2bfb27b9fd Big Pappa 1782945264 -0500 commit: v0.16.0 +0418832a140a12154cc2587eced7ce2bfb27b9fd b76c9f770786652151e0cf61818bd96961d57ba6 Big Pappa 1782948612 -0500 commit: v0.17.0 +b76c9f770786652151e0cf61818bd96961d57ba6 51a04152ea23980635070f0b721a65b3701694d1 Big Pappa 1783020022 -0500 commit: v0.18.0 +51a04152ea23980635070f0b721a65b3701694d1 4ccfc9e5faa358a5f133cc7cfb7ebaf82fc84919 Big Pappa 1783367177 -0500 commit: v0.19.0 +4ccfc9e5faa358a5f133cc7cfb7ebaf82fc84919 9c4ef251fd0b98b7e000e20a1c68540770c7d83c Big Pappa 1783416396 -0500 commit: v0.20.0 +9c4ef251fd0b98b7e000e20a1c68540770c7d83c 1ccc406dbf0f440e3ecc1d5da94a11ca2d66179e Big Pappa 1783431619 -0500 commit: v0.20.0 +1ccc406dbf0f440e3ecc1d5da94a11ca2d66179e 7d26cd4ddd04cafe90cc9d24b27b412eaccc02d4 Big Pappa 1783462003 -0500 commit: v0.21.0 +7d26cd4ddd04cafe90cc9d24b27b412eaccc02d4 76c6894f0073441c23ad48ac931c8f02a1f9cd2d Big Pappa 1783504717 -0500 commit: v0.22.0 +76c6894f0073441c23ad48ac931c8f02a1f9cd2d 89e0995c150c4f143759983a8d1357189667b44d Big Pappa 1783509550 -0500 commit: v0.22.0 +89e0995c150c4f143759983a8d1357189667b44d f0873fb455ee34404e74a573da151660219d5658 Big Pappa 1783923430 -0500 commit: v0.23.0 +f0873fb455ee34404e74a573da151660219d5658 d299a41ec6c9bb5e63a793eec1e8b3d129e5da46 Big Pappa 1783934388 -0500 commit: v0.23.0 +d299a41ec6c9bb5e63a793eec1e8b3d129e5da46 aab96a938507320fdca7937873d5562145b502d4 Big Pappa 1783973975 -0500 commit: v0.30.0 +aab96a938507320fdca7937873d5562145b502d4 1852e9f15e8af7150f466466297bb184d705eb97 Big Pappa 1784137506 -0500 commit: v0.40.0 +1852e9f15e8af7150f466466297bb184d705eb97 8805b55f68fb69ced0061abb3bdb0f3cf7cacb67 Big Pappa 1784170630 -0500 commit: v0.40.1 +8805b55f68fb69ced0061abb3bdb0f3cf7cacb67 d443ed90408a2e02009b6223b2a36a0704c63ec9 Big Pappa 1784266802 -0500 commit: v0.40.2 +d443ed90408a2e02009b6223b2a36a0704c63ec9 fc48398f5f3496b06d0a27ba8cf2bdb06e399858 Big Pappa 1784576271 -0500 commit: v0.40.4 +fc48398f5f3496b06d0a27ba8cf2bdb06e399858 7ab2a8928d89f5ca8301ce2a3daa4d13ddc68e79 Big Pappa 1784678893 -0500 commit: v0.40.4 +7ab2a8928d89f5ca8301ce2a3daa4d13ddc68e79 7d1eeb06bf9f352658aef8be00c8b0fc88abb718 Big Pappa 1785098931 -0500 commit: v0.40.5 +7d1eeb06bf9f352658aef8be00c8b0fc88abb718 67941294fcc5198d307f35b7d1342d24c4e6cba1 Big Pappa 1785296491 -0500 commit: v0.50.1 +67941294fcc5198d307f35b7d1342d24c4e6cba1 b01f07cdfffd00ab4f70a530de81473dbaa79268 Big Pappa 1785312925 -0500 commit: v0.50.2 +b01f07cdfffd00ab4f70a530de81473dbaa79268 153dbfe75bf61a8fbbabc19541e62f15cf3b5f68 Big Pappa 1785320034 -0500 commit: v0.50.2 +153dbfe75bf61a8fbbabc19541e62f15cf3b5f68 951db2564705080a8d51749ab7ca681a6c5fe37e Big Pappa 1785357975 -0500 commit: v0.50.2 +951db2564705080a8d51749ab7ca681a6c5fe37e 5c5363c25682a6dc8a19262fc63d4b1f123e318b Big Pappa 1786034617 -0500 commit: 1.0.0 +5c5363c25682a6dc8a19262fc63d4b1f123e318b 003f9724e48adcf06b0ab65d6f41864743d18ba0 Big Pappa 1786057922 -0500 commit: 1.0.0 +003f9724e48adcf06b0ab65d6f41864743d18ba0 003f9724e48adcf06b0ab65d6f41864743d18ba0 Big Pappa 1786071787 -0500 Branch: renamed refs/heads/main to refs/heads/main diff --git a/.git-pre-1.0/objects/00/3f9724e48adcf06b0ab65d6f41864743d18ba0 b/.git-pre-1.0/objects/00/3f9724e48adcf06b0ab65d6f41864743d18ba0 new file mode 100644 index 0000000..a379d81 --- /dev/null +++ b/.git-pre-1.0/objects/00/3f9724e48adcf06b0ab65d6f41864743d18ba0 @@ -0,0 +1,5 @@ +x¥ŽAjÄ @»öÿô;3”2tQè®WøÑŸD5¨!íí;ô +ݾ�çKJ±ƒ–øÒ+3XôË”&é<: ²GëõŒaÒ&‡ +ñŠ$vªœ;o´Õ�uH6xGjB‹‹·:\gµ(Ô¬•›}+Þã +_´ï¯õh�óQ×J?©äp_ÅÇàKz5:+Í8!ÂE)Å“>G;ÿ#!Ô )ÄGüæpŸ­ gìÄΩAÛÊó +1BÛKopnœ!—ÔZ\3 ?3ˆ_” `Ù \ No newline at end of file diff --git a/.git-pre-1.0/objects/01/a36d563b889e12a73ea3ba9b61298325c5e6c7 b/.git-pre-1.0/objects/01/a36d563b889e12a73ea3ba9b61298325c5e6c7 new file mode 100644 index 0000000..fa70ad7 --- /dev/null +++ b/.git-pre-1.0/objects/01/a36d563b889e12a73ea3ba9b61298325c5e6c7 @@ -0,0 +1 @@ +x=Ê1Â0 @QæœÂ'¨èÌX±•C8ÆJ-BÙŽª¸;Û“þÏU3ÌóùÔ‘XHŸ“¹“Iiåð �7ÎapQ{ÿÁw‰KJ}ä*TÑ–ßt=ÚªÆ7ncÙ0VñàÆ{ú¤/DO, \ No newline at end of file diff --git a/.git-pre-1.0/objects/05/caa9970a260d34ace5ec3accb75f35b9e2b526 b/.git-pre-1.0/objects/05/caa9970a260d34ace5ec3accb75f35b9e2b526 new file mode 100644 index 0000000..ccfced0 Binary files /dev/null and b/.git-pre-1.0/objects/05/caa9970a260d34ace5ec3accb75f35b9e2b526 differ diff --git a/.git-pre-1.0/objects/06/d04659cdf7f38ab3fecafc1d918475fbb64d72 b/.git-pre-1.0/objects/06/d04659cdf7f38ab3fecafc1d918475fbb64d72 new file mode 100644 index 0000000..f9c3c05 Binary files /dev/null and b/.git-pre-1.0/objects/06/d04659cdf7f38ab3fecafc1d918475fbb64d72 differ diff --git a/.git-pre-1.0/objects/07/365705b95af7b82539f4beee71e137bdd3dc00 b/.git-pre-1.0/objects/07/365705b95af7b82539f4beee71e137bdd3dc00 new file mode 100644 index 0000000..61cd762 Binary files /dev/null and b/.git-pre-1.0/objects/07/365705b95af7b82539f4beee71e137bdd3dc00 differ diff --git a/.git-pre-1.0/objects/0f/b041ab9a3e50c32e214c4e5eccbca16bbc5c45 b/.git-pre-1.0/objects/0f/b041ab9a3e50c32e214c4e5eccbca16bbc5c45 new file mode 100644 index 0000000..91e176f Binary files /dev/null and b/.git-pre-1.0/objects/0f/b041ab9a3e50c32e214c4e5eccbca16bbc5c45 differ diff --git a/.git-pre-1.0/objects/10/0c4bc4d635022ca45e587d7ccb4c6793faee46 b/.git-pre-1.0/objects/10/0c4bc4d635022ca45e587d7ccb4c6793faee46 new file mode 100644 index 0000000..685b29a Binary files /dev/null and b/.git-pre-1.0/objects/10/0c4bc4d635022ca45e587d7ccb4c6793faee46 differ diff --git a/.git-pre-1.0/objects/12/3ade710a80790a98e3b809dc582d73b2dc4294 b/.git-pre-1.0/objects/12/3ade710a80790a98e3b809dc582d73b2dc4294 new file mode 100644 index 0000000..22ef780 Binary files /dev/null and b/.git-pre-1.0/objects/12/3ade710a80790a98e3b809dc582d73b2dc4294 differ diff --git a/.git-pre-1.0/objects/13/ce049bd7dc0cebc74f6b3481ae591e4de0ceca b/.git-pre-1.0/objects/13/ce049bd7dc0cebc74f6b3481ae591e4de0ceca new file mode 100644 index 0000000..18596ea Binary files /dev/null and b/.git-pre-1.0/objects/13/ce049bd7dc0cebc74f6b3481ae591e4de0ceca differ diff --git a/.git-pre-1.0/objects/14/d95a10aa13043845065aa1640e5bd73106e07b b/.git-pre-1.0/objects/14/d95a10aa13043845065aa1640e5bd73106e07b new file mode 100644 index 0000000..947d7e6 Binary files /dev/null and b/.git-pre-1.0/objects/14/d95a10aa13043845065aa1640e5bd73106e07b differ diff --git a/.git-pre-1.0/objects/15/3dbfe75bf61a8fbbabc19541e62f15cf3b5f68 b/.git-pre-1.0/objects/15/3dbfe75bf61a8fbbabc19541e62f15cf3b5f68 new file mode 100644 index 0000000..efdbff5 Binary files /dev/null and b/.git-pre-1.0/objects/15/3dbfe75bf61a8fbbabc19541e62f15cf3b5f68 differ diff --git a/.git-pre-1.0/objects/19/d1108c3ab541278310e83d598b836546a0ed3d b/.git-pre-1.0/objects/19/d1108c3ab541278310e83d598b836546a0ed3d new file mode 100644 index 0000000..8a12efc Binary files /dev/null and b/.git-pre-1.0/objects/19/d1108c3ab541278310e83d598b836546a0ed3d differ diff --git a/.git-pre-1.0/objects/1a/95bf9648a636d911e37882b2d3111863e1fb92 b/.git-pre-1.0/objects/1a/95bf9648a636d911e37882b2d3111863e1fb92 new file mode 100644 index 0000000..f22cfa7 Binary files /dev/null and b/.git-pre-1.0/objects/1a/95bf9648a636d911e37882b2d3111863e1fb92 differ diff --git a/.git-pre-1.0/objects/1e/a03c378b1e613898f18cebca08ffb8c57363c6 b/.git-pre-1.0/objects/1e/a03c378b1e613898f18cebca08ffb8c57363c6 new file mode 100644 index 0000000..8ffc9aa Binary files /dev/null and b/.git-pre-1.0/objects/1e/a03c378b1e613898f18cebca08ffb8c57363c6 differ diff --git a/.git-pre-1.0/objects/2b/43b549e4ef368f27b23e2227c2b276b94edfe3 b/.git-pre-1.0/objects/2b/43b549e4ef368f27b23e2227c2b276b94edfe3 new file mode 100644 index 0000000..005b19c Binary files /dev/null and b/.git-pre-1.0/objects/2b/43b549e4ef368f27b23e2227c2b276b94edfe3 differ diff --git a/.git-pre-1.0/objects/2c/5edf8a15831ae177af338986af362acc0dc590 b/.git-pre-1.0/objects/2c/5edf8a15831ae177af338986af362acc0dc590 new file mode 100644 index 0000000..9649bdc Binary files /dev/null and b/.git-pre-1.0/objects/2c/5edf8a15831ae177af338986af362acc0dc590 differ diff --git a/.git-pre-1.0/objects/2d/0915bcf166d79de4cffbc789b8611c377d21bc b/.git-pre-1.0/objects/2d/0915bcf166d79de4cffbc789b8611c377d21bc new file mode 100644 index 0000000..e301d17 Binary files /dev/null and b/.git-pre-1.0/objects/2d/0915bcf166d79de4cffbc789b8611c377d21bc differ diff --git a/.git-pre-1.0/objects/2e/a1a4539f2fba8442f564adbe7dee01c0fb725e b/.git-pre-1.0/objects/2e/a1a4539f2fba8442f564adbe7dee01c0fb725e new file mode 100644 index 0000000..357df29 Binary files /dev/null and b/.git-pre-1.0/objects/2e/a1a4539f2fba8442f564adbe7dee01c0fb725e differ diff --git a/.git-pre-1.0/objects/38/65bd8e0b9c5bbbd4abc33898b0a71f7a0628bd b/.git-pre-1.0/objects/38/65bd8e0b9c5bbbd4abc33898b0a71f7a0628bd new file mode 100644 index 0000000..9508410 Binary files /dev/null and b/.git-pre-1.0/objects/38/65bd8e0b9c5bbbd4abc33898b0a71f7a0628bd differ diff --git a/.git-pre-1.0/objects/3a/f202a42b5d541830d39daf6b5e3f7e4e6334dd b/.git-pre-1.0/objects/3a/f202a42b5d541830d39daf6b5e3f7e4e6334dd new file mode 100644 index 0000000..f8c6537 Binary files /dev/null and b/.git-pre-1.0/objects/3a/f202a42b5d541830d39daf6b5e3f7e4e6334dd differ diff --git a/.git-pre-1.0/objects/3b/f9143247bb4778ba384e2b474ce0b0e2823cfe b/.git-pre-1.0/objects/3b/f9143247bb4778ba384e2b474ce0b0e2823cfe new file mode 100644 index 0000000..df878d2 Binary files /dev/null and b/.git-pre-1.0/objects/3b/f9143247bb4778ba384e2b474ce0b0e2823cfe differ diff --git a/.git-pre-1.0/objects/3d/15d25103d8da32a89a0747c0bb3778654758c0 b/.git-pre-1.0/objects/3d/15d25103d8da32a89a0747c0bb3778654758c0 new file mode 100644 index 0000000..4dabfd8 Binary files /dev/null and b/.git-pre-1.0/objects/3d/15d25103d8da32a89a0747c0bb3778654758c0 differ diff --git a/.git-pre-1.0/objects/3d/3e6cc0841729a20d7ccd9a741971e2e08cadbd b/.git-pre-1.0/objects/3d/3e6cc0841729a20d7ccd9a741971e2e08cadbd new file mode 100644 index 0000000..407b313 Binary files /dev/null and b/.git-pre-1.0/objects/3d/3e6cc0841729a20d7ccd9a741971e2e08cadbd differ diff --git a/.git-pre-1.0/objects/3d/eea135869843563fdb1165aceba5c119567ca1 b/.git-pre-1.0/objects/3d/eea135869843563fdb1165aceba5c119567ca1 new file mode 100644 index 0000000..3330d07 Binary files /dev/null and b/.git-pre-1.0/objects/3d/eea135869843563fdb1165aceba5c119567ca1 differ diff --git a/.git-pre-1.0/objects/3f/04136ec6f8147f5fc97b89d555ab154a0fa0c3 b/.git-pre-1.0/objects/3f/04136ec6f8147f5fc97b89d555ab154a0fa0c3 new file mode 100644 index 0000000..765b699 Binary files /dev/null and b/.git-pre-1.0/objects/3f/04136ec6f8147f5fc97b89d555ab154a0fa0c3 differ diff --git a/.git-pre-1.0/objects/3f/4fab88a50a49d64299d9aa598332944d1a9203 b/.git-pre-1.0/objects/3f/4fab88a50a49d64299d9aa598332944d1a9203 new file mode 100644 index 0000000..2250f7f Binary files /dev/null and b/.git-pre-1.0/objects/3f/4fab88a50a49d64299d9aa598332944d1a9203 differ diff --git a/.git-pre-1.0/objects/40/f09d8f822ebc96117541c56c6d1888f7b925de b/.git-pre-1.0/objects/40/f09d8f822ebc96117541c56c6d1888f7b925de new file mode 100644 index 0000000..c5a4127 Binary files /dev/null and b/.git-pre-1.0/objects/40/f09d8f822ebc96117541c56c6d1888f7b925de differ diff --git a/.git-pre-1.0/objects/4c/0c90a62ada915a4e7668c88b95fcc3725dfad7 b/.git-pre-1.0/objects/4c/0c90a62ada915a4e7668c88b95fcc3725dfad7 new file mode 100644 index 0000000..26da0bc --- /dev/null +++ b/.git-pre-1.0/objects/4c/0c90a62ada915a4e7668c88b95fcc3725dfad7 @@ -0,0 +1 @@ +x%ÆA! Pל‚LÂÚ¥ÎN½Ca¦(釘‰ñyy±hô!„S§ô¤Ì>i] H&}HË¿¿Èx× ^h«Òþ‚ц³s}Æ"ɧB€¿Ðà¬v¬›Œ« :TùÎmÞƒ›»�ûlj,u \ No newline at end of file diff --git a/.git-pre-1.0/objects/4c/e4417b9d46e7ffb2bf1a47964d27675f383d2b b/.git-pre-1.0/objects/4c/e4417b9d46e7ffb2bf1a47964d27675f383d2b new file mode 100644 index 0000000..b2e54a8 Binary files /dev/null and b/.git-pre-1.0/objects/4c/e4417b9d46e7ffb2bf1a47964d27675f383d2b differ diff --git a/.git-pre-1.0/objects/4d/31deee871a5835aa028f17e66d28b12e0005f7 b/.git-pre-1.0/objects/4d/31deee871a5835aa028f17e66d28b12e0005f7 new file mode 100644 index 0000000..b4a3afe --- /dev/null +++ b/.git-pre-1.0/objects/4d/31deee871a5835aa028f17e66d28b12e0005f7 @@ -0,0 +1,4 @@ +xÍVMoÛ0 Ý9¿BëÉÆ6a_VdÁ¬A‚¤Å°S¡Øj"D–\Iî ýï%Ë‘k§CóÁ‘Cêññ‘¢½är‰Þ:üü¢$Ù†¬(Êd�•Ö™b¥abe׿ˆ¢kYiŠ3bèJªm³ 93Gƒ+J©Ì½[I^0�Ý='_”¹ÅÖx_O¦GOÑTk&…Æcd©,üŸÏ‰5!ª¢Ù‘'S”˲!9± +FøŒeª&TTÿ,mmâä§þùÑ€…�¼–<§ +ϰëÔ=4d¤ZáeµÙ0ƒ©0ÌlñŒ“m$Cìpc]ðî§Däü>¯3¦ ÷y0@Ðcã°r«–÷­VVKûˆ2N´F¡öAVÈ$„ ú²ÍÉ©MØhlèÏÀ™¿Ä¬Ý?5ü�d9’¢M!i ¹ms@ˆw畆àÊ®Pò2qF¼¢¦Ù™¤-Dp»¯E�‘ mˆÈ¨¼BqÕ�¯dÚŠ `ŠšJ +<Àu»[:Nu ؘ Ü8ORL¯+Âu;UØz0<9}›Î^Nìb>>9»œ�‡ßGóƒýi¼šš!¤Ä9Í»A�ªè>JØ7z+¥¬îcC‹$EÇÇHTœ?I ßܨt=ŽŽ›��8\‰wH}�¡F?ÖÒµ¥e�F¼BCFÃÕ“ª¶Ç»7¢f]U<'TÓ× Á®+ +õëP�ÙµT[pi¼\;bÕœ±-O8[~dÍì0ìgdýÖ¸ ¿û­�óÛ׆Á¿!.tdkTº¸)zƒÞõîoçç ¨±ÎË’Š~¾¾úÉ>@²Eð.•‡ŽdÓÔ»ò~xŽò<@½º£ì]âAàßî öŸ©Øù²À•ûÖÄ»õޤ YÂQê¿)Nkâ´ê í.8™çÛ’öœÊÆE�"¶Çª.Ñ»}�ÔûšuOb á¾hÑä +³HÑBÞÐ…ÿ¶êÊç£ïC!„}óÜþ·/ùÇ \ No newline at end of file diff --git a/.git-pre-1.0/objects/4e/3aa7ae6ef142b35e0bce17f7c5950c1bb98b14 b/.git-pre-1.0/objects/4e/3aa7ae6ef142b35e0bce17f7c5950c1bb98b14 new file mode 100644 index 0000000..18d12b8 Binary files /dev/null and b/.git-pre-1.0/objects/4e/3aa7ae6ef142b35e0bce17f7c5950c1bb98b14 differ diff --git a/.git-pre-1.0/objects/4e/813b475a536557dfb88e26faeaaa90c228e84e b/.git-pre-1.0/objects/4e/813b475a536557dfb88e26faeaaa90c228e84e new file mode 100644 index 0000000..379d658 Binary files /dev/null and b/.git-pre-1.0/objects/4e/813b475a536557dfb88e26faeaaa90c228e84e differ diff --git a/.git-pre-1.0/objects/55/a57bd9f687ffd29130601da7c851f6b896867d b/.git-pre-1.0/objects/55/a57bd9f687ffd29130601da7c851f6b896867d new file mode 100644 index 0000000..ef11f3a Binary files /dev/null and b/.git-pre-1.0/objects/55/a57bd9f687ffd29130601da7c851f6b896867d differ diff --git a/.git-pre-1.0/objects/56/e00e09f253d17caa894365f14d117072d84bce b/.git-pre-1.0/objects/56/e00e09f253d17caa894365f14d117072d84bce new file mode 100644 index 0000000..af7a223 Binary files /dev/null and b/.git-pre-1.0/objects/56/e00e09f253d17caa894365f14d117072d84bce differ diff --git a/.git-pre-1.0/objects/57/1820270693f059df21f8ca515f8a47143d1020 b/.git-pre-1.0/objects/57/1820270693f059df21f8ca515f8a47143d1020 new file mode 100644 index 0000000..c9b656f Binary files /dev/null and b/.git-pre-1.0/objects/57/1820270693f059df21f8ca515f8a47143d1020 differ diff --git a/.git-pre-1.0/objects/58/64829a3132fd41a16701086b5c4cccbfc985b9 b/.git-pre-1.0/objects/58/64829a3132fd41a16701086b5c4cccbfc985b9 new file mode 100644 index 0000000..90ee167 Binary files /dev/null and b/.git-pre-1.0/objects/58/64829a3132fd41a16701086b5c4cccbfc985b9 differ diff --git a/.git-pre-1.0/objects/58/c04451c6e7ab13c6c841784976fa314718da7c b/.git-pre-1.0/objects/58/c04451c6e7ab13c6c841784976fa314718da7c new file mode 100644 index 0000000..cd5ed19 Binary files /dev/null and b/.git-pre-1.0/objects/58/c04451c6e7ab13c6c841784976fa314718da7c differ diff --git a/.git-pre-1.0/objects/5c/5363c25682a6dc8a19262fc63d4b1f123e318b b/.git-pre-1.0/objects/5c/5363c25682a6dc8a19262fc63d4b1f123e318b new file mode 100644 index 0000000..b5cc756 Binary files /dev/null and b/.git-pre-1.0/objects/5c/5363c25682a6dc8a19262fc63d4b1f123e318b differ diff --git a/.git-pre-1.0/objects/5e/58df6db7c6a757a4f4c99c7cc952df24b6414e b/.git-pre-1.0/objects/5e/58df6db7c6a757a4f4c99c7cc952df24b6414e new file mode 100644 index 0000000..5c5568d Binary files /dev/null and b/.git-pre-1.0/objects/5e/58df6db7c6a757a4f4c99c7cc952df24b6414e differ diff --git a/.git-pre-1.0/objects/61/24496e14f549282ebca2756dfdc87170fb9b6b b/.git-pre-1.0/objects/61/24496e14f549282ebca2756dfdc87170fb9b6b new file mode 100644 index 0000000..00a9b19 Binary files /dev/null and b/.git-pre-1.0/objects/61/24496e14f549282ebca2756dfdc87170fb9b6b differ diff --git a/.git-pre-1.0/objects/62/cf7d13a08c282752ec26c3b2d935d58212242a b/.git-pre-1.0/objects/62/cf7d13a08c282752ec26c3b2d935d58212242a new file mode 100644 index 0000000..ba038f1 Binary files /dev/null and b/.git-pre-1.0/objects/62/cf7d13a08c282752ec26c3b2d935d58212242a differ diff --git a/.git-pre-1.0/objects/63/7a511eb808f4d523ee7bfb829c315c38f3b39d b/.git-pre-1.0/objects/63/7a511eb808f4d523ee7bfb829c315c38f3b39d new file mode 100644 index 0000000..f4a21df Binary files /dev/null and b/.git-pre-1.0/objects/63/7a511eb808f4d523ee7bfb829c315c38f3b39d differ diff --git a/.git-pre-1.0/objects/64/e681ec731bae20d090e1800df608dea71e2551 b/.git-pre-1.0/objects/64/e681ec731bae20d090e1800df608dea71e2551 new file mode 100644 index 0000000..8d28d62 Binary files /dev/null and b/.git-pre-1.0/objects/64/e681ec731bae20d090e1800df608dea71e2551 differ diff --git a/.git-pre-1.0/objects/66/ac0fbe65eac74c80b16ba8d9b91425f114b011 b/.git-pre-1.0/objects/66/ac0fbe65eac74c80b16ba8d9b91425f114b011 new file mode 100644 index 0000000..715d597 Binary files /dev/null and b/.git-pre-1.0/objects/66/ac0fbe65eac74c80b16ba8d9b91425f114b011 differ diff --git a/.git-pre-1.0/objects/6b/57394b6352aaa4db4266a6b3c386148486894d b/.git-pre-1.0/objects/6b/57394b6352aaa4db4266a6b3c386148486894d new file mode 100644 index 0000000..ee372f3 --- /dev/null +++ b/.git-pre-1.0/objects/6b/57394b6352aaa4db4266a6b3c386148486894d @@ -0,0 +1,3 @@ +x+)JMU040f040031QðÉ,.IÍK- +JM²Š‹ô²Ë +ïäLÔ½ðà�Ňz…ÖŠÞÓ-Î8t”dæçA4%ªxæ‰|õÔÐÛ³¨4÷ï‰Â‚ß³³µ,1 \ No newline at end of file diff --git a/.git-pre-1.0/objects/6b/ca02b5b4ec05078120aefde5301be5398f1c00 b/.git-pre-1.0/objects/6b/ca02b5b4ec05078120aefde5301be5398f1c00 new file mode 100644 index 0000000..30b5a7b Binary files /dev/null and b/.git-pre-1.0/objects/6b/ca02b5b4ec05078120aefde5301be5398f1c00 differ diff --git a/.git-pre-1.0/objects/77/667f90a21eb33e2cc6f90b0c79b084fc2479de b/.git-pre-1.0/objects/77/667f90a21eb33e2cc6f90b0c79b084fc2479de new file mode 100644 index 0000000..3a3f21a Binary files /dev/null and b/.git-pre-1.0/objects/77/667f90a21eb33e2cc6f90b0c79b084fc2479de differ diff --git a/.git-pre-1.0/objects/78/42c8b4cb8d0742017a95e1d569ce805b66d6e9 b/.git-pre-1.0/objects/78/42c8b4cb8d0742017a95e1d569ce805b66d6e9 new file mode 100644 index 0000000..27e36d7 Binary files /dev/null and b/.git-pre-1.0/objects/78/42c8b4cb8d0742017a95e1d569ce805b66d6e9 differ diff --git a/.git-pre-1.0/objects/7d/3a406e6ce451654b545e18d83b5d5cd49dd4d2 b/.git-pre-1.0/objects/7d/3a406e6ce451654b545e18d83b5d5cd49dd4d2 new file mode 100644 index 0000000..7349e3d Binary files /dev/null and b/.git-pre-1.0/objects/7d/3a406e6ce451654b545e18d83b5d5cd49dd4d2 differ diff --git a/.git-pre-1.0/objects/87/caea6138c6ef56e6a3fea0286f75f29617d288 b/.git-pre-1.0/objects/87/caea6138c6ef56e6a3fea0286f75f29617d288 new file mode 100644 index 0000000..c254ec9 Binary files /dev/null and b/.git-pre-1.0/objects/87/caea6138c6ef56e6a3fea0286f75f29617d288 differ diff --git a/.git-pre-1.0/objects/89/ebfcd0801d44aef767f5cea22d49c6669e6a04 b/.git-pre-1.0/objects/89/ebfcd0801d44aef767f5cea22d49c6669e6a04 new file mode 100644 index 0000000..047324d Binary files /dev/null and b/.git-pre-1.0/objects/89/ebfcd0801d44aef767f5cea22d49c6669e6a04 differ diff --git a/.git-pre-1.0/objects/8c/74e90f09a6d6639fd5d841b2d1a832e901b98a b/.git-pre-1.0/objects/8c/74e90f09a6d6639fd5d841b2d1a832e901b98a new file mode 100644 index 0000000..093ee64 Binary files /dev/null and b/.git-pre-1.0/objects/8c/74e90f09a6d6639fd5d841b2d1a832e901b98a differ diff --git a/.git-pre-1.0/objects/8c/fcfd13ef32648f6de4ba6db9a1d05435c4ea17 b/.git-pre-1.0/objects/8c/fcfd13ef32648f6de4ba6db9a1d05435c4ea17 new file mode 100644 index 0000000..90bacbd Binary files /dev/null and b/.git-pre-1.0/objects/8c/fcfd13ef32648f6de4ba6db9a1d05435c4ea17 differ diff --git a/.git-pre-1.0/objects/8d/8f6e0905d4e86622b8709e4a852d0a4b97822b b/.git-pre-1.0/objects/8d/8f6e0905d4e86622b8709e4a852d0a4b97822b new file mode 100644 index 0000000..153b81a Binary files /dev/null and b/.git-pre-1.0/objects/8d/8f6e0905d4e86622b8709e4a852d0a4b97822b differ diff --git a/.git-pre-1.0/objects/90/02f9d05dd907e3e4c73ba86d3a62de8ff19707 b/.git-pre-1.0/objects/90/02f9d05dd907e3e4c73ba86d3a62de8ff19707 new file mode 100644 index 0000000..b21a3e7 Binary files /dev/null and b/.git-pre-1.0/objects/90/02f9d05dd907e3e4c73ba86d3a62de8ff19707 differ diff --git a/.git-pre-1.0/objects/95/1db2564705080a8d51749ab7ca681a6c5fe37e b/.git-pre-1.0/objects/95/1db2564705080a8d51749ab7ca681a6c5fe37e new file mode 100644 index 0000000..c082c5b Binary files /dev/null and b/.git-pre-1.0/objects/95/1db2564705080a8d51749ab7ca681a6c5fe37e differ diff --git a/.git-pre-1.0/objects/96/5a6e24d8a047502018a7dfce1b5856e3b613b7 b/.git-pre-1.0/objects/96/5a6e24d8a047502018a7dfce1b5856e3b613b7 new file mode 100644 index 0000000..2d47af3 Binary files /dev/null and b/.git-pre-1.0/objects/96/5a6e24d8a047502018a7dfce1b5856e3b613b7 differ diff --git a/.git-pre-1.0/objects/96/d4025f373135f533594f0b3d187db6bc6c4736 b/.git-pre-1.0/objects/96/d4025f373135f533594f0b3d187db6bc6c4736 new file mode 100644 index 0000000..9981dcd Binary files /dev/null and b/.git-pre-1.0/objects/96/d4025f373135f533594f0b3d187db6bc6c4736 differ diff --git a/.git-pre-1.0/objects/98/389e10e02620a82049013138909cb27e6d2dde b/.git-pre-1.0/objects/98/389e10e02620a82049013138909cb27e6d2dde new file mode 100644 index 0000000..1de085a Binary files /dev/null and b/.git-pre-1.0/objects/98/389e10e02620a82049013138909cb27e6d2dde differ diff --git a/.git-pre-1.0/objects/9b/6e4cf0d7cc95476f9dda06ce677868a117192f b/.git-pre-1.0/objects/9b/6e4cf0d7cc95476f9dda06ce677868a117192f new file mode 100644 index 0000000..126a509 Binary files /dev/null and b/.git-pre-1.0/objects/9b/6e4cf0d7cc95476f9dda06ce677868a117192f differ diff --git a/.git-pre-1.0/objects/9b/a60f2cbd6a72640af0bac05a494c9d7da37733 b/.git-pre-1.0/objects/9b/a60f2cbd6a72640af0bac05a494c9d7da37733 new file mode 100644 index 0000000..003327b Binary files /dev/null and b/.git-pre-1.0/objects/9b/a60f2cbd6a72640af0bac05a494c9d7da37733 differ diff --git a/.git-pre-1.0/objects/9f/30a6045b9268c4c231b8c4363f5e7dcafea294 b/.git-pre-1.0/objects/9f/30a6045b9268c4c231b8c4363f5e7dcafea294 new file mode 100644 index 0000000..9da0e4c Binary files /dev/null and b/.git-pre-1.0/objects/9f/30a6045b9268c4c231b8c4363f5e7dcafea294 differ diff --git a/.git-pre-1.0/objects/a2/3ed12ecbf59c4aaca39eeb99c27e9953b4ee77 b/.git-pre-1.0/objects/a2/3ed12ecbf59c4aaca39eeb99c27e9953b4ee77 new file mode 100644 index 0000000..6ad32d4 Binary files /dev/null and b/.git-pre-1.0/objects/a2/3ed12ecbf59c4aaca39eeb99c27e9953b4ee77 differ diff --git a/.git-pre-1.0/objects/a3/0e5a4b42d7e5d4ce60548fa59d33616d527201 b/.git-pre-1.0/objects/a3/0e5a4b42d7e5d4ce60548fa59d33616d527201 new file mode 100644 index 0000000..c9e8608 Binary files /dev/null and b/.git-pre-1.0/objects/a3/0e5a4b42d7e5d4ce60548fa59d33616d527201 differ diff --git a/.git-pre-1.0/objects/a3/227846e5d224078a76d9197a0a34cb44c455f4 b/.git-pre-1.0/objects/a3/227846e5d224078a76d9197a0a34cb44c455f4 new file mode 100644 index 0000000..fb2327e Binary files /dev/null and b/.git-pre-1.0/objects/a3/227846e5d224078a76d9197a0a34cb44c455f4 differ diff --git a/.git-pre-1.0/objects/a4/5c1cba928608dac43b552d67c421b79ccc3837 b/.git-pre-1.0/objects/a4/5c1cba928608dac43b552d67c421b79ccc3837 new file mode 100644 index 0000000..a51a539 Binary files /dev/null and b/.git-pre-1.0/objects/a4/5c1cba928608dac43b552d67c421b79ccc3837 differ diff --git a/.git-pre-1.0/objects/b0/d865f612861260ba30daf6c9c67f5499efb12b b/.git-pre-1.0/objects/b0/d865f612861260ba30daf6c9c67f5499efb12b new file mode 100644 index 0000000..462d4fe Binary files /dev/null and b/.git-pre-1.0/objects/b0/d865f612861260ba30daf6c9c67f5499efb12b differ diff --git a/.git-pre-1.0/objects/b1/000215825dc6c9bb3a0a6a5d986fe653eb2da0 b/.git-pre-1.0/objects/b1/000215825dc6c9bb3a0a6a5d986fe653eb2da0 new file mode 100644 index 0000000..b1b7472 Binary files /dev/null and b/.git-pre-1.0/objects/b1/000215825dc6c9bb3a0a6a5d986fe653eb2da0 differ diff --git a/.git-pre-1.0/objects/b4/1f03b15a67b056cd45f3f9f82f6cdff46f9e04 b/.git-pre-1.0/objects/b4/1f03b15a67b056cd45f3f9f82f6cdff46f9e04 new file mode 100644 index 0000000..7a409be Binary files /dev/null and b/.git-pre-1.0/objects/b4/1f03b15a67b056cd45f3f9f82f6cdff46f9e04 differ diff --git a/.git-pre-1.0/objects/b5/7489f9d18302c2317d0a66c825f4b607e34634 b/.git-pre-1.0/objects/b5/7489f9d18302c2317d0a66c825f4b607e34634 new file mode 100644 index 0000000..730cc5b Binary files /dev/null and b/.git-pre-1.0/objects/b5/7489f9d18302c2317d0a66c825f4b607e34634 differ diff --git a/.git-pre-1.0/objects/b8/1e66f6edf51af69ba071ad12be19b3708421bd b/.git-pre-1.0/objects/b8/1e66f6edf51af69ba071ad12be19b3708421bd new file mode 100644 index 0000000..747d2bc Binary files /dev/null and b/.git-pre-1.0/objects/b8/1e66f6edf51af69ba071ad12be19b3708421bd differ diff --git a/.git-pre-1.0/objects/bd/80165fccd781bd1f1cf58b51ce0ecb228396cf b/.git-pre-1.0/objects/bd/80165fccd781bd1f1cf58b51ce0ecb228396cf new file mode 100644 index 0000000..dbd96c0 Binary files /dev/null and b/.git-pre-1.0/objects/bd/80165fccd781bd1f1cf58b51ce0ecb228396cf differ diff --git a/.git-pre-1.0/objects/be/6f008c8de5e4a2c05c1138853ba86f8a8bbeb2 b/.git-pre-1.0/objects/be/6f008c8de5e4a2c05c1138853ba86f8a8bbeb2 new file mode 100644 index 0000000..d4d0801 Binary files /dev/null and b/.git-pre-1.0/objects/be/6f008c8de5e4a2c05c1138853ba86f8a8bbeb2 differ diff --git a/.git-pre-1.0/objects/bf/8553f0fa63816bb36aad321889d9aa18113045 b/.git-pre-1.0/objects/bf/8553f0fa63816bb36aad321889d9aa18113045 new file mode 100644 index 0000000..aad73d4 Binary files /dev/null and b/.git-pre-1.0/objects/bf/8553f0fa63816bb36aad321889d9aa18113045 differ diff --git a/.git-pre-1.0/objects/c0/91f0b5dff117b60c98a5a6bc1def04713753bc b/.git-pre-1.0/objects/c0/91f0b5dff117b60c98a5a6bc1def04713753bc new file mode 100644 index 0000000..8bcda04 Binary files /dev/null and b/.git-pre-1.0/objects/c0/91f0b5dff117b60c98a5a6bc1def04713753bc differ diff --git a/.git-pre-1.0/objects/c1/9ce9ce854396c1daed26e5fdf5066f945d3c6a b/.git-pre-1.0/objects/c1/9ce9ce854396c1daed26e5fdf5066f945d3c6a new file mode 100644 index 0000000..7b0f0fe Binary files /dev/null and b/.git-pre-1.0/objects/c1/9ce9ce854396c1daed26e5fdf5066f945d3c6a differ diff --git a/.git-pre-1.0/objects/c3/d02bf241629e830cb5067fab2ec5b6202234e6 b/.git-pre-1.0/objects/c3/d02bf241629e830cb5067fab2ec5b6202234e6 new file mode 100644 index 0000000..634b0bd Binary files /dev/null and b/.git-pre-1.0/objects/c3/d02bf241629e830cb5067fab2ec5b6202234e6 differ diff --git a/.git-pre-1.0/objects/c5/2c001ecff0ab68fa0c88e0006b343fdf9767c7 b/.git-pre-1.0/objects/c5/2c001ecff0ab68fa0c88e0006b343fdf9767c7 new file mode 100644 index 0000000..bae0dbd Binary files /dev/null and b/.git-pre-1.0/objects/c5/2c001ecff0ab68fa0c88e0006b343fdf9767c7 differ diff --git a/.git-pre-1.0/objects/c6/032fbe50b11cb7dd78b00c28b34d81041006a5 b/.git-pre-1.0/objects/c6/032fbe50b11cb7dd78b00c28b34d81041006a5 new file mode 100644 index 0000000..eb51343 Binary files /dev/null and b/.git-pre-1.0/objects/c6/032fbe50b11cb7dd78b00c28b34d81041006a5 differ diff --git a/.git-pre-1.0/objects/cd/7ab01c69c5ff00d52b667cd47760b61408d307 b/.git-pre-1.0/objects/cd/7ab01c69c5ff00d52b667cd47760b61408d307 new file mode 100644 index 0000000..305a609 Binary files /dev/null and b/.git-pre-1.0/objects/cd/7ab01c69c5ff00d52b667cd47760b61408d307 differ diff --git a/.git-pre-1.0/objects/cf/644a4ccd8919db1e93d58b9cd94fa122cc0aab b/.git-pre-1.0/objects/cf/644a4ccd8919db1e93d58b9cd94fa122cc0aab new file mode 100644 index 0000000..6147e72 Binary files /dev/null and b/.git-pre-1.0/objects/cf/644a4ccd8919db1e93d58b9cd94fa122cc0aab differ diff --git a/.git-pre-1.0/objects/d1/581b939b6938a23920a5174063a9d26ed3482d b/.git-pre-1.0/objects/d1/581b939b6938a23920a5174063a9d26ed3482d new file mode 100644 index 0000000..d62bf30 Binary files /dev/null and b/.git-pre-1.0/objects/d1/581b939b6938a23920a5174063a9d26ed3482d differ diff --git a/.git-pre-1.0/objects/db/bffc4131e908cf5c674803cba45031195aef41 b/.git-pre-1.0/objects/db/bffc4131e908cf5c674803cba45031195aef41 new file mode 100644 index 0000000..6b5dfe2 Binary files /dev/null and b/.git-pre-1.0/objects/db/bffc4131e908cf5c674803cba45031195aef41 differ diff --git a/.git-pre-1.0/objects/e0/249262d6f4ccdb5e61b031b3a662527b9876c9 b/.git-pre-1.0/objects/e0/249262d6f4ccdb5e61b031b3a662527b9876c9 new file mode 100644 index 0000000..016b946 Binary files /dev/null and b/.git-pre-1.0/objects/e0/249262d6f4ccdb5e61b031b3a662527b9876c9 differ diff --git a/.git-pre-1.0/objects/e0/e5d1cc99ec34272576aeea559fe187d6b8ba93 b/.git-pre-1.0/objects/e0/e5d1cc99ec34272576aeea559fe187d6b8ba93 new file mode 100644 index 0000000..4f387c3 Binary files /dev/null and b/.git-pre-1.0/objects/e0/e5d1cc99ec34272576aeea559fe187d6b8ba93 differ diff --git a/.git-pre-1.0/objects/e2/0980d6d4ddb800eee347122f6315eb3889d6db b/.git-pre-1.0/objects/e2/0980d6d4ddb800eee347122f6315eb3889d6db new file mode 100644 index 0000000..220c8ec Binary files /dev/null and b/.git-pre-1.0/objects/e2/0980d6d4ddb800eee347122f6315eb3889d6db differ diff --git a/.git-pre-1.0/objects/e7/81d97a54ae37d929e3204da59d9671c68223d1 b/.git-pre-1.0/objects/e7/81d97a54ae37d929e3204da59d9671c68223d1 new file mode 100644 index 0000000..022d747 --- /dev/null +++ b/.git-pre-1.0/objects/e7/81d97a54ae37d929e3204da59d9671c68223d1 @@ -0,0 +1,2 @@ +x=Ê1 +Ã0 @ÑÎ>…NÚ¥KÇ�-=„¬GÔ±ŒdSBèÝ›¡t{ðÌáv½_*Ò é6˜;™Ô&%�~£ñªÝy lœÔö?x‘ö¡ö˜…€2ºÃø›¦³ÍjüäÒgñÆ… Žð _— *� \ No newline at end of file diff --git a/.git-pre-1.0/objects/ea/9c5db9d386b871a83595de63c78767fa9927b9 b/.git-pre-1.0/objects/ea/9c5db9d386b871a83595de63c78767fa9927b9 new file mode 100644 index 0000000..93b6b9c Binary files /dev/null and b/.git-pre-1.0/objects/ea/9c5db9d386b871a83595de63c78767fa9927b9 differ diff --git a/.git-pre-1.0/objects/ec/143d5ae39c2032a7b66d807f37448f0de53602 b/.git-pre-1.0/objects/ec/143d5ae39c2032a7b66d807f37448f0de53602 new file mode 100644 index 0000000..f439d37 Binary files /dev/null and b/.git-pre-1.0/objects/ec/143d5ae39c2032a7b66d807f37448f0de53602 differ diff --git a/.git-pre-1.0/objects/f1/b5082328aacc6af4f8026388475acaad3c7203 b/.git-pre-1.0/objects/f1/b5082328aacc6af4f8026388475acaad3c7203 new file mode 100644 index 0000000..029f8db Binary files /dev/null and b/.git-pre-1.0/objects/f1/b5082328aacc6af4f8026388475acaad3c7203 differ diff --git a/.git-pre-1.0/objects/f2/cebb98ef105f9ea6f64437342283aa345ca5ca b/.git-pre-1.0/objects/f2/cebb98ef105f9ea6f64437342283aa345ca5ca new file mode 100644 index 0000000..2cc6133 Binary files /dev/null and b/.git-pre-1.0/objects/f2/cebb98ef105f9ea6f64437342283aa345ca5ca differ diff --git a/.git-pre-1.0/objects/f3/7f1a831caf4571f7f50161e7e720524e5b9e6b b/.git-pre-1.0/objects/f3/7f1a831caf4571f7f50161e7e720524e5b9e6b new file mode 100644 index 0000000..b0e0399 Binary files /dev/null and b/.git-pre-1.0/objects/f3/7f1a831caf4571f7f50161e7e720524e5b9e6b differ diff --git a/.git-pre-1.0/objects/f3/ffb87e0ed77052fa98adfb1c274cd33cb92dc6 b/.git-pre-1.0/objects/f3/ffb87e0ed77052fa98adfb1c274cd33cb92dc6 new file mode 100644 index 0000000..893fe23 Binary files /dev/null and b/.git-pre-1.0/objects/f3/ffb87e0ed77052fa98adfb1c274cd33cb92dc6 differ diff --git a/.git-pre-1.0/objects/f6/3e7571560668e84211b8f8e417959c0f4cbe0c b/.git-pre-1.0/objects/f6/3e7571560668e84211b8f8e417959c0f4cbe0c new file mode 100644 index 0000000..d926e09 Binary files /dev/null and b/.git-pre-1.0/objects/f6/3e7571560668e84211b8f8e417959c0f4cbe0c differ diff --git a/.git-pre-1.0/objects/fa/a21502f476a2e25a6e52aab982692b60f614ce b/.git-pre-1.0/objects/fa/a21502f476a2e25a6e52aab982692b60f614ce new file mode 100644 index 0000000..a3c6c72 --- /dev/null +++ b/.git-pre-1.0/objects/fa/a21502f476a2e25a6e52aab982692b60f614ce @@ -0,0 +1,3 @@ +x%ÆA +1 P×=EN0(.]ªK½Cš 5Ø6¥¿Eñî +n/f�tØw�åÉII¼,�nmXM¿¿¸ëÃ'táµXý Ì+N!´³ If€Î<4yß®«�‹¡eÞî\ô¦uÒ;| þ)0 \ No newline at end of file diff --git a/.git-pre-1.0/objects/fd/d749167f6b4ddba420531c63540498a06f88be b/.git-pre-1.0/objects/fd/d749167f6b4ddba420531c63540498a06f88be new file mode 100644 index 0000000..b538c9a Binary files /dev/null and b/.git-pre-1.0/objects/fd/d749167f6b4ddba420531c63540498a06f88be differ diff --git a/.git-pre-1.0/objects/fe/6e623bd6886270b5cd485c2be62beab4e1d86a b/.git-pre-1.0/objects/fe/6e623bd6886270b5cd485c2be62beab4e1d86a new file mode 100644 index 0000000..ed3e6b7 Binary files /dev/null and b/.git-pre-1.0/objects/fe/6e623bd6886270b5cd485c2be62beab4e1d86a differ diff --git a/.git-pre-1.0/objects/info/packs b/.git-pre-1.0/objects/info/packs new file mode 100644 index 0000000..994bab2 --- /dev/null +++ b/.git-pre-1.0/objects/info/packs @@ -0,0 +1,3 @@ +P pack-091227e431babe2a5e47fb5d2d6e3b5947591f33.pack +P pack-c635a9249202c299756cc28e67675855546a7a4d.pack + diff --git a/.git-pre-1.0/objects/pack/multi-pack-index b/.git-pre-1.0/objects/pack/multi-pack-index new file mode 100644 index 0000000..84d70b6 Binary files /dev/null and b/.git-pre-1.0/objects/pack/multi-pack-index differ diff --git a/.git-pre-1.0/objects/pack/pack-091227e431babe2a5e47fb5d2d6e3b5947591f33.idx b/.git-pre-1.0/objects/pack/pack-091227e431babe2a5e47fb5d2d6e3b5947591f33.idx new file mode 100644 index 0000000..6d79fd5 Binary files /dev/null and b/.git-pre-1.0/objects/pack/pack-091227e431babe2a5e47fb5d2d6e3b5947591f33.idx differ diff --git a/.git-pre-1.0/objects/pack/pack-091227e431babe2a5e47fb5d2d6e3b5947591f33.mtimes b/.git-pre-1.0/objects/pack/pack-091227e431babe2a5e47fb5d2d6e3b5947591f33.mtimes new file mode 100644 index 0000000..32fd5f8 Binary files /dev/null and b/.git-pre-1.0/objects/pack/pack-091227e431babe2a5e47fb5d2d6e3b5947591f33.mtimes differ diff --git a/.git-pre-1.0/objects/pack/pack-091227e431babe2a5e47fb5d2d6e3b5947591f33.pack b/.git-pre-1.0/objects/pack/pack-091227e431babe2a5e47fb5d2d6e3b5947591f33.pack new file mode 100644 index 0000000..5cbcfdb Binary files /dev/null and b/.git-pre-1.0/objects/pack/pack-091227e431babe2a5e47fb5d2d6e3b5947591f33.pack differ diff --git a/.git-pre-1.0/objects/pack/pack-091227e431babe2a5e47fb5d2d6e3b5947591f33.rev b/.git-pre-1.0/objects/pack/pack-091227e431babe2a5e47fb5d2d6e3b5947591f33.rev new file mode 100644 index 0000000..276680c Binary files /dev/null and b/.git-pre-1.0/objects/pack/pack-091227e431babe2a5e47fb5d2d6e3b5947591f33.rev differ diff --git a/.git-pre-1.0/objects/pack/pack-c635a9249202c299756cc28e67675855546a7a4d.idx b/.git-pre-1.0/objects/pack/pack-c635a9249202c299756cc28e67675855546a7a4d.idx new file mode 100644 index 0000000..9679fab Binary files /dev/null and b/.git-pre-1.0/objects/pack/pack-c635a9249202c299756cc28e67675855546a7a4d.idx differ diff --git a/.git-pre-1.0/objects/pack/pack-c635a9249202c299756cc28e67675855546a7a4d.pack b/.git-pre-1.0/objects/pack/pack-c635a9249202c299756cc28e67675855546a7a4d.pack new file mode 100644 index 0000000..11ae43a Binary files /dev/null and b/.git-pre-1.0/objects/pack/pack-c635a9249202c299756cc28e67675855546a7a4d.pack differ diff --git a/.git-pre-1.0/objects/pack/pack-c635a9249202c299756cc28e67675855546a7a4d.rev b/.git-pre-1.0/objects/pack/pack-c635a9249202c299756cc28e67675855546a7a4d.rev new file mode 100644 index 0000000..7861750 Binary files /dev/null and b/.git-pre-1.0/objects/pack/pack-c635a9249202c299756cc28e67675855546a7a4d.rev differ diff --git a/.git-pre-1.0/refs/heads/main b/.git-pre-1.0/refs/heads/main new file mode 100644 index 0000000..61fa9f7 --- /dev/null +++ b/.git-pre-1.0/refs/heads/main @@ -0,0 +1 @@ +003f9724e48adcf06b0ab65d6f41864743d18ba0 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..480bdf5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ +.kotlin + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..30cf57e --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Ignored default folder with query files +/queries/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..5cb71ef --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..bfe80fd --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..3bf9143 --- /dev/null +++ b/pom.xml @@ -0,0 +1,79 @@ + + + 4.0.0 + + com.rsscripting + RS-Warehouse + RS-Warehouse + 1.0.0 + + + 21 + 21 + UTF-8 + + + + + + + src/main/resources + true + + + database.db + + + + + src/main/resources + false + + + database.db + + + + + + + + + papermc-repo + https://repo.papermc.io/repository/maven-public/ + + + codemc-repo + https://repo.codemc.io/repository/maven-public/ + + + + + + + io.papermc.paper + paper-api + 1.21.6-R0.1-SNAPSHOT + provided + + + + org.xerial + sqlite-jdbc + 3.50.3.0 + + + + net.wesjd + anvilgui + 1.10.10-SNAPSHOT + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/RSWarehouse.java b/src/main/java/com/rsscripting/rswarehouse/RSWarehouse.java new file mode 100644 index 0000000..c8ce84f --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/RSWarehouse.java @@ -0,0 +1,164 @@ +package com.rsscripting.rswarehouse; + +import com.rsscripting.rswarehouse.admin.admindao.PurgeVariantsDAO; +import com.rsscripting.rswarehouse.chestautoprocess.ChestAutoProcessingTask; +import com.rsscripting.rswarehouse.commands.RSPluginCommand; +import com.rsscripting.rswarehouse.commands.RSTabCompleter; +import com.rsscripting.rswarehouse.commands.ShopCommand; +import com.rsscripting.rswarehouse.config.ConfigManager; +import com.rsscripting.rswarehouse.database.DatabaseManager; +import com.rsscripting.rswarehouse.registration.ListenerRegistration; +import com.rsscripting.rswarehouse.constants.RSConstants; +import com.rsscripting.rswarehouse.updatechecker.GitHubUpdateChecker; +import org.bukkit.command.PluginCommand; +import org.bukkit.plugin.java.JavaPlugin; + +public class RSWarehouse + extends JavaPlugin { + + private static RSWarehouse instance; + + @Override + public void onEnable() { + + saveDefaultConfig(); + + instance = this; + + /* CONFIG */ + ConfigManager.setup(); + + /* Database */ + DatabaseManager.initialize( + this + ); + + PurgeVariantsDAO + .purgeAll(); + + /* REGISTER LISTENERS */ + ListenerRegistration.registerAll( + this + ); + + /* REGISTER COMMANDS */ + registerCommands(); + + /* UPDATE CHECKER */ + GitHubUpdateChecker.checkForUpdates(); + + /* ENABLE MESSAGE */ + logEnabledMessage(); + + /* Start Chest Auto-Processing Tasks */ + startChestAutoProcessingTask(); + + } + + @Override + public void onDisable() { + + getLogger().info( + RSConstants.PLUGIN_NAME + + " Disabled" + ); + + } + + /* Register Commands method */ + private void registerCommands() { + + /* rswarehous command */ + PluginCommand command = + getCommand( + RSConstants.COMMAND_ALIAS + ); + + if (command != null) { + + command.setExecutor( + new RSPluginCommand() + ); + + command.setTabCompleter( + new RSTabCompleter() + ); + + } + + /* Shop Comment */ + PluginCommand shopCommand = getCommand("shop"); + + if (shopCommand != null) { + shopCommand.setExecutor(new ShopCommand()); + } + + } + + /* Start Chest Auto Processing Task method */ + private void startChestAutoProcessingTask() { + + boolean chestAutoProcessingEnabled = + ConfigManager.get() + .getBoolean( + "chest-auto-processing.enabled" + ); + + if (!chestAutoProcessingEnabled) { + + return; + + } + + int intervalSeconds = + ConfigManager.get() + .getInt( + "chest-auto-processing.interval-seconds" + ); + + if (intervalSeconds < 15) { + + getLogger().warning( + "Chest auto processing interval " + + "cannot be less than 15 seconds. " + + "Using 15 seconds." + ); + + intervalSeconds = 15; + + } + + new ChestAutoProcessingTask() + .runTaskTimer( + this, + intervalSeconds * 20L, + intervalSeconds * 20L + ); + + getLogger().info( + "Chest auto processing enabled. " + + "Interval: " + + intervalSeconds + + " seconds." + ); + + } + + /* Log Enabled Message */ + private void logEnabledMessage() { + + getLogger().info( + RSConstants.PLUGIN_NAME + + " Enabled" + ); + + } + + /* Get Instance */ + public static RSWarehouse getInstance() { + + return instance; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/AdminMenu.java b/src/main/java/com/rsscripting/rswarehouse/admin/AdminMenu.java new file mode 100644 index 0000000..1fa4916 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/AdminMenu.java @@ -0,0 +1,192 @@ +package com.rsscripting.rswarehouse.admin; + + +import com.rsscripting.rswarehouse.admin.admindao.WarehouseStatisticsDAO; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import com.rsscripting.rswarehouse.utils.VersionUtils; +import com.rsscripting.rswarehouse.updatechecker.GitHubUpdateChecker; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import net.kyori.adventure.text.Component; + +import java.util.List; + +public class AdminMenu { + + public static final String MENU_TITLE = "Admin"; + + public static void open( + Player player + ) { + + Inventory menu = + Bukkit.createInventory( + new RSMenuHolder( + "ADMIN" + ), + 54, + Component.text( + MENU_TITLE + ).color( + NamedTextColor.GOLD + ) + ); + + + /* + |-------------------------------------------------------------------------- + | FILLER + |-------------------------------------------------------------------------- + */ + + ItemStack filler = + RSMenuUtils.createFillerPane(); + + for (int i = 0; i < menu.getSize(); i++) { + + menu.setItem(i, filler); + + } + + /* +|-------------------------------------------------------------------------- +| BACK +|-------------------------------------------------------------------------- +*/ + + menu.setItem( + 4, + RSMenuUtils.createMenuItem( + + Material.OAK_DOOR, + + "§eBack" + + ) + ); + + /* + |-------------------------------------------------------------------------- + | RELOAD + |-------------------------------------------------------------------------- + */ + + menu.setItem( + 1, + RSMenuUtils.createMenuItem( + + Material.ENCHANTED_BOOK, + + "§cReload Plugin" + + ) + ); + + /* + |-------------------------------------------------------------------------- + | VERSION + |-------------------------------------------------------------------------- + */ + + menu.setItem( + 7, + RSMenuUtils.createMenuItemWithLore( + + Material.BOOK, + + "§ePlugin Version", + + List.of( + + "§7Installed: §f" + + VersionUtils.getVersion(), + + "", + + "§7Status: §f" + + GitHubUpdateChecker.getUpdateStatus(), + + "", + + "§7Latest: §f" + + ( + GitHubUpdateChecker.getLatestVersion() + == null + ? "Unknown" + : GitHubUpdateChecker.getLatestVersion() + ) + + ) + + ) + ); + + menu.setItem( + 10, + RSMenuUtils.createMenuItemWithLore( + Material.BOOKSHELF, + "§aCreate Category", + List.of( + "§7Create a new warehouse category." + ) + ) + ); + + menu.setItem( + 16, + RSMenuUtils.createMenuItemWithLore( + + Material.WRITABLE_BOOK, + + "§aWarehouse Statistics", + + List.of( + + "§7Total Unique Items: §f" + + String.format( + "%,d", + WarehouseStatisticsDAO.getTotalUniqueItems() + ), + + "§7Total Items: §f" + + String.format( + "%,d", + WarehouseStatisticsDAO.getTotalInventory() + ), + + "", + + "§7Unique Enchanted Variants: §f" + + String.format( + "%,d", + WarehouseStatisticsDAO.getTotalEnchantedVariants() + ), + + "§7Unique Damaged Variants: §f" + + String.format( + "%,d", + WarehouseStatisticsDAO.getTotalDamagedVariants() + ), + + "§7Unique Partially Filled Variants: §f" + + String.format( + "%,d", + WarehouseStatisticsDAO.getTotalPartiallyFilledVariants() + ) + + ) + + ) + ); + + + player.openInventory(menu); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/AdminMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/admin/AdminMenuListener.java new file mode 100644 index 0000000..4e813b4 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/AdminMenuListener.java @@ -0,0 +1,138 @@ +package com.rsscripting.rswarehouse.admin; + +import com.rsscripting.rswarehouse.config.ConfigManager; +import com.rsscripting.rswarehouse.conversion.ConvertMenuListener; +import com.rsscripting.rswarehouse.category.categorycreation.CategoryNameMenu; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.constants.RSConstants; +import com.rsscripting.rswarehouse.main.MainMenu; +import com.rsscripting.rswarehouse.navigation.NavigationManager; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import org.bukkit.block.Block; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.entity.Player; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; + +public class AdminMenuListener + implements Listener { + + private final ConvertMenuListener + conversionListener; + + public AdminMenuListener( + ConvertMenuListener conversionListener + ) { + + this.conversionListener = + conversionListener; + + } + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getWhoClicked() + instanceof Player player)) { + return; + } + + if (!(event.getInventory() + .getHolder() + instanceof RSMenuHolder holder)) { + return; + } + + if (!holder.getMenuId() + .equals( + "ADMIN" + )) { + return; + } + + event.setCancelled(true); + + /* + |-------------------------------------------------------------------------- + | SECURITY + |-------------------------------------------------------------------------- + */ + + if (!player.isOp() + || + + !player.hasPermission( + RSConstants.ADMIN_PERMISSION + )) { + + player.closeInventory(); + + return; + + } + + /* + |-------------------------------------------------------------------------- + | BACK + |-------------------------------------------------------------------------- + */ + + if (event.getRawSlot() == 4) { + + Block block = + conversionListener.getSelectedBlock(player); + + if (block == null) { + + player.closeInventory(); + + return; + + } + + GuiSessionManager + .getSession(player) + .setSelectedBlock(block); + + NavigationManager.openMain(player); + + return; + + } + + /* + |-------------------------------------------------------------------------- + | RELOAD + |-------------------------------------------------------------------------- + */ + + if (event.getRawSlot() == 1) { + + ConfigManager.reload(); + + RSMessageUtils.success( + player, + "Configuration reloaded." + ); + + AdminMenu.open( + player + ); + + } + + if (event.getRawSlot() == 10) { + + CategoryNameMenu.open( + player + ); + + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/admindao/CategoryPlacementDAO.java b/src/main/java/com/rsscripting/rswarehouse/admin/admindao/CategoryPlacementDAO.java new file mode 100644 index 0000000..8e9cb04 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/admindao/CategoryPlacementDAO.java @@ -0,0 +1,62 @@ +package com.rsscripting.rswarehouse.admin.admindao; + +import com.rsscripting.rswarehouse.database.DatabaseManager; + +import java.sql.Connection; +import java.sql.PreparedStatement; + +public class CategoryPlacementDAO { + + public static void assignPageSlot( + int categoryId, + int page, + int slot + ) { + + String sql = + """ + UPDATE warehouse_categories + SET page = ?, + slot = ? + WHERE id = ? + """; + + try ( + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + sql + ) + ) { + + statement.setInt( + 1, + page + ); + + statement.setInt( + 2, + slot + ); + + statement.setInt( + 3, + categoryId + ); + + statement.executeUpdate(); + + } + catch ( + Exception exception + ) { + + exception.printStackTrace(); + + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/admindao/CreateCategoryDAO.java b/src/main/java/com/rsscripting/rswarehouse/admin/admindao/CreateCategoryDAO.java new file mode 100644 index 0000000..ca55f41 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/admindao/CreateCategoryDAO.java @@ -0,0 +1,89 @@ +package com.rsscripting.rswarehouse.admin.admindao; + +import com.rsscripting.rswarehouse.database.DatabaseManager; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class CreateCategoryDAO { + + public static void createCategory( + String internalName, + String displayName, + String material, + String lore + ) { + + int nextDisplayOrder = 1; + + try ( + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + INSERT INTO warehouse_categories ( + internal_name, + display_name, + material, + lore, + display_order, + page, + slot + ) + VALUES ( + ?, ?, ?, ?, ?, ?, ? + ) + """ + ) + ) { + + try ( + PreparedStatement maxStatement = + connection.prepareStatement( + """ + SELECT COALESCE( + MAX(display_order), + 0 + ) + FROM warehouse_categories + """ + ) + ) { + + ResultSet resultSet = + maxStatement.executeQuery(); + + if (resultSet.next()) { + + nextDisplayOrder = + resultSet.getInt(1) + 1; + + } + + } + + statement.setString(1, internalName); + statement.setString(2, displayName); + statement.setString(3, material); + statement.setString(4, lore); + statement.setInt(5, nextDisplayOrder); + statement.setInt(6, 0); + statement.setInt(7, 0); + + statement.executeUpdate(); + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/admindao/CreateSubCategoryDAO.java b/src/main/java/com/rsscripting/rswarehouse/admin/admindao/CreateSubCategoryDAO.java new file mode 100644 index 0000000..51d3043 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/admindao/CreateSubCategoryDAO.java @@ -0,0 +1,136 @@ +package com.rsscripting.rswarehouse.admin.admindao; + +import com.rsscripting.rswarehouse.database.DatabaseManager; + +import java.sql.*; + +public class CreateSubCategoryDAO { + + public static int createSubCategory( + int parentCategoryId, + String internalName, + String displayName, + String material, + String lore + ) { + + int nextDisplayOrder = 1; + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + INSERT INTO warehouse_categories ( + parent_category_id, + internal_name, + display_name, + material, + lore, + display_order, + page, + slot + ) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) + """, + Statement.RETURN_GENERATED_KEYS + ) + + ) { + + try ( + + PreparedStatement maxStatement = + connection.prepareStatement( + """ + SELECT COALESCE( + MAX(display_order), + 0 + ) + FROM warehouse_categories + """ + ) + + ) { + + ResultSet resultSet = + maxStatement.executeQuery(); + + if (resultSet.next()) { + + nextDisplayOrder = + resultSet.getInt(1) + 1; + + } + + } + + statement.setInt( + 1, + parentCategoryId + ); + + statement.setString( + 2, + internalName + ); + + statement.setString( + 3, + displayName + ); + + statement.setString( + 4, + material + ); + + statement.setString( + 5, + lore + ); + + statement.setInt( + 6, + nextDisplayOrder + ); + + statement.setInt( + 7, + 0 + ); + + statement.setInt( + 8, + 0 + ); + + statement.executeUpdate(); + + ResultSet keys = + statement.getGeneratedKeys(); + + if (keys.next()) { + + return keys.getInt( + 1 + ); + + } + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + return -1; + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/admindao/PurgeVariantsDAO.java b/src/main/java/com/rsscripting/rswarehouse/admin/admindao/PurgeVariantsDAO.java new file mode 100644 index 0000000..e129865 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/admindao/PurgeVariantsDAO.java @@ -0,0 +1,130 @@ +package com.rsscripting.rswarehouse.admin.admindao; + +import com.rsscripting.rswarehouse.database.DatabaseManager; +import org.bukkit.Bukkit; + +import java.sql.Connection; +import java.sql.PreparedStatement; + +public class PurgeVariantsDAO { + + public static void purgeZeroQuantityDamagedVariants() { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + DELETE + FROM damaged_variants + WHERE quantity <= 0 + """ + ); + + int deleted = + statement.executeUpdate(); + + Bukkit.getLogger().info( + "[RS-Warehouse] Purged " + + deleted + + " empty damaged variants." + ); + + } catch (Exception e) { + + e.printStackTrace(); + + } + + } + + public static void purgeZeroQuantityEnchantedVariants() { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + DELETE + FROM enchanted_variants + WHERE quantity <= 0 + """ + ); + + int deleted = + statement.executeUpdate(); + + Bukkit.getLogger().info( + "[RS-Warehouse] Purged " + + deleted + + " empty enchanted variants." + ); + + } + + catch (Exception exception) { + + exception.printStackTrace(); + + } + + } + + public static void purgeZeroQuantityPartiallyFilledVariants() { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + DELETE + FROM partially_filled_variants + WHERE quantity <= 0 + """ + ); + + int deleted = + statement.executeUpdate(); + + Bukkit.getLogger().info( + "[RS-Warehouse] Purged " + + deleted + + " empty partially filled variants." + ); + + } + + catch (Exception exception) { + + exception.printStackTrace(); + + } + + } + + public static void purgeAll() { + + purgeZeroQuantityDamagedVariants(); + + purgeZeroQuantityEnchantedVariants(); + + purgeZeroQuantityPartiallyFilledVariants(); + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/admindao/UpdateCategoryDAO.java b/src/main/java/com/rsscripting/rswarehouse/admin/admindao/UpdateCategoryDAO.java new file mode 100644 index 0000000..cf644a4 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/admindao/UpdateCategoryDAO.java @@ -0,0 +1,140 @@ +package com.rsscripting.rswarehouse.admin.admindao; + +import com.rsscripting.rswarehouse.database.DatabaseManager; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +public class UpdateCategoryDAO { + + public static void updateMaterial( + int categoryId, + String material + ) { + + String sql = + """ + UPDATE warehouse_categories + SET material = ? + WHERE id = ? + """; + + try ( + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + sql + ) + ) { + + statement.setString( + 1, + material + ); + + statement.setInt( + 2, + categoryId + ); + + statement.executeUpdate(); + + } + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + } + + public static void updateDisplayName( + int categoryId, + String displayName + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + UPDATE warehouse_categories + SET display_name = ? + WHERE id = ? + """ + ) + + ) { + + statement.setString( + 1, + displayName + ); + + statement.setInt( + 2, + categoryId + ); + + statement.executeUpdate(); + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + } + + public static void updateLore( + int categoryId, + String lore + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + UPDATE warehouse_categories + SET lore = ? + WHERE id = ? + """ + ) + + ) { + + statement.setString( + 1, + lore + ); + + statement.setInt( + 2, + categoryId + ); + + statement.executeUpdate(); + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/admindao/WarehouseStatisticsDAO.java b/src/main/java/com/rsscripting/rswarehouse/admin/admindao/WarehouseStatisticsDAO.java new file mode 100644 index 0000000..b61eed0 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/admindao/WarehouseStatisticsDAO.java @@ -0,0 +1,169 @@ +package com.rsscripting.rswarehouse.admin.admindao; + +import com.rsscripting.rswarehouse.database.DatabaseManager; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; + +public class WarehouseStatisticsDAO { + + public static long getTotalInventory() { + + long total = 0; + + total += getSum( + "warehouse_inventory" + ); + + total += getSum( + "damaged_variants" + ); + + total += getSum( + "enchanted_variants" + ); + + total += getSum( + "partially_filled_variants" + ); + + return total; + + } + + public static int getTotalUniqueItems() { + + int total = 0; + + total += getCount( + "warehouse_inventory" + ); + + total += getCount( + "damaged_variants" + ); + + total += getCount( + "enchanted_variants" + ); + + total += getCount( + "partially_filled_variants" + ); + + return total; + + } + + public static int getTotalDamagedVariants() { + + return getCount( + "damaged_variants" + ); + + } + + public static int getTotalEnchantedVariants() { + + return getCount( + "enchanted_variants" + ); + + } + + public static int getTotalPartiallyFilledVariants() { + + return getCount( + "partially_filled_variants" + ); + + } + + private static int getCount( + String table + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + "SELECT COUNT(*) FROM " + + table + ) + + ) { + + ResultSet result = + statement.executeQuery(); + + if ( + result.next() + ) { + + return result.getInt( + 1 + ); + + } + + } + + catch ( + Exception ignored + ) { + } + + return 0; + + } + + private static long getSum( + String table + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + "SELECT COALESCE(SUM(quantity),0) FROM " + + table + ) + + ) { + + ResultSet result = + statement.executeQuery(); + + if ( + result.next() + ) { + + return result.getLong( + 1 + ); + + } + + } + + catch ( + Exception exception + ) + { + + exception.printStackTrace(); + + } + + return 0; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/CategoryEditSession.java b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/CategoryEditSession.java new file mode 100644 index 0000000..4ce4417 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/CategoryEditSession.java @@ -0,0 +1,138 @@ +package com.rsscripting.rswarehouse.admin.adminsessions; + +public class CategoryEditSession { + + private final int categoryId; + + private final String[] lore = + new String[5]; + + private int loreSlot = -1; + + private long loreExpiration = 0; + + private String displayName; + + private boolean editingDisplayName = false; + + private long displayNameExpiration = 0; + + public CategoryEditSession( + int categoryId + ) { + + this.categoryId = + categoryId; + + } + + public int getCategoryId() { + + return categoryId; + + } + + public String getLore( + int index + ) { + + return lore[index]; + + } + + public void setLore( + int index, + String value + ) { + + lore[index] = + value; + + } + + public int getLoreSlot() { + + return loreSlot; + + } + + public void setLoreSlot( + int loreSlot + ) { + + this.loreSlot = + loreSlot; + + } + + public long getLoreExpiration() { + + return loreExpiration; + + } + + public void setLoreExpiration( + long loreExpiration + ) { + + this.loreExpiration = + loreExpiration; + + } + + public String getDisplayName() { + + return displayName; + + } + + public void setDisplayName( + String displayName + ) { + + this.displayName = + displayName; + + } + + public boolean isEditingDisplayName() { + + return editingDisplayName; + + } + + public void setEditingDisplayName( + boolean editingDisplayName + ) { + + this.editingDisplayName = + editingDisplayName; + + } + + public long getDisplayNameExpiration() { + + return displayNameExpiration; + + } + + public void setDisplayNameExpiration( + long displayNameExpiration + ) { + + this.displayNameExpiration = + displayNameExpiration; + + } + + private int materialPickerPage = 0; + + public int getMaterialPickerPage() { + return materialPickerPage; + } + + public void setMaterialPickerPage(int materialPickerPage) { + this.materialPickerPage = materialPickerPage; + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/CategoryEditSessionManager.java b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/CategoryEditSessionManager.java new file mode 100644 index 0000000..123ade7 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/CategoryEditSessionManager.java @@ -0,0 +1,54 @@ +package com.rsscripting.rswarehouse.admin.adminsessions; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class CategoryEditSessionManager { + + private static final Map< + UUID, + CategoryEditSession + > sessions = + new HashMap<>(); + + public static CategoryEditSession createSession( + UUID uuid, + int categoryId + ) { + + CategoryEditSession session = + new CategoryEditSession( + categoryId + ); + + sessions.put( + uuid, + session + ); + + return session; + + } + + public static CategoryEditSession getSession( + UUID uuid + ) { + + return sessions.get( + uuid + ); + + } + + public static void removeSession( + UUID uuid + ) { + + sessions.remove( + uuid + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/CategoryOptionsMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/CategoryOptionsMenuListener.java new file mode 100644 index 0000000..98389e1 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/CategoryOptionsMenuListener.java @@ -0,0 +1,4 @@ +package com.rsscripting.rswarehouse.admin.adminsessions; + +public class CategoryOptionsMenuListener { +} diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/CategoryPageSlotSession.java b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/CategoryPageSlotSession.java new file mode 100644 index 0000000..23d2ec7 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/CategoryPageSlotSession.java @@ -0,0 +1,56 @@ +package com.rsscripting.rswarehouse.admin.adminsessions; + +public class CategoryPageSlotSession { + + private final int categoryId; + + private Integer page; + + private Integer slot; + + public CategoryPageSlotSession( + int categoryId + ) { + + this.categoryId = + categoryId; + + } + + public int getCategoryId() { + + return categoryId; + + } + + public Integer getPage() { + + return page; + + } + + public void setPage( + Integer page + ) { + + this.page = + page; + + } + + public Integer getSlot() { + + return slot; + + } + + public void setSlot( + Integer slot + ) { + + this.slot = + slot; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/CategoryPageSlotSessionManager.java b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/CategoryPageSlotSessionManager.java new file mode 100644 index 0000000..f8f3726 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/CategoryPageSlotSessionManager.java @@ -0,0 +1,49 @@ +package com.rsscripting.rswarehouse.admin.adminsessions; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class CategoryPageSlotSessionManager { + + private static final Map< + UUID, + CategoryPageSlotSession + > sessions = + new HashMap<>(); + + public static void createSession( + UUID uuid, + int categoryId + ) { + + sessions.put( + uuid, + new CategoryPageSlotSession( + categoryId + ) + ); + + } + + public static CategoryPageSlotSession getSession( + UUID uuid + ) { + + return sessions.get( + uuid + ); + + } + + public static void removeSession( + UUID uuid + ) { + + sessions.remove( + uuid + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/PageSlotAssignmentSession.java b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/PageSlotAssignmentSession.java new file mode 100644 index 0000000..fd21b5e --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/PageSlotAssignmentSession.java @@ -0,0 +1,85 @@ +package com.rsscripting.rswarehouse.admin.adminsessions; + +public class PageSlotAssignmentSession { + + private final int itemId; + + private int categoryId; + + private String categoryName; + + private Integer page; + + private Integer slot; + + public PageSlotAssignmentSession( + int itemId + ) { + + this.itemId = itemId; + + } + + public int getItemId() { + + return itemId; + + } + + public Integer getPage() { + + return page; + + } + + public void setPage( + Integer page + ) { + + this.page = page; + + } + + public Integer getSlot() { + + return slot; + + } + + public void setSlot( + Integer slot + ) { + + this.slot = slot; + + } + + public int getCategoryId() { + + return categoryId; + + } + + public void setCategoryId( + int categoryId + ) { + + this.categoryId = categoryId; + + } + + public String getCategoryName() { + + return categoryName; + + } + + public void setCategoryName( + String categoryName + ) { + + this.categoryName = categoryName; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/PageSlotAssignmentSessionManager.java b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/PageSlotAssignmentSessionManager.java new file mode 100644 index 0000000..50bdcfd --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/PageSlotAssignmentSessionManager.java @@ -0,0 +1,80 @@ +package com.rsscripting.rswarehouse.admin.adminsessions; + +import com.rsscripting.rswarehouse.category.categorymenu.CategoryDAO; +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; +import com.rsscripting.rswarehouse.model.WarehouseCategory; +import com.rsscripting.rswarehouse.model.WarehouseItem; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class PageSlotAssignmentSessionManager { + + private static final Map sessions = + new HashMap<>(); + + public static void createSession( + UUID uuid, + int itemId + ) { + + PageSlotAssignmentSession session = + new PageSlotAssignmentSession( + itemId + ); + + WarehouseItem item = + ItemDAO.getItemById( + itemId + ); + + if (item != null) { + + session.setCategoryId( + item.categoryId() + ); + + WarehouseCategory category = + CategoryDAO.getCategoryById( + item.categoryId() + ); + + if (category != null) { + + session.setCategoryName( + category.displayName() + ); + + } + + } + + sessions.put( + uuid, + session + ); + + } + + public static PageSlotAssignmentSession getSession( + UUID uuid + ) { + + return sessions.get( + uuid + ); + + } + + public static void removeSession( + UUID uuid + ) { + + sessions.remove( + uuid + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/SubCategoryCreationSession.java b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/SubCategoryCreationSession.java new file mode 100644 index 0000000..3e1170f --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/SubCategoryCreationSession.java @@ -0,0 +1,118 @@ +package com.rsscripting.rswarehouse.admin.adminsessions; + +public class SubCategoryCreationSession { + + private final int itemId; + + private String internalName; + + private String displayName; + + private final String[] lore = + new String[5]; + + private int loreSlot = + -1; + + private long loreExpiration = + 0; + + public SubCategoryCreationSession( + int itemId + ) { + + this.itemId = itemId; + + } + + public int getItemId() { + + return itemId; + + } + + public String getInternalName() { + + return internalName; + + } + + public void setInternalName( + String internalName + ) { + + this.internalName = internalName; + + } + + public String getDisplayName() { + + return displayName; + + } + + public void setDisplayName( + String displayName + ) { + + this.displayName = displayName; + + } + + public void setLore( + int slot, + String value + ) { + + lore[slot] = value; + + } + + public String getLore( + int slot + ) { + + return lore[slot]; + + } + + public void clearLore() { + + for (int i = 0; i < lore.length; i++) { + + lore[i] = null; + + } + + } + + public int getLoreSlot() { + + return loreSlot; + + } + + public void setLoreSlot( + int loreSlot + ) { + + this.loreSlot = loreSlot; + + } + + public long getLoreExpiration() { + + return loreExpiration; + + } + + public void setLoreExpiration( + long loreExpiration + ) { + + this.loreExpiration = loreExpiration; + + } + + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/SubCategoryCreationSessionManager.java b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/SubCategoryCreationSessionManager.java new file mode 100644 index 0000000..5b1588c --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/SubCategoryCreationSessionManager.java @@ -0,0 +1,47 @@ +package com.rsscripting.rswarehouse.admin.adminsessions; + + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class SubCategoryCreationSessionManager { + + private static final Map sessions = + new HashMap<>(); + + public static void createSession( + UUID uuid, + int itemId + ) { + + sessions.put( + uuid, + new SubCategoryCreationSession( + itemId + ) + ); + + } + + public static SubCategoryCreationSession getSession( + UUID uuid + ) { + + return sessions.get( + uuid + ); + + } + + public static void removeSession( + UUID uuid + ) { + + sessions.remove( + uuid + ); + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/SubCategoryEditSession.java b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/SubCategoryEditSession.java new file mode 100644 index 0000000..2eaf677 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/SubCategoryEditSession.java @@ -0,0 +1,83 @@ +package com.rsscripting.rswarehouse.admin.adminsessions; + +public class SubCategoryEditSession { + + private final int itemId; + + private final int subCategoryId; + + private final String[] lore = + new String[5]; + + private int loreSlot = -1; + + private long loreExpiration = 0; + + public String getLore( + int index + ) { + + return lore[index]; + + } + + public void setLore( + int index, + String value + ) { + + lore[index] = value; + + } + + public int getLoreSlot() { + + return loreSlot; + + } + + public void setLoreSlot( + int loreSlot + ) { + + this.loreSlot = loreSlot; + + } + + public long getLoreExpiration() { + + return loreExpiration; + + } + + public void setLoreExpiration( + long loreExpiration + ) { + + this.loreExpiration = loreExpiration; + + } + + public SubCategoryEditSession( + int itemId, + int subCategoryId + ) { + + this.itemId = itemId; + this.subCategoryId = subCategoryId; + + } + + public int getItemId() { + + return itemId; + + } + + public int getSubCategoryId() { + + return subCategoryId; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/SubCategoryEditSessionManager.java b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/SubCategoryEditSessionManager.java new file mode 100644 index 0000000..4e64284 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/adminsessions/SubCategoryEditSessionManager.java @@ -0,0 +1,53 @@ +package com.rsscripting.rswarehouse.admin.adminsessions; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class SubCategoryEditSessionManager { + + private static final Map sessions = + new HashMap<>(); + + public static SubCategoryEditSession createSession( + UUID uuid, + int itemId, + int subCategoryId + ) { + + SubCategoryEditSession session = + new SubCategoryEditSession( + itemId, + subCategoryId + ); + + sessions.put( + uuid, + session + ); + + return session; + + } + + public static SubCategoryEditSession getSession( + UUID uuid + ) { + + return sessions.get( + uuid + ); + + } + + public static void removeSession( + UUID uuid + ) { + + sessions.remove( + uuid + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/CategoryPageNumberMenu.java b/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/CategoryPageNumberMenu.java new file mode 100644 index 0000000..b1ceefe --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/CategoryPageNumberMenu.java @@ -0,0 +1,126 @@ +package com.rsscripting.rswarehouse.admin.assignpageslot; + +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryPageSlotSession; +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryPageSlotSessionManager; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.MenuType; +import org.bukkit.inventory.meta.ItemMeta; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryDAO; +import com.rsscripting.rswarehouse.model.WarehouseCategory; +import org.bukkit.inventory.view.AnvilView; + +import java.util.List; + +public class CategoryPageNumberMenu { + + public static final String TITLE = + "Page Number"; + + public static void open( + Player player + ) { + + CategoryPageSlotSession session = + CategoryPageSlotSessionManager.getSession( + player.getUniqueId() + ); + + if (session == null) { + return; + } + + AnvilView view = + MenuType.ANVIL.builder() + .title( + Component.text(TITLE) + ) + .build(player); + + ItemStack confirm = + new ItemStack(Material.LIME_WOOL); + + ItemMeta meta = + confirm.getItemMeta(); + + WarehouseCategory category = + CategoryDAO.getCategoryById( + session.getCategoryId() + ); + + if ( + category != null + && category.page() > 0 + ) { + + meta.displayName( + Component.text( + String.valueOf( + category.page() + ) + ) + ); + + } + else { + + meta.displayName( + Component.empty() + ); + + } + + meta.lore( + List.of( + Component.text( + "Save page." + ).color( + NamedTextColor.WHITE + ) + ) + ); + + confirm.setItemMeta(meta); + + view.setItem( + 0, + confirm + ); + + ItemStack cancel = + new ItemStack(Material.RED_WOOL); + + ItemMeta cancelMeta = + cancel.getItemMeta(); + + cancelMeta.displayName( + Component.empty() + ); + + cancelMeta.lore( + List.of( + Component.text( + "Cancel" + ).color( + NamedTextColor.WHITE + ) + ) + ); + + cancel.setItemMeta( + cancelMeta + ); + + view.setItem( + 1, + cancel + ); + + view.open(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/CategoryPageNumberMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/CategoryPageNumberMenuListener.java new file mode 100644 index 0000000..38c6d4d --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/CategoryPageNumberMenuListener.java @@ -0,0 +1,157 @@ +package com.rsscripting.rswarehouse.admin.assignpageslot; + +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryPageSlotSession; +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryPageSlotSessionManager; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.view.AnvilView; + +public class CategoryPageNumberMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getView() instanceof AnvilView anvilView)) { + return; + } + + if (!event.getView() + .title() + .toString() + .contains(CategoryPageNumberMenu.TITLE)) { + + return; + + } + + Player player = + (Player) event.getWhoClicked(); + + CategoryPageSlotSession session = + CategoryPageSlotSessionManager.getSession( + player.getUniqueId() + ); + + if (session == null) { + + return; + + } + + event.setCancelled(true); + + if (event.getCurrentItem() == null) { + return; + } + + if (event.getRawSlot() == 0) { + + String pageText = + anvilView.getRenameText(); + + if (pageText.isBlank()) { + + RSMessageUtils.error( + player, + "Page cannot be blank." + ); + + return; + + } + + int page; + + try { + + page = + Integer.parseInt( + pageText + ); + + } + + catch (NumberFormatException exception) { + + RSMessageUtils.error( + player, + "Page must be a number." + ); + + return; + + } + + if (page < 1) { + + RSMessageUtils.error( + player, + "Page must be 1 or greater." + ); + + return; + + } + + session.setPage( + page + ); + + event.getView() + .getTopInventory() + .clear(); + + CategorySlotNumberMenu.open( + player + ); + + return; + + } + + if (event.getRawSlot() == 1) { + + event.getView() + .getTopInventory() + .clear(); + + player.closeInventory(); + + } + + } + + @EventHandler + public void onInventoryClose( + InventoryCloseEvent event + ) { + + if (!(event.getView() instanceof AnvilView)) { + + return; + + } + + if (!event.getView() + .title() + .toString() + .contains(PageNumberMenu.TITLE)) { + + return; + + } + + event.getView() + .getTopInventory() + .clear(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/CategorySlotNumberMenu.java b/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/CategorySlotNumberMenu.java new file mode 100644 index 0000000..5cbfaef --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/CategorySlotNumberMenu.java @@ -0,0 +1,118 @@ +package com.rsscripting.rswarehouse.admin.assignpageslot; + +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryPageSlotSession; +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryPageSlotSessionManager; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.MenuType; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.view.AnvilView; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryDAO; +import com.rsscripting.rswarehouse.model.WarehouseCategory; + +import java.util.List; + +public class CategorySlotNumberMenu { + + public static final String TITLE = + "Slot Number"; + + public static void open( + Player player + ) { + + CategoryPageSlotSession session = + CategoryPageSlotSessionManager.getSession( + player.getUniqueId() + ); + + if (session == null) { + + return; + + } + + AnvilView view = + MenuType.ANVIL.builder() + .title( + Component.text(TITLE) + ) + .build(player); + + ItemStack confirm = + new ItemStack(Material.LIME_WOOL); + + ItemMeta meta = + confirm.getItemMeta(); + + WarehouseCategory category = + CategoryDAO.getCategoryById( + session.getCategoryId() + ); + + if ( + category != null + && category.slot() > 0 + ) { + + meta.displayName( + Component.text( + String.valueOf( + category.slot() + ) + ) + ); + + } + else { + + meta.displayName( + Component.empty() + ); + + } + + meta.lore( + List.of( + Component.text( + "Save slot." + ).color( + NamedTextColor.WHITE + ) + ) + ); + + confirm.setItemMeta(meta); + + view.setItem( + 0, + confirm + ); + + ItemStack cancel = + new ItemStack(Material.RED_WOOL); + + ItemMeta cancelMeta = + cancel.getItemMeta(); + + cancelMeta.displayName( + Component.empty() + ); + + cancel.setItemMeta( + cancelMeta + ); + + view.setItem( + 1, + cancel + ); + + view.open(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/CategorySlotNumberMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/CategorySlotNumberMenuListener.java new file mode 100644 index 0000000..7c4ead7 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/CategorySlotNumberMenuListener.java @@ -0,0 +1,181 @@ +package com.rsscripting.rswarehouse.admin.assignpageslot; + +import com.rsscripting.rswarehouse.admin.admindao.CategoryPlacementDAO; +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryPageSlotSession; +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryPageSlotSessionManager; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryMenu; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.view.AnvilView; + +public class CategorySlotNumberMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getView() instanceof AnvilView anvilView)) { + return; + } + + if (!event.getView() + .title() + .toString() + .contains( + CategorySlotNumberMenu.TITLE + )) { + + return; + + } + + Player player = + (Player) event.getWhoClicked(); + + CategoryPageSlotSession session = + CategoryPageSlotSessionManager.getSession( + player.getUniqueId() + ); + + if (session == null) { + + return; + + } + + event.setCancelled(true); + + if (event.getCurrentItem() == null) { + + return; + + } + + if (event.getRawSlot() == 0) { + + String slotText = + anvilView.getRenameText(); + + if (slotText.isBlank()) { + + RSMessageUtils.error( + player, + "Slot cannot be blank." + ); + + return; + + } + + int slot; + + try { + + slot = + Integer.parseInt( + slotText + ); + + } + + catch (NumberFormatException exception) { + + RSMessageUtils.error( + player, + "Slot must be a number." + ); + + return; + + } + + if (slot < 9 || slot > 53) { + + RSMessageUtils.error( + player, + "Slot must be between 9 and 53." + ); + + return; + + } + + session.setSlot( + slot + ); + + CategoryPlacementDAO.assignPageSlot( + session.getCategoryId(), + session.getPage(), + session.getSlot() + ); + + event.getView() + .getTopInventory() + .clear(); + + player.closeInventory(); + + CategoryMenu.open( + player + ); + + CategoryPageSlotSessionManager.removeSession( + player.getUniqueId() + ); + + RSMessageUtils.success( + player, + "Item page/slot updated." + ); + + return; + } + + if (event.getRawSlot() == 1) { + + event.getView() + .getTopInventory() + .clear(); + + player.closeInventory(); + + } + + } + + @EventHandler + public void onInventoryClose( + InventoryCloseEvent event + ) { + + if (!(event.getView() instanceof AnvilView)) { + + return; + + } + + if (!event.getView() + .title() + .toString() + .contains( + CategorySlotNumberMenu.TITLE + )) { + + return; + + } + + event.getView() + .getTopInventory() + .clear(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/PageNumberMenu.java b/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/PageNumberMenu.java new file mode 100644 index 0000000..b42ddd7 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/PageNumberMenu.java @@ -0,0 +1,120 @@ +package com.rsscripting.rswarehouse.admin.assignpageslot; + +import com.rsscripting.rswarehouse.admin.adminsessions.PageSlotAssignmentSession; +import com.rsscripting.rswarehouse.admin.adminsessions.PageSlotAssignmentSessionManager; +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; +import com.rsscripting.rswarehouse.model.WarehouseItem; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.MenuType; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.view.AnvilView; + +import java.util.List; + +public class PageNumberMenu { + + public static final String TITLE = + "Page Number"; + + public static void open( + Player player + ) { + + PageSlotAssignmentSession session = + PageSlotAssignmentSessionManager.getSession( + player.getUniqueId() + ); + + if (session == null) { + return; + } + + WarehouseItem item = + ItemDAO.getItemById( + session.getItemId() + ); + + AnvilView view = + MenuType.ANVIL.builder() + .title( + Component.text(TITLE) + ) + .build(player); + + ItemStack confirm = + new ItemStack(Material.LIME_WOOL); + + ItemMeta meta = + confirm.getItemMeta(); + + if (item != null && item.page() != null) { + + meta.displayName( + Component.text( + String.valueOf(item.page()) + ) + ); + + } else { + + meta.displayName( + Component.empty() + ); + + } + + meta.lore( + List.of( + Component.text( + "Save page." + ).color( + NamedTextColor.WHITE + ) + ) + ); + + confirm.setItemMeta(meta); + + view.setItem( + 0, + confirm + ); + + ItemStack cancel = + new ItemStack(Material.RED_WOOL); + + ItemMeta cancelMeta = + cancel.getItemMeta(); + + cancelMeta.displayName( + Component.empty() + ); + + cancelMeta.lore( + List.of( + Component.text( + "Cancel" + ).color( + NamedTextColor.WHITE + ) + ) + ); + + cancel.setItemMeta( + cancelMeta + ); + + view.setItem( + 1, + cancel + ); + + view.open(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/PageNumberMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/PageNumberMenuListener.java new file mode 100644 index 0000000..84a0707 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/PageNumberMenuListener.java @@ -0,0 +1,157 @@ +package com.rsscripting.rswarehouse.admin.assignpageslot; + +import com.rsscripting.rswarehouse.admin.adminsessions.PageSlotAssignmentSession; +import com.rsscripting.rswarehouse.admin.adminsessions.PageSlotAssignmentSessionManager; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.view.AnvilView; + +public class PageNumberMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getView() instanceof AnvilView anvilView)) { + return; + } + + if (!event.getView() + .title() + .toString() + .contains(PageNumberMenu.TITLE)) { + + return; + + } + + Player player = + (Player) event.getWhoClicked(); + + PageSlotAssignmentSession session = + PageSlotAssignmentSessionManager.getSession( + player.getUniqueId() + ); + + if (session == null) { + + return; + + } + + event.setCancelled(true); + + if (event.getCurrentItem() == null) { + return; + } + + if (event.getRawSlot() == 0) { + + String pageText = + anvilView.getRenameText(); + + if (pageText.isBlank()) { + + RSMessageUtils.error( + player, + "Page cannot be blank." + ); + + return; + + } + + int page; + + try { + + page = + Integer.parseInt( + pageText + ); + + } + + catch (NumberFormatException exception) { + + RSMessageUtils.error( + player, + "Page must be a number." + ); + + return; + + } + + if (page < 1) { + + RSMessageUtils.error( + player, + "Page must be 1 or greater." + ); + + return; + + } + + session.setPage( + page + ); + + event.getView() + .getTopInventory() + .clear(); + + SlotNumberMenu.open( + player + ); + + return; + + } + + if (event.getRawSlot() == 1) { + + event.getView() + .getTopInventory() + .clear(); + + player.closeInventory(); + + } + + } + + @EventHandler + public void onInventoryClose( + InventoryCloseEvent event + ) { + + if (!(event.getView() instanceof AnvilView)) { + + return; + + } + + if (!event.getView() + .title() + .toString() + .contains(PageNumberMenu.TITLE)) { + + return; + + } + + event.getView() + .getTopInventory() + .clear(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/SlotNumberMenu.java b/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/SlotNumberMenu.java new file mode 100644 index 0000000..9b64a9f --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/SlotNumberMenu.java @@ -0,0 +1,112 @@ +package com.rsscripting.rswarehouse.admin.assignpageslot; + +import com.rsscripting.rswarehouse.admin.adminsessions.PageSlotAssignmentSession; +import com.rsscripting.rswarehouse.admin.adminsessions.PageSlotAssignmentSessionManager; +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; +import com.rsscripting.rswarehouse.model.WarehouseItem; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.MenuType; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.view.AnvilView; + +import java.util.List; + +public class SlotNumberMenu { + + public static final String TITLE = + "Slot Number"; + + public static void open( + Player player + ) { + + PageSlotAssignmentSession session = + PageSlotAssignmentSessionManager.getSession( + player.getUniqueId() + ); + + if (session == null) { + + return; + + } + + WarehouseItem item = + ItemDAO.getItemById( + session.getItemId() + ); + + AnvilView view = + MenuType.ANVIL.builder() + .title( + Component.text(TITLE) + ) + .build(player); + + ItemStack confirm = + new ItemStack(Material.LIME_WOOL); + + ItemMeta meta = + confirm.getItemMeta(); + + if (item != null && item.slot() != null) { + + meta.displayName( + Component.text( + String.valueOf(item.slot()) + ) + ); + + } else { + + meta.displayName( + Component.empty() + ); + + } + + meta.lore( + List.of( + Component.text( + "Save slot." + ).color( + NamedTextColor.WHITE + ) + ) + ); + + confirm.setItemMeta(meta); + + view.setItem( + 0, + confirm + ); + + ItemStack cancel = + new ItemStack(Material.RED_WOOL); + + ItemMeta cancelMeta = + cancel.getItemMeta(); + + cancelMeta.displayName( + Component.empty() + ); + + cancel.setItemMeta( + cancelMeta + ); + + view.setItem( + 1, + cancel + ); + + view.open(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/SlotNumberMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/SlotNumberMenuListener.java new file mode 100644 index 0000000..3b77954 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/admin/assignpageslot/SlotNumberMenuListener.java @@ -0,0 +1,184 @@ +package com.rsscripting.rswarehouse.admin.assignpageslot; + +import com.rsscripting.rswarehouse.admin.adminsessions.PageSlotAssignmentSession; +import com.rsscripting.rswarehouse.admin.adminsessions.PageSlotAssignmentSessionManager; +import com.rsscripting.rswarehouse.placement.placementdao.ItemPlacementDAO; +import com.rsscripting.rswarehouse.item.ItemsMenu; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.view.AnvilView; + +public class SlotNumberMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getView() instanceof AnvilView anvilView)) { + return; + } + + if (!event.getView() + .title() + .toString() + .contains( + SlotNumberMenu.TITLE + )) { + + return; + + } + + Player player = + (Player) event.getWhoClicked(); + + PageSlotAssignmentSession session = + PageSlotAssignmentSessionManager.getSession( + player.getUniqueId() + ); + + if (session == null) { + + return; + + } + + event.setCancelled(true); + + if (event.getCurrentItem() == null) { + + return; + + } + + if (event.getRawSlot() == 0) { + + String slotText = + anvilView.getRenameText(); + + if (slotText.isBlank()) { + + RSMessageUtils.error( + player, + "Slot cannot be blank." + ); + + return; + + } + + int slot; + + try { + + slot = + Integer.parseInt( + slotText + ); + + } + + catch (NumberFormatException exception) { + + RSMessageUtils.error( + player, + "Slot must be a number." + ); + + return; + + } + + if (slot < 9 || slot > 53) { + + RSMessageUtils.error( + player, + "Slot must be between 9 and 53." + ); + + return; + + } + + session.setSlot( + slot + ); + + ItemPlacementDAO.assignPageSlot( + session.getItemId(), + session.getPage(), + session.getSlot() + ); + + event.getView() + .getTopInventory() + .clear(); + + player.closeInventory(); + + ItemsMenu.open( + player, + session.getCategoryId(), + session.getCategoryName(), + session.getPage() - 1 + ); + + PageSlotAssignmentSessionManager.removeSession( + player.getUniqueId() + ); + + RSMessageUtils.success( + player, + "Item page/slot updated." + ); + + return; + } + + if (event.getRawSlot() == 1) { + + event.getView() + .getTopInventory() + .clear(); + + player.closeInventory(); + + } + + } + + @EventHandler + public void onInventoryClose( + InventoryCloseEvent event + ) { + + if (!(event.getView() instanceof AnvilView)) { + + return; + + } + + if (!event.getView() + .title() + .toString() + .contains( + SlotNumberMenu.TITLE + )) { + + return; + + } + + event.getView() + .getTopInventory() + .clear(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/autodeposit/AutoDepositMenu.java b/src/main/java/com/rsscripting/rswarehouse/autodeposit/AutoDepositMenu.java new file mode 100644 index 0000000..d2d73e5 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/autodeposit/AutoDepositMenu.java @@ -0,0 +1,161 @@ +package com.rsscripting.rswarehouse.autodeposit; + +import com.rsscripting.rswarehouse.autodeposit.autodepositdao.AutoDepositDAO; +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class AutoDepositMenu { + + public static final String MENU_ID = + "AUTO_DEPOSIT"; + + public static final String TITLE = + "Auto Deposit"; + + public static void open( + Player player + ) { + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + int page = + Math.max( + 1, + session.getAutoDepositPage() + ); + + session.setAutoDepositPage( + page + ); + + Inventory inventory = + Bukkit.createInventory( + new RSMenuHolder( + MENU_ID + ), + 54, + Component.text( + TITLE + ) + ); + + ItemStack filler = + RSMenuUtils.createFillerPane(); + + for ( + int slot = 0; + slot <= 8; + slot++ + ) { + + inventory.setItem( + slot, + filler + ); + + } + + boolean enabled = + AutoDepositDAO.isEnabled( + player.getUniqueId() + ); + + inventory.setItem( + 2, + enabled + ? RSMenuUtils.createMenuItem( + Material.GREEN_DYE, + "Enabled" + ) + : RSMenuUtils.createMenuItem( + Material.RED_DYE, + "Disabled" + ) + ); + + inventory.setItem( + 4, + RSMenuUtils.createMenuItem( + Material.OAK_DOOR, + "§a Back to Category Menu" + ) + ); + + List filters = + AutoDepositDAO.getFilters( + player.getUniqueId() + ); + + int highestPage = + filters.size() / 45 + 1; + + int start = + (page - 1) * 45; + + int slot = + 9; + + for ( + int i = start; + i < filters.size() + && slot <= 53; + i++ + ) { + + inventory.setItem( + slot++, + filters.get( + i + ) + ); + + } + + if ( + page > 1 + ) { + + inventory.setItem( + 0, + RSMenuUtils.createMenuItem( + Material.ARROW, + "§ePrevious Page" + ) + ); + + } + + if ( + page < highestPage + 1 + ) { + + inventory.setItem( + 8, + RSMenuUtils.createMenuItem( + Material.ARROW, + "§eNext Page" + ) + ); + + } + + player.openInventory( + inventory + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/autodeposit/AutoDepositMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/autodeposit/AutoDepositMenuListener.java new file mode 100644 index 0000000..8504dcc --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/autodeposit/AutoDepositMenuListener.java @@ -0,0 +1,190 @@ +package com.rsscripting.rswarehouse.autodeposit; + +import com.rsscripting.rswarehouse.autodeposit.autodepositdao.AutoDepositDAO; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryMenu; +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +public class AutoDepositMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getInventory() + .getHolder() + instanceof RSMenuHolder holder)) { + + return; + + } + + if (!holder.getMenuId().equals( + AutoDepositMenu.MENU_ID + )) { + + return; + + } + + if ( + event.getClickedInventory() + == event.getView() + .getTopInventory() + ) { + + event.setCancelled( + true + ); + + } + + Player player = + (Player) event.getWhoClicked(); + + int slot = + event.getRawSlot(); + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + if ( + slot == 0 + ) { + + session.setAutoDepositPage( + session.getAutoDepositPage() + - 1 + ); + + AutoDepositMenu.open( + player + ); + + return; + + } + + if ( + slot == 8 + ) { + + session.setAutoDepositPage( + session.getAutoDepositPage() + + 1 + ); + + AutoDepositMenu.open( + player + ); + + return; + + } + + if ( + slot == 4 + ) { + + CategoryMenu.open( + player + ); + + return; + + } + + if ( + slot >= 9 + && slot <= 53 + && event.getCursor() != null + && !event.getCursor() + .getType() + .isAir() + ) { + + ItemStack filter = + event.getCursor() + .clone(); + + filter.setAmount( + 1 + ); + + AutoDepositDAO.addFilter( + player.getUniqueId(), + filter + ); + + RSMessageUtils.success( + player, + "Filter added." + ); + + AutoDepositMenu.open( + player + ); + + return; + + } + + if (slot == 2) { + + boolean enabled = + AutoDepositDAO.isEnabled( + player.getUniqueId() + ); + + AutoDepositDAO.setEnabled( + player.getUniqueId(), + !enabled + ); + + AutoDepositMenu.open( + player + ); + + return; + + } + + if ( + slot >= 9 + && slot <= 53 + && event.getCurrentItem() != null + && !event.getCurrentItem() + .getType() + .isAir() + ) { + + AutoDepositDAO.removeFilter( + player.getUniqueId(), + event.getCurrentItem() + ); + + RSMessageUtils.success( + player, + "Filter removed." + ); + + AutoDepositMenu.open( + player + ); + + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/autodeposit/AutoDepositPickupListener.java b/src/main/java/com/rsscripting/rswarehouse/autodeposit/AutoDepositPickupListener.java new file mode 100644 index 0000000..5608ee4 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/autodeposit/AutoDepositPickupListener.java @@ -0,0 +1,97 @@ +package com.rsscripting.rswarehouse.autodeposit; + +import com.rsscripting.rswarehouse.autodeposit.autodepositdao.AutoDepositDAO; +import com.rsscripting.rswarehouse.inventory.inventorydao.InventoryLookupDAO; +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityPickupItemEvent; +import org.bukkit.inventory.ItemStack; + +public class AutoDepositPickupListener + implements Listener { + + @EventHandler + public void onEntityPickupItem( + EntityPickupItemEvent event + ) { + + if ( + !(event.getEntity() + instanceof Player player) + ) { + + return; + + } + + if ( + !AutoDepositDAO.isEnabled( + player.getUniqueId() + ) + ) { + + return; + + } + + Item entity = + event.getItem(); + + ItemStack item = + entity.getItemStack(); + + if ( + !AutoDepositDAO.matchesFilter( + player.getUniqueId(), + item + ) + ) { + + return; + + } + + Integer inventoryId = + InventoryLookupDAO.findInventoryId( + item + ); + + if ( + inventoryId == null + && + !player.getServer() + .getPluginManager() + .getPlugin( + "RS-Warehouse" + ) + .getConfig() + .getBoolean( + "allow-uncategorized-item-creation", + true + ) + ) { + + return; + + } + + ItemDAO.addItem( + player.getUniqueId() + .toString(), + player.getName(), + item, + item.getAmount() + ); + + event.setCancelled( + true + ); + + entity.remove(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/autodeposit/autodepositdao/AutoDepositDAO.java b/src/main/java/com/rsscripting/rswarehouse/autodeposit/autodepositdao/AutoDepositDAO.java new file mode 100644 index 0000000..2182761 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/autodeposit/autodepositdao/AutoDepositDAO.java @@ -0,0 +1,346 @@ +package com.rsscripting.rswarehouse.autodeposit.autodepositdao; + +import com.rsscripting.rswarehouse.database.DatabaseManager; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import org.bukkit.inventory.ItemStack; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class AutoDepositDAO { + + public static boolean isEnabled( + UUID playerUuid + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT enabled + FROM auto_deposit_settings + WHERE player_uuid = ? + """ + ) + + ) { + + statement.setString( + 1, + playerUuid.toString() + ); + + ResultSet resultSet = + statement.executeQuery(); + + if ( + resultSet.next() + ) { + + return resultSet.getInt( + "enabled" + ) == 1; + + } + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + return false; + + } + + public static void setEnabled( + UUID playerUuid, + boolean enabled + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + INSERT OR REPLACE + INTO auto_deposit_settings ( + player_uuid, + enabled + ) + VALUES ( + ?, + ? + ) + """ + ) + + ) { + + statement.setString( + 1, + playerUuid.toString() + ); + + statement.setInt( + 2, + enabled + ? 1 + : 0 + ); + + statement.executeUpdate(); + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + } + + public static void addFilter( + UUID playerUuid, + ItemStack item + ) { + + item = + normalize( + item + ); + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + INSERT OR IGNORE + INTO auto_deposit_filters ( + player_uuid, + serialized_item + ) + VALUES ( + ?, + ? + ) + """ + ) + + ) { + + statement.setString( + 1, + playerUuid.toString() + ); + + statement.setString( + 2, + ItemStackUtils.serialize( + item + ) + ); + + statement.executeUpdate(); + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + } + + public static void removeFilter( + UUID playerUuid, + ItemStack item + ) { + + item = + normalize( + item + ); + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + DELETE + FROM auto_deposit_filters + WHERE player_uuid = ? + AND serialized_item = ? + """ + ) + + ) { + + statement.setString( + 1, + playerUuid.toString() + ); + + statement.setString( + 2, + ItemStackUtils.serialize( + item + ) + ); + + statement.executeUpdate(); + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + } + + public static List getFilters( + UUID playerUuid + ) { + + List filters = + new ArrayList<>(); + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT serialized_item + FROM auto_deposit_filters + WHERE player_uuid = ? + """ + ) + + ) { + + statement.setString( + 1, + playerUuid.toString() + ); + + ResultSet resultSet = + statement.executeQuery(); + + while ( + resultSet.next() + ) { + + filters.add( + ItemStackUtils.deserialize( + resultSet.getString( + "serialized_item" + ) + ) + ); + + } + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + return filters; + + } + + public static boolean matchesFilter( + UUID playerUuid, + ItemStack item + ) { + + item = + normalize( + item + ); + + for ( + ItemStack filter + : getFilters( + playerUuid + ) + ) { + + if ( + filter.isSimilar( + item + ) + ) { + + return true; + + } + + } + + return false; + + } + + public static boolean shouldBlockWithdrawal( + UUID playerUuid, + ItemStack item + ) { + + return isEnabled( + playerUuid + ) + && + matchesFilter( + playerUuid, + item + ); + + } + + private static ItemStack normalize( + ItemStack item + ) { + + ItemStack copy = + item.clone(); + + copy.setAmount( + 1 + ); + + return copy; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryDisplayNameMenu.java b/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryDisplayNameMenu.java new file mode 100644 index 0000000..ae63078 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryDisplayNameMenu.java @@ -0,0 +1,93 @@ +package com.rsscripting.rswarehouse.category.categorycreation; + +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.MenuType; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.view.AnvilView; + +import java.util.List; + +public class CategoryDisplayNameMenu { + + public static final String TITLE = + "Display Name"; + + public static void open(Player player) { + + AnvilView view = MenuType.ANVIL + .builder() + .title( + Component.text( + TITLE + ) + ) + .build(player); + + ItemStack confirm = new ItemStack(Material.LIME_WOOL); + + ItemMeta meta = confirm.getItemMeta(); + + meta.displayName( + Component.text("") + ); + + meta.lore( + List.of( + Component.text( + "Save and proceed to material picker." + ).color( + NamedTextColor.WHITE + ) + ) + ); + + confirm.setItemMeta(meta); + + view.setItem( + 0, + confirm + ); + + + ItemStack cancel = new ItemStack(Material.RED_WOOL); + + ItemMeta metacancel = cancel.getItemMeta(); + + metacancel.displayName( + Component.text("") + ); + + metacancel.lore( + List.of( + Component.text( + "Cancel" + ).color( + NamedTextColor.WHITE + ) + ) + ); + + cancel.setItemMeta(metacancel); + + + view.setItem( + 1, + cancel + ); + + GuiSessionManager.getSession( + player + ).setCategoryDisplayNameMenuOpen( + true + ); + + view.open(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryDisplayNameMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryDisplayNameMenuListener.java new file mode 100644 index 0000000..1ea03c3 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryDisplayNameMenuListener.java @@ -0,0 +1,158 @@ +package com.rsscripting.rswarehouse.category.categorycreation; + +import com.rsscripting.rswarehouse.category.categorymenu.CategoryDAO; +import com.rsscripting.rswarehouse.admin.AdminMenu; +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.view.AnvilView; +import org.bukkit.event.inventory.InventoryCloseEvent; + +public class CategoryDisplayNameMenuListener implements Listener { + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + + if (!(event.getView() instanceof AnvilView anvilView)) { + return; + } + + if (!event.getView() + .title() + .toString() + .contains( + CategoryDisplayNameMenu.TITLE + )) { + + return; + + } + + Player player = + (Player) event.getWhoClicked(); + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + if (!session.isCategoryDisplayNameMenuOpen()) { + + return; + + } + + event.setCancelled(true); + + if (event.getCurrentItem() == null) { + return; + } + + if (event.getRawSlot() == 0) { + + String categoryName = + anvilView.getRenameText(); + + if (categoryName.length() > 25) { + + RSMessageUtils.error( + player, + "Category names may not exceed 25 characters." + ); + + return; + + } + + if (categoryName.isBlank()) { + + RSMessageUtils.error( + player, + "Category name cannot be empty." + ); + + return; + + } + + if ( + CategoryDAO.categoryExists( + categoryName + ) + ) { + + RSMessageUtils.error( + player, + "A category with that name already exists." + ); + + return; + + } + + session.setPendingCategoryDisplayName( + categoryName + ); + + session.setCategoryDisplayNameMenuOpen( + false + ); + + session.clearPendingCategoryLore(); + + event.getView().getTopInventory().clear(); + + CategoryMaterialPickerMenu.open( + player, + 0 + ); + + return; + + } + + if (event.getRawSlot() == 1) { + + event.getView().getTopInventory().clear(); + + AdminMenu.open( + player + ); + + } + } + + @EventHandler + public void onInventoryClose( + InventoryCloseEvent event + ) { + + if (!(event.getView() + instanceof AnvilView)) { + + return; + + } + + if (!event.getView() + .title() + .toString() + .contains( + CategoryDisplayNameMenu.TITLE + )) { + + return; + + } + + event.getView() + .getTopInventory() + .clear(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryLoreChatListener.java b/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryLoreChatListener.java new file mode 100644 index 0000000..b7573d1 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryLoreChatListener.java @@ -0,0 +1,130 @@ +package com.rsscripting.rswarehouse.category.categorycreation; + +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; + +public class CategoryLoreChatListener + implements Listener { + + @EventHandler + public void onPlayerChat( + AsyncPlayerChatEvent event + ) { + + Player player = + event.getPlayer(); + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + int loreSlot = + session.getPendingCategoryLoreSlot(); + + if (loreSlot < 0) { + + return; + + } + + event.setCancelled( + true + ); + + String message = + event.getMessage(); + + if (message.length() > 50) { + + RSMessageUtils.error( + player, + "Lore lines may not exceed 50 characters." + ); + + Bukkit.getScheduler() + .runTask( + Bukkit.getPluginManager() + .getPlugin( + "RS-Warehouse" + ), + () -> CategoryLoreMenu.open( + player + ) + ); + + return; + + } + + if ( + message.equalsIgnoreCase( + "cancel" + ) + ) { + + session.setPendingCategoryLoreSlot( + -1 + ); + + session.setPendingCategoryLoreExpiration( + 0 + ); + + Bukkit.getScheduler() + .runTask( + Bukkit.getPluginManager() + .getPlugin( + "RS-Warehouse" + ), + () -> CategoryLoreMenu.open( + player + ) + ); + + return; + + } + + session.setPendingCategoryLore( + loreSlot, + message + ); + + session.setPendingCategoryLoreSlot( + -1 + ); + + session.setPendingCategoryLoreExpiration( + 0 + ); + + Bukkit.getScheduler() + .runTask( + Bukkit.getPluginManager() + .getPlugin( + "RS-Warehouse" + ), + () -> { + + RSMessageUtils.success( + player, + "Lore line saved." + ); + + CategoryLoreMenu.open( + player + ); + + } + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryLoreMenu.java b/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryLoreMenu.java new file mode 100644 index 0000000..56d6e75 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryLoreMenu.java @@ -0,0 +1,144 @@ +package com.rsscripting.rswarehouse.category.categorycreation; + +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.ArrayList; +import java.util.List; + +public class CategoryLoreMenu { + + public static void open( + Player player + ) { + + Inventory menu = + Bukkit.createInventory( + new RSMenuHolder( + "CATEGORY_LORE" + ), + 27, + Component.text( + "Category Lore" + ) + ); + + for (int i = 0; i < menu.getSize(); i++) { + + menu.setItem( + i, + RSMenuUtils.createFillerPane() + ); + + } + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + for (int i = 0; i < 5; i++) { + + ItemStack book = + new ItemStack( + Material.WRITABLE_BOOK + ); + + ItemMeta meta = + book.getItemMeta(); + + meta.displayName( + Component.text( + "Lore Line " + + (i + 1) + ) + ); + + List lore = + new ArrayList<>(); + + String value = + session.getPendingCategoryLore( + i + ); + + if ( + value == null + || value.isBlank() + ) { + + lore.add( + Component.text( + "(Empty)" + ) + ); + + } + + else { + + lore.add( + Component.text( + value + ) + ); + + } + + lore.add( + Component.empty() + ); + + lore.add( + Component.text( + "Click to edit." + ) + ); + + meta.lore( + lore + ); + + book.setItemMeta( + meta + ); + + menu.setItem( + 11 + i, + book + ); + + } + + menu.setItem( + 22, + RSMenuUtils.createMenuItem( + Material.LIME_WOOL, + "§aCreate Category" + ) + ); + + menu.setItem( + 4, + RSMenuUtils.createMenuItem( + Material.OAK_DOOR, + "§eBack" + ) + ); + + player.openInventory( + menu + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryLoreMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryLoreMenuListener.java new file mode 100644 index 0000000..4ce4a35 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryLoreMenuListener.java @@ -0,0 +1,236 @@ +package com.rsscripting.rswarehouse.category.categorycreation; + +import com.rsscripting.rswarehouse.admin.admindao.CreateCategoryDAO; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryMenu; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; + +public class CategoryLoreMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getInventory() + .getHolder() + instanceof RSMenuHolder holder)) { + + return; + + } + + if (!holder.getMenuId().equals( + "CATEGORY_LORE" + )) { + + return; + + } + + event.setCancelled( + true + ); + + Player player = + (Player) event.getWhoClicked(); + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + switch (event.getSlot()) { + + case 4 -> CategoryMaterialPickerMenu.open( + player, + 0 + ); + + case 11 -> editLore( + player, + session, + 0 + ); + + case 12 -> editLore( + player, + session, + 1 + ); + + case 13 -> editLore( + player, + session, + 2 + ); + + case 14 -> editLore( + player, + session, + 3 + ); + + case 15 -> editLore( + player, + session, + 4 + ); + + case 22 -> createCategory( + player, + session + ); + + } + + } + + private void editLore( + Player player, + GuiSession session, + int loreSlot + ) { + + session.setPendingCategoryLoreSlot( + loreSlot + ); + + session.setPendingCategoryLoreExpiration( + System.currentTimeMillis() + + 30000 + ); + + final long expiration = + session.getPendingCategoryLoreExpiration(); + + Bukkit.getScheduler() + .runTaskLater( + Bukkit.getPluginManager() + .getPlugin( + "RS-Warehouse" + ), + () -> { + + if ( + session.getPendingCategoryLoreExpiration() + != expiration + ) { + + return; + + } + + session.setPendingCategoryLoreSlot( + -1 + ); + + session.setPendingCategoryLoreExpiration( + 0 + ); + + RSMessageUtils.error( + player, + "Lore input timed out." + ); + + }, + 20L * 30 + ); + + player.closeInventory(); + + RSMessageUtils.info( + player, + "Enter lore for line " + + (loreSlot + 1) + + " in chat." + ); + + RSMessageUtils.info( + player, + "Type 'cancel' to abort." + ); + + RSMessageUtils.info( + player, + "Auto-Cancels after 30 seconds." + ); + + } + + private void createCategory( + Player player, + GuiSession session + ) { + + StringBuilder loreBuilder = + new StringBuilder(); + + for (int i = 0; i < 5; i++) { + + String line = + session.getPendingCategoryLore( + i + ); + + if (line == null) { + + line = ""; + + } + + loreBuilder.append( + line + ); + + if (i < 4) { + + loreBuilder.append( + "\n" + ); + + } + + } + + CreateCategoryDAO.createCategory( + session.getPendingCategoryInternalName(), + session.getPendingCategoryDisplayName(), + session.getPendingCategoryMaterial(), + loreBuilder.toString() + ); + + session.setPendingCategoryInternalName( + null + ); + + session.setPendingCategoryDisplayName( + null + ); + + session.setPendingCategoryMaterial( + null + ); + + session.clearPendingCategoryLore(); + + session.setPendingCategoryLoreSlot( + -1 + ); + + CategoryMenu.open( + player + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryMaterialPickerMenu.java b/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryMaterialPickerMenu.java new file mode 100644 index 0000000..33e5cc7 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryMaterialPickerMenu.java @@ -0,0 +1,110 @@ +package com.rsscripting.rswarehouse.category.categorycreation; + +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.Arrays; +import java.util.List; + +public class CategoryMaterialPickerMenu { + + public static void open( + Player player, + int page + ) { + + Inventory menu = + Bukkit.createInventory( + new RSMenuHolder( + "CATEGORY_MATERIAL_PICKER" + ), + 54, + "Select Material" + ); + + int slot = 0; + + List materials = + Arrays.stream( + Material.values() + ) + .filter( + Material::isItem + ) + .filter( + material -> + !material.name().endsWith( + "_SMITHING_TEMPLATE" + ) + ) + .toList(); + + int startIndex = + page * 45; + + int maxPages = + (int) Math.ceil( + (double) materials.size() + / 45 + ); + + for (int inventorySlot = 0; + inventorySlot < 45; + inventorySlot++) { + + int materialIndex = + startIndex + inventorySlot; + + if (materialIndex >= materials.size()) { + + break; + + } + + menu.setItem( + inventorySlot, + new ItemStack( + materials.get( + materialIndex + ) + ) + ); + + } + + if (page > 0) { + + menu.setItem( + 45, + RSMenuUtils.createMenuItem( + Material.ARROW, + "§cPrevious Page" + ) + ); + + } + + if (page < maxPages - 1) { + + menu.setItem( + 53, + RSMenuUtils.createMenuItem( + Material.ARROW, + "§aNext Page" + ) + ); + + } + + player.openInventory( + menu + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryMaterialPickerMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryMaterialPickerMenuListener.java new file mode 100644 index 0000000..0904814 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryMaterialPickerMenuListener.java @@ -0,0 +1,109 @@ +package com.rsscripting.rswarehouse.category.categorycreation; + +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; + +public class CategoryMaterialPickerMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getInventory() + .getHolder() + instanceof RSMenuHolder holder)) { + + return; + + } + + if (!holder.getMenuId().equals( + "CATEGORY_MATERIAL_PICKER" + )) { + + return; + + } + + event.setCancelled( + true + ); + + if (event.getCurrentItem() == null) { + + return; + + } + + Player player = + (Player) event.getWhoClicked(); + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + String categoryName = + session.getPendingCategoryInternalName(); + + if (categoryName == null) { + + player.closeInventory(); + + return; + + } + + if (event.getSlot() == 45) { + + session.setMaterialPickerPage( + Math.max( + 0, + session.getMaterialPickerPage() - 1 + ) + ); + + CategoryMaterialPickerMenu.open( + player, + session.getMaterialPickerPage() + ); + + return; + + } + + if (event.getSlot() == 53) { + + session.setMaterialPickerPage( + session.getMaterialPickerPage() + 1 + ); + + CategoryMaterialPickerMenu.open( + player, + session.getMaterialPickerPage() + ); + + return; + + } + + session.setPendingCategoryMaterial( + event.getCurrentItem() + .getType() + .name() + ); + + CategoryLoreMenu.open( + player + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryNameMenu.java b/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryNameMenu.java new file mode 100644 index 0000000..635dab6 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryNameMenu.java @@ -0,0 +1,94 @@ +package com.rsscripting.rswarehouse.category.categorycreation; + +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.MenuType; +import net.kyori.adventure.text.Component; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.view.AnvilView; + +import java.util.List; + + +public class CategoryNameMenu { + + public static final String TITLE = + "Category Name"; + + public static void open(Player player) { + + AnvilView view = MenuType.ANVIL + .builder() + .title( + Component.text( + TITLE + ) + ) + .build(player); + + ItemStack confirm = new ItemStack(Material.LIME_WOOL); + + ItemMeta meta = confirm.getItemMeta(); + + meta.displayName( + Component.text("") + ); + + meta.lore( + List.of( + Component.text( + "Save and proceed to material picker." + ).color( + NamedTextColor.WHITE + ) + ) + ); + + confirm.setItemMeta(meta); + + view.setItem( + 0, + confirm + ); + + + ItemStack cancel = new ItemStack(Material.RED_WOOL); + + ItemMeta metacancel = cancel.getItemMeta(); + + metacancel.displayName( + Component.text("") + ); + + metacancel.lore( + List.of( + Component.text( + "Cancel" + ).color( + NamedTextColor.WHITE + ) + ) + ); + + cancel.setItemMeta(metacancel); + + + view.setItem( + 1, + cancel + ); + + GuiSessionManager.getSession( + player + ).setCategoryInternalNameMenuOpen( + true + ); + + view.open(); + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryNameMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryNameMenuListener.java new file mode 100644 index 0000000..05caa99 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categorycreation/CategoryNameMenuListener.java @@ -0,0 +1,145 @@ +package com.rsscripting.rswarehouse.category.categorycreation; + +import com.rsscripting.rswarehouse.admin.AdminMenu; +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.view.AnvilView; +import org.bukkit.event.inventory.InventoryCloseEvent; + +public class CategoryNameMenuListener implements Listener { + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + + if (!(event.getView() instanceof AnvilView anvilView)) { + return; + } + + if (!event.getView() + .title() + .toString() + .contains( + CategoryNameMenu.TITLE + )) { + + return; + + } + + Player player = + (Player) event.getWhoClicked(); + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + if (!session.isCategoryInternalNameMenuOpen()) { + + return; + + } + + event.setCancelled(true); + + if (event.getCurrentItem() == null) { + return; + } + + if (event.getRawSlot() == 0) { + + String categoryName = + anvilView.getRenameText(); + + if (categoryName.length() > 25) { + + RSMessageUtils.error( + player, + "Category names may not exceed 25 characters." + ); + + return; + + } + + if (categoryName.isBlank()) { + + RSMessageUtils.error( + player, + "Category name cannot be empty." + ); + + return; + + } + + session.setPendingCategoryInternalName( + categoryName + ); + + session.setPendingCategoryMaterial( + null + ); + + session.clearPendingCategoryLore(); + + event.getView().getTopInventory().clear(); + + session.setCategoryInternalNameMenuOpen( + false + ); + + CategoryDisplayNameMenu.open( + player + ); + + return; + + } + + if (event.getRawSlot() == 1) { + + event.getView().getTopInventory().clear(); + + AdminMenu.open( + player + ); + + } + } + + @EventHandler + public void onInventoryClose( + InventoryCloseEvent event + ) { + + if (!(event.getView() + instanceof AnvilView)) { + + return; + + } + + if (!event.getView() + .title() + .toString() + .contains( + CategoryNameMenu.TITLE + )) { + + return; + + } + + event.getView() + .getTopInventory() + .clear(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditDisplayNameMenu.java b/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditDisplayNameMenu.java new file mode 100644 index 0000000..b0d865f --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditDisplayNameMenu.java @@ -0,0 +1,101 @@ +package com.rsscripting.rswarehouse.category.categoryedit; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.MenuType; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.view.AnvilView; + +import java.util.List; + +public class CategoryEditDisplayNameMenu { + + public static final String TITLE = + "Edit Display Name"; + + public static void open( + Player player, + String currentDisplayName + ) { + + AnvilView view = MenuType.ANVIL + .builder() + .title( + Component.text( + TITLE + ) + ) + .build(player); + + ItemStack confirm = + new ItemStack( + Material.LIME_WOOL + ); + + ItemMeta meta = + confirm.getItemMeta(); + + meta.displayName( + Component.text( + currentDisplayName + ) + ); + + meta.lore( + List.of( + Component.text( + "§aSave display name." + ).color( + NamedTextColor.WHITE + ) + ) + ); + + confirm.setItemMeta( + meta + ); + + view.setItem( + 0, + confirm + ); + + ItemStack cancel = + new ItemStack( + Material.RED_WOOL + ); + + ItemMeta cancelMeta = + cancel.getItemMeta(); + + cancelMeta.displayName( + Component.text("") + ); + + cancelMeta.lore( + List.of( + Component.text( + "Cancel" + ).color( + NamedTextColor.WHITE + ) + ) + ); + + cancel.setItemMeta( + cancelMeta + ); + + view.setItem( + 1, + cancel + ); + + view.open(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditDisplayNameMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditDisplayNameMenuListener.java new file mode 100644 index 0000000..fdd7491 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditDisplayNameMenuListener.java @@ -0,0 +1,159 @@ +package com.rsscripting.rswarehouse.category.categoryedit; + +import com.rsscripting.rswarehouse.admin.admindao.UpdateCategoryDAO; +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryEditSession; +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryEditSessionManager; +import com.rsscripting.rswarehouse.category.categoryoptions.CategoryOptionsMenu; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.view.AnvilView; + +public class CategoryEditDisplayNameMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getView() instanceof AnvilView anvilView)) { + return; + } + + if (!event.getView() + .title() + .toString() + .contains( + CategoryEditDisplayNameMenu.TITLE + )) { + + return; + + } + + Player player = + (Player) event.getWhoClicked(); + + CategoryEditSession session = + CategoryEditSessionManager.getSession( + player.getUniqueId() + ); + + if (session == null) { + + return; + + } + + event.setCancelled( + true + ); + + if (event.getCurrentItem() == null) { + + return; + + } + + if (event.getRawSlot() == 0) { + + String displayName = + anvilView.getRenameText(); + + if (displayName.length() > 25) { + + RSMessageUtils.error( + player, + "Category names may not exceed 25 characters." + ); + + return; + + } + + if (displayName.isBlank()) { + + RSMessageUtils.error( + player, + "Category name cannot be empty." + ); + + return; + + } + + UpdateCategoryDAO.updateDisplayName( + session.getCategoryId(), + displayName + ); + + event.getView() + .getTopInventory() + .clear(); + + CategoryOptionsMenu.open( + player, + session.getCategoryId() + ); + + CategoryEditSessionManager.removeSession( + player.getUniqueId() + ); + + return; + + } + + if (event.getRawSlot() == 1) { + + event.getView() + .getTopInventory() + .clear(); + + CategoryOptionsMenu.open( + player, + session.getCategoryId() + ); + + CategoryEditSessionManager.removeSession( + player.getUniqueId() + ); + + } + + } + + @EventHandler + public void onInventoryClose( + InventoryCloseEvent event + ) { + + if (!(event.getView() + instanceof AnvilView)) { + + return; + + } + + if (!event.getView() + .title() + .toString() + .contains( + CategoryEditDisplayNameMenu.TITLE + )) { + + return; + + } + + event.getView() + .getTopInventory() + .clear(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditLoreMenu.java b/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditLoreMenu.java new file mode 100644 index 0000000..3d15d25 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditLoreMenu.java @@ -0,0 +1,169 @@ +package com.rsscripting.rswarehouse.category.categoryedit; + +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryEditSession; +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryEditSessionManager; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryDAO; +import com.rsscripting.rswarehouse.model.WarehouseCategory; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.ArrayList; +import java.util.List; + +public class CategoryEditLoreMenu { + + public static void open( + Player player + ) { + + Inventory menu = + Bukkit.createInventory( + new RSMenuHolder( + "CATEGORY_EDIT_LORE" + ), + 27, + Component.text( + " Edit Category Lore" + ) + ); + + for (int i = 0; i < menu.getSize(); i++) { + + menu.setItem( + i, + RSMenuUtils.createFillerPane() + ); + + } + + CategoryEditSession session = + CategoryEditSessionManager.getSession( + player.getUniqueId() + ); + + WarehouseCategory category = + CategoryDAO.getCategoryById( + session.getCategoryId() + ); + + String[] loreLines = + category.lore() == null + ? new String[5] + : category.lore().split("\n", -1); + + if (session.getLore(0) == null) { + + for (int i = 0; i < 5; i++) { + + if (i < loreLines.length) { + + session.setLore( + i, + loreLines[i] + ); + + } + + } + + } + + for (int i = 0; i < 5; i++) { + + ItemStack book = + new ItemStack( + Material.WRITABLE_BOOK + ); + + ItemMeta meta = + book.getItemMeta(); + + meta.displayName( + Component.text( + "Lore Line " + + (i + 1) + ) + ); + + List lore = + new ArrayList<>(); + + String value = + session.getLore(i); + + if ( + value == null + || value.isBlank() + ) { + + lore.add( + Component.text( + "(Empty)" + ) + ); + + } else { + + lore.add( + Component.text( + value + ) + ); + + } + + lore.add( + Component.empty() + ); + + lore.add( + Component.text( + "Click to edit." + ) + ); + + meta.lore( + lore + ); + + book.setItemMeta( + meta + ); + + menu.setItem( + 11 + i, + book + ); + + } + + menu.setItem( + 22, + RSMenuUtils.createMenuItem( + Material.LIME_WOOL, + "§aSave Lore" + ) + ); + + menu.setItem( + 4, + RSMenuUtils.createMenuItem( + Material.OAK_DOOR, + "§eBack" + ) + ); + + player.openInventory( + menu + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditLoreMenuChatListener.java b/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditLoreMenuChatListener.java new file mode 100644 index 0000000..2d0915b --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditLoreMenuChatListener.java @@ -0,0 +1,146 @@ +package com.rsscripting.rswarehouse.category.categoryedit; + +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryEditSession; +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryEditSessionManager; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; + +public class CategoryEditLoreMenuChatListener + implements Listener { + + @EventHandler + public void onPlayerChat( + AsyncPlayerChatEvent event + ) { + + Player player = + event.getPlayer(); + + CategoryEditSession session = + CategoryEditSessionManager.getSession( + player.getUniqueId() + ); + + if (session == null) { + + return; + + } + + int loreSlot = + session.getLoreSlot(); + + if (loreSlot < 0) { + + return; + + } + + event.setCancelled( + true + ); + + String message = + event.getMessage(); + + if (message.length() > 50) { + + RSMessageUtils.error( + player, + "Lore lines may not exceed 50 characters." + ); + + Bukkit.getScheduler() + .runTask( + Bukkit.getPluginManager() + .getPlugin( + "RS-Warehouse" + ), + () -> CategoryEditLoreMenu.open(player) + ); + + return; + + } + + if ( + message.equalsIgnoreCase( + "cancel" + ) + ) { + + session.setLoreSlot( + -1 + ); + + session.setLoreExpiration( + 0 + ); + + Bukkit.getScheduler() + .runTask( + Bukkit.getPluginManager() + .getPlugin( + "RS-Warehouse" + ), + () -> CategoryEditLoreMenu.open(player) + ); + + return; + + } + + if ( + message.equalsIgnoreCase("clear") + ) { + + session.setLore( + loreSlot, + "" + ); + + } + else { + + session.setLore( + loreSlot, + message + ); + + } + + session.setLoreSlot( + -1 + ); + + session.setLoreExpiration( + 0 + ); + + Bukkit.getScheduler() + .runTask( + Bukkit.getPluginManager() + .getPlugin( + "RS-Warehouse" + ), + () -> { + + RSMessageUtils.success( + player, + "Lore line saved." + ); + + CategoryEditLoreMenu.open( + player + ); + + } + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditLoreMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditLoreMenuListener.java new file mode 100644 index 0000000..b41f03b --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditLoreMenuListener.java @@ -0,0 +1,228 @@ +package com.rsscripting.rswarehouse.category.categoryedit; + +import com.rsscripting.rswarehouse.admin.admindao.UpdateCategoryDAO; +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryEditSession; +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryEditSessionManager; +import com.rsscripting.rswarehouse.category.categoryoptions.CategoryOptionsMenu; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; + +public class CategoryEditLoreMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getInventory() + .getHolder() + instanceof RSMenuHolder holder)) { + + return; + + } + + if (!holder.getMenuId().equals( + "CATEGORY_EDIT_LORE" + )) { + + return; + + } + + event.setCancelled( + true + ); + + Player player = + (Player) event.getWhoClicked(); + + CategoryEditSession session = + CategoryEditSessionManager.getSession( + player.getUniqueId() + ); + + switch (event.getSlot()) { + + case 4 -> { + + CategoryOptionsMenu.open( + player, + session.getCategoryId() + ); + + } + + case 11 -> editLore( + player, + session, + 0 + ); + + case 12 -> editLore( + player, + session, + 1 + ); + + case 13 -> editLore( + player, + session, + 2 + ); + + case 14 -> editLore( + player, + session, + 3 + ); + + case 15 -> editLore( + player, + session, + 4 + ); + + case 22 -> saveLore( + player, + session + ); + + } + + } + + private void editLore( + Player player, + CategoryEditSession session, + int loreSlot + ){ + + session.setLoreSlot( + loreSlot + ); + + session.setLoreExpiration( + System.currentTimeMillis() + + 30000 + ); + + final long expiration = + session.getLoreExpiration(); + + Bukkit.getScheduler() + .runTaskLater( + Bukkit.getPluginManager() + .getPlugin( + "RS-Warehouse" + ), + () -> { + + if ( + session.getLoreExpiration() + != expiration + ) { + + return; + + } + + session.setLoreSlot( + -1 + ); + + session.setLoreExpiration( + 0 + ); + + RSMessageUtils.error( + player, + "Lore input timed out." + ); + + }, + 20L * 30 + ); + + player.closeInventory(); + + RSMessageUtils.info( + player, + "Enter lore for line " + + (loreSlot + 1) + + " in chat." + ); + + RSMessageUtils.info( + player, + "Type 'cancel' to abort." + ); + + RSMessageUtils.info( + player, + "Type 'clear' to clear the lore line." + ); + + RSMessageUtils.info( + player, + "Auto-Cancels after 30 seconds." + ); + + } + + private void saveLore( + Player player, + CategoryEditSession session + ) { + + StringBuilder loreBuilder = + new StringBuilder(); + + for (int i = 0; i < 5; i++) { + + String line = + session.getLore(i); + + if (line == null) { + + line = ""; + + } + + loreBuilder.append( + line + ); + + if (i < 4) { + + loreBuilder.append( + "\n" + ); + + } + + } + + UpdateCategoryDAO.updateLore( + session.getCategoryId(), + loreBuilder.toString() + ); + + CategoryEditSessionManager.removeSession( + player.getUniqueId() + ); + + CategoryOptionsMenu.open( + player, + session.getCategoryId() + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditMaterialMenu.java b/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditMaterialMenu.java new file mode 100644 index 0000000..be6f008 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditMaterialMenu.java @@ -0,0 +1,110 @@ +package com.rsscripting.rswarehouse.category.categoryedit; + +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.Arrays; +import java.util.List; + +public class CategoryEditMaterialMenu { + + public static void open( + Player player, + int page + ) { + + Inventory menu = + Bukkit.createInventory( + new RSMenuHolder( + "CATEGORY_EDIT_MATERIAL_PICKER" + ), + 54, + "Select Material" + ); + + int slot = 0; + + List materials = + Arrays.stream( + Material.values() + ) + .filter( + Material::isItem + ) + .filter( + material -> + !material.name().endsWith( + "_SMITHING_TEMPLATE" + ) + ) + .toList(); + + int startIndex = + page * 45; + + int maxPages = + (int) Math.ceil( + (double) materials.size() + / 45 + ); + + for (int inventorySlot = 0; + inventorySlot < 45; + inventorySlot++) { + + int materialIndex = + startIndex + inventorySlot; + + if (materialIndex >= materials.size()) { + + break; + + } + + menu.setItem( + inventorySlot, + new ItemStack( + materials.get( + materialIndex + ) + ) + ); + + } + + if (page > 0) { + + menu.setItem( + 45, + RSMenuUtils.createMenuItem( + Material.ARROW, + "§cPrevious Page" + ) + ); + + } + + if (page < maxPages - 1) { + + menu.setItem( + 53, + RSMenuUtils.createMenuItem( + Material.ARROW, + "§aNext Page" + ) + ); + + } + + player.openInventory( + menu + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditMaterialMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditMaterialMenuListener.java new file mode 100644 index 0000000..f63e757 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categoryedit/CategoryEditMaterialMenuListener.java @@ -0,0 +1,106 @@ +package com.rsscripting.rswarehouse.category.categoryedit; + +import com.rsscripting.rswarehouse.admin.admindao.UpdateCategoryDAO; +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryEditSession; +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryEditSessionManager; +import com.rsscripting.rswarehouse.category.categoryoptions.CategoryOptionsMenu; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; + +public class CategoryEditMaterialMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getInventory() + .getHolder() + instanceof RSMenuHolder holder)) { + + return; + + } + + if (!holder.getMenuId().equals( + "CATEGORY_EDIT_MATERIAL_PICKER" + )) { + + return; + + } + + event.setCancelled( + true + ); + + if (event.getCurrentItem() == null) { + + return; + + } + + Player player = + (Player) event.getWhoClicked(); + + CategoryEditSession session = + CategoryEditSessionManager.getSession( + player.getUniqueId() + ); + + if (event.getSlot() == 45) { + + session.setMaterialPickerPage( + Math.max( + 0, + session.getMaterialPickerPage() - 1 + ) + ); + + CategoryEditMaterialMenu.open( + player, + session.getMaterialPickerPage() + ); + + return; + + } + + if (event.getSlot() == 53) { + + session.setMaterialPickerPage( + session.getMaterialPickerPage() + 1 + ); + + CategoryEditMaterialMenu.open( + player, + session.getMaterialPickerPage() + ); + + return; + + } + + UpdateCategoryDAO.updateMaterial( + session.getCategoryId(), + event.getCurrentItem() + .getType() + .name() + ); + + CategoryOptionsMenu.open( + player, + session.getCategoryId() + ); + + CategoryEditSessionManager.removeSession( + player.getUniqueId() + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categorymenu/CategoryDAO.java b/src/main/java/com/rsscripting/rswarehouse/category/categorymenu/CategoryDAO.java new file mode 100644 index 0000000..b976696 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categorymenu/CategoryDAO.java @@ -0,0 +1,263 @@ +package com.rsscripting.rswarehouse.category.categorymenu; + +import com.rsscripting.rswarehouse.database.DatabaseManager; +import com.rsscripting.rswarehouse.model.WarehouseCategory; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +public class CategoryDAO { + + public static List getCategories(){ + + List categories = + new ArrayList<>(); + + try ( + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT + id, + parent_category_id, + internal_name, + display_name, + material, + lore, + display_order, + page, + slot + FROM warehouse_categories + WHERE parent_category_id IS NULL + ORDER BY display_order ASC + """ + ); + + ResultSet resultSet = + statement.executeQuery() + ) { + + while (resultSet.next()) { + + categories.add( + new WarehouseCategory( + resultSet.getInt( + "id" + ), + resultSet.getObject( + "parent_category_id" + ) == null + ? null + : resultSet.getInt( + "parent_category_id" + ), + resultSet.getString( + "internal_name" + ), + resultSet.getString( + "display_name" + ), + resultSet.getString( + "material" + ), + resultSet.getString( + "lore" + ), + resultSet.getInt( + "display_order" + ), + resultSet.getInt( + "page" + ), + resultSet.getInt( + "slot" + ) + ) + ); + + } + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + return categories; + + } + + public static WarehouseCategory getCategoryById( + int categoryId + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT + id, + parent_category_id, + internal_name, + display_name, + material, + lore, + display_order, + page, + slot + FROM warehouse_categories + WHERE id = ? + """ + ) + + ) { + + statement.setInt( + 1, + categoryId + ); + + ResultSet resultSet = + statement.executeQuery(); + + if (resultSet.next()) { + + return new WarehouseCategory( + resultSet.getInt( + "id" + ), + resultSet.getObject( + "parent_category_id" + ) == null + ? null + : resultSet.getInt( + "parent_category_id" + ), + resultSet.getString( + "internal_name" + ), + resultSet.getString( + "display_name" + ), + resultSet.getString( + "material" + ), + resultSet.getString( + "lore" + ), + resultSet.getInt( + "display_order" + ), + resultSet.getInt( + "page" + ), + resultSet.getInt( + "slot" + ) + ); + + } + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + return null; + + } + + public static boolean categoryExists( + String name + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT 1 + FROM warehouse_categories + WHERE LOWER(internal_name) = LOWER(?) + LIMIT 1 + """ + ) + + ) { + + statement.setString( + 1, + name + ); + + return statement.executeQuery().next(); + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + return false; + + } + + public static void deleteCategory( + int categoryId + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + DELETE + FROM warehouse_categories + WHERE id = ? + """ + ) + + ) { + + statement.setInt( + 1, + categoryId + ); + + statement.executeUpdate(); + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categorymenu/CategoryMenu.java b/src/main/java/com/rsscripting/rswarehouse/category/categorymenu/CategoryMenu.java new file mode 100644 index 0000000..8b5824a --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categorymenu/CategoryMenu.java @@ -0,0 +1,429 @@ +package com.rsscripting.rswarehouse.category.categorymenu; + +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.model.WarehouseCategory; +import com.rsscripting.rswarehouse.constants.RSKeys; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CategoryMenu { + + public static final String MENU_TITLE = + "Categories"; + + public static void open( + Player player + ) { + + open( + player, + 1 + ); + + } + + public static void open( + Player player, + int page + ) { + + RSMenuHolder holder = + new RSMenuHolder( + "CATEGORIES" + ); + + holder.setPage( + page + ); + + Inventory menu = + Bukkit.createInventory( + holder, + 54, + Component.text( + MENU_TITLE + ).color( + NamedTextColor.BLUE + ) + ); + + ItemStack filler = + RSMenuUtils.createFillerPane(); + + for ( + int slot = 0; + slot <= 8; + slot++ + ) { + + menu.setItem( + slot, + filler + ); + + } + + menu.setItem( + 2, + RSMenuUtils.createMenuItemWithLore( + Material.HOPPER, + "§aAuto Deposit", + List.of( + "§7Automatically deposits", + "§7matching items into", + "§7Warehouse when picked up.", + "", + "§eClick to open." + ) + ) + ); + + List categories = + CategoryDAO.getCategories(); + + WarehouseCategory uncategorized = + null; + + List displayCategories = + new ArrayList<>(); + + for ( + WarehouseCategory category + : categories + ) { + + if ( + category.displayName() + .equalsIgnoreCase( + "Uncategorized" + ) + ) { + + uncategorized = + category; + + } + else { + + displayCategories.add( + category + ); + + } + + } + + if (page > 1) { + + menu.setItem( + 0, + RSMenuUtils.createMenuItem( + Material.ARROW, + "§aPrevious Page" + ) + ); + + } + + for ( + WarehouseCategory category + : displayCategories + ) { + + if ( + category.page() <= 0 + || category.slot() <= 0 + ) { + + continue; + + } + + if ( + category.page() + != page + ) { + + continue; + + } + + int slot = + category.slot(); + + if ( + slot < 9 + || slot > 53 + ) { + + continue; + + } + + List lore = + new ArrayList<>(); + + if ( + category.lore() != null + && !category.lore() + .isBlank() + ) { + + lore.addAll( + Arrays.asList( + category.lore() + .split( + "\n" + ) + ) + ); + + } + + ItemStack icon = + RSMenuUtils.createMenuItemWithLore( + Material.valueOf( + category.material() + ), + "§a" + + category.displayName(), + lore + ); + + ItemMeta meta = + icon.getItemMeta(); + + if (meta != null) { + + meta.addItemFlags( + ItemFlag.HIDE_ATTRIBUTES, + ItemFlag.HIDE_ADDITIONAL_TOOLTIP + ); + + meta.getPersistentDataContainer() + .set( + RSKeys.CATEGORY_ID, + PersistentDataType.INTEGER, + category.id() + ); + + icon.setItemMeta( + meta + ); + + } + + menu.setItem( + slot, + icon + ); + + } + + int highestAssignedPage = 1; + + List unassigned = + new ArrayList<>(); + + for ( + WarehouseCategory category + : displayCategories + ) { + + if ( + category.page() > 0 + ) { + + highestAssignedPage = + Math.max( + highestAssignedPage, + category.page() + ); + + } + + if ( + category.page() <= 0 + || category.slot() <= 0 + ) { + + unassigned.add( + category + ); + + } + + } + + boolean hasNextPage = + displayCategories.stream() + .anyMatch( + category -> + category.page() + > page + ); + + if ( + !unassigned.isEmpty() + && page + == highestAssignedPage + ) { + + hasNextPage = + true; + + } + + if (hasNextPage) { + + menu.setItem( + 8, + RSMenuUtils.createMenuItem( + Material.ARROW, + "§aNext Page" + ) + ); + + } + + if ( + page + == highestAssignedPage + 1 + ) { + + int slot = 9; + + for ( + WarehouseCategory category + : unassigned + ) { + + if (slot > 53) { + break; + } + + List lore = + new ArrayList<>(); + + if ( + category.lore() != null + && !category.lore() + .isBlank() + ) { + + lore.addAll( + Arrays.asList( + category.lore() + .split( + "\n" + ) + ) + ); + + } + + ItemStack icon = + RSMenuUtils.createMenuItemWithLore( + Material.valueOf( + category.material() + ), + "§a" + + category.displayName(), + lore + ); + + ItemMeta meta = + icon.getItemMeta(); + + if (meta != null) { + + meta.addItemFlags( + ItemFlag.HIDE_ATTRIBUTES, + ItemFlag.HIDE_ADDITIONAL_TOOLTIP + ); + + meta.getPersistentDataContainer() + .set( + RSKeys.CATEGORY_ID, + PersistentDataType.INTEGER, + category.id() + ); + + icon.setItemMeta( + meta + ); + + } + + menu.setItem( + slot, + icon + ); + + slot++; + + } + + } + + if (uncategorized != null) { + + ItemStack icon = + RSMenuUtils.createMenuItem( + Material.valueOf( + uncategorized.material() + ), + "§a" + + uncategorized.displayName() + ); + + ItemMeta meta = + icon.getItemMeta(); + + if (meta != null) { + + meta.addItemFlags( + ItemFlag.HIDE_ATTRIBUTES, + ItemFlag.HIDE_ADDITIONAL_TOOLTIP + ); + + meta.getPersistentDataContainer() + .set( + RSKeys.CATEGORY_ID, + PersistentDataType.INTEGER, + uncategorized.id() + ); + + icon.setItemMeta( + meta + ); + + } + + menu.setItem( + 4, + icon + ); + + } + + player.openInventory( + menu + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categorymenu/CategoryMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/category/categorymenu/CategoryMenuListener.java new file mode 100644 index 0000000..3dc30dd --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categorymenu/CategoryMenuListener.java @@ -0,0 +1,158 @@ +package com.rsscripting.rswarehouse.category.categorymenu; + + +import com.rsscripting.rswarehouse.category.categoryoptions.CategoryOptionsMenu; +import com.rsscripting.rswarehouse.autodeposit.AutoDepositMenu; +import com.rsscripting.rswarehouse.item.ItemsMenu; +import com.rsscripting.rswarehouse.navigation.NavigationManager; +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.constants.RSKeys; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; + + +public class CategoryMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + Player player = + (Player) event.getWhoClicked(); + + if (event.getView() + .getTopInventory() + .getHolder() + instanceof RSMenuHolder holder + && holder.getMenuId().equals( + "CATEGORIES" + )) { + + event.setCancelled( + true + ); + + ItemStack clicked = + event.getCurrentItem(); + + if (clicked == null) { + return; + } + + ItemMeta meta = + clicked.getItemMeta(); + + if (meta == null) { + return; + } + + RSMenuHolder menuHolder = + (RSMenuHolder) + event.getView() + .getTopInventory() + .getHolder(); + + int currentPage = + menuHolder.getPage(); + + if ( + event.getRawSlot() == 2 + ) { + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + session.setAutoDepositPage( + 1 + ); + + AutoDepositMenu.open( + player + ); + + return; + + } + + if ( + event.getRawSlot() + == 0 + ) { + + CategoryMenu.open( + player, + currentPage - 1 + ); + + return; + + } + + if ( + event.getRawSlot() + == 8 + ) { + + CategoryMenu.open( + player, + currentPage + 1 + ); + + return; + + } + + Integer categoryId = + meta.getPersistentDataContainer().get( + RSKeys.CATEGORY_ID, + PersistentDataType.INTEGER + ); + + if (categoryId == null) { + return; + } + + if ( + player.isOp() + && event.getClick() + == ClickType.SHIFT_RIGHT + ) { + + CategoryOptionsMenu.open( + player, + categoryId + ); + + return; + + } + + String categoryName = + clicked.getItemMeta() + .getDisplayName(); + + NavigationManager.openItems( + player, + categoryId, + categoryName, + 0 + ); + + } + + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categoryoptions/CategoryOptionsMenu.java b/src/main/java/com/rsscripting/rswarehouse/category/categoryoptions/CategoryOptionsMenu.java new file mode 100644 index 0000000..965a6e2 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categoryoptions/CategoryOptionsMenu.java @@ -0,0 +1,236 @@ +package com.rsscripting.rswarehouse.category.categoryoptions; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +public class CategoryOptionsMenu { + + public static void open( + Player player, + int categoryId + ) { + + Inventory menu = + Bukkit.createInventory( + new CategoryOptionsMenuHolder( + categoryId + ), + 27, + "Category Options" + ); + + ItemStack filler = + new ItemStack( + Material.LIGHT_BLUE_STAINED_GLASS_PANE + ); + + ItemMeta fillerMeta = + filler.getItemMeta(); + + fillerMeta.displayName( + Component.text( + " " + ) + ); + + filler.setItemMeta( + fillerMeta + ); + + for ( + int i = 0; + i <= 8; + i++ + ) { + + menu.setItem( + i, + filler + ); + + } + + ItemStack back = + new ItemStack( + Material.OAK_DOOR + ); + + ItemMeta backMeta = + back.getItemMeta(); + + backMeta.displayName( + Component.text( + "Back" + ).color( + NamedTextColor.GREEN + ) + ); + + back.setItemMeta( + backMeta + ); + + menu.setItem( + 4, + back + ); + + player.openInventory( + menu + ); + + ItemStack editName = + new ItemStack( + Material.NAME_TAG + ); + + ItemMeta editNameMeta = + editName.getItemMeta(); + + editNameMeta.displayName( + Component.text( + "Edit Display Name" + ).color( + NamedTextColor.YELLOW + ) + ); + + editName.setItemMeta( + editNameMeta + ); + + menu.setItem( + 9, + editName + ); + + ItemStack pageSlot = + new ItemStack( + Material.BOOK + ); + + ItemMeta pageSlotMeta = + pageSlot.getItemMeta(); + + pageSlotMeta.displayName( + Component.text( + "Assign Page / Slot" + ).color( + NamedTextColor.YELLOW + ) + ); + + pageSlot.setItemMeta( + pageSlotMeta + ); + + menu.setItem( + 11, + pageSlot + ); + + ItemStack editLore = + new ItemStack( + Material.WRITABLE_BOOK + ); + + ItemMeta editLoreMeta = + editLore.getItemMeta(); + + editLoreMeta.displayName( + Component.text( + "Edit Lore" + ).color( + NamedTextColor.YELLOW + ) + ); + + editLore.setItemMeta( + editLoreMeta + ); + + menu.setItem( + 13, + editLore + ); + + ItemStack material = + new ItemStack( + Material.ITEM_FRAME + ); + + ItemMeta materialMeta = + material.getItemMeta(); + + materialMeta.displayName( + Component.text( + "Change Material" + ).color( + NamedTextColor.YELLOW + ) + ); + + material.setItemMeta( + materialMeta + ); + + menu.setItem( + 15, + material + ); + + ItemStack delete = + new ItemStack( + Material.BARRIER + ); + + ItemMeta deleteMeta = + delete.getItemMeta(); + + deleteMeta.displayName( + Component.text( + "Delete Category" + ).color( + NamedTextColor.RED + ) + ); + + deleteMeta.lore( + java.util.List.of( + Component.text( + "Warning!!" + ).color( + NamedTextColor.RED + ), + Component.text( + "This cannot be undone." + ).color( + NamedTextColor.GRAY + ), + Component.empty(), + Component.text( + "Category must be empty." + ).color( + NamedTextColor.YELLOW + ) + ) + ); + + delete.setItemMeta( + deleteMeta + ); + + menu.setItem( + 17, + delete + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categoryoptions/CategoryOptionsMenuHolder.java b/src/main/java/com/rsscripting/rswarehouse/category/categoryoptions/CategoryOptionsMenuHolder.java new file mode 100644 index 0000000..6a472db --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categoryoptions/CategoryOptionsMenuHolder.java @@ -0,0 +1,25 @@ +package com.rsscripting.rswarehouse.category.categoryoptions; + +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +public class CategoryOptionsMenuHolder + implements InventoryHolder { + + private final int categoryId; + + public CategoryOptionsMenuHolder( + int categoryId + ) { + this.categoryId = categoryId; + } + + public int getCategoryId() { + return categoryId; + } + + @Override + public Inventory getInventory() { + return null; + } +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/categoryoptions/CategoryOptionsMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/category/categoryoptions/CategoryOptionsMenuListener.java new file mode 100644 index 0000000..3f04136 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/categoryoptions/CategoryOptionsMenuListener.java @@ -0,0 +1,242 @@ +package com.rsscripting.rswarehouse.category.categoryoptions; + +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryEditSession; +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryEditSessionManager; +import com.rsscripting.rswarehouse.admin.assignpageslot.CategoryPageNumberMenu; +import com.rsscripting.rswarehouse.admin.adminsessions.CategoryPageSlotSessionManager; +import com.rsscripting.rswarehouse.category.categoryedit.CategoryEditDisplayNameMenu; +import com.rsscripting.rswarehouse.category.categoryedit.CategoryEditLoreMenu; +import com.rsscripting.rswarehouse.category.categoryedit.CategoryEditMaterialMenu; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryMenu; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryDAO; +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; +import com.rsscripting.rswarehouse.model.WarehouseCategory; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; + +public class CategoryOptionsMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getView() + .getTopInventory() + .getHolder() + instanceof CategoryOptionsMenuHolder)) { + return; + } + + event.setCancelled( + true + ); + + Player player = + (Player) event.getWhoClicked(); + + if ( + event.getRawSlot() + == 4 + ) { + + CategoryMenu.open( + player + ); + + } + + if ( + event.getRawSlot() + == 9 + ) + { + + CategoryOptionsMenuHolder holder = + (CategoryOptionsMenuHolder) + event.getView() + .getTopInventory() + .getHolder(); + + CategoryEditSession session = + CategoryEditSessionManager.createSession( + player.getUniqueId(), + holder.getCategoryId() + ); + + WarehouseCategory category = + CategoryDAO.getCategoryById( + holder.getCategoryId() + ); + + CategoryEditDisplayNameMenu.open( + player, + category.displayName() + ); + + return; + + } + + if ( + event.getRawSlot() + == 11 + ) { + + CategoryOptionsMenuHolder holder = + (CategoryOptionsMenuHolder) + event.getView() + .getTopInventory() + .getHolder(); + + CategoryPageSlotSessionManager.createSession( + player.getUniqueId(), + holder.getCategoryId() + ); + + CategoryPageNumberMenu.open( + player + ); + + return; + + } + + if ( + event.getRawSlot() + == 13 + ) + { + + CategoryOptionsMenuHolder holder = + (CategoryOptionsMenuHolder) + event.getView() + .getTopInventory() + .getHolder(); + + CategoryEditSessionManager.createSession( + player.getUniqueId(), + holder.getCategoryId() + ); + + CategoryEditLoreMenu.open( + player + ); + + return; + + } + + if ( + event.getRawSlot() + == 15 + ) + { + + CategoryOptionsMenuHolder holder = + (CategoryOptionsMenuHolder) + event.getView() + .getTopInventory() + .getHolder(); + + CategoryEditSessionManager.createSession( + player.getUniqueId(), + holder.getCategoryId() + ); + + CategoryEditMaterialMenu.open( + player, + 0 + ); + + return; + + } + + if ( + event.getRawSlot() + == 17 + ) + { + + CategoryOptionsMenuHolder holder = + (CategoryOptionsMenuHolder) + event.getView() + .getTopInventory() + .getHolder(); + + int categoryId = + holder.getCategoryId(); + + WarehouseCategory category = + CategoryDAO.getCategoryById( + categoryId + ); + + if ( + category != null + && + category.internalName() + .equalsIgnoreCase( + "uncategorized" + ) + ) { + + player.sendMessage( + Component.text( + "Uncategorized cannot be deleted." + ).color( + NamedTextColor.RED + ) + ); + + return; + + } + + if ( + ItemDAO.categoryHasItems( + categoryId + ) + ) { + + player.sendMessage( + Component.text( + "Cannot delete category. Category not empty." + ).color( + NamedTextColor.RED + ) + ); + + return; + + } + + CategoryDAO.deleteCategory( + categoryId + ); + + player.sendMessage( + Component.text( + "Category deleted." + ).color( + NamedTextColor.GREEN + ) + ); + + CategoryMenu.open( + player + ); + + return; + + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/copytocategory/CopyToCategoryMenu.java b/src/main/java/com/rsscripting/rswarehouse/category/copytocategory/CopyToCategoryMenu.java new file mode 100644 index 0000000..4ae16b8 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/copytocategory/CopyToCategoryMenu.java @@ -0,0 +1,196 @@ +package com.rsscripting.rswarehouse.category.copytocategory; + +import com.rsscripting.rswarehouse.category.categorymenu.CategoryDAO; +import com.rsscripting.rswarehouse.model.WarehouseCategory; +import com.rsscripting.rswarehouse.constants.RSKeys; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CopyToCategoryMenu { + + public static final String MENU_TITLE = + "Copy To Category"; + + public static void open( + Player player, + int itemId, + int page + ) { + + Inventory menu = + Bukkit.createInventory( + new CopyToCategoryMenuHolder( + itemId, + page + ), + 54, + Component.text( + MENU_TITLE + ).color( + NamedTextColor.BLUE + ) + ); + + ItemStack filler = + RSMenuUtils.createFillerPane(); + + for (int slot = 0; slot <= 8; slot++) { + + menu.setItem( + slot, + filler + ); + + } + + for (int slot = 45; slot <= 53; slot++) { + + menu.setItem( + slot, + filler + ); + + } + + List categories = + CategoryDAO.getCategories(); + + List displayCategories = + new ArrayList<>(); + + for (WarehouseCategory category : categories) { + displayCategories.add( + category + ); + } + + int pageSize = 36; + + int maxPage = + Math.max( + 0, + (displayCategories.size() - 1) + / pageSize + ); + + int startIndex = + page * pageSize; + + int endIndex = + Math.min( + startIndex + pageSize, + displayCategories.size() + ); + + boolean hasPrevious = + page > 0; + + boolean hasNext = + page < maxPage; + + if (hasPrevious) { + + menu.setItem( + 0, + RSMenuUtils.createMenuItem( + Material.ARROW, + "§aPrevious Page" + ) + ); + + } + + if (hasNext) { + + menu.setItem( + 8, + RSMenuUtils.createMenuItem( + Material.ARROW, + "§aNext Page" + ) + ); + + } + + int slot = 9; + + for ( + + int i = startIndex; + + i < endIndex; + + i++ + + ) { + + WarehouseCategory category = + displayCategories.get( + i + ); + + List lore = + new ArrayList<>(); + + if ( + category.lore() != null + && + !category.lore().isBlank() + ) { + + lore.addAll( + Arrays.asList( + category.lore().split("\n") + ) + ); + + } + + ItemStack icon = + RSMenuUtils.createMenuItemWithLore( + Material.valueOf( + category.material() + ), + "§a" + category.displayName(), + lore + ); + + ItemMeta meta = + icon.getItemMeta(); + + meta.getPersistentDataContainer().set( + RSKeys.CATEGORY_ID, + PersistentDataType.INTEGER, + category.id() + ); + + icon.setItemMeta( + meta + ); + + menu.setItem( + slot++, + icon + ); + + } + + player.openInventory( + menu + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/copytocategory/CopyToCategoryMenuHolder.java b/src/main/java/com/rsscripting/rswarehouse/category/copytocategory/CopyToCategoryMenuHolder.java new file mode 100644 index 0000000..138ccad --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/copytocategory/CopyToCategoryMenuHolder.java @@ -0,0 +1,41 @@ +package com.rsscripting.rswarehouse.category.copytocategory; + +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; + +public class CopyToCategoryMenuHolder + extends RSMenuHolder { + + private final int itemId; + + private final int page; + + public CopyToCategoryMenuHolder( + int itemId, + int page + ) { + + super( + "COPY_TO_CATEGORY" + ); + + this.itemId = + itemId; + + this.page = + page; + + } + + public int getItemId() { + + return itemId; + + } + + public int getPage() { + + return page; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/copytocategory/CopyToCategoryMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/category/copytocategory/CopyToCategoryMenuListener.java new file mode 100644 index 0000000..f7fcec1 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/copytocategory/CopyToCategoryMenuListener.java @@ -0,0 +1,143 @@ +package com.rsscripting.rswarehouse.category.copytocategory; + +import com.rsscripting.rswarehouse.category.categorymenu.CategoryDAO; +import com.rsscripting.rswarehouse.placement.placementdao.ItemPlacementDAO; +import com.rsscripting.rswarehouse.model.WarehouseCategory; +import com.rsscripting.rswarehouse.constants.RSKeys; +import com.rsscripting.rswarehouse.item.ItemsMenu; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +public class CopyToCategoryMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getWhoClicked() + instanceof Player player)) { + + return; + + } + + if (!(event.getInventory() + .getHolder() + instanceof CopyToCategoryMenuHolder holder)) { + + return; + + } + + if (!holder.getMenuId().equals( + "COPY_TO_CATEGORY" + )) { + + return; + + } + + event.setCancelled( + true + ); + + ItemStack clicked = + event.getCurrentItem(); + + if (clicked == null) { + + return; + + } + + ItemMeta meta = + clicked.getItemMeta(); + + if ( + clicked.getType() == Material.ARROW + ) { + + String name = + clicked.getItemMeta() + .getDisplayName(); + + if (name.equals("§aPrevious Page")) { + + CopyToCategoryMenu.open( + player, + holder.getItemId(), + holder.getPage() - 1 + ); + + return; + + } + + if (name.equals("§aNext Page")) { + + CopyToCategoryMenu.open( + player, + holder.getItemId(), + holder.getPage() + 1 + ); + + return; + + } + + } + + if (meta == null) { + + return; + + } + + Integer categoryId = + meta.getPersistentDataContainer().get( + RSKeys.CATEGORY_ID, + PersistentDataType.INTEGER + ); + + if (categoryId == null) { + + return; + + } + + ItemPlacementDAO.copyItemToCategory( + holder.getItemId(), + categoryId + ); + + player.sendMessage( + "§aItem copied successfully." + ); + + WarehouseCategory category = + CategoryDAO.getCategoryById( + categoryId + ); + + if (category != null) { + + ItemsMenu.open( + player, + category.id(), + category.displayName(), + 0 + ); + + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/movetocategory/MoveToCategoryMenu.java b/src/main/java/com/rsscripting/rswarehouse/category/movetocategory/MoveToCategoryMenu.java new file mode 100644 index 0000000..a17d835 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/movetocategory/MoveToCategoryMenu.java @@ -0,0 +1,265 @@ +package com.rsscripting.rswarehouse.category.movetocategory; + +import com.rsscripting.rswarehouse.category.categorymenu.CategoryDAO; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import com.rsscripting.rswarehouse.model.WarehouseCategory; +import com.rsscripting.rswarehouse.utils.MenuAutoCenterAndPagenation; +import com.rsscripting.rswarehouse.constants.RSKeys; + +import org.bukkit.Material; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.persistence.PersistentDataType; + +import java.util.Arrays; + +import java.util.ArrayList; +import java.util.List; + +public class MoveToCategoryMenu { + + public static final String MENU_TITLE = + "Move Item To Category"; + + public static void open( + Player player, + int itemId + ) { + + Inventory menu = + Bukkit.createInventory( + new MoveToCategoryMenuHolder( + itemId + ), + 54, + Component.text( + MENU_TITLE + ).color( + NamedTextColor.BLUE + ) + ); + + ItemStack filler = + RSMenuUtils.createFillerPane(); + + for (int slot = 0; slot <= 8; slot++) { + + menu.setItem( + slot, + filler + ); + + } + + for (int slot = 45; slot <= 53; slot++) { + + menu.setItem( + slot, + filler + ); + + } + + List categories = + CategoryDAO.getCategories(); + + WarehouseCategory uncategorized = null; + + List displayCategories = + new ArrayList<>(); + + for (WarehouseCategory category : categories) { + + if (category.displayName().equalsIgnoreCase( + "Uncategorized" + )) { + + uncategorized = category; + + } + + else { + + displayCategories.add( + category + ); + + } + + } + + int categoryIndex = 0; + + for (int row = 0; + row < 4; + row++) { + + int remaining = + displayCategories.size() + - categoryIndex; + + if (remaining <= 0) { + break; + } + + int itemsThisRow; + + if (remaining > 9) { + + itemsThisRow = 9; + + } + + else { + + itemsThisRow = remaining; + + } + + List rowSlots = + MenuAutoCenterAndPagenation + .getCenteredRowSlots( + itemsThisRow + ); + + if (itemsThisRow == 9) { + + rowSlots = List.of( + 0, 1, 2, 3, 4, 5, 6, 7, 8 + ); + + } + + int rowOffset = + 9 + (row * 9); + + for (int slot : rowSlots) { + + if (categoryIndex >= + displayCategories.size()) { + + break; + + } + + WarehouseCategory category = + displayCategories.get( + categoryIndex + ); + + List lore = + new ArrayList<>(); + + if ( + category.lore() != null + && !category.lore().isBlank() + ) { + + lore.addAll( + Arrays.asList( + category.lore() + .split("\n") + ) + ); + + } + + ItemStack icon = + RSMenuUtils.createMenuItemWithLore( + Material.valueOf( + category.material() + ), + "§a" + category.displayName(), + lore + ); + + ItemMeta meta = + icon.getItemMeta(); + + if (meta != null) { + + meta.addItemFlags( + ItemFlag.HIDE_ATTRIBUTES, + ItemFlag.HIDE_ADDITIONAL_TOOLTIP + ); + + meta.getPersistentDataContainer().set( + RSKeys.CATEGORY_ID, + PersistentDataType.INTEGER, + category.id() + ); + + icon.setItemMeta( + meta + ); + + } + + menu.setItem( + rowOffset + slot, + icon + ); + + categoryIndex++; + + } + + } + + if (uncategorized != null) { + + ItemStack icon = + RSMenuUtils.createMenuItem( + Material.valueOf( + uncategorized.material() + ), + "§a" + uncategorized.displayName() + ); + + ItemMeta meta = + icon.getItemMeta(); + + if (meta != null) { + + meta.addItemFlags( + ItemFlag.HIDE_ATTRIBUTES, + ItemFlag.HIDE_ADDITIONAL_TOOLTIP + ); + + meta.getPersistentDataContainer().set( + RSKeys.CATEGORY_ID, + PersistentDataType.INTEGER, + uncategorized.id() + ); + + icon.setItemMeta( + meta + ); + + } + + menu.setItem( + 4, + icon + ); + + } + + + + + + + player.openInventory( + menu + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/movetocategory/MoveToCategoryMenuHolder.java b/src/main/java/com/rsscripting/rswarehouse/category/movetocategory/MoveToCategoryMenuHolder.java new file mode 100644 index 0000000..f8dc013 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/movetocategory/MoveToCategoryMenuHolder.java @@ -0,0 +1,29 @@ +package com.rsscripting.rswarehouse.category.movetocategory; + +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; + +public class MoveToCategoryMenuHolder + extends RSMenuHolder { + + private final int itemId; + + public MoveToCategoryMenuHolder( + int itemId + ) { + + super( + "MOVE_TO_CATEGORY" + ); + + this.itemId = + itemId; + + } + + public int getItemId() { + + return itemId; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/category/movetocategory/MoveToCategoryMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/category/movetocategory/MoveToCategoryMenuListener.java new file mode 100644 index 0000000..95ef0ee --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/category/movetocategory/MoveToCategoryMenuListener.java @@ -0,0 +1,108 @@ +package com.rsscripting.rswarehouse.category.movetocategory; + +import com.rsscripting.rswarehouse.category.categorymenu.CategoryDAO; +import com.rsscripting.rswarehouse.placement.placementdao.ItemPlacementDAO; +import com.rsscripting.rswarehouse.item.ItemsMenu; +import com.rsscripting.rswarehouse.model.WarehouseCategory; +import com.rsscripting.rswarehouse.constants.RSKeys; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +public class MoveToCategoryMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getWhoClicked() + instanceof Player player)) { + + return; + + } + + if (!(event.getInventory() + .getHolder() + instanceof MoveToCategoryMenuHolder holder)) { + + return; + + } + + if (!holder.getMenuId().equals( + "MOVE_TO_CATEGORY" + )) { + + return; + + } + + event.setCancelled( + true + ); + + ItemStack clicked = + event.getCurrentItem(); + + if (clicked == null) { + + return; + + } + + ItemMeta meta = + clicked.getItemMeta(); + + if (meta == null) { + + return; + + } + + Integer categoryId = + meta.getPersistentDataContainer().get( + RSKeys.CATEGORY_ID, + PersistentDataType.INTEGER + ); + + if (categoryId == null) { + + return; + + } + + ItemPlacementDAO.moveItemToCategory( + holder.getItemId(), + categoryId + ); + + player.sendMessage( + "§aItem moved successfully." + ); + + WarehouseCategory category = + CategoryDAO.getCategoryById( + categoryId + ); + + if (category != null) { + + ItemsMenu.open( + player, + category.id(), + category.displayName(), + 0 + ); + + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/chestautoprocess/ChestAutoProcessingTask.java b/src/main/java/com/rsscripting/rswarehouse/chestautoprocess/ChestAutoProcessingTask.java new file mode 100644 index 0000000..3d7c7c3 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/chestautoprocess/ChestAutoProcessingTask.java @@ -0,0 +1,91 @@ +package com.rsscripting.rswarehouse.chestautoprocess; + +import com.rsscripting.rswarehouse.deposit.dao.ChestDAO; +import com.rsscripting.rswarehouse.deposit.dao.WarehouseChestDAO; +import org.bukkit.block.Chest; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import com.rsscripting.rswarehouse.deposit.WarehouseChestProcessor; +import org.bukkit.block.Block; + +import java.util.List; + +public class ChestAutoProcessingTask + extends BukkitRunnable { + + @Override + public void run() { + + List chests = + WarehouseChestDAO.getAllWarehouseChests(); + + for (Block block : chests) { + + if (!block.getChunk().isLoaded()) { + + continue; + + } + + if (!(block.getState() + instanceof Chest chest)) { + + continue; + + } + + String ownerName = + ChestDAO.getOwnerName( + chest.getBlock() + ); + + String ownerUuid = + ChestDAO.getOwnerUuid( + chest.getBlock() + ); + + int[] results = + WarehouseChestProcessor.processWarehouseChest( + chest + ); + + int processedStacks = + results[0]; + + int processedItems = + results[1]; + + if (processedStacks <= 0) { + + continue; + + } + + Player owner = + ChestDAO.getOnlineOwner( + chest + ); + + if (owner == null) { + + continue; + + } + + owner.sendMessage( + "§aYour Community Warehouse processed " + + processedItems + + " item" + + (processedItems == 1 ? "" : "s") + + " from " + + processedStacks + + " stack" + + (processedStacks == 1 ? "" : "s") + + "." + ); + + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/commands/RSPluginCommand.java b/src/main/java/com/rsscripting/rswarehouse/commands/RSPluginCommand.java new file mode 100644 index 0000000..1a95bf9 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/commands/RSPluginCommand.java @@ -0,0 +1,134 @@ +package com.rsscripting.rswarehouse.commands; + +import com.rsscripting.rswarehouse.config.ConfigManager; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryMenu; +import com.rsscripting.rswarehouse.constants.RSConstants; +import com.rsscripting.rswarehouse.navigation.NavigationManager; +import com.rsscripting.rswarehouse.utils.VersionUtils; +import org.bukkit.entity.Player; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +public class RSPluginCommand + implements CommandExecutor { + + + + @Override + public boolean onCommand( + + @NotNull CommandSender sender, + @NotNull Command command, + @NotNull String label, + @NotNull String @NotNull [] args + + ) { + + /* + |-------------------------------------------------------------------------- + | BASE COMMAND + |-------------------------------------------------------------------------- + */ + + if (args.length == 0) { + + sender.sendMessage( + RSConstants.PREFIX + + "Running " + + RSConstants.PLUGIN_NAME + ); + + return true; + + } + + /* + |-------------------------------------------------------------------------- + | RELOAD COMMAND + |-------------------------------------------------------------------------- + */ + + if (args[0].equalsIgnoreCase( + "reload" + )) { + + if (!sender.hasPermission( + RSConstants.ADMIN_PERMISSION + )) { + + sender.sendMessage( + RSConstants.PREFIX + + "No permission." + ); + + return true; + + } + + ConfigManager.reload(); + + sender.sendMessage( + RSConstants.PREFIX + + "Configuration reloaded." + ); + + return true; + + } + + /* + |-------------------------------------------------------------------------- + | OPEN COMMAND + |-------------------------------------------------------------------------- + */ + + if (args[0].equalsIgnoreCase( + "open" + )) { + + if (!(sender instanceof Player player)) { + + sender.sendMessage( + RSConstants.PREFIX + + "Players only." + ); + + return true; + + } + + NavigationManager.clear(player); + NavigationManager.openCategory(player, 1); + + return true; + + } + + /* + |-------------------------------------------------------------------------- + | VERSION COMMAND + |-------------------------------------------------------------------------- + */ + + if (args[0].equalsIgnoreCase( + "version" + )) { + + sender.sendMessage( + RSConstants.PREFIX + + RSConstants.PLUGIN_NAME + + " v" + + VersionUtils.getVersion() + ); + + return true; + + } + + return true; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/commands/RSTabCompleter.java b/src/main/java/com/rsscripting/rswarehouse/commands/RSTabCompleter.java new file mode 100644 index 0000000..4611d85 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/commands/RSTabCompleter.java @@ -0,0 +1,48 @@ +package com.rsscripting.rswarehouse.commands; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +public class RSTabCompleter + implements TabCompleter { + + @Override + public List onTabComplete( + + @NotNull CommandSender sender, + @NotNull Command command, + @NotNull String label, + @NotNull String @NotNull [] args + + + ) { + + List completions = + new ArrayList<>(); + + /* + |-------------------------------------------------------------------------- + | FIRST ARGUMENT + |-------------------------------------------------------------------------- + */ + + if (args.length == 1) { + + completions.add("reload"); + + completions.add("version"); + + completions.add("open"); + + } + + return completions; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/commands/ShopCommand.java b/src/main/java/com/rsscripting/rswarehouse/commands/ShopCommand.java new file mode 100644 index 0000000..8cfcfd1 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/commands/ShopCommand.java @@ -0,0 +1,36 @@ +package com.rsscripting.rswarehouse.commands; + +import com.rsscripting.rswarehouse.category.categorymenu.CategoryMenu; +import com.rsscripting.rswarehouse.deposit.DepositInventory; +import com.rsscripting.rswarehouse.navigation.NavigationManager; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +public class ShopCommand implements CommandExecutor { + + @Override + public boolean onCommand( + @NotNull CommandSender sender, + @NotNull Command command, + @NotNull String label, + @NotNull String[] args + ) { + + if (!(sender instanceof Player player)) { + return true; + } + + if (args.length == 1 && args[0].equalsIgnoreCase("deposit")) { + DepositInventory.open(player); + return true; + } + + NavigationManager.clear(player); + NavigationManager.openCategory(player, 1); + + return true; + } +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/config/ConfigManager.java b/src/main/java/com/rsscripting/rswarehouse/config/ConfigManager.java new file mode 100644 index 0000000..9a24b2e --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/config/ConfigManager.java @@ -0,0 +1,96 @@ +package com.rsscripting.rswarehouse.config; + +import com.rsscripting.rswarehouse.RSWarehouse; +import org.bukkit.configuration.file.FileConfiguration; + +public class ConfigManager { + + private static FileConfiguration config; + + /* + |-------------------------------------------------------------------------- + | SETUP + |-------------------------------------------------------------------------- + */ + + public static void setup() { + + RSWarehouse.getInstance() + .saveDefaultConfig(); + + config = + RSWarehouse.getInstance() + .getConfig(); + + } + + /* + |-------------------------------------------------------------------------- + | RELOAD + |-------------------------------------------------------------------------- + */ + + public static void reload() { + + RSWarehouse.getInstance() + .reloadConfig(); + + config = + RSWarehouse.getInstance() + .getConfig(); + + } + + /* + |-------------------------------------------------------------------------- + | GET CONFIG + |-------------------------------------------------------------------------- + */ + + public static FileConfiguration get() { + + return config; + + } + + /* + | Warehouse Chest name + */ + + public String getWarehouseChestName() { + + return config.getString( + "warehouse-chest-name", + "Community Warehouse" + ); + + } + + /* + | Uncateforized enabled + */ + + public boolean isUncategorizedEnabled() { + + return config.getBoolean( + "allow-uncategorized-item-creation", + true + ); + + } + + /* + | Chest Protection Enabled + */ + + public boolean isWarehouseChestProtectionEnabled() { + + return config.getBoolean( + "protect-warehouse-chests", + true + ); + + } + + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/constants/RSConstants.java b/src/main/java/com/rsscripting/rswarehouse/constants/RSConstants.java new file mode 100644 index 0000000..0a4ebba --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/constants/RSConstants.java @@ -0,0 +1,74 @@ +package com.rsscripting.rswarehouse.constants; + +import org.bukkit.Material; + +public class RSConstants { + + /* + |-------------------------------------------------------------------------- + | PLUGIN INFO + |-------------------------------------------------------------------------- + */ + + public static final String PLUGIN_NAME = + "RS-Warehouse"; + + public static final String PREFIX = + "§7[§cRS-Warehouse§7] §r"; + + public static final String COMMAND_ALIAS = + "rswarehouse"; + + /* + |-------------------------------------------------------------------------- + | GITHUB + |-------------------------------------------------------------------------- + */ + + public static final String GITHUB_USER = + "RS-Scripting"; + + public static final String GITHUB_REPOSITORY = + "RS-Warehouse"; + + /* + |-------------------------------------------------------------------------- + | PERMISSIONS + |-------------------------------------------------------------------------- + */ + + public static final String ADMIN_PERMISSION = + "rswarehouse.admin"; + + public static final String BYPASS_PERMISSION = + "rswarehouse.bypass"; + + /* + |-------------------------------------------------------------------------- + | REQUIRED CONVERSION ITEMS + |-------------------------------------------------------------------------- + */ + + public static final Material REQUIRED_HELD_ITEM = + Material.STICK; + + /* + |-------------------------------------------------------------------------- + | REQUIRED TARGET ENTITY + |-------------------------------------------------------------------------- + */ + + public static final Material + REQUIRED_TARGET_BLOCK = + Material.CHEST; + + /* + |-------------------------------------------------------------------------- + | MENU SETTINGS + |-------------------------------------------------------------------------- + */ + + public static final Material MENU_FILLER_MATERIAL = + Material.WHITE_STAINED_GLASS_PANE; + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/constants/RSKeys.java b/src/main/java/com/rsscripting/rswarehouse/constants/RSKeys.java new file mode 100644 index 0000000..b135ee6 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/constants/RSKeys.java @@ -0,0 +1,48 @@ +package com.rsscripting.rswarehouse.constants; + +import org.bukkit.NamespacedKey; + +import com.rsscripting.rswarehouse.RSWarehouse; + +public class RSKeys { + + public static final String FILTER_ALLOW_ALL = + "allow_all"; + + public static final String FILTER_WHITELIST = + "whitelist"; + + public static final String FILTER_BLACKLIST = + "blacklist"; + + public static final NamespacedKey CATEGORY_ID = + new NamespacedKey( + RSWarehouse.getInstance(), + "category_id" + ); + + public static final NamespacedKey ITEM_ID = + new NamespacedKey( + RSWarehouse.getInstance(), + "item_id" + ); + + public static final NamespacedKey DAMAGED_VARIANT_ID = + new NamespacedKey( + RSWarehouse.getInstance(), + "damaged_variant_id" + ); + + public static final NamespacedKey PARTIALLY_FILLED_VARIANT_ID = + new NamespacedKey( + RSWarehouse.getInstance(), + "partially_filled_variant_id" + ); + + public static final NamespacedKey ENCHANTED_VARIANT_ID = + new NamespacedKey( + RSWarehouse.getInstance(), + "enchanted_variant_id" + ); + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/conversion/ConvertMenu.java b/src/main/java/com/rsscripting/rswarehouse/conversion/ConvertMenu.java new file mode 100644 index 0000000..50cd979 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/conversion/ConvertMenu.java @@ -0,0 +1,67 @@ +package com.rsscripting.rswarehouse.conversion; + +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +public class ConvertMenu { + + public static final String MENU_TITLE = "Activate Warehouse Chest"; + + public static void open( + Player player + ) { + + Inventory menu = + Bukkit.createInventory( + new RSMenuHolder( + "CONVERT" + ), + 9, + Component.text( + MENU_TITLE + ).color( + NamedTextColor.BLUE + ) + ); + + /* + |-------------------------------------------------------------------------- + | FILLER + |-------------------------------------------------------------------------- + */ + + ItemStack filler = + RSMenuUtils.createFillerPane(); + + for (int i = 0; i < menu.getSize(); i++) { + + menu.setItem(i, filler); + + } + + /* + |-------------------------------------------------------------------------- + | CONVERT BUTTON + |-------------------------------------------------------------------------- + */ + + menu.setItem( + 4, + RSMenuUtils.createMenuItem( + Material.CRAFTING_TABLE, + "§aConvert" + ) + ); + + player.openInventory(menu); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/conversion/ConvertMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/conversion/ConvertMenuListener.java new file mode 100644 index 0000000..b100021 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/conversion/ConvertMenuListener.java @@ -0,0 +1,293 @@ +package com.rsscripting.rswarehouse.conversion; + +import com.rsscripting.rswarehouse.deposit.dao.ChestDAO; +import com.rsscripting.rswarehouse.deposit.dao.WarehouseChestDAO; +import com.rsscripting.rswarehouse.deposit.dao.VerifyIsChestDAO; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryMenu; +import com.rsscripting.rswarehouse.main.MainMenu; +import com.rsscripting.rswarehouse.constants.RSConstants; +import com.rsscripting.rswarehouse.navigation.NavigationManager; +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; + +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.block.Block; +import org.bukkit.block.Chest; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; +import org.bukkit.block.DoubleChest; +import org.bukkit.inventory.InventoryHolder; + +public class ConvertMenuListener + implements Listener { + + @EventHandler + public void onPlayerInteractBlock( + PlayerInteractEvent event + ) { + + Player player = + event.getPlayer(); + + if (event.getHand() != EquipmentSlot.HAND) { + return; + } + + Block block = + event.getClickedBlock(); + + if (block == null) { + return; + } + + /* + |-------------------------------------------------------------------------- + | REQUIRE SNEAKING + |-------------------------------------------------------------------------- + */ + + if (!player.isSneaking()) { + return; + } + + /* + |-------------------------------------------------------------------------- + | VALIDATE TARGET ENTITY + |-------------------------------------------------------------------------- + */ + + if (block.getType() != + RSConstants.REQUIRED_TARGET_BLOCK) { + return; + } + + /* + |-------------------------------------------------------------------------- + | VALIDATE HELD ITEM + |-------------------------------------------------------------------------- + */ + + ItemStack heldItem = + player.getInventory() + .getItemInMainHand(); + + if (heldItem.getType() != + RSConstants.REQUIRED_HELD_ITEM) { + return; + } + + /* + |-------------------------------------------------------------------------- + | CANCEL VANILLA ACTION + |-------------------------------------------------------------------------- + */ + + event.setCancelled(true); + + /* + |-------------------------------------------------------------------------- + | STORE SELECTED ENTITY + |-------------------------------------------------------------------------- + */ + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + Block warehouseBlock = + WarehouseChestDAO.getWarehouseChest( + block + ); + + if (warehouseBlock != null) { + + session.setSelectedBlock( + warehouseBlock + ); + + } + else { + + session.setSelectedBlock( + block + ); + + } + + /* +|-------------------------------------------------------------------------- +| ALREADY CONVERTED +|-------------------------------------------------------------------------- +*/ + + boolean warehouseChest = + VerifyIsChestDAO.isWarehouseChest( + block + ); + + if (!warehouseChest + && block.getState() + instanceof Chest chest) { + + InventoryHolder holder = + chest.getInventory() + .getHolder(); + + if (holder instanceof DoubleChest doubleChest) { + + if (doubleChest.getLeftSide() + instanceof Chest leftChest + && VerifyIsChestDAO.isWarehouseChest( + leftChest.getBlock() + )) { + + warehouseChest = true; + + } + + if (doubleChest.getRightSide() + instanceof Chest rightChest + && VerifyIsChestDAO.isWarehouseChest( + rightChest.getBlock() + )) { + + warehouseChest = true; + + } + + } + + } + + if (warehouseChest) { + + Block selectedBlock = + WarehouseChestDAO.getWarehouseChest( + block + ); + + if (selectedBlock == null) { + + selectedBlock = block; + + } + + if ( + + player.isOp() + + || + + ChestDAO.isOwner( + selectedBlock, + player + ) + + ) { + + NavigationManager.clear(player); + + GuiSessionManager + .getSession(player) + .setSelectedBlock(selectedBlock); + + NavigationManager.openMain(player); + + } + + else { + + CategoryMenu.open( + player + ); + + } + + return; + + } + + /* + |-------------------------------------------------------------------------- + | OPEN CONVERSION MENU + |-------------------------------------------------------------------------- + */ + + ConvertMenu.open(player); + + } + + /* + |-------------------------------------------------------------------------- + | GET SELECTED ENTITY + |-------------------------------------------------------------------------- + */ + + public Block getSelectedBlock( + Player player + ) { + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + return session.getSelectedBlock(); + + } + + /* + |-------------------------------------------------------------------------- + | Convert Back + |-------------------------------------------------------------------------- + */ + + public void convertBack( + Player player + ) { + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + Block block = + session.getSelectedBlock(); + + if (block == null) { + + player.closeInventory(); + + return; + + } + + WarehouseChestDAO.unregisterChest( + block + ); + + if (block.getState() instanceof Chest chest) { + + chest.customName( + null + ); + + chest.update(); + + } + + RSMessageUtils.success( + player, + "Warehouse Chest removed." + ); + + player.closeInventory(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/database/DatabaseManager.java b/src/main/java/com/rsscripting/rswarehouse/database/DatabaseManager.java new file mode 100644 index 0000000..5574ab4 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/database/DatabaseManager.java @@ -0,0 +1,97 @@ +package com.rsscripting.rswarehouse.database; + +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.logging.Level; + +public class DatabaseManager { + + private static JavaPlugin plugin; + + private static String databaseUrl; + + public static void initialize( + JavaPlugin pluginInstance + ) { + + plugin = pluginInstance; + + createDatabase(); + + DatabaseTableCreator.createTables( + plugin, + databaseUrl + ); + + DatabaseUpdater.updateDatabase( + plugin, + databaseUrl + ); + + } + + private static void createDatabase() { + + try { + + File databaseFile = + new File( + plugin.getDataFolder(), + "database.db" + ); + + if (!plugin.getDataFolder().exists()) { + + if (!plugin.getDataFolder().mkdirs()) { + + plugin.getLogger().severe( + "Failed to create plugin data folder." + ); + + return; + + } + + } + + databaseUrl = + "jdbc:sqlite:" + + databaseFile.getAbsolutePath(); + + Connection connection = + DriverManager.getConnection( + databaseUrl + ); + + connection.close(); + + plugin.getLogger().info( + "SQLite database initialized." + ); + + } catch (Exception e) { + + plugin.getLogger().log( + Level.SEVERE, + "Failed to initialize database.", + e + ); + + } + + } + + public static Connection getConnection() + throws SQLException { + + return DriverManager.getConnection( + databaseUrl + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/database/DatabaseTableCreator.java b/src/main/java/com/rsscripting/rswarehouse/database/DatabaseTableCreator.java new file mode 100644 index 0000000..05957db --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/database/DatabaseTableCreator.java @@ -0,0 +1,197 @@ +package com.rsscripting.rswarehouse.database; + +import org.bukkit.plugin.java.JavaPlugin; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.util.logging.Level; + +public class DatabaseTableCreator { + + public static void createTables( + JavaPlugin plugin, + String databaseUrl + ) { + + try ( + + Connection connection = + DriverManager.getConnection( + databaseUrl + ) + + ) { + + connection.createStatement().execute( + """ + CREATE TABLE IF NOT EXISTS warehouse_chests ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + world TEXT NOT NULL, + x INTEGER NOT NULL, + y INTEGER NOT NULL, + z INTEGER NOT NULL, + owner_uuid TEXT NOT NULL, + owner_name TEXT NOT NULL, + created_at TEXT NOT NULL + + ) + """ + ); + + connection.createStatement().execute( + """ + CREATE TABLE IF NOT EXISTS warehouse_items ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + category_id INTEGER NOT NULL, + serialized_item TEXT NOT NULL, + default_lore TEXT, + inventory_id INTEGER, + subcategory_id INTEGER, + page INTEGER, + slot INTEGER, + created_at TEXT NOT NULL + ) + """ + ); + + connection.createStatement().execute( + """ + CREATE TABLE IF NOT EXISTS warehouse_categories ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + parent_category_id INTEGER, + internal_name TEXT NOT NULL UNIQUE, + display_name TEXT NOT NULL, + material TEXT NOT NULL, + lore TEXT, + display_order INTEGER NOT NULL DEFAULT 0, + page INTEGER NOT NULL DEFAULT 0, + slot INTEGER NOT NULL DEFAULT 0 + ) + """ + ); + + connection.createStatement().execute( + """ + INSERT OR IGNORE INTO warehouse_categories ( + internal_name, + display_name, + material, + display_order, + page, + slot + ) + VALUES ( + 'uncategorized', + 'Uncategorized', + 'CHEST', + 0, + 0, + 4 + ) + + """ + ); + + connection.createStatement().execute( + """ + + CREATE TABLE IF NOT EXISTS warehouse_inventory ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + serialized_item TEXT NOT NULL, + quantity INTEGER NOT NULL, + discoverer_uuid TEXT NULL, + discoverer_name TEXT NULL, + discovered_date TEXT NULL, + lore TEXT + ) + """ + ); + + connection.createStatement().execute( + """ + + CREATE TABLE IF NOT EXISTS partially_filled_variants ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + parent_inventory_id INTEGER NOT NULL, + serialized_item TEXT NOT NULL, + quantity INTEGER NOT NULL, + lore TEXT, + FOREIGN KEY(parent_inventory_id) + REFERENCES warehouse_inventory(id) + ON DELETE CASCADE + ) + """ + ); + + connection.createStatement().execute( + """ + CREATE TABLE IF NOT EXISTS damaged_variants ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + parent_inventory_id INTEGER NOT NULL, + serialized_item TEXT NOT NULL, + quantity INTEGER NOT NULL, + lore TEXT + ) + """ + ); + + connection.createStatement().execute( + """ + CREATE TABLE IF NOT EXISTS enchanted_variants ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + parent_inventory_id INTEGER NOT NULL, + serialized_item TEXT NOT NULL, + quantity INTEGER NOT NULL, + lore TEXT + ) + """ + ); + + connection.createStatement().execute( + """ + CREATE TABLE IF NOT EXISTS auto_deposit_settings ( + player_uuid TEXT PRIMARY KEY, + enabled INTEGER NOT NULL DEFAULT 0 + ) + """ + ); + + connection.createStatement().execute( + """ + CREATE TABLE IF NOT EXISTS auto_deposit_filters ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + player_uuid TEXT NOT NULL, + serialized_item TEXT NOT NULL + ) + """ + ); + + connection.createStatement().execute( + """ + CREATE UNIQUE INDEX IF NOT EXISTS + idx_auto_deposit_filter + ON auto_deposit_filters ( + player_uuid, + serialized_item + ) + """ + ); + + + plugin.getLogger().info( + "Database tables initialized." + ); + + } catch (Exception e) { + + plugin.getLogger().log( + Level.SEVERE, + "Failed to create tables.", + e + ); + + } + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/database/DatabaseUpdater.java b/src/main/java/com/rsscripting/rswarehouse/database/DatabaseUpdater.java new file mode 100644 index 0000000..6cd76e9 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/database/DatabaseUpdater.java @@ -0,0 +1,102 @@ +package com.rsscripting.rswarehouse.database; + +import org.bukkit.plugin.java.JavaPlugin; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.util.logging.Level; + +public class DatabaseUpdater { + + public static void updateDatabase( + JavaPlugin plugin, + String databaseUrl + ) { + + try ( + + Connection connection = + DriverManager.getConnection( + databaseUrl + ) + + ) { + + ensureColumnExists( + connection, + "warehouse_items", + "page", + "INTEGER" + ); + + ensureColumnExists( + connection, + "warehouse_items", + "slot", + "INTEGER" + ); + + } + + catch (Exception e) { + + plugin.getLogger().log( + Level.SEVERE, + "Failed updating database.", + e + ); + + } + + } + + private static void ensureColumnExists( + Connection connection, + String table, + String column, + String definition + ) { + + try ( + + var columns = + connection + .getMetaData() + .getColumns( + null, + null, + table, + column + ) + + ) { + + if (!columns.next()) { + + connection.createStatement().execute( + "ALTER TABLE " + + table + + " ADD COLUMN " + + column + + " " + + definition + ); + + } + + } catch (Exception e) { + + JavaPlugin.getProvidingPlugin( + DatabaseUpdater.class + ).getLogger().log( + Level.SEVERE, + "Failed updating column " + + column, + e + ); + + } + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/deposit/DepositInventory.java b/src/main/java/com/rsscripting/rswarehouse/deposit/DepositInventory.java new file mode 100644 index 0000000..fd6e080 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/deposit/DepositInventory.java @@ -0,0 +1,25 @@ +package com.rsscripting.rswarehouse.deposit; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +public final class DepositInventory { + + private static final String TITLE = "Warehouse Deposit"; + + private DepositInventory() { + } + + public static void open(Player player) { + + Inventory inventory = Bukkit.createInventory( + new DepositInventoryHolder(), + 54, + TITLE + ); + + player.openInventory(inventory); + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/deposit/DepositInventoryHolder.java b/src/main/java/com/rsscripting/rswarehouse/deposit/DepositInventoryHolder.java new file mode 100644 index 0000000..811568f --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/deposit/DepositInventoryHolder.java @@ -0,0 +1,12 @@ +package com.rsscripting.rswarehouse.deposit; + +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +public final class DepositInventoryHolder implements InventoryHolder { + + @Override + public Inventory getInventory() { + return null; + } +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/deposit/WarehouseChestProcessor.java b/src/main/java/com/rsscripting/rswarehouse/deposit/WarehouseChestProcessor.java new file mode 100644 index 0000000..dcf902f --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/deposit/WarehouseChestProcessor.java @@ -0,0 +1,349 @@ +package com.rsscripting.rswarehouse.deposit; + +import com.rsscripting.rswarehouse.deposit.dao.ChestDAO; +import com.rsscripting.rswarehouse.inventory.inventorydao.InventoryCreationDAO; +import com.rsscripting.rswarehouse.inventory.inventorydao.InventoryLookupDAO; +import com.rsscripting.rswarehouse.variants.dao.DamagedVariantsDAO; +import com.rsscripting.rswarehouse.variants.dao.EnchantedVariantsDAO; +import com.rsscripting.rswarehouse.variants.dao.PartiallyFilledVariantsDAO; +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; +import com.rsscripting.rswarehouse.config.ConfigManager; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import org.bukkit.block.Chest; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.Damageable; + +public class WarehouseChestProcessor { + + public static int[] processWarehouseChest( + Chest chest + ) { + + int processedStacks = 0; + int processedItems = 0; + + String ownerUuid = + ChestDAO.getOwnerUuid( + chest.getBlock() + ); + + String ownerName = + ChestDAO.getOwnerName( + chest.getBlock() + ); + + ItemStack[] contents = + chest.getInventory() + .getContents(); + + boolean allowUncategorizedItemCreation = + ConfigManager.get() + .getBoolean( + "allow-uncategorized-item-creation" + ); + + boolean allowDamagedItemCreation = + ConfigManager.get() + .getBoolean( + "allow-damaged-item-creation" + ); + + for (ItemStack item : contents) { + + if (item == null) { + + continue; + + } + + int amount = + item.getAmount(); + + ItemStack baseItem = + ItemStackUtils.createBaseItem( + item + ); + + Integer parentId = + InventoryLookupDAO.findInventoryId( + baseItem + ); + + if (parentId == null) { + + if (!allowUncategorizedItemCreation) { + + continue; + + } + + parentId = + InventoryCreationDAO.createParentInventoryItem( + baseItem, + ownerUuid, + ownerName + ); + + } + + /* + * Damaged item test path + */ + + if ( + item.hasItemMeta() + && item.getItemMeta() + instanceof Damageable damageable + && damageable.getDamage() > 0 + ) { + + if (!allowDamagedItemCreation) { + + continue; + + } + + DamagedVariantsDAO.createDamagedVariant( + parentId, + item + ); + + item.setAmount( + 0 + ); + + processedStacks++; + processedItems += amount; + + continue; + + } + + /* + * Enchanted item test path + */ + + if ( + item.hasItemMeta() + && item.getItemMeta().hasEnchants() + ) { + + EnchantedVariantsDAO.createEnchantedVariant( + parentId, + item + ); + + item.setAmount( + 0 + ); + + processedStacks++; + processedItems += amount; + + continue; + + } + + /* + * Partially Filled item test path + */ + + if ( + ItemStackUtils.hasStoredContents( + item + ) + ) { + + PartiallyFilledVariantsDAO.createPartiallyFilledVariant( + parentId, + item + ); + + item.setAmount( + 0 + ); + + processedStacks++; + processedItems += amount; + + continue; + + } + + + ItemDAO.addItem( + ownerUuid, + ownerName, + baseItem, + item.getAmount(), + parentId + ); + + item.setAmount( + 0 + ); + + processedStacks++; + processedItems += amount; + + } + + return new int[] { + processedStacks, + processedItems + }; + + } + + public static int[] processDepositInventory( + Inventory inventory, + String ownerUuid, + String ownerName + ) { + + int processedStacks = 0; + int processedItems = 0; + + ItemStack[] contents = + inventory.getContents(); + + boolean allowUncategorizedItemCreation = + ConfigManager.get() + .getBoolean( + "allow-uncategorized-item-creation" + ); + + boolean allowDamagedItemCreation = + ConfigManager.get() + .getBoolean( + "allow-damaged-item-creation" + ); + + for (ItemStack item : contents) { + + if (item == null) { + + continue; + + } + + int amount = + item.getAmount(); + + ItemStack baseItem = + ItemStackUtils.createBaseItem( + item + ); + + Integer parentId = + InventoryLookupDAO.findInventoryId( + baseItem + ); + + if (parentId == null) { + + if (!allowUncategorizedItemCreation) { + + continue; + + } + + parentId = + InventoryCreationDAO.createParentInventoryItem( + baseItem, + ownerUuid, + ownerName + ); + + } + + if ( + item.hasItemMeta() + && item.getItemMeta() + instanceof Damageable damageable + && damageable.getDamage() > 0 + ) { + + if (!allowDamagedItemCreation) { + + continue; + + } + + DamagedVariantsDAO.createDamagedVariant( + parentId, + item + ); + + item.setAmount(0); + + processedStacks++; + processedItems += amount; + + continue; + + } + + if ( + item.hasItemMeta() + && item.getItemMeta().hasEnchants() + ) { + + EnchantedVariantsDAO.createEnchantedVariant( + parentId, + item + ); + + item.setAmount(0); + + processedStacks++; + processedItems += amount; + + continue; + + } + + if ( + ItemStackUtils.hasStoredContents( + item + ) + ) { + + PartiallyFilledVariantsDAO.createPartiallyFilledVariant( + parentId, + item + ); + + item.setAmount(0); + + processedStacks++; + processedItems += amount; + + continue; + + } + + ItemDAO.addItem( + ownerUuid, + ownerName, + baseItem, + item.getAmount(), + parentId + ); + + item.setAmount(0); + + processedStacks++; + processedItems += amount; + + } + + return new int[] { + processedStacks, + processedItems + }; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/deposit/WarehouseCloseListener.java b/src/main/java/com/rsscripting/rswarehouse/deposit/WarehouseCloseListener.java new file mode 100644 index 0000000..7842c8b --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/deposit/WarehouseCloseListener.java @@ -0,0 +1,103 @@ +package com.rsscripting.rswarehouse.deposit; + +import com.rsscripting.rswarehouse.admin.admindao.PurgeVariantsDAO; +import com.rsscripting.rswarehouse.deposit.dao.VerifyIsChestDAO; +import com.rsscripting.rswarehouse.config.ConfigManager; +import com.rsscripting.rswarehouse.navigation.NavigationManager; +import org.bukkit.block.Chest; +import org.bukkit.block.DoubleChest; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.InventoryHolder; + +public class WarehouseCloseListener + implements Listener { + + @EventHandler + public void onInventoryClose( + InventoryCloseEvent event + ) { + + boolean chestCloseProcessingEnabled = + ConfigManager.get() + .getBoolean( + "chest-close-processing.enabled" + ); + + if (!chestCloseProcessingEnabled) { + + return; + + } + + Player player = + (Player) event.getPlayer(); + + InventoryHolder holder = + event.getInventory() + .getHolder(); + + Chest chest; + + if (holder instanceof Chest singleChest) { + + chest = singleChest; + + } else if (holder instanceof DoubleChest doubleChest) { + + Chest leftChest = + (Chest) doubleChest + .getLeftSide(); + + Chest rightChest = + (Chest) doubleChest + .getRightSide(); + + if ( + VerifyIsChestDAO.isWarehouseChest( + leftChest.getBlock() + ) + ) { + + chest = leftChest; + + } else { + + chest = rightChest; + + } + + } else if (holder instanceof DepositInventoryHolder) { + + WarehouseChestProcessor.processDepositInventory( + event.getInventory(), + player.getUniqueId().toString(), + player.getName() + ); + + return; + + } else { + + return; + + } + + if ( + !VerifyIsChestDAO.isWarehouseChest( + chest.getBlock() + ) + ) { + + return; + + } + WarehouseChestProcessor.processWarehouseChest( + chest + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/deposit/dao/ChestDAO.java b/src/main/java/com/rsscripting/rswarehouse/deposit/dao/ChestDAO.java new file mode 100644 index 0000000..b42da7a --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/deposit/dao/ChestDAO.java @@ -0,0 +1,207 @@ +package com.rsscripting.rswarehouse.deposit.dao; + +import com.rsscripting.rswarehouse.RSWarehouse; +import com.rsscripting.rswarehouse.database.DatabaseManager; +import org.bukkit.Bukkit; +import org.bukkit.block.Block; +import org.bukkit.block.Chest; +import org.bukkit.entity.Player; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; + +public class ChestDAO { + + public static String getOwnerUuid( + Block block + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT owner_uuid + FROM warehouse_chests + WHERE world = ? + AND x = ? + AND y = ? + AND z = ? + """ + ); + + statement.setString( + 1, + block.getWorld().getName() + ); + + statement.setInt( + 2, + block.getX() + ); + + statement.setInt( + 3, + block.getY() + ); + + statement.setInt( + 4, + block.getZ() + ); + + ResultSet resultSet = + statement.executeQuery(); + + if (resultSet.next()) { + + return resultSet.getString( + "owner_uuid" + ); + + } + + } + + catch (Exception e) { + + RSWarehouse.getInstance() + .getLogger() + .severe( + "Failed getting warehouse owner UUID." + ); + + } + + return null; + + } + + public static String getOwnerName( + Block block + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT owner_name + FROM warehouse_chests + WHERE world = ? + AND x = ? + AND y = ? + AND z = ? + """ + ); + + statement.setString( + 1, + block.getWorld().getName() + ); + + statement.setInt( + 2, + block.getX() + ); + + statement.setInt( + 3, + block.getY() + ); + + statement.setInt( + 4, + block.getZ() + ); + + ResultSet resultSet = + statement.executeQuery(); + + if (resultSet.next()) { + + return resultSet.getString( + "owner_name" + ); + + } + + } + + catch (Exception e) { + + RSWarehouse.getInstance() + .getLogger() + .severe( + "Failed getting warehouse owner name." + ); + + } + + return null; + + } + + public static Player getOnlineOwner( + Chest chest + ) { + + String ownerUuid = + getOwnerUuid( + chest.getBlock() + ); + + if (ownerUuid == null) { + + return null; + + } + + try { + + return Bukkit.getPlayer( + java.util.UUID.fromString( + ownerUuid + ) + ); + + } + + catch (IllegalArgumentException e) { + + return null; + + } + + } + + public static boolean isOwner( + Block block, + Player player + ) { + + String ownerUuid = + getOwnerUuid( + block + ); + + return ownerUuid != null + && + ownerUuid.equals( + player.getUniqueId().toString() + ); + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/deposit/dao/VerifyIsChestDAO.java b/src/main/java/com/rsscripting/rswarehouse/deposit/dao/VerifyIsChestDAO.java new file mode 100644 index 0000000..6caf6c2 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/deposit/dao/VerifyIsChestDAO.java @@ -0,0 +1,73 @@ +package com.rsscripting.rswarehouse.deposit.dao; + +import com.rsscripting.rswarehouse.RSWarehouse; +import com.rsscripting.rswarehouse.database.DatabaseManager; +import org.bukkit.block.Block; + +import java.sql.Connection; +import java.sql.PreparedStatement; + +public class VerifyIsChestDAO { + + public static boolean isWarehouseChest( + Block block + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT 1 + FROM warehouse_chests + WHERE world = ? + AND x = ? + AND y = ? + AND z = ? + """ + ); + + statement.setString( + 1, + block.getWorld().getName() + ); + + statement.setInt( + 2, + block.getX() + ); + + statement.setInt( + 3, + block.getY() + ); + + statement.setInt( + 4, + block.getZ() + ); + + return statement.executeQuery().next(); + + } + + catch (Exception e) { + + RSWarehouse.getInstance() + .getLogger() + .severe( + "Failed checking Community Warehouse chest registration." + ); + + } + + return false; + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/deposit/dao/WarehouseChestDAO.java b/src/main/java/com/rsscripting/rswarehouse/deposit/dao/WarehouseChestDAO.java new file mode 100644 index 0000000..f292a7c --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/deposit/dao/WarehouseChestDAO.java @@ -0,0 +1,313 @@ +package com.rsscripting.rswarehouse.deposit.dao; + +import com.rsscripting.rswarehouse.RSWarehouse; +import com.rsscripting.rswarehouse.config.ConfigManager; +import com.rsscripting.rswarehouse.database.DatabaseManager; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.Chest; +import org.bukkit.block.DoubleChest; +import org.bukkit.entity.Player; +import org.bukkit.inventory.InventoryHolder; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; + +import static com.rsscripting.rswarehouse.deposit.dao.VerifyIsChestDAO.isWarehouseChest; + +public class WarehouseChestDAO { + + public static void unregisterChest( + Block block + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + DELETE FROM warehouse_chests + WHERE world = ? + AND x = ? + AND y = ? + AND z = ? + """ + ); + + statement.setString( + 1, + block.getWorld().getName() + ); + + statement.setInt( + 2, + block.getX() + ); + + statement.setInt( + 3, + block.getY() + ); + + statement.setInt( + 4, + block.getZ() + ); + + statement.executeUpdate(); + + } + + catch (Exception e) { + + RSWarehouse.getInstance() + .getLogger() + .severe( + "Failed to unregister Community Warehouse chest." + ); + + } + + } + + public static void registerChest( + Block block, + Player player + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + INSERT INTO warehouse_chests ( + world, + x, + y, + z, + owner_uuid, + owner_name, + created_at + ) + VALUES (?, ?, ?, ?, ?, ?, ?) + """ + ); + + statement.setString( + 1, + block.getWorld().getName() + ); + + statement.setInt( + 2, + block.getX() + ); + + statement.setInt( + 3, + block.getY() + ); + + statement.setInt( + 4, + block.getZ() + ); + + statement.setString( + 5, + player.getUniqueId().toString() + ); + + statement.setString( + 6, + player.getName() + ); + + statement.setString( + 7, + String.valueOf( + System.currentTimeMillis() + ) + ); + + statement.executeUpdate(); + + if (block.getState() instanceof Chest chest) { + + chest.customName( + Component.text( + ConfigManager.get() + .getString( + "warehouse-chest-name", + "Community Warehouse" + ) + ) + ); + + chest.update(); + + } + + } + + catch (Exception e) { + + RSWarehouse.getInstance() + .getLogger() + .severe( + "Failed to register Community Warehouse chest." + ); + + } + + } + + public static Block getWarehouseChest( + Block block + ) { + + if (isWarehouseChest(block)) { + + return block; + + } + + if (!(block.getState() instanceof Chest chest)) { + + return null; + + } + + InventoryHolder holder = + chest.getInventory() + .getHolder(); + + if (!(holder instanceof DoubleChest doubleChest)) { + + return null; + + } + + if (doubleChest.getLeftSide() + instanceof Chest leftChest + && isWarehouseChest( + leftChest.getBlock() + )) { + + return leftChest.getBlock(); + + } + + if (doubleChest.getRightSide() + instanceof Chest rightChest + && isWarehouseChest( + rightChest.getBlock() + )) { + + return rightChest.getBlock(); + + } + + return null; + + } + + public static List getAllWarehouseChests() { + + List chests = + new ArrayList<>(); + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT world, x, y, z + FROM warehouse_chests + """ + ); + + ResultSet resultSet = + statement.executeQuery(); + + while (resultSet.next()) { + + World world = + Bukkit.getWorld( + resultSet.getString( + "world" + ) + ); + + if (world == null) { + + continue; + + } + + int x = + resultSet.getInt( + "x" + ); + + int y = + resultSet.getInt( + "y" + ); + + int z = + resultSet.getInt( + "z" + ); + + Block block = + world.getBlockAt( + x, + y, + z + ); + + chests.add( + block + ); + + } + + } + + catch (Exception e) { + + RSWarehouse.getInstance() + .getLogger() + .severe( + "Failed loading warehouse chests." + ); + + } + + return chests; + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/discovery/0 b/src/main/java/com/rsscripting/rswarehouse/discovery/0 new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/rsscripting/rswarehouse/discovery/discoverydao/DiscoveryDAO.java b/src/main/java/com/rsscripting/rswarehouse/discovery/discoverydao/DiscoveryDAO.java new file mode 100644 index 0000000..e959105 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/discovery/discoverydao/DiscoveryDAO.java @@ -0,0 +1,70 @@ +package com.rsscripting.rswarehouse.discovery.discoverydao; + +import com.rsscripting.rswarehouse.database.DatabaseManager; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.time.LocalDate; + +public class DiscoveryDAO { + + public static void assignDiscovererIfNull( + int inventoryId, + String discovererUuid, + String discovererName + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + UPDATE warehouse_inventory + SET + discoverer_uuid = ?, + discoverer_name = ?, + discovered_date = ? + WHERE + id = ? + AND + discoverer_uuid IS NULL + """ + ); + + statement.setString( + 1, + discovererUuid + ); + + statement.setString( + 2, + discovererName + ); + + statement.setString( + 3, + LocalDate.now().toString() + ); + + statement.setInt( + 4, + inventoryId + ); + + int updated = + statement.executeUpdate(); + + } catch (Exception e) { + + e.printStackTrace(); + + } + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/inventory/InventoryQuantityDAO.java b/src/main/java/com/rsscripting/rswarehouse/inventory/InventoryQuantityDAO.java new file mode 100644 index 0000000..309bbdd --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/inventory/InventoryQuantityDAO.java @@ -0,0 +1,177 @@ +package com.rsscripting.rswarehouse.inventory; + +import com.rsscripting.rswarehouse.database.DatabaseManager; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class InventoryQuantityDAO { + + public static void deleteInventory( + int inventoryId + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + DELETE + FROM warehouse_inventory + WHERE id = ? + """ + ) + + ) { + + statement.setInt( + 1, + inventoryId + ); + + statement.executeUpdate(); + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + } + + public static long getInventoryQuantity( + int inventoryId + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT quantity + FROM warehouse_inventory + WHERE id = ? + """ + ); + + statement.setInt( + 1, + inventoryId + ); + + ResultSet resultSet = + statement.executeQuery(); + + if (resultSet.next()) { + + return resultSet.getLong( + "quantity" + ); + + } + + } catch (Exception e) { + + e.printStackTrace(); + + } + + return 0; + + } + + public static void updateInventoryQuantity( + int inventoryId, + long quantity + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + UPDATE warehouse_inventory + SET quantity = quantity + ? + WHERE id = ? + """ + ); + + statement.setLong( + 1, + quantity + ); + + statement.setInt( + 2, + inventoryId + ); + + statement.executeUpdate(); + + } catch (Exception e) { + + e.printStackTrace(); + + } + + } + + public static void removeInventoryQuantity( + int inventoryId, + long quantity + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + UPDATE warehouse_inventory + SET quantity = quantity - ? + WHERE id = ? + """ + ); + + statement.setLong( + 1, + quantity + ); + + statement.setInt( + 2, + inventoryId + ); + + statement.executeUpdate(); + + } catch (Exception e) { + + e.printStackTrace(); + + } + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/inventory/inventorydao/InventoryCreationDAO.java b/src/main/java/com/rsscripting/rswarehouse/inventory/inventorydao/InventoryCreationDAO.java new file mode 100644 index 0000000..38dd4f2 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/inventory/inventorydao/InventoryCreationDAO.java @@ -0,0 +1,128 @@ +package com.rsscripting.rswarehouse.inventory.inventorydao; + +import com.rsscripting.rswarehouse.references.referencesdao.WarehouseReferenceDAO; +import com.rsscripting.rswarehouse.database.DatabaseManager; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import org.bukkit.inventory.ItemStack; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.Statement; +import java.time.LocalDate; + +public class InventoryCreationDAO { + + public static Integer createParentInventoryItem( + ItemStack item, + String discovererUuid, + String discovererName + ) { + + int inventoryId = + createInventoryItem( + item, + 0, + discovererUuid, + discovererName + ); + + if (inventoryId == -1) { + + return -1; + + } + + WarehouseReferenceDAO.createWarehouseItemReference( + item, + inventoryId + ); + + return inventoryId; + + } + + public static int createInventoryItem( + ItemStack item, + long quantity, + String discovererUuid, + String discovererName + ) { + + String serializedItem = + ItemStackUtils.serialize( + item + ); + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + INSERT INTO warehouse_inventory ( + serialized_item, + quantity, + discoverer_uuid, + discoverer_name, + discovered_date + ) + VALUES (?, ?, ?, ?, ?) + """, + Statement.RETURN_GENERATED_KEYS + ); + + statement.setString( + 1, + serializedItem + ); + + statement.setLong( + 2, + quantity + ); + + statement.setString( + 3, + discovererUuid + ); + + statement.setString( + 4, + discovererName + ); + + statement.setString( + 5, + LocalDate.now().toString() + ); + + statement.executeUpdate(); + + ResultSet resultSet = + statement.getGeneratedKeys(); + + if (resultSet.next()) { + + return resultSet.getInt( + 1 + ); + + } + + } catch (Exception e) { + + e.printStackTrace(); + + } + + return -1; + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/inventory/inventorydao/InventoryLookupDAO.java b/src/main/java/com/rsscripting/rswarehouse/inventory/inventorydao/InventoryLookupDAO.java new file mode 100644 index 0000000..163ebbf --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/inventory/inventorydao/InventoryLookupDAO.java @@ -0,0 +1,85 @@ +package com.rsscripting.rswarehouse.inventory.inventorydao; + +import com.rsscripting.rswarehouse.database.DatabaseManager; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import org.bukkit.inventory.ItemStack; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; + +public class InventoryLookupDAO { + + public static Integer findInventoryId( + ItemStack item + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT id, serialized_item + FROM warehouse_inventory + """ + ); + + ResultSet resultSet = + statement.executeQuery(); + + while (resultSet.next()) { + + ItemStack stored = + ItemStackUtils.deserialize( + resultSet.getString( + "serialized_item" + ) + ); + + if (stored == null) { + + continue; + + } + + stored = + ItemStackUtils.createBaseItem( + stored + ); + + stored = + ItemStackUtils.createBaseItem( + stored + ); + + ItemStack compare = + ItemStackUtils.createBaseItem( + item.clone() + ); + + if (stored.isSimilar(compare)) { + + return resultSet.getInt( + "id" + ); + + } + + } + + } catch (Exception e) { + + e.printStackTrace(); + + } + + return null; + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/item/ItemsBuilder.java b/src/main/java/com/rsscripting/rswarehouse/item/ItemsBuilder.java new file mode 100644 index 0000000..1dd487d --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/ItemsBuilder.java @@ -0,0 +1,365 @@ +package com.rsscripting.rswarehouse.item; + +import com.rsscripting.rswarehouse.category.categorymenu.CategoryDAO; +import com.rsscripting.rswarehouse.model.WarehouseCategory; +import com.rsscripting.rswarehouse.model.WarehouseItem; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import com.rsscripting.rswarehouse.constants.RSKeys; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + + +public class ItemsBuilder { + + public static void applyDiscoveryLore( + WarehouseItem warehouseItem, + List lore + ){ + + lore.add( + Component.empty() + ); + + String discoveredDate = null; + + if (warehouseItem.discoveredDate() != null) { + + discoveredDate = + LocalDate.parse( + warehouseItem.discoveredDate() + ).format( + DateTimeFormatter.ofPattern( + "MM-dd-yyyy" + ) + ); + + } + + String discovererName = + warehouseItem.discovererName(); + + if ( + + discoveredDate == null + && discovererName == null + + ) { + + lore.add( + Component.text( + "Currently Undiscovered" + ).color( + NamedTextColor.YELLOW + ) + ); + + } + + else if ( + + discoveredDate != null + && discovererName != null + + ) { + + lore.add( + Component.text( + "Discovered on " + + discoveredDate + + " by " + + discovererName + ).color( + NamedTextColor.GRAY + ) + ); + + } + + else if ( + + discoveredDate != null + + ) { + + lore.add( + Component.text( + "Discovered on " + + discoveredDate + ).color( + NamedTextColor.GRAY + ) + ); + + } + + else { + + lore.add( + Component.text( + "Discovered by " + + discovererName + ).color( + NamedTextColor.GRAY + ) + ); + + } + + } + + public static void applyStockLore( + WarehouseItem warehouseItem, + List lore + ) { + + lore.add( + Component.text( + "In Stock: " + + String.format( + "%,d", + warehouseItem.quantity() + ) + ) + ); + + } + + public static void applySubCategoryLore( + WarehouseItem warehouseItem, + List lore + ) { + + lore.add( + Component.text( + "Click to open subcategory" + ).color( + NamedTextColor.GOLD + ) + ); + + String displayLore = null; + + if ( + warehouseItem.subcategoryId() != null + ) { + + WarehouseCategory subCategory = + CategoryDAO.getCategoryById( + warehouseItem.subcategoryId() + ); + + if (subCategory != null) { + + displayLore = + subCategory.lore(); + + } + + } + else { + + displayLore = + warehouseItem.defaultLore(); + + } + + if ( + displayLore != null + && + !displayLore.isBlank() + ) { + + lore.add( + Component.empty() + ); + + for ( + String line : + displayLore.split( + "\n", + -1 + ) + ) { + + if ( + line.isBlank() + ) { + + continue; + + } + + lore.add( + Component.text( + line + ).color( + NamedTextColor.GRAY + ) + ); + + } + + } + + } + + public static List createLore( + ItemMeta meta, + boolean isSubCategory + ) { + + List lore = + new ArrayList<>(); + + if (!isSubCategory) { + + List existingLore = + meta.lore(); + + if (existingLore != null) { + + lore.addAll( + existingLore + ); + + } + + } + + if (!lore.isEmpty()) { + + lore.add( + Component.empty() + ); + + } + + return lore; + + } + + public static void applyDisplayName( + WarehouseItem warehouseItem, + ItemMeta meta + ){ + + boolean isSubCategory = + warehouseItem.subcategoryId() != null; + + if (isSubCategory) { + + WarehouseCategory subCategory = + CategoryDAO.getCategoryById( + warehouseItem.subcategoryId() + ); + + if (subCategory != null) { + + meta.displayName( + Component.text( + subCategory.displayName() + ).color( + NamedTextColor.WHITE + ) + ); + + } + + } + + } + + public static ItemStack buildDisplayItem( + WarehouseItem warehouseItem + ) { + + ItemStack item = + ItemStackUtils.deserialize( + warehouseItem.serializedItem() + ); + + boolean isSubCategory = + warehouseItem.subcategoryId() != null; + + if (isSubCategory) { + + item = + ItemStackUtils.createNavigationItem( + item + ); + + } + + if (item == null) { + + Bukkit.getLogger().info( + "Deserialize Failed" + ); + + return null; + + } + + return item; + + } + + public static void applyOperatorLore( + Player player, + WarehouseItem warehouseItem, + List lore + ) { + + if (!player.isOp()) { + + return; + + } + + lore.add( + Component.empty() + ); + + lore.add( + Component.text( + "Item ID: " + + warehouseItem.id() + ).color( + NamedTextColor.DARK_GRAY + ) + ); + + lore.add( + Component.text( + "Shift + Right Click for Item Options" + ).color( + NamedTextColor.GRAY + ) + ); + + } + + public static void applyPersistentData( + ItemMeta meta, + WarehouseItem warehouseItem + ) { + + meta.getPersistentDataContainer().set( + RSKeys.ITEM_ID, + PersistentDataType.INTEGER, + warehouseItem.id() + ); + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/item/ItemsMenu.java b/src/main/java/com/rsscripting/rswarehouse/item/ItemsMenu.java new file mode 100644 index 0000000..b57489f --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/ItemsMenu.java @@ -0,0 +1,354 @@ +package com.rsscripting.rswarehouse.item; + +import com.rsscripting.rswarehouse.RSWarehouse; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.model.WarehouseItem; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.MapMeta; +import org.bukkit.map.MapView; + +import java.util.List; + +public class ItemsMenu { + + public static final String MENU_TITLE = "Items"; + + public static void open( + Player player, + int categoryId, + String categoryName, + int page + ){ + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + session.setItemsCategoryId( + categoryId + ); + + session.setItemsCategoryName( + categoryName + ); + + session.setItemsPage( + page + ); + + Inventory menu = + Bukkit.createInventory( + new RSMenuHolder( + "ITEMS" + ), + 54, + Component.text( + categoryName + + " (Page " + + (page + 1) + + ")" + ).color( + NamedTextColor.BLUE + ) + ); + + ItemStack filler = + RSMenuUtils.createFillerPane(); + + for (int slot = 0; slot <= 8; slot++) { + + menu.setItem( + slot, + filler + ); + + } + + menu.setItem( + 4, + RSMenuUtils.createMenuItem( + Material.OAK_DOOR, + "§a Back" + ) + ); + + List items = + ItemsPagination.getItemsForDisplay( + categoryId, + page + ); + + int maxPage = + ItemsPagination.getMaximumPage( + categoryId + ); + + page = + Math.max( + 0, + Math.min( + page, + maxPage + ) + ); + + session.setItemsPage( + page + ); + + boolean hasPrevious = + page > 0; + + boolean hasNext = + page < maxPage; + int slot = 9; + + /* + * Find the highest assigned slot on this page. + * Automatic items begin immediately after it. + */ + for (WarehouseItem warehouseItem : items) { + + if ( + warehouseItem.page() != null + && + warehouseItem.slot() != null + && + warehouseItem.page() == (page + 1) + && + warehouseItem.slot() >= 9 + ) { + + slot = Math.max( + slot, + warehouseItem.slot() + 1 + ); + + } + + } + + for (WarehouseItem warehouseItem : items) { + + ItemStack item = + ItemsBuilder.buildDisplayItem( + warehouseItem + ); + + if (item == null) { + + continue; + + } + + boolean isSubCategory = + warehouseItem.subcategoryId() != null; + + ItemMeta meta = + item.getItemMeta(); + + + if (meta == null) { + + continue; + + } + + ItemsBuilder.applyDisplayName( + warehouseItem, + meta + ); + + List lore = + ItemsBuilder.createLore( + meta, + isSubCategory + ); + + if (isSubCategory) { + + ItemsBuilder.applySubCategoryLore( + warehouseItem, + lore + ); + + } + else { + + ItemsBuilder.applyStockLore( + warehouseItem, + lore + ); + + } + + if ( + + !isSubCategory + + && + + RSWarehouse.getInstance() + .getConfig() + .getBoolean( + "display.show-discovery-information", + true + ) + + ) { + + ItemsBuilder.applyDiscoveryLore( + warehouseItem, + lore + ); + + } + + ItemsBuilder.applyOperatorLore( + player, + warehouseItem, + lore + ); + + lore.addAll( + ItemStackUtils.getSpecialItemLore(item) + ); + + meta.lore( + lore + ); + + ItemsBuilder.applyPersistentData( + meta, + warehouseItem + ); + + item.setItemMeta( + meta + ); + + int displaySlot; + + if ( + warehouseItem.page() != null + && + warehouseItem.slot() != null + && + warehouseItem.page() > 0 + && + warehouseItem.slot() > 0 + ){ + + displaySlot = + warehouseItem.slot(); + + } + else { + + displaySlot = + slot++; + + } + + menu.setItem( + displaySlot, + item + ); + + } + + if (hasPrevious) { + + menu.setItem( + 0, + RSMenuUtils.createMenuItem( + Material.ARROW, + "§aPrevious Page" + ) + ); + + } + + if (hasNext) { + + menu.setItem( + 8, + RSMenuUtils.createMenuItem( + Material.ARROW, + "§aNext Page" + ) + ); + + } + + for (WarehouseItem warehouseItem : items) { + + ItemStack item = + ItemStackUtils.deserialize( + warehouseItem.serializedItem() + ); + + if ( + item == null + || + item.getType() + != Material.FILLED_MAP + ) { + + continue; + + } + + if ( + !(item.getItemMeta() + instanceof MapMeta mapMeta) + ) { + + continue; + + } + + if ( + !mapMeta.hasMapView() + ) { + + continue; + + } + + MapView mapView = + mapMeta.getMapView(); + + if ( + mapView == null + ) { + + continue; + + } + + player.sendMap( + mapView + ); + + } + + player.openInventory( + menu + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/item/ItemsMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/item/ItemsMenuListener.java new file mode 100644 index 0000000..c21c9af --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/ItemsMenuListener.java @@ -0,0 +1,177 @@ +package com.rsscripting.rswarehouse.item; + +import com.rsscripting.rswarehouse.category.categorymenu.CategoryDAO; +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryMenu; +import com.rsscripting.rswarehouse.item.options.ItemOptionsMenu; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.navigation.NavigationManager; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryClickEvent; +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import com.rsscripting.rswarehouse.session.TransactionSession; +import com.rsscripting.rswarehouse.model.WarehouseCategory; +import com.rsscripting.rswarehouse.model.WarehouseItem; +import com.rsscripting.rswarehouse.constants.RSKeys; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +public class ItemsMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + Player player = + (Player) event.getWhoClicked(); + + if ( + event.getView() + .getTopInventory() + .getHolder() + instanceof RSMenuHolder holder + && holder.getMenuId().equals( + "ITEMS" + ) + ) { + + event.setCancelled( + true + ); + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + if (event.getSlot() == 0) { + + if (session.getItemsPage() > 0) { + + ItemsMenu.open( + player, + session.getItemsCategoryId(), + session.getItemsCategoryName(), + session.getItemsPage() - 1 + ); + + } + + return; + + } + + if (event.getSlot() == 8) { + + ItemsMenu.open( + player, + session.getItemsCategoryId(), + session.getItemsCategoryName(), + session.getItemsPage() + 1 + ); + + return; + + } + + if (event.getSlot() == 4) { + + NavigationManager.back(player); + + return; + + } + + if (event.getCurrentItem() == null) { + + return; + + } + + ItemMeta meta = + event.getCurrentItem() + .getItemMeta(); + + if (meta == null) { + + return; + + } + + Integer itemId = + meta.getPersistentDataContainer() + .get( + RSKeys.ITEM_ID, + PersistentDataType.INTEGER + ); + + if (itemId == null) { + + return; + + } + + WarehouseItem warehouseItem = + ItemDAO.getItemById( + itemId + ); + + if ( + event.getClick() == ClickType.SHIFT_RIGHT + && player.isOp() + ) { + + ItemOptionsMenu.open( + player, + itemId + ); + + return; + + } + + if ( + + warehouseItem.subcategoryId() + != null + + ) { + + WarehouseCategory subCategory = + CategoryDAO.getCategoryById( + warehouseItem.subcategoryId() + ); + + NavigationManager.openItems( + player, + subCategory.id(), + subCategory.displayName(), + 0); + + return; + + } + + session.setItemActionSession( + new TransactionSession( + itemId + ) + ); + + TransactionAmountMenu.open( + player, + itemId, + 0 + ); + + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/item/ItemsPagination.java b/src/main/java/com/rsscripting/rswarehouse/item/ItemsPagination.java new file mode 100644 index 0000000..06d0465 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/ItemsPagination.java @@ -0,0 +1,308 @@ +package com.rsscripting.rswarehouse.item; + +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; +import com.rsscripting.rswarehouse.model.WarehouseItem; + +import java.util.ArrayList; +import java.util.List; + +public class ItemsPagination { + + public static int getMaximumPage( + int categoryId + ) { + + List items = + ItemDAO.getItemsForCategory( + categoryId + ); + + int highestAssignedPage = -1; + int unassigned = 0; + + for (WarehouseItem item : items) { + + if ( + item.page() != null + && + item.slot() != null + && + item.page() > 0 + && + item.slot() > 0 + ) { + + highestAssignedPage = + Math.max( + highestAssignedPage, + item.page() - 1 + ); + + } else { + + unassigned++; + + } + + } + + int consumed = 0; + + for (int assignedPage = 0; + assignedPage <= highestAssignedPage; + assignedPage++) { + + int highestSlot = 8; + + for (WarehouseItem item : items) { + + if ( + item.page() != null + && + item.slot() != null + && + item.page() == assignedPage + 1 + ) { + + highestSlot = + Math.max( + highestSlot, + item.slot() + ); + + } + + } + + consumed += + Math.max( + 0, + 53 - highestSlot + ); + + } + + consumed = + Math.min( + consumed, + unassigned + ); + + unassigned -= consumed; + + int overflowPages = + (unassigned + 44) / 45; + + return Math.max( + 0, + highestAssignedPage + overflowPages + ); + + } + + public static List getItemsForDisplay( + int categoryId, + int page + ) { + + List allItems = + ItemDAO.getItemsForCategory( + categoryId + ); + + List assigned = + new ArrayList<>(); + + List unassigned = + new ArrayList<>(); + + int highestAssignedPage = -1; + + for (WarehouseItem item : allItems) { + + if ( + item.page() != null + && + item.slot() != null + && + item.page() > 0 + && + item.slot() > 0 + ) { + + assigned.add(item); + + highestAssignedPage = + Math.max( + highestAssignedPage, + item.page() - 1 + ); + + } + + else { + + unassigned.add(item); + + } + + } + + /* + * Assigned pages + */ + if (page <= highestAssignedPage) { + + List results = + new ArrayList<>(); + + int highestSlot = 8; + + for (WarehouseItem item : assigned) { + + if (item.page() == (page + 1)) { + + results.add(item); + + highestSlot = + Math.max( + highestSlot, + item.slot() + ); + + } + + } + + /* + * Figure out how many unassigned items have + * already been consumed by previous assigned pages. + */ + int consumed = 0; + + for (int previousPage = 0; + previousPage < page; + previousPage++) { + + int previousHighestSlot = 8; + + for (WarehouseItem item : assigned) { + + if (item.page() == (previousPage + 1)) { + + previousHighestSlot = + Math.max( + previousHighestSlot, + item.slot() + ); + + } + + } + + consumed += + Math.max( + 0, + 53 - previousHighestSlot + ); + + } + + int remainingSlots = + Math.max( + 0, + 53 - highestSlot + ); + + while ( + remainingSlots > 0 + && + consumed < unassigned.size() + ) { + + results.add( + unassigned.get( + consumed + ) + ); + + consumed++; + remainingSlots--; + + } + + return results; + + } + + int consumed = 0; + + for (int assignedPage = 0; + assignedPage <= highestAssignedPage; + assignedPage++) { + + int highestSlot = 8; + + for (WarehouseItem item : assigned) { + + if (item.page() == assignedPage + 1) { + + highestSlot = + Math.max( + highestSlot, + item.slot() + ); + + } + + } + + consumed += + Math.max( + 0, + 53 - highestSlot + ); + + } + + consumed = + Math.min( + consumed, + unassigned.size() + ); + + /* + * Overflow pages + */ + + int overflowPage = + page + - highestAssignedPage + - 1; + + int start = + consumed + + (overflowPage * 45); + + if (start >= unassigned.size()) { + + return new ArrayList<>(); + + } + + int end = + Math.min( + start + 45, + unassigned.size() + ); + + return new ArrayList<>( + unassigned.subList( + start, + end + ) + ); + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/item/TransactionAmountButtonHandler.java b/src/main/java/com/rsscripting/rswarehouse/item/TransactionAmountButtonHandler.java new file mode 100644 index 0000000..c286426 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/TransactionAmountButtonHandler.java @@ -0,0 +1,58 @@ +package com.rsscripting.rswarehouse.item; + +public class TransactionAmountButtonHandler { + + public static Integer handle( + int slot, + int amount, + long playerHas, + long maxWithdraw + ) { + + switch (slot) { + + case 9 -> + amount -= 64; + + case 10 -> + amount -= 16; + + case 11 -> + amount -= 1; + + case 15 -> + amount += 1; + + case 16 -> + amount += 16; + + case 17 -> + amount += 64; + + default -> { + + return null; + + } + + } + + if (amount > playerHas) { + + amount = + (int) playerHas; + + } + + if (amount < -maxWithdraw) { + + amount = + (int) -maxWithdraw; + + } + + return amount; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/item/TransactionAmountMenu.java b/src/main/java/com/rsscripting/rswarehouse/item/TransactionAmountMenu.java new file mode 100644 index 0000000..7c156de --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/TransactionAmountMenu.java @@ -0,0 +1,225 @@ +package com.rsscripting.rswarehouse.item; + +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.model.WarehouseItem; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +public class TransactionAmountMenu { + + public static void open( + Player player, + int itemId, + int amount + ) { + + String title; + + if (amount > 0) { + + title = + "Deposit: " + + String.format( + "%,d", + amount + ); + + } else if (amount < 0) { + + title = + "Withdraw: " + + String.format( + "%,d", + Math.abs( + amount + ) + ); + + } else { + + title = + "Amount: 0"; + + } + + Inventory menu = + Bukkit.createInventory( + new RSMenuHolder( + "ITEM_ACTION" + ), + 27, + Component.text( + title + ).color( + NamedTextColor.BLUE + ) + ); + + /* + |-------------------------------------------------------------------------- + | FILLER + |-------------------------------------------------------------------------- + */ + + for (int i = 0; i < menu.getSize(); i++) { + + menu.setItem( + i, + RSMenuUtils.createFillerPane() + ); + + } + +/* +|-------------------------------------------------------------------------- +| CENTER ITEM +|-------------------------------------------------------------------------- +*/ + + WarehouseItem warehouseItem = + ItemDAO.getItemById( + itemId + ); + + TransactionCenterItemBuilder.addCenterItem( + menu, + player, + warehouseItem + ); + + /* + |-------------------------------------------------------------------------- + | WITHDRAW + |-------------------------------------------------------------------------- + */ + + ItemStack subtract64 = + RSMenuUtils.createMenuItem( + Material.RED_WOOL, + "§cSubtract 64" + ); + + subtract64.setAmount( + 64 + ); + + menu.setItem( + 9, + subtract64 + ); + + ItemStack subtract16 = + RSMenuUtils.createMenuItem( + Material.RED_WOOL, + "§cSubtract 16" + ); + + subtract16.setAmount( + 16 + ); + + menu.setItem( + 10, + subtract16 + ); + + + ItemStack subtract1 = + RSMenuUtils.createMenuItem( + Material.RED_WOOL, + "§cSubtract 1" + ); + + subtract1.setAmount( + 1 + ); + + menu.setItem( + 11, + subtract1 + ); + + /* + |-------------------------------------------------------------------------- + | DEPOSIT + |-------------------------------------------------------------------------- + */ + + ItemStack add1 = + RSMenuUtils.createMenuItem( + Material.GREEN_WOOL, + "§cAdd 1" + ); + + add1.setAmount( + 1 + ); + + menu.setItem( + 15, + add1 + ); + + ItemStack add16 = + RSMenuUtils.createMenuItem( + Material.GREEN_WOOL, + "§cAdd 16" + ); + + add16.setAmount( + 16 + ); + + menu.setItem( + 16, + add16 + ); + + ItemStack add64 = + RSMenuUtils.createMenuItem( + Material.GREEN_WOOL, + "§cAdd 64" + ); + + add64.setAmount( + 64 + ); + + menu.setItem( + 17, + add64 + ); + + TransactionVariantBuilder.addVariantButtons( + menu, + warehouseItem + ); + + /* + |-------------------------------------------------------------------------- + | BACK + |-------------------------------------------------------------------------- + */ + + menu.setItem( + 4, + RSMenuUtils.createMenuItem( + Material.OAK_DOOR, + "§eBack" + ) + ); + + player.openInventory( + menu + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/item/TransactionAmountMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/item/TransactionAmountMenuListener.java new file mode 100644 index 0000000..589b529 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/TransactionAmountMenuListener.java @@ -0,0 +1,216 @@ +package com.rsscripting.rswarehouse.item; + +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryMenu; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import com.rsscripting.rswarehouse.session.TransactionSession; +import com.rsscripting.rswarehouse.model.WarehouseItem; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +public class TransactionAmountMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if ( + !(event.getWhoClicked() + instanceof Player player) + ) { + + return; + + } + + if ( + !(event.getInventory() + .getHolder() + instanceof RSMenuHolder holder) + ) { + + return; + + } + + if ( + !holder.getMenuId() + .equals( + "ITEM_ACTION" + ) + ) { + + return; + + } + + event.setCancelled( + true + ); + + + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + TransactionSession itemSession = + session.getItemActionSession(); + + if (itemSession == null) { + + return; + + } + + int amount = + itemSession.getAmount(); + + int itemId = + itemSession.getWarehouseItemId(); + + WarehouseItem warehouseItem = + ItemDAO.getItemById( + itemId + ); + + if (warehouseItem == null) { + + return; + + } + + if ( + TransactionVariantHandler.handle( + player, + event.getSlot(), + event.getCurrentItem(), + warehouseItem + ) + ) { + + return; + + } + + if (event.getSlot() == 4) { + + ItemsMenu.open( + player, + session.getItemsCategoryId(), + session.getItemsCategoryName(), + session.getItemsPage()); + + + return; + } + + ItemStack item = + ItemStackUtils.deserialize( + warehouseItem.serializedItem() + ); + + if (item == null) { + + return; + + } + + long playerHas = + TransactionUtils.getPlayerItemCount( + player, + item + ); + + if (event.getSlot() == 13) { + + if ( + TransactionConfirmHandler.handle( + player, + itemSession, + item, + amount + ) + ) { + + return; + + } + + if (amount == 0) { + + return; + + } + + if ( + TransactionWithdrawHandler.handle( + player, + itemSession, + item, + amount + ) + ) { + + return; + + } + + return; + + } + + long warehouseStock = + warehouseItem.quantity(); + + int inventoryCapacity = + TransactionUtils.getAvailableCapacity( + player, + item + ); + + long maxWithdraw = + Math.min( + warehouseStock, + inventoryCapacity + ); + + Integer newAmount = + TransactionAmountButtonHandler.handle( + event.getSlot(), + amount, + playerHas, + maxWithdraw + ); + + if (newAmount == null) { + + return; + + } + + amount = + newAmount; + + itemSession.setAmount( + amount + ); + + TransactionAmountMenu.open( + player, + itemSession.getWarehouseItemId(), + amount + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/item/TransactionCenterItemBuilder.java b/src/main/java/com/rsscripting/rswarehouse/item/TransactionCenterItemBuilder.java new file mode 100644 index 0000000..9ef1394 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/TransactionCenterItemBuilder.java @@ -0,0 +1,96 @@ +package com.rsscripting.rswarehouse.item; + +import com.rsscripting.rswarehouse.model.WarehouseItem; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.List; + +public class TransactionCenterItemBuilder { + + public static void addCenterItem( + Inventory menu, + Player player, + WarehouseItem warehouseItem + ){ + + if (warehouseItem != null) { + + ItemStack item = + ItemStackUtils.deserialize( + warehouseItem.serializedItem() + ); + + if (item != null) { + + ItemMeta meta = + item.getItemMeta(); + + if (meta != null) { + + long playerHas = + TransactionUtils.getPlayerItemCount( + player, + item + ); + + meta.lore( + List.of( + Component.text( + "In Stock: " + + String.format( + "%,d", + warehouseItem.quantity() + ) + ).color( + NamedTextColor.LIGHT_PURPLE + ), + + Component.text( + "Player Has: " + + String.format( + "%,d", + playerHas + ) + ).color( + NamedTextColor.GREEN + ), + + Component.text( + " " + ).color( + NamedTextColor.YELLOW + ), + + Component.text( + "Click to complete transaction." + ).color( + NamedTextColor.YELLOW + ) + + ) + ); + + item.setItemMeta( + meta + ); + + } + + menu.setItem( + 13, + item + ); + + } + + } + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/item/TransactionConfirmHandler.java b/src/main/java/com/rsscripting/rswarehouse/item/TransactionConfirmHandler.java new file mode 100644 index 0000000..9348538 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/TransactionConfirmHandler.java @@ -0,0 +1,74 @@ +package com.rsscripting.rswarehouse.item; + +import com.rsscripting.rswarehouse.session.TransactionSession; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; + +public class TransactionConfirmHandler { + + public static boolean handle( + Player player, + TransactionSession itemSession, + ItemStack item, + int amount + ) { + + if (amount == 0) { + + return false; + + } + + if (amount > 0) { + + ItemStack depositItem = + item.clone(); + + depositItem.setAmount( + 1 + ); + + if ( + TransactionUtils.removeItems( + player, + depositItem, + amount + ) + ) { + + ItemDAO.addItem( + player.getUniqueId() + .toString(), + player.getName(), + depositItem, + amount + ); + + player.sendMessage( + "§aYou have deposited " + + amount + + " items." + ); + + itemSession.setAmount( + 0 + ); + + TransactionAmountMenu.open( + player, + itemSession.getWarehouseItemId(), + 0 + ); + + } + + return true; + + } + + return false; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/item/TransactionUtils.java b/src/main/java/com/rsscripting/rswarehouse/item/TransactionUtils.java new file mode 100644 index 0000000..ee2338b --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/TransactionUtils.java @@ -0,0 +1,152 @@ +package com.rsscripting.rswarehouse.item; + +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +public class TransactionUtils { + + public static long getPlayerItemCount( + Player player, + ItemStack target + ) { + + long count = 0; + + for (ItemStack item : player.getInventory().getContents()) { + + if (item == null) { + continue; + } + + if ( + item.isSimilar( + target + ) + ) { + + count += item.getAmount(); + + } + + + } + + return count; + + } + + public static int getAvailableCapacity( + Player player, + ItemStack target + ) { + + int capacity = 0; + + int maxStack = + target.getMaxStackSize(); + + for ( + ItemStack item : + player.getInventory() + .getStorageContents() + ) { + + if (item == null) { + + capacity += maxStack; + + continue; + + } + + if ( + item.isSimilar( + target + ) + ) { + + capacity += + maxStack + - item.getAmount(); + + } + + } + + return capacity; + + } + + public static boolean removeItems( + Player player, + ItemStack target, + int amount + ){ + + int remaining = + amount; + + ItemStack[] contents = + player.getInventory() + .getContents(); + + for (int slot = 0; + slot < contents.length; + slot++) { + + ItemStack item = + contents[slot]; + + if (item == null) { + + continue; + + } + + if (!item.isSimilar(target)) { + + continue; + + } + + if ( + item.getAmount() + <= remaining + ) { + + remaining -= + item.getAmount(); + + player.getInventory() + .setItem( + slot, + null + ); + + } + + else { + + item.setAmount( + item.getAmount() + - remaining + ); + + remaining = + 0; + + } + + if (remaining <= 0) { + + return true; + + } + + } + + return false; + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/item/TransactionVariantBuilder.java b/src/main/java/com/rsscripting/rswarehouse/item/TransactionVariantBuilder.java new file mode 100644 index 0000000..a437ebc --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/TransactionVariantBuilder.java @@ -0,0 +1,232 @@ +package com.rsscripting.rswarehouse.item; + +import com.rsscripting.rswarehouse.variants.dao.DamagedVariantsDAO; +import com.rsscripting.rswarehouse.variants.dao.EnchantedVariantsDAO; +import com.rsscripting.rswarehouse.variants.dao.PartiallyFilledVariantsDAO; +import com.rsscripting.rswarehouse.model.WarehouseItem; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import com.rsscripting.rswarehouse.constants.RSKeys; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import org.bukkit.Material; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.Damageable; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.persistence.PersistentDataType; + +public class TransactionVariantBuilder { + + public static void addVariantButtons( + Inventory menu, + WarehouseItem warehouseItem + ) { + + /* + | Enchanted Variants Button + */ + + if ( + warehouseItem != null + && warehouseItem.inventoryId() != null + ) { + + if ( + EnchantedVariantsDAO.hasEnchantedVariants( + warehouseItem.inventoryId() + ) + ) { + + ItemStack enchantedIcon = + ItemStackUtils.deserialize( + warehouseItem.serializedItem() + ); + + if (enchantedIcon != null) { + + ItemMeta meta = + enchantedIcon.getItemMeta(); + + if (meta != null) { + + meta.addEnchant( + Enchantment.UNBREAKING, + 1, + true + ); + + meta.addItemFlags( + ItemFlag.HIDE_ENCHANTS + ); + + enchantedIcon.setItemMeta( + meta + ); + + } + + ItemStack menuIcon = + RSMenuUtils.createMenuItem( + enchantedIcon, + "§eView Enchanted Variants" + ); + + ItemMeta menuMeta = + menuIcon.getItemMeta(); + + menuMeta.getPersistentDataContainer().set( + RSKeys.ENCHANTED_VARIANT_ID, + PersistentDataType.INTEGER, + warehouseItem.inventoryId() + ); + + if (menuMeta != null) { + + menuMeta.addItemFlags( + ItemFlag.HIDE_ATTRIBUTES + ); + + menuIcon.setItemMeta( + menuMeta + ); + + } + + menu.setItem( + 1, + menuIcon + ); + + } + + } + else if ( + PartiallyFilledVariantsDAO.hasPartiallyFilledVariants( + warehouseItem.inventoryId() + ) + ) { + + ItemStack partiallyFilledIcon = + ItemStackUtils.deserialize( + warehouseItem.serializedItem() + ); + + if (partiallyFilledIcon != null) { + + ItemStack menuIcon = + RSMenuUtils.createMenuItem( + partiallyFilledIcon, + "§eView Partially Filled Variants" + ); + + ItemMeta menuMeta = + menuIcon.getItemMeta(); + + menuMeta.getPersistentDataContainer().set( + RSKeys.PARTIALLY_FILLED_VARIANT_ID, + PersistentDataType.INTEGER, + warehouseItem.inventoryId() + ); + + if (menuMeta != null) { + + menuMeta.addItemFlags( + ItemFlag.HIDE_ATTRIBUTES, + ItemFlag.HIDE_ADDITIONAL_TOOLTIP + ); + + menuIcon.setItemMeta( + menuMeta + ); + + } + + menu.setItem( + 2, + menuIcon + ); + + } + + } + + } + + +/* +|-------------------------------------------------------------------------- +| VARIANTS +|-------------------------------------------------------------------------- +*/ + + if ( + warehouseItem != null + && warehouseItem.inventoryId() != null + && DamagedVariantsDAO.hasDamagedVariants( + warehouseItem.inventoryId() + ) + ) { + + ItemStack damagedIcon = + ItemStackUtils.deserialize( + warehouseItem.serializedItem() + ); + + if (damagedIcon == null) { + + damagedIcon = new ItemStack(Material.ANVIL); + + } + + if (damagedIcon.getItemMeta() instanceof Damageable damageable) { + + int maxDurability = damagedIcon.getType().getMaxDurability(); + + damageable.setDamage(maxDurability / 2); + + damagedIcon.setItemMeta(damageable); + + } else { + + damagedIcon = new ItemStack(Material.ANVIL); + + } + + ItemStack menuIcon = + RSMenuUtils.createMenuItem( + damagedIcon, + "§eView Damaged Variants" + ); + + ItemMeta menuMeta = + menuIcon.getItemMeta(); + + if (menuMeta != null) { + + menuMeta.addItemFlags( + ItemFlag.HIDE_ATTRIBUTES + ); + + menuMeta.getPersistentDataContainer().set( + RSKeys.DAMAGED_VARIANT_ID, + PersistentDataType.INTEGER, + warehouseItem.inventoryId() + ); + + menuIcon.setItemMeta( + menuMeta + ); + + } + + menu.setItem( + 0, + menuIcon + ); + + } + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/item/TransactionVariantHandler.java b/src/main/java/com/rsscripting/rswarehouse/item/TransactionVariantHandler.java new file mode 100644 index 0000000..bcef78c --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/TransactionVariantHandler.java @@ -0,0 +1,110 @@ +package com.rsscripting.rswarehouse.item; + +import com.rsscripting.rswarehouse.model.WarehouseItem; +import com.rsscripting.rswarehouse.constants.RSKeys; +import com.rsscripting.rswarehouse.variantsdamaged.DamagedVariantsMenu; +import com.rsscripting.rswarehouse.variantsenchanted.EnchantedVariantsMenu; +import com.rsscripting.rswarehouse.variantspartiallyfilled.PartiallyFilledVariantsMenu; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; + +public class TransactionVariantHandler { + + public static boolean handle( + Player player, + int slot, + ItemStack clicked, + WarehouseItem warehouseItem + ) { + + if ( + clicked == null + || !clicked.hasItemMeta() + ) { + + return false; + + } + + PersistentDataContainer pdc = + clicked.getItemMeta() + .getPersistentDataContainer(); + + if (slot == 0) { + + if ( + !pdc.has( + RSKeys.DAMAGED_VARIANT_ID, + PersistentDataType.INTEGER + ) + ) { + + return false; + + } + + DamagedVariantsMenu.open( + player, + warehouseItem.id(), + warehouseItem.inventoryId() + ); + + return true; + + } + + if (slot == 1) { + + if ( + !pdc.has( + RSKeys.ENCHANTED_VARIANT_ID, + PersistentDataType.INTEGER + ) + ) { + + return false; + + } + + EnchantedVariantsMenu.open( + player, + warehouseItem.id(), + warehouseItem.inventoryId() + ); + + return true; + + } + + if (slot == 2) { + + if ( + !pdc.has( + RSKeys.PARTIALLY_FILLED_VARIANT_ID, + PersistentDataType.INTEGER + ) + ) { + + return false; + + } + + PartiallyFilledVariantsMenu.open( + player, + warehouseItem.id(), + warehouseItem.inventoryId() + ); + + return true; + + } + + return false; + + } + + + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/item/TransactionWithdrawHandler.java b/src/main/java/com/rsscripting/rswarehouse/item/TransactionWithdrawHandler.java new file mode 100644 index 0000000..3c64135 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/TransactionWithdrawHandler.java @@ -0,0 +1,83 @@ +package com.rsscripting.rswarehouse.item; + +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import com.rsscripting.rswarehouse.autodeposit.autodepositdao.AutoDepositDAO; +import com.rsscripting.rswarehouse.session.TransactionSession; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +public class TransactionWithdrawHandler { + + public static boolean handle( + Player player, + TransactionSession itemSession, + ItemStack item, + int amount + ) { + + if (amount >= 0) { + + return false; + + } + + int withdrawAmount = + Math.abs( + amount + ); + + ItemStack withdrawItem = + item.clone(); + + withdrawItem.setAmount( + withdrawAmount + ); + + if ( + AutoDepositDAO.shouldBlockWithdrawal( + player.getUniqueId(), + withdrawItem + ) + ) { + + RSMessageUtils.error( + player, + "Disable Auto Deposit or remove this item from your filter before withdrawing it." + ); + + return true; + + } + + player.getInventory() + .addItem( + withdrawItem + ); + + ItemDAO.removeItem( + withdrawItem, + withdrawAmount + ); + + player.sendMessage( + "§aYou have withdrawn " + + withdrawAmount + + " items." + ); + + itemSession.setAmount( + 0 + ); + + TransactionAmountMenu.open( + player, + itemSession.getWarehouseItemId(), + 0 + ); + + return true; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/item/deleteitem/DeleteConfirmationMenu.java b/src/main/java/com/rsscripting/rswarehouse/item/deleteitem/DeleteConfirmationMenu.java new file mode 100644 index 0000000..9c148a5 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/deleteitem/DeleteConfirmationMenu.java @@ -0,0 +1,98 @@ +package com.rsscripting.rswarehouse.item.deleteitem; + +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; +import com.rsscripting.rswarehouse.model.WarehouseItem; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +public class DeleteConfirmationMenu { + + public static void open( + Player player, + int itemId + ) { + + WarehouseItem warehouseItem = + ItemDAO.getItemById( + itemId + ); + + if (warehouseItem == null) { + + player.sendMessage( + "§cUnable to locate warehouse item." + ); + + return; + + } + + Inventory menu = + Bukkit.createInventory( + new DeleteConfirmationMenuHolder( + itemId + ), + 27, + Component.text( + "Delete Item?" + ).color( + NamedTextColor.RED + ) + ); + + ItemStack filler = + RSMenuUtils.createFillerPane(); + + for (int i = 0; i < 27; i++) { + + menu.setItem( + i, + filler + ); + + } + + menu.setItem( + 11, + RSMenuUtils.createMenuItem( + Material.RED_WOOL, + "§cCancel" + ) + ); + + menu.setItem( + 15, + RSMenuUtils.createMenuItem( + Material.LIME_WOOL, + "§aDelete" + ) + ); + + ItemStack displayItem = + ItemStackUtils.deserialize( + warehouseItem.serializedItem() + ); + + if (displayItem != null) { + + menu.setItem( + 13, + displayItem + ); + + } + + player.openInventory( + menu + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/item/deleteitem/DeleteConfirmationMenuHolder.java b/src/main/java/com/rsscripting/rswarehouse/item/deleteitem/DeleteConfirmationMenuHolder.java new file mode 100644 index 0000000..fe745fa --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/deleteitem/DeleteConfirmationMenuHolder.java @@ -0,0 +1,29 @@ +package com.rsscripting.rswarehouse.item.deleteitem; + +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; + +public class DeleteConfirmationMenuHolder + extends RSMenuHolder { + + private final int itemId; + + public DeleteConfirmationMenuHolder( + int itemId + ) { + + super( + "DELETE_CONFIRMATION" + ); + + this.itemId = + itemId; + + } + + public int getItemId() { + + return itemId; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/item/deleteitem/DeleteConfirmationMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/item/deleteitem/DeleteConfirmationMenuListener.java new file mode 100644 index 0000000..b473653 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/deleteitem/DeleteConfirmationMenuListener.java @@ -0,0 +1,173 @@ +package com.rsscripting.rswarehouse.item.deleteitem; + +import com.rsscripting.rswarehouse.item.options.ItemOptionsMenu; +import com.rsscripting.rswarehouse.inventory.InventoryQuantityDAO; +import com.rsscripting.rswarehouse.references.referencesdao.WarehouseReferenceDAO; +import com.rsscripting.rswarehouse.variants.dao.DamagedVariantsDAO; +import com.rsscripting.rswarehouse.variants.dao.EnchantedVariantsDAO; +import com.rsscripting.rswarehouse.variants.dao.PartiallyFilledVariantsDAO; +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; +import com.rsscripting.rswarehouse.model.WarehouseItem; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; + +public class DeleteConfirmationMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getWhoClicked() + instanceof Player player)) { + + return; + + } + + if (!(event.getInventory().getHolder() + instanceof DeleteConfirmationMenuHolder holder)) { + + return; + + } + + if (!holder.getMenuId().equals( + "DELETE_CONFIRMATION" + )) { + + return; + + } + + event.setCancelled( + true + ); + + if (event.getCurrentItem() == null) { + + return; + + } + + Material material = + event.getCurrentItem().getType(); + + if (material == Material.RED_WOOL) { + + ItemOptionsMenu.open( + player, + holder.getItemId() + ); + + return; + + } + + if (material == Material.LIME_WOOL) { + + WarehouseItem warehouseItem = + ItemDAO.getItemById( + holder.getItemId() + ); + + if (warehouseItem == null) { + + player.sendMessage( + "§cUnable to locate warehouse item." + ); + + return; + + } + + if (warehouseItem.inventoryId() == null) { + + player.sendMessage( + "§cCannot delete subcategories yet." + ); + + return; + + } + + int references = + WarehouseReferenceDAO.countInventoryReferences( + warehouseItem.inventoryId() + ); + + if (references > 1) { + + WarehouseReferenceDAO.deleteItemReference( + warehouseItem.id() + ); + + player.sendMessage( + "§aItem reference deleted." + ); + + player.closeInventory(); + + return; + + } + + if (DamagedVariantsDAO.hasDamagedVariants( + warehouseItem.inventoryId() + )) { + + player.sendMessage( + "§cCannot delete. Inventory contains damaged variants." + ); + + return; + + } + + if (EnchantedVariantsDAO.hasEnchantedVariants( + warehouseItem.inventoryId() + )) { + + player.sendMessage( + "§cCannot delete. Inventory contains enchanted variants." + ); + + return; + + } + + if (PartiallyFilledVariantsDAO.hasPartiallyFilledVariants( + warehouseItem.inventoryId() + )) { + + player.sendMessage( + "§cCannot delete. Inventory contains partially filled variants." + ); + + return; + + } + + WarehouseReferenceDAO.deleteItemReference( + warehouseItem.id() + ); + + InventoryQuantityDAO.deleteInventory( + warehouseItem.inventoryId() + ); + + player.sendMessage( + "§aItem deleted." + ); + + player.closeInventory(); + + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/item/itemdao/ItemDAO.java b/src/main/java/com/rsscripting/rswarehouse/item/itemdao/ItemDAO.java new file mode 100644 index 0000000..14d95a1 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/itemdao/ItemDAO.java @@ -0,0 +1,370 @@ +package com.rsscripting.rswarehouse.item.itemdao; + +import com.rsscripting.rswarehouse.RSWarehouse; +import com.rsscripting.rswarehouse.discovery.discoverydao.DiscoveryDAO; +import com.rsscripting.rswarehouse.inventory.inventorydao.InventoryCreationDAO; +import com.rsscripting.rswarehouse.inventory.inventorydao.InventoryLookupDAO; +import com.rsscripting.rswarehouse.inventory.InventoryQuantityDAO; +import com.rsscripting.rswarehouse.references.referencesdao.WarehouseReferenceDAO; +import com.rsscripting.rswarehouse.database.DatabaseManager; +import com.rsscripting.rswarehouse.model.WarehouseItem; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import org.bukkit.inventory.ItemStack; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; + + +public class ItemDAO { + + public static void addItem( + String discovererUuid, + String discovererName, + ItemStack item, + long quantity, + Integer inventoryId + ) { + + item = ItemStackUtils.normalizeSpecialItems(item); + + String serializedItem = + ItemStackUtils.serialize( + item + ); + + if (serializedItem == null) { + return; + } + + boolean enableUncategorized = + RSWarehouse.getInstance() + .getConfig() + .getBoolean( + "allow-uncategorized-item-creation", + true + ); + + if ( + inventoryId == null + && !enableUncategorized + ) { + + return; + + } + + if (inventoryId != null) { + + long previousQuantity = + InventoryQuantityDAO.getInventoryQuantity( + inventoryId + ); + + InventoryQuantityDAO.updateInventoryQuantity( + inventoryId, + quantity + ); + + if (previousQuantity == 0) { + + DiscoveryDAO.assignDiscovererIfNull( + inventoryId, + discovererUuid, + discovererName + ); + + } + + return; + + } + + inventoryId = + InventoryCreationDAO.createInventoryItem( + item, + quantity, + discovererUuid, + discovererName + ); + + if (inventoryId == -1) { + + return; + + } + + WarehouseReferenceDAO.createWarehouseItemReference( + item, + inventoryId + ); + + } + + public static WarehouseItem getItemById( + int itemId + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT + wi.*, + inv.quantity, + inv.discoverer_uuid, + inv.discoverer_name, + inv.discovered_date + FROM warehouse_items wi + LEFT JOIN warehouse_inventory inv + ON wi.inventory_id = inv.id + WHERE wi.id = ? + """ + ); + + statement.setInt( + 1, + itemId + ); + + ResultSet resultSet = + statement.executeQuery(); + + if (resultSet.next()) { + + return new WarehouseItem( + + resultSet.getInt("id"), + + resultSet.getInt("category_id"), + resultSet.getString("serialized_item"), + + resultSet.getString("default_lore"), + + resultSet.getObject("inventory_id") == null + ? null + : resultSet.getInt("inventory_id"), + + resultSet.getObject("subcategory_id") == null + ? null + : resultSet.getInt("subcategory_id"), + + resultSet.getLong("quantity"), + + resultSet.getString("discoverer_uuid"), + + resultSet.getString("discoverer_name"), + + resultSet.getString("discovered_date"), + + resultSet.getObject("page") == null + ? null + : resultSet.getInt("page"), + + resultSet.getObject("slot") == null + ? null + : resultSet.getInt("slot") + ); + + } + + } catch (Exception e) { + + e.printStackTrace(); + + } + + return null; + + } + + public static List getItemsForCategory( + int categoryId + ) { + + List items = + new ArrayList<>(); + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + SELECT + wi.*, + inv.quantity, + inv.discoverer_uuid, + inv.discoverer_name, + inv.discovered_date + FROM warehouse_items wi + LEFT JOIN warehouse_inventory inv + ON wi.inventory_id = inv.id + WHERE wi.category_id = ? + ORDER BY wi.id + """ + ); + + statement.setInt( + 1, + categoryId + ); + + ResultSet resultSet = + statement.executeQuery(); + + while (resultSet.next()) { + + items.add( + new WarehouseItem( + + resultSet.getInt("id"), + + resultSet.getInt("category_id"), + + resultSet.getString("serialized_item"), + + resultSet.getString("default_lore"), + + resultSet.getObject("inventory_id") == null + ? null + : resultSet.getInt("inventory_id"), + + resultSet.getObject("subcategory_id") == null + ? null + : resultSet.getInt("subcategory_id"), + + resultSet.getLong("quantity"), + + resultSet.getString("discoverer_uuid"), + + resultSet.getString("discoverer_name"), + + resultSet.getString("discovered_date"), + + resultSet.getObject("page") == null + ? null + : resultSet.getInt("page"), + + resultSet.getObject("slot") == null + ? null + : resultSet.getInt("slot") + ) + ); + + } + + } catch (Exception e) { + + e.printStackTrace(); + + } + + return items; + + } + + public static void removeItem( + ItemStack item, + long quantity + ) { + + Integer inventoryId = + InventoryLookupDAO.findInventoryId( + item + ); + + if (inventoryId == null) { + + return; + + } + + InventoryQuantityDAO.removeInventoryQuantity( + inventoryId, + quantity + ); + + } + + public static void addItem( + String discovererUuid, + String discovererName, + ItemStack item, + long quantity + ) { + + addItem( + discovererUuid, + discovererName, + item, + quantity, + InventoryLookupDAO.findInventoryId( + item + ) + ); + + } + + public static boolean categoryHasItems( + int categoryId + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT COUNT(*) + FROM warehouse_items + WHERE category_id = ? + """ + ) + + ) { + + statement.setInt( + 1, + categoryId + ); + + ResultSet resultSet = + statement.executeQuery(); + + if (resultSet.next()) { + + return resultSet.getInt( + 1 + ) > 0; + + } + + } + + catch (Exception exception) { + + exception.printStackTrace(); + + } + + return false; + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/item/options/ItemOptionsMenu.java b/src/main/java/com/rsscripting/rswarehouse/item/options/ItemOptionsMenu.java new file mode 100644 index 0000000..66cf8db --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/options/ItemOptionsMenu.java @@ -0,0 +1,253 @@ +package com.rsscripting.rswarehouse.item.options; + +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; +import com.rsscripting.rswarehouse.model.WarehouseItem; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import com.rsscripting.rswarehouse.references.referencesdao.WarehouseReferenceDAO; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; + +import java.util.List; + +public class ItemOptionsMenu { + + public static void open( + Player player, + int itemId + ) { + + Inventory menu = + Bukkit.createInventory( + new ItemOptionsMenuHolder( + itemId + ), + 36, + Component.text( + "Item Options" + ).color( + NamedTextColor.BLUE + ) + ); + + for (int i = 0; i < menu.getSize(); i++) { + + menu.setItem( + i, + RSMenuUtils.createFillerPane() + ); + + } + + WarehouseItem warehouseItem = + ItemDAO.getItemById( + itemId + ); + + boolean isSubCategory = + warehouseItem != null + && + warehouseItem.subcategoryId() != null; + + menu.setItem( + 4, + RSMenuUtils.createMenuItem( + Material.OAK_DOOR, + "§eBack" + ) + ); + + if (isSubCategory) { + + menu.setItem( + 10, + RSMenuUtils.createMenuItemWithLore( + Material.CRAFTER, + "§7Already A SubCategory", + List.of( + "§7This item is already", + "§7a SubCategory link.", + "", + "§cCannot convert again." + ) + ) + ); + + menu.setItem( + 25, + RSMenuUtils.createMenuItem( + Material.NAME_TAG, + "§eEdit Display Name" + ) + ); + + menu.setItem( + 28, + RSMenuUtils.createMenuItem( + Material.WRITABLE_BOOK, + "§eEdit Lore" + ) + ); + + + } else { + + menu.setItem( + 10, + RSMenuUtils.createMenuItem( + Material.CRAFTER, + "§eConvert To New SubCategory" + ) + ); + + + menu.setItem( + 25, + RSMenuUtils.createMenuItemWithLore( + Material.NAME_TAG, + "§4Not A SubCategory", + List.of( + "§7This option is only", + "§7available for SubCategories." + ) + ) + ); + + menu.setItem( + 28, + RSMenuUtils.createMenuItemWithLore( + Material.WRITABLE_BOOK, + "§4Not A SubCategory", + List.of( + "§7This option is only", + "§7available for SubCategories." + ) + ) + ); + + } + + boolean canDelete = false; + + if (warehouseItem != null && + warehouseItem.subcategoryId() == null) { + + int references = + WarehouseReferenceDAO.countInventoryReferences( + warehouseItem.inventoryId() + ); + + if (references > 1) { + + canDelete = true; + + } else if (warehouseItem.quantity() == 0) { + + canDelete = true; + + } + + } + + menu.setItem( + 12, + RSMenuUtils.createMenuItem( + Material.BOOK, + "§eAssign Page/Slot" + ) + ); + + menu.setItem( + 14, + RSMenuUtils.createMenuItem( + Material.PISTON, + "§eMove to Category" + ) + ); + + menu.setItem( + 16, + RSMenuUtils.createMenuItem( + Material.STICKY_PISTON, + "§eMove to SubCategory" + ) + ); + + if (canDelete) { + + menu.setItem( + 19, + RSMenuUtils.createMenuItemWithLore( + Material.BARRIER, + "§4Delete Item", + List.of( + "§4CAUTION!! CAUTION!! CAUTION!!", + "§7This is irreversible." + ) + ) + ); + + } + else if (isSubCategory) { + + menu.setItem( + 19, + RSMenuUtils.createMenuItemWithLore( + Material.BARRIER, + "§4Delete SubCategory", + List.of( + "§4CAUTION!! CAUTION!! CAUTION!!", + "§7Deletes this SubCategory", + "§7if it contains no items." + ) + ) + ); + + } + else { + + menu.setItem( + 19, + RSMenuUtils.createMenuItemWithLore( + Material.BARRIER, + "§4Cannot Delete Item", + List.of( + "§7This is the last reference.", + "§7Inventory still contains items.", + "", + "§7Remove or move the items", + "§7before deleting this reference." + ) + ) + ); + + } + + menu.setItem( + 21, + RSMenuUtils.createMenuItem( + Material.OAK_SIGN, + "§eCopy to Category" + ) + ); + + + + menu.setItem( + 23, + RSMenuUtils.createMenuItem( + Material.OAK_HANGING_SIGN, + "§eCopy to SubCategory" + ) + ); + + player.openInventory( + menu + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/item/options/ItemOptionsMenuHolder.java b/src/main/java/com/rsscripting/rswarehouse/item/options/ItemOptionsMenuHolder.java new file mode 100644 index 0000000..b73e4df --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/options/ItemOptionsMenuHolder.java @@ -0,0 +1,29 @@ +package com.rsscripting.rswarehouse.item.options; + +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; + +public class ItemOptionsMenuHolder + extends RSMenuHolder { + + private final int itemId; + + public ItemOptionsMenuHolder( + int itemId + ) { + + super( + "ITEM_OPTIONS" + ); + + this.itemId = + itemId; + + } + + public int getItemId() { + + return itemId; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/item/options/ItemOptionsMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/item/options/ItemOptionsMenuListener.java new file mode 100644 index 0000000..4e946b8 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/item/options/ItemOptionsMenuListener.java @@ -0,0 +1,321 @@ +package com.rsscripting.rswarehouse.item.options; + +import com.rsscripting.rswarehouse.category.copytocategory.CopyToCategoryMenu; +import com.rsscripting.rswarehouse.subcategory.copytosubcategory.CopyToSubCategoryMenu; +import com.rsscripting.rswarehouse.item.deleteitem.DeleteConfirmationMenu; +import com.rsscripting.rswarehouse.category.movetocategory.MoveToCategoryMenu; +import com.rsscripting.rswarehouse.subcategory.movetosubcategory.MoveToSubCategoryMenu; +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryCreationSessionManager; +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryEditSession; +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryEditSessionManager; +import com.rsscripting.rswarehouse.subcategory.items.SubCategoryEditDisplayNameMenu; +import com.rsscripting.rswarehouse.subcategory.items.SubCategoryEditLoreMenu; +import com.rsscripting.rswarehouse.subcategory.items.SubCategoryInternalNameMenu; +import com.rsscripting.rswarehouse.admin.adminsessions.PageSlotAssignmentSessionManager; +import com.rsscripting.rswarehouse.admin.assignpageslot.PageNumberMenu; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryDAO; +import com.rsscripting.rswarehouse.subcategory.subcategorydao.SubCategoryDAO; +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; +import com.rsscripting.rswarehouse.references.referencesdao.WarehouseReferenceDAO; +import com.rsscripting.rswarehouse.model.WarehouseCategory; +import com.rsscripting.rswarehouse.model.WarehouseItem; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; + +public class ItemOptionsMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getWhoClicked() + instanceof Player player)) { + + return; + + } + + if (!(event.getInventory() + .getHolder() + instanceof ItemOptionsMenuHolder holder)) { + + return; + + } + + if (!holder.getMenuId().equals( + "ITEM_OPTIONS" + )) { + + return; + + } + + event.setCancelled( + true + ); + + if (event.getSlot() == 4) { + + player.closeInventory(); + + return; + + } + + if (event.getSlot() == 12) { + + PageSlotAssignmentSessionManager.createSession( + player.getUniqueId(), + holder.getItemId() + ); + + PageNumberMenu.open( + player + ); + + return; + + } + + if (event.getSlot() == 10) { + + WarehouseItem warehouseItem = + ItemDAO.getItemById( + holder.getItemId() + ); + + if ( + warehouseItem != null + && + warehouseItem.subcategoryId() != null + ) { + + return; + + } + + SubCategoryCreationSessionManager.createSession( + player.getUniqueId(), + holder.getItemId() + ); + + SubCategoryInternalNameMenu.open( + player + ); + + return; + + } + + if (event.getSlot() == 14) { + + MoveToCategoryMenu.open( + player, + holder.getItemId() + ); + + } + + if (event.getSlot() == 16) { + + MoveToSubCategoryMenu.open( + player, + holder.getItemId(), + holder.getPage() + ); + + return; + + } + + if (event.getSlot() == 19) { + + WarehouseItem warehouseItem = + ItemDAO.getItemById( + holder.getItemId() + ); + + if (warehouseItem == null) { + + return; + + } + + if (warehouseItem.subcategoryId() != null) { + + int references = + SubCategoryDAO.countSubCategoryReferences( + warehouseItem.subcategoryId() + ); + + // More than one link points to this SubCategory. + // Delete only this link item. + if (references > 1) { + + WarehouseReferenceDAO.deleteSubCategoryReference( + warehouseItem.id() + ); + + player.sendMessage( + "§aSubCategory link deleted." + ); + + player.closeInventory(); + + return; + + } + + // Last remaining link. + // Only allow deletion if the SubCategory contains no inventory references. + if (!SubCategoryDAO.isSubCategoryEmpty( + warehouseItem.subcategoryId() + )) { + + player.sendMessage( + "§cThis SubCategory must be empty before it can be deleted." + ); + + return; + + } + + if (SubCategoryDAO.deleteSubCategoryAndLinkItem( + warehouseItem.subcategoryId(), + warehouseItem.id() + )) { + + player.sendMessage( + "§aSubCategory deleted." + ); + + } else { + + player.sendMessage( + "§cUnable to delete SubCategory." + ); + + } + + player.closeInventory(); + + return; + + } + + DeleteConfirmationMenu.open( + player, + holder.getItemId() + ); + + return; + + } + + if (event.getSlot() == 21) { + + CopyToCategoryMenu.open( + player, + holder.getItemId(), + 0 + ); + } + + if (event.getSlot() == 23) { + + CopyToSubCategoryMenu.open( + player, + holder.getItemId(), + 0 + ); + + return; + + } + + if (event.getSlot() == 25) { + + SubCategoryEditSession session = + createEditSession( + player, + holder.getItemId() + ); + + if (session == null) { + + return; + + } + + WarehouseCategory category = + CategoryDAO.getCategoryById( + session.getSubCategoryId() + ); + + SubCategoryEditDisplayNameMenu.open( + player, + category.displayName() + ); + + return; + + } + + if (event.getSlot() == 28) { + + SubCategoryEditSession session = + createEditSession( + player, + holder.getItemId() + ); + + if (session == null) { + + return; + + } + + SubCategoryEditLoreMenu.open( + player + ); + + return; + + } + + } + + private SubCategoryEditSession createEditSession( + Player player, + int itemId + ) { + + WarehouseItem warehouseItem = + ItemDAO.getItemById( + itemId + ); + + if ( + warehouseItem == null + || + warehouseItem.subcategoryId() == null + ) { + + return null; + + } + + return SubCategoryEditSessionManager.createSession( + player.getUniqueId(), + itemId, + warehouseItem.subcategoryId() + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/main/MainMenu.java b/src/main/java/com/rsscripting/rswarehouse/main/MainMenu.java new file mode 100644 index 0000000..ce6cb9b --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/main/MainMenu.java @@ -0,0 +1,98 @@ +package com.rsscripting.rswarehouse.main; + +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.constants.RSConstants; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +public class MainMenu { + + public static final String MENU_TITLE = "Main"; + + public static void open( + Player player, + Block block + ) { + + Inventory menu = + Bukkit.createInventory( + new RSMenuHolder( + "MAIN" + ), + 18, + Component.text( + MENU_TITLE + ).color( + NamedTextColor.BLUE + ) + ); + + /* + |-------------------------------------------------------------------------- + | FILLER + |-------------------------------------------------------------------------- + */ + + ItemStack filler = + RSMenuUtils.createFillerPane(); + + for (int i = 0; i < menu.getSize(); i++) { + + menu.setItem(i, filler); + + } + + /* + |-------------------------------------------------------------------------- + | CONVERT BACK + |-------------------------------------------------------------------------- + */ + + menu.setItem( + 4, + RSMenuUtils.createMenuItem( + Material.COMPOSTER, + "§6Convert Back" + ) + ); + + /* + |-------------------------------------------------------------------------- + | ADMIN + |-------------------------------------------------------------------------- + */ + + if (player.hasPermission( + RSConstants.ADMIN_PERMISSION + )) { + + menu.setItem( + 6, + RSMenuUtils.createMenuItem( + Material.COMMAND_BLOCK, + "§cAdmin" + ) + ); + + } + + menu.setItem( + 11, + RSMenuUtils.createMenuItem( + Material.BOOKSHELF, + "§aOpen Warehouse" + ) + ); + + player.openInventory(menu); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/main/MainMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/main/MainMenuListener.java new file mode 100644 index 0000000..a30e5a4 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/main/MainMenuListener.java @@ -0,0 +1,178 @@ +package com.rsscripting.rswarehouse.main; + +import com.rsscripting.rswarehouse.deposit.dao.WarehouseChestDAO; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryMenu; +import com.rsscripting.rswarehouse.admin.AdminMenu; +import com.rsscripting.rswarehouse.conversion.ConvertMenuListener; +import com.rsscripting.rswarehouse.constants.RSConstants; +import com.rsscripting.rswarehouse.navigation.NavigationManager; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; + +public class MainMenuListener + implements Listener { + + private final ConvertMenuListener + conversionListener; + + public MainMenuListener( + ConvertMenuListener conversionListener + ) { + + this.conversionListener = + conversionListener; + + } + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + Player player = + (Player) event.getWhoClicked(); + + /* + |-------------------------------------------------------------------------- + | CONVERSION MENU + |-------------------------------------------------------------------------- + */ + + if (event.getInventory() + .getHolder() + instanceof RSMenuHolder holder + && holder.getMenuId() + .equals( + "CONVERT" + )) { + + event.setCancelled(true); + + if (event.getCurrentItem() == null) { + return; + } + + if (event.getRawSlot() == 4) { + + Block block = + conversionListener.getSelectedBlock(player); + + if (block == null){ + + player.closeInventory(); + + return; + + } + + RSMessageUtils.success( + player, + "Community Warehouse registered." + ); + + WarehouseChestDAO.registerChest( + block, + player + ); + + NavigationManager.clear(player); + + NavigationManager.openMain(player); + + } + + return; + + } + + /* + |-------------------------------------------------------------------------- + | MAIN MENU + |-------------------------------------------------------------------------- + */ + + if (event.getInventory() + .getHolder() + instanceof RSMenuHolder holder + && holder.getMenuId() + .equals( + "MAIN" + )) { + + event.setCancelled(true); + + if (event.getCurrentItem() == null) { + return; + } + + Block block = + conversionListener.getSelectedBlock(player); + + if (block == null) { + + player.closeInventory(); + + return; + + } + + /* + |-------------------------------------------------------------------------- + | CONVERT BACK + |-------------------------------------------------------------------------- + */ + + if (event.getRawSlot() == 4) { + + conversionListener.convertBack( + player + ); + + return; + + } + + /* + |-------------------------------------------------------------------------- + | ADMIN MENU + |-------------------------------------------------------------------------- + */ + + if (event.getRawSlot() == 6) { + + if (!player.isOp() + || + + !player.hasPermission( + RSConstants.ADMIN_PERMISSION + )) { + + return; + + } + + AdminMenu.open( + player + ); + + } + + if (event.getRawSlot() == 11) { + + NavigationManager.openCategory( + player, + 1 + ); + + } + + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/menuholder/RSMenuHolder.java b/src/main/java/com/rsscripting/rswarehouse/menuholder/RSMenuHolder.java new file mode 100644 index 0000000..a30427d --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/menuholder/RSMenuHolder.java @@ -0,0 +1,57 @@ +package com.rsscripting.rswarehouse.menuholder; + +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.jetbrains.annotations.NotNull; + +public class RSMenuHolder + implements InventoryHolder { + + private final String menuId; + + private int page = 1; + + public RSMenuHolder( + String menuId + ) { + + this.menuId = menuId; + + } + + public String getMenuId() { + + return menuId; + + } + + public int getPage() { + + return page; + + } + + public void setPage( + int page + ) { + + if (page < 1) { + + page = 1; + + } + + this.page = page; + + } + + @Override + public @NotNull Inventory getInventory() { + + throw new UnsupportedOperationException( + "RSMenuHolder does not store an inventory." + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/model/DamagedVariant.java b/src/main/java/com/rsscripting/rswarehouse/model/DamagedVariant.java new file mode 100644 index 0000000..9b52f8f --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/model/DamagedVariant.java @@ -0,0 +1,5 @@ +package com.rsscripting.rswarehouse.model; + +public record DamagedVariant(int id, int parentInventoryId, String serializedItem, long quantity, String lore) { + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/model/EnchantedVariant.java b/src/main/java/com/rsscripting/rswarehouse/model/EnchantedVariant.java new file mode 100644 index 0000000..ba278ad --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/model/EnchantedVariant.java @@ -0,0 +1,11 @@ +package com.rsscripting.rswarehouse.model; + +public record EnchantedVariant( + int id, + int parentInventoryId, + String serializedItem, + long quantity, + String lore +) { + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/model/PartiallyFilledVariant.java b/src/main/java/com/rsscripting/rswarehouse/model/PartiallyFilledVariant.java new file mode 100644 index 0000000..989ec80 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/model/PartiallyFilledVariant.java @@ -0,0 +1,12 @@ +package com.rsscripting.rswarehouse.model; + +public record PartiallyFilledVariant( + + int id, + int parentInventoryId, + String serializedItem, + long quantity, + String lore + +) { +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/model/WarehouseCategory.java b/src/main/java/com/rsscripting/rswarehouse/model/WarehouseCategory.java new file mode 100644 index 0000000..b213e3b --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/model/WarehouseCategory.java @@ -0,0 +1,15 @@ +package com.rsscripting.rswarehouse.model; + +public record WarehouseCategory( + int id, + Integer parentCategoryId, + String internalName, + String displayName, + String material, + String lore, + int displayOrder, + int page, + int slot +) { + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/model/WarehouseItem.java b/src/main/java/com/rsscripting/rswarehouse/model/WarehouseItem.java new file mode 100644 index 0000000..6e991bf --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/model/WarehouseItem.java @@ -0,0 +1,30 @@ +package com.rsscripting.rswarehouse.model; + +public record WarehouseItem( + + int id, + + int categoryId, + + String serializedItem, + + String defaultLore, + + Integer inventoryId, + + Integer subcategoryId, + + long quantity, + + String discovererUuid, + + String discovererName, + + String discoveredDate, + + Integer page, + + Integer slot + +) { +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/model/WarehouseSubCategory.java b/src/main/java/com/rsscripting/rswarehouse/model/WarehouseSubCategory.java new file mode 100644 index 0000000..8c6d372 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/model/WarehouseSubCategory.java @@ -0,0 +1,15 @@ +package com.rsscripting.rswarehouse.model; + +public record WarehouseSubCategory( + + int id, + int categoryId, + String name, + String material, + String lore, + int displayOrder, + int page, + int slot + +) { +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/navigation/NavigationHistory.java b/src/main/java/com/rsscripting/rswarehouse/navigation/NavigationHistory.java new file mode 100644 index 0000000..b97690c --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/navigation/NavigationHistory.java @@ -0,0 +1,71 @@ +package com.rsscripting.rswarehouse.navigation; + +import org.bukkit.entity.Player; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public final class NavigationHistory { + + private static final int MAX_HISTORY = 5; + + private static final Map> HISTORY = new HashMap<>(); + + private NavigationHistory() {} + + public static void push(Player player, NavigationLocation location) { + + Deque history = + HISTORY.computeIfAbsent(player.getUniqueId(), k -> new ArrayDeque<>()); + + if (!history.isEmpty() && history.peekLast().equals(location)) { + return; + } + + history.addLast(location); + + while (history.size() > MAX_HISTORY) { + history.removeFirst(); + } + } + + public static NavigationLocation pop(Player player) { + + Deque history = HISTORY.get(player.getUniqueId()); + + if (history == null || history.isEmpty()) { + return null; + } + + NavigationLocation location = history.removeLast(); + + return location; + } + + public static NavigationLocation peek(Player player) { + + Deque history = HISTORY.get(player.getUniqueId()); + + if (history == null || history.isEmpty()) { + return null; + } + + NavigationLocation location = history.peekLast(); + + return location; + } + + public static void clear(Player player) { + HISTORY.remove(player.getUniqueId()); + } + + public static int size(Player player) { + + Deque history = HISTORY.get(player.getUniqueId()); + + return history == null ? 0 : history.size(); + } +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/navigation/NavigationLocation.java b/src/main/java/com/rsscripting/rswarehouse/navigation/NavigationLocation.java new file mode 100644 index 0000000..599fd4a --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/navigation/NavigationLocation.java @@ -0,0 +1,90 @@ +package com.rsscripting.rswarehouse.navigation; + +import org.bukkit.Material; + +import java.util.Objects; + +public class NavigationLocation { + + private final NavigationType type; + private final Integer categoryId; + private final String categoryName; + private final int page; + private final Material material; + + public NavigationLocation( + NavigationType type, + Integer categoryId, + String categoryName, + int page, + Material material) { + + this.type = type; + this.categoryId = categoryId; + this.categoryName = categoryName; + this.page = page; + this.material = material; + } + + public NavigationType getType() { + return type; + } + + public Integer getCategoryId() { + return categoryId; + } + + public String getCategoryName() { + return categoryName; + } + + public Integer getPage() { + return page; + } + + public Material getMaterial() { + return material; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof NavigationLocation other)) return false; + + return type == other.type && + Objects.equals(categoryId, other.categoryId) && + Objects.equals(categoryName, other.categoryName) && + Objects.equals(page, other.page) && + material == other.material; + } + + @Override + public int hashCode() { + return Objects.hash( + type, + categoryId, + categoryName, + page, + material); + } + + @Override + public String toString() { + + return switch (type) { + + case MAIN -> + "MAIN"; + + case CATEGORY -> + "CATEGORY(page=" + page + ")"; + + case ITEMS -> + "ITEMS(categoryId=" + categoryId + + ", name=" + categoryName + + ", page=" + page + ")"; + + }; + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/navigation/NavigationManager.java b/src/main/java/com/rsscripting/rswarehouse/navigation/NavigationManager.java new file mode 100644 index 0000000..4310b1a --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/navigation/NavigationManager.java @@ -0,0 +1,150 @@ +package com.rsscripting.rswarehouse.navigation; + +import com.rsscripting.rswarehouse.category.categorymenu.CategoryMenu; +import com.rsscripting.rswarehouse.item.ItemsMenu; +import com.rsscripting.rswarehouse.main.MainMenu; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import org.bukkit.entity.Player; + +public final class NavigationManager { + + private NavigationManager() { + } + + public static void openMain(Player player) { + openMain(player, true); + } + + private static void openMain( + Player player, + boolean addToHistory) { + + if (addToHistory) { + + NavigationHistory.push(player, + new NavigationLocation( + NavigationType.MAIN, + null, + null, + 1, + null)); + } + + MainMenu.open( + player, + GuiSessionManager + .getSession(player) + .getSelectedBlock()); + } + + public static void openCategory( + Player player, + int page) { + + openCategory(player, page, true); + } + + private static void openCategory( + Player player, + int page, + boolean addToHistory) { + + if (addToHistory) { + + NavigationHistory.push(player, + new NavigationLocation( + NavigationType.CATEGORY, + null, + null, + page, + null)); + } + + CategoryMenu.open( + player, + page); + } + + public static void openItems( + Player player, + int categoryId, + String categoryName, + int page) { + + openItems( + player, + categoryId, + categoryName, + page, + true); + } + + private static void openItems( + Player player, + int categoryId, + String categoryName, + int page, + boolean addToHistory) { + + if (addToHistory) { + + NavigationHistory.push(player, + new NavigationLocation( + NavigationType.ITEMS, + categoryId, + categoryName, + page, + null)); + } + + ItemsMenu.open( + player, + categoryId, + categoryName, + page); + } + + public static void back(Player player) { + + // Remove the current page. + NavigationHistory.pop(player); + + // Get the previous page. + NavigationLocation previous = + NavigationHistory.peek(player); + + if (previous == null) { + return; + } + + switch (previous.getType()) { + + case MAIN -> + openMain( + player, + false); + + case CATEGORY -> + openCategory( + player, + previous.getPage(), + false); + + case ITEMS -> + openItems( + player, + previous.getCategoryId(), + previous.getCategoryName(), + previous.getPage(), + false); + } + + } + + public static void clear(Player player) { + + NavigationHistory.clear(player); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/navigation/NavigationType.java b/src/main/java/com/rsscripting/rswarehouse/navigation/NavigationType.java new file mode 100644 index 0000000..dc4a072 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/navigation/NavigationType.java @@ -0,0 +1,9 @@ +package com.rsscripting.rswarehouse.navigation; + +public enum NavigationType { + + MAIN, + CATEGORY, + ITEMS + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/otherlisteners/RSUpdateNotificationListener.java b/src/main/java/com/rsscripting/rswarehouse/otherlisteners/RSUpdateNotificationListener.java new file mode 100644 index 0000000..d4e5288 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/otherlisteners/RSUpdateNotificationListener.java @@ -0,0 +1,53 @@ +package com.rsscripting.rswarehouse.otherlisteners; + +import com.rsscripting.rswarehouse.updatechecker.GitHubUpdateChecker; +import com.rsscripting.rswarehouse.constants.RSConstants; +import com.rsscripting.rswarehouse.utils.VersionUtils; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; + +public class RSUpdateNotificationListener implements Listener { + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + + Player player = + event.getPlayer(); + + if (!player.isOp()) { + + return; + + } + + if (!GitHubUpdateChecker.isUpdateAvailable()) { + + return; + + } + + Bukkit.getScheduler().runTaskLater( + + org.bukkit.plugin.java.JavaPlugin + .getProvidingPlugin(getClass()), + + () -> player.sendMessage( + + RSConstants.PREFIX + + "Update available! Current: " + + VersionUtils.getVersion() + + " Latest: " + + GitHubUpdateChecker.getLatestVersion() + + ), + + 40L + + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/otherlisteners/WarehouseChestBreakListener.java b/src/main/java/com/rsscripting/rswarehouse/otherlisteners/WarehouseChestBreakListener.java new file mode 100644 index 0000000..a04d4d8 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/otherlisteners/WarehouseChestBreakListener.java @@ -0,0 +1,78 @@ +package com.rsscripting.rswarehouse.otherlisteners; + +import com.rsscripting.rswarehouse.deposit.dao.VerifyIsChestDAO; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.block.Chest; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.block.DoubleChest; + +public class WarehouseChestBreakListener + implements Listener { + + @EventHandler + public void onBlockBreak( + BlockBreakEvent event + ) { + + Player player = + event.getPlayer(); + + boolean warehouseChest = + VerifyIsChestDAO.isWarehouseChest( + event.getBlock() + ); + + if (!warehouseChest + && event.getBlock().getState() + instanceof Chest chest) { + + InventoryHolder holder = + chest.getInventory() + .getHolder(); + + if (holder instanceof DoubleChest doubleChest) { + + if (doubleChest.getLeftSide() + instanceof Chest leftChest + && VerifyIsChestDAO.isWarehouseChest( + leftChest.getBlock() + )) { + + warehouseChest = true; + + } + + if (doubleChest.getRightSide() + instanceof Chest rightChest + && VerifyIsChestDAO.isWarehouseChest( + rightChest.getBlock() + )) { + + warehouseChest = true; + + } + + } + + } + + if (warehouseChest) { + + RSMessageUtils.error( + player, + "Convert the warehouse back before breaking it." + ); + + event.setCancelled( + true + ); + + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/placement/0 b/src/main/java/com/rsscripting/rswarehouse/placement/0 new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/rsscripting/rswarehouse/placement/placementdao/ItemPlacementDAO.java b/src/main/java/com/rsscripting/rswarehouse/placement/placementdao/ItemPlacementDAO.java new file mode 100644 index 0000000..b76b60a --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/placement/placementdao/ItemPlacementDAO.java @@ -0,0 +1,335 @@ +package com.rsscripting.rswarehouse.placement.placementdao; + +import com.rsscripting.rswarehouse.database.DatabaseManager; +import com.rsscripting.rswarehouse.model.WarehouseItem; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import static com.rsscripting.rswarehouse.item.itemdao.ItemDAO.getItemById; + +public class ItemPlacementDAO { + + public static void copyItemToCategory( + int itemId, + int categoryId + ) { + + String sql = """ + INSERT INTO warehouse_items ( + category_id, + serialized_item, + default_lore, + inventory_id, + subcategory_id, + created_at, + page, + slot + ) + SELECT + ?, + serialized_item, + default_lore, + inventory_id, + subcategory_id, + created_at, + NULL, + NULL + FROM warehouse_items + WHERE id = ? + """; + + try ( + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + sql + ) + ) { + + statement.setInt( + 1, + categoryId + ); + + statement.setInt( + 2, + itemId + ); + + statement.executeUpdate(); + + } + catch (SQLException e) { + + e.printStackTrace(); + + } + + } + + public static void clearPageSlot( + int categoryId, + int page, + int slot + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + + UPDATE warehouse_items + SET + page = NULL, + slot = NULL + WHERE + category_id = ? + AND + page = ? + AND + slot = ? + """ + ) + + ) { + + statement.setInt(1, categoryId); + statement.setInt(2, page); + statement.setInt(3, slot); + + statement.executeUpdate(); + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + } + + public static void assignPageSlot( + int itemId, + int page, + int slot + ) { + + WarehouseItem item = + getItemById( + itemId + ); + + if (item != null) { + + clearPageSlot( + item.categoryId(), + page, + slot + ); + + } + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + UPDATE warehouse_items + SET + page = ?, + slot = ? + WHERE + id = ? + """ + ) + + ) { + + statement.setInt(1, page); + statement.setInt(2, slot); + statement.setInt(3, itemId); + + statement.executeUpdate(); + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + } + + public static void moveItemToCategory( + int itemId, + int categoryId + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + UPDATE warehouse_items + SET + category_id = ?, + page = NULL, + slot = NULL + WHERE id = ? + """ + ); + + statement.setInt( + 1, + categoryId + ); + + statement.setInt( + 2, + itemId + ); + + statement.executeUpdate(); + + } catch (Exception e) { + + e.printStackTrace(); + + } + + } + + public static void cloneItemToSubCategory( + int itemId, + int subCategoryId + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + INSERT INTO warehouse_items ( + category_id, + serialized_item, + default_lore, + inventory_id, + subcategory_id, + created_at, + page, + slot + ) + SELECT + ?, + serialized_item, + default_lore, + inventory_id, + NULL, + created_at, + NULL, + NULL + FROM warehouse_items + WHERE id = ? + """ + ) + + ) { + + statement.setInt( + 1, + subCategoryId + ); + + statement.setInt( + 2, + itemId + ); + + statement.executeUpdate(); + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + } + + public static void convertItemToSubCategoryLink( + int itemId, + int subCategoryId, + String lore + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + + UPDATE warehouse_items + SET + inventory_id = NULL, + subcategory_id = ?, + default_lore = ? + WHERE id = ? + """ + ) + + ) { + + statement.setInt( + 1, + subCategoryId + ); + + statement.setString( + 2, + lore + ); + + statement.setInt( + 3, + itemId + ); + + statement.executeUpdate(); + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/references/0 b/src/main/java/com/rsscripting/rswarehouse/references/0 new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/rsscripting/rswarehouse/references/referencesdao/WarehouseReferenceDAO.java b/src/main/java/com/rsscripting/rswarehouse/references/referencesdao/WarehouseReferenceDAO.java new file mode 100644 index 0000000..a063324 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/references/referencesdao/WarehouseReferenceDAO.java @@ -0,0 +1,232 @@ +package com.rsscripting.rswarehouse.references.referencesdao; + +import com.rsscripting.rswarehouse.database.DatabaseManager; +import com.rsscripting.rswarehouse.model.WarehouseItem; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import org.bukkit.Bukkit; +import org.bukkit.inventory.ItemStack; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import static com.rsscripting.rswarehouse.item.itemdao.ItemDAO.getItemById; + +public class WarehouseReferenceDAO { + + public static int countInventoryReferences( + int inventoryId + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT COUNT(*) + FROM warehouse_items + WHERE inventory_id = ? + """ + ) + + ) { + + statement.setInt( + 1, + inventoryId + ); + + ResultSet resultSet = + statement.executeQuery(); + + if (resultSet.next()) { + + return resultSet.getInt( + 1 + ); + + } + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + return 0; + + } + + public static boolean deleteItemReference( + int itemId + ) { + + WarehouseItem warehouseItem = + getItemById( + itemId + ); + + if ( + warehouseItem == null + || + warehouseItem.subcategoryId() != null + ) { + + return false; + + } + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + DELETE + FROM warehouse_items + WHERE id = ? + """ + ) + + ) { + + statement.setInt( + 1, + itemId + ); + + return statement.executeUpdate() > 0; + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + return false; + + } + + public static void createWarehouseItemReference( + ItemStack item, + int inventoryId + ) { + + String serializedItem = + ItemStackUtils.serialize( + item + ); + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + INSERT INTO warehouse_items ( + category_id, + serialized_item, + inventory_id, + default_lore, + created_at + ) + VALUES (?, ?, ?, ?, ?) + + """ + ); + + statement.setInt( + 1, + 1 + ); + + statement.setString( + 2, + serializedItem + ); + + statement.setInt( + 3, + inventoryId + ); + + statement.setString( + 4, + null + ); + + statement.setString( + 5, + String.valueOf( + System.currentTimeMillis() + ) + ); + + statement.executeUpdate(); + + } catch (Exception e) { + + Bukkit.getLogger().severe( + "[RS-Warehouse] Failed creating warehouse_items reference." + ); + + e.printStackTrace(); + + } + + } + + public static boolean deleteSubCategoryReference( + int itemId + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + DELETE + FROM warehouse_items + WHERE id = ? + """ + ) + + ) { + + statement.setInt( + 1, + itemId + ); + + return statement.executeUpdate() > 0; + + } + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + return false; + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/registration/ListenerRegistrar.java b/src/main/java/com/rsscripting/rswarehouse/registration/ListenerRegistrar.java new file mode 100644 index 0000000..71df706 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/registration/ListenerRegistrar.java @@ -0,0 +1,26 @@ +package com.rsscripting.rswarehouse.registration; + +import com.rsscripting.rswarehouse.RSWarehouse; +import org.bukkit.event.Listener; + +public final class ListenerRegistrar { + + private ListenerRegistrar() { + + } + + public static void register( + RSWarehouse plugin, + Listener listener + ) { + + plugin.getServer() + .getPluginManager() + .registerEvents( + listener, + plugin + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/registration/ListenerRegistration.java b/src/main/java/com/rsscripting/rswarehouse/registration/ListenerRegistration.java new file mode 100644 index 0000000..6124496 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/registration/ListenerRegistration.java @@ -0,0 +1,279 @@ +package com.rsscripting.rswarehouse.registration; + +import com.rsscripting.rswarehouse.RSWarehouse; +import com.rsscripting.rswarehouse.category.categorycreation.*; +import com.rsscripting.rswarehouse.category.categoryedit.CategoryEditDisplayNameMenuListener; +import com.rsscripting.rswarehouse.category.categoryedit.CategoryEditLoreMenuChatListener; +import com.rsscripting.rswarehouse.category.categoryedit.CategoryEditLoreMenuListener; +import com.rsscripting.rswarehouse.category.categoryedit.CategoryEditMaterialMenuListener; +import com.rsscripting.rswarehouse.subcategory.items.*; +import com.rsscripting.rswarehouse.admin.AdminMenuListener; +import com.rsscripting.rswarehouse.admin.assignpageslot.CategoryPageNumberMenuListener; +import com.rsscripting.rswarehouse.admin.assignpageslot.CategorySlotNumberMenuListener; +import com.rsscripting.rswarehouse.admin.assignpageslot.PageNumberMenuListener; +import com.rsscripting.rswarehouse.admin.assignpageslot.SlotNumberMenuListener; +import com.rsscripting.rswarehouse.category.categoryoptions.CategoryOptionsMenuListener; +import com.rsscripting.rswarehouse.category.copytocategory.CopyToCategoryMenuListener; +import com.rsscripting.rswarehouse.subcategory.copytosubcategory.CopyToSubCategoryMenuListener; +import com.rsscripting.rswarehouse.item.deleteitem.DeleteConfirmationMenuListener; +import com.rsscripting.rswarehouse.item.options.ItemOptionsMenuListener; +import com.rsscripting.rswarehouse.category.movetocategory.MoveToCategoryMenuListener; +import com.rsscripting.rswarehouse.subcategory.movetosubcategory.MoveToSubCategoryMenuListener; +import com.rsscripting.rswarehouse.deposit.WarehouseCloseListener; +import com.rsscripting.rswarehouse.conversion.ConvertMenuListener; +import com.rsscripting.rswarehouse.autodeposit.AutoDepositMenuListener; +import com.rsscripting.rswarehouse.autodeposit.AutoDepositPickupListener; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryMenuListener; +import com.rsscripting.rswarehouse.variantsdamaged.DamagedVariantsMenuListener; +import com.rsscripting.rswarehouse.variantsdamaged.DamagedVariantsTransactionMenuListener; +import com.rsscripting.rswarehouse.variantsenchanted.EnchantedVariantsMenuListener; +import com.rsscripting.rswarehouse.variantsenchanted.EnchantedVariantsTransactionMenuListener; +import com.rsscripting.rswarehouse.item.ItemsMenuListener; +import com.rsscripting.rswarehouse.item.TransactionAmountMenuListener; +import com.rsscripting.rswarehouse.main.MainMenuListener; +import com.rsscripting.rswarehouse.otherlisteners.RSUpdateNotificationListener; +import com.rsscripting.rswarehouse.otherlisteners.WarehouseChestBreakListener; +import com.rsscripting.rswarehouse.variantspartiallyfilled.PartiallyFilledVariantsMenuListener; +import com.rsscripting.rswarehouse.variantspartiallyfilled.PartiallyFilledVariantsTransactionMenuListener; + +public final class ListenerRegistration { + + private ListenerRegistration() { + + } + + public static void registerAll( + RSWarehouse plugin + ) { + + ConvertMenuListener conversionListener = + new ConvertMenuListener(); + + ListenerRegistrar.register( + plugin, + conversionListener + ); + + ListenerRegistrar.register( + plugin, + new MainMenuListener( + conversionListener + ) + ); + + ListenerRegistrar.register( + plugin, + new SubCategoryDisplayNameMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new CategoryEditLoreMenuChatListener() + ); + + ListenerRegistrar.register( + plugin, + new CategoryEditLoreMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new CategoryEditDisplayNameMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new CategoryEditMaterialMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new SubCategoryInternalNameMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new SubCategoryLoreChatListener() + ); + + ListenerRegistrar.register( + plugin, + new SubCategoryLoreMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new MoveToSubCategoryMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new RSUpdateNotificationListener() + ); + + ListenerRegistrar.register( + plugin, + new SubCategoryEditDisplayNameMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new SubCategoryEditLoreMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new SubCategoryEditLoreChatListener() + ); + + ListenerRegistrar.register( + plugin, + new DeleteConfirmationMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new ItemOptionsMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new AdminMenuListener( + conversionListener + ) + ); + + ListenerRegistrar.register( + plugin, + new CategoryLoreMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new EnchantedVariantsMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new EnchantedVariantsTransactionMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new PartiallyFilledVariantsTransactionMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new CategoryLoreChatListener() + ); + + ListenerRegistrar.register( + plugin, + new MoveToCategoryMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new AutoDepositMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new AutoDepositPickupListener() + ); + + ListenerRegistrar.register( + plugin, + new WarehouseChestBreakListener() + ); + + ListenerRegistrar.register( + plugin, + new WarehouseCloseListener() + ); + + ListenerRegistrar.register( + plugin, + new PartiallyFilledVariantsMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new CategoryNameMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new CategoryDisplayNameMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new CategoryMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new CategoryMaterialPickerMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new ItemsMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new DamagedVariantsMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new DamagedVariantsTransactionMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new TransactionAmountMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new PageNumberMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new SlotNumberMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new CopyToSubCategoryMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new CopyToCategoryMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new CategoryOptionsMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new CategoryPageNumberMenuListener() + ); + + ListenerRegistrar.register( + plugin, + new CategorySlotNumberMenuListener() + ); + + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/session/CategoryCreationSession.java b/src/main/java/com/rsscripting/rswarehouse/session/CategoryCreationSession.java new file mode 100644 index 0000000..c6d441a --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/session/CategoryCreationSession.java @@ -0,0 +1,160 @@ +package com.rsscripting.rswarehouse.session; + +public class CategoryCreationSession { + + private boolean categoryInternalNameMenuOpen; + + private boolean categoryDisplayNameMenuOpen; + + private String pendingCategoryInternalName; + + private String pendingCategoryDisplayName; + + private String pendingCategoryMaterial; + + private final String[] pendingCategoryLore = + new String[5]; + + private int pendingCategoryLoreSlot = -1; + + private long pendingCategoryLoreExpiration; + + public boolean isCategoryInternalNameMenuOpen() { + + return categoryInternalNameMenuOpen; + + } + + public void setCategoryInternalNameMenuOpen( + boolean categoryInternalNameMenuOpen + ) { + + this.categoryInternalNameMenuOpen = + categoryInternalNameMenuOpen; + + } + + public boolean isCategoryDisplayNameMenuOpen() { + + return categoryDisplayNameMenuOpen; + + } + + public void setCategoryDisplayNameMenuOpen( + boolean categoryDisplayNameMenuOpen + ) { + + this.categoryDisplayNameMenuOpen = + categoryDisplayNameMenuOpen; + + } + + public String getPendingCategoryInternalName() { + + return pendingCategoryInternalName; + + } + + public void setPendingCategoryInternalName( + String pendingCategoryInternalName + ) { + + this.pendingCategoryInternalName = + pendingCategoryInternalName; + + } + + public String getPendingCategoryDisplayName() { + + return pendingCategoryDisplayName; + + } + + public void setPendingCategoryDisplayName( + String pendingCategoryDisplayName + ) { + + this.pendingCategoryDisplayName = + pendingCategoryDisplayName; + + } + + public String getPendingCategoryMaterial() { + + return pendingCategoryMaterial; + + } + + public void setPendingCategoryMaterial( + String pendingCategoryMaterial + ) { + + this.pendingCategoryMaterial = + pendingCategoryMaterial; + + } + + public String getPendingCategoryLore( + int index + ) { + + return pendingCategoryLore[index]; + + } + + public void setPendingCategoryLore( + int index, + String value + ) { + + pendingCategoryLore[index] = + value; + + } + + public void clearPendingCategoryLore() { + + for ( + int i = 0; + i < pendingCategoryLore.length; + i++ + ) { + + pendingCategoryLore[i] = + null; + + } + + } + + public int getPendingCategoryLoreSlot() { + + return pendingCategoryLoreSlot; + + } + + public void setPendingCategoryLoreSlot( + int pendingCategoryLoreSlot + ) { + + this.pendingCategoryLoreSlot = + pendingCategoryLoreSlot; + + } + + public long getPendingCategoryLoreExpiration() { + + return pendingCategoryLoreExpiration; + + } + + public void setPendingCategoryLoreExpiration( + long pendingCategoryLoreExpiration + ) { + + this.pendingCategoryLoreExpiration = + pendingCategoryLoreExpiration; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/session/GuiSession.java b/src/main/java/com/rsscripting/rswarehouse/session/GuiSession.java new file mode 100644 index 0000000..00e59a2 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/session/GuiSession.java @@ -0,0 +1,504 @@ +package com.rsscripting.rswarehouse.session; + +import org.bukkit.block.Block; + +import java.util.UUID; + +public class GuiSession { + + /* +|-------------------------------------------------------------------------- +| Player Session +|-------------------------------------------------------------------------- +*/ + + private final UUID playerUuid; + + private Block selectedBlock; + + public GuiSession( + UUID playerUuid + ) { + + this.playerUuid = + playerUuid; + + } + +/* +|-------------------------------------------------------------------------- +| Category Creation +|-------------------------------------------------------------------------- +*/ + + private final CategoryCreationSession + categoryCreationSession = + new CategoryCreationSession(); + + private int autoDepositPage; + + private int materialPickerPage; + +/* +|-------------------------------------------------------------------------- +| SubCategory Creation +|-------------------------------------------------------------------------- +*/ + + private final SubCategoryCreationSession + subCategoryCreationSession = + new SubCategoryCreationSession(); + + private final ItemBrowserSession + itemBrowserSession = + new ItemBrowserSession(); + +/* +|-------------------------------------------------------------------------- +| Item Browser +|-------------------------------------------------------------------------- +*/ + + public int getItemsCategoryId() { + + return itemBrowserSession + .getItemsCategoryId(); + + } + + public void setItemsCategoryId( + int itemsCategoryId + ) { + + itemBrowserSession + .setItemsCategoryId( + itemsCategoryId + ); + + } + + public String getItemsCategoryName() { + + return itemBrowserSession + .getItemsCategoryName(); + + } + + public void setItemsCategoryName( + String itemsCategoryName + ) { + + itemBrowserSession + .setItemsCategoryName( + itemsCategoryName + ); + + } + + public int getItemsPage() { + + return itemBrowserSession + .getItemsPage(); + + } + + public void setItemsPage( + int itemsPage + ) { + + itemBrowserSession + .setItemsPage( + itemsPage + ); + + } + + private TransactionSession transactionSession; + +/* +|-------------------------------------------------------------------------- +| Transactions +|-------------------------------------------------------------------------- +*/ + + public TransactionSession getItemActionSession() { + + return transactionSession; + + } + + public void setItemActionSession( + TransactionSession transactionSession + ) { + + this.transactionSession = + transactionSession; + + } + +/* +|-------------------------------------------------------------------------- +| Player Session +|-------------------------------------------------------------------------- +*/ + + public UUID getPlayerUuid() { + + return playerUuid; + + } + + public Block getSelectedBlock() { + + return selectedBlock; + + } + + public void setSelectedBlock( + Block selectedBlock + ) { + + this.selectedBlock = + selectedBlock; + + } + +/* +|-------------------------------------------------------------------------- +| Category Creation +|-------------------------------------------------------------------------- +*/ + + public boolean isCategoryInternalNameMenuOpen() { + + return categoryCreationSession + .isCategoryInternalNameMenuOpen(); + + } + + public void setCategoryInternalNameMenuOpen( + boolean categoryInternalNameMenuOpen + ) { + + categoryCreationSession + .setCategoryInternalNameMenuOpen( + categoryInternalNameMenuOpen + ); + + } + + public boolean isCategoryDisplayNameMenuOpen() { + + return categoryCreationSession + .isCategoryDisplayNameMenuOpen(); + + } + + public void setCategoryDisplayNameMenuOpen( + boolean categoryDisplayNameMenuOpen + ) { + + categoryCreationSession + .setCategoryDisplayNameMenuOpen( + categoryDisplayNameMenuOpen + ); + + } + + public String getPendingCategoryInternalName() { + + return categoryCreationSession + .getPendingCategoryInternalName(); + + } + + public void setPendingCategoryInternalName( + String pendingCategoryInternalName + ) { + + categoryCreationSession + .setPendingCategoryInternalName( + pendingCategoryInternalName + ); + + } + + public String getPendingCategoryDisplayName() { + + return categoryCreationSession + .getPendingCategoryDisplayName(); + + } + + public void setPendingCategoryDisplayName( + String pendingCategoryDisplayName + ) { + + categoryCreationSession + .setPendingCategoryDisplayName( + pendingCategoryDisplayName + ); + + } + + public String getPendingCategoryMaterial() { + + return categoryCreationSession + .getPendingCategoryMaterial(); + + } + + public void setPendingCategoryMaterial( + String pendingCategoryMaterial + ) { + + categoryCreationSession + .setPendingCategoryMaterial( + pendingCategoryMaterial + ); + + } + + public String getPendingCategoryLore( + int index + ) { + + return categoryCreationSession + .getPendingCategoryLore( + index + ); + + } + + public void setPendingCategoryLore( + int index, + String value + ) { + + categoryCreationSession + .setPendingCategoryLore( + index, + value + ); + + } + + public void clearPendingCategoryLore() { + + categoryCreationSession + .clearPendingCategoryLore(); + + } + + public int getPendingCategoryLoreSlot() { + + return categoryCreationSession + .getPendingCategoryLoreSlot(); + + } + + public void setPendingCategoryLoreSlot( + int pendingCategoryLoreSlot + ) { + + categoryCreationSession + .setPendingCategoryLoreSlot( + pendingCategoryLoreSlot + ); + + } + + public long getPendingCategoryLoreExpiration() { + + return categoryCreationSession + .getPendingCategoryLoreExpiration(); + + } + + public void setPendingCategoryLoreExpiration( + long pendingCategoryLoreExpiration + ) { + + categoryCreationSession + .setPendingCategoryLoreExpiration( + pendingCategoryLoreExpiration + ); + + } + + public int getMaterialPickerPage() { + + return materialPickerPage; + + } + + public void setMaterialPickerPage( + int materialPickerPage + ) { + + this.materialPickerPage = + materialPickerPage; + + } + + /* +|-------------------------------------------------------------------------- +| SubCategory Creation +|-------------------------------------------------------------------------- +*/ + + public boolean isSubCategoryNameMenuOpen() { + + return subCategoryCreationSession + .isSubCategoryNameMenuOpen(); + + } + + public void setSubCategoryNameMenuOpen( + boolean subCategoryNameMenuOpen + ) { + + subCategoryCreationSession + .setSubCategoryNameMenuOpen( + subCategoryNameMenuOpen + ); + + } + + public boolean isSubCategoryDisplayNameMenuOpen() { + + return subCategoryCreationSession + .isSubCategoryDisplayNameMenuOpen(); + } + + public void setSubCategoryDisplayNameMenuOpen( + boolean subCategoryDisplayNameMenuOpen + ) { + + subCategoryCreationSession + .setSubCategoryDisplayNameMenuOpen( + subCategoryDisplayNameMenuOpen + ); + + } + + public String getPendingSubCategoryName() { + + return subCategoryCreationSession + .getPendingSubCategoryName(); + + } + + public void setPendingSubCategoryName( + String pendingSubCategoryName + ) { + + subCategoryCreationSession + .setPendingSubCategoryName( + pendingSubCategoryName + ); + + } + + public String getPendingSubCategoryDisplayName() { + + return subCategoryCreationSession + .getPendingSubCategoryDisplayName(); + + } + + public void setPendingSubCategoryDisplayName( + String pendingSubCategoryDisplayName + ) { + + subCategoryCreationSession + .setPendingSubCategoryDisplayName( + pendingSubCategoryDisplayName + ); + + } + + public String getPendingSubCategoryLore( + int index + ) { + + return subCategoryCreationSession + .getPendingSubCategoryLore( + index + ); + + } + + public void setPendingSubCategoryLore( + int index, + String value + ) { + + subCategoryCreationSession + .setPendingSubCategoryLore( + index, + value + ); + + } + + public void clearPendingSubCategoryLore() { + + subCategoryCreationSession + .clearPendingSubCategoryLore(); + + } + + public int getPendingSubCategoryLoreSlot() { + + return subCategoryCreationSession + .getPendingSubCategoryLoreSlot(); + + } + + public void setPendingSubCategoryLoreSlot( + int pendingSubCategoryLoreSlot + ) { + + subCategoryCreationSession + .setPendingSubCategoryLoreSlot( + pendingSubCategoryLoreSlot + ); + + } + + public long getPendingSubCategoryLoreExpiration() { + + return subCategoryCreationSession + .getPendingSubCategoryLoreExpiration(); + + } + + public void setPendingSubCategoryLoreExpiration( + long pendingSubCategoryLoreExpiration + ) { + + subCategoryCreationSession + .setPendingSubCategoryLoreExpiration( + pendingSubCategoryLoreExpiration + ); + + } + + public int getAutoDepositPage() { + + return autoDepositPage; + + } + + public void setAutoDepositPage( + int autoDepositPage + ) { + + this.autoDepositPage = + autoDepositPage; + + } + + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/session/GuiSessionManager.java b/src/main/java/com/rsscripting/rswarehouse/session/GuiSessionManager.java new file mode 100644 index 0000000..388166b --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/session/GuiSessionManager.java @@ -0,0 +1,35 @@ +package com.rsscripting.rswarehouse.session; + +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class GuiSessionManager { + + private static final Map sessions = + new HashMap<>(); + + public static GuiSession getSession( + Player player + ) { + + return sessions.computeIfAbsent( + player.getUniqueId(), + GuiSession::new + ); + + } + + public static void removeSession( + Player player + ) { + + sessions.remove( + player.getUniqueId() + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/session/ItemActionSessionManager.java b/src/main/java/com/rsscripting/rswarehouse/session/ItemActionSessionManager.java new file mode 100644 index 0000000..af56a0f --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/session/ItemActionSessionManager.java @@ -0,0 +1,49 @@ +package com.rsscripting.rswarehouse.session; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class ItemActionSessionManager { + + private static final Map< + UUID, + TransactionSession + > SESSIONS = + new HashMap<>(); + + public static TransactionSession getSession( + UUID playerUuid + ) { + + return SESSIONS.get( + playerUuid + ); + + } + + public static void createSession( + UUID playerUuid, + int itemId + ) { + + SESSIONS.put( + playerUuid, + new TransactionSession( + itemId + ) + ); + + } + + public static void removeSession( + UUID playerUuid + ) { + + SESSIONS.remove( + playerUuid + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/session/ItemBrowserSession.java b/src/main/java/com/rsscripting/rswarehouse/session/ItemBrowserSession.java new file mode 100644 index 0000000..16ec348 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/session/ItemBrowserSession.java @@ -0,0 +1,56 @@ +package com.rsscripting.rswarehouse.session; + +public class ItemBrowserSession { + + private int itemsCategoryId; + + private String itemsCategoryName; + + private int itemsPage; + + public int getItemsCategoryId() { + + return itemsCategoryId; + + } + + public void setItemsCategoryId( + int itemsCategoryId + ) { + + this.itemsCategoryId = + itemsCategoryId; + + } + + public String getItemsCategoryName() { + + return itemsCategoryName; + + } + + public void setItemsCategoryName( + String itemsCategoryName + ) { + + this.itemsCategoryName = + itemsCategoryName; + + } + + public int getItemsPage() { + + return itemsPage; + + } + + public void setItemsPage( + int itemsPage + ) { + + this.itemsPage = + itemsPage; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/session/SubCategoryCreationSession.java b/src/main/java/com/rsscripting/rswarehouse/session/SubCategoryCreationSession.java new file mode 100644 index 0000000..25688b3 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/session/SubCategoryCreationSession.java @@ -0,0 +1,143 @@ +package com.rsscripting.rswarehouse.session; + +public class SubCategoryCreationSession { + + private boolean subCategoryNameMenuOpen; + + private boolean subCategoryDisplayNameMenuOpen; + + private String pendingSubCategoryName; + + private String pendingSubCategoryDisplayName; + + private final String[] pendingSubCategoryLore = + new String[5]; + + private int pendingSubCategoryLoreSlot = -1; + + private long pendingSubCategoryLoreExpiration; + + public boolean isSubCategoryNameMenuOpen() { + + return subCategoryNameMenuOpen; + + } + + public void setSubCategoryNameMenuOpen( + boolean subCategoryNameMenuOpen + ) { + + this.subCategoryNameMenuOpen = + subCategoryNameMenuOpen; + + } + + public boolean isSubCategoryDisplayNameMenuOpen() { + + return subCategoryDisplayNameMenuOpen; + + } + + public void setSubCategoryDisplayNameMenuOpen( + boolean subCategoryDisplayNameMenuOpen + ) { + + this.subCategoryDisplayNameMenuOpen = + subCategoryDisplayNameMenuOpen; + + } + + public String getPendingSubCategoryName() { + + return pendingSubCategoryName; + + } + + public void setPendingSubCategoryName( + String pendingSubCategoryName + ) { + + this.pendingSubCategoryName = + pendingSubCategoryName; + + } + + public String getPendingSubCategoryDisplayName() { + + return pendingSubCategoryDisplayName; + + } + + public void setPendingSubCategoryDisplayName( + String pendingSubCategoryDisplayName + ) { + + this.pendingSubCategoryDisplayName = + pendingSubCategoryDisplayName; + + } + + public String getPendingSubCategoryLore( + int index + ) { + + return pendingSubCategoryLore[index]; + + } + + public void setPendingSubCategoryLore( + int index, + String value + ) { + + pendingSubCategoryLore[index] = + value; + + } + + public void clearPendingSubCategoryLore() { + + for ( + int i = 0; + i < pendingSubCategoryLore.length; + i++ + ) { + + pendingSubCategoryLore[i] = + null; + + } + + } + + public int getPendingSubCategoryLoreSlot() { + + return pendingSubCategoryLoreSlot; + + } + + public void setPendingSubCategoryLoreSlot( + int pendingSubCategoryLoreSlot + ) { + + this.pendingSubCategoryLoreSlot = + pendingSubCategoryLoreSlot; + + } + + public long getPendingSubCategoryLoreExpiration() { + + return pendingSubCategoryLoreExpiration; + + } + + public void setPendingSubCategoryLoreExpiration( + long pendingSubCategoryLoreExpiration + ) { + + this.pendingSubCategoryLoreExpiration = + pendingSubCategoryLoreExpiration; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/session/TransactionSession.java b/src/main/java/com/rsscripting/rswarehouse/session/TransactionSession.java new file mode 100644 index 0000000..adcf81b --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/session/TransactionSession.java @@ -0,0 +1,82 @@ +package com.rsscripting.rswarehouse.session; + +public class TransactionSession { + + private final int warehouseItemId; + + private VariantType variantType; + + private Integer variantRecordId; + + private int amount; + + public TransactionSession( + int warehouseItemId + ) { + + this.warehouseItemId = + warehouseItemId; + + this.variantType = + VariantType.NONE; + + this.variantRecordId = + null; + + this.amount = + 0; + + } + + public int getWarehouseItemId() { + + return warehouseItemId; + + } + + public VariantType getVariantType() { + + return variantType; + + } + + public void setVariantType( + VariantType variantType + ) { + + this.variantType = + variantType; + + } + + public Integer getVariantRecordId() { + + return variantRecordId; + + } + + public void setVariantRecordId( + Integer variantRecordId + ) { + + this.variantRecordId = + variantRecordId; + + } + + public int getAmount() { + + return amount; + + } + + public void setAmount( + int amount + ) { + + this.amount = + amount; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/session/VariantType.java b/src/main/java/com/rsscripting/rswarehouse/session/VariantType.java new file mode 100644 index 0000000..d8111e9 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/session/VariantType.java @@ -0,0 +1,10 @@ +package com.rsscripting.rswarehouse.session; + +public enum VariantType { + + NONE, + DAMAGED, + ENCHANTED, + PARTIAL + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/copytosubcategory/CopyToSubCategoryMenu.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/copytosubcategory/CopyToSubCategoryMenu.java new file mode 100644 index 0000000..ee857dc --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/copytosubcategory/CopyToSubCategoryMenu.java @@ -0,0 +1,196 @@ +package com.rsscripting.rswarehouse.subcategory.copytosubcategory; + +import com.rsscripting.rswarehouse.subcategory.subcategorydao.SubCategoryDAO; +import com.rsscripting.rswarehouse.model.WarehouseCategory; +import com.rsscripting.rswarehouse.constants.RSKeys; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class CopyToSubCategoryMenu { + + public static final String MENU_TITLE = + "Copy To SubCategory"; + + public static void open( + Player player, + int itemId, + int page + ) { + + Inventory menu = + Bukkit.createInventory( + new CopyToSubCategoryMenuHolder( + itemId, + page + ), + 54, + Component.text( + MENU_TITLE + ).color( + NamedTextColor.BLUE + ) + ); + + ItemStack filler = + RSMenuUtils.createFillerPane(); + + for (int slot = 0; slot <= 8; slot++) { + + menu.setItem( + slot, + filler + ); + + } + + for (int slot = 45; slot <= 53; slot++) { + + menu.setItem( + slot, + filler + ); + + } + + List categories = + SubCategoryDAO.getSubCategories(); + + List displayCategories = + new ArrayList<>(); + + for (WarehouseCategory category : categories) { + displayCategories.add( + category + ); + } + + int pageSize = 36; + + int maxPage = + Math.max( + 0, + (displayCategories.size() - 1) + / pageSize + ); + + int startIndex = + page * pageSize; + + int endIndex = + Math.min( + startIndex + pageSize, + displayCategories.size() + ); + + boolean hasPrevious = + page > 0; + + boolean hasNext = + page < maxPage; + + if (hasPrevious) { + + menu.setItem( + 0, + RSMenuUtils.createMenuItem( + Material.ARROW, + "§aPrevious Page" + ) + ); + + } + + if (hasNext) { + + menu.setItem( + 8, + RSMenuUtils.createMenuItem( + Material.ARROW, + "§aNext Page" + ) + ); + + } + + int slot = 9; + + for ( + + int i = startIndex; + + i < endIndex; + + i++ + + ) { + + WarehouseCategory category = + displayCategories.get( + i + ); + + List lore = + new ArrayList<>(); + + if ( + category.lore() != null + && + !category.lore().isBlank() + ) { + + lore.addAll( + Arrays.asList( + category.lore().split("\n") + ) + ); + + } + + ItemStack icon = + RSMenuUtils.createMenuItemWithLore( + Material.valueOf( + category.material() + ), + "§a" + category.displayName(), + lore + ); + + ItemMeta meta = + icon.getItemMeta(); + + meta.getPersistentDataContainer().set( + RSKeys.CATEGORY_ID, + PersistentDataType.INTEGER, + category.id() + ); + + icon.setItemMeta( + meta + ); + + menu.setItem( + slot++, + icon + ); + + } + + player.openInventory( + menu + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/copytosubcategory/CopyToSubCategoryMenuHolder.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/copytosubcategory/CopyToSubCategoryMenuHolder.java new file mode 100644 index 0000000..0f97878 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/copytosubcategory/CopyToSubCategoryMenuHolder.java @@ -0,0 +1,41 @@ +package com.rsscripting.rswarehouse.subcategory.copytosubcategory; + +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; + +public class CopyToSubCategoryMenuHolder + extends RSMenuHolder { + + private final int itemId; + + private final int page; + + public CopyToSubCategoryMenuHolder( + int itemId, + int page + ) { + + super( + "COPY_TO_SUBCATEGORY" + ); + + this.itemId = + itemId; + + this.page = + page; + + } + + public int getItemId() { + + return itemId; + + } + + public int getPage() { + + return page; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/copytosubcategory/CopyToSubCategoryMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/copytosubcategory/CopyToSubCategoryMenuListener.java new file mode 100644 index 0000000..62302aa --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/copytosubcategory/CopyToSubCategoryMenuListener.java @@ -0,0 +1,180 @@ +package com.rsscripting.rswarehouse.subcategory.copytosubcategory; + +import com.rsscripting.rswarehouse.category.categorymenu.CategoryDAO; +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; +import com.rsscripting.rswarehouse.placement.placementdao.ItemPlacementDAO; +import com.rsscripting.rswarehouse.model.WarehouseCategory; +import com.rsscripting.rswarehouse.model.WarehouseItem; +import com.rsscripting.rswarehouse.constants.RSKeys; +import com.rsscripting.rswarehouse.item.ItemsMenu; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +public class CopyToSubCategoryMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getWhoClicked() + instanceof Player player)) { + + return; + + } + + if (!(event.getInventory() + .getHolder() + instanceof CopyToSubCategoryMenuHolder holder)) { + + return; + + } + + if (!holder.getMenuId().equals( + "COPY_TO_SUBCATEGORY" + )) { + + return; + + } + + event.setCancelled( + true + ); + + ItemStack clicked = + event.getCurrentItem(); + + if (clicked == null) { + + return; + + } + + ItemMeta meta = + clicked.getItemMeta(); + + if ( + clicked.getType() == Material.ARROW + ) { + + String name = + clicked.getItemMeta() + .getDisplayName(); + + if (name.equals("§aPrevious Page")) { + + CopyToSubCategoryMenu.open( + player, + holder.getItemId(), + holder.getPage() - 1 + ); + + return; + + } + + if (name.equals("§aNext Page")) { + + CopyToSubCategoryMenu.open( + player, + holder.getItemId(), + holder.getPage() + 1 + ); + + return; + + } + + } + + if (meta == null) { + + return; + + } + + Integer categoryId = + meta.getPersistentDataContainer().get( + RSKeys.CATEGORY_ID, + PersistentDataType.INTEGER + ); + + if (categoryId == null) { + + return; + + } + + WarehouseItem warehouseItem = + ItemDAO.getItemById( + holder.getItemId() + ); + + if ( + + warehouseItem != null + + && + + warehouseItem.subcategoryId() != null + + && + + warehouseItem.subcategoryId().equals( + categoryId + ) + + ) { + + player.sendMessage( + "§cYou cannot copy a subcategory link into the subcategory it references." + ); + + CopyToSubCategoryMenu.open( + player, + holder.getItemId(), + holder.getPage() + ); + + return; + + } + + ItemPlacementDAO.copyItemToCategory( + holder.getItemId(), + categoryId + ); + + player.sendMessage( + "§aItem copied successfully." + ); + + WarehouseCategory category = + CategoryDAO.getCategoryById( + categoryId + ); + + if (category != null) { + + ItemsMenu.open( + player, + category.id(), + category.displayName(), + 0 + ); + + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryDisplayNameMenu.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryDisplayNameMenu.java new file mode 100644 index 0000000..7563138 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryDisplayNameMenu.java @@ -0,0 +1,86 @@ +package com.rsscripting.rswarehouse.subcategory.items; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.MenuType; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.view.AnvilView; + +import java.util.List; + +public class SubCategoryDisplayNameMenu { + + public static final String TITLE = + "SubCat Display Name"; + + public static void open(Player player) { + + AnvilView view = MenuType.ANVIL + .builder() + .title( + Component.text( + TITLE + ) + ) + .build(player); + + ItemStack confirm = new ItemStack(Material.LIME_WOOL); + + ItemMeta meta = confirm.getItemMeta(); + + meta.displayName( + Component.text("") + ); + + meta.lore( + List.of( + Component.text( + "Save and proceed to material picker." + ).color( + NamedTextColor.WHITE + ) + ) + ); + + confirm.setItemMeta(meta); + + view.setItem( + 0, + confirm + ); + + + ItemStack cancel = new ItemStack(Material.RED_WOOL); + + ItemMeta metacancel = cancel.getItemMeta(); + + metacancel.displayName( + Component.text("") + ); + + metacancel.lore( + List.of( + Component.text( + "Cancel" + ).color( + NamedTextColor.WHITE + ) + ) + ); + + cancel.setItemMeta(metacancel); + + + view.setItem( + 1, + cancel + ); + + view.open(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryDisplayNameMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryDisplayNameMenuListener.java new file mode 100644 index 0000000..e0e5d1c --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryDisplayNameMenuListener.java @@ -0,0 +1,151 @@ +package com.rsscripting.rswarehouse.subcategory.items; + +import com.rsscripting.rswarehouse.admin.AdminMenu; +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryCreationSession; +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryCreationSessionManager; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryDAO; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.view.AnvilView; + +public class SubCategoryDisplayNameMenuListener implements Listener { + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + + if (!(event.getView() instanceof AnvilView anvilView)) { + return; + } + + if (!event.getView() + .title() + .toString() + .contains( + SubCategoryDisplayNameMenu.TITLE + )) { + + return; + + } + + Player player = + (Player) event.getWhoClicked(); + + SubCategoryCreationSession session = + SubCategoryCreationSessionManager.getSession( + player.getUniqueId() + ); + + if (session == null) { + + return; + + } + + event.setCancelled(true); + + if (event.getCurrentItem() == null) { + return; + } + + if (event.getRawSlot() == 0) { + + String categoryName = + anvilView.getRenameText(); + + if (categoryName.length() > 25) { + + RSMessageUtils.error( + player, + "Category names may not exceed 25 characters." + ); + + return; + + } + + if (categoryName.isBlank()) { + + RSMessageUtils.error( + player, + "Category name cannot be empty." + ); + + return; + + } + + if ( + CategoryDAO.categoryExists( + categoryName + ) + ) { + + RSMessageUtils.error( + player, + "A category with that name already exists." + ); + + return; + + } + + session.setDisplayName( + categoryName + ); + + event.getView().getTopInventory().clear(); + + SubCategoryLoreMenu.open( + player + ); + + return; + + } + + if (event.getRawSlot() == 1) { + + event.getView().getTopInventory().clear(); + + AdminMenu.open( + player + ); + + } + } + + @EventHandler + public void onInventoryClose( + InventoryCloseEvent event + ) { + + if (!(event.getView() + instanceof AnvilView)) { + + return; + + } + + if (!event.getView() + .title() + .toString() + .contains( + SubCategoryDisplayNameMenu.TITLE + )) { + + return; + + } + + event.getView() + .getTopInventory() + .clear(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryEditDisplayNameMenu.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryEditDisplayNameMenu.java new file mode 100644 index 0000000..e74e190 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryEditDisplayNameMenu.java @@ -0,0 +1,93 @@ +package com.rsscripting.rswarehouse.subcategory.items; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.MenuType; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.view.AnvilView; + +import java.util.List; + +public class SubCategoryEditDisplayNameMenu { + + public static final String TITLE = + "Edit Display Name"; + + public static void open( + Player player, + String currentDisplayName + ) { + + AnvilView view = MenuType.ANVIL + .builder() + .title( + Component.text( + TITLE + ) + ) + .build(player); + + ItemStack confirm = new ItemStack(Material.LIME_WOOL); + + ItemMeta meta = + confirm.getItemMeta(); + + meta.displayName( + Component.text( + currentDisplayName + ) + ); + + meta.lore( + List.of( + Component.text( + "§aSave display name." + ).color( + NamedTextColor.WHITE + ) + ) + ); + + confirm.setItemMeta( + meta + ); + + view.setItem( + 0, + confirm + ); + + ItemStack cancel = new ItemStack(Material.RED_WOOL); + + ItemMeta metacancel = cancel.getItemMeta(); + + metacancel.displayName( + Component.text("") + ); + + metacancel.lore( + List.of( + Component.text( + "Cancel" + ).color( + NamedTextColor.WHITE + ) + ) + ); + + cancel.setItemMeta(metacancel); + + + view.setItem( + 1, + cancel + ); + + view.open(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryEditDisplayNameMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryEditDisplayNameMenuListener.java new file mode 100644 index 0000000..4e3aa7a --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryEditDisplayNameMenuListener.java @@ -0,0 +1,143 @@ +package com.rsscripting.rswarehouse.subcategory.items; + +import com.rsscripting.rswarehouse.admin.admindao.UpdateCategoryDAO; +import com.rsscripting.rswarehouse.item.options.ItemOptionsMenu; +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryEditSession; +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryEditSessionManager; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.view.AnvilView; + +public class SubCategoryEditDisplayNameMenuListener implements Listener { + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + + if (!(event.getView() instanceof AnvilView anvilView)) { + return; + } + + if (!event.getView() + .title() + .toString() + .contains( + SubCategoryEditDisplayNameMenu.TITLE + )) { + + return; + + } + + Player player = + (Player) event.getWhoClicked(); + + SubCategoryEditSession session = + SubCategoryEditSessionManager.getSession( + player.getUniqueId() + ); + + if (session == null) { + + return; + + } + + event.setCancelled(true); + + if (event.getCurrentItem() == null) { + return; + } + + if (event.getRawSlot() == 0) { + + String categoryName = + anvilView.getRenameText(); + + if (categoryName.length() > 25) { + + RSMessageUtils.error( + player, + "Category names may not exceed 25 characters." + ); + + return; + + } + + if (categoryName.isBlank()) { + + RSMessageUtils.error( + player, + "Category name cannot be empty." + ); + + return; + + } + + UpdateCategoryDAO.updateDisplayName( + session.getSubCategoryId(), + categoryName + ); + + event.getView().getTopInventory().clear(); + + ItemOptionsMenu.open( + player, + session.getItemId() + ); + + return; + + } + + if (event.getRawSlot() == 1) { + + event.getView().getTopInventory().clear(); + + ItemOptionsMenu.open( + player, + session.getItemId() + ); + + SubCategoryEditSessionManager.removeSession( + player.getUniqueId() + ); + + } + } + + @EventHandler + public void onInventoryClose( + InventoryCloseEvent event + ) { + + if (!(event.getView() + instanceof AnvilView)) { + + return; + + } + + if (!event.getView() + .title() + .toString() + .contains( + SubCategoryDisplayNameMenu.TITLE + )) { + + return; + + } + + event.getView() + .getTopInventory() + .clear(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryEditLoreChatListener.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryEditLoreChatListener.java new file mode 100644 index 0000000..3865bd8 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryEditLoreChatListener.java @@ -0,0 +1,144 @@ +package com.rsscripting.rswarehouse.subcategory.items; + +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryEditSession; +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryEditSessionManager; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; + +public class SubCategoryEditLoreChatListener + implements Listener { + + @EventHandler + public void onPlayerChat( + AsyncPlayerChatEvent event + ) { + + Player player = + event.getPlayer(); + + SubCategoryEditSession session = + SubCategoryEditSessionManager.getSession( + player.getUniqueId() + ); + + if (session == null) { + + return; + + } + + int loreSlot = + session.getLoreSlot(); + + if (loreSlot < 0) { + + return; + + } + + event.setCancelled( + true + ); + + String message = + event.getMessage(); + + if (message.length() > 50) { + + RSMessageUtils.error( + player, + "Lore lines may not exceed 50 characters." + ); + + Bukkit.getScheduler() + .runTask( + Bukkit.getPluginManager() + .getPlugin( + "RS-Warehouse" + ), + () -> SubCategoryEditLoreMenu.open(player) + ); + + return; + + } + + if ( + message.equalsIgnoreCase( + "cancel" + ) + ) { + + session.setLoreSlot( + -1 + ); + + session.setLoreExpiration( + 0 + ); + + Bukkit.getScheduler() + .runTask( + Bukkit.getPluginManager() + .getPlugin( + "RS-Warehouse" + ), + () -> SubCategoryEditLoreMenu.open(player) + ); + + return; + + } + + if ( + message.equalsIgnoreCase("clear") + ) { + + session.setLore( + loreSlot, + "" + ); + + } + else { + + session.setLore( + loreSlot, + message + ); + + } + + session.setLoreSlot( + -1 + ); + + session.setLoreExpiration( + 0 + ); + + Bukkit.getScheduler() + .runTask( + Bukkit.getPluginManager() + .getPlugin( + "RS-Warehouse" + ), + () -> { + + RSMessageUtils.success( + player, + "Lore line saved." + ); + + SubCategoryEditLoreMenu.open(player); + + } + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryEditLoreMenu.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryEditLoreMenu.java new file mode 100644 index 0000000..7a2cb2c --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryEditLoreMenu.java @@ -0,0 +1,173 @@ +package com.rsscripting.rswarehouse.subcategory.items; + +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryEditSession; +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryEditSessionManager; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryDAO; +import com.rsscripting.rswarehouse.model.WarehouseCategory; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.ArrayList; +import java.util.List; + +public class SubCategoryEditLoreMenu { + + public static void open( + Player player + ) { + + Inventory menu = + Bukkit.createInventory( + new RSMenuHolder( + "SUBCATEGORY_EDIT_LORE" + ), + 27, + Component.text( + " Edit SubCategory Lore" + ) + ); + + for (int i = 0; i < menu.getSize(); i++) { + + menu.setItem( + i, + RSMenuUtils.createFillerPane() + ); + + } + + SubCategoryEditSession session = + SubCategoryEditSessionManager.getSession( + player.getUniqueId() + ); + + WarehouseCategory category = + CategoryDAO.getCategoryById( + session.getSubCategoryId() + ); + + String[] loreLines = + category.lore() == null + ? new String[5] + : category.lore().split("\n", -1); + + if (session.getLore(0) == null) { + + for (int i = 0; i < 5; i++) { + + if (i < loreLines.length) { + + session.setLore( + i, + loreLines[i] + ); + + } + + } + + } + + for (int i = 0; i < 5; i++) { + + ItemStack book = + new ItemStack( + Material.WRITABLE_BOOK + ); + + ItemMeta meta = + book.getItemMeta(); + + meta.displayName( + Component.text( + "Lore Line " + + (i + 1) + ) + ); + + List lore = + new ArrayList<>(); + + String value = + session.getLore( + i + ); + + if ( + value == null + || value.isBlank() + ) { + + lore.add( + Component.text( + "(Empty)" + ) + ); + + } + + else { + + lore.add( + Component.text( + value + ) + ); + + } + + lore.add( + Component.empty() + ); + + lore.add( + Component.text( + "Click to edit." + ) + ); + + meta.lore( + lore + ); + + book.setItemMeta( + meta + ); + + menu.setItem( + 11 + i, + book + ); + + } + + menu.setItem( + 22, + RSMenuUtils.createMenuItem( + Material.LIME_WOOL, + "§aSave Lore" + ) + ); + + menu.setItem( + 4, + RSMenuUtils.createMenuItem( + Material.OAK_DOOR, + "§eBack" + ) + ); + + player.openInventory( + menu + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryEditLoreMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryEditLoreMenuListener.java new file mode 100644 index 0000000..f2cebb9 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryEditLoreMenuListener.java @@ -0,0 +1,230 @@ +package com.rsscripting.rswarehouse.subcategory.items; + +import com.rsscripting.rswarehouse.admin.admindao.UpdateCategoryDAO; +import com.rsscripting.rswarehouse.item.options.ItemOptionsMenu; +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryEditSession; +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryEditSessionManager; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; + +public class SubCategoryEditLoreMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getInventory() + .getHolder() + instanceof RSMenuHolder holder)) { + + return; + + } + + if (!holder.getMenuId().equals( + "SUBCATEGORY_EDIT_LORE" + )) { + + return; + + } + + event.setCancelled( + true + ); + + Player player = + (Player) event.getWhoClicked(); + + SubCategoryEditSession session = + SubCategoryEditSessionManager.getSession( + player.getUniqueId() + ); + + switch (event.getSlot()) { + + case 4 -> { + + ItemOptionsMenu.open( + player, + session.getItemId() + ); + + } + + case 11 -> editLore( + player, + session, + 0 + ); + + case 12 -> editLore( + player, + session, + 1 + ); + + case 13 -> editLore( + player, + session, + 2 + ); + + case 14 -> editLore( + player, + session, + 3 + ); + + case 15 -> editLore( + player, + session, + 4 + ); + + case 22 -> saveLore( + player, + session + ); + + } + + } + + private void editLore( + Player player, + SubCategoryEditSession session, + int loreSlot + ){ + + session.setLoreSlot( + loreSlot + ); + + session.setLoreExpiration( + System.currentTimeMillis() + + 30000 + ); + + final long expiration = + session.getLoreExpiration(); + + Bukkit.getScheduler() + .runTaskLater( + Bukkit.getPluginManager() + .getPlugin( + "RS-Warehouse" + ), + () -> { + + if ( + session.getLoreExpiration() + != expiration + ) { + + return; + + } + + session.setLoreSlot( + -1 + ); + + session.setLoreExpiration( + 0 + ); + + RSMessageUtils.error( + player, + "Lore input timed out." + ); + + }, + 20L * 30 + ); + + player.closeInventory(); + + RSMessageUtils.info( + player, + "Enter lore for line " + + (loreSlot + 1) + + " in chat." + ); + + RSMessageUtils.info( + player, + "Type 'cancel' to abort." + ); + + RSMessageUtils.info( + player, + "Auto-Cancels after 30 seconds." + ); + + RSMessageUtils.info( + player, + "Type 'clear' to clear the lore line." + ); + + } + + private void saveLore( + Player player, + SubCategoryEditSession session + ) { + + StringBuilder loreBuilder = + new StringBuilder(); + + for (int i = 0; i < 5; i++) { + + String line = + session.getLore( + i + ); + + if (line == null) { + + line = ""; + + } + + loreBuilder.append( + line + ); + + if (i < 4) { + + loreBuilder.append( + "\n" + ); + + } + + } + + UpdateCategoryDAO.updateLore( + session.getSubCategoryId(), + loreBuilder.toString() + ); + + SubCategoryEditSessionManager.removeSession( + player.getUniqueId() + ); + + ItemOptionsMenu.open( + player, + session.getItemId() + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryInternalNameMenu.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryInternalNameMenu.java new file mode 100644 index 0000000..0679f34 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryInternalNameMenu.java @@ -0,0 +1,87 @@ +package com.rsscripting.rswarehouse.subcategory.items; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.MenuType; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.view.AnvilView; + +import java.util.List; + + +public class SubCategoryInternalNameMenu { + + public static final String TITLE = + "SubCat Internal Name"; + + public static void open(Player player) { + + AnvilView view = MenuType.ANVIL + .builder() + .title( + Component.text( + TITLE + ) + ) + .build(player); + + ItemStack confirm = new ItemStack(Material.LIME_WOOL); + + ItemMeta meta = confirm.getItemMeta(); + + meta.displayName( + Component.text("") + ); + + meta.lore( + List.of( + Component.text( + "Save and proceed to material picker." + ).color( + NamedTextColor.WHITE + ) + ) + ); + + confirm.setItemMeta(meta); + + view.setItem( + 0, + confirm + ); + + + ItemStack cancel = new ItemStack(Material.RED_WOOL); + + ItemMeta metacancel = cancel.getItemMeta(); + + metacancel.displayName( + Component.text("") + ); + + metacancel.lore( + List.of( + Component.text( + "Cancel" + ).color( + NamedTextColor.WHITE + ) + ) + ); + + cancel.setItemMeta(metacancel); + + + view.setItem( + 1, + cancel + ); + + view.open(); + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryInternalNameMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryInternalNameMenuListener.java new file mode 100644 index 0000000..9f30a60 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryInternalNameMenuListener.java @@ -0,0 +1,135 @@ +package com.rsscripting.rswarehouse.subcategory.items; + +import com.rsscripting.rswarehouse.admin.AdminMenu; +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryCreationSession; +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryCreationSessionManager; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.view.AnvilView; + +public class SubCategoryInternalNameMenuListener implements Listener { + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + + if (!(event.getView() instanceof AnvilView anvilView)) { + return; + } + + if (!event.getView() + .title() + .toString() + .contains( + SubCategoryInternalNameMenu.TITLE + )) { + + return; + + } + + Player player = + (Player) event.getWhoClicked(); + + SubCategoryCreationSession session = + SubCategoryCreationSessionManager.getSession( + player.getUniqueId() + ); + + if (session == null) { + + return; + + } + + event.setCancelled(true); + + if (event.getCurrentItem() == null) { + return; + } + + if (event.getRawSlot() == 0) { + + String categoryName = + anvilView.getRenameText(); + + if (categoryName.length() > 25) { + + RSMessageUtils.error( + player, + "Category names may not exceed 25 characters." + ); + + return; + + } + + if (categoryName.isBlank()) { + + RSMessageUtils.error( + player, + "Category name cannot be empty." + ); + + return; + + } + + session.setInternalName( + categoryName + ); + + event.getView().getTopInventory().clear(); + + SubCategoryDisplayNameMenu.open( + player + ); + + return; + + } + + if (event.getRawSlot() == 1) { + + event.getView().getTopInventory().clear(); + + AdminMenu.open( + player + ); + + } + } + + @EventHandler + public void onInventoryClose( + InventoryCloseEvent event + ) { + + if (!(event.getView() + instanceof AnvilView)) { + + return; + + } + + if (!event.getView() + .title() + .toString() + .contains( + SubCategoryInternalNameMenu.TITLE + )) { + + return; + + } + + event.getView() + .getTopInventory() + .clear(); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryLoreChatListener.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryLoreChatListener.java new file mode 100644 index 0000000..e841fd9 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryLoreChatListener.java @@ -0,0 +1,136 @@ +package com.rsscripting.rswarehouse.subcategory.items; + +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryCreationSession; +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryCreationSessionManager; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; + +public class SubCategoryLoreChatListener + implements Listener { + + @EventHandler + public void onPlayerChat( + AsyncPlayerChatEvent event + ) { + + Player player = + event.getPlayer(); + + SubCategoryCreationSession session = + SubCategoryCreationSessionManager.getSession( + player.getUniqueId() + ); + + if (session == null) { + + return; + + } + + int loreSlot = + session.getLoreSlot(); + + if (loreSlot < 0) { + + return; + + } + + event.setCancelled( + true + ); + + String message = + event.getMessage(); + + if (message.length() > 50) { + + RSMessageUtils.error( + player, + "Lore lines may not exceed 50 characters." + ); + + Bukkit.getScheduler() + .runTask( + Bukkit.getPluginManager() + .getPlugin( + "RS-Warehouse" + ), + () -> SubCategoryLoreMenu.open( + player + ) + ); + + return; + + } + + if ( + message.equalsIgnoreCase( + "cancel" + ) + ) { + + session.setLoreSlot( + -1 + ); + + session.setLoreExpiration( + 0 + ); + + Bukkit.getScheduler() + .runTask( + Bukkit.getPluginManager() + .getPlugin( + "RS-Warehouse" + ), + () -> SubCategoryLoreMenu.open( + player + ) + ); + + return; + + } + + session.setLore( + loreSlot, + message + ); + + session.setLoreSlot( + -1 + ); + + session.setLoreExpiration( + 0 + ); + + Bukkit.getScheduler() + .runTask( + Bukkit.getPluginManager() + .getPlugin( + "RS-Warehouse" + ), + () -> { + + RSMessageUtils.success( + player, + "Lore line saved." + ); + + SubCategoryLoreMenu.open( + player + ); + + } + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryLoreMenu.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryLoreMenu.java new file mode 100644 index 0000000..597d595 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryLoreMenu.java @@ -0,0 +1,144 @@ +package com.rsscripting.rswarehouse.subcategory.items; + +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryCreationSession; +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryCreationSessionManager; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.ArrayList; +import java.util.List; + +public class SubCategoryLoreMenu { + + public static void open( + Player player + ) { + + Inventory menu = + Bukkit.createInventory( + new RSMenuHolder( + "SUBCATEGORY_LORE" + ), + 27, + Component.text( + "SubCategory Lore" + ) + ); + + for (int i = 0; i < menu.getSize(); i++) { + + menu.setItem( + i, + RSMenuUtils.createFillerPane() + ); + + } + + SubCategoryCreationSession session = + SubCategoryCreationSessionManager.getSession( + player.getUniqueId() + ); + + for (int i = 0; i < 5; i++) { + + ItemStack book = + new ItemStack( + Material.WRITABLE_BOOK + ); + + ItemMeta meta = + book.getItemMeta(); + + meta.displayName( + Component.text( + "Lore Line " + + (i + 1) + ) + ); + + List lore = + new ArrayList<>(); + + String value = + session.getLore( + i + ); + + if ( + value == null + || value.isBlank() + ) { + + lore.add( + Component.text( + "(Empty)" + ) + ); + + } + + else { + + lore.add( + Component.text( + value + ) + ); + + } + + lore.add( + Component.empty() + ); + + lore.add( + Component.text( + "Click to edit." + ) + ); + + meta.lore( + lore + ); + + book.setItemMeta( + meta + ); + + menu.setItem( + 11 + i, + book + ); + + } + + menu.setItem( + 22, + RSMenuUtils.createMenuItem( + Material.LIME_WOOL, + "§aCreate SubCategory" + ) + ); + + menu.setItem( + 4, + RSMenuUtils.createMenuItem( + Material.OAK_DOOR, + "§eBack" + ) + ); + + player.openInventory( + menu + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryLoreMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryLoreMenuListener.java new file mode 100644 index 0000000..d4d9328 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/items/SubCategoryLoreMenuListener.java @@ -0,0 +1,250 @@ +package com.rsscripting.rswarehouse.subcategory.items; + +import com.rsscripting.rswarehouse.admin.admindao.CreateSubCategoryDAO; +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryCreationSession; +import com.rsscripting.rswarehouse.admin.adminsessions.SubCategoryCreationSessionManager; +import com.rsscripting.rswarehouse.placement.placementdao.ItemPlacementDAO; +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; +import com.rsscripting.rswarehouse.item.ItemsMenu; +import com.rsscripting.rswarehouse.model.WarehouseItem; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; + +public class SubCategoryLoreMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getInventory() + .getHolder() + instanceof RSMenuHolder holder)) { + + return; + + } + + if (!holder.getMenuId().equals( + "SUBCATEGORY_LORE" + )) { + + return; + + } + + event.setCancelled( + true + ); + + Player player = + (Player) event.getWhoClicked(); + + SubCategoryCreationSession session = + SubCategoryCreationSessionManager.getSession( + player.getUniqueId() + ); + + switch (event.getSlot()) { + + case 4 -> SubCategoryDisplayNameMenu.open( + player + ); + + case 11 -> editLore( + player, + session, + 0 + ); + + case 12 -> editLore( + player, + session, + 1 + ); + + case 13 -> editLore( + player, + session, + 2 + ); + + case 14 -> editLore( + player, + session, + 3 + ); + + case 15 -> editLore( + player, + session, + 4 + ); + + case 22 -> createSubCategory( + player, + session + ); + + } + + } + + private void editLore( + Player player, + SubCategoryCreationSession session, + int loreSlot + ){ + + session.setLoreSlot( + loreSlot + ); + + session.setLoreExpiration( + System.currentTimeMillis() + + 30000 + ); + + final long expiration = + session.getLoreExpiration(); + + Bukkit.getScheduler() + .runTaskLater( + Bukkit.getPluginManager() + .getPlugin( + "RS-Warehouse" + ), + () -> { + + if ( + session.getLoreExpiration() + != expiration + ) { + + return; + + } + + session.setLoreSlot( + -1 + ); + + session.setLoreExpiration( + 0 + ); + + RSMessageUtils.error( + player, + "Lore input timed out." + ); + + }, + 20L * 30 + ); + + player.closeInventory(); + + RSMessageUtils.info( + player, + "Enter lore for line " + + (loreSlot + 1) + + " in chat." + ); + + RSMessageUtils.info( + player, + "Type 'cancel' to abort." + ); + + RSMessageUtils.info( + player, + "Auto-Cancels after 30 seconds." + ); + + } + + private void createSubCategory( + Player player, + SubCategoryCreationSession session + ) { + + SubCategoryCreationSession subCategorySession = + SubCategoryCreationSessionManager.getSession( + player.getUniqueId() + ); + + WarehouseItem clickedItem = + ItemDAO.getItemById( + subCategorySession.getItemId() + ); + + StringBuilder loreBuilder = + new StringBuilder(); + + for (int i = 0; i < 5; i++) { + + String line = + session.getLore( + i + ); + + if (line == null) { + + line = ""; + + } + + loreBuilder.append( + line + ); + + if (i < 4) { + + loreBuilder.append( + "\n" + ); + + } + + } + + int newSubCategoryId = + CreateSubCategoryDAO.createSubCategory( + clickedItem.categoryId(), + subCategorySession.getInternalName(), + subCategorySession.getDisplayName(), + ItemStackUtils.deserialize( + clickedItem.serializedItem() + ).getType().name(), + loreBuilder.toString() + ); + + ItemPlacementDAO.cloneItemToSubCategory( + clickedItem.id(), + newSubCategoryId + ); + + ItemPlacementDAO.convertItemToSubCategoryLink( + clickedItem.id(), + newSubCategoryId, + loreBuilder.toString() + ); + + ItemsMenu.open( + player, + newSubCategoryId, + session.getDisplayName(), + 0 + ); + + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/movetosubcategory/MoveToSubCategoryMenu.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/movetosubcategory/MoveToSubCategoryMenu.java new file mode 100644 index 0000000..5651a8b --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/movetosubcategory/MoveToSubCategoryMenu.java @@ -0,0 +1,196 @@ +package com.rsscripting.rswarehouse.subcategory.movetosubcategory; + +import com.rsscripting.rswarehouse.subcategory.subcategorydao.SubCategoryDAO; +import com.rsscripting.rswarehouse.model.WarehouseCategory; +import com.rsscripting.rswarehouse.constants.RSKeys; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class MoveToSubCategoryMenu { + + public static final String MENU_TITLE = + "Move Item To SubCategory"; + + public static void open( + Player player, + int itemId, + int page + ) { + + Inventory menu = + Bukkit.createInventory( + new MoveToSubCategoryMenuHolder( + itemId, + page + ), + 54, + Component.text( + MENU_TITLE + ).color( + NamedTextColor.BLUE + ) + ); + + ItemStack filler = + RSMenuUtils.createFillerPane(); + + for (int slot = 0; slot <= 8; slot++) { + + menu.setItem( + slot, + filler + ); + + } + + for (int slot = 45; slot <= 53; slot++) { + + menu.setItem( + slot, + filler + ); + + } + + List categories = + SubCategoryDAO.getSubCategories(); + + List displayCategories = + new ArrayList<>(); + + for (WarehouseCategory category : categories) { + displayCategories.add( + category + ); + } + + int pageSize = 36; + + int maxPage = + Math.max( + 0, + (displayCategories.size() - 1) + / pageSize + ); + + int startIndex = + page * pageSize; + + int endIndex = + Math.min( + startIndex + pageSize, + displayCategories.size() + ); + + boolean hasPrevious = + page > 0; + + boolean hasNext = + page < maxPage; + + if (hasPrevious) { + + menu.setItem( + 0, + RSMenuUtils.createMenuItem( + Material.ARROW, + "§aPrevious Page" + ) + ); + + } + + if (hasNext) { + + menu.setItem( + 8, + RSMenuUtils.createMenuItem( + Material.ARROW, + "§aNext Page" + ) + ); + + } + + int slot = 9; + + for ( + + int i = startIndex; + + i < endIndex; + + i++ + + ) { + + WarehouseCategory category = + displayCategories.get( + i + ); + + List lore = + new ArrayList<>(); + + if ( + category.lore() != null + && + !category.lore().isBlank() + ) { + + lore.addAll( + Arrays.asList( + category.lore().split("\n") + ) + ); + + } + + ItemStack icon = + RSMenuUtils.createMenuItemWithLore( + Material.valueOf( + category.material() + ), + "§a" + category.displayName(), + lore + ); + + ItemMeta meta = + icon.getItemMeta(); + + meta.getPersistentDataContainer().set( + RSKeys.CATEGORY_ID, + PersistentDataType.INTEGER, + category.id() + ); + + icon.setItemMeta( + meta + ); + + menu.setItem( + slot++, + icon + ); + + } + + player.openInventory( + menu + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/movetosubcategory/MoveToSubCategoryMenuHolder.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/movetosubcategory/MoveToSubCategoryMenuHolder.java new file mode 100644 index 0000000..b6e4c5e --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/movetosubcategory/MoveToSubCategoryMenuHolder.java @@ -0,0 +1,41 @@ +package com.rsscripting.rswarehouse.subcategory.movetosubcategory; + +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; + +public class MoveToSubCategoryMenuHolder + extends RSMenuHolder { + + private final int itemId; + + private final int page; + + public MoveToSubCategoryMenuHolder( + int itemId, + int page + ) { + + super( + "MOVE_TO_SUBCATEGORY" + ); + + this.itemId = + itemId; + + this.page = + page; + + } + + public int getItemId() { + + return itemId; + + } + + public int getPage() { + + return page; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/movetosubcategory/MoveToSubCategoryMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/movetosubcategory/MoveToSubCategoryMenuListener.java new file mode 100644 index 0000000..c2343ae --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/movetosubcategory/MoveToSubCategoryMenuListener.java @@ -0,0 +1,180 @@ +package com.rsscripting.rswarehouse.subcategory.movetosubcategory; + +import com.rsscripting.rswarehouse.category.categorymenu.CategoryDAO; +import com.rsscripting.rswarehouse.item.itemdao.ItemDAO; +import com.rsscripting.rswarehouse.placement.placementdao.ItemPlacementDAO; +import com.rsscripting.rswarehouse.item.ItemsMenu; +import com.rsscripting.rswarehouse.model.WarehouseCategory; +import com.rsscripting.rswarehouse.model.WarehouseItem; +import com.rsscripting.rswarehouse.constants.RSKeys; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +public class MoveToSubCategoryMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if (!(event.getWhoClicked() + instanceof Player player)) { + + return; + + } + + if (!(event.getInventory() + .getHolder() + instanceof MoveToSubCategoryMenuHolder holder)) { + + return; + + } + + if (!holder.getMenuId().equals( + "MOVE_TO_SUBCATEGORY" + )) { + + return; + + } + + event.setCancelled( + true + ); + + ItemStack clicked = + event.getCurrentItem(); + + if (clicked == null) { + + return; + + } + + ItemMeta meta = + clicked.getItemMeta(); + + if ( + clicked.getType() == Material.ARROW + ) { + + String name = + clicked.getItemMeta() + .getDisplayName(); + + if (name.equals("§aPrevious Page")) { + + MoveToSubCategoryMenu.open( + player, + holder.getItemId(), + holder.getPage() - 1 + ); + + return; + + } + + if (name.equals("§aNext Page")) { + + MoveToSubCategoryMenu.open( + player, + holder.getItemId(), + holder.getPage() + 1 + ); + + return; + + } + + } + + if (meta == null) { + + return; + + } + + Integer categoryId = + meta.getPersistentDataContainer().get( + RSKeys.CATEGORY_ID, + PersistentDataType.INTEGER + ); + + if (categoryId == null) { + + return; + + } + + WarehouseItem warehouseItem = + ItemDAO.getItemById( + holder.getItemId() + ); + + if ( + + warehouseItem != null + + && + + warehouseItem.subcategoryId() != null + + && + + warehouseItem.subcategoryId().equals( + categoryId + ) + + ) { + + player.sendMessage( + "§cYou cannot move a subcategory link into the subcategory it references." + ); + + MoveToSubCategoryMenu.open( + player, + holder.getItemId(), + holder.getPage() + ); + + return; + + } + + ItemPlacementDAO.moveItemToCategory( + holder.getItemId(), + categoryId + ); + + player.sendMessage( + "§aItem moved successfully." + ); + + WarehouseCategory category = + CategoryDAO.getCategoryById( + categoryId + ); + + if (category != null) { + + ItemsMenu.open( + player, + category.id(), + category.displayName(), + 0 + ); + + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/subcategory/subcategorydao/SubCategoryDAO.java b/src/main/java/com/rsscripting/rswarehouse/subcategory/subcategorydao/SubCategoryDAO.java new file mode 100644 index 0000000..3993ca4 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/subcategory/subcategorydao/SubCategoryDAO.java @@ -0,0 +1,323 @@ +package com.rsscripting.rswarehouse.subcategory.subcategorydao; + +import com.rsscripting.rswarehouse.database.DatabaseManager; +import com.rsscripting.rswarehouse.model.WarehouseCategory; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +public class SubCategoryDAO { + + public static List getSubCategories() { + + List categories = + new ArrayList<>(); + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT + id, + parent_category_id, + internal_name, + display_name, + material, + lore, + display_order, + page, + slot + FROM warehouse_categories + WHERE parent_category_id IS NOT NULL + ORDER BY display_order ASC + """ + ); + + ResultSet resultSet = + statement.executeQuery() + + ) { + + while (resultSet.next()) { + + categories.add( + new WarehouseCategory( + resultSet.getInt( + "id" + ), + resultSet.getObject( + "parent_category_id" + ) == null + ? null + : resultSet.getInt( + "parent_category_id" + ), + resultSet.getString( + "internal_name" + ), + resultSet.getString( + "display_name" + ), + resultSet.getString( + "material" + ), + resultSet.getString( + "lore" + ), + resultSet.getInt( + "display_order" + ), + resultSet.getInt( + "page" + ), + resultSet.getInt( + "slot" + ) + ) + ); + + } + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + return categories; + + } + + public static boolean isSubCategoryEmpty( + int subCategoryId + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT COUNT(*) + FROM warehouse_items + WHERE subcategory_id = ? + AND inventory_id IS NOT NULL + """ + ) + + ) { + + statement.setInt( + 1, + subCategoryId + ); + + try ( + ResultSet resultSet = + statement.executeQuery() + ) { + + if (resultSet.next()) { + + return resultSet.getInt(1) == 0; + + } + + } + + } + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + return false; + + } + + public static void deleteSubCategory( + int subCategoryId + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + DELETE FROM warehouse_categories + WHERE id = ? + """ + ) + + ) { + + statement.setInt( + 1, + subCategoryId + ); + + statement.executeUpdate(); + + } + + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + } + + public static boolean deleteSubCategoryAndLinkItem( + int subCategoryId, + int linkItemId + ) { + + try ( + Connection connection = DatabaseManager.getConnection() + ) { + + connection.setAutoCommit(false); + + try { + + int itemRows; + int categoryRows; + + try ( + PreparedStatement deleteItem = + connection.prepareStatement( + """ + DELETE FROM warehouse_items + WHERE id = ? + """ + ); + + PreparedStatement deleteCategory = + connection.prepareStatement( + """ + DELETE FROM warehouse_categories + WHERE id = ? + """ + ) + ) { + + deleteItem.setInt( + 1, + linkItemId + ); + + itemRows = deleteItem.executeUpdate(); + + deleteCategory.setInt( + 1, + subCategoryId + ); + + categoryRows = deleteCategory.executeUpdate(); + + } + + if ( + itemRows != 1 || + categoryRows != 1 + ) { + + connection.rollback(); + + return false; + + } + + connection.commit(); + + return true; + + } + catch (SQLException exception) { + + connection.rollback(); + + exception.printStackTrace(); + + return false; + + } + finally { + + connection.setAutoCommit(true); + + } + + } + catch (SQLException exception) { + + exception.printStackTrace(); + + return false; + + } + + } + + public static int countSubCategoryReferences( + int subCategoryId + ) { + + try ( + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT COUNT(*) + FROM warehouse_items + WHERE subcategory_id = ? + """ + ) + ) { + + statement.setInt( + 1, + subCategoryId + ); + + try ( + ResultSet resultSet = + statement.executeQuery() + ) { + + if (resultSet.next()) { + return resultSet.getInt(1); + } + + } + + } + catch (SQLException exception) { + + exception.printStackTrace(); + + } + + return 0; + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/updatechecker/GitHubUpdateChecker.java b/src/main/java/com/rsscripting/rswarehouse/updatechecker/GitHubUpdateChecker.java new file mode 100644 index 0000000..9be7427 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/updatechecker/GitHubUpdateChecker.java @@ -0,0 +1,186 @@ +package com.rsscripting.rswarehouse.updatechecker; + +import com.rsscripting.rswarehouse.RSWarehouse; +import com.rsscripting.rswarehouse.constants.RSConstants; +import com.rsscripting.rswarehouse.utils.VersionUtils; +import org.bukkit.Bukkit; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URI; + +public class GitHubUpdateChecker { + + /* + |-------------------------------------------------------------------------- + | UPDATE STATUS + |-------------------------------------------------------------------------- + */ + + private static String latestVersion = null; + + private static String updateStatus = + "Checking..."; + + /* + |-------------------------------------------------------------------------- + | CHECK FOR UPDATES + |-------------------------------------------------------------------------- + */ + + public static void checkForUpdates() { + + Bukkit.getScheduler().runTaskAsynchronously( + + RSWarehouse.getInstance(), + + () -> { + + try { + + String apiURL = + "https://api.github.com/repos/" + + RSConstants.GITHUB_USER + + "/" + + RSConstants.GITHUB_REPOSITORY + + "/releases/latest"; + + HttpURLConnection connection = + (HttpURLConnection) + URI.create(apiURL) + .toURL() + .openConnection(); + + connection.setRequestMethod("GET"); + + BufferedReader reader = + new BufferedReader( + new InputStreamReader( + connection.getInputStream() + ) + ); + + StringBuilder response = + new StringBuilder(); + + String line; + + while ((line = reader.readLine()) != null) { + + response.append(line); + + } + + reader.close(); + + String json = + response.toString(); + + latestVersion = + json.split("\"tag_name\":\"")[1] + .split("\"")[0]; + + String currentVersion = + VersionUtils.getVersion(); + + /* + |-------------------------------------------------------------------------- + | UPDATE AVAILABLE + |-------------------------------------------------------------------------- + */ + + if (!latestVersion.equalsIgnoreCase( + currentVersion + )) { + + updateStatus = + "Update Available"; + + Bukkit.getConsoleSender().sendMessage( + + RSConstants.PREFIX + + "Update available! Current: " + + currentVersion + + " Latest: " + + latestVersion + + ); + + } + + /* + |-------------------------------------------------------------------------- + | UP TO DATE + |-------------------------------------------------------------------------- + */ + + else { + + updateStatus = + "Up To Date"; + + Bukkit.getConsoleSender().sendMessage( + + RSConstants.PREFIX + + "Plugin is up to date." + + ); + + } + + } + + catch (Exception exception) { + + updateStatus = + "Unable To Check"; + + Bukkit.getConsoleSender().sendMessage( + + RSConstants.PREFIX + + "Failed to check for updates." + + ); + + } + + } + + ); + + } + + /* + |-------------------------------------------------------------------------- + | GET LATEST VERSION + |-------------------------------------------------------------------------- + */ + + public static String getLatestVersion() { + + return latestVersion; + + } + + public static boolean isUpdateAvailable() { + + return "Update Available".equalsIgnoreCase( + updateStatus + ); + + } + + /* + |-------------------------------------------------------------------------- + | GET UPDATE STATUS + |-------------------------------------------------------------------------- + */ + + public static String getUpdateStatus() { + + return updateStatus; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/utils/ItemStackUtils.java b/src/main/java/com/rsscripting/rswarehouse/utils/ItemStackUtils.java new file mode 100644 index 0000000..77667f9 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/utils/ItemStackUtils.java @@ -0,0 +1,543 @@ +package com.rsscripting.rswarehouse.utils; + +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.block.ShulkerBox; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.*; +import org.bukkit.util.io.BukkitObjectInputStream; +import org.bukkit.util.io.BukkitObjectOutputStream; + +import io.papermc.paper.datacomponent.DataComponentTypes; +import io.papermc.paper.datacomponent.item.SuspiciousStewEffects; +import io.papermc.paper.potion.SuspiciousEffectEntry; +import net.kyori.adventure.text.Component; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.Base64; +import java.util.List; + +public class ItemStackUtils { + + public static String serialize( + ItemStack item + ) { + + ItemStack serializedItem = + item.clone(); + + serializedItem.setAmount( + 1 + ); + + try { + + ByteArrayOutputStream outputStream = + new ByteArrayOutputStream(); + + BukkitObjectOutputStream dataOutput = + new BukkitObjectOutputStream( + outputStream + ); + + dataOutput.writeObject( + serializedItem + ); + + dataOutput.close(); + + return Base64.getEncoder() + .encodeToString( + outputStream.toByteArray() + ); + + } + + catch (Exception e) { + + return null; + + } + + } + public static ItemStack deserialize( + String data + ) { + + try { + + byte[] bytes = + Base64.getDecoder() + .decode( + data + ); + + ByteArrayInputStream inputStream = + new ByteArrayInputStream( + bytes + ); + + BukkitObjectInputStream dataInput = + new BukkitObjectInputStream( + inputStream + ); + + ItemStack item = + (ItemStack) dataInput.readObject(); + + dataInput.close(); + + return item; + + } + + catch (Exception e) { + + e.printStackTrace(); + + return null; + + } + + } + + public static ItemStack removeDamage( + ItemStack item + ) { + + ItemStack copy = + item.clone(); + + if ( + copy.hasItemMeta() + && copy.getItemMeta() + instanceof Damageable damageable + ) { + + damageable.setDamage( + 0 + ); + + copy.setItemMeta( + damageable + ); + + } + + return copy; + + } + + public static ItemStack removeEnchantments( + ItemStack item + ) { + + ItemStack cleanItem = + item.clone(); + + ItemMeta meta = + cleanItem.getItemMeta(); + + if (meta == null) { + + return cleanItem; + + } + + List enchantments = + new ArrayList<>( + meta.getEnchants().keySet() + ); + + for (Enchantment enchantment : enchantments) { + + meta.removeEnchant( + enchantment + ); + + } + + if (meta.hasEnchants()) { + + Bukkit.getLogger().warning( + "Enchantments still remain after removeEnchantments(): " + + meta.getEnchants() + ); + + } + + if (meta instanceof Repairable repairable) { + + repairable.setRepairCost( + 0 + ); + + } + + cleanItem.setItemMeta( + meta + ); + + return cleanItem; + + } + + public static ItemStack removeStoredContents( + ItemStack item + ) { + + ItemStack copy = + item.clone(); + + ItemMeta meta = + copy.getItemMeta(); + + if (meta == null) { + + return copy; + + } + + /* + |-------------------------------------------------------------------------- + | SHULKER BOXES + |-------------------------------------------------------------------------- + */ + + if ( + meta instanceof BlockStateMeta blockStateMeta + ) { + + if ( + blockStateMeta.getBlockState() + instanceof ShulkerBox shulkerBox + ) { + + return new ItemStack( + item.getType() + ); + + } + + } + +/* +|-------------------------------------------------------------------------- +| BUNDLES +|-------------------------------------------------------------------------- +*/ + + if (meta instanceof BundleMeta) { + + return new ItemStack( + item.getType() + ); + + } + + return copy; + + } + + public static ItemStack createBaseItem( + ItemStack item + ) { + + ItemStack base = + removeDamage(item); + + base = + removeEnchantments(base); + + base = + removeStoredContents(base); + + base = + normalizeSpecialItems(base); + + return base; + + } + + public static ItemStack normalizeSpecialItems( + ItemStack item + ) { + + ItemStack copy = item.clone(); + + switch (copy.getType()) { + + case SUSPICIOUS_STEW -> { + + SuspiciousStewEffects stewEffects = + copy.getData(DataComponentTypes.SUSPICIOUS_STEW_EFFECTS); + + if (stewEffects == null || stewEffects.effects().isEmpty()) { + return copy; + } + + List names = new ArrayList<>(); + + for (SuspiciousEffectEntry entry : stewEffects.effects()) { + + String effectName = + entry.effect() + .key() + .value(); + + effectName = effectName.replace('_', ' '); + + StringBuilder pretty = new StringBuilder(); + + for (String word : effectName.split(" ")) { + + if (!pretty.isEmpty()) { + pretty.append(' '); + } + + pretty.append(Character.toUpperCase(word.charAt(0))); + + if (word.length() > 1) { + pretty.append(word.substring(1)); + } + } + + names.add(pretty.toString()); + } + + } + + default -> { + } + } + + return copy; + + } + + public static ItemStack createNavigationItem( + ItemStack original + ) { + + if (original == null) { + + return null; + + } + + /* + * Create a PAPER that will display another item's model. + */ + + ItemStack item = + new ItemStack( + Material.PAPER + ); + + ItemMeta originalMeta = + original.getItemMeta(); + + ItemMeta meta = + item.getItemMeta(); + + if ( + originalMeta == null + || + meta == null + ) { + + return item; + + } + + /* + * Use the vanilla model that matches the original material. + */ + + meta.setItemModel( + org.bukkit.NamespacedKey.minecraft( + original.getType() + .name() + .toLowerCase() + ) + ); + + /* + * Hide everything we don't want. + */ + + meta.addItemFlags( + ItemFlag.HIDE_ATTRIBUTES, + ItemFlag.HIDE_ARMOR_TRIM, + ItemFlag.HIDE_DESTROYS, + ItemFlag.HIDE_DYE, + ItemFlag.HIDE_ENCHANTS, + ItemFlag.HIDE_PLACED_ON, + ItemFlag.HIDE_STORED_ENCHANTS, + ItemFlag.HIDE_UNBREAKABLE, + ItemFlag.HIDE_ADDITIONAL_TOOLTIP + ); + + /* + * Preserve the display name. + */ + + if (originalMeta.hasDisplayName()) { + + meta.displayName( + originalMeta.displayName() + ); + + } + + item.setItemMeta( + meta + ); + + return item; + + } + + public static boolean hasStoredContents( + ItemStack item + ) { + + if (item == null) { + + return false; + + } + + ItemMeta meta = + item.getItemMeta(); + + if (meta == null) { + + return false; + + } + + /* + |-------------------------------------------------------------------------- + | SHULKER BOXES + |-------------------------------------------------------------------------- + */ + + if (meta instanceof BlockStateMeta blockStateMeta) { + + if (blockStateMeta.getBlockState() instanceof ShulkerBox shulkerBox) { + + return !shulkerBox + .getInventory() + .isEmpty(); + + } + + } + +/* +|-------------------------------------------------------------------------- +| BUNDLES +|-------------------------------------------------------------------------- +*/ + + if (meta instanceof BundleMeta bundleMeta) { + + return bundleMeta.hasItems(); + + } + + return false; + + } + + public static List getSpecialItemLore( + ItemStack item + ) { + + List lore = + new ArrayList<>(); + + if (item == null) { + return lore; + } + + switch (item.getType()) { + + case SUSPICIOUS_STEW -> { + + SuspiciousStewEffects stewEffects = + item.getData( + DataComponentTypes.SUSPICIOUS_STEW_EFFECTS + ); + + if ( + stewEffects == null + || + stewEffects.effects().isEmpty() + ) { + return lore; + } + + lore.add(Component.empty()); + + lore.add( + Component.text("Effects:") + .color(NamedTextColor.GOLD) + ); + + for (SuspiciousEffectEntry entry : stewEffects.effects()) { + + String effectName = + entry.effect() + .key() + .value(); + + effectName = + effectName.replace('_', ' '); + + StringBuilder pretty = + new StringBuilder(); + + for (String word : effectName.split(" ")) { + + if (!pretty.isEmpty()) { + pretty.append(' '); + } + + pretty.append( + Character.toUpperCase( + word.charAt(0) + ) + ); + + if (word.length() > 1) { + pretty.append( + word.substring(1) + ); + } + } + + lore.add( + Component.text( + "• " + pretty + ).color( + NamedTextColor.GRAY + ) + ); + } + } + + default -> { + } + } + + return lore; + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/utils/MenuAutoCenterAndPagenation.java b/src/main/java/com/rsscripting/rswarehouse/utils/MenuAutoCenterAndPagenation.java new file mode 100644 index 0000000..9b376f9 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/utils/MenuAutoCenterAndPagenation.java @@ -0,0 +1,80 @@ +package com.rsscripting.rswarehouse.utils; + +import java.util.ArrayList; +import java.util.List; + +public class MenuAutoCenterAndPagenation { + + public static List getCenteredRowSlots( + int itemsThisRow + ) { + + List rowSlots = + new ArrayList<>(); + + if (itemsThisRow % 2 == 0) { + + switch (itemsThisRow) { + + case 2 -> + rowSlots = List.of( + 3, + 5 + ); + + case 4 -> + rowSlots = List.of( + 2, + 3, + 5, + 6 + ); + + case 6 -> + rowSlots = List.of( + 1, + 2, + 3, + 5, + 6, + 7 + ); + + case 8 -> + rowSlots = List.of( + 0, + 1, + 2, + 3, + 5, + 6, + 7, + 8 + ); + + } + + } + + else { + + int startSlot = + (9 - itemsThisRow) / 2; + + for (int i = 0; + i < itemsThisRow; + i++) { + + rowSlots.add( + startSlot + i + ); + + } + + } + + return rowSlots; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/utils/RSMenuUtils.java b/src/main/java/com/rsscripting/rswarehouse/utils/RSMenuUtils.java new file mode 100644 index 0000000..93a8015 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/utils/RSMenuUtils.java @@ -0,0 +1,165 @@ +package com.rsscripting.rswarehouse.utils; + +import com.rsscripting.rswarehouse.constants.RSConstants; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import net.kyori.adventure.text.Component; + +import java.util.List; + +public class RSMenuUtils { + + /* + |-------------------------------------------------------------------------- + | CREATE FILLER PANE + |-------------------------------------------------------------------------- + */ + + public static ItemStack createFillerPane() { + + ItemStack item = + new ItemStack( + RSConstants.MENU_FILLER_MATERIAL + ); + + ItemMeta meta = + item.getItemMeta(); + + meta.setHideTooltip(true); + item.setItemMeta(meta); + + + if (meta != null) { + + meta.displayName( + Component.empty() + ); + + item.setItemMeta(meta); + + } + + return item; + + } + + /* + |-------------------------------------------------------------------------- + | CREATE MENU ITEM + |-------------------------------------------------------------------------- + */ + + public static ItemStack createMenuItem( + + Material material, + + String name + + ) { + + ItemStack item = + new ItemStack(material); + + ItemMeta meta = + item.getItemMeta(); + + if (meta != null) { + + meta.displayName( + Component.text( + name + ) + ); + + item.setItemMeta(meta); + + } + + return item; + + } + + /* +|-------------------------------------------------------------------------- +| CREATE MENU ITEM FROM ITEMSTACK +|-------------------------------------------------------------------------- +*/ + + public static ItemStack createMenuItem( + + ItemStack item, + + String name + + ) { + + ItemStack clone = + item.clone(); + + ItemMeta meta = + clone.getItemMeta(); + + if (meta != null) { + + meta.displayName( + Component.text( + name + ) + ); + + clone.setItemMeta( + meta + ); + + } + + return clone; + + } + + /* + |-------------------------------------------------------------------------- + | CREATE MENU ITEM WITH LORE + |-------------------------------------------------------------------------- + */ + + public static ItemStack createMenuItemWithLore( + + Material material, + + String name, + + List lore + + ) { + + ItemStack item = + new ItemStack(material); + + ItemMeta meta = + item.getItemMeta(); + + if (meta != null) { + + meta.displayName( + Component.text( + name + ) + ); + + meta.lore( + lore.stream() + .map(Component::text) + .toList() + ); + + item.setItemMeta(meta); + + } + + return item; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/utils/RSMessageUtils.java b/src/main/java/com/rsscripting/rswarehouse/utils/RSMessageUtils.java new file mode 100644 index 0000000..0a7d81b --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/utils/RSMessageUtils.java @@ -0,0 +1,170 @@ +package com.rsscripting.rswarehouse.utils; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.entity.Player; + +public class RSMessageUtils { + + /* + |-------------------------------------------------------------------------- + | PREFIX + |-------------------------------------------------------------------------- + */ + + private static final Component PREFIX = + + Component.text("[") + .color(NamedTextColor.GRAY) + + .append( + Component.text( + "RS-Warehouse" + ).color( + NamedTextColor.RED + ) + ) + + .append( + Component.text("] ") + .color( + NamedTextColor.GRAY + ) + ); + + /* + |-------------------------------------------------------------------------- + | SUCCESS + |-------------------------------------------------------------------------- + */ + + public static void success( + Player player, + String message + ) { + + player.sendMessage( + + PREFIX.append( + + Component.text( + message + ).color( + NamedTextColor.GREEN + ) + + ) + + ); + + } + + /* + |-------------------------------------------------------------------------- + | WARNING + |-------------------------------------------------------------------------- + */ + + public static void warning( + Player player, + String message + ) { + + player.sendMessage( + + PREFIX.append( + + Component.text( + message + ).color( + NamedTextColor.YELLOW + ) + + ) + + ); + + } + + /* + |-------------------------------------------------------------------------- + | ERROR + |-------------------------------------------------------------------------- + */ + + public static void error( + Player player, + String message + ) { + + player.sendMessage( + + PREFIX.append( + + Component.text( + message + ).color( + NamedTextColor.RED + ) + + ) + + ); + + } + + /* + |-------------------------------------------------------------------------- + | INFO + |-------------------------------------------------------------------------- + */ + + public static void info( + Player player, + String message + ) { + + player.sendMessage( + + PREFIX.append( + + Component.text( + message + ).color( + NamedTextColor.AQUA + ) + + ) + + ); + + } + + /* + |-------------------------------------------------------------------------- + | ADMIN + |-------------------------------------------------------------------------- + */ + + public static void admin( + Player player, + String message + ) { + + player.sendMessage( + + PREFIX.append( + + Component.text( + message + ).color( + NamedTextColor.GOLD + ) + + ) + + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/utils/VersionUtils.java b/src/main/java/com/rsscripting/rswarehouse/utils/VersionUtils.java new file mode 100644 index 0000000..38e3704 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/utils/VersionUtils.java @@ -0,0 +1,20 @@ +package com.rsscripting.rswarehouse.utils; + +import com.rsscripting.rswarehouse.RSWarehouse; + +public class VersionUtils { + + /* + |-------------------------------------------------------------------------- + | GET INSTALLED VERSION + |-------------------------------------------------------------------------- + */ + + public static String getVersion() { + + return RSWarehouse.getInstance() + .getDescription() + .getVersion(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/variants/0 b/src/main/java/com/rsscripting/rswarehouse/variants/0 new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/rsscripting/rswarehouse/variants/dao/DamagedVariantsDAO.java b/src/main/java/com/rsscripting/rswarehouse/variants/dao/DamagedVariantsDAO.java new file mode 100644 index 0000000..1a2b6e3 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/variants/dao/DamagedVariantsDAO.java @@ -0,0 +1,432 @@ +package com.rsscripting.rswarehouse.variants.dao; + +import com.rsscripting.rswarehouse.database.DatabaseManager; +import com.rsscripting.rswarehouse.model.DamagedVariant; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.Damageable; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; + +public class DamagedVariantsDAO { + + public static void createDamagedVariant( + int parentInventoryId, + ItemStack item + ) { + + Integer variantId = + findDamagedVariantId( + parentInventoryId, + item + ); + + if (variantId != null) { + + updateDamagedVariantQuantity( + variantId, + item.getAmount() + ); + + return; + + } + + String serializedItem = + ItemStackUtils.serialize( + item + ); + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + INSERT INTO damaged_variants ( + parent_inventory_id, + serialized_item, + quantity, + lore + ) + VALUES (?, ?, ?, ?) + + """ + ); + + statement.setInt( + 1, + parentInventoryId + ); + + statement.setString( + 2, + serializedItem + ); + + statement.setInt( + 3, + item.getAmount() + ); + + statement.setString( + 4, + null + ); + + statement.executeUpdate(); + + } catch (Exception e) { + + e.printStackTrace(); + + } + + } + + private static Integer findDamagedVariantId( + int parentInventoryId, + ItemStack item + ) { + + String serializedItem = + ItemStackUtils.serialize( + item + ); + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + SELECT id + FROM damaged_variants + WHERE parent_inventory_id = ? + AND serialized_item = ? + + """ + ); + + statement.setInt( + 1, + parentInventoryId + ); + + statement.setString( + 2, + serializedItem + ); + + ResultSet resultSet = + statement.executeQuery(); + + if (resultSet.next()) { + + return resultSet.getInt( + "id" + ); + + } + + } catch (Exception e) { + + e.printStackTrace(); + + } + + return null; + + } + + public static boolean hasDamagedVariants( + int parentInventoryId + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + SELECT 1 + FROM damaged_variants + WHERE parent_inventory_id = ? + AND quantity > 0 + LIMIT 1 + + """ + ); + + statement.setInt( + 1, + parentInventoryId + ); + + return statement.executeQuery().next(); + + } catch (Exception e) { + + e.printStackTrace(); + + } + + return false; + + } + + private static void updateDamagedVariantQuantity( + int variantId, + int amount + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + UPDATE damaged_variants + SET quantity = quantity + ? + WHERE id = ? + + """ + ); + + statement.setInt( + 1, + amount + ); + + statement.setInt( + 2, + variantId + ); + + statement.executeUpdate(); + + } catch (Exception e) { + + e.printStackTrace(); + + } + + } + + public static DamagedVariant getDamagedVariantById( + int variantId + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + SELECT * + FROM damaged_variants + WHERE id = ? + + """ + ); + + statement.setInt( + 1, + variantId + ); + + ResultSet resultSet = + statement.executeQuery(); + + if (resultSet.next()) { + + return new DamagedVariant( + resultSet.getInt( + "id" + ), + resultSet.getInt( + "parent_inventory_id" + ), + resultSet.getString( + "serialized_item" + ), + resultSet.getLong( + "quantity" + ), + resultSet.getString( + "lore" + ) + ); + + } + + } catch (Exception e) { + + e.printStackTrace(); + + } + + return null; + + } + + + + public static void removeDamagedVariantQuantity( + int variantId, + int amount + ) { + + updateDamagedVariantQuantity( + variantId, + -amount + ); + + } + + public static void addDamagedVariantQuantity( + int variantId, + int amount + ) { + + updateDamagedVariantQuantity( + variantId, + amount + ); + + } + + public static List getDamagedVariants( + int parentInventoryId + ) { + + List variants = + new ArrayList<>(); + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + SELECT * + FROM damaged_variants + WHERE parent_inventory_id = ? + AND quantity > 0 + + """ + ); + + statement.setInt( + 1, + parentInventoryId + ); + + ResultSet resultSet = + statement.executeQuery(); + + while (resultSet.next()) { + + variants.add( + new DamagedVariant( + resultSet.getInt( + "id" + ), + resultSet.getInt( + "parent_inventory_id" + ), + resultSet.getString( + "serialized_item" + ), + resultSet.getLong( + "quantity" + ), + resultSet.getString( + "lore" + ) + ) + ); + + } + + } catch (Exception e) { + + e.printStackTrace(); + + } + + variants.sort( + (a, b) -> { + + ItemStack itemA = + ItemStackUtils.deserialize( + a.serializedItem() + ); + + ItemStack itemB = + ItemStackUtils.deserialize( + b.serializedItem() + ); + + if ( + itemA == null + || itemB == null + ) { + + return 0; + + } + + Damageable damageA = + (Damageable) itemA.getItemMeta(); + + Damageable damageB = + (Damageable) itemB.getItemMeta(); + + return Integer.compare( + damageA.getDamage(), + damageB.getDamage() + ); + + } + ); + + return variants; + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/variants/dao/EnchantedVariantsDAO.java b/src/main/java/com/rsscripting/rswarehouse/variants/dao/EnchantedVariantsDAO.java new file mode 100644 index 0000000..cbe98ab --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/variants/dao/EnchantedVariantsDAO.java @@ -0,0 +1,393 @@ +package com.rsscripting.rswarehouse.variants.dao; + +import com.rsscripting.rswarehouse.database.DatabaseManager; +import com.rsscripting.rswarehouse.model.EnchantedVariant; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import org.bukkit.inventory.ItemStack; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; + +public class EnchantedVariantsDAO { + + public static boolean hasEnchantedVariants( + int parentInventoryId + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + SELECT 1 + FROM enchanted_variants + WHERE parent_inventory_id = ? + AND quantity > 0 + LIMIT 1 + + """ + ); + + statement.setInt( + 1, + parentInventoryId + ); + + return statement.executeQuery().next(); + + } catch (Exception e) { + + e.printStackTrace(); + + } + + return false; + + } + + private static Integer findEnchantedVariantId( + int parentInventoryId, + ItemStack item + ) { + + String serializedItem = + ItemStackUtils.serialize( + item + ); + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + SELECT id + FROM enchanted_variants + WHERE parent_inventory_id = ? + AND serialized_item = ? + + """ + ); + + statement.setInt( + 1, + parentInventoryId + ); + + statement.setString( + 2, + serializedItem + ); + + ResultSet resultSet = + statement.executeQuery(); + + if (resultSet.next()) { + + return resultSet.getInt( + "id" + ); + + } + + } catch (Exception e) { + + e.printStackTrace(); + + } + + return null; + + } + + public static void createEnchantedVariant( + int parentInventoryId, + ItemStack item + ) { + + Integer variantId = + findEnchantedVariantId( + parentInventoryId, + item + ); + + if (variantId != null) { + + updateEnchantedVariantQuantity( + variantId, + item.getAmount() + ); + + return; + + } + + String serializedItem = + ItemStackUtils.serialize( + item + ); + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + INSERT INTO enchanted_variants ( + parent_inventory_id, + serialized_item, + quantity, + lore + ) + VALUES (?, ?, ?, ?) + + """ + ); + + statement.setInt( + 1, + parentInventoryId + ); + + statement.setString( + 2, + serializedItem + ); + + statement.setInt( + 3, + item.getAmount() + ); + + statement.setString( + 4, + null + ); + + statement.executeUpdate(); + + } catch (Exception e) { + + e.printStackTrace(); + + } + + } + + public static List getEnchantedVariants( + int parentInventoryId + ) { + + List variants = + new ArrayList<>(); + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + SELECT * + FROM enchanted_variants + WHERE parent_inventory_id = ? + AND quantity > 0 + + """ + ); + + statement.setInt( + 1, + parentInventoryId + ); + + ResultSet resultSet = + statement.executeQuery(); + + while (resultSet.next()) { + + variants.add( + new EnchantedVariant( + resultSet.getInt( + "id" + ), + resultSet.getInt( + "parent_inventory_id" + ), + resultSet.getString( + "serialized_item" + ), + resultSet.getLong( + "quantity" + ), + resultSet.getString( + "lore" + ) + ) + ); + + } + + } catch (Exception e) { + + e.printStackTrace(); + + } + + return variants; + + } + + private static void updateEnchantedVariantQuantity( + int variantId, + int amount + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + UPDATE enchanted_variants + SET quantity = quantity + ? + WHERE id = ? + + """ + ); + + statement.setInt( + 1, + amount + ); + + statement.setInt( + 2, + variantId + ); + + statement.executeUpdate(); + + } catch (Exception e) { + + e.printStackTrace(); + + } + + } + + public static EnchantedVariant getEnchantedVariantById( + int variantId + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + SELECT * + FROM enchanted_variants + WHERE id = ? + + """ + ); + + statement.setInt( + 1, + variantId + ); + + ResultSet resultSet = + statement.executeQuery(); + + if (resultSet.next()) { + + return new EnchantedVariant( + resultSet.getInt( + "id" + ), + resultSet.getInt( + "parent_inventory_id" + ), + resultSet.getString( + "serialized_item" + ), + resultSet.getLong( + "quantity" + ), + resultSet.getString( + "lore" + ) + ); + + } + + } catch (Exception e) { + + e.printStackTrace(); + + } + + return null; + + } + + public static void addEnchantedVariantQuantity( + int variantId, + int amount + ) { + + updateEnchantedVariantQuantity( + variantId, + amount + ); + + } + + public static void removeEnchantedVariantQuantity( + int variantId, + int amount + ) { + + updateEnchantedVariantQuantity( + variantId, + -amount + ); + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/variants/dao/PartiallyFilledVariantsDAO.java b/src/main/java/com/rsscripting/rswarehouse/variants/dao/PartiallyFilledVariantsDAO.java new file mode 100644 index 0000000..4bd2684 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/variants/dao/PartiallyFilledVariantsDAO.java @@ -0,0 +1,394 @@ +package com.rsscripting.rswarehouse.variants.dao; + +import com.rsscripting.rswarehouse.database.DatabaseManager; +import com.rsscripting.rswarehouse.model.PartiallyFilledVariant; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import org.bukkit.inventory.ItemStack; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; + + +public class PartiallyFilledVariantsDAO { + + public static List getPartiallyFilledVariants( + int parentInventoryId + ) { + + List variants = + new ArrayList<>(); + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + SELECT * + FROM partially_filled_variants + WHERE parent_inventory_id = ? + AND quantity > 0 + + """ + ); + + statement.setInt( + 1, + parentInventoryId + ); + + ResultSet resultSet = + statement.executeQuery(); + + while (resultSet.next()) { + + variants.add( + new PartiallyFilledVariant( + resultSet.getInt( + "id" + ), + resultSet.getInt( + "parent_inventory_id" + ), + resultSet.getString( + "serialized_item" + ), + resultSet.getLong( + "quantity" + ), + resultSet.getString( + "lore" + ) + ) + ); + + } + + } catch (Exception e) { + + e.printStackTrace(); + + } + + return variants; + + } + + public static PartiallyFilledVariant getPartiallyFilledVariantById( + int variantId + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + SELECT * + FROM partially_filled_variants + WHERE id = ? + + """ + ); + + statement.setInt( + 1, + variantId + ); + + ResultSet resultSet = + statement.executeQuery(); + + if (resultSet.next()) { + + return new PartiallyFilledVariant( + resultSet.getInt( + "id" + ), + resultSet.getInt( + "parent_inventory_id" + ), + resultSet.getString( + "serialized_item" + ), + resultSet.getLong( + "quantity" + ), + resultSet.getString( + "lore" + ) + ); + + } + + } catch (Exception e) { + + e.printStackTrace(); + + } + + return null; + + } + + public static void removePartiallyFilledVariantQuantity( + int variantId, + int amount + ) { + + updatePartiallyFilledVariantQuantity( + variantId, + -amount + ); + + } + + public static void addPartiallyFilledVariantQuantity( + int variantId, + int amount + ) { + + updatePartiallyFilledVariantQuantity( + variantId, + amount + ); + + } + + private static void updatePartiallyFilledVariantQuantity( + int variantId, + int amount + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + UPDATE partially_filled_variants + SET quantity = quantity + ? + WHERE id = ? + + """ + ); + + statement.setInt( + 1, + amount + ); + + statement.setInt( + 2, + variantId + ); + + statement.executeUpdate(); + + } catch (Exception e) { + + e.printStackTrace(); + + } + + } + + private static Integer findPartiallyFilledVariantId( + int parentInventoryId, + ItemStack item + ) { + + String serializedItem = + ItemStackUtils.serialize( + item + ); + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + SELECT id + FROM partially_filled_variants + WHERE parent_inventory_id = ? + AND serialized_item = ? + + """ + ); + + statement.setInt( + 1, + parentInventoryId + ); + + statement.setString( + 2, + serializedItem + ); + + ResultSet resultSet = + statement.executeQuery(); + + if (resultSet.next()) { + + return resultSet.getInt( + "id" + ); + + } + + } catch (Exception e) { + + e.printStackTrace(); + + } + + return null; + + } + + public static void createPartiallyFilledVariant( + int parentInventoryId, + ItemStack item + ) { + + Integer variantId = + findPartiallyFilledVariantId( + parentInventoryId, + item + ); + + if (variantId != null) { + + updatePartiallyFilledVariantQuantity( + variantId, + item.getAmount() + ); + + return; + + } + + String serializedItem = + ItemStackUtils.serialize( + item + ); + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + INSERT INTO partially_filled_variants ( + parent_inventory_id, + serialized_item, + quantity, + lore + ) + VALUES (?, ?, ?, ?) + + """ + ); + + statement.setInt( + 1, + parentInventoryId + ); + + statement.setString( + 2, + serializedItem + ); + + statement.setInt( + 3, + item.getAmount() + ); + + statement.setString( + 4, + null + ); + + statement.executeUpdate(); + + } catch (Exception e) { + + e.printStackTrace(); + + } + + } + + public static boolean hasPartiallyFilledVariants( + int parentInventoryId + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection() + + ) { + + PreparedStatement statement = + connection.prepareStatement( + """ + + SELECT 1 + FROM partially_filled_variants + WHERE parent_inventory_id = ? + AND quantity > 0 + LIMIT 1 + + """ + ); + + statement.setInt( + 1, + parentInventoryId + ); + + return statement.executeQuery().next(); + + } catch (Exception e) { + + e.printStackTrace(); + + } + + return false; + + } + +} diff --git a/src/main/java/com/rsscripting/rswarehouse/variantsdamaged/DamagedVariantsMenu.java b/src/main/java/com/rsscripting/rswarehouse/variantsdamaged/DamagedVariantsMenu.java new file mode 100644 index 0000000..fdb1e88 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/variantsdamaged/DamagedVariantsMenu.java @@ -0,0 +1,179 @@ +package com.rsscripting.rswarehouse.variantsdamaged; + +import com.rsscripting.rswarehouse.variants.dao.DamagedVariantsDAO; +import com.rsscripting.rswarehouse.model.DamagedVariant; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import com.rsscripting.rswarehouse.constants.RSKeys; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.Damageable; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +import java.util.ArrayList; +import java.util.List; + +public class DamagedVariantsMenu { + + public static void open( + Player player, + int itemId, + int parentInventoryId + ) { + + Inventory menu = + Bukkit.createInventory( + new RSMenuHolder( + "DAMAGED_VARIANTS:" + itemId + ), + 54, + Component.text( + "Damaged Variants" + ).color( + NamedTextColor.BLUE + ) + ); + + ItemStack filler = + RSMenuUtils.createFillerPane(); + + for (int slot = 0; slot <= 8; slot++) { + + menu.setItem( + slot, + filler + ); + + } + + for (int slot = 45; slot <= 53; slot++) { + + menu.setItem( + slot, + filler + ); + + } + + menu.setItem( + 4, + RSMenuUtils.createMenuItem( + Material.OAK_DOOR, + "§a Back" + ) + ); + + List variants = + DamagedVariantsDAO.getDamagedVariants( + parentInventoryId + ); + + int slot = 9; + + for ( + DamagedVariant variant + : variants + ) { + + ItemStack item = + ItemStackUtils.deserialize( + variant.serializedItem() + ); + + if (item == null) { + + continue; + + } + + if ( + item.getItemMeta() + instanceof Damageable damageable + ) { + + ItemMeta meta = + item.getItemMeta(); + + int maxDurability = + item.getType() + .getMaxDurability(); + + int remainingDurability = + maxDurability + - damageable.getDamage(); + + List lore = + new ArrayList<>(); + + lore.add( + Component.text( + "Durability: " + + remainingDurability + + " / " + + maxDurability + ) + ); + + lore.add( + Component.text( + "Quantity: " + + String.format( + "%,d", + variant.quantity() + ) + ) + ); + + meta.lore( + lore + ); + + item.setItemMeta( + meta + ); + + } + + ItemMeta meta = + item.getItemMeta(); + + meta.getPersistentDataContainer() + .set( + RSKeys.DAMAGED_VARIANT_ID, + PersistentDataType.INTEGER, + variant.id() + ); + + item.setItemMeta( + meta + ); + + menu.setItem( + slot, + item + ); + + slot++; + + if (slot >= 45) { + + break; + + } + + } + + player.openInventory( + menu + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/variantsdamaged/DamagedVariantsMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/variantsdamaged/DamagedVariantsMenuListener.java new file mode 100644 index 0000000..90787d4 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/variantsdamaged/DamagedVariantsMenuListener.java @@ -0,0 +1,149 @@ +package com.rsscripting.rswarehouse.variantsdamaged; + +import com.rsscripting.rswarehouse.item.TransactionAmountMenu; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.constants.RSKeys; +import com.rsscripting.rswarehouse.session.VariantType; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import com.rsscripting.rswarehouse.session.TransactionSession; + +public class DamagedVariantsMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if ( + !(event.getWhoClicked() + instanceof Player player) + ) { + + return; + + } + + if ( + !(event.getInventory() + .getHolder() + instanceof RSMenuHolder holder) + ) { + + return; + + } + + if ( + !holder.getMenuId() + .startsWith( + "DAMAGED_VARIANTS:" + ) + ) { + + return; + + } + + event.setCancelled( + true + ); + + int itemId = + Integer.parseInt( + holder.getMenuId() + .split(":")[1] + ); + +/* +|-------------------------------------------------------------------------- +| BACK +|-------------------------------------------------------------------------- +*/ + + if (event.getSlot() == 4) { + + TransactionAmountMenu.open( + player, + itemId, + 0 + ); + + return; + + } + +/* +|-------------------------------------------------------------------------- +| DAMAGED VARIANT +|-------------------------------------------------------------------------- +*/ + + ItemStack clickedItem = + event.getCurrentItem(); + + if (clickedItem == null) { + + return; + + } + + ItemMeta meta = + clickedItem.getItemMeta(); + + if (meta == null) { + + return; + + } + + Integer damagedVariantId = + meta.getPersistentDataContainer() + .get( + RSKeys.DAMAGED_VARIANT_ID, + PersistentDataType.INTEGER + ); + + if (damagedVariantId == null) { + + return; + + } + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + TransactionSession transactionSession = + new TransactionSession(itemId); + + transactionSession.setVariantType( + VariantType.DAMAGED + ); + + transactionSession.setVariantRecordId( + damagedVariantId + ); + + session.setItemActionSession( + transactionSession + ); + + DamagedVariantsTransactionMenu.open( + player, + damagedVariantId, + 0 + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/variantsdamaged/DamagedVariantsTransactionMenu.java b/src/main/java/com/rsscripting/rswarehouse/variantsdamaged/DamagedVariantsTransactionMenu.java new file mode 100644 index 0000000..329c887 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/variantsdamaged/DamagedVariantsTransactionMenu.java @@ -0,0 +1,321 @@ +package com.rsscripting.rswarehouse.variantsdamaged; + +import com.rsscripting.rswarehouse.variants.dao.DamagedVariantsDAO; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import com.rsscripting.rswarehouse.model.DamagedVariant; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.List; + +public class DamagedVariantsTransactionMenu { + + public static void open( + Player player, + int damagedVariantId, + int amount + ) { + + String title; + + if (amount > 0) { + + title = + "Deposit: " + + String.format( + "%,d", + amount + ); + + } + + else if (amount < 0) { + + title = + "Withdraw: " + + String.format( + "%,d", + Math.abs( + amount + ) + ); + + } + + else { + + title = + "Amount: 0"; + + } + + Inventory menu = + Bukkit.createInventory( + new RSMenuHolder( + "DAMAGED_ITEM_ACTION" + ), + 27, + Component.text( + title + ).color( + NamedTextColor.BLUE + ) + ); + + /* + |-------------------------------------------------------------------------- + | FILLER + |-------------------------------------------------------------------------- + */ + + for (int i = 0; i < menu.getSize(); i++) { + + menu.setItem( + i, + RSMenuUtils.createFillerPane() + ); + + } + +/* +|-------------------------------------------------------------------------- +| CENTER ITEM +|-------------------------------------------------------------------------- +*/ + + DamagedVariant damagedVariant = + DamagedVariantsDAO.getDamagedVariantById( + damagedVariantId + ); + + if (damagedVariant != null) { + + ItemStack item = + ItemStackUtils.deserialize( + damagedVariant.serializedItem() + ); + + if (item != null) { + + ItemMeta meta = + item.getItemMeta(); + + if (meta != null) { + + long playerHas = + getPlayerItemCount( + player, + item + ); + + meta.lore( + List.of( + Component.text( + "In Stock: " + + String.format( + "%,d", + damagedVariant.quantity() + ) + ).color( + NamedTextColor.LIGHT_PURPLE + ), + + Component.text( + "Player Has: " + + String.format( + "%,d", + playerHas + ) + ).color( + NamedTextColor.GREEN + ), + + Component.text( + " " + ), + + Component.text( + "Click to complete transaction." + ).color( + NamedTextColor.YELLOW + ) + ) + ); + + item.setItemMeta( + meta + ); + + } + + menu.setItem( + 13, + item + ); + + } + + } + + /* + |-------------------------------------------------------------------------- + | WITHDRAW + |-------------------------------------------------------------------------- + */ + + ItemStack subtract64 = + RSMenuUtils.createMenuItem( + Material.RED_WOOL, + "§cSubtract 64" + ); + + subtract64.setAmount( + 64 + ); + + menu.setItem( + 9, + subtract64 + ); + + ItemStack subtract16 = + RSMenuUtils.createMenuItem( + Material.RED_WOOL, + "§cSubtract 16" + ); + + subtract16.setAmount( + 16 + ); + + menu.setItem( + 10, + subtract16 + ); + + + ItemStack subtract1 = + RSMenuUtils.createMenuItem( + Material.RED_WOOL, + "§cSubtract 1" + ); + + subtract1.setAmount( + 1 + ); + + menu.setItem( + 11, + subtract1 + ); + + /* + |-------------------------------------------------------------------------- + | DEPOSIT + |-------------------------------------------------------------------------- + */ + + ItemStack add1 = + RSMenuUtils.createMenuItem( + Material.GREEN_WOOL, + "§cAdd 1" + ); + + add1.setAmount( + 1 + ); + + menu.setItem( + 15, + add1 + ); + + ItemStack add16 = + RSMenuUtils.createMenuItem( + Material.GREEN_WOOL, + "§cAdd 16" + ); + + add16.setAmount( + 16 + ); + + menu.setItem( + 16, + add16 + ); + + ItemStack add64 = + RSMenuUtils.createMenuItem( + Material.GREEN_WOOL, + "§cAdd 64" + ); + + add64.setAmount( + 64 + ); + + menu.setItem( + 17, + add64 + ); + + /* + |-------------------------------------------------------------------------- + | BACK + |-------------------------------------------------------------------------- + */ + + menu.setItem( + 4, + RSMenuUtils.createMenuItem( + Material.OAK_DOOR, + "§eReturn to main menu." + ) + ); + + player.openInventory( + menu + ); + + } + + public static long getPlayerItemCount( + Player player, + ItemStack target + ) { + + long count = 0; + + for (ItemStack item : player.getInventory().getContents()) { + + if (item == null) { + continue; + } + + if ( + item.isSimilar( + target + ) + ) { + + count += item.getAmount(); + + } + + + } + + return count; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/variantsdamaged/DamagedVariantsTransactionMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/variantsdamaged/DamagedVariantsTransactionMenuListener.java new file mode 100644 index 0000000..9bf379b --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/variantsdamaged/DamagedVariantsTransactionMenuListener.java @@ -0,0 +1,433 @@ +package com.rsscripting.rswarehouse.variantsdamaged; + +import com.rsscripting.rswarehouse.item.TransactionAmountMenu; +import com.rsscripting.rswarehouse.variants.dao.DamagedVariantsDAO; +import com.rsscripting.rswarehouse.autodeposit.autodepositdao.AutoDepositDAO; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryMenu; +import com.rsscripting.rswarehouse.model.DamagedVariant; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.item.TransactionUtils; +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import com.rsscripting.rswarehouse.session.TransactionSession; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +public class DamagedVariantsTransactionMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if ( + !(event.getWhoClicked() + instanceof Player player) + ) { + + return; + + } + + if ( + !(event.getInventory() + .getHolder() + instanceof RSMenuHolder holder) + ) { + + return; + + } + + if ( + !holder.getMenuId() + .equals( + "DAMAGED_ITEM_ACTION" + ) + ) { + + return; + + } + + event.setCancelled( + true + ); + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + TransactionSession itemSession = + session.getItemActionSession(); + + if (itemSession == null) { + + return; + + } + + int amount = + itemSession.getAmount(); + + int warehouseItemId = + itemSession.getWarehouseItemId(); + + int damagedVariantId = + itemSession.getVariantRecordId(); + + DamagedVariant damagedVariant = + DamagedVariantsDAO.getDamagedVariantById( + damagedVariantId + ); + + if (damagedVariant == null) { + + return; + + } + + if (event.getSlot() == 4) { + + TransactionAmountMenu.open( + player, + warehouseItemId, + 0 + ); + + return; + } + + if (event.getSlot() == 5) { + + player.closeInventory(); + + } + + ItemStack item = + ItemStackUtils.deserialize( + damagedVariant.serializedItem() + ); + + if (item == null) { + + return; + + } + + long playerHas = + TransactionUtils.getPlayerItemCount( + player, + item + ); + + if (event.getSlot() == 13) { + + if (amount == 0) { + + return; + + } + + if (amount > 0) { + + ItemStack depositItem = + item.clone(); + + depositItem.setAmount( + 1 + ); + + if ( + removeItems( + player, + depositItem, + amount + ) + ) { + + DamagedVariantsDAO.addDamagedVariantQuantity( + damagedVariant.id(), + amount + ); + + player.sendMessage( + "§aYou have deposited " + + amount + + " items." + ); + + itemSession.setAmount( + 0 + ); + + DamagedVariantsTransactionMenu.open( + player, + damagedVariantId, + 0 + ); + + } + + return; + + } + + else { + + int withdrawAmount = + Math.abs( + amount + ); + + ItemStack withdrawItem = + item.clone(); + + withdrawItem.setAmount( + withdrawAmount + ); + + if ( + AutoDepositDAO.shouldBlockWithdrawal( + player.getUniqueId(), + withdrawItem + ) + ) { + + RSMessageUtils.error( + player, + "Disable Auto Deposit or remove this item from your filter before withdrawing it." + ); + + return; + + } + + player.getInventory() + .addItem( + withdrawItem + ); + + DamagedVariantsDAO.removeDamagedVariantQuantity( + damagedVariant.id(), + withdrawAmount + ); + + player.sendMessage( + "§aYou have withdrawn " + + withdrawAmount + + " items." + ); + + itemSession.setAmount( + 0 + ); + + DamagedVariantsTransactionMenu.open( + player, + damagedVariantId, + 0 + ); + + } + + return; + + } + + long warehouseStock = + damagedVariant.quantity(); + + int inventoryCapacity = + getAvailableCapacity( + player, + item + ); + + long maxWithdraw = + Math.min( + warehouseStock, + inventoryCapacity + ); + + switch ( + event.getSlot() + ) { + + case 9 -> + amount -= 64; + + case 10 -> + amount -= 16; + + case 11 -> + amount -= 1; + + case 15 -> + amount += 1; + + case 16 -> + amount += 16; + + case 17 -> + amount += 64; + + default -> { + + return; + + } + + } + + if (amount > playerHas) { + + amount = + (int) playerHas; + + } + + if ( + amount < -maxWithdraw + ) + { + + amount = + (int) -maxWithdraw; + + } + + itemSession.setAmount( + amount + ); + + DamagedVariantsTransactionMenu.open( + player, + damagedVariantId, + amount + ); + + } + + private boolean removeItems( + Player player, + ItemStack target, + int amount + ) { + + int remaining = + amount; + + ItemStack[] contents = + player.getInventory() + .getContents(); + + for (int slot = 0; + slot < contents.length; + slot++) { + + ItemStack item = + contents[slot]; + + if (item == null) { + + continue; + + } + + if (!item.isSimilar(target)) { + + continue; + + } + + if ( + item.getAmount() + <= remaining + ) { + + remaining -= + item.getAmount(); + + player.getInventory() + .setItem( + slot, + null + ); + + } + + else { + + item.setAmount( + item.getAmount() + - remaining + ); + + remaining = + 0; + + } + + if (remaining <= 0) { + + return true; + + } + + } + + return false; + + } + + private int getAvailableCapacity( + Player player, + ItemStack target + ) { + + int capacity = 0; + + int maxStack = + target.getMaxStackSize(); + + for ( + ItemStack item : + player.getInventory() + .getStorageContents() + ) { + + if (item == null) { + + capacity += maxStack; + + continue; + + } + + if ( + item.isSimilar( + target + ) + ) { + + capacity += + maxStack + - item.getAmount(); + + } + + } + + return capacity; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/variantsenchanted/EnchantedVariantsMenu.java b/src/main/java/com/rsscripting/rswarehouse/variantsenchanted/EnchantedVariantsMenu.java new file mode 100644 index 0000000..5fa421f --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/variantsenchanted/EnchantedVariantsMenu.java @@ -0,0 +1,147 @@ +package com.rsscripting.rswarehouse.variantsenchanted; + +import com.rsscripting.rswarehouse.variants.dao.EnchantedVariantsDAO; +import com.rsscripting.rswarehouse.model.EnchantedVariant; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import com.rsscripting.rswarehouse.constants.RSKeys; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +import java.util.ArrayList; +import java.util.List; + +public class EnchantedVariantsMenu { + + public static void open( + Player player, + int itemId, + int parentInventoryId + ) { + + Inventory menu = + Bukkit.createInventory( + new RSMenuHolder( + "ENCHANTED_VARIANTS:" + itemId + ), + 54, + Component.text( + "Enchanted Variants" + ).color( + NamedTextColor.BLUE + ) + ); + + ItemStack filler = + RSMenuUtils.createFillerPane(); + + for (int slot = 0; slot <= 8; slot++) { + + menu.setItem( + slot, + filler + ); + + } + + for (int slot = 45; slot <= 53; slot++) { + + menu.setItem( + slot, + filler + ); + + } + + menu.setItem( + 4, + RSMenuUtils.createMenuItem( + Material.OAK_DOOR, + "§a Back" + ) + ); + + List variants = + EnchantedVariantsDAO.getEnchantedVariants( + parentInventoryId + ); + + int slot = 9; + + for ( + EnchantedVariant variant + : variants + ) { + + ItemStack item = + ItemStackUtils.deserialize( + variant.serializedItem() + ); + + if (item == null) { + + continue; + + } + + ItemMeta meta = + item.getItemMeta(); + + List lore = + new ArrayList<>(); + + lore.add( + Component.text( + "Quantity: " + + String.format( + "%,d", + variant.quantity() + ) + ) + ); + + meta.lore( + lore + ); + + meta.getPersistentDataContainer() + .set( + RSKeys.ENCHANTED_VARIANT_ID, + PersistentDataType.INTEGER, + variant.id() + ); + + item.setItemMeta( + meta + ); + + menu.setItem( + slot, + item + ); + + slot++; + + if (slot >= 45) { + + break; + + } + + } + + player.openInventory( + menu + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/variantsenchanted/EnchantedVariantsMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/variantsenchanted/EnchantedVariantsMenuListener.java new file mode 100644 index 0000000..6e2bcb4 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/variantsenchanted/EnchantedVariantsMenuListener.java @@ -0,0 +1,151 @@ +package com.rsscripting.rswarehouse.variantsenchanted; + +import com.rsscripting.rswarehouse.item.TransactionAmountMenu; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import com.rsscripting.rswarehouse.session.TransactionSession; +import com.rsscripting.rswarehouse.constants.RSKeys; +import com.rsscripting.rswarehouse.session.VariantType; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +public class EnchantedVariantsMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if ( + !(event.getWhoClicked() + instanceof Player player) + ) { + + return; + + } + + if ( + !(event.getInventory() + .getHolder() + instanceof RSMenuHolder holder) + ) { + + return; + + } + + if ( + !holder.getMenuId() + .startsWith( + "ENCHANTED_VARIANTS:" + ) + ) { + + return; + + } + + event.setCancelled( + true + ); + + int itemId = + Integer.parseInt( + holder.getMenuId() + .split( + ":" + )[1] + ); + +/* +|-------------------------------------------------------------------------- +| BACK +|-------------------------------------------------------------------------- +*/ + + if (event.getSlot() == 4) { + + TransactionAmountMenu.open( + player, + itemId, + 0 + ); + + return; + + } + +/* +|-------------------------------------------------------------------------- +| ENCHANTED VARIANT +|-------------------------------------------------------------------------- +*/ + + ItemStack clickedItem = + event.getCurrentItem(); + + if (clickedItem == null) { + + return; + + } + + ItemMeta meta = + clickedItem.getItemMeta(); + + if (meta == null) { + + return; + + } + + Integer enchantedVariantId = + meta.getPersistentDataContainer() + .get( + RSKeys.ENCHANTED_VARIANT_ID, + PersistentDataType.INTEGER + ); + + if (enchantedVariantId == null) { + + return; + + } + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + TransactionSession transactionSession = + new TransactionSession(itemId); + + transactionSession.setVariantType( + VariantType.ENCHANTED + ); + + transactionSession.setVariantRecordId( + enchantedVariantId + ); + + session.setItemActionSession( + transactionSession + ); + + EnchantedVariantsTransactionMenu.open( + player, + enchantedVariantId, + 0 + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/variantsenchanted/EnchantedVariantsTransactionMenu.java b/src/main/java/com/rsscripting/rswarehouse/variantsenchanted/EnchantedVariantsTransactionMenu.java new file mode 100644 index 0000000..92ebe23 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/variantsenchanted/EnchantedVariantsTransactionMenu.java @@ -0,0 +1,321 @@ +package com.rsscripting.rswarehouse.variantsenchanted; + +import com.rsscripting.rswarehouse.variants.dao.EnchantedVariantsDAO; +import com.rsscripting.rswarehouse.model.EnchantedVariant; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.List; + +public class EnchantedVariantsTransactionMenu { + + public static void open( + Player player, + int enchantedVariantId, + int amount + ) { + + String title; + + if (amount > 0) { + + title = + "Deposit: " + + String.format( + "%,d", + amount + ); + + } + + else if (amount < 0) { + + title = + "Withdraw: " + + String.format( + "%,d", + Math.abs( + amount + ) + ); + + } + + else { + + title = + "Amount: 0"; + + } + + Inventory menu = + Bukkit.createInventory( + new RSMenuHolder( + "ENCHANTED_ITEM_ACTION" + ), + 27, + Component.text( + title + ).color( + NamedTextColor.BLUE + ) + ); + + /* + |-------------------------------------------------------------------------- + | FILLER + |-------------------------------------------------------------------------- + */ + + for (int i = 0; i < menu.getSize(); i++) { + + menu.setItem( + i, + RSMenuUtils.createFillerPane() + ); + + } + +/* +|-------------------------------------------------------------------------- +| CENTER ITEM +|-------------------------------------------------------------------------- +*/ + + EnchantedVariant enchantedVariant = + EnchantedVariantsDAO.getEnchantedVariantById( + enchantedVariantId + ); + + if (enchantedVariant != null) { + + ItemStack item = + ItemStackUtils.deserialize( + enchantedVariant.serializedItem() + ); + + if (item != null) { + + ItemMeta meta = + item.getItemMeta(); + + if (meta != null) { + + long playerHas = + getPlayerItemCount( + player, + item + ); + + meta.lore( + List.of( + Component.text( + "In Stock: " + + String.format( + "%,d", + enchantedVariant.quantity() + ) + ).color( + NamedTextColor.LIGHT_PURPLE + ), + + Component.text( + "Player Has: " + + String.format( + "%,d", + playerHas + ) + ).color( + NamedTextColor.GREEN + ), + + Component.text( + " " + ), + + Component.text( + "Click to complete transaction." + ).color( + NamedTextColor.YELLOW + ) + ) + ); + + item.setItemMeta( + meta + ); + + } + + menu.setItem( + 13, + item + ); + + } + + } + + /* + |-------------------------------------------------------------------------- + | WITHDRAW + |-------------------------------------------------------------------------- + */ + + ItemStack subtract64 = + RSMenuUtils.createMenuItem( + Material.RED_WOOL, + "§cSubtract 64" + ); + + subtract64.setAmount( + 64 + ); + + menu.setItem( + 9, + subtract64 + ); + + ItemStack subtract16 = + RSMenuUtils.createMenuItem( + Material.RED_WOOL, + "§cSubtract 16" + ); + + subtract16.setAmount( + 16 + ); + + menu.setItem( + 10, + subtract16 + ); + + + ItemStack subtract1 = + RSMenuUtils.createMenuItem( + Material.RED_WOOL, + "§cSubtract 1" + ); + + subtract1.setAmount( + 1 + ); + + menu.setItem( + 11, + subtract1 + ); + + /* + |-------------------------------------------------------------------------- + | DEPOSIT + |-------------------------------------------------------------------------- + */ + + ItemStack add1 = + RSMenuUtils.createMenuItem( + Material.GREEN_WOOL, + "§cAdd 1" + ); + + add1.setAmount( + 1 + ); + + menu.setItem( + 15, + add1 + ); + + ItemStack add16 = + RSMenuUtils.createMenuItem( + Material.GREEN_WOOL, + "§cAdd 16" + ); + + add16.setAmount( + 16 + ); + + menu.setItem( + 16, + add16 + ); + + ItemStack add64 = + RSMenuUtils.createMenuItem( + Material.GREEN_WOOL, + "§cAdd 64" + ); + + add64.setAmount( + 64 + ); + + menu.setItem( + 17, + add64 + ); + + /* + |-------------------------------------------------------------------------- + | BACK + |-------------------------------------------------------------------------- + */ + + menu.setItem( + 4, + RSMenuUtils.createMenuItem( + Material.OAK_DOOR, + "§eReturn to main menu." + ) + ); + + player.openInventory( + menu + ); + + } + + public static long getPlayerItemCount( + Player player, + ItemStack target + ) { + + long count = 0; + + for (ItemStack item : player.getInventory().getContents()) { + + if (item == null) { + continue; + } + + if ( + item.isSimilar( + target + ) + ) { + + count += item.getAmount(); + + } + + + } + + return count; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/variantsenchanted/EnchantedVariantsTransactionMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/variantsenchanted/EnchantedVariantsTransactionMenuListener.java new file mode 100644 index 0000000..cbee146 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/variantsenchanted/EnchantedVariantsTransactionMenuListener.java @@ -0,0 +1,433 @@ +package com.rsscripting.rswarehouse.variantsenchanted; + +import com.rsscripting.rswarehouse.item.TransactionAmountMenu; +import com.rsscripting.rswarehouse.variants.dao.EnchantedVariantsDAO; +import com.rsscripting.rswarehouse.autodeposit.autodepositdao.AutoDepositDAO; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryMenu; +import com.rsscripting.rswarehouse.model.EnchantedVariant; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.item.TransactionUtils; +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import com.rsscripting.rswarehouse.session.TransactionSession; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +public class EnchantedVariantsTransactionMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if ( + !(event.getWhoClicked() + instanceof Player player) + ) { + + return; + + } + + if ( + !(event.getInventory() + .getHolder() + instanceof RSMenuHolder holder) + ) { + + return; + + } + + if ( + !holder.getMenuId() + .equals( + "ENCHANTED_ITEM_ACTION" + ) + ) { + + return; + + } + + event.setCancelled( + true + ); + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + TransactionSession itemSession = + session.getItemActionSession(); + + if (itemSession == null) { + + return; + + } + + int amount = + itemSession.getAmount(); + + int warehouseItemId = + itemSession.getWarehouseItemId(); + + int enchantedVariantId = + itemSession.getVariantRecordId(); + + EnchantedVariant enchantedVariant = + EnchantedVariantsDAO.getEnchantedVariantById( + enchantedVariantId + ); + + if (enchantedVariant == null) { + + return; + + } + + if (event.getSlot() == 4) { + + TransactionAmountMenu.open( + player, + warehouseItemId, + 0 + ); + + return; + } + + if (event.getSlot() == 5) { + + player.closeInventory(); + + } + + ItemStack item = + ItemStackUtils.deserialize( + enchantedVariant.serializedItem() + ); + + if (item == null) { + + return; + + } + + long playerHas = + TransactionUtils.getPlayerItemCount( + player, + item + ); + + if (event.getSlot() == 13) { + + if (amount == 0) { + + return; + + } + + if (amount > 0) { + + ItemStack depositItem = + item.clone(); + + depositItem.setAmount( + 1 + ); + + if ( + removeItems( + player, + depositItem, + amount + ) + ) { + + EnchantedVariantsDAO.addEnchantedVariantQuantity( + enchantedVariant.id(), + amount + ); + + player.sendMessage( + "§aYou have deposited " + + amount + + " items." + ); + + itemSession.setAmount( + 0 + ); + + EnchantedVariantsTransactionMenu.open( + player, + enchantedVariantId, + amount + ); + + } + + return; + + } + + else { + + int withdrawAmount = + Math.abs( + amount + ); + + ItemStack withdrawItem = + item.clone(); + + withdrawItem.setAmount( + withdrawAmount + ); + + if ( + AutoDepositDAO.shouldBlockWithdrawal( + player.getUniqueId(), + withdrawItem + ) + ) { + + RSMessageUtils.error( + player, + "Disable Auto Deposit or remove this item from your filter before withdrawing it." + ); + + return; + + } + + player.getInventory() + .addItem( + withdrawItem + ); + + EnchantedVariantsDAO.removeEnchantedVariantQuantity( + enchantedVariant.id(), + withdrawAmount + ); + + player.sendMessage( + "§aYou have withdrawn " + + withdrawAmount + + " items." + ); + + itemSession.setAmount( + 0 + ); + + EnchantedVariantsTransactionMenu.open( + player, + enchantedVariantId, + 0 + ); + + } + + return; + + } + + long warehouseStock = + enchantedVariant.quantity(); + + int inventoryCapacity = + getAvailableCapacity( + player, + item + ); + + long maxWithdraw = + Math.min( + warehouseStock, + inventoryCapacity + ); + + switch ( + event.getSlot() + ) { + + case 9 -> + amount -= 64; + + case 10 -> + amount -= 16; + + case 11 -> + amount -= 1; + + case 15 -> + amount += 1; + + case 16 -> + amount += 16; + + case 17 -> + amount += 64; + + default -> { + + return; + + } + + } + + if (amount > playerHas) { + + amount = + (int) playerHas; + + } + + if ( + amount < -maxWithdraw + ) + { + + amount = + (int) -maxWithdraw; + + } + + itemSession.setAmount( + amount + ); + + EnchantedVariantsTransactionMenu.open( + player, + warehouseItemId, + 0 + ); + + } + + private boolean removeItems( + Player player, + ItemStack target, + int amount + ) { + + int remaining = + amount; + + ItemStack[] contents = + player.getInventory() + .getContents(); + + for (int slot = 0; + slot < contents.length; + slot++) { + + ItemStack item = + contents[slot]; + + if (item == null) { + + continue; + + } + + if (!item.isSimilar(target)) { + + continue; + + } + + if ( + item.getAmount() + <= remaining + ) { + + remaining -= + item.getAmount(); + + player.getInventory() + .setItem( + slot, + null + ); + + } + + else { + + item.setAmount( + item.getAmount() + - remaining + ); + + remaining = + 0; + + } + + if (remaining <= 0) { + + return true; + + } + + } + + return false; + + } + + private int getAvailableCapacity( + Player player, + ItemStack target + ) { + + int capacity = 0; + + int maxStack = + target.getMaxStackSize(); + + for ( + ItemStack item : + player.getInventory() + .getStorageContents() + ) { + + if (item == null) { + + capacity += maxStack; + + continue; + + } + + if ( + item.isSimilar( + target + ) + ) { + + capacity += + maxStack + - item.getAmount(); + + } + + } + + return capacity; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/variantspartiallyfilled/PartiallyFilledVariantsMenu.java b/src/main/java/com/rsscripting/rswarehouse/variantspartiallyfilled/PartiallyFilledVariantsMenu.java new file mode 100644 index 0000000..8906be3 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/variantspartiallyfilled/PartiallyFilledVariantsMenu.java @@ -0,0 +1,147 @@ +package com.rsscripting.rswarehouse.variantspartiallyfilled; + +import com.rsscripting.rswarehouse.variants.dao.PartiallyFilledVariantsDAO; +import com.rsscripting.rswarehouse.model.PartiallyFilledVariant; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import com.rsscripting.rswarehouse.constants.RSKeys; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +import java.util.ArrayList; +import java.util.List; + +public class PartiallyFilledVariantsMenu { + + public static void open( + Player player, + int itemId, + int parentInventoryId + ) { + + Inventory menu = + Bukkit.createInventory( + new RSMenuHolder( + "PARTIALLY_FILLED_VARIANTS:" + itemId + ), + 54, + Component.text( + "Partially Filled Variants" + ).color( + NamedTextColor.BLUE + ) + ); + + ItemStack filler = + RSMenuUtils.createFillerPane(); + + for (int slot = 0; slot <= 8; slot++) { + + menu.setItem( + slot, + filler + ); + + } + + for (int slot = 45; slot <= 53; slot++) { + + menu.setItem( + slot, + filler + ); + + } + + menu.setItem( + 4, + RSMenuUtils.createMenuItem( + Material.OAK_DOOR, + "§a Back" + ) + ); + + List variants = + PartiallyFilledVariantsDAO.getPartiallyFilledVariants( + parentInventoryId + ); + + int slot = 9; + + for ( + PartiallyFilledVariant variant + : variants + ) { + + ItemStack item = + ItemStackUtils.deserialize( + variant.serializedItem() + ); + + if (item == null) { + + continue; + + } + + ItemMeta meta = + item.getItemMeta(); + + List lore = + new ArrayList<>(); + + lore.add( + Component.text( + "Quantity: " + + String.format( + "%,d", + variant.quantity() + ) + ) + ); + + meta.lore( + lore + ); + + meta.getPersistentDataContainer() + .set( + RSKeys.PARTIALLY_FILLED_VARIANT_ID, + PersistentDataType.INTEGER, + variant.id() + ); + + item.setItemMeta( + meta + ); + + menu.setItem( + slot, + item + ); + + slot++; + + if (slot >= 45) { + + break; + + } + + } + + player.openInventory( + menu + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/variantspartiallyfilled/PartiallyFilledVariantsMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/variantspartiallyfilled/PartiallyFilledVariantsMenuListener.java new file mode 100644 index 0000000..ec21518 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/variantspartiallyfilled/PartiallyFilledVariantsMenuListener.java @@ -0,0 +1,150 @@ +package com.rsscripting.rswarehouse.variantspartiallyfilled; + +import com.rsscripting.rswarehouse.item.TransactionAmountMenu; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import com.rsscripting.rswarehouse.session.TransactionSession; +import com.rsscripting.rswarehouse.constants.RSKeys; +import com.rsscripting.rswarehouse.session.VariantType; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +public class PartiallyFilledVariantsMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if ( + !(event.getWhoClicked() + instanceof Player player) + ) { + + return; + + } + + if ( + !(event.getInventory() + .getHolder() + instanceof RSMenuHolder holder) + ) { + + return; + + } + + if ( + !holder.getMenuId() + .startsWith( + "PARTIALLY_FILLED_VARIANTS:" + ) + ) { + + return; + + } + + event.setCancelled( + true + ); + + int itemId = + Integer.parseInt( + holder.getMenuId() + .split( + ":" + )[1] + ); + +/* +|-------------------------------------------------------------------------- +| BACK +|-------------------------------------------------------------------------- +*/ + + if (event.getSlot() == 4) { + + TransactionAmountMenu.open( + player, + itemId, + 0 + ); + + return; + } + +/* +|-------------------------------------------------------------------------- +| ENCHANTED VARIANT +|-------------------------------------------------------------------------- +*/ + + ItemStack clickedItem = + event.getCurrentItem(); + + if (clickedItem == null) { + + return; + + } + + ItemMeta meta = + clickedItem.getItemMeta(); + + if (meta == null) { + + return; + + } + + Integer partiallyFilledVariantId = + meta.getPersistentDataContainer() + .get( + RSKeys.PARTIALLY_FILLED_VARIANT_ID, + PersistentDataType.INTEGER + ); + + if (partiallyFilledVariantId == null) { + + return; + + } + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + TransactionSession transactionSession = + new TransactionSession(itemId); + + transactionSession.setVariantType( + VariantType.PARTIAL + ); + + transactionSession.setVariantRecordId( + partiallyFilledVariantId + ); + + session.setItemActionSession( + transactionSession + ); + + PartiallyFilledVariantsTransactionMenu.open( + player, + partiallyFilledVariantId, + 0 + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/variantspartiallyfilled/PartiallyFilledVariantsTransactionMenu.java b/src/main/java/com/rsscripting/rswarehouse/variantspartiallyfilled/PartiallyFilledVariantsTransactionMenu.java new file mode 100644 index 0000000..b733e8f --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/variantspartiallyfilled/PartiallyFilledVariantsTransactionMenu.java @@ -0,0 +1,321 @@ +package com.rsscripting.rswarehouse.variantspartiallyfilled; + +import com.rsscripting.rswarehouse.variants.dao.PartiallyFilledVariantsDAO; +import com.rsscripting.rswarehouse.model.PartiallyFilledVariant; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import com.rsscripting.rswarehouse.utils.RSMenuUtils; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.List; + +public class PartiallyFilledVariantsTransactionMenu { + + public static void open( + Player player, + int partiallyFilledVariantId, + int amount + ) { + + String title; + + if (amount > 0) { + + title = + "Deposit: " + + String.format( + "%,d", + amount + ); + + } + + else if (amount < 0) { + + title = + "Withdraw: " + + String.format( + "%,d", + Math.abs( + amount + ) + ); + + } + + else { + + title = + "Amount: 0"; + + } + + Inventory menu = + Bukkit.createInventory( + new RSMenuHolder( + "PARTIALLY_FILLED_ITEM_ACTION" + ), + 27, + Component.text( + title + ).color( + NamedTextColor.BLUE + ) + ); + + /* + |-------------------------------------------------------------------------- + | FILLER + |-------------------------------------------------------------------------- + */ + + for (int i = 0; i < menu.getSize(); i++) { + + menu.setItem( + i, + RSMenuUtils.createFillerPane() + ); + + } + +/* +|-------------------------------------------------------------------------- +| CENTER ITEM +|-------------------------------------------------------------------------- +*/ + + PartiallyFilledVariant partiallyFilledVariant = + PartiallyFilledVariantsDAO.getPartiallyFilledVariantById( + partiallyFilledVariantId + ); + + if (partiallyFilledVariant != null) { + + ItemStack item = + ItemStackUtils.deserialize( + partiallyFilledVariant.serializedItem() + ); + + if (item != null) { + + ItemMeta meta = + item.getItemMeta(); + + if (meta != null) { + + long playerHas = + getPlayerItemCount( + player, + item + ); + + meta.lore( + List.of( + Component.text( + "In Stock: " + + String.format( + "%,d", + partiallyFilledVariant.quantity() + ) + ).color( + NamedTextColor.LIGHT_PURPLE + ), + + Component.text( + "Player Has: " + + String.format( + "%,d", + playerHas + ) + ).color( + NamedTextColor.GREEN + ), + + Component.text( + " " + ), + + Component.text( + "Click to complete transaction." + ).color( + NamedTextColor.YELLOW + ) + ) + ); + + item.setItemMeta( + meta + ); + + } + + menu.setItem( + 13, + item + ); + + } + + } + + /* + |-------------------------------------------------------------------------- + | WITHDRAW + |-------------------------------------------------------------------------- + */ + + ItemStack subtract64 = + RSMenuUtils.createMenuItem( + Material.RED_WOOL, + "§cSubtract 64" + ); + + subtract64.setAmount( + 64 + ); + + menu.setItem( + 9, + subtract64 + ); + + ItemStack subtract16 = + RSMenuUtils.createMenuItem( + Material.RED_WOOL, + "§cSubtract 16" + ); + + subtract16.setAmount( + 16 + ); + + menu.setItem( + 10, + subtract16 + ); + + + ItemStack subtract1 = + RSMenuUtils.createMenuItem( + Material.RED_WOOL, + "§cSubtract 1" + ); + + subtract1.setAmount( + 1 + ); + + menu.setItem( + 11, + subtract1 + ); + + /* + |-------------------------------------------------------------------------- + | DEPOSIT + |-------------------------------------------------------------------------- + */ + + ItemStack add1 = + RSMenuUtils.createMenuItem( + Material.GREEN_WOOL, + "§cAdd 1" + ); + + add1.setAmount( + 1 + ); + + menu.setItem( + 15, + add1 + ); + + ItemStack add16 = + RSMenuUtils.createMenuItem( + Material.GREEN_WOOL, + "§cAdd 16" + ); + + add16.setAmount( + 16 + ); + + menu.setItem( + 16, + add16 + ); + + ItemStack add64 = + RSMenuUtils.createMenuItem( + Material.GREEN_WOOL, + "§cAdd 64" + ); + + add64.setAmount( + 64 + ); + + menu.setItem( + 17, + add64 + ); + + /* + |-------------------------------------------------------------------------- + | BACK + |-------------------------------------------------------------------------- + */ + + menu.setItem( + 4, + RSMenuUtils.createMenuItem( + Material.OAK_DOOR, + "§eReturn to main menu." + ) + ); + + player.openInventory( + menu + ); + + } + + public static long getPlayerItemCount( + Player player, + ItemStack target + ) { + + long count = 0; + + for (ItemStack item : player.getInventory().getContents()) { + + if (item == null) { + continue; + } + + if ( + item.isSimilar( + target + ) + ) { + + count += item.getAmount(); + + } + + + } + + return count; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rswarehouse/variantspartiallyfilled/PartiallyFilledVariantsTransactionMenuListener.java b/src/main/java/com/rsscripting/rswarehouse/variantspartiallyfilled/PartiallyFilledVariantsTransactionMenuListener.java new file mode 100644 index 0000000..a2d96d1 --- /dev/null +++ b/src/main/java/com/rsscripting/rswarehouse/variantspartiallyfilled/PartiallyFilledVariantsTransactionMenuListener.java @@ -0,0 +1,433 @@ +package com.rsscripting.rswarehouse.variantspartiallyfilled; + +import com.rsscripting.rswarehouse.item.TransactionAmountMenu; +import com.rsscripting.rswarehouse.variants.dao.PartiallyFilledVariantsDAO; +import com.rsscripting.rswarehouse.autodeposit.autodepositdao.AutoDepositDAO; +import com.rsscripting.rswarehouse.category.categorymenu.CategoryMenu; +import com.rsscripting.rswarehouse.model.PartiallyFilledVariant; +import com.rsscripting.rswarehouse.menuholder.RSMenuHolder; +import com.rsscripting.rswarehouse.item.TransactionUtils; +import com.rsscripting.rswarehouse.session.GuiSession; +import com.rsscripting.rswarehouse.session.GuiSessionManager; +import com.rsscripting.rswarehouse.session.TransactionSession; +import com.rsscripting.rswarehouse.utils.ItemStackUtils; +import com.rsscripting.rswarehouse.utils.RSMessageUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +public class PartiallyFilledVariantsTransactionMenuListener + implements Listener { + + @EventHandler + public void onInventoryClick( + InventoryClickEvent event + ) { + + if ( + !(event.getWhoClicked() + instanceof Player player) + ) { + + return; + + } + + if ( + !(event.getInventory() + .getHolder() + instanceof RSMenuHolder holder) + ) { + + return; + + } + + if ( + !holder.getMenuId() + .equals( + "PARTIALLY_FILLED_ITEM_ACTION" + ) + ) { + + return; + + } + + event.setCancelled( + true + ); + + GuiSession session = + GuiSessionManager.getSession( + player + ); + + TransactionSession itemSession = + session.getItemActionSession(); + + if (itemSession == null) { + + return; + + } + + int amount = + itemSession.getAmount(); + + int warehouseItemId = + itemSession.getWarehouseItemId(); + + int partiallyFilledVariantId = + itemSession.getVariantRecordId(); + + PartiallyFilledVariant partiallyFilledVariant = + PartiallyFilledVariantsDAO.getPartiallyFilledVariantById( + partiallyFilledVariantId + ); + + if (partiallyFilledVariant == null) { + + return; + + } + + if (event.getSlot() == 4) { + + TransactionAmountMenu.open( + player, + warehouseItemId, + 0 + ); + + return; + } + + if (event.getSlot() == 5) { + + player.closeInventory(); + + } + + ItemStack item = + ItemStackUtils.deserialize( + partiallyFilledVariant.serializedItem() + ); + + if (item == null) { + + return; + + } + + long playerHas = + TransactionUtils.getPlayerItemCount( + player, + item + ); + + if (event.getSlot() == 13) { + + if (amount == 0) { + + return; + + } + + if (amount > 0) { + + ItemStack depositItem = + item.clone(); + + depositItem.setAmount( + 1 + ); + + if ( + removeItems( + player, + depositItem, + amount + ) + ) { + + PartiallyFilledVariantsDAO.addPartiallyFilledVariantQuantity( + partiallyFilledVariant.id(), + amount + ); + + player.sendMessage( + "§aYou have deposited " + + amount + + " items." + ); + + itemSession.setAmount( + 0 + ); + + PartiallyFilledVariantsTransactionMenu.open( + player, + partiallyFilledVariantId, + 0 + ); + + } + + return; + + } + + else { + + int withdrawAmount = + Math.abs( + amount + ); + + ItemStack withdrawItem = + item.clone(); + + withdrawItem.setAmount( + withdrawAmount + ); + + if ( + AutoDepositDAO.shouldBlockWithdrawal( + player.getUniqueId(), + withdrawItem + ) + ) { + + RSMessageUtils.error( + player, + "Disable Auto Deposit or remove this item from your filter before withdrawing it." + ); + + return; + + } + + player.getInventory() + .addItem( + withdrawItem + ); + + PartiallyFilledVariantsDAO.removePartiallyFilledVariantQuantity( + partiallyFilledVariant.id(), + withdrawAmount + ); + + player.sendMessage( + "§aYou have withdrawn " + + withdrawAmount + + " items." + ); + + itemSession.setAmount( + 0 + ); + + PartiallyFilledVariantsTransactionMenu.open( + player, + partiallyFilledVariantId, + 0 + ); + + } + + return; + + } + + long warehouseStock = + partiallyFilledVariant.quantity(); + + int inventoryCapacity = + getAvailableCapacity( + player, + item + ); + + long maxWithdraw = + Math.min( + warehouseStock, + inventoryCapacity + ); + + switch ( + event.getSlot() + ) { + + case 9 -> + amount -= 64; + + case 10 -> + amount -= 16; + + case 11 -> + amount -= 1; + + case 15 -> + amount += 1; + + case 16 -> + amount += 16; + + case 17 -> + amount += 64; + + default -> { + + return; + + } + + } + + if (amount > playerHas) { + + amount = + (int) playerHas; + + } + + if ( + amount < -maxWithdraw + ) + { + + amount = + (int) -maxWithdraw; + + } + + itemSession.setAmount( + amount + ); + + PartiallyFilledVariantsTransactionMenu.open( + player, + partiallyFilledVariantId, + amount + ); + + } + + private boolean removeItems( + Player player, + ItemStack target, + int amount + ) { + + int remaining = + amount; + + ItemStack[] contents = + player.getInventory() + .getContents(); + + for (int slot = 0; + slot < contents.length; + slot++) { + + ItemStack item = + contents[slot]; + + if (item == null) { + + continue; + + } + + if (!item.isSimilar(target)) { + + continue; + + } + + if ( + item.getAmount() + <= remaining + ) { + + remaining -= + item.getAmount(); + + player.getInventory() + .setItem( + slot, + null + ); + + } + + else { + + item.setAmount( + item.getAmount() + - remaining + ); + + remaining = + 0; + + } + + if (remaining <= 0) { + + return true; + + } + + } + + return false; + + } + + private int getAvailableCapacity( + Player player, + ItemStack target + ) { + + int capacity = 0; + + int maxStack = + target.getMaxStackSize(); + + for ( + ItemStack item : + player.getInventory() + .getStorageContents() + ) { + + if (item == null) { + + capacity += maxStack; + + continue; + + } + + if ( + item.isSimilar( + target + ) + ) { + + capacity += + maxStack + - item.getAmount(); + + } + + } + + return capacity; + + } + +} \ No newline at end of file diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..0fea1d7 --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,43 @@ +# +# RS-Warehouse +# + +display: + # Display when item was first deposited + # to database and what date it happened. + show-discovery-information: true + +############################################ +# Automatic-Chest scan and process settings. +############################################ + +chest-auto-processing: + enabled: true + interval-seconds: 30 + + ############################################ + # Item Creation. Wether to allow + # automatic creation when items aren't in + # databse. + ############################################ + + # Allow item to be added to Uncategorized + # if item is not currently in warehouse. +allow-uncategorized-item-creation: true + + # Allow damaged items to be added to + # damaged variant menu of base items. +allow-damaged-item-creation: true + + +####################################### +# Chest close processing +####################################### + +chest-close-processing: + + # Process warehouse chests immediately + # when a player closes them. + enabled: true + + diff --git a/src/main/resources/database.db b/src/main/resources/database.db new file mode 100644 index 0000000..22d5158 Binary files /dev/null and b/src/main/resources/database.db differ diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml new file mode 100644 index 0000000..5b0caae --- /dev/null +++ b/src/main/resources/plugin.yml @@ -0,0 +1,25 @@ +name: RS-Warehouse +version: ${project.version} +main: com.rsscripting.rswarehouse.RSWarehouse +api-version: '1.21' + +author: RSScripting +description: RS Warehouse + +commands: + rswarehouse: + description: Main plugin command + usage: /rswh + + shop: + description: Opens the Shop + usage: /shop + +permissions: + rswarehouse.admin: + description: Admin access + default: op + + rswarehouse.bypass: + description: Bypass ownership protection + default: op \ No newline at end of file